void wined3d_resource_invalidate_location(struct wined3d_resource *resource, DWORD location) { TRACE("Resource %p, setting %s.\n", resource, wined3d_debug_location(location)); resource->locations &= ~location; TRACE("new location flags are %s.\n", wined3d_debug_location(resource->locations)); resource->resource_ops->resource_location_invalidated(resource, location); }
/* Context activation is done by the caller. */ BOOL wined3d_resource_prepare_map_memory(struct wined3d_resource *resource, struct wined3d_context *context) { switch (resource->map_binding) { case WINED3D_LOCATION_BUFFER: wined3d_resource_prepare_bo(resource, context); return TRUE; case WINED3D_LOCATION_SYSMEM: return wined3d_resource_prepare_system_memory(resource); case WINED3D_LOCATION_USER_MEMORY: if (!resource->user_memory) ERR("Map binding is set to WINED3D_LOCATION_USER_MEMORY but resource->user_memory is NULL.\n"); return TRUE; case WINED3D_LOCATION_DIB: if (!resource->bitmap_data) ERR("Map binding is set to WINED3D_LOCATION_DIB but resource->bitmap_data is NULL.\n"); return TRUE; default: ERR("Unexpected map binding %s.\n", wined3d_debug_location(resource->map_binding)); return FALSE; } }
void wined3d_resource_release_map_ptr(const struct wined3d_resource *resource, const struct wined3d_context *context) { const struct wined3d_gl_info *gl_info; switch (resource->map_binding) { case WINED3D_LOCATION_BUFFER: gl_info = context->gl_info; GL_EXTCALL(glBindBuffer(GL_PIXEL_UNPACK_BUFFER, resource->map_buffer->name)); GL_EXTCALL(glUnmapBuffer(GL_PIXEL_UNPACK_BUFFER)); GL_EXTCALL(glBindBuffer(GL_PIXEL_UNPACK_BUFFER, 0)); checkGLcall("Unmap GL buffer"); return; case WINED3D_LOCATION_SYSMEM: case WINED3D_LOCATION_DIB: case WINED3D_LOCATION_USER_MEMORY: return; default: ERR("Unexpected map binding %s.\n", wined3d_debug_location(resource->map_binding)); return; } }
void wined3d_resource_get_memory(const struct wined3d_resource *resource, DWORD location, struct wined3d_bo_address *data) { if (location & WINED3D_LOCATION_BUFFER) { data->buffer_object = resource->buffer->name; data->addr = NULL; return; } if (location & WINED3D_LOCATION_USER_MEMORY) { data->buffer_object = 0; data->addr = resource->user_memory; return; } if (location & WINED3D_LOCATION_DIB) { data->buffer_object = 0; data->addr = resource->bitmap_data; return; } if (location & WINED3D_LOCATION_SYSMEM) { data->buffer_object = 0; data->addr = resource->heap_memory; return; } ERR("Unexpected location %s.\n", wined3d_debug_location(location)); }
void *wined3d_resource_map_internal(struct wined3d_resource *resource, DWORD flags) { struct wined3d_device *device = resource->device; struct wined3d_context *context = NULL; void *mem; if (device->d3d_initialized) context = context_acquire(device, NULL); if (!wined3d_resource_prepare_map_memory(resource, context)) { WARN("Out of memory.\n"); context_release(context); return NULL; } if (flags & WINED3D_MAP_DISCARD) { switch (resource->map_binding) { case WINED3D_LOCATION_BUFFER: resource->map_buffer = wined3d_device_get_bo(device, resource->size, GL_STREAM_DRAW_ARB, GL_PIXEL_UNPACK_BUFFER_ARB, context); break; case WINED3D_LOCATION_SYSMEM: wined3d_resource_allocate_sysmem(resource); break; default: if (resource->access_fence) ERR("Location %s does not support DISCARD maps.\n", wined3d_debug_location(resource->map_binding)); if (resource->pool != WINED3D_POOL_DEFAULT) FIXME("Discard used on %s pool resource.\n", debug_d3dpool(resource->pool)); } wined3d_resource_validate_location(resource, resource->map_binding); } else { wined3d_resource_load_location(resource, context, resource->map_binding); } mem = wined3d_resource_get_map_ptr(resource, context, flags); if (context) context_release(context); return mem; }
BYTE *wined3d_resource_get_map_ptr(const struct wined3d_resource *resource, const struct wined3d_context *context, DWORD flags) { const struct wined3d_gl_info *gl_info; BYTE *ptr; switch (resource->map_binding) { case WINED3D_LOCATION_BUFFER: gl_info = context->gl_info; GL_EXTCALL(glBindBuffer(GL_PIXEL_UNPACK_BUFFER, resource->map_buffer->name)); if (gl_info->supported[ARB_MAP_BUFFER_RANGE]) { GLbitfield mapflags = wined3d_resource_gl_map_flags(flags); mapflags &= ~GL_MAP_FLUSH_EXPLICIT_BIT; ptr = GL_EXTCALL(glMapBufferRange(GL_PIXEL_UNPACK_BUFFER, 0, resource->size, mapflags)); } else { GLenum access = wined3d_resource_gl_legacy_map_flags(flags); ptr = GL_EXTCALL(glMapBuffer(GL_PIXEL_UNPACK_BUFFER, access)); } GL_EXTCALL(glBindBuffer(GL_PIXEL_UNPACK_BUFFER, 0)); checkGLcall("Map GL buffer"); return ptr; case WINED3D_LOCATION_SYSMEM: return resource->map_heap_memory; case WINED3D_LOCATION_DIB: return resource->bitmap_data; case WINED3D_LOCATION_USER_MEMORY: return resource->user_memory; default: ERR("Unexpected map binding %s.\n", wined3d_debug_location(resource->map_binding)); return NULL; } }
/* 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)); } }
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)); }
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)); }
/* 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; }
HRESULT wined3d_resource_map(struct wined3d_resource *resource, struct wined3d_map_desc *map_desc, const struct wined3d_box *box, DWORD flags) { struct wined3d_device *device = resource->device; BYTE *base_memory; const struct wined3d_format *format = resource->format; TRACE("resource %p, map_desc %p, box %p, flags %#x.\n", resource, map_desc, box, flags); if (resource->usage & WINED3DUSAGE_RENDERTARGET && wined3d_settings.ignore_rt_map) { WARN("Ignoring render target map, only finishing CS.\n"); wined3d_cs_emit_glfinish(device->cs); map_desc->row_pitch = 0; map_desc->slice_pitch = 0; map_desc->data = NULL; device->cs->ops->finish(device->cs); return WINED3D_OK; } if (resource->map_count) { WARN("Volume is already mapped.\n"); return WINED3DERR_INVALIDCALL; } flags = wined3d_resource_sanitize_map_flags(resource, flags); if (flags & WINED3D_MAP_NOOVERWRITE) FIXME("WINED3D_MAP_NOOVERWRITE are not implemented yet.\n"); if (flags & WINED3D_MAP_DISCARD) { switch (resource->map_binding) { case WINED3D_LOCATION_BUFFER: case WINED3D_LOCATION_SYSMEM: break; default: FIXME("Implement discard maps with %s map binding.\n", wined3d_debug_location(resource->map_binding)); wined3d_resource_sync(resource); } } else wined3d_resource_sync(resource); base_memory = wined3d_cs_emit_resource_map(device->cs, resource, flags); if (!base_memory) { WARN("Map failed.\n"); return WINED3DERR_INVALIDCALL; } TRACE("Base memory pointer %p.\n", base_memory); if (format->flags & WINED3DFMT_FLAG_BROKEN_PITCH) { map_desc->row_pitch = resource->width * format->byte_count; map_desc->slice_pitch = map_desc->row_pitch * resource->height; } else { wined3d_resource_get_pitch(resource, &map_desc->row_pitch, &map_desc->slice_pitch); } if (!box) { TRACE("No box supplied - all is ok\n"); map_desc->data = base_memory; } else { TRACE("Lock Box (%p) = l %u, t %u, r %u, b %u, fr %u, ba %u\n", box, box->left, box->top, box->right, box->bottom, box->front, box->back); if ((format->flags & (WINED3DFMT_FLAG_BLOCKS | WINED3DFMT_FLAG_BROKEN_PITCH)) == WINED3DFMT_FLAG_BLOCKS) { /* Compressed textures are block based, so calculate the offset of * the block that contains the top-left pixel of the locked rectangle. */ map_desc->data = base_memory + (box->front * map_desc->slice_pitch) + ((box->top / format->block_height) * map_desc->row_pitch) + ((box->left / format->block_width) * format->block_byte_count); } else { map_desc->data = base_memory + (map_desc->slice_pitch * box->front) + (map_desc->row_pitch * box->top) + (box->left * format->byte_count); } } if (!(flags & WINED3D_MAP_READONLY)) resource->unmap_dirtify = TRUE; resource->map_count++; TRACE("Returning memory %p, row pitch %d, slice pitch %d.\n", map_desc->data, map_desc->row_pitch, map_desc->slice_pitch); return WINED3D_OK; }