/* Context activation is done by the caller. */ static void wined3d_volume_load_location(struct wined3d_volume *volume, struct wined3d_context *context, DWORD location) { DWORD required_access = volume_access_from_location(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 & required_access) != required_access) { ERR("Operation requires %#x access, but volume only has %#x.\n", required_access, volume->resource.access_flags); return; } switch (location) { case WINED3D_LOCATION_TEXTURE_RGB: case WINED3D_LOCATION_TEXTURE_SRGB: if ((location == WINED3D_LOCATION_TEXTURE_RGB && !(volume->flags & WINED3D_VFLAG_ALLOCATED)) || (location == WINED3D_LOCATION_TEXTURE_SRGB && !(volume->flags & WINED3D_VFLAG_SRGB_ALLOCATED))) ERR("Trying to load (s)RGB texture without prior allocation.\n"); 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 if (volume->locations & WINED3D_LOCATION_BUFFER) { struct wined3d_bo_address data = {volume->pbo, NULL}; wined3d_volume_upload_data(volume, context, &data); } else if (volume->locations & WINED3D_LOCATION_TEXTURE_RGB) { wined3d_volume_srgb_transfer(volume, context, TRUE); } else if (volume->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)); return; } wined3d_volume_validate_location(volume, location); if (volume->resource.pool == WINED3D_POOL_MANAGED && volume->download_count < 10) wined3d_volume_evict_sysmem(volume); 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 if (volume->locations & (WINED3D_LOCATION_TEXTURE_RGB | WINED3D_LOCATION_TEXTURE_SRGB)) { struct wined3d_bo_address data = {0, volume->resource.allocatedMemory}; if (volume->locations & WINED3D_LOCATION_TEXTURE_RGB) volume_bind_and_dirtify(volume, context, FALSE); else volume_bind_and_dirtify(volume, context, TRUE); volume->download_count++; wined3d_volume_download_data(volume, context, &data); } 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; case WINED3D_LOCATION_BUFFER: if (!volume->pbo || !(volume->flags & WINED3D_VFLAG_PBO)) ERR("Trying to load WINED3D_LOCATION_BUFFER without setting it up first.\n"); 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_TEXTURE_RGB | WINED3D_LOCATION_TEXTURE_SRGB)) { struct wined3d_bo_address data = {volume->pbo, NULL}; if (volume->locations & WINED3D_LOCATION_TEXTURE_RGB) volume_bind_and_dirtify(volume, context, FALSE); else volume_bind_and_dirtify(volume, context, TRUE); wined3d_volume_download_data(volume, context, &data); } else { FIXME("Implement WINED3D_LOCATION_BUFFER loading from %s.\n", wined3d_debug_location(volume->locations)); return; } wined3d_volume_validate_location(volume, WINED3D_LOCATION_BUFFER); 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. */ BOOL wined3d_volume_load_location(struct wined3d_volume *volume, struct wined3d_context *context, DWORD location) { DWORD required_access = volume_access_from_location(location); unsigned int sub_resource_idx = volume->texture_level; struct wined3d_texture *texture = volume->container; struct wined3d_texture_sub_resource *sub_resource; sub_resource = &texture->sub_resources[sub_resource_idx]; TRACE("Volume %p, loading %s, have %s.\n", volume, wined3d_debug_location(location), wined3d_debug_location(sub_resource->locations)); if ((sub_resource->locations & location) == location) { TRACE("Location(s) already up to date.\n"); return TRUE; } if ((texture->resource.access_flags & required_access) != required_access) { ERR("Operation requires %#x access, but volume only has %#x.\n", required_access, texture->resource.access_flags); return FALSE; } if (!wined3d_texture_prepare_location(texture, sub_resource_idx, context, location)) return FALSE; if (sub_resource->locations & WINED3D_LOCATION_DISCARDED) { TRACE("Volume previously discarded, nothing to do.\n"); wined3d_texture_validate_location(texture, sub_resource_idx, location); wined3d_texture_invalidate_location(texture, sub_resource_idx, WINED3D_LOCATION_DISCARDED); goto done; } switch (location) { case WINED3D_LOCATION_TEXTURE_RGB: case WINED3D_LOCATION_TEXTURE_SRGB: 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 (sub_resource->locations & WINED3D_LOCATION_BUFFER) { 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 (sub_resource->locations & WINED3D_LOCATION_TEXTURE_RGB) { wined3d_volume_srgb_transfer(volume, context, TRUE); } 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(sub_resource->locations)); return FALSE; } break; case WINED3D_LOCATION_SYSMEM: if (sub_resource->locations & (WINED3D_LOCATION_TEXTURE_RGB | WINED3D_LOCATION_TEXTURE_SRGB)) { struct wined3d_bo_address data = {0, volume->resource.heap_memory}; 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); wined3d_volume_download_data(volume, context, &data); ++texture->download_count; } else { FIXME("Implement WINED3D_LOCATION_SYSMEM loading from %s.\n", wined3d_debug_location(sub_resource->locations)); return FALSE; } break; case WINED3D_LOCATION_BUFFER: if (sub_resource->locations & (WINED3D_LOCATION_TEXTURE_RGB | WINED3D_LOCATION_TEXTURE_SRGB)) { struct wined3d_bo_address data = {sub_resource->buffer_object, NULL}; 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); wined3d_volume_download_data(volume, context, &data); } else { FIXME("Implement WINED3D_LOCATION_BUFFER loading from %s.\n", wined3d_debug_location(sub_resource->locations)); return FALSE; } break; default: FIXME("Implement %s loading from %s.\n", wined3d_debug_location(location), wined3d_debug_location(sub_resource->locations)); return FALSE; } done: wined3d_texture_validate_location(texture, sub_resource_idx, location); if (location != WINED3D_LOCATION_SYSMEM && wined3d_volume_can_evict(volume)) wined3d_volume_evict_sysmem(volume); return TRUE; }