[PATCH 6/6] wined3d: Store sub-resource locations in the sub-resource structure.

Henri Verbeet hverbeet at codeweavers.com
Mon Mar 28 11:58:01 CDT 2016


From: Stefan Dösinger <stefan at codeweavers.com>

Signed-off-by: Henri Verbeet <hverbeet at codeweavers.com>
---
 dlls/wined3d/arb_program_shader.c |   3 +-
 dlls/wined3d/device.c             |   5 +-
 dlls/wined3d/drawprim.c           |   2 +-
 dlls/wined3d/surface.c            | 114 +++++++++++++++++++++-----------------
 dlls/wined3d/swapchain.c          |  14 +++--
 dlls/wined3d/texture.c            |  31 ++++++-----
 dlls/wined3d/volume.c             |  62 +++++++++++----------
 dlls/wined3d/wined3d_private.h    |  15 ++++-
 8 files changed, 138 insertions(+), 108 deletions(-)

diff --git a/dlls/wined3d/arb_program_shader.c b/dlls/wined3d/arb_program_shader.c
index 298107a..4583f1e 100644
--- a/dlls/wined3d/arb_program_shader.c
+++ b/dlls/wined3d/arb_program_shader.c
@@ -7884,7 +7884,8 @@ static void arbfp_blit_surface(struct wined3d_device *device, enum wined3d_blit_
 
     /* Now load the surface */
     if (wined3d_settings.offscreen_rendering_mode != ORM_FBO
-            && (src_surface->locations & (WINED3D_LOCATION_TEXTURE_RGB | WINED3D_LOCATION_DRAWABLE))
+            && (surface_get_sub_resource(src_surface)->locations
+            & (WINED3D_LOCATION_TEXTURE_RGB | WINED3D_LOCATION_DRAWABLE))
             == WINED3D_LOCATION_DRAWABLE
             && !wined3d_resource_is_offscreen(&src_texture->resource))
     {
diff --git a/dlls/wined3d/device.c b/dlls/wined3d/device.c
index f91e3f7..cd392b3 100644
--- a/dlls/wined3d/device.c
+++ b/dlls/wined3d/device.c
@@ -234,9 +234,10 @@ static BOOL is_full_clear(const struct wined3d_surface *target, const RECT *draw
 static void prepare_ds_clear(struct wined3d_surface *ds, struct wined3d_context *context,
         DWORD location, const RECT *draw_rect, UINT rect_count, const RECT *clear_rect, RECT *out_rect)
 {
+    struct wined3d_texture_sub_resource *sub_resource = surface_get_sub_resource(ds);
     RECT current_rect, r;
 
-    if (ds->locations & WINED3D_LOCATION_DISCARDED)
+    if (sub_resource->locations & WINED3D_LOCATION_DISCARDED)
     {
         /* Depth buffer was discarded, make it entirely current in its new location since
          * there is no other place where we would get data anyway. */
@@ -244,7 +245,7 @@ static void prepare_ds_clear(struct wined3d_surface *ds, struct wined3d_context
         return;
     }
 
-    if (ds->locations & location)
+    if (sub_resource->locations & location)
         SetRect(&current_rect, 0, 0,
                 ds->ds_current_size.cx,
                 ds->ds_current_size.cy);
diff --git a/dlls/wined3d/drawprim.c b/dlls/wined3d/drawprim.c
index 4771898..677b4e3 100644
--- a/dlls/wined3d/drawprim.c
+++ b/dlls/wined3d/drawprim.c
@@ -652,7 +652,7 @@ void draw_primitive(struct wined3d_device *device, UINT start_idx, UINT index_co
             if (!context->render_offscreen && ds != device->onscreen_depth_stencil)
                 device_switch_onscreen_ds(device, context, ds);
 
-            if (ds->locations & location)
+            if (surface_get_sub_resource(ds)->locations & location)
                 SetRect(&current_rect, 0, 0, ds->ds_current_size.cx, ds->ds_current_size.cy);
             else
                 SetRectEmpty(&current_rect);
diff --git a/dlls/wined3d/surface.c b/dlls/wined3d/surface.c
index 1f83a22..114b368 100644
--- a/dlls/wined3d/surface.c
+++ b/dlls/wined3d/surface.c
@@ -40,11 +40,6 @@ static const DWORD surface_simple_locations =
         WINED3D_LOCATION_SYSMEM | WINED3D_LOCATION_USER_MEMORY
         | WINED3D_LOCATION_DIB | WINED3D_LOCATION_BUFFER;
 
-static unsigned int surface_get_sub_resource_idx(const struct wined3d_surface *surface)
-{
-    return surface->texture_layer * surface->container->level_count + surface->texture_level;
-}
-
 void wined3d_surface_cleanup(struct wined3d_surface *surface)
 {
     struct wined3d_surface *overlay, *cur;
@@ -502,7 +497,7 @@ static void surface_prepare_system_memory(struct wined3d_surface *surface)
     if (!wined3d_resource_allocate_sysmem(&surface->resource))
         ERR("Failed to allocate system memory.\n");
 
-    if (surface->locations & WINED3D_LOCATION_SYSMEM)
+    if (surface_get_sub_resource(surface)->locations & WINED3D_LOCATION_SYSMEM)
         ERR("Surface without system memory has WINED3D_LOCATION_SYSMEM set.\n");
 }
 
@@ -1363,7 +1358,7 @@ HRESULT surface_upload_from_surface(struct wined3d_surface *dst_surface, const P
         surface_load_location(dst_surface, context, WINED3D_LOCATION_TEXTURE_RGB);
     wined3d_texture_bind_and_dirtify(dst_texture, context, FALSE);
 
-    surface_get_memory(src_surface, &data, src_surface->locations);
+    surface_get_memory(src_surface, &data, surface_get_sub_resource(src_surface)->locations);
     wined3d_texture_get_pitch(src_texture, src_surface->texture_level, &src_row_pitch, &src_slice_pitch);
 
     wined3d_surface_upload_data(dst_surface, gl_info, src_format, src_rect,
@@ -1454,7 +1449,7 @@ void surface_load(struct wined3d_surface *surface, struct wined3d_context *conte
     if (surface->container->resource.pool == WINED3D_POOL_SCRATCH)
         ERR("Not supported on scratch surfaces.\n");
 
-    if (surface->locations & location)
+    if (surface_get_sub_resource(surface)->locations & location)
     {
         TRACE("surface is already in texture\n");
         return;
@@ -2238,7 +2233,7 @@ static void fb_copy_to_texture_hwstretch(struct wined3d_surface *dst_surface, st
         checkGLcall("glEnable(texture_target)");
 
         /* For now invalidate the texture copy of the back buffer. Drawable and sysmem copy are untouched */
-        src_surface->locations &= ~WINED3D_LOCATION_TEXTURE_RGB;
+        surface_get_sub_resource(src_surface)->locations &= ~WINED3D_LOCATION_TEXTURE_RGB;
     }
 
     /* Make sure that the top pixel is always above the bottom pixel, and keep a separate upside down flag
@@ -2784,15 +2779,19 @@ static void surface_depth_blt(const struct wined3d_surface *surface, struct wine
 void surface_modify_ds_location(struct wined3d_surface *surface,
         DWORD location, UINT w, UINT h)
 {
+    struct wined3d_texture_sub_resource *sub_resource;
+
     TRACE("surface %p, new location %#x, w %u, h %u.\n", surface, location, w, h);
 
-    if (((surface->locations & WINED3D_LOCATION_TEXTURE_RGB) && !(location & WINED3D_LOCATION_TEXTURE_RGB))
-            || (!(surface->locations & WINED3D_LOCATION_TEXTURE_RGB) && (location & WINED3D_LOCATION_TEXTURE_RGB)))
+    sub_resource = surface_get_sub_resource(surface);
+    if (((sub_resource->locations & WINED3D_LOCATION_TEXTURE_RGB) && !(location & WINED3D_LOCATION_TEXTURE_RGB))
+            || (!(sub_resource->locations & WINED3D_LOCATION_TEXTURE_RGB)
+            && (location & WINED3D_LOCATION_TEXTURE_RGB)))
         wined3d_texture_set_dirty(surface->container);
 
     surface->ds_current_size.cx = w;
     surface->ds_current_size.cy = h;
-    surface->locations = location;
+    sub_resource->locations = location;
 }
 
 /* Context activation is done by the caller. */
@@ -2808,7 +2807,7 @@ static void surface_load_ds_location(struct wined3d_surface *surface, struct win
     /* TODO: Make this work for modes other than FBO */
     if (wined3d_settings.offscreen_rendering_mode != ORM_FBO) return;
 
-    if (!(surface->locations & location))
+    if (!(surface_get_sub_resource(surface)->locations & location))
     {
         w = surface->ds_current_size.cx;
         h = surface->ds_current_size.cy;
@@ -2916,18 +2915,21 @@ void surface_validate_location(struct wined3d_surface *surface, DWORD location)
 {
     TRACE("surface %p, location %s.\n", surface, wined3d_debug_location(location));
 
-    surface->locations |= location;
+    surface_get_sub_resource(surface)->locations |= location;
 }
 
 void surface_invalidate_location(struct wined3d_surface *surface, DWORD location)
 {
+    struct wined3d_texture_sub_resource *sub_resource;
+
     TRACE("surface %p, location %s.\n", surface, wined3d_debug_location(location));
 
+    sub_resource = surface_get_sub_resource(surface);
     if (location & (WINED3D_LOCATION_TEXTURE_RGB | WINED3D_LOCATION_TEXTURE_SRGB))
         wined3d_texture_set_dirty(surface->container);
-    surface->locations &= ~location;
+    sub_resource->locations &= ~location;
 
-    if (!surface->locations)
+    if (!sub_resource->locations)
         ERR("Surface %p does not have any up to date location.\n", surface);
 }
 
@@ -2963,7 +2965,7 @@ static void surface_copy_simple_location(struct wined3d_surface *surface, DWORD
     UINT size = surface->resource.size;
 
     surface_get_memory(surface, &dst, location);
-    surface_get_memory(surface, &src, surface->locations);
+    surface_get_memory(surface, &src, surface_get_sub_resource(surface)->locations);
 
     if (dst.buffer_object)
     {
@@ -2995,39 +2997,41 @@ static void surface_load_sysmem(struct wined3d_surface *surface,
         struct wined3d_context *context, DWORD dst_location)
 {
     const struct wined3d_gl_info *gl_info = context->gl_info;
+    struct wined3d_texture_sub_resource *sub_resource;
 
     wined3d_surface_prepare(surface, context, dst_location);
 
-    if (surface->locations & surface_simple_locations)
+    sub_resource = surface_get_sub_resource(surface);
+    if (sub_resource->locations & surface_simple_locations)
     {
         surface_copy_simple_location(surface, dst_location);
         return;
     }
 
-    if (surface->locations & (WINED3D_LOCATION_RB_MULTISAMPLE | WINED3D_LOCATION_RB_RESOLVED))
+    if (sub_resource->locations & (WINED3D_LOCATION_RB_MULTISAMPLE | WINED3D_LOCATION_RB_RESOLVED))
         surface_load_location(surface, context, WINED3D_LOCATION_TEXTURE_RGB);
 
     /* Download the surface to system memory. */
-    if (surface->locations & (WINED3D_LOCATION_TEXTURE_RGB | WINED3D_LOCATION_TEXTURE_SRGB))
+    if (sub_resource->locations & (WINED3D_LOCATION_TEXTURE_RGB | WINED3D_LOCATION_TEXTURE_SRGB))
     {
         struct wined3d_texture *texture = surface->container;
 
         wined3d_texture_bind_and_dirtify(texture, context,
-                !(surface->locations & WINED3D_LOCATION_TEXTURE_RGB));
+                !(sub_resource->locations & WINED3D_LOCATION_TEXTURE_RGB));
         surface_download_data(surface, gl_info, dst_location);
         ++texture->download_count;
 
         return;
     }
 
-    if (surface->locations & WINED3D_LOCATION_DRAWABLE)
+    if (sub_resource->locations & WINED3D_LOCATION_DRAWABLE)
     {
         read_from_framebuffer(surface, context, dst_location);
         return;
     }
 
     FIXME("Can't load surface %p with location flags %s into sysmem.\n",
-            surface, wined3d_debug_location(surface->locations));
+            surface, wined3d_debug_location(sub_resource->locations));
 }
 
 /* Context activation is done by the caller. */
@@ -3061,21 +3065,23 @@ static HRESULT surface_load_texture(struct wined3d_surface *surface,
     struct wined3d_texture *texture = surface->container;
     struct wined3d_device *device = texture->resource.device;
     const struct wined3d_color_key_conversion *conversion;
+    struct wined3d_texture_sub_resource *sub_resource;
     struct wined3d_bo_address data;
     struct wined3d_format format;
     POINT dst_point = {0, 0};
     BYTE *mem = NULL;
 
+    sub_resource = surface_get_sub_resource(surface);
     if (wined3d_settings.offscreen_rendering_mode != ORM_FBO
             && wined3d_resource_is_offscreen(&texture->resource)
-            && (surface->locations & WINED3D_LOCATION_DRAWABLE))
+            && (sub_resource->locations & WINED3D_LOCATION_DRAWABLE))
     {
         surface_load_fb_texture(surface, srgb, context);
 
         return WINED3D_OK;
     }
 
-    if (surface->locations & (WINED3D_LOCATION_TEXTURE_SRGB | WINED3D_LOCATION_TEXTURE_RGB)
+    if (sub_resource->locations & (WINED3D_LOCATION_TEXTURE_SRGB | WINED3D_LOCATION_TEXTURE_RGB)
             && (texture->resource.format_flags & WINED3DFMT_FLAG_FBO_ATTACHABLE_SRGB)
             && fbo_blit_supported(gl_info, WINED3D_BLIT_OP_COLOR_BLIT,
                 NULL, texture->resource.usage, texture->resource.pool, texture->resource.format,
@@ -3091,13 +3097,13 @@ static HRESULT surface_load_texture(struct wined3d_surface *surface,
         return WINED3D_OK;
     }
 
-    if (surface->locations & (WINED3D_LOCATION_RB_MULTISAMPLE | WINED3D_LOCATION_RB_RESOLVED)
+    if (sub_resource->locations & (WINED3D_LOCATION_RB_MULTISAMPLE | WINED3D_LOCATION_RB_RESOLVED)
             && (!srgb || (texture->resource.format_flags & WINED3DFMT_FLAG_FBO_ATTACHABLE_SRGB))
             && fbo_blit_supported(gl_info, WINED3D_BLIT_OP_COLOR_BLIT,
                 NULL, texture->resource.usage, texture->resource.pool, texture->resource.format,
                 NULL, texture->resource.usage, texture->resource.pool, texture->resource.format))
     {
-        DWORD src_location = surface->locations & WINED3D_LOCATION_RB_RESOLVED ?
+        DWORD src_location = sub_resource->locations & WINED3D_LOCATION_RB_RESOLVED ?
                 WINED3D_LOCATION_RB_RESOLVED : WINED3D_LOCATION_RB_MULTISAMPLE;
         DWORD dst_location = srgb ? WINED3D_LOCATION_TEXTURE_SRGB : WINED3D_LOCATION_TEXTURE_RGB;
         RECT rect = {0, 0, surface->resource.width, surface->resource.height};
@@ -3112,7 +3118,7 @@ static HRESULT surface_load_texture(struct wined3d_surface *surface,
 
     if (srgb)
     {
-        if ((surface->locations & (WINED3D_LOCATION_TEXTURE_RGB | surface->resource.map_binding))
+        if ((sub_resource->locations & (WINED3D_LOCATION_TEXTURE_RGB | surface->resource.map_binding))
                 == WINED3D_LOCATION_TEXTURE_RGB)
         {
             /* Performance warning... */
@@ -3122,7 +3128,7 @@ static HRESULT surface_load_texture(struct wined3d_surface *surface,
     }
     else
     {
-        if ((surface->locations & (WINED3D_LOCATION_TEXTURE_SRGB | surface->resource.map_binding))
+        if ((sub_resource->locations & (WINED3D_LOCATION_TEXTURE_SRGB | surface->resource.map_binding))
                 == WINED3D_LOCATION_TEXTURE_SRGB)
         {
             /* Performance warning... */
@@ -3131,7 +3137,7 @@ static HRESULT surface_load_texture(struct wined3d_surface *surface,
         }
     }
 
-    if (!(surface->locations & surface_simple_locations))
+    if (!(sub_resource->locations & surface_simple_locations))
     {
         WARN("Trying to load a texture from sysmem, but no simple location is valid.\n");
         /* Lets hope we get it from somewhere... */
@@ -3165,7 +3171,7 @@ static HRESULT surface_load_texture(struct wined3d_surface *surface,
         wined3d_texture_remove_buffer_object(texture, surface_get_sub_resource_idx(surface), gl_info);
     }
 
-    surface_get_memory(surface, &data, surface->locations);
+    surface_get_memory(surface, &data, sub_resource->locations);
     if (format.convert)
     {
         /* This code is entered for texture formats which need a fixup. */
@@ -3221,13 +3227,14 @@ static void surface_load_renderbuffer(struct wined3d_surface *surface, struct wi
         DWORD dst_location)
 {
     const RECT rect = {0, 0, surface->resource.width, surface->resource.height};
+    DWORD locations = surface_get_sub_resource(surface)->locations;
     DWORD src_location;
 
-    if (surface->locations & WINED3D_LOCATION_RB_MULTISAMPLE)
+    if (locations & WINED3D_LOCATION_RB_MULTISAMPLE)
         src_location = WINED3D_LOCATION_RB_MULTISAMPLE;
-    else if (surface->locations & WINED3D_LOCATION_RB_RESOLVED)
+    else if (locations & WINED3D_LOCATION_RB_RESOLVED)
         src_location = WINED3D_LOCATION_RB_RESOLVED;
-    else if (surface->locations & WINED3D_LOCATION_TEXTURE_SRGB)
+    else if (locations & WINED3D_LOCATION_TEXTURE_SRGB)
         src_location = WINED3D_LOCATION_TEXTURE_SRGB;
     else /* surface_blt_fbo will load the source location if necessary. */
         src_location = WINED3D_LOCATION_TEXTURE_RGB;
@@ -3239,12 +3246,13 @@ static void surface_load_renderbuffer(struct wined3d_surface *surface, struct wi
 /* Context activation is done by the caller. Context may be NULL in ddraw-only mode. */
 HRESULT surface_load_location(struct wined3d_surface *surface, struct wined3d_context *context, DWORD location)
 {
+    struct wined3d_texture_sub_resource *sub_resource = surface_get_sub_resource(surface);
     struct wined3d_texture *texture = surface->container;
     HRESULT hr;
 
     TRACE("surface %p, location %s.\n", surface, wined3d_debug_location(location));
 
-    if (surface->locations & location && (!(texture->resource.usage & WINED3DUSAGE_DEPTHSTENCIL)
+    if (sub_resource->locations & location && (!(texture->resource.usage & WINED3DUSAGE_DEPTHSTENCIL)
             || (surface->ds_current_size.cx == surface->resource.width
             && surface->ds_current_size.cy == surface->resource.height)))
     {
@@ -3260,7 +3268,7 @@ HRESULT surface_load_location(struct wined3d_surface *surface, struct wined3d_co
                     required_access, texture->resource.access_flags);
     }
 
-    if (surface->locations & WINED3D_LOCATION_DISCARDED)
+    if (sub_resource->locations & WINED3D_LOCATION_DISCARDED)
     {
         TRACE("Surface previously discarded, nothing to do.\n");
         wined3d_surface_prepare(surface, context, location);
@@ -3269,7 +3277,7 @@ HRESULT surface_load_location(struct wined3d_surface *surface, struct wined3d_co
         goto done;
     }
 
-    if (!surface->locations)
+    if (!sub_resource->locations)
     {
         ERR("Surface %p does not have any up to date location.\n", surface);
         surface_validate_location(surface, WINED3D_LOCATION_DISCARDED);
@@ -3278,15 +3286,15 @@ HRESULT surface_load_location(struct wined3d_surface *surface, struct wined3d_co
 
     if (texture->resource.usage & WINED3DUSAGE_DEPTHSTENCIL)
     {
-        if ((location == WINED3D_LOCATION_TEXTURE_RGB && surface->locations & WINED3D_LOCATION_DRAWABLE)
-                || (location == WINED3D_LOCATION_DRAWABLE && surface->locations & WINED3D_LOCATION_TEXTURE_RGB))
+        if ((location == WINED3D_LOCATION_TEXTURE_RGB && sub_resource->locations & WINED3D_LOCATION_DRAWABLE)
+                || (location == WINED3D_LOCATION_DRAWABLE && sub_resource->locations & WINED3D_LOCATION_TEXTURE_RGB))
         {
             surface_load_ds_location(surface, context, location);
             goto done;
         }
 
         FIXME("Unimplemented copy from %s to %s for depth/stencil buffers.\n",
-                wined3d_debug_location(surface->locations), wined3d_debug_location(location));
+                wined3d_debug_location(sub_resource->locations), wined3d_debug_location(location));
         return WINED3DERR_INVALIDCALL;
     }
 
@@ -3330,7 +3338,7 @@ done:
         surface->ds_current_size.cy = surface->resource.height;
     }
 
-    if (location != WINED3D_LOCATION_SYSMEM && (surface->locations & WINED3D_LOCATION_SYSMEM))
+    if (location != WINED3D_LOCATION_SYSMEM && (sub_resource->locations & WINED3D_LOCATION_SYSMEM))
         surface_evict_sysmem(surface);
 
     return WINED3D_OK;
@@ -4349,12 +4357,16 @@ HRESULT wined3d_surface_blt(struct wined3d_surface *dst_surface, const RECT *dst
     }
     else
     {
+        struct wined3d_texture_sub_resource *src_sub_resource, *dst_sub_resource;
         const struct blit_shader *blitter;
 
+        dst_sub_resource = surface_get_sub_resource(dst_surface);
+        src_sub_resource = src_surface ? surface_get_sub_resource(src_surface) : NULL;
+
         /* 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_surface->locations & dst_surface->resource.map_binding)
-                && (!src_surface || (src_surface->locations & src_surface->resource.map_binding)))
+        if ((dst_sub_resource->locations & dst_surface->resource.map_binding)
+                && (!src_surface || (src_sub_resource->locations & src_surface->resource.map_binding)))
         {
             if (scale)
                 TRACE("Not doing sysmem blit because of scaling.\n");
@@ -4398,8 +4410,8 @@ HRESULT wined3d_surface_blt(struct wined3d_surface *dst_surface, const RECT *dst
             {
                 blit_op = WINED3D_BLIT_OP_COLOR_BLIT_ALPHATEST;
             }
-            else if ((src_surface->locations & WINED3D_LOCATION_SYSMEM)
-                    && !(dst_surface->locations & WINED3D_LOCATION_SYSMEM))
+            else if ((src_sub_resource->locations & WINED3D_LOCATION_SYSMEM)
+                    && !(dst_sub_resource->locations & WINED3D_LOCATION_SYSMEM))
             {
                 /* Upload */
                 if (scale)
@@ -4560,7 +4572,10 @@ HRESULT wined3d_surface_init(struct wined3d_surface *surface, struct wined3d_tex
     }
 
     surface->container = container;
-    surface_validate_location(surface, WINED3D_LOCATION_SYSMEM);
+    surface->texture_target = target;
+    surface->texture_level = level;
+    surface->texture_layer = layer;
+
     list_init(&surface->renderbuffers);
     list_init(&surface->overlays);
 
@@ -4570,12 +4585,9 @@ HRESULT wined3d_surface_init(struct wined3d_surface *surface, struct wined3d_tex
     if (lockable || desc->format == WINED3DFMT_D16_LOCKABLE)
         surface->resource.access_flags |= WINED3D_RESOURCE_ACCESS_CPU;
 
-    surface->texture_target = target;
-    surface->texture_level = level;
-    surface->texture_layer = layer;
-
+    surface_validate_location(surface, WINED3D_LOCATION_SYSMEM);
     if (container->resource.usage & WINED3DUSAGE_DEPTHSTENCIL)
-        surface->locations = WINED3D_LOCATION_DISCARDED;
+        surface_get_sub_resource(surface)->locations = WINED3D_LOCATION_DISCARDED;
 
     if (wined3d_texture_use_pbo(container, gl_info))
         surface->resource.map_binding = WINED3D_LOCATION_BUFFER;
diff --git a/dlls/wined3d/swapchain.c b/dlls/wined3d/swapchain.c
index 67eb2d2..09cc45a 100644
--- a/dlls/wined3d/swapchain.c
+++ b/dlls/wined3d/swapchain.c
@@ -429,6 +429,7 @@ static void swapchain_blit(const struct wined3d_swapchain *swapchain,
 /* Context activation is done by the caller. */
 static void wined3d_swapchain_rotate(struct wined3d_swapchain *swapchain, struct wined3d_context *context)
 {
+    struct wined3d_texture_sub_resource *sub_resource;
     struct gl_texture tex0;
     GLuint rb0;
     DWORD locations0;
@@ -439,25 +440,26 @@ static void wined3d_swapchain_rotate(struct wined3d_swapchain *swapchain, struct
     if (swapchain->desc.backbuffer_count < 2 || !swapchain->render_to_fbo)
         return;
 
-    surface_prev = surface_from_resource(wined3d_texture_get_sub_resource(swapchain->back_buffers[0], 0));
+    surface_prev = swapchain->back_buffers[0]->sub_resources[0].u.surface;
 
     /* Back buffer 0 is already in the draw binding. */
     tex0 = swapchain->back_buffers[0]->texture_rgb;
     rb0 = surface_prev->rb_multisample;
-    locations0 = surface_prev->locations;
+    locations0 = surface_get_sub_resource(surface_prev)->locations;
 
     for (i = 1; i < swapchain->desc.backbuffer_count; ++i)
     {
-        surface = surface_from_resource(wined3d_texture_get_sub_resource(swapchain->back_buffers[i], 0));
+        sub_resource = &swapchain->back_buffers[i]->sub_resources[0];
+        surface = sub_resource->u.surface;
 
-        if (!(surface->locations & supported_locations))
+        if (!(sub_resource->locations & supported_locations))
             surface_load_location(surface, context, swapchain->back_buffers[i]->resource.draw_binding);
 
         swapchain->back_buffers[i - 1]->texture_rgb = swapchain->back_buffers[i]->texture_rgb;
         surface_prev->rb_multisample = surface->rb_multisample;
 
-        surface_validate_location(surface_prev, surface->locations & supported_locations);
-        surface_invalidate_location(surface_prev, ~(surface->locations & supported_locations));
+        surface_validate_location(surface_prev, sub_resource->locations & supported_locations);
+        surface_invalidate_location(surface_prev, ~(sub_resource->locations & supported_locations));
 
         surface_prev = surface;
     }
diff --git a/dlls/wined3d/texture.c b/dlls/wined3d/texture.c
index e163e83..4cf445a 100644
--- a/dlls/wined3d/texture.c
+++ b/dlls/wined3d/texture.c
@@ -735,6 +735,7 @@ HRESULT CDECL wined3d_texture_update_desc(struct wined3d_texture *texture, UINT
     const struct wined3d_gl_info *gl_info = &device->adapter->gl_info;
     const struct wined3d_format *format = wined3d_get_format(gl_info, format_id);
     UINT resource_size = wined3d_format_calculate_size(format, device->surface_alignment, width, height, 1);
+    struct wined3d_texture_sub_resource *sub_resource;
     struct wined3d_surface *surface;
     DWORD valid_location = 0;
     BOOL create_dib = FALSE;
@@ -771,8 +772,9 @@ HRESULT CDECL wined3d_texture_update_desc(struct wined3d_texture *texture, UINT
         return WINED3DERR_INVALIDCALL;
     }
 
-    surface = texture->sub_resources[0].u.surface;
-    if (surface->resource.map_count || (surface->flags & SFLAG_DCINUSE))
+    sub_resource = &texture->sub_resources[0];
+    surface = sub_resource->u.surface;
+    if (sub_resource->resource->map_count || (surface->flags & SFLAG_DCINUSE))
     {
         WARN("Surface is mapped or the DC is in use.\n");
         return WINED3DERR_INVALIDCALL;
@@ -792,7 +794,7 @@ HRESULT CDECL wined3d_texture_update_desc(struct wined3d_texture *texture, UINT
         create_dib = TRUE;
     }
 
-    wined3d_resource_free_sysmem(&surface->resource);
+    wined3d_resource_free_sysmem(sub_resource->resource);
 
     if ((texture->row_pitch = pitch))
         texture->slice_pitch = height * pitch;
@@ -807,12 +809,12 @@ HRESULT CDECL wined3d_texture_update_desc(struct wined3d_texture *texture, UINT
     texture->resource.width = width;
     texture->resource.height = height;
 
-    surface->resource.format = format;
-    surface->resource.multisample_type = multisample_type;
-    surface->resource.multisample_quality = multisample_quality;
-    surface->resource.width = width;
-    surface->resource.height = height;
-    surface->resource.size = texture->slice_pitch;
+    sub_resource->resource->format = format;
+    sub_resource->resource->multisample_type = multisample_type;
+    sub_resource->resource->multisample_quality = multisample_quality;
+    sub_resource->resource->width = width;
+    sub_resource->resource->height = height;
+    sub_resource->resource->size = texture->slice_pitch;
 
     if (((width & (width - 1)) || (height & (height - 1))) && !gl_info->supported[ARB_TEXTURE_NON_POWER_OF_TWO]
             && !gl_info->supported[ARB_TEXTURE_RECTANGLE] && !gl_info->supported[WINED3D_GL_NORMALIZED_TEXRECT])
@@ -831,11 +833,11 @@ HRESULT CDECL wined3d_texture_update_desc(struct wined3d_texture *texture, UINT
         surface->pow2Height = height;
     }
 
-    surface->locations = 0;
+    sub_resource->locations = 0;
 
     if ((texture->user_memory = mem))
     {
-        surface->resource.map_binding = WINED3D_LOCATION_USER_MEMORY;
+        sub_resource->resource->map_binding = WINED3D_LOCATION_USER_MEMORY;
         valid_location = WINED3D_LOCATION_USER_MEMORY;
     }
     else if (create_dib && SUCCEEDED(surface_create_dib_section(surface)))
@@ -852,8 +854,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 (surface->resource.map_binding == WINED3D_LOCATION_BUFFER && !wined3d_texture_use_pbo(texture, gl_info))
-        surface->resource.map_binding = surface->dib.DIBsection ? WINED3D_LOCATION_DIB : WINED3D_LOCATION_SYSMEM;
+    if (sub_resource->resource->map_binding == WINED3D_LOCATION_BUFFER && !wined3d_texture_use_pbo(texture, gl_info))
+        sub_resource->resource->map_binding = surface->dib.DIBsection ? WINED3D_LOCATION_DIB : WINED3D_LOCATION_SYSMEM;
 
     surface_validate_location(surface, valid_location);
 
@@ -1420,7 +1422,8 @@ static HRESULT texture_resource_sub_resource_unmap(struct wined3d_resource *reso
     {
         struct wined3d_surface *surface = texture->sub_resources[sub_resource_idx].u.surface;
 
-        if (!(surface->locations & (WINED3D_LOCATION_DRAWABLE | WINED3D_LOCATION_TEXTURE_RGB)))
+        if (!(surface_get_sub_resource(surface)->locations
+                & (WINED3D_LOCATION_DRAWABLE | WINED3D_LOCATION_TEXTURE_RGB)))
             texture->swapchain->swapchain_ops->swapchain_frontbuffer_updated(texture->swapchain);
     }
     else if (resource->format_flags & (WINED3DFMT_FLAG_DEPTH | WINED3DFMT_FLAG_STENCIL))
diff --git a/dlls/wined3d/volume.c b/dlls/wined3d/volume.c
index f23a385..fe1b6ee 100644
--- a/dlls/wined3d/volume.c
+++ b/dlls/wined3d/volume.c
@@ -132,20 +132,28 @@ void wined3d_volume_upload_data(struct wined3d_volume *volume, const struct wine
 
 void wined3d_volume_validate_location(struct wined3d_volume *volume, DWORD location)
 {
+    struct wined3d_texture_sub_resource *sub_resource;
+
     TRACE("Volume %p, setting %s.\n", volume, wined3d_debug_location(location));
-    volume->locations |= location;
-    TRACE("new location flags are %s.\n", wined3d_debug_location(volume->locations));
+
+    sub_resource = &volume->container->sub_resources[volume->texture_level];
+    sub_resource->locations |= location;
+
+    TRACE("new location flags are %s.\n", wined3d_debug_location(sub_resource->locations));
 }
 
 void wined3d_volume_invalidate_location(struct wined3d_volume *volume, DWORD location)
 {
+    struct wined3d_texture_sub_resource *sub_resource;
+
     TRACE("Volume %p, clearing %s.\n", volume, wined3d_debug_location(location));
 
+    sub_resource = &volume->container->sub_resources[volume->texture_level];
     if (location & (WINED3D_LOCATION_TEXTURE_RGB | WINED3D_LOCATION_TEXTURE_SRGB))
         wined3d_texture_set_dirty(volume->container);
-    volume->locations &= ~location;
+    sub_resource->locations &= ~location;
 
-    TRACE("new location flags are %s.\n", wined3d_debug_location(volume->locations));
+    TRACE("new location flags are %s.\n", wined3d_debug_location(sub_resource->locations));
 }
 
 /* Context activation is done by the caller. */
@@ -253,11 +261,13 @@ BOOL wined3d_volume_load_location(struct wined3d_volume *volume,
 {
     DWORD required_access = volume_access_from_location(location);
     struct wined3d_texture *texture = volume->container;
+    struct wined3d_texture_sub_resource *sub_resource;
 
+    sub_resource = &texture->sub_resources[volume->texture_level];
     TRACE("Volume %p, loading %s, have %s.\n", volume, wined3d_debug_location(location),
-        wined3d_debug_location(volume->locations));
+        wined3d_debug_location(sub_resource->locations));
 
-    if ((volume->locations & location) == location)
+    if ((sub_resource->locations & location) == location)
     {
         TRACE("Location(s) already up to date.\n");
         return TRUE;
@@ -273,7 +283,7 @@ BOOL wined3d_volume_load_location(struct wined3d_volume *volume,
     if (!wined3d_volume_prepare_location(volume, context, location))
         return FALSE;
 
-    if (volume->locations & WINED3D_LOCATION_DISCARDED)
+    if (sub_resource->locations & WINED3D_LOCATION_DISCARDED)
     {
         TRACE("Volume previously discarded, nothing to do.\n");
         wined3d_volume_invalidate_location(volume, WINED3D_LOCATION_DISCARDED);
@@ -284,45 +294,41 @@ BOOL wined3d_volume_load_location(struct wined3d_volume *volume,
     {
         case WINED3D_LOCATION_TEXTURE_RGB:
         case WINED3D_LOCATION_TEXTURE_SRGB:
-            if (volume->locations & WINED3D_LOCATION_SYSMEM)
+            if (sub_resource->locations & WINED3D_LOCATION_SYSMEM)
             {
                 struct wined3d_const_bo_address data = {0, volume->resource.heap_memory};
                 wined3d_texture_bind_and_dirtify(texture, context,
                         location == WINED3D_LOCATION_TEXTURE_SRGB);
                 wined3d_volume_upload_data(volume, context, &data);
             }
-            else if (volume->locations & WINED3D_LOCATION_BUFFER)
+            else if (sub_resource->locations & WINED3D_LOCATION_BUFFER)
             {
-                struct wined3d_const_bo_address data =
-                {
-                    texture->sub_resources[volume->texture_level].buffer_object,
-                    NULL
-                };
+                struct wined3d_const_bo_address data = {sub_resource->buffer_object, NULL};
                 wined3d_texture_bind_and_dirtify(texture, context,
                         location == WINED3D_LOCATION_TEXTURE_SRGB);
                 wined3d_volume_upload_data(volume, context, &data);
             }
-            else if (volume->locations & WINED3D_LOCATION_TEXTURE_RGB)
+            else if (sub_resource->locations & WINED3D_LOCATION_TEXTURE_RGB)
             {
                 wined3d_volume_srgb_transfer(volume, context, TRUE);
             }
-            else if (volume->locations & WINED3D_LOCATION_TEXTURE_SRGB)
+            else if (sub_resource->locations & WINED3D_LOCATION_TEXTURE_SRGB)
             {
                 wined3d_volume_srgb_transfer(volume, context, FALSE);
             }
             else
             {
-                FIXME("Implement texture loading from %s.\n", wined3d_debug_location(volume->locations));
+                FIXME("Implement texture loading from %s.\n", wined3d_debug_location(sub_resource->locations));
                 return FALSE;
             }
             break;
 
         case WINED3D_LOCATION_SYSMEM:
-            if (volume->locations & (WINED3D_LOCATION_TEXTURE_RGB | WINED3D_LOCATION_TEXTURE_SRGB))
+            if (sub_resource->locations & (WINED3D_LOCATION_TEXTURE_RGB | WINED3D_LOCATION_TEXTURE_SRGB))
             {
                 struct wined3d_bo_address data = {0, volume->resource.heap_memory};
 
-                if (volume->locations & WINED3D_LOCATION_TEXTURE_RGB)
+                if (sub_resource->locations & WINED3D_LOCATION_TEXTURE_RGB)
                     wined3d_texture_bind_and_dirtify(texture, context, FALSE);
                 else
                     wined3d_texture_bind_and_dirtify(texture, context, TRUE);
@@ -333,21 +339,17 @@ BOOL wined3d_volume_load_location(struct wined3d_volume *volume,
             else
             {
                 FIXME("Implement WINED3D_LOCATION_SYSMEM loading from %s.\n",
-                        wined3d_debug_location(volume->locations));
+                        wined3d_debug_location(sub_resource->locations));
                 return FALSE;
             }
             break;
 
         case WINED3D_LOCATION_BUFFER:
-            if (volume->locations & (WINED3D_LOCATION_TEXTURE_RGB | WINED3D_LOCATION_TEXTURE_SRGB))
+            if (sub_resource->locations & (WINED3D_LOCATION_TEXTURE_RGB | WINED3D_LOCATION_TEXTURE_SRGB))
             {
-                struct wined3d_bo_address data =
-                {
-                    texture->sub_resources[volume->texture_level].buffer_object,
-                    NULL
-                };
+                struct wined3d_bo_address data = {sub_resource->buffer_object, NULL};
 
-                if (volume->locations & WINED3D_LOCATION_TEXTURE_RGB)
+                if (sub_resource->locations & WINED3D_LOCATION_TEXTURE_RGB)
                     wined3d_texture_bind_and_dirtify(texture, context, FALSE);
                 else
                     wined3d_texture_bind_and_dirtify(texture, context, TRUE);
@@ -357,14 +359,14 @@ BOOL wined3d_volume_load_location(struct wined3d_volume *volume,
             else
             {
                 FIXME("Implement WINED3D_LOCATION_BUFFER loading from %s.\n",
-                        wined3d_debug_location(volume->locations));
+                        wined3d_debug_location(sub_resource->locations));
                 return FALSE;
             }
             break;
 
         default:
             FIXME("Implement %s loading from %s.\n", wined3d_debug_location(location),
-                    wined3d_debug_location(volume->locations));
+                    wined3d_debug_location(sub_resource->locations));
             return FALSE;
     }
 
@@ -488,7 +490,7 @@ HRESULT wined3d_volume_init(struct wined3d_volume *volume, struct wined3d_textur
     }
 
     volume->texture_level = level;
-    volume->locations = WINED3D_LOCATION_DISCARDED;
+    container->sub_resources[level].locations = WINED3D_LOCATION_DISCARDED;
 
     if (wined3d_texture_use_pbo(container, gl_info))
     {
diff --git a/dlls/wined3d/wined3d_private.h b/dlls/wined3d/wined3d_private.h
index 229f6fd..6e5b96b 100644
--- a/dlls/wined3d/wined3d_private.h
+++ b/dlls/wined3d/wined3d_private.h
@@ -2417,7 +2417,7 @@ struct wined3d_texture
         DWORD color_key_flags;
     } async;
 
-    struct
+    struct wined3d_texture_sub_resource
     {
         struct wined3d_resource *resource;
         union
@@ -2426,6 +2426,7 @@ struct wined3d_texture
             struct wined3d_volume *volume;
         } u;
 
+        DWORD locations;
         GLuint buffer_object;
     } sub_resources[1];
 };
@@ -2502,7 +2503,6 @@ struct wined3d_volume
     struct wined3d_resource resource;
     struct wined3d_texture *container;
 
-    DWORD locations;
     GLint texture_level;
 };
 
@@ -2567,7 +2567,6 @@ struct wined3d_surface
 {
     struct wined3d_resource resource;
     struct wined3d_texture *container;
-    DWORD locations;
 
     DWORD flags;
 
@@ -2606,6 +2605,16 @@ static inline BOOL needs_separate_srgb_gl_texture(const struct wined3d_context *
             && context->d3d_info->wined3d_creation_flags & WINED3D_SRGB_READ_WRITE_CONTROL;
 }
 
+static inline unsigned int surface_get_sub_resource_idx(const struct wined3d_surface *surface)
+{
+    return surface->texture_layer * surface->container->level_count + surface->texture_level;
+}
+
+static inline struct wined3d_texture_sub_resource *surface_get_sub_resource(struct wined3d_surface *surface)
+{
+    return &surface->container->sub_resources[surface_get_sub_resource_idx(surface)];
+}
+
 static inline GLuint surface_get_texture_name(const struct wined3d_surface *surface,
         const struct wined3d_context *context, BOOL srgb)
 {
-- 
2.1.4




More information about the wine-patches mailing list