[PATCH 3/6] wined3d: Move format conversion to surface_upload_data.

Stefan Dösinger stefan at codeweavers.com
Tue Nov 26 17:26:38 CST 2013


---
 dlls/wined3d/surface.c | 182 ++++++++++++++++++++++++-------------------------
 1 file changed, 89 insertions(+), 93 deletions(-)

diff --git a/dlls/wined3d/surface.c b/dlls/wined3d/surface.c
index b499bd1..c8fd16a 100644
--- a/dlls/wined3d/surface.c
+++ b/dlls/wined3d/surface.c
@@ -1672,8 +1672,9 @@ static void surface_download_data(struct wined3d_surface *surface, const struct
     }
 }
 
-static HRESULT d3dfmt_get_conv(const struct wined3d_surface *surface, BOOL need_alpha_ck, BOOL use_texturing,
-        struct wined3d_format *format, enum wined3d_conversion_type *conversion_type)
+static HRESULT d3dfmt_get_conv(const struct wined3d_surface *surface, const struct wined3d_format *src_format,
+        BOOL need_alpha_ck, BOOL use_texturing, struct wined3d_format *format,
+        enum wined3d_conversion_type *conversion_type)
 {
     BOOL colorkey_active = need_alpha_ck && (surface->CKeyFlags & WINEDDSD_CKSRCBLT);
     const struct wined3d_device *device = surface->resource.device;
@@ -1682,11 +1683,11 @@ static HRESULT d3dfmt_get_conv(const struct wined3d_surface *surface, BOOL need_
 
     /* Copy the default values from the surface. Below we might perform fixups */
     /* TODO: get rid of color keying desc fixups by using e.g. a table. */
-    *format = *surface->resource.format;
+    *format = *src_format;
     *conversion_type = WINED3D_CT_NONE;
 
     /* Ok, now look if we have to do any conversion */
-    switch (surface->resource.format->id)
+    switch (src_format->id)
     {
         case WINED3DFMT_P8_UINT:
             /* Below the call to blit_supported is disabled for Wine 1.2
@@ -1983,14 +1984,19 @@ static HRESULT d3dfmt_convert_surface(const BYTE *src, BYTE *dst, UINT pitch, UI
  * correct texture. */
 /* Context activation is done by the caller. */
 static void surface_upload_data(struct wined3d_surface *surface, const struct wined3d_gl_info *gl_info,
-        const struct wined3d_format *format, const RECT *src_rect, UINT src_pitch, const POINT *dst_point,
+        const struct wined3d_format *src_format, const RECT *src_rect, UINT src_pitch, const POINT *dst_point,
         BOOL srgb, const struct wined3d_bo_address *data)
 {
     UINT update_w = src_rect->right - src_rect->left;
     UINT update_h = src_rect->bottom - src_rect->top;
+    BYTE *mem, *conv_dst = NULL;
+    enum wined3d_conversion_type convert;
+    const struct wined3d_device *device = surface->resource.device;
+    struct wined3d_format conv_format;
+    BOOL adjust_initial_offset = TRUE;
 
     TRACE("surface %p, gl_info %p, format %s, src_rect %s, src_pitch %u, dst_point %s, srgb %#x, data {%#x:%p}.\n",
-            surface, gl_info, debug_d3dformat(format->id), wine_dbgstr_rect(src_rect), src_pitch,
+            surface, gl_info, debug_d3dformat(src_format->id), wine_dbgstr_rect(src_rect), src_pitch,
             wine_dbgstr_point(dst_point), srgb, data->buffer_object, data->addr);
 
     if (surface->resource.map_count)
@@ -1999,10 +2005,10 @@ static void surface_upload_data(struct wined3d_surface *surface, const struct wi
         surface->flags |= SFLAG_PIN_SYSMEM;
     }
 
-    if (format->flags & WINED3DFMT_FLAG_HEIGHT_SCALE)
+    if (src_format->flags & WINED3DFMT_FLAG_HEIGHT_SCALE)
     {
-        update_h *= format->height_scale.numerator;
-        update_h /= format->height_scale.denominator;
+        update_h *= src_format->height_scale.numerator;
+        update_h /= src_format->height_scale.denominator;
     }
 
     if (data->buffer_object)
@@ -2011,31 +2017,75 @@ static void surface_upload_data(struct wined3d_surface *surface, const struct wi
         checkGLcall("glBindBufferARB");
     }
 
-    if (format->flags & WINED3DFMT_FLAG_COMPRESSED)
+    d3dfmt_get_conv(surface, src_format, TRUE /* We need color keying */,
+            TRUE /* We will use textures */, &conv_format, &convert);
+    if (conv_format.convert || convert != WINED3D_CT_NONE)
+    {
+        DWORD conv_dst_pitch;
+        BYTE *conv_src = data->addr;
+
+        if (data->buffer_object)
+            ERR("Attempting to load a converted surface from a PBO.\n");
+        if (conv_format.flags & WINED3DFMT_FLAG_COMPRESSED)
+            ERR("Converting a compressed format.\n");
+
+        conv_src += src_rect->top * src_pitch;
+        conv_src += src_rect->left * src_format->byte_count;
+
+        /* Stick to the alignment for the converted surface too, makes it easier to load the surface */
+        conv_dst_pitch = update_w * conv_format.conv_byte_count;
+        conv_dst_pitch = (conv_dst_pitch + device->surface_alignment - 1) & ~(device->surface_alignment - 1);
+
+        if (!(conv_dst = HeapAlloc(GetProcessHeap(), 0, conv_dst_pitch * update_h)))
+        {
+            ERR("Out of memory (%u).\n", conv_dst_pitch * update_h);
+            return;
+        }
+
+        if (convert != WINED3D_CT_NONE)
+            d3dfmt_convert_surface(conv_src, conv_dst, src_pitch,
+                    update_w, update_h, conv_dst_pitch, convert, surface);
+        else
+            conv_format.convert(conv_src, conv_dst, src_pitch, src_pitch * update_h,
+                    conv_dst_pitch, conv_dst_pitch * update_h, update_w, update_h, 1);
+
+        conv_format.byte_count = conv_format.conv_byte_count;
+        src_pitch = conv_dst_pitch;
+        mem = conv_dst;
+        adjust_initial_offset = FALSE;
+    }
+    else
+    {
+        mem = data->addr;
+    }
+
+    if (conv_format.flags & WINED3DFMT_FLAG_COMPRESSED)
     {
-        UINT row_length = wined3d_format_calculate_size(format, 1, update_w, 1, 1);
-        UINT row_count = (update_h + format->block_height - 1) / format->block_height;
-        const BYTE *addr = data->addr;
+        UINT row_length = wined3d_format_calculate_size(&conv_format, 1, update_w, 1, 1);
+        UINT row_count = (update_h + conv_format.block_height - 1) / conv_format.block_height;
         GLenum internal;
 
-        addr += (src_rect->top / format->block_height) * src_pitch;
-        addr += (src_rect->left / format->block_width) * format->block_byte_count;
+        if (adjust_initial_offset)
+        {
+            mem += (src_rect->top / conv_format.block_height) * src_pitch;
+            mem += (src_rect->left / conv_format.block_width) * conv_format.block_byte_count;
+        }
 
         if (srgb)
-            internal = format->glGammaInternal;
+            internal = conv_format.glGammaInternal;
         else if (surface->resource.usage & WINED3DUSAGE_RENDERTARGET && surface_is_offscreen(surface))
-            internal = format->rtInternal;
+            internal = conv_format.rtInternal;
         else
-            internal = format->glInternal;
+            internal = conv_format.glInternal;
 
         TRACE("glCompressedTexSubImage2DARB, target %#x, level %d, x %d, y %d, w %d, h %d, "
                 "format %#x, image_size %#x, addr %p.\n", surface->texture_target, surface->texture_level,
-                dst_point->x, dst_point->y, update_w, update_h, internal, row_count * row_length, addr);
+                dst_point->x, dst_point->y, update_w, update_h, internal, row_count * row_length, mem);
 
         if (row_length == src_pitch)
         {
             GL_EXTCALL(glCompressedTexSubImage2DARB(surface->texture_target, surface->texture_level,
-                    dst_point->x, dst_point->y, update_w, update_h, internal, row_count * row_length, addr));
+                    dst_point->x, dst_point->y, update_w, update_h, internal, row_count * row_length, mem));
         }
         else
         {
@@ -2046,27 +2096,28 @@ static void surface_upload_data(struct wined3d_surface *surface, const struct wi
             for (row = 0, y = dst_point->y; row < row_count; ++row)
             {
                 GL_EXTCALL(glCompressedTexSubImage2DARB(surface->texture_target, surface->texture_level,
-                        dst_point->x, y, update_w, format->block_height, internal, row_length, addr));
-                y += format->block_height;
-                addr += src_pitch;
+                        dst_point->x, y, update_w, conv_format.block_height, internal, row_length, mem));
+                y += conv_format.block_height;
+                mem += src_pitch;
             }
         }
         checkGLcall("glCompressedTexSubImage2DARB");
     }
     else
     {
-        const BYTE *addr = data->addr;
-
-        addr += src_rect->top * src_pitch;
-        addr += src_rect->left * format->byte_count;
+        if (adjust_initial_offset)
+        {
+            mem += src_rect->top * src_pitch;
+            mem += src_rect->left * conv_format.byte_count;
+        }
 
         TRACE("glTexSubImage2D, target %#x, level %d, x %d, y %d, w %d, h %d, format %#x, type %#x, addr %p.\n",
                 surface->texture_target, surface->texture_level, dst_point->x, dst_point->y,
-                update_w, update_h, format->glFormat, format->glType, addr);
+                update_w, update_h, conv_format.glFormat, conv_format.glType, mem);
 
-        gl_info->gl_ops.gl.p_glPixelStorei(GL_UNPACK_ROW_LENGTH, src_pitch / format->byte_count);
+        gl_info->gl_ops.gl.p_glPixelStorei(GL_UNPACK_ROW_LENGTH, src_pitch / conv_format.byte_count);
         gl_info->gl_ops.gl.p_glTexSubImage2D(surface->texture_target, surface->texture_level,
-                dst_point->x, dst_point->y, update_w, update_h, format->glFormat, format->glType, addr);
+                dst_point->x, dst_point->y, update_w, update_h, conv_format.glFormat, conv_format.glType, mem);
         gl_info->gl_ops.gl.p_glPixelStorei(GL_UNPACK_ROW_LENGTH, 0);
         checkGLcall("glTexSubImage2D");
     }
@@ -2090,6 +2141,8 @@ static void surface_upload_data(struct wined3d_surface *surface, const struct wi
             context_surface_update(device->contexts[i], surface);
         }
     }
+
+    HeapFree(GetProcessHeap(), 0, conv_dst);
 }
 
 static BOOL surface_check_block_align(struct wined3d_surface *surface, const RECT *rect)
@@ -2196,7 +2249,7 @@ HRESULT surface_upload_from_surface(struct wined3d_surface *dst_surface, const P
     }
 
     /* Use wined3d_surface_blt() instead of uploading directly if we need conversion. */
-    d3dfmt_get_conv(dst_surface, FALSE, TRUE, &format, &convert);
+    d3dfmt_get_conv(dst_surface, dst_surface->resource.format, FALSE, TRUE, &format, &convert);
     if (convert != WINED3D_CT_NONE || format.convert)
         return wined3d_surface_blt(dst_surface, &dst_rect, src_surface, src_rect, 0, NULL, WINED3D_TEXF_POINT);
 
@@ -3875,7 +3928,7 @@ static void surface_prepare_texture_internal(struct wined3d_surface *surface,
 
     if (surface->flags & alloc_flag) return;
 
-    d3dfmt_get_conv(surface, TRUE, TRUE, &format, &convert);
+    d3dfmt_get_conv(surface, surface->resource.format, TRUE, TRUE, &format, &convert);
     if (convert != WINED3D_CT_NONE || format.convert)
         surface->flags |= SFLAG_CONVERTED;
     else surface->flags &= ~SFLAG_CONVERTED;
@@ -5072,13 +5125,10 @@ static HRESULT surface_load_texture(struct wined3d_surface *surface,
 {
     RECT src_rect = {0, 0, surface->resource.width, surface->resource.height};
     struct wined3d_device *device = surface->resource.device;
-    enum wined3d_conversion_type convert;
     struct wined3d_context *context;
-    UINT width, src_pitch, dst_pitch;
+    UINT src_pitch;
     struct wined3d_bo_address data;
-    struct wined3d_format format;
     POINT dst_point = {0, 0};
-    BYTE *mem;
 
     if (wined3d_settings.offscreen_rendering_mode != ORM_FBO
             && surface_is_offscreen(surface)
@@ -5122,10 +5172,6 @@ static HRESULT surface_load_texture(struct wined3d_surface *surface,
     }
 
     /* Upload from system memory */
-
-    d3dfmt_get_conv(surface, TRUE /* We need color keying */,
-            TRUE /* We will use textures */, &format, &convert);
-
     if (srgb)
     {
         if ((surface->flags & (SFLAG_INTEXTURE | SFLAG_INSYSMEM)) == SFLAG_INTEXTURE)
@@ -5165,73 +5211,23 @@ static HRESULT surface_load_texture(struct wined3d_surface *surface,
     }
     else surface->flags &= ~SFLAG_GLCKEY;
 
-    width = surface->resource.width;
     src_pitch = wined3d_surface_get_pitch(surface);
 
     /* Don't use PBOs for converted surfaces. During PBO conversion we look at
      * SFLAG_CONVERTED but it isn't set (yet) in all cases it is getting
      * called. */
-    if ((convert != WINED3D_CT_NONE || format.convert) && (surface->flags & SFLAG_PBO))
+    if ((surface->flags & SFLAG_GLCKEY || surface->resource.format->convert) && (surface->flags & SFLAG_PBO))
     {
         TRACE("Removing the pbo attached to surface %p.\n", surface);
         surface_remove_pbo(surface, gl_info);
     }
 
-    if (format.convert)
-    {
-        /* This code is entered for texture formats which need a fixup. */
-        UINT height = surface->resource.height;
-
-        /* Stick to the alignment for the converted surface too, makes it easier to load the surface */
-        dst_pitch = width * format.conv_byte_count;
-        dst_pitch = (dst_pitch + device->surface_alignment - 1) & ~(device->surface_alignment - 1);
-
-        if (!(mem = HeapAlloc(GetProcessHeap(), 0, dst_pitch * height)))
-        {
-            ERR("Out of memory (%u).\n", dst_pitch * height);
-            context_release(context);
-            return E_OUTOFMEMORY;
-        }
-        format.convert(surface->resource.allocatedMemory, mem, src_pitch, src_pitch * height,
-                dst_pitch, dst_pitch * height, width, height, 1);
-        format.byte_count = format.conv_byte_count;
-        src_pitch = dst_pitch;
-    }
-    else if (convert != WINED3D_CT_NONE && surface->resource.allocatedMemory)
-    {
-        /* This code is only entered for color keying fixups */
-        UINT height = surface->resource.height;
-
-        /* Stick to the alignment for the converted surface too, makes it easier to load the surface */
-        dst_pitch = width * format.conv_byte_count;
-        dst_pitch = (dst_pitch + device->surface_alignment - 1) & ~(device->surface_alignment - 1);
-
-        if (!(mem = HeapAlloc(GetProcessHeap(), 0, dst_pitch * height)))
-        {
-            ERR("Out of memory (%u).\n", dst_pitch * height);
-            context_release(context);
-            return E_OUTOFMEMORY;
-        }
-        d3dfmt_convert_surface(surface->resource.allocatedMemory, mem, src_pitch,
-                width, height, dst_pitch, convert, surface);
-        format.byte_count = format.conv_byte_count;
-        src_pitch = dst_pitch;
-    }
-    else
-    {
-        mem = surface->resource.allocatedMemory;
-    }
-
     data.buffer_object = surface->pbo;
-    data.addr = mem;
-    surface_upload_data(surface, gl_info, &format, &src_rect, src_pitch, &dst_point, srgb, &data);
+    data.addr = surface->resource.allocatedMemory;
+    surface_upload_data(surface, gl_info, surface->resource.format, &src_rect, src_pitch, &dst_point, srgb, &data);
 
     context_release(context);
 
-    /* Don't delete PBO memory. */
-    if ((mem != surface->resource.allocatedMemory) && !(surface->flags & SFLAG_PBO))
-        HeapFree(GetProcessHeap(), 0, mem);
-
     return WINED3D_OK;
 }
 
-- 
1.8.3.2




More information about the wine-patches mailing list