st/nine: Split NineSurface9_CopySurface
authorAxel Davy <axel.davy@ens.fr>
Sun, 3 May 2015 20:40:38 +0000 (22:40 +0200)
committerAxel Davy <axel.davy@ens.fr>
Fri, 21 Aug 2015 20:21:45 +0000 (22:21 +0200)
NineSurface9_CopySurface was supporting more cases than what
we needed, and doing checks that were innapropriate for
some NineSurface9_CopySurface use cases.

This patch splits it into two for the two use cases, and moves
the checks to the caller.

This patch also adds a few checks to NineDevice9_UpdateSurface

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

index a1c05b48ff4ce3fd1cf1c69f7d9a5e57597a4a6d..57831c4a40a3b08214eabb4bab373733a478ee22 100644 (file)
@@ -1185,6 +1185,8 @@ NineDevice9_UpdateSurface( struct NineDevice9 *This,
 {
     struct NineSurface9 *dst = NineSurface9(pDestinationSurface);
     struct NineSurface9 *src = NineSurface9(pSourceSurface);
+    int copy_width, copy_height;
+    RECT destRect;
 
     DBG("This=%p pSourceSurface=%p pDestinationSurface=%p "
         "pSourceRect=%p pDestPoint=%p\n", This,
@@ -1196,13 +1198,75 @@ NineDevice9_UpdateSurface( struct NineDevice9 *This,
     if (pDestPoint)
         DBG("pDestPoint = (%u,%u)\n", pDestPoint->x, pDestPoint->y);
 
+    user_assert(dst && src, D3DERR_INVALIDCALL);
+
     user_assert(dst->base.pool == D3DPOOL_DEFAULT, D3DERR_INVALIDCALL);
     user_assert(src->base.pool == D3DPOOL_SYSTEMMEM, D3DERR_INVALIDCALL);
 
     user_assert(dst->desc.MultiSampleType == D3DMULTISAMPLE_NONE, D3DERR_INVALIDCALL);
     user_assert(src->desc.MultiSampleType == D3DMULTISAMPLE_NONE, D3DERR_INVALIDCALL);
 
-    return NineSurface9_CopySurface(dst, src, pDestPoint, pSourceRect);
+    user_assert(!src->lock_count, D3DERR_INVALIDCALL);
+    user_assert(!dst->lock_count, D3DERR_INVALIDCALL);
+
+    user_assert(dst->desc.Format == src->desc.Format, D3DERR_INVALIDCALL);
+    user_assert(!depth_stencil_format(dst->desc.Format), D3DERR_INVALIDCALL);
+
+    if (pSourceRect) {
+        copy_width = pSourceRect->right - pSourceRect->left;
+        copy_height = pSourceRect->bottom - pSourceRect->top;
+
+        user_assert(pSourceRect->left >= 0 &&
+                    copy_width > 0 &&
+                    pSourceRect->right <= src->desc.Width &&
+                    pSourceRect->top >= 0 &&
+                    copy_height > 0 &&
+                    pSourceRect->bottom <= src->desc.Height,
+                    D3DERR_INVALIDCALL);
+    } else {
+        copy_width = src->desc.Width;
+        copy_height = src->desc.Height;
+    }
+
+    destRect.right = copy_width;
+    destRect.bottom = copy_height;
+
+    if (pDestPoint) {
+        user_assert(pDestPoint->x >= 0 && pDestPoint->y >= 0,
+                    D3DERR_INVALIDCALL);
+        destRect.right += pDestPoint->x;
+        destRect.bottom += pDestPoint->y;
+    }
+
+    user_assert(destRect.right <= dst->desc.Width &&
+                destRect.bottom <= dst->desc.Height,
+                D3DERR_INVALIDCALL);
+
+    if (compressed_format(dst->desc.Format)) {
+        const unsigned w = util_format_get_blockwidth(dst->base.info.format);
+        const unsigned h = util_format_get_blockheight(dst->base.info.format);
+
+        if (pDestPoint) {
+            user_assert(!(pDestPoint->x % w) && !(pDestPoint->y % h),
+                        D3DERR_INVALIDCALL);
+        }
+
+        if (pSourceRect) {
+            user_assert(!(pSourceRect->left % w) && !(pSourceRect->top % h),
+                        D3DERR_INVALIDCALL);
+        }
+        if (!(copy_width == src->desc.Width &&
+              copy_width == dst->desc.Width &&
+              copy_height == src->desc.Height &&
+              copy_height == dst->desc.Height)) {
+            user_assert(!(copy_width  % w) && !(copy_height % h),
+                        D3DERR_INVALIDCALL);
+        }
+    }
+
+    NineSurface9_CopyMemToDefault(dst, src, pDestPoint, pSourceRect);
+
+    return D3D_OK;
 }
 
 HRESULT WINAPI
@@ -1267,8 +1331,8 @@ NineDevice9_UpdateTexture( struct NineDevice9 *This,
         struct NineTexture9 *src = NineTexture9(srcb);
 
         for (l = 0; l <= last_level; ++l, ++m)
-            NineSurface9_CopySurface(dst->surfaces[l],
-                                     src->surfaces[m], NULL, NULL);
+            NineSurface9_CopyMemToDefault(dst->surfaces[l],
+                                          src->surfaces[m], NULL, NULL);
     } else
     if (dstb->base.type == D3DRTYPE_CUBETEXTURE) {
         struct NineCubeTexture9 *dst = NineCubeTexture9(dstb);
@@ -1278,8 +1342,8 @@ NineDevice9_UpdateTexture( struct NineDevice9 *This,
         /* GPUs usually have them stored as arrays of mip-mapped 2D textures. */
         for (z = 0; z < 6; ++z) {
             for (l = 0; l <= last_level; ++l, ++m) {
-                NineSurface9_CopySurface(dst->surfaces[l * 6 + z],
-                                         src->surfaces[m * 6 + z], NULL, NULL);
+                 NineSurface9_CopyMemToDefault(dst->surfaces[l * 6 + z],
+                                               src->surfaces[m * 6 + z], NULL, NULL);
             }
             m -= l;
         }
@@ -1320,7 +1384,12 @@ NineDevice9_GetRenderTargetData( struct NineDevice9 *This,
     user_assert(dst->desc.MultiSampleType < 2, D3DERR_INVALIDCALL);
     user_assert(src->desc.MultiSampleType < 2, D3DERR_INVALIDCALL);
 
-    return NineSurface9_CopySurface(dst, src, NULL, NULL);
+    user_assert(src->desc.Width == dst->desc.Width, D3DERR_INVALIDCALL);
+    user_assert(src->desc.Height == dst->desc.Height, D3DERR_INVALIDCALL);
+
+    NineSurface9_CopyDefaultToMem(dst, src);
+
+    return D3D_OK;
 }
 
 HRESULT WINAPI
index 43a7737cdf982a6a3535d14905b5ef8ba7464f05..2da39cb058c885319bb13c7b161a1304ec7e311d 100644 (file)
@@ -164,6 +164,23 @@ pipe_to_d3d9_format(enum pipe_format format)
     return nine_pipe_to_d3d9_format_map[format];
 }
 
+/* ATI1 and ATI2 are not officially compressed in d3d9 */
+static inline boolean
+compressed_format( D3DFORMAT fmt )
+{
+    switch (fmt) {
+    case D3DFMT_DXT1:
+    case D3DFMT_DXT2:
+    case D3DFMT_DXT3:
+    case D3DFMT_DXT4:
+    case D3DFMT_DXT5:
+        return TRUE;
+    default:
+        break;
+    }
+    return FALSE;
+}
+
 static inline boolean
 depth_stencil_format( D3DFORMAT fmt )
 {
index 164b34e02d53fe0f78350032b6860017d0d47516..3e9465a98285abeb5feb28bd993d4272deb43c32 100644 (file)
@@ -463,140 +463,92 @@ IDirect3DSurface9Vtbl NineSurface9_vtable = {
     (void *)NineSurface9_ReleaseDC
 };
 
-HRESULT
-NineSurface9_CopySurface( struct NineSurface9 *This,
-                          struct NineSurface9 *From,
-                          const POINT *pDestPoint,
-                          const RECT *pSourceRect )
+/* When this function is called, we have already checked
+ * The copy regions fit the surfaces */
+void
+NineSurface9_CopyMemToDefault( struct NineSurface9 *This,
+                               struct NineSurface9 *From,
+                               const POINT *pDestPoint,
+                               const RECT *pSourceRect )
 {
     struct pipe_context *pipe = This->pipe;
     struct pipe_resource *r_dst = This->base.resource;
-    struct pipe_resource *r_src = From->base.resource;
-    struct pipe_transfer *transfer;
-    struct pipe_box src_box;
     struct pipe_box dst_box;
-    uint8_t *p_dst;
     const uint8_t *p_src;
+    int src_x, src_y, dst_x, dst_y, copy_width, copy_height;
 
-    DBG("This=%p From=%p pDestPoint=%p pSourceRect=%p\n",
-        This, From, pDestPoint, pSourceRect);
-
-    assert(This->base.pool != D3DPOOL_MANAGED &&
-           From->base.pool != D3DPOOL_MANAGED);
+    assert(This->base.pool == D3DPOOL_DEFAULT &&
+           From->base.pool == D3DPOOL_SYSTEMMEM);
 
-    user_assert(This->desc.Format == From->desc.Format, D3DERR_INVALIDCALL);
+    if (pDestPoint) {
+        dst_x = pDestPoint->x;
+        dst_y = pDestPoint->y;
+    } else {
+        dst_x = 0;
+        dst_y = 0;
+    }
 
-    dst_box.x = pDestPoint ? pDestPoint->x : 0;
-    dst_box.y = pDestPoint ? pDestPoint->y : 0;
+    if (pSourceRect) {
+        src_x = pSourceRect->left;
+        src_y = pSourceRect->top;
+        copy_width = pSourceRect->right - pSourceRect->left;
+        copy_height = pSourceRect->bottom - pSourceRect->top;
+    } else {
+        src_x = 0;
+        src_y = 0;
+        copy_width = From->desc.Width;
+        copy_height = From->desc.Height;
+    }
 
-    user_assert(dst_box.x >= 0 &&
-                dst_box.y >= 0, D3DERR_INVALIDCALL);
+    u_box_2d_zslice(dst_x, dst_y, This->layer,
+                    copy_width, copy_height, &dst_box);
 
-    dst_box.z = This->layer;
-    src_box.z = From->layer;
+    p_src = NineSurface9_GetSystemMemPointer(From, src_x, src_y);
 
-    dst_box.depth = 1;
-    src_box.depth = 1;
+    pipe->transfer_inline_write(pipe, r_dst, This->level,
+                                0, /* WRITE|DISCARD are implicit */
+                                &dst_box, p_src, From->stride, 0);
 
-    if (pSourceRect) {
-        /* make sure it doesn't range outside the source surface */
-        user_assert(pSourceRect->left >= 0 &&
-                    pSourceRect->right <= From->desc.Width &&
-                    pSourceRect->top >= 0 &&
-                    pSourceRect->bottom <= From->desc.Height,
-                    D3DERR_INVALIDCALL);
-        if (rect_to_pipe_box_xy_only_clamp(&src_box, pSourceRect))
-            return D3D_OK;
-    } else {
-        src_box.x = 0;
-        src_box.y = 0;
-        src_box.width = From->desc.Width;
-        src_box.height = From->desc.Height;
-    }
+    NineSurface9_MarkContainerDirty(This);
+}
 
-    /* limits */
-    dst_box.width = This->desc.Width - dst_box.x;
-    dst_box.height = This->desc.Height - dst_box.y;
+void
+NineSurface9_CopyDefaultToMem( struct NineSurface9 *This,
+                               struct NineSurface9 *From )
+{
+    struct pipe_context *pipe = This->pipe;
+    struct pipe_resource *r_src = From->base.resource;
+    struct pipe_transfer *transfer;
+    struct pipe_box src_box;
+    uint8_t *p_dst;
+    const uint8_t *p_src;
 
-    user_assert(src_box.width <= dst_box.width &&
-                src_box.height <= dst_box.height, D3DERR_INVALIDCALL);
+    assert(This->base.pool == D3DPOOL_SYSTEMMEM &&
+           From->base.pool == D3DPOOL_DEFAULT);
 
-    dst_box.width = src_box.width;
-    dst_box.height = src_box.height;
+    assert(This->desc.Width == From->desc.Width);
+    assert(This->desc.Height == From->desc.Height);
 
-    /* check source block align for compressed textures */
-    if (util_format_is_compressed(From->base.info.format) &&
-        ((src_box.width != From->desc.Width) ||
-         (src_box.height != From->desc.Height))) {
-        const unsigned w = util_format_get_blockwidth(From->base.info.format);
-        const unsigned h = util_format_get_blockheight(From->base.info.format);
-        user_assert(!(src_box.width % w) &&
-                    !(src_box.height % h),
-                    D3DERR_INVALIDCALL);
-    }
+    u_box_origin_2d(This->desc.Width, This->desc.Height, &src_box);
+    src_box.z = From->layer;
 
-    /* check destination block align for compressed textures */
-    if (util_format_is_compressed(This->base.info.format) &&
-        ((dst_box.width != This->desc.Width) ||
-         (dst_box.height != This->desc.Height) ||
-         dst_box.x != 0 ||
-         dst_box.y != 0)) {
-        const unsigned w = util_format_get_blockwidth(This->base.info.format);
-        const unsigned h = util_format_get_blockheight(This->base.info.format);
-        user_assert(!(dst_box.x % w) && !(dst_box.width % w) &&
-                    !(dst_box.y % h) && !(dst_box.height % h),
-                    D3DERR_INVALIDCALL);
-    }
+    p_src = pipe->transfer_map(pipe, r_src, From->level,
+                               PIPE_TRANSFER_READ,
+                               &src_box, &transfer);
+    p_dst = NineSurface9_GetSystemMemPointer(This, 0, 0);
 
-    if (r_dst && r_src) {
-        pipe->resource_copy_region(pipe,
-                                   r_dst, This->level,
-                                   dst_box.x, dst_box.y, dst_box.z,
-                                   r_src, From->level,
-                                   &src_box);
-    } else
-    if (r_dst) {
-        p_src = NineSurface9_GetSystemMemPointer(From, src_box.x, src_box.y);
-
-        pipe->transfer_inline_write(pipe, r_dst, This->level,
-                                    0, /* WRITE|DISCARD are implicit */
-                                    &dst_box, p_src, From->stride, 0);
-    } else
-    if (r_src) {
-        p_dst = NineSurface9_GetSystemMemPointer(This, 0, 0);
-
-        p_src = pipe->transfer_map(pipe, r_src, From->level,
-                                   PIPE_TRANSFER_READ,
-                                   &src_box, &transfer);
-        if (!p_src)
-            return D3DERR_DRIVERINTERNALERROR;
-
-        util_copy_rect(p_dst, This->base.info.format,
-                       This->stride, dst_box.x, dst_box.y,
-                       dst_box.width, dst_box.height,
-                       p_src,
-                       transfer->stride, src_box.x, src_box.y);
-
-        pipe->transfer_unmap(pipe, transfer);
-    } else {
-        p_dst = NineSurface9_GetSystemMemPointer(This, 0, 0);
-        p_src = NineSurface9_GetSystemMemPointer(From, 0, 0);
-
-        util_copy_rect(p_dst, This->base.info.format,
-                       This->stride, dst_box.x, dst_box.y,
-                       dst_box.width, dst_box.height,
-                       p_src,
-                       From->stride, src_box.x, src_box.y);
-    }
+    assert (p_src && p_dst);
 
-    if (This->base.pool == D3DPOOL_DEFAULT)
-        NineSurface9_MarkContainerDirty(This);
-    if (!r_dst && This->base.resource)
-        NineSurface9_AddDirtyRect(This, &dst_box);
+    util_copy_rect(p_dst, This->base.info.format,
+                   This->stride, 0, 0,
+                   This->desc.Width, This->desc.Height,
+                   p_src,
+                   transfer->stride, 0, 0);
 
-    return D3D_OK;
+    pipe->transfer_unmap(pipe, transfer);
 }
 
+
 /* Gladly, rendering to a MANAGED surface is not permitted, so we will
  * never have to do the reverse, i.e. download the surface.
  */
index 73092ab8cf5101df344333ff9ab3acc4b7ed40ad..76156ae699c3c3ff0f6956e6041da4eada44f193 100644 (file)
@@ -125,11 +125,15 @@ HRESULT
 NineSurface9_UploadSelf( struct NineSurface9 *This,
                          const struct pipe_box *damaged );
 
-HRESULT
-NineSurface9_CopySurface( struct NineSurface9 *This,
-                          struct NineSurface9 *From,
-                          const POINT *pDestPoint,
-                          const RECT *pSourceRect );
+void
+NineSurface9_CopyMemToDefault( struct NineSurface9 *This,
+                               struct NineSurface9 *From,
+                               const POINT *pDestPoint,
+                               const RECT *pSourceRect );
+
+void
+NineSurface9_CopyDefaultToMem( struct NineSurface9 *This,
+                               struct NineSurface9 *From );
 
 static inline boolean
 NineSurface9_IsOffscreenPlain (struct NineSurface9 *This )
index b8ad403456cf18030d5380030ea11685bb6059c9..b6bc9c81f875c9efe9940d8730eafc895dcc7576 100644 (file)
@@ -859,6 +859,8 @@ NineSwapChain9_GetFrontBufferData( struct NineSwapChain9 *This,
     DBG("GetFrontBufferData: This=%p pDestSurface=%p\n",
         This, pDestSurface);
 
+    user_assert(dest_surface->base.pool == D3DPOOL_SYSTEMMEM, D3DERR_INVALIDCALL);
+
     width = dest_surface->desc.Width;
     height = dest_surface->desc.Height;
 
@@ -873,7 +875,7 @@ NineSwapChain9_GetFrontBufferData( struct NineSwapChain9 *This,
     desc.MultiSampleQuality = 0;
     desc.Width = width;
     desc.Height = height;
-    /* NineSurface9_CopySurface needs same format. */
+    /* NineSurface9_CopyDefaultToMem needs same format. */
     desc.Format = dest_surface->desc.Format;
     desc.Usage = D3DUSAGE_RENDERTARGET;
     hr = NineSurface9_new(pDevice, NineUnknown(This), temp_resource, NULL, 0,
@@ -886,7 +888,7 @@ NineSwapChain9_GetFrontBufferData( struct NineSwapChain9 *This,
 
     ID3DPresent_FrontBufferCopy(This->present, temp_handle);
 
-    NineSurface9_CopySurface(dest_surface, temp_surface, NULL, NULL);
+    NineSurface9_CopyDefaultToMem(dest_surface, temp_surface);
 
     ID3DPresent_DestroyD3DWindowBuffer(This->present, temp_handle);
     NineUnknown_Destroy(NineUnknown(temp_surface));