wined3d: Store the EXT_fbo "renderbuffers" list in the texture instead of the surface.
Signed-off-by: Henri Verbeet <hverbeet@codeweavers.com> Signed-off-by: Alexandre Julliard <julliard@winehq.org>
This commit is contained in:
parent
6fd5bce038
commit
3d21ea0807
|
@ -445,19 +445,15 @@ static inline void context_set_fbo_key_for_render_target(const struct wined3d_co
|
|||
}
|
||||
|
||||
texture = wined3d_texture_from_resource(resource);
|
||||
if (resource->type == WINED3D_RTYPE_TEXTURE_2D)
|
||||
if (texture->current_renderbuffer)
|
||||
{
|
||||
struct wined3d_surface *surface = texture->sub_resources[sub_resource_idx].u.surface;
|
||||
|
||||
if (surface->current_renderbuffer)
|
||||
{
|
||||
key->objects[idx].object = surface->current_renderbuffer->id;
|
||||
key->objects[idx].target = 0;
|
||||
key->objects[idx].level = key->objects[idx].layer = 0;
|
||||
key->rb_namespace |= 1 << idx;
|
||||
return;
|
||||
}
|
||||
key->objects[idx].object = texture->current_renderbuffer->id;
|
||||
key->objects[idx].target = 0;
|
||||
key->objects[idx].level = key->objects[idx].layer = 0;
|
||||
key->rb_namespace |= 1 << idx;
|
||||
return;
|
||||
}
|
||||
|
||||
key->objects[idx].target = wined3d_texture_get_sub_resource_target(texture, sub_resource_idx);
|
||||
key->objects[idx].level = sub_resource_idx % texture->level_count;
|
||||
key->objects[idx].layer = sub_resource_idx / texture->level_count;
|
||||
|
@ -604,10 +600,7 @@ static struct fbo_entry *context_find_fbo_entry(struct wined3d_context *context,
|
|||
}
|
||||
else if (depth_stencil->resource->type == WINED3D_RTYPE_TEXTURE_2D)
|
||||
{
|
||||
struct wined3d_surface *surface;
|
||||
|
||||
surface = ds_texture->sub_resources[depth_stencil->sub_resource_idx].u.surface;
|
||||
surface_set_compatible_renderbuffer(surface, &render_targets[0]);
|
||||
wined3d_texture_set_compatible_renderbuffer(ds_texture, ds_level, &render_targets[0]);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -975,90 +975,6 @@ static HRESULT surface_upload_from_surface(struct wined3d_surface *dst_surface,
|
|||
return WINED3D_OK;
|
||||
}
|
||||
|
||||
/* In D3D the depth stencil dimensions have to be greater than or equal to the
|
||||
* render target dimensions. With FBOs, the dimensions have to be an exact match. */
|
||||
/* TODO: We should synchronize the renderbuffer's content with the texture's content. */
|
||||
/* Context activation is done by the caller. */
|
||||
void surface_set_compatible_renderbuffer(struct wined3d_surface *surface, const struct wined3d_rendertarget_info *rt)
|
||||
{
|
||||
unsigned int sub_resource_idx, width, height, level;
|
||||
struct wined3d_renderbuffer_entry *entry;
|
||||
const struct wined3d_texture *texture;
|
||||
const struct wined3d_gl_info *gl_info;
|
||||
unsigned int src_width, src_height;
|
||||
GLuint renderbuffer = 0;
|
||||
|
||||
texture = surface->container;
|
||||
gl_info = &texture->resource.device->adapter->gl_info;
|
||||
sub_resource_idx = surface_get_sub_resource_idx(surface);
|
||||
level = sub_resource_idx % texture->level_count;
|
||||
|
||||
if (rt && rt->resource->format->id != WINED3DFMT_NULL)
|
||||
{
|
||||
struct wined3d_texture *rt_texture;
|
||||
unsigned int rt_level;
|
||||
|
||||
if (rt->resource->type == WINED3D_RTYPE_BUFFER)
|
||||
{
|
||||
FIXME("Unsupported resource type %s.\n", debug_d3dresourcetype(rt->resource->type));
|
||||
return;
|
||||
}
|
||||
rt_texture = wined3d_texture_from_resource(rt->resource);
|
||||
rt_level = rt->sub_resource_idx % rt_texture->level_count;
|
||||
|
||||
width = wined3d_texture_get_level_pow2_width(rt_texture, rt_level);
|
||||
height = wined3d_texture_get_level_pow2_height(rt_texture, rt_level);
|
||||
}
|
||||
else
|
||||
{
|
||||
width = wined3d_texture_get_level_pow2_width(texture, level);
|
||||
height = wined3d_texture_get_level_pow2_height(texture, level);
|
||||
}
|
||||
|
||||
src_width = wined3d_texture_get_level_pow2_width(texture, level);
|
||||
src_height = wined3d_texture_get_level_pow2_height(texture, level);
|
||||
|
||||
/* A depth stencil smaller than the render target is not valid */
|
||||
if (width > src_width || height > src_height) return;
|
||||
|
||||
/* Remove any renderbuffer set if the sizes match */
|
||||
if (gl_info->supported[ARB_FRAMEBUFFER_OBJECT]
|
||||
|| (width == src_width && height == src_height))
|
||||
{
|
||||
surface->current_renderbuffer = NULL;
|
||||
return;
|
||||
}
|
||||
|
||||
/* Look if we've already got a renderbuffer of the correct dimensions */
|
||||
LIST_FOR_EACH_ENTRY(entry, &surface->renderbuffers, struct wined3d_renderbuffer_entry, entry)
|
||||
{
|
||||
if (entry->width == width && entry->height == height)
|
||||
{
|
||||
renderbuffer = entry->id;
|
||||
surface->current_renderbuffer = entry;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (!renderbuffer)
|
||||
{
|
||||
gl_info->fbo_ops.glGenRenderbuffers(1, &renderbuffer);
|
||||
gl_info->fbo_ops.glBindRenderbuffer(GL_RENDERBUFFER, renderbuffer);
|
||||
gl_info->fbo_ops.glRenderbufferStorage(GL_RENDERBUFFER,
|
||||
texture->resource.format->glInternal, width, height);
|
||||
|
||||
entry = heap_alloc(sizeof(*entry));
|
||||
entry->width = width;
|
||||
entry->height = height;
|
||||
entry->id = renderbuffer;
|
||||
list_add_head(&surface->renderbuffers, &entry->entry);
|
||||
|
||||
surface->current_renderbuffer = entry;
|
||||
}
|
||||
|
||||
checkGLcall("set_compatible_renderbuffer");
|
||||
}
|
||||
|
||||
/* See also float_16_to_32() in wined3d_private.h */
|
||||
static inline unsigned short float_32_to_16(const float *in)
|
||||
{
|
||||
|
|
|
@ -418,6 +418,8 @@ static HRESULT wined3d_texture_init(struct wined3d_texture *texture, const struc
|
|||
texture->flags |= WINED3D_TEXTURE_GENERATE_MIPMAPS;
|
||||
}
|
||||
|
||||
list_init(&texture->renderbuffers);
|
||||
|
||||
return WINED3D_OK;
|
||||
}
|
||||
|
||||
|
@ -654,8 +656,9 @@ static void wined3d_texture_cleanup(struct wined3d_texture *texture)
|
|||
{
|
||||
unsigned int sub_count = texture->level_count * texture->layer_count;
|
||||
struct wined3d_device *device = texture->resource.device;
|
||||
struct wined3d_renderbuffer_entry *entry, *entry2;
|
||||
const struct wined3d_gl_info *gl_info = NULL;
|
||||
struct wined3d_context *context = NULL;
|
||||
const struct wined3d_gl_info *gl_info;
|
||||
GLuint buffer_object;
|
||||
unsigned int i;
|
||||
|
||||
|
@ -678,6 +681,21 @@ static void wined3d_texture_cleanup(struct wined3d_texture *texture)
|
|||
|
||||
GL_EXTCALL(glDeleteBuffers(1, &buffer_object));
|
||||
}
|
||||
|
||||
if (!context && !list_empty(&texture->renderbuffers))
|
||||
{
|
||||
context = context_acquire(device, NULL, 0);
|
||||
gl_info = context->gl_info;
|
||||
}
|
||||
|
||||
LIST_FOR_EACH_ENTRY_SAFE(entry, entry2, &texture->renderbuffers, struct wined3d_renderbuffer_entry, entry)
|
||||
{
|
||||
TRACE("Deleting renderbuffer %u.\n", entry->id);
|
||||
context_gl_resource_released(device, entry->id, TRUE);
|
||||
gl_info->fbo_ops.glDeleteRenderbuffers(1, &entry->id);
|
||||
heap_free(entry);
|
||||
}
|
||||
|
||||
if (context)
|
||||
context_release(context);
|
||||
|
||||
|
@ -1233,6 +1251,89 @@ HRESULT CDECL wined3d_texture_set_color_key(struct wined3d_texture *texture,
|
|||
return WINED3D_OK;
|
||||
}
|
||||
|
||||
/* In D3D the depth stencil dimensions have to be greater than or equal to the
|
||||
* render target dimensions. With FBOs, the dimensions have to be an exact match. */
|
||||
/* TODO: We should synchronize the renderbuffer's content with the texture's content. */
|
||||
/* Context activation is done by the caller. */
|
||||
void wined3d_texture_set_compatible_renderbuffer(struct wined3d_texture *texture,
|
||||
unsigned int level, const struct wined3d_rendertarget_info *rt)
|
||||
{
|
||||
struct wined3d_renderbuffer_entry *entry;
|
||||
const struct wined3d_gl_info *gl_info;
|
||||
unsigned int src_width, src_height;
|
||||
unsigned int width, height;
|
||||
GLuint renderbuffer = 0;
|
||||
|
||||
gl_info = &texture->resource.device->adapter->gl_info;
|
||||
if (gl_info->supported[ARB_FRAMEBUFFER_OBJECT])
|
||||
return;
|
||||
|
||||
if (rt && rt->resource->format->id != WINED3DFMT_NULL)
|
||||
{
|
||||
struct wined3d_texture *rt_texture;
|
||||
unsigned int rt_level;
|
||||
|
||||
if (rt->resource->type == WINED3D_RTYPE_BUFFER)
|
||||
{
|
||||
FIXME("Unsupported resource type %s.\n", debug_d3dresourcetype(rt->resource->type));
|
||||
return;
|
||||
}
|
||||
rt_texture = wined3d_texture_from_resource(rt->resource);
|
||||
rt_level = rt->sub_resource_idx % rt_texture->level_count;
|
||||
|
||||
width = wined3d_texture_get_level_pow2_width(rt_texture, rt_level);
|
||||
height = wined3d_texture_get_level_pow2_height(rt_texture, rt_level);
|
||||
}
|
||||
else
|
||||
{
|
||||
width = wined3d_texture_get_level_pow2_width(texture, level);
|
||||
height = wined3d_texture_get_level_pow2_height(texture, level);
|
||||
}
|
||||
|
||||
src_width = wined3d_texture_get_level_pow2_width(texture, level);
|
||||
src_height = wined3d_texture_get_level_pow2_height(texture, level);
|
||||
|
||||
/* A depth stencil smaller than the render target is not valid */
|
||||
if (width > src_width || height > src_height)
|
||||
return;
|
||||
|
||||
/* Remove any renderbuffer set if the sizes match */
|
||||
if (width == src_width && height == src_height)
|
||||
{
|
||||
texture->current_renderbuffer = NULL;
|
||||
return;
|
||||
}
|
||||
|
||||
/* Look if we've already got a renderbuffer of the correct dimensions */
|
||||
LIST_FOR_EACH_ENTRY(entry, &texture->renderbuffers, struct wined3d_renderbuffer_entry, entry)
|
||||
{
|
||||
if (entry->width == width && entry->height == height)
|
||||
{
|
||||
renderbuffer = entry->id;
|
||||
texture->current_renderbuffer = entry;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (!renderbuffer)
|
||||
{
|
||||
gl_info->fbo_ops.glGenRenderbuffers(1, &renderbuffer);
|
||||
gl_info->fbo_ops.glBindRenderbuffer(GL_RENDERBUFFER, renderbuffer);
|
||||
gl_info->fbo_ops.glRenderbufferStorage(GL_RENDERBUFFER,
|
||||
texture->resource.format->glInternal, width, height);
|
||||
|
||||
entry = heap_alloc(sizeof(*entry));
|
||||
entry->width = width;
|
||||
entry->height = height;
|
||||
entry->id = renderbuffer;
|
||||
list_add_head(&texture->renderbuffers, &entry->entry);
|
||||
|
||||
texture->current_renderbuffer = entry;
|
||||
}
|
||||
|
||||
checkGLcall("set_compatible_renderbuffer");
|
||||
}
|
||||
|
||||
static void texture2d_create_dc(void *object)
|
||||
{
|
||||
struct wined3d_surface *surface = object;
|
||||
|
@ -1738,10 +1839,7 @@ static void texture2d_prepare_texture(struct wined3d_texture *texture, struct wi
|
|||
static void texture2d_cleanup_sub_resources(struct wined3d_texture *texture)
|
||||
{
|
||||
unsigned int sub_count = texture->level_count * texture->layer_count;
|
||||
struct wined3d_device *device = texture->resource.device;
|
||||
struct wined3d_texture_sub_resource *sub_resource;
|
||||
struct wined3d_renderbuffer_entry *entry, *entry2;
|
||||
const struct wined3d_gl_info *gl_info = NULL;
|
||||
struct wined3d_context *context = NULL;
|
||||
struct wined3d_surface *surface;
|
||||
unsigned int i;
|
||||
|
@ -1754,20 +1852,6 @@ static void texture2d_cleanup_sub_resources(struct wined3d_texture *texture)
|
|||
|
||||
TRACE("surface %p.\n", surface);
|
||||
|
||||
if (!context && !list_empty(&surface->renderbuffers))
|
||||
{
|
||||
context = context_acquire(device, NULL, 0);
|
||||
gl_info = context->gl_info;
|
||||
}
|
||||
|
||||
LIST_FOR_EACH_ENTRY_SAFE(entry, entry2, &surface->renderbuffers, struct wined3d_renderbuffer_entry, entry)
|
||||
{
|
||||
TRACE("Deleting renderbuffer %u.\n", entry->id);
|
||||
context_gl_resource_released(device, entry->id, TRUE);
|
||||
gl_info->fbo_ops.glDeleteRenderbuffers(1, &entry->id);
|
||||
heap_free(entry);
|
||||
}
|
||||
|
||||
if (surface->dc)
|
||||
texture2d_destroy_dc(surface);
|
||||
}
|
||||
|
@ -1813,6 +1897,7 @@ static void wined3d_texture_unload(struct wined3d_resource *resource)
|
|||
{
|
||||
struct wined3d_texture *texture = texture_from_resource(resource);
|
||||
UINT sub_count = texture->level_count * texture->layer_count;
|
||||
struct wined3d_renderbuffer_entry *entry, *entry2;
|
||||
struct wined3d_device *device = resource->device;
|
||||
const struct wined3d_gl_info *gl_info;
|
||||
struct wined3d_context *context;
|
||||
|
@ -1847,24 +1932,18 @@ static void wined3d_texture_unload(struct wined3d_resource *resource)
|
|||
|
||||
if (sub_resource->buffer_object)
|
||||
wined3d_texture_remove_buffer_object(texture, i, context->gl_info);
|
||||
|
||||
if (resource->type == WINED3D_RTYPE_TEXTURE_2D)
|
||||
{
|
||||
struct wined3d_surface *surface = sub_resource->u.surface;
|
||||
struct wined3d_renderbuffer_entry *entry, *entry2;
|
||||
|
||||
LIST_FOR_EACH_ENTRY_SAFE(entry, entry2, &surface->renderbuffers, struct wined3d_renderbuffer_entry, entry)
|
||||
{
|
||||
context_gl_resource_released(device, entry->id, TRUE);
|
||||
gl_info->fbo_ops.glDeleteRenderbuffers(1, &entry->id);
|
||||
list_remove(&entry->entry);
|
||||
heap_free(entry);
|
||||
}
|
||||
list_init(&surface->renderbuffers);
|
||||
surface->current_renderbuffer = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
LIST_FOR_EACH_ENTRY_SAFE(entry, entry2, &texture->renderbuffers, struct wined3d_renderbuffer_entry, entry)
|
||||
{
|
||||
context_gl_resource_released(device, entry->id, TRUE);
|
||||
gl_info->fbo_ops.glDeleteRenderbuffers(1, &entry->id);
|
||||
list_remove(&entry->entry);
|
||||
heap_free(entry);
|
||||
}
|
||||
list_init(&texture->renderbuffers);
|
||||
texture->current_renderbuffer = NULL;
|
||||
|
||||
context_release(context);
|
||||
|
||||
wined3d_texture_force_reload(texture);
|
||||
|
@ -2247,7 +2326,6 @@ static HRESULT texture_init(struct wined3d_texture *texture, const struct wined3
|
|||
surface->container = texture;
|
||||
surface->texture_level = i;
|
||||
surface->texture_layer = j;
|
||||
list_init(&surface->renderbuffers);
|
||||
|
||||
sub_resource = &texture->sub_resources[idx];
|
||||
sub_resource->locations = WINED3D_LOCATION_DISCARDED;
|
||||
|
|
|
@ -3155,6 +3155,9 @@ struct wined3d_texture
|
|||
RECT dst_rect;
|
||||
} *overlay_info;
|
||||
|
||||
struct list renderbuffers;
|
||||
const struct wined3d_renderbuffer_entry *current_renderbuffer;
|
||||
|
||||
struct wined3d_texture_sub_resource
|
||||
{
|
||||
void *parent;
|
||||
|
@ -3252,6 +3255,8 @@ BOOL wined3d_texture_prepare_location(struct wined3d_texture *texture, unsigned
|
|||
struct wined3d_context *context, DWORD location) DECLSPEC_HIDDEN;
|
||||
void wined3d_texture_prepare_texture(struct wined3d_texture *texture,
|
||||
struct wined3d_context *context, BOOL srgb) DECLSPEC_HIDDEN;
|
||||
void wined3d_texture_set_compatible_renderbuffer(struct wined3d_texture *texture,
|
||||
unsigned int level, const struct wined3d_rendertarget_info *rt) DECLSPEC_HIDDEN;
|
||||
void wined3d_texture_set_map_binding(struct wined3d_texture *texture, DWORD map_binding) DECLSPEC_HIDDEN;
|
||||
void wined3d_texture_set_swapchain(struct wined3d_texture *texture,
|
||||
struct wined3d_swapchain *swapchain) DECLSPEC_HIDDEN;
|
||||
|
@ -3317,9 +3322,6 @@ struct wined3d_surface
|
|||
/* For GetDC */
|
||||
HBITMAP bitmap;
|
||||
HDC dc;
|
||||
|
||||
struct list renderbuffers;
|
||||
const struct wined3d_renderbuffer_entry *current_renderbuffer;
|
||||
};
|
||||
|
||||
static inline unsigned int surface_get_sub_resource_idx(const struct wined3d_surface *surface)
|
||||
|
@ -3339,8 +3341,6 @@ void surface_load_fb_texture(struct wined3d_surface *surface, BOOL srgb,
|
|||
struct wined3d_context *context) DECLSPEC_HIDDEN;
|
||||
BOOL surface_load_location(struct wined3d_surface *surface,
|
||||
struct wined3d_context *context, DWORD location) DECLSPEC_HIDDEN;
|
||||
void surface_set_compatible_renderbuffer(struct wined3d_surface *surface,
|
||||
const struct wined3d_rendertarget_info *rt) DECLSPEC_HIDDEN;
|
||||
void wined3d_surface_upload_data(struct wined3d_texture *texture, unsigned int sub_resource_idx,
|
||||
const struct wined3d_gl_info *gl_info, const struct wined3d_format *format, const RECT *src_rect,
|
||||
unsigned int src_pitch, const POINT *dst_point, BOOL srgb,
|
||||
|
|
Loading…
Reference in New Issue