From d881b92c1c1adf3b96937879ba6d04126435b84e Mon Sep 17 00:00:00 2001 From: Toni Spets Date: Sat, 13 Nov 2010 10:49:46 +0200 Subject: [PATCH] Support minimize and close buttons --- main.c | 194 +++++++++++++++++++++++++++++++++--------------------- main.h | 5 +- render.c | 26 +++++--- surface.c | 23 ++++--- 4 files changed, 152 insertions(+), 96 deletions(-) diff --git a/main.c b/main.c index e7cb27d..fea258b 100644 --- a/main.c +++ b/main.c @@ -31,7 +31,7 @@ void mouse_unlock(); IDirectDrawImpl *ddraw = NULL; -extern struct render render_opengl; +DWORD WINAPI render_main(void); HRESULT __stdcall ddraw_Compact(IDirectDrawImpl *This) { @@ -139,11 +139,107 @@ HRESULT __stdcall ddraw_Initialize(IDirectDrawImpl *This, GUID *a) HRESULT __stdcall ddraw_RestoreDisplayMode(IDirectDrawImpl *This) { printf("DirectDraw::RestoreDisplayMode(This=%p)\n", This); + if(!This->render.run) + { + return DD_OK; + } + if(!ddraw->windowed) { This->mode.dmFields = DM_BITSPERPEL|DM_PELSWIDTH|DM_PELSHEIGHT|DM_DISPLAYFLAGS|DM_DISPLAYFREQUENCY|DM_POSITION; ChangeDisplaySettings(&This->mode, 0); } + + This->render.run = FALSE; + WaitForSingleObject(This->render.thread, INFINITE); + This->render.thread = NULL; + + return DD_OK; +} + +HRESULT __stdcall ddraw_SetDisplayMode(IDirectDrawImpl *This, DWORD width, DWORD height, DWORD bpp) +{ + printf("DirectDraw::SetDisplayMode(This=%p, width=%d, height=%d, bpp=%d)\n", This, (unsigned int)width, (unsigned int)height, (unsigned int)bpp); + + if(This->render.run) + { + return DD_OK; + } + This->render.run = TRUE; + + /* currently we only support 8 bit modes */ + if(bpp != 8) + { + return DDERR_INVALIDMODE; + } + + This->mode.dmSize = sizeof(DEVMODE); + This->mode.dmDriverExtra = 0; + + if(EnumDisplaySettings(NULL, ENUM_CURRENT_SETTINGS, &This->mode) == FALSE) + { + /* not expected */ + return DDERR_UNSUPPORTED; + } + + This->width = width; + This->height = height; + This->bpp = bpp; + + if(This->render.width < This->width) + { + This->render.width = This->width; + } + if(This->render.height < This->height) + { + This->render.height = This->height; + } + + mouse_unlock(); + + if(This->windowed) + { + if(!This->windowed_init) + { + SetWindowLong(This->hWnd, GWL_STYLE, GetWindowLong(This->hWnd, GWL_STYLE) | WS_CAPTION | WS_BORDER | WS_SYSMENU | WS_MINIMIZEBOX); + + /* center the window with correct dimensions */ + int x = (This->mode.dmPelsWidth / 2) - (This->render.width / 2); + int y = (This->mode.dmPelsHeight / 2) - (This->render.height / 2); + RECT dst = { x, y, This->render.width+x, This->render.height+y }; + AdjustWindowRect(&dst, GetWindowLong(This->hWnd, GWL_STYLE), FALSE); + SetWindowPos(This->hWnd, HWND_NOTOPMOST, dst.left, dst.top, (dst.right - dst.left), (dst.bottom - dst.top), SWP_SHOWWINDOW); + + This->windowed_init = TRUE; + } + } + else + { + SetWindowPos(This->hWnd, HWND_TOPMOST, 0, 0, This->render.width, This->render.height, SWP_SHOWWINDOW); + SendMessage(This->hWnd, WM_WINDOWPOSCHANGED, 0, 0); + + mouse_lock(); + + memset(&This->render.mode, 0, sizeof(DEVMODE)); + This->render.mode.dmSize = sizeof(DEVMODE); + This->render.mode.dmFields = DM_PELSWIDTH|DM_PELSHEIGHT; + This->render.mode.dmPelsWidth = This->render.width; + This->render.mode.dmPelsHeight = This->render.height; + if(This->render.bpp) + { + This->render.mode.dmFields |= DM_BITSPERPEL; + This->render.mode.dmBitsPerPel = This->render.bpp; + } + + if(ChangeDisplaySettings(&This->render.mode, CDS_FULLSCREEN) != DISP_CHANGE_SUCCESSFUL) + { + This->render.run = FALSE; + return DDERR_INVALIDMODE; + } + } + + This->render.thread = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)render_main, NULL, 0, NULL); + return DD_OK; } @@ -151,6 +247,22 @@ LRESULT CALLBACK WndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam) { switch(uMsg) { + case WM_SYSCOMMAND: + if(wParam == SC_CLOSE) + { + exit(0); + } + break; + case WM_SIZE: + if(wParam == SIZE_RESTORED) + { + ddraw_SetDisplayMode(ddraw, ddraw->width, ddraw->height, ddraw->bpp); + } + if(wParam == SIZE_MINIMIZED) + { + ddraw_RestoreDisplayMode(ddraw); + } + break; case WM_NCACTIVATE: /* game's drawing loop stops when it inactivates, so don't */ DefWindowProc(hWnd, uMsg, wParam, lParam); @@ -159,10 +271,6 @@ LRESULT CALLBACK WndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam) { mouse_unlock(); } - else - { - mouse_lock(); - } return 0; case WM_KEYDOWN: @@ -281,75 +389,6 @@ HRESULT __stdcall ddraw_SetCooperativeLevel(IDirectDrawImpl *This, HWND hWnd, DW return DD_OK; } -HRESULT __stdcall ddraw_SetDisplayMode(IDirectDrawImpl *This, DWORD width, DWORD height, DWORD bpp) -{ - printf("DirectDraw::SetDisplayMode(This=%p, width=%d, height=%d, bpp=%d)\n", This, (unsigned int)width, (unsigned int)height, (unsigned int)bpp); - - /* currently we only support 8 bit modes */ - if(bpp != 8) - { - return DDERR_INVALIDMODE; - } - - This->mode.dmSize = sizeof(DEVMODE); - This->mode.dmDriverExtra = 0; - - if(EnumDisplaySettings(NULL, ENUM_CURRENT_SETTINGS, &This->mode) == FALSE) - { - /* not expected */ - return DDERR_UNSUPPORTED; - } - - This->width = width; - This->height = height; - This->bpp = bpp; - - if(This->render.width < This->width) - { - This->render.width = This->width; - } - if(This->render.height < This->height) - { - This->render.height = This->height; - } - - mouse_unlock(); - - if(This->windowed) - { - SetWindowLong(This->hWnd, GWL_STYLE, GetWindowLong(This->hWnd, GWL_STYLE) | WS_CAPTION | WS_BORDER); - - /* center the window with correct dimensions */ - int x = (This->mode.dmPelsWidth / 2) - (This->render.width / 2); - int y = (This->mode.dmPelsHeight / 2) - (This->render.height / 2); - RECT dst = { x, y, This->render.width+x, This->render.height+y }; - AdjustWindowRect(&dst, GetWindowLong(This->hWnd, GWL_STYLE), FALSE); - SetWindowPos(This->hWnd, HWND_NOTOPMOST, dst.left, dst.top, (dst.right - dst.left), (dst.bottom - dst.top), SWP_SHOWWINDOW); - } - else - { - SetWindowPos(This->hWnd, HWND_TOPMOST, 0, 0, This->render.width, This->render.height, SWP_SHOWWINDOW); - SendMessage(This->hWnd, WM_WINDOWPOSCHANGED, 0, 0); - - mouse_lock(); - - memset(&This->render.mode, 0, sizeof(DEVMODE)); - This->render.mode.dmSize = sizeof(DEVMODE); - This->render.mode.dmFields = DM_PELSWIDTH|DM_PELSHEIGHT; - This->render.mode.dmPelsWidth = This->render.width; - This->render.mode.dmPelsHeight = This->render.height; - if(This->render.bpp) - { - This->render.mode.dmFields |= DM_BITSPERPEL; - This->render.mode.dmBitsPerPel = This->render.bpp; - } - - return ChangeDisplaySettings(&This->render.mode, CDS_FULLSCREEN) == DISP_CHANGE_SUCCESSFUL ? DD_OK : DDERR_INVALIDMODE; - } - - return DD_OK; -} - HRESULT __stdcall ddraw_WaitForVerticalBlank(IDirectDrawImpl *This, DWORD a, HANDLE b) { #if _DEBUG @@ -382,6 +421,13 @@ ULONG __stdcall ddraw_Release(IDirectDrawImpl *This) if(This->Ref == 0) { + if(This->render.run) + { + This->render.run = FALSE; + WaitForSingleObject(This->render.thread, INFINITE); + This->render.thread = NULL; + } + /* restore old wndproc, subsequent ddraw creation will otherwise fail */ SetWindowLong(This->hWnd, GWL_WNDPROC, (LONG)This->WndProc); //free(This); diff --git a/main.h b/main.h index c570de2..c24fb10 100644 --- a/main.h +++ b/main.h @@ -24,6 +24,7 @@ struct IDirectDrawImpl; struct IDirectDrawImplVtbl; +struct IDirectDrawSurfaceImpl; extern struct IDirectDrawImpl *ddraw; @@ -36,9 +37,10 @@ typedef struct IDirectDrawImpl DWORD width; DWORD height; DWORD bpp; - DWORD freq; BOOL windowed; + BOOL windowed_init; DEVMODE mode; + struct IDirectDrawSurfaceImpl *primary; /* real export from system32\ddraw.dll */ HRESULT WINAPI (*DirectDrawCreate)(GUID FAR*, LPDIRECTDRAW FAR*, IUnknown FAR*); @@ -54,6 +56,7 @@ typedef struct IDirectDrawImpl HANDLE thread; BOOL run; HANDLE ev; + CRITICAL_SECTION cs; DEVMODE mode; } render; diff --git a/render.c b/render.c index 76acead..8e64322 100644 --- a/render.c +++ b/render.c @@ -20,7 +20,7 @@ #include "main.h" #include "surface.h" -DWORD WINAPI render_main(IDirectDrawSurfaceImpl *surface) +DWORD WINAPI render_main(void) { int i,j; PIXELFORMATDESCRIPTOR pfd; @@ -31,8 +31,8 @@ DWORD WINAPI render_main(IDirectDrawSurfaceImpl *surface) int tex_width = 1024; int tex_height = 1024; - float scale_w = (float)surface->width/tex_width; - float scale_h = (float)surface->height/tex_height; + float scale_w = 1.0f; + float scale_h = 1.0f; int *tex = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, tex_width * tex_height * sizeof(int)); memset(&pfd, 0, sizeof(PIXELFORMATDESCRIPTOR)); @@ -53,7 +53,7 @@ DWORD WINAPI render_main(IDirectDrawSurfaceImpl *surface) if(ddraw->render.maxfps < 0) { - ddraw->render.maxfps = ddraw->freq; + ddraw->render.maxfps = ddraw->mode.dmDisplayFrequency; } if(ddraw->render.maxfps > 0) @@ -62,6 +62,7 @@ DWORD WINAPI render_main(IDirectDrawSurfaceImpl *surface) } ddraw->render.ev = CreateEvent(NULL, TRUE, FALSE, NULL); + InitializeCriticalSection(&ddraw->render.cs); glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, tex_width, tex_height, 0, GL_RGBA, GL_UNSIGNED_BYTE, tex); glViewport(0, 0, ddraw->render.width, ddraw->render.height); @@ -82,6 +83,9 @@ DWORD WINAPI render_main(IDirectDrawSurfaceImpl *surface) while(ddraw->render.run) { ResetEvent(ddraw->render.ev); + + scale_w = (float)ddraw->width/tex_width; + scale_h = (float)ddraw->height/tex_height; if(ddraw->render.maxfps > 0) { @@ -89,18 +93,20 @@ DWORD WINAPI render_main(IDirectDrawSurfaceImpl *surface) } /* convert ddraw surface to opengl texture */ - if(surface->palette) + EnterCriticalSection(&ddraw->render.cs); + if(ddraw->primary && ddraw->primary->palette) { - for(i=0; iheight; i++) + for(i=0; iheight; i++) { - for(j=0; jwidth; j++) + for(j=0; jwidth; j++) { - tex[i*surface->width+j] = surface->palette->data_bgr[((unsigned char *)surface->surface)[i*surface->lPitch + j*surface->lXPitch]]; + tex[i*ddraw->width+j] = ddraw->primary->palette->data_bgr[((unsigned char *)ddraw->primary->surface)[i*ddraw->primary->lPitch + j*ddraw->primary->lXPitch]]; } } } + LeaveCriticalSection(&ddraw->render.cs); - glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, surface->width, surface->height, GL_RGBA, GL_UNSIGNED_BYTE, tex); + glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, ddraw->width, ddraw->height, GL_RGBA, GL_UNSIGNED_BYTE, tex); glBegin(GL_TRIANGLE_FAN); glTexCoord2f(0,0); glVertex2f(-1, 1); @@ -124,7 +130,9 @@ DWORD WINAPI render_main(IDirectDrawSurfaceImpl *surface) SetEvent(ddraw->render.ev); } + DeleteCriticalSection(&ddraw->render.cs); CloseHandle(ddraw->render.ev); + ddraw->render.ev = NULL; free(tex); diff --git a/surface.c b/surface.c index b79655d..42a96c7 100644 --- a/surface.c +++ b/surface.c @@ -20,9 +20,6 @@ #include "main.h" #include "surface.h" -DWORD WINAPI render_main(IDirectDrawSurfaceImpl *); -IDirectDrawSurfaceImpl *ddraw_primary = NULL; - void dump_ddscaps(DWORD dwCaps); void dump_ddsd(DWORD dwFlags); @@ -49,8 +46,16 @@ ULONG __stdcall ddraw_surface_Release(IDirectDrawSurfaceImpl *This) { if(This->caps == DDSCAPS_PRIMARYSURFACE) { - ddraw->render.run = FALSE; - WaitForSingleObject(ddraw->render.thread, INFINITE); + if(ddraw->render.run) + { + EnterCriticalSection(&ddraw->render.cs); + ddraw->primary = NULL; + LeaveCriticalSection(&ddraw->render.cs); + } + else + { + ddraw->primary = NULL; + } } if(This->surface) { @@ -415,7 +420,7 @@ HRESULT __stdcall ddraw_CreateSurface(IDirectDrawImpl *This, LPDDSURFACEDESC lpD { if(lpDDSurfaceDesc->ddsCaps.dwCaps & DDSCAPS_PRIMARYSURFACE) { - ddraw_primary = Surface; + ddraw->primary = Surface; Surface->width = This->width; Surface->height = This->height; @@ -445,12 +450,6 @@ HRESULT __stdcall ddraw_CreateSurface(IDirectDrawImpl *This, LPDDSURFACEDESC lpD Surface->Ref = 0; ddraw_surface_AddRef(Surface); - if(Surface->caps & DDSCAPS_PRIMARYSURFACE) - { - This->render.run = TRUE; - This->render.thread = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)render_main, (void *)Surface, 0, NULL); - } - return DD_OK; }