HRESULT CDECL wined3d_volume_map(struct wined3d_volume *volume, struct wined3d_map_desc *map_desc, const struct wined3d_box *box, DWORD flags) { struct wined3d_device *device = volume->resource.device; struct wined3d_context *context; const struct wined3d_gl_info *gl_info; BYTE *base_memory; TRACE("volume %p, map_desc %p, box %p, flags %#x.\n", volume, map_desc, box, flags); if (!(volume->resource.access_flags & WINED3D_RESOURCE_ACCESS_CPU)) { WARN("Volume %p is not CPU accessible.\n", volume); map_desc->data = NULL; return WINED3DERR_INVALIDCALL; } flags = wined3d_resource_sanitize_map_flags(&volume->resource, flags); if (volume->flags & WINED3D_VFLAG_PBO) { context = context_acquire(device, NULL); gl_info = context->gl_info; wined3d_volume_prepare_pbo(volume, context); if (flags & WINED3D_MAP_DISCARD) wined3d_volume_validate_location(volume, WINED3D_LOCATION_BUFFER); else wined3d_volume_load_location(volume, context, WINED3D_LOCATION_BUFFER); GL_EXTCALL(glBindBufferARB(GL_PIXEL_UNPACK_BUFFER_ARB, volume->pbo)); if (gl_info->supported[ARB_MAP_BUFFER_RANGE]) { GLbitfield mapflags = wined3d_resource_gl_map_flags(flags); mapflags &= ~GL_MAP_FLUSH_EXPLICIT_BIT; base_memory = GL_EXTCALL(glMapBufferRange(GL_PIXEL_UNPACK_BUFFER_ARB, 0, volume->resource.size, mapflags)); } else { base_memory = GL_EXTCALL(glMapBufferARB(GL_PIXEL_UNPACK_BUFFER_ARB, 0)); } GL_EXTCALL(glBindBufferARB(GL_PIXEL_UNPACK_BUFFER_ARB, 0)); checkGLcall("Map PBO"); context_release(context); } else { if (!volume_prepare_system_memory(volume)) { WARN("Out of memory.\n"); map_desc->data = NULL; return E_OUTOFMEMORY; } if (flags & WINED3D_MAP_DISCARD) { wined3d_volume_validate_location(volume, WINED3D_LOCATION_SYSMEM); } else if (!(volume->locations & WINED3D_LOCATION_SYSMEM)) { context = context_acquire(device, NULL); wined3d_volume_load_location(volume, context, WINED3D_LOCATION_SYSMEM); context_release(context); } base_memory = volume->resource.allocatedMemory; } TRACE("Base memory pointer %p.\n", base_memory); map_desc->row_pitch = volume->resource.format->byte_count * volume->resource.width; /* Bytes / row */ map_desc->slice_pitch = volume->resource.format->byte_count * volume->resource.width * volume->resource.height; /* Bytes / slice */ 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); map_desc->data = base_memory + (map_desc->slice_pitch * box->front) /* FIXME: is front < back or vica versa? */ + (map_desc->row_pitch * box->top) + (box->left * volume->resource.format->byte_count); } if (!(flags & (WINED3D_MAP_NO_DIRTY_UPDATE | WINED3D_MAP_READONLY))) { wined3d_texture_set_dirty(volume->container, TRUE); if (volume->flags & WINED3D_VFLAG_PBO) wined3d_volume_invalidate_location(volume, ~WINED3D_LOCATION_BUFFER); else wined3d_volume_invalidate_location(volume, ~WINED3D_LOCATION_SYSMEM); } volume->flags |= WINED3D_VFLAG_LOCKED; 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; }
HRESULT CDECL wined3d_volume_map(struct wined3d_volume *volume, struct wined3d_map_desc *map_desc, const struct wined3d_box *box, DWORD flags) { struct wined3d_device *device = volume->resource.device; struct wined3d_context *context; const struct wined3d_gl_info *gl_info; BYTE *base_memory; const struct wined3d_format *format = volume->resource.format; TRACE("volume %p, map_desc %p, box %p, flags %#x.\n", volume, map_desc, box, flags); map_desc->data = NULL; if (!(volume->resource.access_flags & WINED3D_RESOURCE_ACCESS_CPU)) { WARN("Volume %p is not CPU accessible.\n", volume); return WINED3DERR_INVALIDCALL; } if (volume->resource.map_count) { WARN("Volume is already mapped.\n"); return WINED3DERR_INVALIDCALL; } if (!wined3d_volume_check_box_dimensions(volume, box)) { WARN("Map box is invalid.\n"); return WINED3DERR_INVALIDCALL; } if ((format->flags & WINED3DFMT_FLAG_BLOCKS) && !volume_check_block_align(volume, box)) { WARN("Map box is misaligned for %ux%u blocks.\n", format->block_width, format->block_height); return WINED3DERR_INVALIDCALL; } flags = wined3d_resource_sanitize_map_flags(&volume->resource, flags); if (volume->flags & WINED3D_VFLAG_PBO) { context = context_acquire(device, NULL); gl_info = context->gl_info; wined3d_volume_prepare_pbo(volume, context); if (flags & WINED3D_MAP_DISCARD) wined3d_volume_validate_location(volume, WINED3D_LOCATION_BUFFER); else wined3d_volume_load_location(volume, context, WINED3D_LOCATION_BUFFER); GL_EXTCALL(glBindBufferARB(GL_PIXEL_UNPACK_BUFFER_ARB, volume->pbo)); if (gl_info->supported[ARB_MAP_BUFFER_RANGE]) { GLbitfield mapflags = wined3d_resource_gl_map_flags(flags); mapflags &= ~GL_MAP_FLUSH_EXPLICIT_BIT; base_memory = GL_EXTCALL(glMapBufferRange(GL_PIXEL_UNPACK_BUFFER_ARB, 0, volume->resource.size, mapflags)); } else { GLenum access = wined3d_resource_gl_legacy_map_flags(flags); base_memory = GL_EXTCALL(glMapBufferARB(GL_PIXEL_UNPACK_BUFFER_ARB, access)); } GL_EXTCALL(glBindBufferARB(GL_PIXEL_UNPACK_BUFFER_ARB, 0)); checkGLcall("Map PBO"); context_release(context); } else { if (!volume_prepare_system_memory(volume)) { WARN("Out of memory.\n"); map_desc->data = NULL; return E_OUTOFMEMORY; } if (flags & WINED3D_MAP_DISCARD) { wined3d_volume_validate_location(volume, WINED3D_LOCATION_SYSMEM); } else if (!(volume->locations & WINED3D_LOCATION_SYSMEM)) { context = context_acquire(device, NULL); wined3d_volume_load_location(volume, context, WINED3D_LOCATION_SYSMEM); context_release(context); } base_memory = volume->resource.heap_memory; } TRACE("Base memory pointer %p.\n", base_memory); if (format->flags & WINED3DFMT_FLAG_BROKEN_PITCH) { map_desc->row_pitch = volume->resource.width * format->byte_count; map_desc->slice_pitch = map_desc->row_pitch * volume->resource.height; } else { wined3d_volume_get_pitch(volume, &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 * volume->resource.format->byte_count); } } if (!(flags & (WINED3D_MAP_NO_DIRTY_UPDATE | WINED3D_MAP_READONLY))) { wined3d_texture_set_dirty(volume->container); if (volume->flags & WINED3D_VFLAG_PBO) wined3d_volume_invalidate_location(volume, ~WINED3D_LOCATION_BUFFER); else wined3d_volume_invalidate_location(volume, ~WINED3D_LOCATION_SYSMEM); } volume->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; }