From c2ac663b31be3ed552041532bf4d1e36d7047b23 Mon Sep 17 00:00:00 2001 From: Sam Lantinga Date: Mon, 7 Aug 2006 05:24:13 +0000 Subject: [PATCH] Added resize support for GDI and Direct3D renderers --- src/video/SDL_renderer_gl.c | 2 +- src/video/win32/SDL_d3drender.c | 69 +++++++++++++++++++++++++++++++-- src/video/win32/SDL_gdirender.c | 46 ++++++++++++++++++++-- 3 files changed, 108 insertions(+), 9 deletions(-) diff --git a/src/video/SDL_renderer_gl.c b/src/video/SDL_renderer_gl.c index 5bbb41198..b96cf8046 100644 --- a/src/video/SDL_renderer_gl.c +++ b/src/video/SDL_renderer_gl.c @@ -789,7 +789,7 @@ GL_DestroyTexture(SDL_Renderer * renderer, SDL_Texture * texture) texture->driverdata = NULL; } -void +static void GL_DestroyRenderer(SDL_Renderer * renderer) { GL_RenderData *data = (GL_RenderData *) renderer->driverdata; diff --git a/src/video/win32/SDL_d3drender.c b/src/video/win32/SDL_d3drender.c index 8b96c6d7e..892e294b7 100644 --- a/src/video/win32/SDL_d3drender.c +++ b/src/video/win32/SDL_d3drender.c @@ -28,6 +28,7 @@ /* Direct3D renderer implementation */ static SDL_Renderer *D3D_CreateRenderer(SDL_Window * window, Uint32 flags); +static int D3D_DisplayModeChanged(SDL_Renderer * renderer); static int D3D_CreateTexture(SDL_Renderer * renderer, SDL_Texture * texture); static int D3D_SetTexturePalette(SDL_Renderer * renderer, SDL_Texture * texture, @@ -61,7 +62,7 @@ SDL_RenderDriver D3D_RenderDriver = { { "d3d", (SDL_RENDERER_SINGLEBUFFER | SDL_RENDERER_PRESENTCOPY | - SDL_RENDERER_PRESENTFLIP2 | sDL_RENDERER_PRESENTFLIP3 | + SDL_RENDERER_PRESENTFLIP2 | SDL_RENDERER_PRESENTFLIP3 | SDL_RENDERER_PRESENTDISCARD | SDL_RENDERER_PRESENTVSYNC | SDL_RENDERER_ACCELERATED), (SDL_TEXTUREBLENDMODE_NONE | SDL_TEXTUREBLENDMODE_MASK | @@ -90,6 +91,7 @@ SDL_RenderDriver D3D_RenderDriver = { typedef struct { IDirect3DDevice9 *device; + D3DPRESENT_PARAMETERS pparams; SDL_bool beginScene; } D3D_RenderData; @@ -182,6 +184,7 @@ D3D_SetError(const char *prefix, HRESULT result) break; } SDL_SetError("%s: %s", prefix, error); + fprintf(stderr, "%s: %s\n", prefix, error); } static D3DFORMAT @@ -253,6 +256,7 @@ D3D_CreateRenderer(SDL_Window * window, Uint32 flags) return NULL; } + renderer->DisplayModeChanged = D3D_DisplayModeChanged; renderer->CreateTexture = D3D_CreateTexture; renderer->SetTexturePalette = D3D_SetTexturePalette; renderer->GetTexturePalette = D3D_GetTexturePalette; @@ -276,7 +280,7 @@ D3D_CreateRenderer(SDL_Window * window, Uint32 flags) pparams.BackBufferHeight = window->h; if (window->flags & SDL_WINDOW_FULLSCREEN) { pparams.BackBufferFormat = - PixelFormatToD3DFMT(display->fullscreen_mode->format); + PixelFormatToD3DFMT(display->fullscreen_mode.format); } else { pparams.BackBufferFormat = D3DFMT_UNKNOWN; } @@ -296,7 +300,7 @@ D3D_CreateRenderer(SDL_Window * window, Uint32 flags) if (window->flags & SDL_WINDOW_FULLSCREEN) { pparams.Windowed = FALSE; pparams.FullScreen_RefreshRateInHz = - display->fullscreen_mode->refresh_rate; + display->fullscreen_mode.refresh_rate; } else { pparams.Windowed = TRUE; pparams.FullScreen_RefreshRateInHz = 0; @@ -355,6 +359,7 @@ D3D_CreateRenderer(SDL_Window * window, Uint32 flags) if (pparams.PresentationInterval == D3DPRESENT_INTERVAL_ONE) { renderer->info.flags |= SDL_RENDERER_PRESENTVSYNC; } + data->pparams = pparams; IDirect3DDevice9_GetDeviceCaps(data->device, &caps); renderer->info.max_texture_width = caps.MaxTextureWidth; @@ -370,6 +375,48 @@ D3D_CreateRenderer(SDL_Window * window, Uint32 flags) return renderer; } +static int +D3D_Reset(SDL_Renderer * renderer) +{ + D3D_RenderData *data = (D3D_RenderData *) renderer->driverdata; + HRESULT result; + + result = IDirect3DDevice9_Reset(data->device, &data->pparams); + if (FAILED(result)) { + if (result == D3DERR_DEVICELOST) { + /* Don't worry about it, we'll reset later... */ + return 0; + } else { + D3D_SetError("Reset()", result); + return -1; + } + } + IDirect3DDevice9_SetVertexShader(data->device, NULL); + IDirect3DDevice9_SetFVF(data->device, D3DFVF_XYZRHW | D3DFVF_TEX1); + IDirect3DDevice9_SetRenderState(data->device, D3DRS_CULLMODE, + D3DCULL_NONE); + IDirect3DDevice9_SetRenderState(data->device, D3DRS_LIGHTING, FALSE); + return 0; +} + +static int +D3D_DisplayModeChanged(SDL_Renderer * renderer) +{ + D3D_RenderData *data = (D3D_RenderData *) renderer->driverdata; + SDL_Window *window = SDL_GetWindowFromID(renderer->window); + SDL_VideoDisplay *display = SDL_GetDisplayFromWindow(window); + + data->pparams.BackBufferWidth = window->w; + data->pparams.BackBufferHeight = window->h; + if (window->flags & SDL_WINDOW_FULLSCREEN) { + data->pparams.BackBufferFormat = + PixelFormatToD3DFMT(display->fullscreen_mode.format); + } else { + data->pparams.BackBufferFormat = D3DFMT_UNKNOWN; + } + return D3D_Reset(renderer); +} + static int D3D_CreateTexture(SDL_Renderer * renderer, SDL_Texture * texture) { @@ -388,6 +435,12 @@ D3D_CreateTexture(SDL_Renderer * renderer, SDL_Texture * texture) texture->driverdata = data; +#if 1 + /* FIXME: Do we want non-managed textures? + They need to be freed on device reset and then reloaded by the app... + */ + texture->access = SDL_TEXTUREACCESS_LOCAL; +#endif if (texture->access == SDL_TEXTUREACCESS_LOCAL) { pool = D3DPOOL_MANAGED; } else { @@ -709,6 +762,14 @@ D3D_RenderPresent(SDL_Renderer * renderer) data->beginScene = SDL_TRUE; } + result = IDirect3DDevice9_TestCooperativeLevel(data->device); + if (result == D3DERR_DEVICELOST) { + /* We'll reset later */ + return; + } + if (result == D3DERR_DEVICENOTRESET) { + D3D_Reset(renderer); + } result = IDirect3DDevice9_Present(data->device, NULL, NULL, NULL, NULL); if (FAILED(result)) { D3D_SetError("Present()", result); @@ -730,7 +791,7 @@ D3D_DestroyTexture(SDL_Renderer * renderer, SDL_Texture * texture) texture->driverdata = NULL; } -void +static void D3D_DestroyRenderer(SDL_Renderer * renderer) { D3D_RenderData *data = (D3D_RenderData *) renderer->driverdata; diff --git a/src/video/win32/SDL_gdirender.c b/src/video/win32/SDL_gdirender.c index e70cc7444..2fdc0023c 100644 --- a/src/video/win32/SDL_gdirender.c +++ b/src/video/win32/SDL_gdirender.c @@ -30,6 +30,7 @@ /* GDI renderer implementation */ static SDL_Renderer *GDI_CreateRenderer(SDL_Window * window, Uint32 flags); +static int GDI_DisplayModeChanged(SDL_Renderer * renderer); static int GDI_CreateTexture(SDL_Renderer * renderer, SDL_Texture * texture); static int GDI_QueryTexturePixels(SDL_Renderer * renderer, SDL_Texture * texture, void **pixels, @@ -66,7 +67,7 @@ SDL_RenderDriver GDI_RenderDriver = { { "gdi", (SDL_RENDERER_SINGLEBUFFER | SDL_RENDERER_PRESENTCOPY | - SDL_RENDERER_PRESENTFLIP2 | sDL_RENDERER_PRESENTFLIP3 | + SDL_RENDERER_PRESENTFLIP2 | SDL_RENDERER_PRESENTFLIP3 | SDL_RENDERER_PRESENTDISCARD | SDL_RENDERER_ACCELERATED), (SDL_TEXTUREBLENDMODE_NONE | SDL_TEXTUREBLENDMODE_MASK | SDL_TEXTUREBLENDMODE_BLEND), @@ -155,6 +156,7 @@ GDI_CreateRenderer(SDL_Window * window, Uint32 flags) return NULL; } + renderer->DisplayModeChanged = GDI_DisplayModeChanged; renderer->CreateTexture = GDI_CreateTexture; renderer->QueryTexturePixels = GDI_QueryTexturePixels; renderer->SetTexturePalette = GDI_SetTexturePalette; @@ -196,7 +198,7 @@ GDI_CreateRenderer(SDL_Window * window, Uint32 flags) if (flags & SDL_RENDERER_SINGLEBUFFER) { renderer->info.flags |= - (SDL_RENDERER_SINGLEBUFFER | sDL_RENDERER_PRESENTCOPY); + (SDL_RENDERER_SINGLEBUFFER | SDL_RENDERER_PRESENTCOPY); n = 0; } else if (flags & SDL_RENDERER_PRESENTFLIP2) { renderer->info.flags |= SDL_RENDERER_PRESENTFLIP2; @@ -230,6 +232,42 @@ GDI_CreateRenderer(SDL_Window * window, Uint32 flags) return renderer; } +static int +GDI_DisplayModeChanged(SDL_Renderer * renderer) +{ + GDI_RenderData *data = (GDI_RenderData *) renderer->driverdata; + SDL_Window *window = SDL_GetWindowFromID(renderer->window); + int i, n; + + if (renderer->info.flags & SDL_RENDERER_SINGLEBUFFER) { + n = 0; + } else if (renderer->info.flags & SDL_RENDERER_PRESENTFLIP2) { + n = 2; + } else if (renderer->info.flags & SDL_RENDERER_PRESENTFLIP3) { + n = 3; + } else { + n = 1; + } + for (i = 0; i < n; ++i) { + if (data->hbm[i]) { + DeleteObject(data->hbm[i]); + data->hbm[i] = NULL; + } + } + for (i = 0; i < n; ++i) { + data->hbm[i] = + CreateCompatibleBitmap(data->window_hdc, window->w, window->h); + if (!data->hbm[i]) { + WIN_SetError("CreateCompatibleBitmap()"); + return -1; + } + } + if (n > 0) { + SelectObject(data->render_hdc, data->hbm[0]); + } + return 0; +} + static int GDI_CreateTexture(SDL_Renderer * renderer, SDL_Texture * texture) { @@ -258,7 +296,7 @@ GDI_CreateTexture(SDL_Renderer * renderer, SDL_Texture * texture) data->pitch = (texture->w * SDL_BYTESPERPIXEL(data->format)); if (data->yuv || texture->access == SDL_TEXTUREACCESS_LOCAL - || texture->format != SDL_GetCurrentDisplayMode()->format) { + || texture->format != display->current_mode.format) { int bmi_size; LPBITMAPINFO bmi; @@ -621,7 +659,7 @@ GDI_DestroyTexture(SDL_Renderer * renderer, SDL_Texture * texture) texture->driverdata = NULL; } -void +static void GDI_DestroyRenderer(SDL_Renderer * renderer) { GDI_RenderData *data = (GDI_RenderData *) renderer->driverdata;