From 52fb1cc245f2b5156e2416d9630fa1cd857a5ae2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Stefan=20D=C3=B6singer?= Date: Thu, 22 Aug 2013 14:57:59 +0200 Subject: [PATCH] wined3d: Implement basic volume location management. --- dlls/wined3d/utils.c | 15 ++++ dlls/wined3d/volume.c | 121 +++++++++++++++++++++++++++++++-- dlls/wined3d/wined3d_private.h | 8 ++- 3 files changed, 138 insertions(+), 6 deletions(-) diff --git a/dlls/wined3d/utils.c b/dlls/wined3d/utils.c index 9462a3c43c6..03b4d3a020c 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[200]; + + 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 0852a7ab0dd..8ef841d26af 100644 --- a/dlls/wined3d/volume.c +++ b/dlls/wined3d/volume.c @@ -98,10 +98,100 @@ static void wined3d_volume_upload_data(struct wined3d_volume *volume, const stru } } +static void wined3d_volume_validate_location(struct wined3d_volume *volume, DWORD location) +{ + 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)); +} + +static void wined3d_volume_invalidate_location(struct wined3d_volume *volume, DWORD location) +{ + TRACE("Volume %p, clearing %s.\n", volume, wined3d_debug_location(location)); + volume->locations &= ~location; + TRACE("new location flags are %s.\n", wined3d_debug_location(volume->locations)); +} + +/* 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.access_flags & WINED3D_RESOURCE_ACCESS_GPU)) + { + if (location & ~WINED3D_LOCATION_SYSMEM) + { + ERR("Trying to load a cpu-only access volume into %s.\n", + wined3d_debug_location(location)); + return; + } + } + + 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"); + wined3d_volume_invalidate_location(volume, WINED3D_LOCATION_DISCARDED); + } + 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; + } + wined3d_volume_validate_location(volume, 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"); + wined3d_volume_invalidate_location(volume, WINED3D_LOCATION_DISCARDED); + } + else + { + FIXME("Implement WINED3D_LOCATION_SYSMEM loading from %s.\n", + wined3d_debug_location(volume->locations)); + return; + } + wined3d_volume_validate_location(volume, WINED3D_LOCATION_SYSMEM); + break; + + default: + FIXME("Implement %s loading from %s.\n", wined3d_debug_location(location), + wined3d_debug_location(volume->locations)); + } +} + /* 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 +200,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_invalidate_location(volume, ~WINED3D_LOCATION_SYSMEM); + + /* The texture name is managed by the container. */ volume->flags &= ~WINED3D_VFLAG_ALLOCATED; resource_unload(resource); @@ -217,6 +318,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 +349,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_invalidate_location(volume, ~WINED3D_LOCATION_SYSMEM); } volume->flags |= WINED3D_VFLAG_LOCKED; @@ -302,6 +412,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 c9be67ec082..c9e92f2c921 100644 --- a/dlls/wined3d/wined3d_private.h +++ b/dlls/wined3d/wined3d_private.h @@ -2050,12 +2050,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; };