[PATCH 5/5] wined3d: Implement basic volume location management
Stefan Dösinger
stefan at codeweavers.com
Wed Aug 21 17:30:42 CDT 2013
---
dlls/wined3d/utils.c | 15 +++++
dlls/wined3d/volume.c | 124 +++++++++++++++++++++++++++++++++++++++--
dlls/wined3d/wined3d_private.h | 8 ++-
3 files changed, 141 insertions(+), 6 deletions(-)
diff --git a/dlls/wined3d/utils.c b/dlls/wined3d/utils.c
index 9462a3c..bb5181e 100644
--- a/dlls/wined3d/utils.c
+++ b/dlls/wined3d/utils.c
@@ -3711,3 +3711,18 @@ void wined3d_get_draw_rect(const struct wined3d_state *state, RECT *rect)
if (state->render_states[WINED3D_RS_SCISSORTESTENABLE])
IntersectRect(rect, rect, &state->scissor_rect);
}
+
+const char *wined3d_debug_location(DWORD location)
+{
+ char buf[238];
+
+ buf[0] = '\0';
+#define LOCATION_TO_STR(u) if (location & u) { strcat(buf, " | "#u); location &= ~u; }
+ LOCATION_TO_STR(WINED3D_LOCATION_DISCARDED);
+ LOCATION_TO_STR(WINED3D_LOCATION_SYSMEM);
+ LOCATION_TO_STR(WINED3D_LOCATION_TEXTURE_RGB);
+#undef LOCATION_TO_STR
+ if (location) FIXME("Unrecognized location flag(s) %#x.\n", location);
+
+ return buf[0] ? wine_dbg_sprintf("%s", &buf[3]) : "0";
+}
diff --git a/dlls/wined3d/volume.c b/dlls/wined3d/volume.c
index 0852a7a..a73047a 100644
--- a/dlls/wined3d/volume.c
+++ b/dlls/wined3d/volume.c
@@ -99,9 +99,102 @@ static void wined3d_volume_upload_data(struct wined3d_volume *volume, const stru
}
/* Context activation is done by the caller. */
+static void wined3d_volume_load_location(struct wined3d_volume *volume,
+ struct wined3d_context *context, DWORD location)
+{
+ TRACE("Volume %p, loading %s, have %s.\n", volume, wined3d_debug_location(location),
+ wined3d_debug_location(volume->locations));
+
+ if ((volume->locations & location) == location)
+ {
+ TRACE("Location(s) already up to date.\n");
+ return;
+ }
+
+ if (volume->resource.pool == WINED3D_POOL_SYSTEM_MEM
+ || volume->resource.pool == WINED3D_POOL_SCRATCH)
+ {
+ if (location & ~WINED3D_LOCATION_SYSMEM)
+ {
+ ERR("Trying to load a sysmem or scratch volume into %s.\n",
+ wined3d_debug_location(location));
+ return;
+ }
+ }
+
+ if (count_bits(location) > 1)
+ FIXME("Implement loading two locations with one call\n");
+
+ switch (location)
+ {
+ case WINED3D_LOCATION_TEXTURE_RGB:
+ if (!(volume->flags & WINED3D_VFLAG_ALLOCATED))
+ {
+ ERR("Trying to load RGB texture without prior allocation.\n");
+ return;
+ }
+
+ if (volume->locations & WINED3D_LOCATION_DISCARDED)
+ {
+ TRACE("Volume previously discarded, nothing to do.\n");
+ }
+ else if (volume->locations & WINED3D_LOCATION_SYSMEM)
+ {
+ struct wined3d_bo_address data = {0, volume->resource.allocatedMemory};
+ wined3d_volume_upload_data(volume, context, &data);
+ }
+ else
+ {
+ FIXME("Implement texture loading from %s.\n", wined3d_debug_location(volume->locations));
+ return;
+ }
+ volume->locations |= WINED3D_LOCATION_TEXTURE_RGB;
+ break;
+
+ case WINED3D_LOCATION_SYSMEM:
+ if (!volume->resource.allocatedMemory || !volume->resource.heap_memory)
+ {
+ ERR("Trying to load WINED3D_LOCATION_SYSMEM without setting it up first.\n");
+ return;
+ }
+
+ if (volume->locations & WINED3D_LOCATION_DISCARDED)
+ {
+ TRACE("Volume previously discarded, nothing to do.\n");
+ }
+ else
+ {
+ FIXME("Implement WINED3D_LOCATION_SYSMEM loading from %s.\n",
+ wined3d_debug_location(volume->locations));
+ return;
+ }
+ volume->locations |= WINED3D_LOCATION_SYSMEM;
+ break;
+
+ default:
+ FIXME("Implement %s loading from %s.\n", wined3d_debug_location(location),
+ wined3d_debug_location(volume->locations));
+ }
+}
+
+static void wined3d_volume_update_location(struct wined3d_volume *volume, DWORD location, BOOL keep)
+{
+ if (keep)
+ {
+ TRACE("Volume %p, invalidating %s.\n", volume,
+ wined3d_debug_location(volume->locations & ~location));
+ volume->locations = location;
+ }
+ else
+ {
+ TRACE("Volume %p, invalidating %s.\n", volume, wined3d_debug_location(location));
+ volume->locations &= ~location;
+ }
+}
+
+/* Context activation is done by the caller. */
void wined3d_volume_load(struct wined3d_volume *volume, struct wined3d_context *context, BOOL srgb_mode)
{
- struct wined3d_bo_address data = {0, volume->resource.allocatedMemory};
volume_bind_and_dirtify(volume, context);
if (!(volume->flags & WINED3D_VFLAG_ALLOCATED))
@@ -110,18 +203,29 @@ void wined3d_volume_load(struct wined3d_volume *volume, struct wined3d_context *
volume->flags |= WINED3D_VFLAG_ALLOCATED;
}
- wined3d_volume_upload_data(volume, context, &data);
+ wined3d_volume_load_location(volume, context, WINED3D_LOCATION_TEXTURE_RGB);
}
-/* Do not call while under the GL lock. */
static void volume_unload(struct wined3d_resource *resource)
{
struct wined3d_volume *volume = volume_from_resource(resource);
+ struct wined3d_device *device = volume->resource.device;
+ struct wined3d_context *context;
+
+ if (volume->resource.pool == WINED3D_POOL_DEFAULT)
+ ERR("Unloading DEFAULT pool volume.\n");
TRACE("texture %p.\n", resource);
- /* The whole content is shadowed on This->resource.allocatedMemory, and
- * the texture name is managed by the VolumeTexture container. */
+ context = context_acquire(device, NULL);
+
+ wined3d_volume_load_location(volume, context, WINED3D_LOCATION_SYSMEM);
+
+ context_release(context);
+
+ wined3d_volume_update_location(volume, WINED3D_LOCATION_SYSMEM, TRUE);
+
+ /* The texture name is managed by the container. */
volume->flags &= ~WINED3D_VFLAG_ALLOCATED;
resource_unload(resource);
@@ -217,6 +321,14 @@ HRESULT CDECL wined3d_volume_map(struct wined3d_volume *volume,
volume->resource.allocatedMemory = volume->resource.heap_memory;
}
+ if (!(volume->locations & WINED3D_LOCATION_SYSMEM))
+ {
+ struct wined3d_device *device = volume->resource.device;
+ struct wined3d_context *context = context_acquire(device, NULL);
+ wined3d_volume_load_location(volume, context, WINED3D_LOCATION_SYSMEM);
+ context_release(context);
+ }
+
TRACE("allocatedMemory %p.\n", volume->resource.allocatedMemory);
map_desc->row_pitch = volume->resource.format->byte_count * volume->resource.width; /* Bytes / row */
@@ -240,6 +352,7 @@ HRESULT CDECL wined3d_volume_map(struct wined3d_volume *volume,
if (!(flags & (WINED3D_MAP_NO_DIRTY_UPDATE | WINED3D_MAP_READONLY)))
{
wined3d_texture_set_dirty(volume->container, TRUE);
+ wined3d_volume_update_location(volume, WINED3D_LOCATION_SYSMEM, TRUE);
}
volume->flags |= WINED3D_VFLAG_LOCKED;
@@ -302,6 +415,7 @@ static HRESULT volume_init(struct wined3d_volume *volume, struct wined3d_device
}
volume->texture_level = level;
+ volume->locations = WINED3D_LOCATION_DISCARDED;
return WINED3D_OK;
}
diff --git a/dlls/wined3d/wined3d_private.h b/dlls/wined3d/wined3d_private.h
index e19a61e..1244c38 100644
--- a/dlls/wined3d/wined3d_private.h
+++ b/dlls/wined3d/wined3d_private.h
@@ -2053,12 +2053,18 @@ void wined3d_texture_set_dirty(struct wined3d_texture *texture, BOOL dirty) DECL
#define WINED3D_VFLAG_LOCKED 0x00000001
#define WINED3D_VFLAG_ALLOCATED 0x00000002
+#define WINED3D_LOCATION_DISCARDED 0x00000001
+#define WINED3D_LOCATION_SYSMEM 0x00000002
+#define WINED3D_LOCATION_TEXTURE_RGB 0x00000004
+
+const char *wined3d_debug_location(DWORD location) DECLSPEC_HIDDEN;
+
struct wined3d_volume
{
struct wined3d_resource resource;
struct wined3d_texture *container;
- DWORD flags;
+ DWORD flags, locations;
GLint texture_level;
};
--
1.8.1.5
More information about the wine-patches
mailing list