Added resize support for GDI and Direct3D renderers
authorSam Lantinga <slouken@libsdl.org>
Mon, 07 Aug 2006 05:24:13 +0000
changeset 1975 ccef0d0c40c6
parent 1974 70deaf574153
child 1976 b1620a317791
Added resize support for GDI and Direct3D renderers
src/video/SDL_renderer_gl.c
src/video/win32/SDL_d3drender.c
src/video/win32/SDL_gdirender.c
--- a/src/video/SDL_renderer_gl.c	Sun Aug 06 23:34:59 2006 +0000
+++ b/src/video/SDL_renderer_gl.c	Mon Aug 07 05:24:13 2006 +0000
@@ -789,7 +789,7 @@
     texture->driverdata = NULL;
 }
 
-void
+static void
 GL_DestroyRenderer(SDL_Renderer * renderer)
 {
     GL_RenderData *data = (GL_RenderData *) renderer->driverdata;
--- a/src/video/win32/SDL_d3drender.c	Sun Aug 06 23:34:59 2006 +0000
+++ b/src/video/win32/SDL_d3drender.c	Mon Aug 07 05:24:13 2006 +0000
@@ -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 @@
     {
      "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 @@
 typedef struct
 {
     IDirect3DDevice9 *device;
+    D3DPRESENT_PARAMETERS pparams;
     SDL_bool beginScene;
 } D3D_RenderData;
 
@@ -182,6 +184,7 @@
         break;
     }
     SDL_SetError("%s: %s", prefix, error);
+    fprintf(stderr, "%s: %s\n", prefix, error);
 }
 
 static D3DFORMAT
@@ -253,6 +256,7 @@
         return NULL;
     }
 
+    renderer->DisplayModeChanged = D3D_DisplayModeChanged;
     renderer->CreateTexture = D3D_CreateTexture;
     renderer->SetTexturePalette = D3D_SetTexturePalette;
     renderer->GetTexturePalette = D3D_GetTexturePalette;
@@ -276,7 +280,7 @@
     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 @@
     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 @@
     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;
@@ -371,6 +376,48 @@
 }
 
 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)
 {
     D3D_RenderData *renderdata = (D3D_RenderData *) renderer->driverdata;
@@ -388,6 +435,12 @@
 
     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 @@
         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 @@
     texture->driverdata = NULL;
 }
 
-void
+static void
 D3D_DestroyRenderer(SDL_Renderer * renderer)
 {
     D3D_RenderData *data = (D3D_RenderData *) renderer->driverdata;
--- a/src/video/win32/SDL_gdirender.c	Sun Aug 06 23:34:59 2006 +0000
+++ b/src/video/win32/SDL_gdirender.c	Mon Aug 07 05:24:13 2006 +0000
@@ -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 @@
     {
      "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 @@
         return NULL;
     }
 
+    renderer->DisplayModeChanged = GDI_DisplayModeChanged;
     renderer->CreateTexture = GDI_CreateTexture;
     renderer->QueryTexturePixels = GDI_QueryTexturePixels;
     renderer->SetTexturePalette = GDI_SetTexturePalette;
@@ -196,7 +198,7 @@
 
     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;
@@ -231,6 +233,42 @@
 }
 
 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)
 {
     GDI_RenderData *renderdata = (GDI_RenderData *) renderer->driverdata;
@@ -258,7 +296,7 @@
     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 @@
     texture->driverdata = NULL;
 }
 
-void
+static void
 GDI_DestroyRenderer(SDL_Renderer * renderer)
 {
     GDI_RenderData *data = (GDI_RenderData *) renderer->driverdata;