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:
parent
09c862b6a2
commit
fbe2737537
|
@ -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);
|
||||
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
@ -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");
|
||||
|
|
|
@ -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;
|
||||
|
|
Loading…
Reference in New Issue