wined3d: Store surface/volume buffer objects in the sub-resource structure.

Signed-off-by: Henri Verbeet <hverbeet@codeweavers.com>
Signed-off-by: Alexandre Julliard <julliard@winehq.org>
This commit is contained in:
Henri Verbeet 2016-03-02 19:24:18 +01:00 committed by Alexandre Julliard
parent 09c862b6a2
commit fbe2737537
4 changed files with 76 additions and 51 deletions

View File

@ -40,13 +40,20 @@ static const DWORD surface_simple_locations =
WINED3D_LOCATION_SYSMEM | WINED3D_LOCATION_USER_MEMORY
| WINED3D_LOCATION_DIB | WINED3D_LOCATION_BUFFER;
static unsigned int surface_get_sub_resource_idx(const struct wined3d_surface *surface)
{
return surface->texture_layer * surface->container->level_count + surface->texture_level;
}
void wined3d_surface_cleanup(struct wined3d_surface *surface)
{
struct wined3d_surface *overlay, *cur;
GLuint buffer_object;
TRACE("surface %p.\n", surface);
if (surface->pbo || surface->rb_multisample
buffer_object = surface->container->sub_resources[surface_get_sub_resource_idx(surface)].buffer_object;
if (buffer_object || surface->rb_multisample
|| surface->rb_resolved || !list_empty(&surface->renderbuffers))
{
struct wined3d_renderbuffer_entry *entry, *entry2;
@ -57,10 +64,10 @@ void wined3d_surface_cleanup(struct wined3d_surface *surface)
context = context_acquire(device, NULL);
gl_info = context->gl_info;
if (surface->pbo)
if (buffer_object)
{
TRACE("Deleting PBO %u.\n", surface->pbo);
GL_EXTCALL(glDeleteBuffers(1, &surface->pbo));
TRACE("Deleting buffer object %u.\n", buffer_object);
GL_EXTCALL(glDeleteBuffers(1, &buffer_object));
}
if (surface->rb_multisample)
@ -464,7 +471,7 @@ static void surface_get_memory(const struct wined3d_surface *surface, struct win
if (location & WINED3D_LOCATION_BUFFER)
{
data->addr = NULL;
data->buffer_object = surface->pbo;
data->buffer_object = surface->container->sub_resources[surface_get_sub_resource_idx(surface)].buffer_object;
return;
}
if (location & WINED3D_LOCATION_USER_MEMORY)
@ -494,23 +501,25 @@ static void surface_get_memory(const struct wined3d_surface *surface, struct win
static void surface_prepare_buffer(struct wined3d_surface *surface)
{
struct wined3d_context *context;
GLuint *buffer_object;
GLenum error;
const struct wined3d_gl_info *gl_info;
if (surface->pbo)
buffer_object = &surface->container->sub_resources[surface_get_sub_resource_idx(surface)].buffer_object;
if (*buffer_object)
return;
context = context_acquire(surface->resource.device, NULL);
gl_info = context->gl_info;
GL_EXTCALL(glGenBuffers(1, &surface->pbo));
GL_EXTCALL(glGenBuffers(1, buffer_object));
error = gl_info->gl_ops.gl.p_glGetError();
if (!surface->pbo || error != GL_NO_ERROR)
if (!*buffer_object || error != GL_NO_ERROR)
ERR("Failed to create a PBO with error %s (%#x).\n", debug_glerror(error), error);
TRACE("Binding PBO %u.\n", surface->pbo);
TRACE("Binding PBO %u.\n", *buffer_object);
GL_EXTCALL(glBindBuffer(GL_PIXEL_UNPACK_BUFFER, surface->pbo));
GL_EXTCALL(glBindBuffer(GL_PIXEL_UNPACK_BUFFER, *buffer_object));
checkGLcall("glBindBuffer");
GL_EXTCALL(glBufferData(GL_PIXEL_UNPACK_BUFFER, surface->resource.size + 4,
@ -1027,10 +1036,13 @@ static HRESULT wined3d_surface_depth_blt(struct wined3d_surface *src_surface, DW
/* Context activation is done by the caller. */
static void surface_remove_pbo(struct wined3d_surface *surface, const struct wined3d_gl_info *gl_info)
{
GL_EXTCALL(glDeleteBuffers(1, &surface->pbo));
checkGLcall("glDeleteBuffers(1, &surface->pbo)");
GLuint *buffer_object;
surface->pbo = 0;
buffer_object = &surface->container->sub_resources[surface_get_sub_resource_idx(surface)].buffer_object;
GL_EXTCALL(glDeleteBuffers(1, buffer_object));
checkGLcall("glDeleteBuffers(1, buffer_object)");
*buffer_object = 0;
surface_invalidate_location(surface, WINED3D_LOCATION_BUFFER);
}
@ -1097,7 +1109,7 @@ static void surface_unload(struct wined3d_resource *resource)
}
/* Destroy PBOs, but load them into real sysmem before */
if (surface->pbo)
if (surface->container->sub_resources[surface_get_sub_resource_idx(surface)].buffer_object)
surface_remove_pbo(surface, gl_info);
/* Destroy fbo render buffers. This is needed for implicit render targets, for
@ -2167,9 +2179,9 @@ do { \
HRESULT wined3d_surface_unmap(struct wined3d_surface *surface)
{
struct wined3d_device *device = surface->resource.device;
struct wined3d_texture *texture = surface->container;
const struct wined3d_gl_info *gl_info;
struct wined3d_context *context;
struct wined3d_texture *texture;
TRACE("surface %p.\n", surface);
@ -2191,7 +2203,8 @@ HRESULT wined3d_surface_unmap(struct wined3d_surface *surface)
context = context_acquire(device, NULL);
gl_info = context->gl_info;
GL_EXTCALL(glBindBuffer(GL_PIXEL_UNPACK_BUFFER, surface->pbo));
GL_EXTCALL(glBindBuffer(GL_PIXEL_UNPACK_BUFFER,
texture->sub_resources[surface_get_sub_resource_idx(surface)].buffer_object));
GL_EXTCALL(glUnmapBuffer(GL_PIXEL_UNPACK_BUFFER));
GL_EXTCALL(glBindBuffer(GL_PIXEL_UNPACK_BUFFER, 0));
checkGLcall("glUnmapBuffer");
@ -2205,7 +2218,6 @@ HRESULT wined3d_surface_unmap(struct wined3d_surface *surface)
if (!(surface->locations & (WINED3D_LOCATION_DRAWABLE | WINED3D_LOCATION_TEXTURE_RGB)))
{
texture = surface->container;
if (texture->swapchain && texture->swapchain->front_buffer == texture)
texture->swapchain->swapchain_ops->swapchain_frontbuffer_updated(texture->swapchain);
else if (texture->resource.format_flags & (WINED3DFMT_FLAG_DEPTH | WINED3DFMT_FLAG_STENCIL))
@ -2307,7 +2319,8 @@ HRESULT wined3d_surface_map(struct wined3d_surface *surface, struct wined3d_map_
context = context_acquire(device, NULL);
gl_info = context->gl_info;
GL_EXTCALL(glBindBuffer(GL_PIXEL_UNPACK_BUFFER, surface->pbo));
GL_EXTCALL(glBindBuffer(GL_PIXEL_UNPACK_BUFFER,
texture->sub_resources[surface_get_sub_resource_idx(surface)].buffer_object));
base_memory = GL_EXTCALL(glMapBuffer(GL_PIXEL_UNPACK_BUFFER, GL_READ_WRITE));
GL_EXTCALL(glBindBuffer(GL_PIXEL_UNPACK_BUFFER, 0));
checkGLcall("map PBO");
@ -3693,7 +3706,8 @@ static HRESULT surface_load_texture(struct wined3d_surface *surface,
/* Don't use PBOs for converted surfaces. During PBO conversion we look at
* WINED3D_TEXTURE_CONVERTED but it isn't set (yet) in all cases it is
* getting called. */
if ((format.convert || conversion) && surface->pbo)
if ((format.convert || conversion)
&& texture->sub_resources[surface_get_sub_resource_idx(surface)].buffer_object)
{
TRACE("Removing the pbo attached to surface %p.\n", surface);

View File

@ -1770,8 +1770,8 @@ HRESULT CDECL wined3d_texture_get_dc(struct wined3d_texture *texture, unsigned i
return WINED3DERR_INVALIDCALL;
}
if (!(surface->resource.map_binding == WINED3D_LOCATION_USER_MEMORY
|| surface->container->flags & WINED3D_TEXTURE_PIN_SYSMEM
|| surface->pbo))
|| texture->flags & WINED3D_TEXTURE_PIN_SYSMEM
|| texture->sub_resources[sub_resource_idx].buffer_object))
surface->resource.map_binding = WINED3D_LOCATION_DIB;
}

View File

@ -214,6 +214,7 @@ static void wined3d_volume_load_location(struct wined3d_volume *volume,
struct wined3d_context *context, DWORD location)
{
DWORD required_access = volume_access_from_location(location);
struct wined3d_texture *texture = volume->container;
TRACE("Volume %p, loading %s, have %s.\n", volume, wined3d_debug_location(location),
wined3d_debug_location(volume->locations));
@ -236,9 +237,9 @@ static void wined3d_volume_load_location(struct wined3d_volume *volume,
case WINED3D_LOCATION_TEXTURE_RGB:
case WINED3D_LOCATION_TEXTURE_SRGB:
if ((location == WINED3D_LOCATION_TEXTURE_RGB
&& !(volume->container->flags & WINED3D_TEXTURE_RGB_ALLOCATED))
&& !(texture->flags & WINED3D_TEXTURE_RGB_ALLOCATED))
|| (location == WINED3D_LOCATION_TEXTURE_SRGB
&& !(volume->container->flags & WINED3D_TEXTURE_SRGB_ALLOCATED)))
&& !(texture->flags & WINED3D_TEXTURE_SRGB_ALLOCATED)))
ERR("Trying to load (s)RGB texture without prior allocation.\n");
if (volume->locations & WINED3D_LOCATION_DISCARDED)
@ -249,14 +250,18 @@ static void wined3d_volume_load_location(struct wined3d_volume *volume,
else if (volume->locations & WINED3D_LOCATION_SYSMEM)
{
struct wined3d_const_bo_address data = {0, volume->resource.heap_memory};
wined3d_texture_bind_and_dirtify(volume->container, context,
wined3d_texture_bind_and_dirtify(texture, context,
location == WINED3D_LOCATION_TEXTURE_SRGB);
wined3d_volume_upload_data(volume, context, &data);
}
else if (volume->locations & WINED3D_LOCATION_BUFFER)
{
struct wined3d_const_bo_address data = {volume->pbo, NULL};
wined3d_texture_bind_and_dirtify(volume->container, context,
struct wined3d_const_bo_address data =
{
texture->sub_resources[volume->texture_level].buffer_object,
NULL
};
wined3d_texture_bind_and_dirtify(texture, context,
location == WINED3D_LOCATION_TEXTURE_SRGB);
wined3d_volume_upload_data(volume, context, &data);
}
@ -294,9 +299,9 @@ static void wined3d_volume_load_location(struct wined3d_volume *volume,
struct wined3d_bo_address data = {0, volume->resource.heap_memory};
if (volume->locations & WINED3D_LOCATION_TEXTURE_RGB)
wined3d_texture_bind_and_dirtify(volume->container, context, FALSE);
wined3d_texture_bind_and_dirtify(texture, context, FALSE);
else
wined3d_texture_bind_and_dirtify(volume->container, context, TRUE);
wined3d_texture_bind_and_dirtify(texture, context, TRUE);
volume->download_count++;
wined3d_volume_download_data(volume, context, &data);
@ -311,7 +316,7 @@ static void wined3d_volume_load_location(struct wined3d_volume *volume,
break;
case WINED3D_LOCATION_BUFFER:
if (!volume->pbo)
if (!texture->sub_resources[volume->texture_level].buffer_object)
ERR("Trying to load WINED3D_LOCATION_BUFFER without setting it up first.\n");
if (volume->locations & WINED3D_LOCATION_DISCARDED)
@ -321,12 +326,16 @@ static void wined3d_volume_load_location(struct wined3d_volume *volume,
}
else if (volume->locations & (WINED3D_LOCATION_TEXTURE_RGB | WINED3D_LOCATION_TEXTURE_SRGB))
{
struct wined3d_bo_address data = {volume->pbo, NULL};
struct wined3d_bo_address data =
{
texture->sub_resources[volume->texture_level].buffer_object,
NULL
};
if (volume->locations & WINED3D_LOCATION_TEXTURE_RGB)
wined3d_texture_bind_and_dirtify(volume->container, context, FALSE);
wined3d_texture_bind_and_dirtify(texture, context, FALSE);
else
wined3d_texture_bind_and_dirtify(volume->container, context, TRUE);
wined3d_texture_bind_and_dirtify(texture, context, TRUE);
wined3d_volume_download_data(volume, context, &data);
}
@ -356,29 +365,31 @@ void wined3d_volume_load(struct wined3d_volume *volume, struct wined3d_context *
/* Context activation is done by the caller. */
static void wined3d_volume_prepare_pbo(struct wined3d_volume *volume, struct wined3d_context *context)
{
GLuint *buffer_object = &volume->container->sub_resources[volume->texture_level].buffer_object;
const struct wined3d_gl_info *gl_info = context->gl_info;
if (volume->pbo)
if (*buffer_object)
return;
GL_EXTCALL(glGenBuffers(1, &volume->pbo));
GL_EXTCALL(glBindBuffer(GL_PIXEL_UNPACK_BUFFER, volume->pbo));
GL_EXTCALL(glGenBuffers(1, buffer_object));
GL_EXTCALL(glBindBuffer(GL_PIXEL_UNPACK_BUFFER, *buffer_object));
GL_EXTCALL(glBufferData(GL_PIXEL_UNPACK_BUFFER, volume->resource.size, NULL, GL_STREAM_DRAW));
GL_EXTCALL(glBindBuffer(GL_PIXEL_UNPACK_BUFFER, 0));
checkGLcall("Create PBO");
TRACE("Created PBO %u for volume %p.\n", volume->pbo, volume);
TRACE("Created PBO %u for volume %p.\n", *buffer_object, volume);
}
static void wined3d_volume_free_pbo(struct wined3d_volume *volume)
{
GLuint *buffer_object = &volume->container->sub_resources[volume->texture_level].buffer_object;
struct wined3d_context *context = context_acquire(volume->resource.device, NULL);
const struct wined3d_gl_info *gl_info = context->gl_info;
TRACE("Deleting PBO %u belonging to volume %p.\n", volume->pbo, volume);
GL_EXTCALL(glDeleteBuffers(1, &volume->pbo));
TRACE("Deleting PBO %u belonging to volume %p.\n", *buffer_object, volume);
GL_EXTCALL(glDeleteBuffers(1, buffer_object));
checkGLcall("glDeleteBuffers");
volume->pbo = 0;
*buffer_object = 0;
context_release(context);
}
@ -386,7 +397,7 @@ void wined3d_volume_cleanup(struct wined3d_volume *volume)
{
TRACE("volume %p.\n", volume);
if (volume->pbo)
if (volume->container->sub_resources[volume->texture_level].buffer_object)
wined3d_volume_free_pbo(volume);
resource_cleanup(&volume->resource);
@ -417,7 +428,7 @@ static void volume_unload(struct wined3d_resource *resource)
wined3d_volume_invalidate_location(volume, ~WINED3D_LOCATION_DISCARDED);
}
if (volume->pbo)
if (volume->container->sub_resources[volume->texture_level].buffer_object)
{
/* Should not happen because only dynamic default pool volumes
* have a buffer, and those are not evicted by device_evit_managed_resources
@ -457,11 +468,12 @@ HRESULT 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_texture *texture = volume->container;
struct wined3d_context *context;
const struct wined3d_gl_info *gl_info;
BYTE *base_memory;
const struct wined3d_format *format = volume->resource.format;
const unsigned int fmt_flags = volume->container->resource.format_flags;
const unsigned int fmt_flags = texture->resource.format_flags;
TRACE("volume %p, map_desc %p, box %s, flags %#x.\n",
volume, map_desc, debug_box(box), flags);
@ -483,7 +495,7 @@ HRESULT wined3d_volume_map(struct wined3d_volume *volume,
return WINED3DERR_INVALIDCALL;
}
if ((fmt_flags & WINED3DFMT_FLAG_BLOCKS) && box
&& !wined3d_texture_check_block_align(volume->container, volume->texture_level, box))
&& !wined3d_texture_check_block_align(texture, volume->texture_level, box))
{
WARN("Map box %s is misaligned for %ux%u blocks.\n",
debug_box(box), format->block_width, format->block_height);
@ -503,7 +515,7 @@ HRESULT wined3d_volume_map(struct wined3d_volume *volume,
else
wined3d_volume_load_location(volume, context, WINED3D_LOCATION_BUFFER);
GL_EXTCALL(glBindBuffer(GL_PIXEL_UNPACK_BUFFER, volume->pbo));
GL_EXTCALL(glBindBuffer(GL_PIXEL_UNPACK_BUFFER, texture->sub_resources[volume->texture_level].buffer_object));
if (gl_info->supported[ARB_MAP_BUFFER_RANGE])
{
@ -554,7 +566,7 @@ HRESULT wined3d_volume_map(struct wined3d_volume *volume,
}
else
{
wined3d_texture_get_pitch(volume->container, volume->texture_level,
wined3d_texture_get_pitch(texture, volume->texture_level,
&map_desc->row_pitch, &map_desc->slice_pitch);
}
@ -584,7 +596,7 @@ HRESULT wined3d_volume_map(struct wined3d_volume *volume,
if (!(flags & (WINED3D_MAP_NO_DIRTY_UPDATE | WINED3D_MAP_READONLY)))
{
wined3d_texture_set_dirty(volume->container);
wined3d_texture_set_dirty(texture);
wined3d_volume_invalidate_location(volume, ~volume->resource.map_binding);
}
@ -612,7 +624,8 @@ HRESULT wined3d_volume_unmap(struct wined3d_volume *volume)
struct wined3d_context *context = context_acquire(device, NULL);
const struct wined3d_gl_info *gl_info = context->gl_info;
GL_EXTCALL(glBindBuffer(GL_PIXEL_UNPACK_BUFFER, volume->pbo));
GL_EXTCALL(glBindBuffer(GL_PIXEL_UNPACK_BUFFER,
volume->container->sub_resources[volume->texture_level].buffer_object));
GL_EXTCALL(glUnmapBuffer(GL_PIXEL_UNPACK_BUFFER));
GL_EXTCALL(glBindBuffer(GL_PIXEL_UNPACK_BUFFER, 0));
checkGLcall("Unmap PBO");

View File

@ -2391,6 +2391,8 @@ struct wined3d_texture
struct wined3d_surface *surface;
struct wined3d_volume *volume;
} u;
GLuint buffer_object;
} sub_resources[1];
};
@ -2445,7 +2447,6 @@ struct wined3d_volume
DWORD locations;
GLint texture_level;
DWORD download_count;
GLuint pbo;
};
static inline struct wined3d_volume *volume_from_resource(struct wined3d_resource *resource)
@ -2521,9 +2522,6 @@ struct wined3d_surface
UINT pow2Width;
UINT pow2Height;
/* PBO */
GLuint pbo;
GLuint rb_multisample;
GLuint rb_resolved;
GLenum texture_target;