diff --git a/src/render/direct3d/SDL_render_d3d.c b/src/render/direct3d/SDL_render_d3d.c index 69279859e..be88da3c8 100644 --- a/src/render/direct3d/SDL_render_d3d.c +++ b/src/render/direct3d/SDL_render_d3d.c @@ -193,6 +193,9 @@ typedef struct typedef struct { SDL_bool dirty; + int w, h; + DWORD usage; + Uint32 format; IDirect3DTexture9 *texture; IDirect3DTexture9 *staging; } D3D_TextureRep; @@ -819,6 +822,10 @@ D3D_CreateTextureRep(IDirect3DDevice9 *device, D3D_TextureRep *texture, DWORD us HRESULT result; texture->dirty = SDL_FALSE; + texture->w = w; + texture->h = h; + texture->usage = usage; + texture->format = format; result = IDirect3DDevice9_CreateTexture(device, w, h, 1, usage, PixelFormatToD3DFMT(format), @@ -826,10 +833,18 @@ D3D_CreateTextureRep(IDirect3DDevice9 *device, D3D_TextureRep *texture, DWORD us if (FAILED(result)) { return D3D_SetError("CreateTexture(D3DPOOL_DEFAULT)", result); } + return 0; +} - if (usage != D3DUSAGE_RENDERTARGET) { - result = IDirect3DDevice9_CreateTexture(device, w, h, 1, usage, - PixelFormatToD3DFMT(format), + +static int +D3D_CreateStagingTexture(IDirect3DDevice9 *device, D3D_TextureRep *texture) +{ + HRESULT result; + + if (texture->staging == NULL) { + result = IDirect3DDevice9_CreateTexture(device, texture->w, texture->h, 1, texture->usage, + PixelFormatToD3DFMT(texture->format), D3DPOOL_SYSTEMMEM, &texture->staging, NULL); if (FAILED(result)) { return D3D_SetError("CreateTexture(D3DPOOL_SYSTEMMEM)", result); @@ -845,14 +860,8 @@ D3D_BindTextureRep(IDirect3DDevice9 *device, D3D_TextureRep *texture, DWORD samp if (texture->dirty && texture->staging) { if (!texture->texture) { - D3DSURFACE_DESC desc; - result = IDirect3DTexture9_GetLevelDesc(texture->staging, 0, &desc); - if (FAILED(result)) { - return D3D_SetError("GetLevelDesc", result); - } - - result = IDirect3DDevice9_CreateTexture(device, desc.Width, desc.Height, 1, 0, - desc.Format, D3DPOOL_DEFAULT, &texture->texture, NULL); + result = IDirect3DDevice9_CreateTexture(device, texture->w, texture->h, 1, texture->usage, + PixelFormatToD3DFMT(texture->format), D3DPOOL_DEFAULT, &texture->texture, NULL); if (FAILED(result)) { return D3D_SetError("CreateTexture(D3DPOOL_DEFAULT)", result); } @@ -878,8 +887,10 @@ D3D_RecreateTextureRep(IDirect3DDevice9 *device, D3D_TextureRep *texture, Uint32 IDirect3DTexture9_Release(texture->texture); texture->texture = NULL; } - IDirect3DTexture9_AddDirtyRect(texture->staging, NULL); - texture->dirty = SDL_TRUE; + if (texture->staging) { + IDirect3DTexture9_AddDirtyRect(texture->staging, NULL); + texture->dirty = SDL_TRUE; + } return 0; } @@ -893,10 +904,15 @@ D3D_UpdateTextureRep(IDirect3DDevice9 *device, D3D_TextureRep *texture, Uint32 f int row, length; HRESULT result; + if (D3D_CreateStagingTexture(device, texture) < 0) { + return -1; + } + d3drect.left = x; d3drect.right = x + w; d3drect.top = y; d3drect.bottom = y + h; + result = IDirect3DTexture9_LockRect(texture->staging, 0, &locked, &d3drect, 0); if (FAILED(result)) { return D3D_SetError("LockRect()", result); @@ -1068,7 +1084,9 @@ static int D3D_LockTexture(SDL_Renderer * renderer, SDL_Texture * texture, const SDL_Rect * rect, void **pixels, int *pitch) { + D3D_RenderData *data = (D3D_RenderData *)renderer->driverdata; D3D_TextureData *texturedata = (D3D_TextureData *)texture->driverdata; + IDirect3DDevice9 *device = data->device; if (!texturedata) { SDL_SetError("Texture is not currently available"); @@ -1095,6 +1113,10 @@ D3D_LockTexture(SDL_Renderer * renderer, SDL_Texture * texture, D3DLOCKED_RECT locked; HRESULT result; + if (D3D_CreateStagingTexture(device, &texturedata->texture) < 0) { + return -1; + } + d3drect.left = rect->x; d3drect.right = rect->x + rect->w; d3drect.top = rect->y; @@ -1137,7 +1159,9 @@ D3D_SetRenderTargetInternal(SDL_Renderer * renderer, SDL_Texture * texture) { D3D_RenderData *data = (D3D_RenderData *) renderer->driverdata; D3D_TextureData *texturedata; + D3D_TextureRep *texturerep; HRESULT result; + IDirect3DDevice9 *device = data->device; /* Release the previous render target if it wasn't the default one */ if (data->currentRenderTarget != NULL) { @@ -1156,6 +1180,24 @@ D3D_SetRenderTargetInternal(SDL_Renderer * renderer, SDL_Texture * texture) return -1; } + /* Make sure the render target is updated if it was locked and written to */ + texturerep = &texturedata->texture; + if (texturerep->dirty && texturerep->staging) { + if (!texturerep->texture) { + result = IDirect3DDevice9_CreateTexture(device, texturerep->w, texturerep->h, 1, texturerep->usage, + PixelFormatToD3DFMT(texturerep->format), D3DPOOL_DEFAULT, &texturerep->texture, NULL); + if (FAILED(result)) { + return D3D_SetError("CreateTexture(D3DPOOL_DEFAULT)", result); + } + } + + result = IDirect3DDevice9_UpdateTexture(device, (IDirect3DBaseTexture9 *)texturerep->staging, (IDirect3DBaseTexture9 *)texturerep->texture); + if (FAILED(result)) { + return D3D_SetError("UpdateTexture()", result); + } + texturerep->dirty = SDL_FALSE; + } + result = IDirect3DTexture9_GetSurfaceLevel(texturedata->texture.texture, 0, &data->currentRenderTarget); if(FAILED(result)) { return D3D_SetError("GetSurfaceLevel()", result);