Okay, I've mentioned this before. I'm making a little program for my class that draws up a window on the second monitor of the computer, which is set up to be displayed at the front of the room via projector. Works fine and dandy, and there's been three versions. One that's just an Allegro GFX_AUTODETECT_WINDOWED, one that's Win32 and OpenGL, and one that's Win32 and uses Allegro to draw the double buffer to the device context via draw_to_hdc(). Those last two are made with the class style WS_POPUP and just drawn to cover the second monitor, making it appear fullscreen (the pure Allegro program I just drag over there
) since I couldn't figure out how to make it go actually fullscreen on monitor two.
Now, I'm hammering out the final version of this thing after all my experimenting. And the third program setup works the best for me; I can use all the fancy Win32 GUI stuff with the simple Allegro graphics routines. Works great. One catch: it's slow. Like, really slow. Like runs at a quarter the speed of the other two programs slow, at best.
Now I assume this is an issue with hardware acceleration of some kind. The other two programs are fine so I know the machine is (barely) capable. The pure Allegro setup won't work because I need a dialog box or two and it's got the ugly border. The Win32/OpenGL version is okay, but OpenGL is a pain to set up compared to Allegro, plus the Allegro code is already done anyway (the Win32/OpenGL test was actually a completely seperate program).
So, I'd really like to know what Allegro is doing that it works fine in the plain version, but runs so slow in the Win32 version. I'm guessing there's some DirectX of some kind running in the background? How hard would it be to add that as a wrapper between Allegro and Win32? I've never used DirectX. Should I just bite the bullet and do the best I can with OpenGL 2D and Win32, and forget Allegro? I'm hoping someone with insight into Allegro's guts can tell me how hard it is to reproduce what it's doing. Otherwise I'll just go with OpenGL, clumsy as I am with it.
I can try to provide some skeleton code of any of these programs if it would help.
I can try to provide some skeleton code of any of these programs if it would help.
I will try to make some test if you do so.
If I'm right, blit_to_hdc() should rely on GDI, not on DirectX.
Do I understand correctly that you have one Allegro application that needs to go fullscreen on the second monitor? So it's not a matter of multiple windows?
I won't have any real solution, though.
[edit]
A quick look at the sources under /win shows that function is in gdi.c, so I guess I'm right.
isn't blit_to_hdc() slow as hell?
Yes.
isn't GDI slow as hell?
Fixed.
GDI is always slow as hell.
I know less than you do about the guts
.
In case you didn't see my thread and do decide to go the OpenGL route yet don't want to learn OpenGL, you could look at my library:
Thing 1.0 Library
Sprite Thing Example
If you do decide to learn OpenGL, maybe my code will make the learning process easier? I'd try to analyze bitmap.h and bitmap_hardware.cpp
As for getting OpenGL up and running (albeit this isn't that difficult), you can look for that in conf.cpp
Also note this: In Conf.cpp you have included aldumb.h... this file is not needed. I don't think I got around to fixing that line of code before the thread closed :-X
If he switches to OpenGL, we will never see TMS!
isn't blit_to_hdc() slow as hell?
isn't GDI slow as hell?
GDI is always slow as hell.
Yes, thank you all. Now, on to how we might rectify it, and more specifically, if anyone knows how Allegro in particular does it ...
I can use all the fancy Win32 GUI stuff with the simple Allegro graphics routines. Works great. One catch: it's slow. Like, really slow. Like runs at a quarter the speed of the other two programs slow, at best.
02:20 am idea (so discard it if sounds strange, tomorrow I'll reread it ^_^): Can't you have all the fancy Win32 GUI stuff in a window and have Allegro manage its other? Or even use a pipe to connect a Win32 program to the Allegro one, and you pass anything you get from the Win32 GUI program to the Allegro program through the pipe or some other IPC system?
The are many Allegro GFX drivers, some of theme are GFX_GDI and GFX_DIRECTX, go figure how allegro does it in each of the two cases.
MR: no, because the whole point is the Allegro window is ugly.
It's got a border I can't get rid of.
MM: I'd love to "go figure how", but the Allegro source code does not make for light reading the last time I examined it. :p
DD: Can I use that with Win32? I already know OpenGL fairly well, the point is to avoid re-writing old code that already works fine in Allegro. I may just bite the bullet and go that path if I can get it running at a decent speed though ....
Yes, thank you all. Now, on to how we might rectify it, and more specifically, if anyone knows how Allegro in particular does it ...
The GDI driver is slow. Always has been. The faster drivers are all DirectX/DirectDraw.
In the other words, there is nothing special Allegro doing in GFX_GDI mode.
That's not very helpful. I didn't ask what Allegro was doing special "in GFX_GDI mode" ...
Screw you guys; I'll just use OpenGL.
No cookies.
That's why we mentioned DirectX. IT USES DIRECTX!. I hope you read that this time.
Did you read it when I said it in the original post as well?
That it uses DirectX I knew already (duh). How I might easily go about doing the same thing to use Allegro in a custom Win32 window without a miserable framerate is kinda the topic. If there's no easy way, then straight up OpenGL it is since I know it better than DirectX. If there is a way, however, I was hoping an Allegro guru could tell me ...
Oh, threre is, win_set_window will let you give allegro your own window. or win_get_window, and you can MODIFY allegro's.
There, now that's information I might actually be able to use.
I didn't know the actual API made allowances for that sort of thing; guess I'll RTFM and see if it fits ....
win_set_window HAS to be done before a call to set_gfx_mode iirc.
Oh, threre is, win_set_window will let you give allegro your own window.
If I may offer a counterpoint, I haven't had much luck getting win_set_window to work. Allegro 4.2.2's input system doesn't seem to behave itself very well when you use this. I've also noticed a number of other posts about win_set_window that have shown problems with various bits of Allegro when trying to use it.
It may be that the feature needs work, or has suffered bit rot.
DD: Can I use that with Win32? I already know OpenGL fairly well, the point is to avoid re-writing old code that already works fine in Allegro. I may just bite the bullet and go that path if I can get it running at a decent speed though ....
It runs on windows as well as linux. On linux you must compile with NO_D3D=1.
If by win32 you mean to ask if it can be placed inside a win32 control, then no.
GDI is slow for a number of reasons;
different colour depths for the screens.. very slow.
allegro in 32bit, desktop in 16 bit... very slow.
sometimes its a drivers issue (often integrated gfx cards on laptops, the 2nd desktop is always slow.
however.. if you match up the allegro version (32bit/16bit) with the desktop depth, and your DONT have windows spanning 2 desktops, then its wicked fast!
if your data for that screen is already in a suitably packed RGB structure, look at the GDI function StretchDiBits() to get the desktops DC, call GetDC(NULL);
regarding your windows without borders etc, that is easy to do also.. by changing the win32 windows style info in the CreateWindow()
another hack i do, used shared memory, and copy it into another running process like a SDL window.
i have heaps of these multi-screen methods, at least one of them ought to work for you.
however.. if you match up the allegro version (32bit/16bit) with the desktop depth, and your DONT have windows spanning 2 desktops, then its wicked fast!
Two requests:
1. Please define "Whicked Fast" (especially compared to DDraw and D3D emulated DDraw)
2. Prove it.
Two problems, GDI != GDI+, and Allegro doesn't use GDI+ afaik. Just plain old gdi32.dll.
ZOMG thread necro.
| 1 | int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow) |
| 2 | { |
| 3 | BITMAP *video_page[2]; |
| 4 | int next_page = 0; |
| 5 | |
| 6 | WNDCLASS wc; |
| 7 | |
| 8 | wc.style = CS_OWNDC; |
| 9 | wc.lpfnWndProc = (WNDPROC) WndProc; |
| 10 | wc.cbClsExtra = 0; |
| 11 | wc.cbWndExtra = 0; |
| 12 | wc.hInstance = hInstance; |
| 13 | wc.hIcon = LoadIcon(NULL, IDI_WINLOGO); |
| 14 | wc.hCursor = LoadCursor(NULL, IDC_ARROW); |
| 15 | wc.hbrBackground = NULL; |
| 16 | wc.lpszMenuName = NULL; |
| 17 | wc.lpszClassName = "Main Window Class"; |
| 18 | |
| 19 | if (!RegisterClass(&wc)) |
| 20 | { |
| 21 | MessageBox(NULL,"Failed To Register The Window Class.","ERROR",MB_OK|MB_ICONEXCLAMATION); |
| 22 | return FALSE; |
| 23 | } |
| 24 | |
| 25 | MSG msg; |
| 26 | |
| 27 | hWnd = CreateWindowEx(WS_EX_APPWINDOW, |
| 28 | "Main Window Class", |
| 29 | "", |
| 30 | WS_POPUP | WS_CLIPSIBLINGS | WS_CLIPCHILDREN, |
| 31 | winxpos, 0, |
| 32 | screenw, |
| 33 | screenh, |
| 34 | NULL, |
| 35 | NULL, |
| 36 | hInstance, |
| 37 | NULL); |
| 38 | |
| 39 | win_set_window(hWnd); |
| 40 | |
| 41 | if (allegro_init() != 0) |
| 42 | return 0; |
| 43 | |
| 44 | install_timer(); |
| 45 | install_keyboard(); |
| 46 | install_sound(DIGI_AUTODETECT, MIDI_NONE, NULL); |
| 47 | set_color_depth(24); |
| 48 | |
| 49 | if (set_gfx_mode(GFX_DIRECTX_WIN, screenw, screenh, 0, 0) != 0) { |
| 50 | MessageBox(hWnd, "Unable the set the graphics mode.", "Error!", MB_ICONERROR | MB_OK); |
| 51 | return 0; |
| 52 | } |
| 53 | |
| 54 | set_display_switch_mode(SWITCH_BACKGROUND); |
| 55 | |
| 56 | video_page[0] = create_video_bitmap(screenw, screenh); |
| 57 | video_page[1] = create_video_bitmap(screenw, screenh); |
| 58 | |
| 59 | ShowWindow(hWnd, SW_SHOW); |
| 60 | UpdateWindow(hWnd); |
| 61 | |
| 62 | // *********************************************************** |
| 63 | DialogBox(hInstance, TEXT ("ControlBox"), hWnd, ControlDlgProc); |
| 64 | // *********************************************************** |
| 65 | |
| 66 | while(1) |
| 67 | { |
| 68 | // process input! |
| 69 | |
| 70 | // clear bitmap |
| 71 | clear_bitmap(video_page[next_page]); |
| 72 | |
| 73 | // Do all drawing! |
| 74 | |
| 75 | // update buffer |
| 76 | show_video_bitmap(video_page[next_page]); |
| 77 | next_page = 1 - next_page; |
| 78 | |
| 79 | while(PeekMessage(&msg, NULL, 0, 0, PM_NOREMOVE)) |
| 80 | { |
| 81 | if (GetMessage(&msg, NULL, 0, 0) && !done) |
| 82 | { |
| 83 | TranslateMessage(&msg); |
| 84 | DispatchMessage(&msg); |
| 85 | } |
| 86 | else |
| 87 | { |
| 88 | destroy_bitmap(video_page[0]); |
| 89 | destroy_bitmap(video_page[1]); |
| 90 | return (msg.wParam); |
| 91 | } |
| 92 | } |
| 93 | } |
| 94 | |
| 95 | } |
This is my main loop and I pretty much have it working. Small question: why is it the dialog box I create (highlighted in stars) seem to block the loop? Nothing happens until I close the dialog, which then causes the program to do all the drawing it wassupposed to do before it closes (program is designed to close when the dialog is). I'm too rusty to spot my error.
Otherwise works great. Going to try it on the intended computer this morning to see how fast it goes.
EDIT: Um, almost seems like the program is outright blocking at that highlighted line. I think I'm calling the wrong dialog creating function .... but it works in all my other programs ....
I think DialogBox is meant to block — it's for modal dialogues. I've no idea why you haven't had problems before. Maybe you want CreateDialog? I'm think that one's modeless.
Just because it's modal doesn't (or shouldn't, I don't think) block execution of the program; just means you can't interact with the lower window until the dialog closes. Which is fine for this. Changing DialogBox to CreateDialog makes the dialog box not even open.
I think you need to call ShowDialog or something like that to open a CreateDialog'd dialog.
Just because it's modal doesn't (or shouldn't, I don't think) block execution of the program
I think it often does in Win32 land because of it's basis on the Win16 API (and the Win16 API's historic basis on ye olde Mac OS).
In any case, per Microsoft, "DialogBox does not return control until the specified callback function terminates the modal dialog box" so this particular function definitely does block unless you programmatically close the modal dialog box early.
EDIT: I thought of CreateDialog as a suggestion for a function you might have used before that looks like DialogBox but doesn't block. This page suggests a CreateDialog/ShowWindow combo, but then it implies you'll have to do some message passing yourself.
I think these sort of complications explain why Microsoft provide several higher level alternatives to Win32 nowadays.
blit_to_hdc() uses StretchDIBits for some reason, but it doesn't seem to incur any scaling speed penalties, so there must be a test in the function.
Have you tried the new D3D driver in 4.9? I haven't so I can't really comment on what it can do yet, but it should be ready to open a full, fast display on the 2nd screen. One drawback is that the 4.0 compatability layer is not written, so you'll have to rewrite your whole program for the new API
It uses StretchDIBits because (I believe) it is required to flip the bitmaps around from Allegro's top-down format to Windows' bottom-up format. StretchDIBits does do some sort of optimization checks because there's at least one buggy one that they introduced that required a work-around in Allegro...
I didn't get a chance to try this on the system intended for it to run on; it seems to be having issues that won't even allow it to boot up in safe mode. But it seems to be working fine now. I was going to scatter cookies about before this locked, but I guess I forgot to set it up for that.