Fixed bugs 2677 and 2625, made it possible to lock render targets in D3D
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149
diff --git a/src/render/direct3d/SDL_render_d3d.c b/src/render/direct3d/SDL_render_d3d.c
index 6927985..be88da3 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;
+}
+
+
+static int
+D3D_CreateStagingTexture(IDirect3DDevice9 *device, D3D_TextureRep *texture)
+{
+ HRESULT result;
- if (usage != D3DUSAGE_RENDERTARGET) {
- result = IDirect3DDevice9_CreateTexture(device, w, h, 1, usage,
- PixelFormatToD3DFMT(format),
+ 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);