[PATCH 2/7] wined3d: Track the map binding per-texture.

Henri Verbeet hverbeet at codeweavers.com
Mon Apr 18 12:06:27 CDT 2016


Signed-off-by: Henri Verbeet <hverbeet at codeweavers.com>
---
 dlls/wined3d/surface.c         | 54 +++++++++++++-----------
 dlls/wined3d/texture.c         | 95 +++++++++++++++++++++++++++++-------------
 dlls/wined3d/volume.c          |  9 ++--
 dlls/wined3d/wined3d_private.h |  6 +--
 4 files changed, 102 insertions(+), 62 deletions(-)

diff --git a/dlls/wined3d/surface.c b/dlls/wined3d/surface.c
index 4fad61f..9e8fddb 100644
--- a/dlls/wined3d/surface.c
+++ b/dlls/wined3d/surface.c
@@ -363,7 +363,7 @@ void wined3d_surface_destroy_dc(struct wined3d_surface *surface)
         gl_info = context->gl_info;
     }
 
-    wined3d_texture_get_memory(texture, sub_resource_idx, &data, surface->resource.map_binding);
+    wined3d_texture_get_memory(texture, sub_resource_idx, &data, texture->resource.map_binding);
     wined3d_texture_unmap_bo_address(&data, gl_info, GL_PIXEL_UNPACK_BUFFER);
 
     if (context)
@@ -399,7 +399,7 @@ HRESULT wined3d_surface_create_dc(struct wined3d_surface *surface)
         gl_info = context->gl_info;
     }
 
-    wined3d_texture_get_memory(texture, sub_resource_idx, &data, surface->resource.map_binding);
+    wined3d_texture_get_memory(texture, sub_resource_idx, &data, texture->resource.map_binding);
     desc.pMemory = wined3d_texture_map_bo_address(&data, surface->resource.size,
             gl_info, GL_PIXEL_UNPACK_BUFFER, 0);
 
@@ -867,8 +867,8 @@ static void surface_unload(struct wined3d_resource *resource)
     }
     else
     {
-        surface_load_location(surface, context, surface->resource.map_binding);
-        wined3d_texture_invalidate_location(texture, sub_resource_idx, ~surface->resource.map_binding);
+        surface_load_location(surface, context, texture->resource.map_binding);
+        wined3d_texture_invalidate_location(texture, sub_resource_idx, ~texture->resource.map_binding);
     }
 
     /* Destroy fbo render buffers. This is needed for implicit render targets, for
@@ -2936,9 +2936,9 @@ static HRESULT surface_load_texture(struct wined3d_surface *surface,
     const struct wined3d_color_key_conversion *conversion;
     struct wined3d_texture_sub_resource *sub_resource;
     struct wined3d_bo_address data;
+    BYTE *src_mem, *dst_mem = NULL;
     struct wined3d_format format;
     POINT dst_point = {0, 0};
-    BYTE *mem = NULL;
     RECT src_rect;
 
     sub_resource = surface_get_sub_resource(surface);
@@ -2991,22 +2991,22 @@ static HRESULT surface_load_texture(struct wined3d_surface *surface,
 
     if (srgb)
     {
-        if ((sub_resource->locations & (WINED3D_LOCATION_TEXTURE_RGB | surface->resource.map_binding))
+        if ((sub_resource->locations & (WINED3D_LOCATION_TEXTURE_RGB | texture->resource.map_binding))
                 == WINED3D_LOCATION_TEXTURE_RGB)
         {
             /* Performance warning... */
             FIXME("Downloading RGB surface %p to reload it as sRGB.\n", surface);
-            surface_load_location(surface, context, surface->resource.map_binding);
+            surface_load_location(surface, context, texture->resource.map_binding);
         }
     }
     else
     {
-        if ((sub_resource->locations & (WINED3D_LOCATION_TEXTURE_SRGB | surface->resource.map_binding))
+        if ((sub_resource->locations & (WINED3D_LOCATION_TEXTURE_SRGB | texture->resource.map_binding))
                 == WINED3D_LOCATION_TEXTURE_SRGB)
         {
             /* Performance warning... */
             FIXME("Downloading sRGB surface %p to reload it as RGB.\n", surface);
-            surface_load_location(surface, context, surface->resource.map_binding);
+            surface_load_location(surface, context, texture->resource.map_binding);
         }
     }
 
@@ -3032,9 +3032,8 @@ static HRESULT surface_load_texture(struct wined3d_surface *surface,
     {
         TRACE("Removing the pbo attached to surface %p.\n", surface);
 
-        surface->resource.map_binding = WINED3D_LOCATION_SYSMEM;
-        surface_load_location(surface, context, surface->resource.map_binding);
-        wined3d_texture_remove_buffer_object(texture, sub_resource_idx, gl_info);
+        surface_load_location(surface, context, WINED3D_LOCATION_SYSMEM);
+        wined3d_texture_set_map_binding(texture, WINED3D_LOCATION_SYSMEM);
     }
 
     wined3d_texture_get_memory(texture, sub_resource_idx, &data, sub_resource->locations);
@@ -3044,16 +3043,21 @@ static HRESULT surface_load_texture(struct wined3d_surface *surface,
         format.byte_count = format.conv_byte_count;
         wined3d_format_calculate_pitch(&format, 1, width, height, &dst_row_pitch, &dst_slice_pitch);
 
-        if (!(mem = HeapAlloc(GetProcessHeap(), 0, dst_slice_pitch)))
+        src_mem = wined3d_texture_map_bo_address(&data, src_slice_pitch,
+                gl_info, GL_PIXEL_UNPACK_BUFFER, WINED3D_MAP_READONLY);
+        if (!(dst_mem = HeapAlloc(GetProcessHeap(), 0, dst_slice_pitch)))
         {
             ERR("Out of memory (%u).\n", dst_slice_pitch);
             context_release(context);
             return E_OUTOFMEMORY;
         }
-        format.convert(data.addr, mem, src_row_pitch, src_slice_pitch,
+        format.convert(src_mem, dst_mem, src_row_pitch, src_slice_pitch,
                 dst_row_pitch, dst_slice_pitch, width, height, 1);
         src_row_pitch = dst_row_pitch;
-        data.addr = mem;
+        wined3d_texture_unmap_bo_address(&data, gl_info, GL_PIXEL_UNPACK_BUFFER);
+
+        data.buffer_object = 0;
+        data.addr = dst_mem;
     }
     else if (conversion)
     {
@@ -3063,7 +3067,9 @@ static HRESULT surface_load_texture(struct wined3d_surface *surface,
         wined3d_format_calculate_pitch(&format, device->surface_alignment,
                 width, height, &dst_row_pitch, &dst_slice_pitch);
 
-        if (!(mem = HeapAlloc(GetProcessHeap(), 0, dst_slice_pitch)))
+        src_mem = wined3d_texture_map_bo_address(&data, src_slice_pitch,
+                gl_info, GL_PIXEL_UNPACK_BUFFER, WINED3D_MAP_READONLY);
+        if (!(dst_mem = HeapAlloc(GetProcessHeap(), 0, dst_slice_pitch)))
         {
             ERR("Out of memory (%u).\n", dst_slice_pitch);
             context_release(context);
@@ -3071,16 +3077,19 @@ static HRESULT surface_load_texture(struct wined3d_surface *surface,
         }
         if (texture->swapchain && texture->swapchain->palette)
             palette = texture->swapchain->palette;
-        conversion->convert(data.addr, src_row_pitch, mem, dst_row_pitch,
+        conversion->convert(src_mem, src_row_pitch, dst_mem, dst_row_pitch,
                 width, height, palette, &texture->async.gl_color_key);
         src_row_pitch = dst_row_pitch;
-        data.addr = mem;
+        wined3d_texture_unmap_bo_address(&data, gl_info, GL_PIXEL_UNPACK_BUFFER);
+
+        data.buffer_object = 0;
+        data.addr = dst_mem;
     }
 
     wined3d_surface_upload_data(surface, gl_info, &format, &src_rect,
             src_row_pitch, &dst_point, srgb, wined3d_const_bo_address(&data));
 
-    HeapFree(GetProcessHeap(), 0, mem);
+    HeapFree(GetProcessHeap(), 0, dst_mem);
 
     return WINED3D_OK;
 }
@@ -4249,8 +4258,8 @@ HRESULT wined3d_surface_blt(struct wined3d_surface *dst_surface, const RECT *dst
 
         /* In principle this would apply to depth blits as well, but we don't
          * implement those in the CPU blitter at the moment. */
-        if ((dst_sub_resource->locations & dst_surface->resource.map_binding)
-                && (!src_texture || (src_sub_resource->locations & src_surface->resource.map_binding)))
+        if ((dst_sub_resource->locations & dst_texture->resource.map_binding)
+                && (!src_texture || (src_sub_resource->locations & src_texture->resource.map_binding)))
         {
             if (scale)
                 TRACE("Not doing sysmem blit because of scaling.\n");
@@ -4422,9 +4431,6 @@ HRESULT wined3d_surface_init(struct wined3d_surface *surface, struct wined3d_tex
     if (container->resource.usage & WINED3DUSAGE_DEPTHSTENCIL)
         container->sub_resources[sub_resource_idx].locations = WINED3D_LOCATION_DISCARDED;
 
-    if (wined3d_texture_use_pbo(container, gl_info))
-        surface->resource.map_binding = WINED3D_LOCATION_BUFFER;
-
     return hr;
 }
 
diff --git a/dlls/wined3d/texture.c b/dlls/wined3d/texture.c
index 38f8c53..f89b5c9 100644
--- a/dlls/wined3d/texture.c
+++ b/dlls/wined3d/texture.c
@@ -28,7 +28,7 @@ WINE_DEFAULT_DEBUG_CHANNEL(d3d);
 WINE_DECLARE_DEBUG_CHANNEL(d3d_perf);
 WINE_DECLARE_DEBUG_CHANNEL(winediag);
 
-BOOL wined3d_texture_use_pbo(const struct wined3d_texture *texture, const struct wined3d_gl_info *gl_info)
+static BOOL wined3d_texture_use_pbo(const struct wined3d_texture *texture, const struct wined3d_gl_info *gl_info)
 {
     return texture->resource.pool == WINED3D_POOL_DEFAULT
             && texture->resource.access_flags & WINED3D_RESOURCE_ACCESS_CPU
@@ -230,7 +230,7 @@ static HRESULT wined3d_texture_init(struct wined3d_texture *texture, const struc
 }
 
 /* Context activation is done by the caller. */
-void wined3d_texture_remove_buffer_object(struct wined3d_texture *texture,
+static void wined3d_texture_remove_buffer_object(struct wined3d_texture *texture,
         unsigned int sub_resource_idx, const struct wined3d_gl_info *gl_info)
 {
     GLuint *buffer_object;
@@ -245,6 +245,40 @@ void wined3d_texture_remove_buffer_object(struct wined3d_texture *texture,
             *buffer_object, texture, sub_resource_idx);
 }
 
+static void wined3d_texture_update_map_binding(struct wined3d_texture *texture)
+{
+    unsigned int sub_count = texture->level_count * texture->layer_count;
+    const struct wined3d_device *device = texture->resource.device;
+    DWORD map_binding = texture->update_map_binding;
+    struct wined3d_context *context = NULL;
+    unsigned int i;
+
+    if (device->d3d_initialized)
+        context = context_acquire(device, NULL);
+
+    for (i = 0; i < sub_count; ++i)
+    {
+        if (texture->sub_resources[i].locations == texture->resource.map_binding
+                && !texture->texture_ops->texture_load_location(texture, i, context, map_binding))
+            ERR("Failed to load location %s.\n", wined3d_debug_location(map_binding));
+        if (texture->resource.map_binding == WINED3D_LOCATION_BUFFER)
+            wined3d_texture_remove_buffer_object(texture, i, context->gl_info);
+    }
+
+    if (context)
+        context_release(context);
+
+    texture->resource.map_binding = map_binding;
+    texture->update_map_binding = 0;
+}
+
+void wined3d_texture_set_map_binding(struct wined3d_texture *texture, DWORD map_binding)
+{
+    texture->update_map_binding = map_binding;
+    if (!texture->resource.map_count)
+        wined3d_texture_update_map_binding(texture);
+}
+
 /* A GL context is provided by the caller */
 static void gltexture_delete(struct wined3d_device *device, const struct wined3d_gl_info *gl_info,
         struct gl_texture *tex)
@@ -692,12 +726,10 @@ void wined3d_texture_load(struct wined3d_texture *texture,
         TRACE("Reloading because of color key value change.\n");
         for (i = 0; i < sub_count; i++)
         {
-            struct wined3d_resource *sub_resource = texture->sub_resources[i].resource;
-
-            if (!texture->texture_ops->texture_load_location(texture, i, context, sub_resource->map_binding))
-                ERR("Failed to load location %s.\n", wined3d_debug_location(sub_resource->map_binding));
+            if (!texture->texture_ops->texture_load_location(texture, i, context, texture->resource.map_binding))
+                ERR("Failed to load location %s.\n", wined3d_debug_location(texture->resource.map_binding));
             else
-                wined3d_texture_invalidate_location(texture, i, ~sub_resource->map_binding);
+                wined3d_texture_invalidate_location(texture, i, ~texture->resource.map_binding);
         }
 
         texture->async.gl_color_key = texture->async.src_blt_color_key;
@@ -962,7 +994,7 @@ HRESULT CDECL wined3d_texture_update_desc(struct wined3d_texture *texture, UINT
 
     if ((texture->user_memory = mem))
     {
-        sub_resource->resource->map_binding = WINED3D_LOCATION_USER_MEMORY;
+        texture->resource.map_binding = WINED3D_LOCATION_USER_MEMORY;
         valid_location = WINED3D_LOCATION_USER_MEMORY;
     }
     else
@@ -975,8 +1007,8 @@ HRESULT CDECL wined3d_texture_update_desc(struct wined3d_texture *texture, UINT
      * If the surface didn't use PBOs previously but could now, don't
      * change it - whatever made us not use PBOs might come back, e.g.
      * color keys. */
-    if (sub_resource->resource->map_binding == WINED3D_LOCATION_BUFFER && !wined3d_texture_use_pbo(texture, gl_info))
-        sub_resource->resource->map_binding = WINED3D_LOCATION_SYSMEM;
+    if (texture->resource.map_binding == WINED3D_LOCATION_BUFFER && !wined3d_texture_use_pbo(texture, gl_info))
+        texture->resource.map_binding = WINED3D_LOCATION_SYSMEM;
 
     wined3d_texture_validate_location(texture, 0, valid_location);
 
@@ -1131,31 +1163,30 @@ struct wined3d_texture_sub_resource *wined3d_texture_get_sub_resource(struct win
 HRESULT CDECL wined3d_texture_add_dirty_region(struct wined3d_texture *texture,
         UINT layer, const struct wined3d_box *dirty_region)
 {
-    struct wined3d_texture_sub_resource *sub_resource;
     struct wined3d_context *context;
     unsigned int sub_resource_idx;
 
     TRACE("texture %p, layer %u, dirty_region %s.\n", texture, layer, debug_box(dirty_region));
 
-    sub_resource_idx = layer * texture->level_count;
-    if (!(sub_resource = wined3d_texture_get_sub_resource(texture, sub_resource_idx)))
+    if (layer >= texture->layer_count)
     {
-        WARN("Failed to get sub-resource.\n");
+        WARN("Invalid layer %u specified.\n", layer);
         return WINED3DERR_INVALIDCALL;
     }
+    sub_resource_idx = layer * texture->level_count;
 
     if (dirty_region)
         FIXME("Ignoring dirty_region %s.\n", debug_box(dirty_region));
 
     context = context_acquire(texture->resource.device, NULL);
     if (!texture->texture_ops->texture_load_location(texture, sub_resource_idx,
-            context, sub_resource->resource->map_binding))
+            context, texture->resource.map_binding))
     {
-        ERR("Failed to load location %s.\n", wined3d_debug_location(sub_resource->resource->map_binding));
+        ERR("Failed to load location %s.\n", wined3d_debug_location(texture->resource.map_binding));
         context_release(context);
         return E_OUTOFMEMORY;
     }
-    wined3d_texture_invalidate_location(texture, sub_resource_idx, ~sub_resource->resource->map_binding);
+    wined3d_texture_invalidate_location(texture, sub_resource_idx, ~texture->resource.map_binding);
     context_release(context);
 
     return WINED3D_OK;
@@ -1421,17 +1452,17 @@ static HRESULT texture_resource_sub_resource_map(struct wined3d_resource *resour
     if (flags & WINED3D_MAP_DISCARD)
     {
         TRACE("WINED3D_MAP_DISCARD flag passed, marking %s as up to date.\n",
-                wined3d_debug_location(sub_resource->resource->map_binding));
+                wined3d_debug_location(texture->resource.map_binding));
         if ((ret = texture->texture_ops->texture_prepare_location(texture,
-                sub_resource_idx, context, sub_resource->resource->map_binding)))
-            wined3d_texture_validate_location(texture, sub_resource_idx, sub_resource->resource->map_binding);
+                sub_resource_idx, context, texture->resource.map_binding)))
+            wined3d_texture_validate_location(texture, sub_resource_idx, texture->resource.map_binding);
     }
     else
     {
         if (resource->usage & WINED3DUSAGE_DYNAMIC)
             WARN_(d3d_perf)("Mapping a dynamic texture without WINED3D_MAP_DISCARD.\n");
         ret = texture->texture_ops->texture_load_location(texture,
-                sub_resource_idx, context, sub_resource->resource->map_binding);
+                sub_resource_idx, context, texture->resource.map_binding);
     }
 
     if (!ret)
@@ -1442,9 +1473,9 @@ static HRESULT texture_resource_sub_resource_map(struct wined3d_resource *resour
     }
 
     if (!(flags & (WINED3D_MAP_NO_DIRTY_UPDATE | WINED3D_MAP_READONLY)))
-        wined3d_texture_invalidate_location(texture, sub_resource_idx, ~sub_resource->resource->map_binding);
+        wined3d_texture_invalidate_location(texture, sub_resource_idx, ~texture->resource.map_binding);
 
-    wined3d_texture_get_memory(texture, sub_resource_idx, &data, sub_resource->resource->map_binding);
+    wined3d_texture_get_memory(texture, sub_resource_idx, &data, texture->resource.map_binding);
     base_memory = wined3d_texture_map_bo_address(&data, sub_resource->resource->size,
             gl_info, GL_PIXEL_UNPACK_BUFFER, flags);
     TRACE("Base memory pointer %p.\n", base_memory);
@@ -1535,7 +1566,7 @@ static HRESULT texture_resource_sub_resource_unmap(struct wined3d_resource *reso
         gl_info = context->gl_info;
     }
 
-    wined3d_texture_get_memory(texture, sub_resource_idx, &data, sub_resource->resource->map_binding);
+    wined3d_texture_get_memory(texture, sub_resource_idx, &data, texture->resource.map_binding);
     wined3d_texture_unmap_bo_address(&data, gl_info, GL_PIXEL_UNPACK_BUFFER);
 
     if (context)
@@ -1552,7 +1583,8 @@ static HRESULT texture_resource_sub_resource_unmap(struct wined3d_resource *reso
     }
 
     --sub_resource->map_count;
-    --resource->map_count;
+    if (!--resource->map_count && texture->update_map_binding)
+        wined3d_texture_update_map_binding(texture);
 
     return WINED3D_OK;
 }
@@ -1713,6 +1745,9 @@ static HRESULT texture_init(struct wined3d_texture *texture, const struct wined3
     texture->pow2_matrix[15] = 1.0f;
     TRACE("x scale %.8e, y scale %.8e.\n", texture->pow2_matrix[0], texture->pow2_matrix[5]);
 
+    if (wined3d_texture_use_pbo(texture, gl_info))
+        texture->resource.map_binding = WINED3D_LOCATION_BUFFER;
+
     if (!(surfaces = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*surfaces) * level_count * layer_count)))
     {
         wined3d_texture_cleanup(texture);
@@ -1977,6 +2012,9 @@ static HRESULT volumetexture_init(struct wined3d_texture *texture, const struct
     texture->pow2_matrix[15] = 1.0f;
     texture->target = GL_TEXTURE_3D;
 
+    if (wined3d_texture_use_pbo(texture, gl_info))
+        texture->resource.map_binding = WINED3D_LOCATION_BUFFER;
+
     if (!(volumes = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*volumes) * levels)))
     {
         wined3d_texture_cleanup(texture);
@@ -2346,8 +2384,8 @@ HRESULT CDECL wined3d_texture_get_dc(struct wined3d_texture *texture, unsigned i
     if (device->d3d_initialized)
         context = context_acquire(device, NULL);
 
-    surface_load_location(surface, context, surface->resource.map_binding);
-    wined3d_texture_invalidate_location(texture, sub_resource_idx, ~surface->resource.map_binding);
+    surface_load_location(surface, context, texture->resource.map_binding);
+    wined3d_texture_invalidate_location(texture, sub_resource_idx, ~texture->resource.map_binding);
 
     if (!surface->dc)
         hr = wined3d_surface_create_dc(surface);
@@ -2399,7 +2437,8 @@ HRESULT CDECL wined3d_texture_release_dc(struct wined3d_texture *texture, unsign
         wined3d_surface_destroy_dc(surface);
 
     --sub_resource->map_count;
-    --texture->resource.map_count;
+    if (!--texture->resource.map_count && texture->update_map_binding)
+        wined3d_texture_update_map_binding(texture);
     if (!(texture->flags & WINED3D_TEXTURE_GET_DC_LENIENT))
         texture->flags &= ~WINED3D_TEXTURE_DC_IN_USE;
 
diff --git a/dlls/wined3d/volume.c b/dlls/wined3d/volume.c
index 643969c..262bbac 100644
--- a/dlls/wined3d/volume.c
+++ b/dlls/wined3d/volume.c
@@ -451,15 +451,12 @@ HRESULT wined3d_volume_init(struct wined3d_volume *volume, struct wined3d_textur
         return hr;
     }
 
+    if (container->resource.map_binding == WINED3D_LOCATION_BUFFER)
+        wined3d_resource_free_sysmem(&volume->resource);
+
     volume->texture_level = level;
     container->sub_resources[level].locations = WINED3D_LOCATION_DISCARDED;
 
-    if (wined3d_texture_use_pbo(container, gl_info))
-    {
-        wined3d_resource_free_sysmem(&volume->resource);
-        volume->resource.map_binding = WINED3D_LOCATION_BUFFER;
-    }
-
     volume->container = container;
 
     return WINED3D_OK;
diff --git a/dlls/wined3d/wined3d_private.h b/dlls/wined3d/wined3d_private.h
index 9da1811..d3e1fba 100644
--- a/dlls/wined3d/wined3d_private.h
+++ b/dlls/wined3d/wined3d_private.h
@@ -2469,6 +2469,7 @@ struct wined3d_texture
     DWORD sampler;
     DWORD flags;
     GLenum target;
+    DWORD update_map_binding;
 
     GLuint rb_multisample;
     GLuint rb_resolved;
@@ -2572,15 +2573,12 @@ void wined3d_texture_prepare_rb(struct wined3d_texture *texture,
         const struct wined3d_gl_info *gl_info, BOOL multisample) DECLSPEC_HIDDEN;
 void wined3d_texture_prepare_texture(struct wined3d_texture *texture,
         struct wined3d_context *context, BOOL srgb) DECLSPEC_HIDDEN;
-void wined3d_texture_remove_buffer_object(struct wined3d_texture *texture,
-        unsigned int sub_resource_idx, const struct wined3d_gl_info *gl_info) DECLSPEC_HIDDEN;
 void wined3d_texture_set_dirty(struct wined3d_texture *texture) DECLSPEC_HIDDEN;
+void wined3d_texture_set_map_binding(struct wined3d_texture *texture, DWORD map_binding) DECLSPEC_HIDDEN;
 void wined3d_texture_set_swapchain(struct wined3d_texture *texture,
         struct wined3d_swapchain *swapchain) DECLSPEC_HIDDEN;
 void wined3d_texture_unmap_bo_address(const struct wined3d_bo_address *data,
         const struct wined3d_gl_info *gl_info, GLenum binding) DECLSPEC_HIDDEN;
-BOOL wined3d_texture_use_pbo(const struct wined3d_texture *texture,
-        const struct wined3d_gl_info *gl_info) DECLSPEC_HIDDEN;
 void wined3d_texture_validate_location(struct wined3d_texture *texture,
         unsigned int sub_resource_idx, DWORD location) DECLSPEC_HIDDEN;
 
-- 
2.1.4




More information about the wine-patches mailing list