From 9508926776cb6d94f7d184fae9642a379f4ee7ad Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Stefan=20D=C3=B6singer?= <stefan@codeweavers.com>
Date: Thu, 3 Oct 2013 12:47:01 +0200
Subject: wined3d: Move load_location into the resource.

The resource part of load_location will handle transfers between sysmem
locations (heap memory, user memory, dib) and buffers. Texture loading
and downloading from textures will be delegated to surfaces / volumes.
---
 dlls/wined3d/buffer.c          |  8 +++++++
 dlls/wined3d/resource.c        | 50 ++++++++++++++++++++++++++++++++++++++++++
 dlls/wined3d/surface.c         | 12 ++++++++--
 dlls/wined3d/texture.c         |  8 +++++++
 dlls/wined3d/volume.c          | 42 ++++++++---------------------------
 dlls/wined3d/wined3d_private.h |  7 +++++-
 6 files changed, 91 insertions(+), 36 deletions(-)

diff --git a/dlls/wined3d/buffer.c b/dlls/wined3d/buffer.c
index 8aac5cb..4e91176 100644
--- a/dlls/wined3d/buffer.c
+++ b/dlls/wined3d/buffer.c
@@ -1193,6 +1193,13 @@ static void wined3d_buffer_location_invalidated(struct wined3d_resource *resourc
     ERR("Not yet implemented.\n");
 }
 
+/* Context activation is done by the caller. */
+static void wined3d_buffer_load_location(struct wined3d_resource *resource,
+        struct wined3d_context *context, DWORD location)
+{
+    ERR("Not yet implemented.\n");
+}
+
 static const struct wined3d_resource_ops buffer_resource_ops =
 {
     buffer_resource_incref,
@@ -1201,6 +1208,7 @@ static const struct wined3d_resource_ops buffer_resource_ops =
     buffer_resource_sub_resource_map,
     buffer_resource_sub_resource_unmap,
     wined3d_buffer_location_invalidated,
+    wined3d_buffer_load_location,
 };
 
 static HRESULT buffer_init(struct wined3d_buffer *buffer, struct wined3d_device *device,
diff --git a/dlls/wined3d/resource.c b/dlls/wined3d/resource.c
index 39346b5..d1f9fd9 100644
--- a/dlls/wined3d/resource.c
+++ b/dlls/wined3d/resource.c
@@ -487,3 +487,53 @@ void wined3d_resource_invalidate_location(struct wined3d_resource *resource, DWO
 
     resource->resource_ops->resource_location_invalidated(resource, location);
 }
+
+DWORD wined3d_resource_access_from_location(DWORD location)
+{
+    switch (location)
+    {
+        case WINED3D_LOCATION_DISCARDED:
+            return 0;
+
+        case WINED3D_LOCATION_SYSMEM:
+        case WINED3D_LOCATION_USER_MEMORY:
+        case WINED3D_LOCATION_DIB:
+            return WINED3D_RESOURCE_ACCESS_CPU;
+
+        case WINED3D_LOCATION_BUFFER:
+        case WINED3D_LOCATION_TEXTURE_RGB:
+        case WINED3D_LOCATION_TEXTURE_SRGB:
+        case WINED3D_LOCATION_DRAWABLE:
+        case WINED3D_LOCATION_RB_MULTISAMPLE:
+        case WINED3D_LOCATION_RB_RESOLVED:
+            return WINED3D_RESOURCE_ACCESS_GPU;
+
+        default:
+            FIXME("Unhandled location %#x.\n", location);
+            return 0;
+    }
+}
+
+/* Context activation is optionally by the caller. Context may be NULL. */
+void wined3d_resource_load_location(struct wined3d_resource *resource,
+        struct wined3d_context *context, DWORD location)
+{
+    DWORD required_access = wined3d_resource_access_from_location(location);
+
+    if ((resource->locations & location) == location)
+    {
+        TRACE("Location(s) already up to date.\n");
+        return;
+    }
+
+    /* Keep this a WARN for now until surfaces are cleaned up. */
+    if ((resource->access_flags & required_access) != required_access)
+        WARN("Operation requires %#x access, but resource only has %#x.\n",
+                required_access, resource->access_flags);
+
+    /* Context is NULL in ddraw-only operation without OpenGL. */
+    if (!context)
+        ERR("A context is required for non-sysmem operation.\n");
+
+    resource->resource_ops->resource_load_location(resource, context, location);
+}
diff --git a/dlls/wined3d/surface.c b/dlls/wined3d/surface.c
index 146d647..791f351 100644
--- a/dlls/wined3d/surface.c
+++ b/dlls/wined3d/surface.c
@@ -1230,6 +1230,13 @@ static void wined3d_surface_location_invalidated(struct wined3d_resource *resour
         wined3d_texture_set_dirty(surface->container);
 }
 
+/* Context activation is done by the caller. */
+static void wined3d_surface_load_location(struct wined3d_resource *resource,
+        struct wined3d_context *context, DWORD location)
+{
+    ERR("Not yet implemented.\n");
+}
+
 static const struct wined3d_resource_ops surface_resource_ops =
 {
     surface_resource_incref,
@@ -1238,6 +1245,7 @@ static const struct wined3d_resource_ops surface_resource_ops =
     surface_resource_sub_resource_map,
     surface_resource_sub_resource_unmap,
     wined3d_surface_location_invalidated,
+    wined3d_surface_load_location,
 };
 
 static const struct wined3d_surface_ops surface_ops =
@@ -3839,7 +3847,7 @@ void surface_load_ds_location(struct wined3d_surface *surface, struct wined3d_co
     surface->ds_current_size.cy = surface->resource.height;
 }
 
-static DWORD resource_access_from_location(DWORD location)
+static DWORD surface_access_from_location(DWORD location)
 {
     switch (location)
     {
@@ -4178,7 +4186,7 @@ void surface_load_location(struct wined3d_surface *surface, struct wined3d_conte
 
     if (WARN_ON(d3d_surface))
     {
-        DWORD required_access = resource_access_from_location(location);
+        DWORD required_access = surface_access_from_location(location);
         if ((surface->resource.access_flags & required_access) != required_access)
             WARN("Operation requires %#x access, but surface only has %#x.\n",
                     required_access, surface->resource.access_flags);
diff --git a/dlls/wined3d/texture.c b/dlls/wined3d/texture.c
index 377d1bc..bcdf96f 100644
--- a/dlls/wined3d/texture.c
+++ b/dlls/wined3d/texture.c
@@ -941,6 +941,13 @@ static void wined3d_texture_load_location_invalidated(struct wined3d_resource *r
     ERR("Should not be called on textures.\n");
 }
 
+/* Context activation is done by the caller. */
+static void wined3d_texture_load_location(struct wined3d_resource *resource,
+        struct wined3d_context *context, DWORD location)
+{
+    ERR("Should not be called on textures.\n");
+}
+
 static const struct wined3d_resource_ops texture2d_resource_ops =
 {
     texture_resource_incref,
@@ -949,6 +956,7 @@ static const struct wined3d_resource_ops texture2d_resource_ops =
     texture2d_resource_sub_resource_map,
     texture2d_resource_sub_resource_unmap,
     wined3d_texture_load_location_invalidated,
+    wined3d_texture_load_location,
 };
 
 static HRESULT texture_init(struct wined3d_texture *texture, const struct wined3d_resource_desc *desc,
diff --git a/dlls/wined3d/volume.c b/dlls/wined3d/volume.c
index 00b9814..457548e 100644
--- a/dlls/wined3d/volume.c
+++ b/dlls/wined3d/volume.c
@@ -137,27 +137,6 @@ static void wined3d_volume_evict_sysmem(struct wined3d_volume *volume)
     wined3d_resource_invalidate_location(&volume->resource, WINED3D_LOCATION_SYSMEM);
 }
 
-static DWORD volume_access_from_location(DWORD location)
-{
-    switch (location)
-    {
-        case WINED3D_LOCATION_DISCARDED:
-            return 0;
-
-        case WINED3D_LOCATION_SYSMEM:
-            return WINED3D_RESOURCE_ACCESS_CPU;
-
-        case WINED3D_LOCATION_BUFFER:
-        case WINED3D_LOCATION_TEXTURE_RGB:
-        case WINED3D_LOCATION_TEXTURE_SRGB:
-            return WINED3D_RESOURCE_ACCESS_GPU;
-
-        default:
-            FIXME("Unhandled location %#x.\n", location);
-            return 0;
-    }
-}
-
 /* Context activation is done by the caller. */
 static void wined3d_volume_srgb_transfer(struct wined3d_volume *volume,
         struct wined3d_context *context, BOOL dest_is_srgb)
@@ -195,21 +174,17 @@ static BOOL wined3d_volume_can_evict(const struct wined3d_volume *volume)
 
     return TRUE;
 }
+
 /* Context activation is done by the caller. */
-static void wined3d_volume_load_location(struct wined3d_volume *volume,
+static void wined3d_volume_load_location(struct wined3d_resource *resource,
         struct wined3d_context *context, DWORD location)
 {
-    DWORD required_access = volume_access_from_location(location);
+    struct wined3d_volume *volume = volume_from_resource(resource);
+    DWORD required_access = wined3d_resource_access_from_location(location);
 
     TRACE("Volume %p, loading %s, have %s.\n", volume, wined3d_debug_location(location),
         wined3d_debug_location(volume->resource.locations));
 
-    if ((volume->resource.locations & location) == location)
-    {
-        TRACE("Location(s) already up to date.\n");
-        return;
-    }
-
     if ((volume->resource.access_flags & required_access) != required_access)
     {
         ERR("Operation requires %#x access, but volume only has %#x.\n",
@@ -335,7 +310,7 @@ static void wined3d_volume_load_location(struct wined3d_volume *volume,
 void wined3d_volume_load(struct wined3d_volume *volume, struct wined3d_context *context, BOOL srgb_mode)
 {
     wined3d_texture_prepare_texture(volume->container, context, srgb_mode);
-    wined3d_volume_load_location(volume, context,
+    wined3d_resource_load_location(&volume->resource, context,
             srgb_mode ? WINED3D_LOCATION_TEXTURE_SRGB : WINED3D_LOCATION_TEXTURE_RGB);
 }
 
@@ -394,7 +369,7 @@ static void volume_unload(struct wined3d_resource *resource)
     if (volume_prepare_system_memory(volume))
     {
         context = context_acquire(device, NULL);
-        wined3d_volume_load_location(volume, context, WINED3D_LOCATION_SYSMEM);
+        wined3d_resource_load_location(&volume->resource, context, WINED3D_LOCATION_SYSMEM);
         context_release(context);
         wined3d_resource_invalidate_location(&volume->resource, ~WINED3D_LOCATION_SYSMEM);
     }
@@ -516,7 +491,7 @@ HRESULT wined3d_volume_map(struct wined3d_volume *volume,
         if (flags & WINED3D_MAP_DISCARD)
             wined3d_resource_validate_location(&volume->resource, WINED3D_LOCATION_BUFFER);
         else
-            wined3d_volume_load_location(volume, context, WINED3D_LOCATION_BUFFER);
+            wined3d_resource_load_location(&volume->resource, context, WINED3D_LOCATION_BUFFER);
 
         GL_EXTCALL(glBindBuffer(GL_PIXEL_UNPACK_BUFFER, volume->pbo));
 
@@ -554,7 +529,7 @@ HRESULT wined3d_volume_map(struct wined3d_volume *volume,
         else if (!(volume->resource.locations & WINED3D_LOCATION_SYSMEM))
         {
             context = context_acquire(device, NULL);
-            wined3d_volume_load_location(volume, context, WINED3D_LOCATION_SYSMEM);
+            wined3d_resource_load_location(&volume->resource, context, WINED3D_LOCATION_SYSMEM);
             context_release(context);
         }
         base_memory = volume->resource.heap_memory;
@@ -685,6 +660,7 @@ static const struct wined3d_resource_ops volume_resource_ops =
     volume_resource_sub_resource_map,
     volume_resource_sub_resource_unmap,
     wined3d_volume_location_invalidated,
+    wined3d_volume_load_location,
 };
 
 static HRESULT volume_init(struct wined3d_volume *volume, struct wined3d_texture *container,
diff --git a/dlls/wined3d/wined3d_private.h b/dlls/wined3d/wined3d_private.h
index bcd6589..7e60c22 100644
--- a/dlls/wined3d/wined3d_private.h
+++ b/dlls/wined3d/wined3d_private.h
@@ -2251,6 +2251,8 @@ struct wined3d_resource_ops
             struct wined3d_map_desc *map_desc, const struct wined3d_box *box, DWORD flags);
     HRESULT (*resource_sub_resource_unmap)(struct wined3d_resource *resource, unsigned int sub_resource_idx);
     void (*resource_location_invalidated)(struct wined3d_resource *resource, DWORD location);
+    void (*resource_load_location)(struct wined3d_resource *resource,
+            struct wined3d_context *context, DWORD location);
 };
 
 struct wined3d_resource
@@ -2303,17 +2305,20 @@ HRESULT resource_init(struct wined3d_resource *resource, struct wined3d_device *
         void *parent, const struct wined3d_parent_ops *parent_ops,
         const struct wined3d_resource_ops *resource_ops) DECLSPEC_HIDDEN;
 void resource_unload(struct wined3d_resource *resource) DECLSPEC_HIDDEN;
+DWORD wined3d_resource_access_from_location(DWORD location) DECLSPEC_HIDDEN;
 BOOL wined3d_resource_allocate_sysmem(struct wined3d_resource *resource) DECLSPEC_HIDDEN;
 void wined3d_resource_free_sysmem(struct wined3d_resource *resource) DECLSPEC_HIDDEN;
 void wined3d_resource_get_pitch(const struct wined3d_resource *resource, UINT *row_pitch,
         UINT *slice_pitch) DECLSPEC_HIDDEN;
 GLbitfield wined3d_resource_gl_map_flags(DWORD d3d_flags) DECLSPEC_HIDDEN;
 GLenum wined3d_resource_gl_legacy_map_flags(DWORD d3d_flags) DECLSPEC_HIDDEN;
+void wined3d_resource_invalidate_location(struct wined3d_resource *resource, DWORD location) DECLSPEC_HIDDEN;
 BOOL wined3d_resource_is_offscreen(struct wined3d_resource *resource) DECLSPEC_HIDDEN;
+void wined3d_resource_load_location(struct wined3d_resource *resource,
+        struct wined3d_context *context, DWORD location) DECLSPEC_HIDDEN;
 DWORD wined3d_resource_sanitize_map_flags(const struct wined3d_resource *resource, DWORD flags) DECLSPEC_HIDDEN;
 void wined3d_resource_update_draw_binding(struct wined3d_resource *resource) DECLSPEC_HIDDEN;
 void wined3d_resource_validate_location(struct wined3d_resource *resource, DWORD location) DECLSPEC_HIDDEN;
-void wined3d_resource_invalidate_location(struct wined3d_resource *resource, DWORD location) DECLSPEC_HIDDEN;
 
 /* Tests show that the start address of resources is 32 byte aligned */
 #define RESOURCE_ALIGNMENT 16
-- 
2.7.0

