Fixed crash and lost pixel data when recovering from a lost device situation (e.g. alt-tab from fullscreen)
authorSam Lantinga <slouken@libsdl.org>
Wed, 04 Jun 2014 10:57:40 -0700
changeset 8822b554a3e19d6c
parent 8821 9f2d28d8c136
child 8823 15a1b4b8e20a
Fixed crash and lost pixel data when recovering from a lost device situation (e.g. alt-tab from fullscreen)
src/render/direct3d/SDL_render_d3d.c
     1.1 --- a/src/render/direct3d/SDL_render_d3d.c	Wed Jun 04 10:57:12 2014 -0700
     1.2 +++ b/src/render/direct3d/SDL_render_d3d.c	Wed Jun 04 10:57:40 2014 -0700
     1.3 @@ -190,6 +190,7 @@
     1.4  
     1.5  typedef struct
     1.6  {
     1.7 +    SDL_bool dirty;
     1.8      IDirect3DTexture9 *texture;
     1.9      IDirect3DTexture9 *staging;
    1.10  } D3D_TextureRep;
    1.11 @@ -652,7 +653,7 @@
    1.12      }
    1.13  
    1.14      /* Store the default render target */
    1.15 -    IDirect3DDevice9_GetRenderTarget(data->device, 0, &data->defaultRenderTarget );
    1.16 +    IDirect3DDevice9_GetRenderTarget(data->device, 0, &data->defaultRenderTarget);
    1.17      data->currentRenderTarget = NULL;
    1.18  
    1.19      /* Set up parameters for rendering */
    1.20 @@ -818,6 +819,8 @@
    1.21  {
    1.22      HRESULT result;
    1.23  
    1.24 +    texture->dirty = SDL_FALSE;
    1.25 +
    1.26      result = IDirect3DDevice9_CreateTexture(device, w, h, 1, usage,
    1.27          PixelFormatToD3DFMT(format),
    1.28          D3DPOOL_DEFAULT, &texture->texture, NULL);
    1.29 @@ -837,30 +840,47 @@
    1.30  }
    1.31  
    1.32  static int
    1.33 -D3D_RecreateTextureRep(IDirect3DDevice9 *device, D3D_TextureRep *texture, Uint32 format, int w, int h)
    1.34 +D3D_BindTextureRep(IDirect3DDevice9 *device, D3D_TextureRep *texture, DWORD sampler)
    1.35  {
    1.36      HRESULT result;
    1.37  
    1.38 -    if (!texture->texture) {
    1.39 -        return 0;
    1.40 +    if (texture->dirty && texture->staging) {
    1.41 +        if (!texture->texture) {
    1.42 +            D3DSURFACE_DESC desc;
    1.43 +            result = IDirect3DTexture9_GetLevelDesc(texture->staging, 0, &desc);
    1.44 +            if (FAILED(result)) {
    1.45 +                return D3D_SetError("GetLevelDesc", result);
    1.46 +            }
    1.47 +
    1.48 +            result = IDirect3DDevice9_CreateTexture(device, desc.Width, desc.Height, 1, 0,
    1.49 +                desc.Format, D3DPOOL_DEFAULT, &texture->texture, NULL);
    1.50 +            if (FAILED(result)) {
    1.51 +                return D3D_SetError("CreateTexture(D3DPOOL_DEFAULT)", result);
    1.52 +            }
    1.53 +        }
    1.54 +
    1.55 +        result = IDirect3DDevice9_UpdateTexture(device, (IDirect3DBaseTexture9 *)texture->staging, (IDirect3DBaseTexture9 *)texture->texture);
    1.56 +        if (FAILED(result)) {
    1.57 +            return D3D_SetError("UpdateTexture()", result);
    1.58 +        }
    1.59 +        texture->dirty = SDL_FALSE;
    1.60      }
    1.61 +    result = IDirect3DDevice9_SetTexture(device, sampler, (IDirect3DBaseTexture9 *)texture->texture);
    1.62 +    if (FAILED(result)) {
    1.63 +        return D3D_SetError("SetTexture()", result);
    1.64 +    }
    1.65 +    return 0;
    1.66 +}
    1.67  
    1.68 -    IDirect3DTexture9_Release(texture->texture);
    1.69 -    result = IDirect3DDevice9_CreateTexture(device, w, h, 1, 0,
    1.70 -        PixelFormatToD3DFMT(format),
    1.71 -        D3DPOOL_DEFAULT, &texture->texture, NULL);
    1.72 -    if (FAILED(result)) {
    1.73 -        return D3D_SetError("CreateTexture(D3DPOOL_DEFAULT)", result);
    1.74 +static int
    1.75 +D3D_RecreateTextureRep(IDirect3DDevice9 *device, D3D_TextureRep *texture, Uint32 format, int w, int h)
    1.76 +{
    1.77 +    if (texture->texture) {
    1.78 +        IDirect3DTexture9_Release(texture->texture);
    1.79 +        texture->texture = NULL;
    1.80      }
    1.81 -
    1.82 -    result = IDirect3DTexture9_AddDirtyRect(texture->staging, NULL);
    1.83 -    if (FAILED(result)) {
    1.84 -        return D3D_SetError("AddDirtyRect()", result);
    1.85 -    }
    1.86 -    result = IDirect3DDevice9_UpdateTexture(device, (IDirect3DBaseTexture9 *)texture->staging, (IDirect3DBaseTexture9 *)texture->texture);
    1.87 -    if (FAILED(result)) {
    1.88 -        return D3D_SetError("UpdateTexture()", result);
    1.89 -    }
    1.90 +    IDirect3DTexture9_AddDirtyRect(texture->staging, NULL);
    1.91 +    texture->dirty = SDL_TRUE;
    1.92      return 0;
    1.93  }
    1.94  
    1.95 @@ -901,8 +921,11 @@
    1.96              dst += locked.Pitch;
    1.97          }
    1.98      }
    1.99 -    IDirect3DTexture9_UnlockRect(texture->staging, 0);
   1.100 -    IDirect3DDevice9_UpdateTexture(device, (IDirect3DBaseTexture9 *)texture->staging, (IDirect3DBaseTexture9 *)texture->texture);
   1.101 +    result = IDirect3DTexture9_UnlockRect(texture->staging, 0);
   1.102 +    if (FAILED(result)) {
   1.103 +        return D3D_SetError("UnlockRect()", result);
   1.104 +    }
   1.105 +    texture->dirty = SDL_TRUE;
   1.106  
   1.107      return 0;
   1.108  }
   1.109 @@ -1106,8 +1129,8 @@
   1.110          D3D_UpdateTexture(renderer, texture, rect, pixels, texturedata->pitch);
   1.111      } else {
   1.112          IDirect3DTexture9_UnlockRect(texturedata->texture.staging, 0);
   1.113 -        IDirect3DDevice9_UpdateTexture(data->device, (IDirect3DBaseTexture9 *)texturedata->texture.staging, (IDirect3DBaseTexture9 *)texturedata->texture.texture);
   1.114 -    }
   1.115 +        texturedata->texture.dirty = SDL_TRUE;
   1.116 +   }
   1.117  }
   1.118  
   1.119  static int
   1.120 @@ -1580,11 +1603,8 @@
   1.121  
   1.122      D3D_UpdateTextureScaleMode(data, texturedata, 0);
   1.123  
   1.124 -    result =
   1.125 -        IDirect3DDevice9_SetTexture(data->device, 0, (IDirect3DBaseTexture9 *)
   1.126 -                                    texturedata->texture.texture);
   1.127 -    if (FAILED(result)) {
   1.128 -        return D3D_SetError("SetTexture()", result);
   1.129 +    if (D3D_BindTextureRep(data->device, &texturedata->texture, 0) < 0) {
   1.130 +        return -1;
   1.131      }
   1.132  
   1.133      if (texturedata->yuv) {
   1.134 @@ -1593,18 +1613,11 @@
   1.135          D3D_UpdateTextureScaleMode(data, texturedata, 1);
   1.136          D3D_UpdateTextureScaleMode(data, texturedata, 2);
   1.137  
   1.138 -        result =
   1.139 -            IDirect3DDevice9_SetTexture(data->device, 1, (IDirect3DBaseTexture9 *)
   1.140 -                                        texturedata->utexture.texture);
   1.141 -        if (FAILED(result)) {
   1.142 -            return D3D_SetError("SetTexture()", result);
   1.143 +        if (D3D_BindTextureRep(data->device, &texturedata->utexture, 1) < 0) {
   1.144 +            return -1;
   1.145          }
   1.146 -
   1.147 -        result =
   1.148 -            IDirect3DDevice9_SetTexture(data->device, 2, (IDirect3DBaseTexture9 *)
   1.149 -                                        texturedata->vtexture.texture);
   1.150 -        if (FAILED(result)) {
   1.151 -            return D3D_SetError("SetTexture()", result);
   1.152 +        if (D3D_BindTextureRep(data->device, &texturedata->vtexture, 2) < 0) {
   1.153 +            return -1;
   1.154          }
   1.155      }
   1.156  
   1.157 @@ -1718,16 +1731,13 @@
   1.158      modelMatrix = MatrixMultiply(
   1.159              MatrixRotationZ((float)(M_PI * (float) angle / 180.0f)),
   1.160              MatrixTranslation(dstrect->x + center->x, dstrect->y + center->y, 0)
   1.161 -            );
   1.162 +);
   1.163      IDirect3DDevice9_SetTransform(data->device, D3DTS_VIEW, (D3DMATRIX*)&modelMatrix);
   1.164  
   1.165      D3D_UpdateTextureScaleMode(data, texturedata, 0);
   1.166  
   1.167 -    result =
   1.168 -        IDirect3DDevice9_SetTexture(data->device, 0, (IDirect3DBaseTexture9 *)
   1.169 -                                    texturedata->texture.texture);
   1.170 -    if (FAILED(result)) {
   1.171 -        return D3D_SetError("SetTexture()", result);
   1.172 +    if (D3D_BindTextureRep(data->device, &texturedata->texture, 0) < 0) {
   1.173 +        return -1;
   1.174      }
   1.175  
   1.176      if (texturedata->yuv) {
   1.177 @@ -1735,19 +1745,12 @@
   1.178  
   1.179          D3D_UpdateTextureScaleMode(data, texturedata, 1);
   1.180          D3D_UpdateTextureScaleMode(data, texturedata, 2);
   1.181 -
   1.182 -        result =
   1.183 -            IDirect3DDevice9_SetTexture(data->device, 1, (IDirect3DBaseTexture9 *)
   1.184 -                                        texturedata->utexture.texture);
   1.185 -        if (FAILED(result)) {
   1.186 -            return D3D_SetError("SetTexture()", result);
   1.187 +        
   1.188 +        if (D3D_BindTextureRep(data->device, &texturedata->utexture, 1) < 0) {
   1.189 +            return -1;
   1.190          }
   1.191 -
   1.192 -        result =
   1.193 -            IDirect3DDevice9_SetTexture(data->device, 2, (IDirect3DBaseTexture9 *)
   1.194 -                                        texturedata->vtexture.texture);
   1.195 -        if (FAILED(result)) {
   1.196 -            return D3D_SetError("SetTexture()", result);
   1.197 +        if (D3D_BindTextureRep(data->device, &texturedata->vtexture, 2) < 0) {
   1.198 +            return -1;
   1.199          }
   1.200      }
   1.201