Fixed crash and lost pixel data when recovering from a lost device situation (e.g. alt-tab from fullscreen)

main
Sam Lantinga 2014-06-04 10:57:40 -07:00
parent 947a0b8bae
commit c15e26d77d
1 changed files with 58 additions and 55 deletions

View File

@ -190,6 +190,7 @@ typedef struct
typedef struct typedef struct
{ {
SDL_bool dirty;
IDirect3DTexture9 *texture; IDirect3DTexture9 *texture;
IDirect3DTexture9 *staging; IDirect3DTexture9 *staging;
} D3D_TextureRep; } D3D_TextureRep;
@ -818,6 +819,8 @@ D3D_CreateTextureRep(IDirect3DDevice9 *device, D3D_TextureRep *texture, DWORD us
{ {
HRESULT result; HRESULT result;
texture->dirty = SDL_FALSE;
result = IDirect3DDevice9_CreateTexture(device, w, h, 1, usage, result = IDirect3DDevice9_CreateTexture(device, w, h, 1, usage,
PixelFormatToD3DFMT(format), PixelFormatToD3DFMT(format),
D3DPOOL_DEFAULT, &texture->texture, NULL); D3DPOOL_DEFAULT, &texture->texture, NULL);
@ -837,30 +840,47 @@ D3D_CreateTextureRep(IDirect3DDevice9 *device, D3D_TextureRep *texture, DWORD us
} }
static int static int
D3D_RecreateTextureRep(IDirect3DDevice9 *device, D3D_TextureRep *texture, Uint32 format, int w, int h) D3D_BindTextureRep(IDirect3DDevice9 *device, D3D_TextureRep *texture, DWORD sampler)
{ {
HRESULT result; HRESULT result;
if (texture->dirty && texture->staging) {
if (!texture->texture) { if (!texture->texture) {
return 0; D3DSURFACE_DESC desc;
result = IDirect3DTexture9_GetLevelDesc(texture->staging, 0, &desc);
if (FAILED(result)) {
return D3D_SetError("GetLevelDesc", result);
} }
IDirect3DTexture9_Release(texture->texture); result = IDirect3DDevice9_CreateTexture(device, desc.Width, desc.Height, 1, 0,
result = IDirect3DDevice9_CreateTexture(device, w, h, 1, 0, desc.Format, D3DPOOL_DEFAULT, &texture->texture, NULL);
PixelFormatToD3DFMT(format),
D3DPOOL_DEFAULT, &texture->texture, NULL);
if (FAILED(result)) { if (FAILED(result)) {
return D3D_SetError("CreateTexture(D3DPOOL_DEFAULT)", result); return D3D_SetError("CreateTexture(D3DPOOL_DEFAULT)", result);
} }
result = IDirect3DTexture9_AddDirtyRect(texture->staging, NULL);
if (FAILED(result)) {
return D3D_SetError("AddDirtyRect()", result);
} }
result = IDirect3DDevice9_UpdateTexture(device, (IDirect3DBaseTexture9 *)texture->staging, (IDirect3DBaseTexture9 *)texture->texture); result = IDirect3DDevice9_UpdateTexture(device, (IDirect3DBaseTexture9 *)texture->staging, (IDirect3DBaseTexture9 *)texture->texture);
if (FAILED(result)) { if (FAILED(result)) {
return D3D_SetError("UpdateTexture()", result); return D3D_SetError("UpdateTexture()", result);
} }
texture->dirty = SDL_FALSE;
}
result = IDirect3DDevice9_SetTexture(device, sampler, (IDirect3DBaseTexture9 *)texture->texture);
if (FAILED(result)) {
return D3D_SetError("SetTexture()", result);
}
return 0;
}
static int
D3D_RecreateTextureRep(IDirect3DDevice9 *device, D3D_TextureRep *texture, Uint32 format, int w, int h)
{
if (texture->texture) {
IDirect3DTexture9_Release(texture->texture);
texture->texture = NULL;
}
IDirect3DTexture9_AddDirtyRect(texture->staging, NULL);
texture->dirty = SDL_TRUE;
return 0; return 0;
} }
@ -901,8 +921,11 @@ D3D_UpdateTextureRep(IDirect3DDevice9 *device, D3D_TextureRep *texture, Uint32 f
dst += locked.Pitch; dst += locked.Pitch;
} }
} }
IDirect3DTexture9_UnlockRect(texture->staging, 0); result = IDirect3DTexture9_UnlockRect(texture->staging, 0);
IDirect3DDevice9_UpdateTexture(device, (IDirect3DBaseTexture9 *)texture->staging, (IDirect3DBaseTexture9 *)texture->texture); if (FAILED(result)) {
return D3D_SetError("UnlockRect()", result);
}
texture->dirty = SDL_TRUE;
return 0; return 0;
} }
@ -1106,7 +1129,7 @@ D3D_UnlockTexture(SDL_Renderer * renderer, SDL_Texture * texture)
D3D_UpdateTexture(renderer, texture, rect, pixels, texturedata->pitch); D3D_UpdateTexture(renderer, texture, rect, pixels, texturedata->pitch);
} else { } else {
IDirect3DTexture9_UnlockRect(texturedata->texture.staging, 0); IDirect3DTexture9_UnlockRect(texturedata->texture.staging, 0);
IDirect3DDevice9_UpdateTexture(data->device, (IDirect3DBaseTexture9 *)texturedata->texture.staging, (IDirect3DBaseTexture9 *)texturedata->texture.texture); texturedata->texture.dirty = SDL_TRUE;
} }
} }
@ -1580,11 +1603,8 @@ D3D_RenderCopy(SDL_Renderer * renderer, SDL_Texture * texture,
D3D_UpdateTextureScaleMode(data, texturedata, 0); D3D_UpdateTextureScaleMode(data, texturedata, 0);
result = if (D3D_BindTextureRep(data->device, &texturedata->texture, 0) < 0) {
IDirect3DDevice9_SetTexture(data->device, 0, (IDirect3DBaseTexture9 *) return -1;
texturedata->texture.texture);
if (FAILED(result)) {
return D3D_SetError("SetTexture()", result);
} }
if (texturedata->yuv) { if (texturedata->yuv) {
@ -1593,18 +1613,11 @@ D3D_RenderCopy(SDL_Renderer * renderer, SDL_Texture * texture,
D3D_UpdateTextureScaleMode(data, texturedata, 1); D3D_UpdateTextureScaleMode(data, texturedata, 1);
D3D_UpdateTextureScaleMode(data, texturedata, 2); D3D_UpdateTextureScaleMode(data, texturedata, 2);
result = if (D3D_BindTextureRep(data->device, &texturedata->utexture, 1) < 0) {
IDirect3DDevice9_SetTexture(data->device, 1, (IDirect3DBaseTexture9 *) return -1;
texturedata->utexture.texture);
if (FAILED(result)) {
return D3D_SetError("SetTexture()", result);
} }
if (D3D_BindTextureRep(data->device, &texturedata->vtexture, 2) < 0) {
result = return -1;
IDirect3DDevice9_SetTexture(data->device, 2, (IDirect3DBaseTexture9 *)
texturedata->vtexture.texture);
if (FAILED(result)) {
return D3D_SetError("SetTexture()", result);
} }
} }
@ -1723,11 +1736,8 @@ D3D_RenderCopyEx(SDL_Renderer * renderer, SDL_Texture * texture,
D3D_UpdateTextureScaleMode(data, texturedata, 0); D3D_UpdateTextureScaleMode(data, texturedata, 0);
result = if (D3D_BindTextureRep(data->device, &texturedata->texture, 0) < 0) {
IDirect3DDevice9_SetTexture(data->device, 0, (IDirect3DBaseTexture9 *) return -1;
texturedata->texture.texture);
if (FAILED(result)) {
return D3D_SetError("SetTexture()", result);
} }
if (texturedata->yuv) { if (texturedata->yuv) {
@ -1736,18 +1746,11 @@ D3D_RenderCopyEx(SDL_Renderer * renderer, SDL_Texture * texture,
D3D_UpdateTextureScaleMode(data, texturedata, 1); D3D_UpdateTextureScaleMode(data, texturedata, 1);
D3D_UpdateTextureScaleMode(data, texturedata, 2); D3D_UpdateTextureScaleMode(data, texturedata, 2);
result = if (D3D_BindTextureRep(data->device, &texturedata->utexture, 1) < 0) {
IDirect3DDevice9_SetTexture(data->device, 1, (IDirect3DBaseTexture9 *) return -1;
texturedata->utexture.texture);
if (FAILED(result)) {
return D3D_SetError("SetTexture()", result);
} }
if (D3D_BindTextureRep(data->device, &texturedata->vtexture, 2) < 0) {
result = return -1;
IDirect3DDevice9_SetTexture(data->device, 2, (IDirect3DBaseTexture9 *)
texturedata->vtexture.texture);
if (FAILED(result)) {
return D3D_SetError("SetTexture()", result);
} }
} }