فهرست منبع

Fixed bugs 2677 and 2625, made it possible to lock render targets in D3D

Sam Lantinga 11 سال پیش
والد
کامیت
d673d8c389
1فایلهای تغییر یافته به همراه55 افزوده شده و 13 حذف شده
  1. 55 13
      src/render/direct3d/SDL_render_d3d.c

+ 55 - 13
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);