st/nine: Simplify Surface9 Managed resources implementation
authorAxel Davy <axel.davy@ens.fr>
Thu, 19 Feb 2015 16:34:45 +0000 (17:34 +0100)
committerAxel Davy <axel.davy@ens.fr>
Wed, 29 Apr 2015 06:28:11 +0000 (08:28 +0200)
Remove the Surface9 code for dirty rects, used only for Managed
resources. Instead convey the information to the parent texture.

According to documentation, this seems to be the expected behaviour,
and if documentation is wrong there, that's not a problem since it can
only leads to more texture updates in corner cases.

Signed-off-by: Axel Davy <axel.davy@ens.fr>
src/gallium/state_trackers/nine/basetexture9.c
src/gallium/state_trackers/nine/nine_pipe.h
src/gallium/state_trackers/nine/surface9.c
src/gallium/state_trackers/nine/surface9.h

index 75a305f099a7d50bb7a1df4b3c8015a31c58f96f..9b7976c3862c5f19efadf223ece21d3366022151 100644 (file)
@@ -279,16 +279,17 @@ NineBaseTexture9_UploadSelf( struct NineBaseTexture9 *This )
             tex->dirty_rect.x, tex->dirty_rect.y,
             tex->dirty_rect.width, tex->dirty_rect.height);
 
+        /* Note: for l < This->managed.lod, the resource is
+         * non-existing, and thus will be entirely re-uploaded
+         * if This->managed.lod changes */
         if (tex->dirty_rect.width) {
-            for (l = 0; l <= last_level; ++l) {
+            for (l = This->managed.lod; l <= last_level; ++l) {
                 u_box_minify_2d(&box, &tex->dirty_rect, l);
-                NineSurface9_AddDirtyRect(tex->surfaces[l], &box);
+                NineSurface9_UploadSelf(tex->surfaces[l], &box);
             }
             memset(&tex->dirty_rect, 0, sizeof(tex->dirty_rect));
             tex->dirty_rect.depth = 1;
         }
-        for (l = This->managed.lod; l <= last_level; ++l)
-            NineSurface9_UploadSelf(tex->surfaces[l]);
     } else
     if (This->base.type == D3DRTYPE_CUBETEXTURE) {
         struct NineCubeTexture9 *tex = NineCubeTexture9(This);
@@ -303,15 +304,13 @@ NineBaseTexture9_UploadSelf( struct NineBaseTexture9 *This )
                 tex->dirty_rect[z].width, tex->dirty_rect[z].height);
 
             if (tex->dirty_rect[z].width) {
-                for (l = 0; l <= last_level; ++l) {
+                for (l = This->managed.lod; l <= last_level; ++l) {
                     u_box_minify_2d(&box, &tex->dirty_rect[z], l);
-                    NineSurface9_AddDirtyRect(tex->surfaces[l * 6 + z], &box);
+                    NineSurface9_UploadSelf(tex->surfaces[l * 6 + z], &box);
                 }
                 memset(&tex->dirty_rect[z], 0, sizeof(tex->dirty_rect[z]));
                 tex->dirty_rect[z].depth = 1;
             }
-            for (l = This->managed.lod; l <= last_level; ++l)
-                NineSurface9_UploadSelf(tex->surfaces[l * 6 + z]);
         }
     } else
     if (This->base.type == D3DRTYPE_VOLUMETEXTURE) {
index 1b88612f2ccc64372b440f90f9397d27770888b7..91da56301224dea379d250a401ffb76245ac9ac0 100644 (file)
@@ -107,17 +107,6 @@ rect_to_pipe_box_flip(struct pipe_box *dst, const RECT *src)
     return TRUE;
 }
 
-static INLINE void
-nine_u_rect_to_pipe_box(struct pipe_box *dst, const struct u_rect *rect, int z)
-{
-    dst->x = rect->x0;
-    dst->y = rect->y0;
-    dst->z = z;
-    dst->width = rect->x1 - rect->x0;
-    dst->height = rect->y1 - rect->y0;
-    dst->depth = 1;
-}
-
 static INLINE void
 rect_to_pipe_box_xy_only(struct pipe_box *dst, const RECT *src)
 {
index 5c6b3bf2c3d3695f767a4e4bc96d793cdd4da834..36e108dd48bb35528c771aa1048ec1c15f379f1a 100644 (file)
 
 #include "surface9.h"
 #include "device9.h"
-#include "basetexture9.h" /* for marking dirty */
+
+/* for marking dirty */
+#include "basetexture9.h"
+#include "texture9.h"
+#include "cubetexture9.h"
 
 #include "nine_helpers.h"
 #include "nine_pipe.h"
@@ -146,7 +150,6 @@ NineSurface9_dtor( struct NineSurface9 *This )
 {
     if (This->transfer)
         NineSurface9_UnlockRect(This);
-    NineSurface9_ClearDirtyRects(This);
 
     pipe_surface_reference(&This->surface[0], NULL);
     pipe_surface_reference(&This->surface[1], NULL);
@@ -257,55 +260,38 @@ NineSurface9_GetDesc( struct NineSurface9 *This,
     return D3D_OK;
 }
 
-/* Wine just keeps a single directy rect and expands it to cover all
- * the dirty rects ever added.
- * We'll keep 2, and expand the one that fits better, just for fun.
- */
+/* Add the dirty rects to the source texture */
 INLINE void
 NineSurface9_AddDirtyRect( struct NineSurface9 *This,
                            const struct pipe_box *box )
 {
-    float area[2];
-    struct u_rect rect, cover_a, cover_b;
+    RECT dirty_rect;
 
     DBG("This=%p box=%p\n", This, box);
 
-    if (!box) {
-        This->dirty_rects[0].x0 = 0;
-        This->dirty_rects[0].y0 = 0;
-        This->dirty_rects[0].x1 = This->desc.Width;
-        This->dirty_rects[0].y1 = This->desc.Height;
+    assert (This->base.pool != D3DPOOL_MANAGED ||
+            This->texture == D3DRTYPE_CUBETEXTURE ||
+            This->texture == D3DRTYPE_TEXTURE);
 
-        memset(&This->dirty_rects[1], 0, sizeof(This->dirty_rects[1]));
+    if (This->base.pool != D3DPOOL_MANAGED)
         return;
-    }
-    rect.x0 = box->x;
-    rect.y0 = box->y;
-    rect.x1 = box->x + box->width;
-    rect.y1 = box->y + box->height;
 
-    if (This->dirty_rects[0].x1 == 0) {
-        This->dirty_rects[0] = rect;
-        return;
-    }
+    /* Add a dirty rect to level 0 of the parent texture */
+    dirty_rect.left = box->x << This->level_actual;
+    dirty_rect.right = dirty_rect.left + (box->width << This->level_actual);
+    dirty_rect.top = box->y << This->level_actual;
+    dirty_rect.bottom = dirty_rect.top + (box->height << This->level_actual);
 
-    u_rect_union(&cover_a, &This->dirty_rects[0], &rect);
-    area[0] = u_rect_area(&cover_a);
+    if (This->texture == D3DRTYPE_TEXTURE) {
+        struct NineTexture9 *tex =
+            NineTexture9(This->base.base.container);
 
-    if (This->dirty_rects[1].x1 == 0) {
-        area[1] = u_rect_area(&This->dirty_rects[0]);
-        if (area[0] > (area[1] * 1.25f))
-            This->dirty_rects[1] = rect;
-        else
-            This->dirty_rects[0] = cover_a;
-    } else {
-        u_rect_union(&cover_b, &This->dirty_rects[1], &rect);
-        area[1] = u_rect_area(&cover_b);
+        NineTexture9_AddDirtyRect(tex, &dirty_rect);
+    } else { /* This->texture == D3DRTYPE_CUBETEXTURE */
+        struct NineCubeTexture9 *ctex =
+            NineCubeTexture9(This->base.base.container);
 
-        if (area[0] > area[1])
-            This->dirty_rects[1] = cover_b;
-        else
-            This->dirty_rects[0] = cover_a;
+        NineCubeTexture9_AddDirtyRect(ctex, This->layer, &dirty_rect);
     }
 }
 
@@ -423,8 +409,7 @@ NineSurface9_LockRect( struct NineSurface9 *This,
 
     if (!(Flags & (D3DLOCK_NO_DIRTY_UPDATE | D3DLOCK_READONLY))) {
         NineSurface9_MarkContainerDirty(This);
-        if (This->base.pool == D3DPOOL_MANAGED)
-            NineSurface9_AddDirtyRect(This, &box);
+        NineSurface9_AddDirtyRect(This, &box);
     }
 
     ++This->lock_count;
@@ -478,13 +463,6 @@ IDirect3DSurface9Vtbl NineSurface9_vtable = {
     (void *)NineSurface9_ReleaseDC
 };
 
-
-static INLINE boolean
-NineSurface9_IsDirty(struct NineSurface9 *This)
-{
-    return This->dirty_rects[0].x1 != 0;
-}
-
 HRESULT
 NineSurface9_CopySurface( struct NineSurface9 *This,
                           struct NineSurface9 *From,
@@ -623,33 +601,35 @@ NineSurface9_CopySurface( struct NineSurface9 *This,
  * never have to do the reverse, i.e. download the surface.
  */
 HRESULT
-NineSurface9_UploadSelf( struct NineSurface9 *This )
+NineSurface9_UploadSelf( struct NineSurface9 *This,
+                         const struct pipe_box *damaged )
 {
     struct pipe_context *pipe = This->pipe;
     struct pipe_resource *res = This->base.resource;
     uint8_t *ptr;
-    unsigned i;
+    struct pipe_box box;
 
-    DBG("This=%p\n", This);
+    DBG("This=%p damaged=%p\n", This, damaged);
 
     assert(This->base.pool == D3DPOOL_MANAGED);
 
-    if (!NineSurface9_IsDirty(This))
-        return D3D_OK;
-
-    for (i = 0; i < Elements(This->dirty_rects); ++i) {
-        struct pipe_box box;
-        nine_u_rect_to_pipe_box(&box, &This->dirty_rects[i], This->layer);
+    if (damaged) {
+        box = *damaged;
+        box.z = This->layer;
+        box.depth = 1;
+    } else {
+        box.x = 0;
+        box.y = 0;
+        box.z = This->layer;
+        box.width = This->desc.Width;
+        box.height = This->desc.Height;
+        box.depth = 1;
+    }
 
-        if (box.width == 0)
-            break;
-        ptr = NineSurface9_GetSystemMemPointer(This, box.x, box.y);
+    ptr = NineSurface9_GetSystemMemPointer(This, box.x, box.y);
 
-        pipe->transfer_inline_write(pipe, res, This->level,
-                                    0,
-                                    &box, ptr, This->stride, 0);
-    }
-    NineSurface9_ClearDirtyRects(This);
+    pipe->transfer_inline_write(pipe, res, This->level, 0,
+                                &box, ptr, This->stride, 0);
 
     return D3D_OK;
 }
index 7d6932a0f170f8f65ebabe9eab62616df4f4cc94..aa586f37e3c0c08367d8b35259133934e2fdb964 100644 (file)
@@ -49,9 +49,6 @@ struct NineSurface9
 
     uint8_t *data; /* system memory backing */
     unsigned stride; /* for system memory backing */
-
-    /* wine doesn't even use these, 2 will be enough */
-    struct u_rect dirty_rects[2];
 };
 static INLINE struct NineSurface9 *
 NineSurface9( void *data )
@@ -121,14 +118,9 @@ void
 NineSurface9_AddDirtyRect( struct NineSurface9 *This,
                            const struct pipe_box *box );
 
-static INLINE void
-NineSurface9_ClearDirtyRects( struct NineSurface9 *This )
-{
-    memset(&This->dirty_rects, 0, sizeof(This->dirty_rects));
-}
-
 HRESULT
-NineSurface9_UploadSelf( struct NineSurface9 *This );
+NineSurface9_UploadSelf( struct NineSurface9 *This,
+                         const struct pipe_box *damaged );
 
 HRESULT
 NineSurface9_CopySurface( struct NineSurface9 *This,