From: Stefan Dösinger Subject: [PATCH 2/6] wined3d: Keep track of FBOs through the GL names (v2). Message-Id: <1446042562-27871-2-git-send-email-stefan@codeweavers.com> Date: Wed, 28 Oct 2015 15:29:18 +0100 In-Reply-To: <1446042562-27871-1-git-send-email-stefan@codeweavers.com> References: <1446042562-27871-1-git-send-email-stefan@codeweavers.com> Version 2: Don't use fbo_entry->d3d_* for logging, plan for it to go away. The disadvantage is now that we don't know the d3d properties once we find out that an FBO doesn't work and need a full TRACE log for this information, but I think that's something we can live with. If there is a prettier way to find the texture target of a GL texture name please advise. I couldn't find any. Signed-off-by: Stefan Dösinger --- dlls/wined3d/context.c | 393 +++++++++++++++++++++++++++-------------- dlls/wined3d/wined3d_private.h | 17 +- 2 files changed, 279 insertions(+), 131 deletions(-) diff --git a/dlls/wined3d/context.c b/dlls/wined3d/context.c index 978f7d7..2bd9eb0 100644 --- a/dlls/wined3d/context.c +++ b/dlls/wined3d/context.c @@ -120,57 +120,39 @@ static void context_attach_depth_stencil_rb(const struct wined3d_gl_info *gl_inf /* Context activation is done by the caller. */ static void context_attach_depth_stencil_fbo(struct wined3d_context *context, - GLenum fbo_target, struct wined3d_surface *depth_stencil, DWORD location) + GLenum fbo_target, const struct wined3d_fbo_resource *resource, BOOL rb_namespace, + DWORD format_flags, GLuint rb_override) { const struct wined3d_gl_info *gl_info = context->gl_info; - TRACE("Attach depth stencil %p\n", depth_stencil); - - if (depth_stencil) + if (resource->object) { - DWORD format_flags = depth_stencil->container->resource.format_flags; + TRACE("Attach depth stencil %u.\n", resource->object); - if (depth_stencil->current_renderbuffer) + if (rb_override) { context_attach_depth_stencil_rb(gl_info, fbo_target, - format_flags, depth_stencil->current_renderbuffer->id); + format_flags, rb_override); + } + else if (rb_namespace) + { + context_attach_depth_stencil_rb(gl_info, fbo_target, + format_flags, resource->object); } else { - switch (location) + if (format_flags & WINED3DFMT_FLAG_DEPTH) { - case WINED3D_LOCATION_TEXTURE_RGB: - case WINED3D_LOCATION_TEXTURE_SRGB: - if (format_flags & WINED3DFMT_FLAG_DEPTH) - { - gl_info->fbo_ops.glFramebufferTexture2D(fbo_target, GL_DEPTH_ATTACHMENT, - depth_stencil->texture_target, depth_stencil->container->texture_rgb.name, - depth_stencil->texture_level); - checkGLcall("glFramebufferTexture2D()"); - } - - if (format_flags & WINED3DFMT_FLAG_STENCIL) - { - gl_info->fbo_ops.glFramebufferTexture2D(fbo_target, GL_STENCIL_ATTACHMENT, - depth_stencil->texture_target, depth_stencil->container->texture_rgb.name, - depth_stencil->texture_level); - checkGLcall("glFramebufferTexture2D()"); - } - break; - - case WINED3D_LOCATION_RB_MULTISAMPLE: - context_attach_depth_stencil_rb(gl_info, fbo_target, - format_flags, depth_stencil->rb_multisample); - break; - - case WINED3D_LOCATION_RB_RESOLVED: - context_attach_depth_stencil_rb(gl_info, fbo_target, - format_flags, depth_stencil->rb_resolved); - break; + gl_info->fbo_ops.glFramebufferTexture2D(fbo_target, GL_DEPTH_ATTACHMENT, + resource->target, resource->object, resource->level); + checkGLcall("glFramebufferTexture2D()"); + } - default: - ERR("Unsupported location %s (%#x).\n", wined3d_debug_location(location), location); - break; + if (format_flags & WINED3DFMT_FLAG_STENCIL) + { + gl_info->fbo_ops.glFramebufferTexture2D(fbo_target, GL_STENCIL_ATTACHMENT, + resource->target, resource->object, resource->level); + checkGLcall("glFramebufferTexture2D()"); } } @@ -188,6 +170,8 @@ static void context_attach_depth_stencil_fbo(struct wined3d_context *context, } else { + TRACE("Attach depth stencil 0.\n"); + gl_info->fbo_ops.glFramebufferTexture2D(fbo_target, GL_DEPTH_ATTACHMENT, GL_TEXTURE_2D, 0, 0); checkGLcall("glFramebufferTexture2D()"); @@ -198,42 +182,26 @@ static void context_attach_depth_stencil_fbo(struct wined3d_context *context, /* Context activation is done by the caller. */ static void context_attach_surface_fbo(struct wined3d_context *context, - GLenum fbo_target, DWORD idx, struct wined3d_surface *surface, DWORD location) + GLenum fbo_target, DWORD idx, const struct wined3d_fbo_resource *resource, BOOL rb_namespace) { const struct wined3d_gl_info *gl_info = context->gl_info; - TRACE("Attach surface %p to %u\n", surface, idx); + TRACE("Attach GL object %u to %u.\n", resource->object, idx); - if (surface && surface->resource.format->id != WINED3DFMT_NULL) + if (resource->object) { - BOOL srgb; - switch (location) + if (rb_namespace) { - case WINED3D_LOCATION_TEXTURE_RGB: - case WINED3D_LOCATION_TEXTURE_SRGB: - srgb = location == WINED3D_LOCATION_TEXTURE_SRGB; - gl_info->fbo_ops.glFramebufferTexture2D(fbo_target, GL_COLOR_ATTACHMENT0 + idx, - surface->texture_target, surface_get_texture_name(surface, gl_info, srgb), - surface->texture_level); - checkGLcall("glFramebufferTexture2D()"); - break; - - case WINED3D_LOCATION_RB_MULTISAMPLE: - gl_info->fbo_ops.glFramebufferRenderbuffer(fbo_target, GL_COLOR_ATTACHMENT0 + idx, - GL_RENDERBUFFER, surface->rb_multisample); - checkGLcall("glFramebufferRenderbuffer()"); - break; - - case WINED3D_LOCATION_RB_RESOLVED: - gl_info->fbo_ops.glFramebufferRenderbuffer(fbo_target, GL_COLOR_ATTACHMENT0 + idx, - GL_RENDERBUFFER, surface->rb_resolved); - checkGLcall("glFramebufferRenderbuffer()"); - break; - - default: - ERR("Unsupported location %s (%#x).\n", wined3d_debug_location(location), location); - break; + gl_info->fbo_ops.glFramebufferRenderbuffer(fbo_target, GL_COLOR_ATTACHMENT0 + idx, + GL_RENDERBUFFER, resource->object); + checkGLcall("glFramebufferRenderbuffer()"); + } + else + { + gl_info->fbo_ops.glFramebufferTexture2D(fbo_target, GL_COLOR_ATTACHMENT0 + idx, + resource->target, resource->object, resource->level); + checkGLcall("glFramebufferTexture2D()"); } } else @@ -243,6 +211,94 @@ static void context_attach_surface_fbo(struct wined3d_context *context, } } +static void context_dump_fbo_attachment(const struct wined3d_gl_info *gl_info, GLenum target, + GLenum attachment, const char *name_string) +{ + GLint type, name, samples, width, height, old_texture, level, face, fmt, tex_target; + + gl_info->fbo_ops.glGetFramebufferAttachmentParameteriv(target, attachment, + GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME, &name); + gl_info->fbo_ops.glGetFramebufferAttachmentParameteriv(target, attachment, + GL_FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE, &type); + + if (type == GL_RENDERBUFFER) + { + gl_info->fbo_ops.glBindRenderbuffer(GL_RENDERBUFFER, name); + gl_info->fbo_ops.glGetRenderbufferParameteriv(GL_RENDERBUFFER, GL_RENDERBUFFER_WIDTH, &width); + gl_info->fbo_ops.glGetRenderbufferParameteriv(GL_RENDERBUFFER, GL_RENDERBUFFER_HEIGHT, &height); + if (gl_info->supported[EXT_FRAMEBUFFER_MULTISAMPLE]) + gl_info->fbo_ops.glGetRenderbufferParameteriv(GL_RENDERBUFFER, GL_RENDERBUFFER_SAMPLES, &samples); + else + samples = 1; + gl_info->fbo_ops.glGetRenderbufferParameteriv(GL_RENDERBUFFER, GL_RENDERBUFFER_INTERNAL_FORMAT, &fmt); + FIXME("\t%s: renderbuffer %d, %dx%d, %d samples, format %x.\n", + name_string, name, width, height, samples, fmt); + } + else if (type == GL_TEXTURE) + { + const char *tex_type_str; + + gl_info->fbo_ops.glGetFramebufferAttachmentParameteriv(target, attachment, + GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LEVEL, &level); + gl_info->fbo_ops.glGetFramebufferAttachmentParameteriv(target, attachment, + GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_CUBE_MAP_FACE, &face); + + if (face) + { + gl_info->gl_ops.gl.p_glGetIntegerv(GL_TEXTURE_BINDING_CUBE_MAP, &old_texture); + + glBindTexture(GL_TEXTURE_CUBE_MAP, name); + glGetTexLevelParameteriv(face, level, GL_TEXTURE_INTERNAL_FORMAT, &fmt); + glGetTexLevelParameteriv(face, level, GL_TEXTURE_WIDTH, &width); + glGetTexLevelParameteriv(face, level, GL_TEXTURE_HEIGHT, &height); + + tex_target = GL_TEXTURE_CUBE_MAP; + tex_type_str = "cube"; + } + else + { + gl_info->gl_ops.gl.p_glGetIntegerv(GL_TEXTURE_BINDING_2D, &old_texture); + while (gl_info->gl_ops.gl.p_glGetError()); + + glBindTexture(GL_TEXTURE_2D, name); + if (!gl_info->gl_ops.gl.p_glGetError()) + { + tex_target = GL_TEXTURE_2D; + tex_type_str = "2d"; + } + else + { + glBindTexture(GL_TEXTURE_2D, old_texture); + gl_info->gl_ops.gl.p_glGetIntegerv(GL_TEXTURE_BINDING_RECTANGLE_ARB, &old_texture); + + glBindTexture(GL_TEXTURE_RECTANGLE_ARB, name); + if (gl_info->gl_ops.gl.p_glGetError()) + { + glBindTexture(GL_TEXTURE_RECTANGLE_ARB, old_texture); + FIXME("Cannot find type of texture %d.\n", name); + return; + } + tex_target = GL_TEXTURE_RECTANGLE_ARB; + tex_type_str = "rectangle"; + } + + glGetTexLevelParameteriv(tex_target, level, GL_TEXTURE_INTERNAL_FORMAT, &fmt); + glGetTexLevelParameteriv(tex_target, level, GL_TEXTURE_WIDTH, &width); + glGetTexLevelParameteriv(tex_target, level, GL_TEXTURE_HEIGHT, &height); + } + + FIXME("\t%s: %s texture %d, %dx%d, format %x.\n", name_string, tex_type_str, name, width, height, fmt); + + glBindTexture(tex_target, old_texture); + } + else if (type == GL_NONE) + { + FIXME("\t%s: NONE.\n", name_string); + } + else + ERR("\t%s: Unknown attachment %x.\n", name_string, type); +} + /* Context activation is done by the caller. */ void context_check_fbo_status(const struct wined3d_context *context, GLenum target) { @@ -258,7 +314,6 @@ void context_check_fbo_status(const struct wined3d_context *context, GLenum targ } else { - const struct wined3d_surface *attachment; unsigned int i; FIXME("FBO status %s (%#x)\n", debug_fbostatus(status), status); @@ -269,29 +324,16 @@ void context_check_fbo_status(const struct wined3d_context *context, GLenum targ return; } - FIXME("\tColor Location %s (%#x).\n", wined3d_debug_location(context->current_fbo->color_location), - context->current_fbo->color_location); - FIXME("\tDepth Stencil Location %s (%#x).\n", wined3d_debug_location(context->current_fbo->ds_location), - context->current_fbo->ds_location); + context_dump_fbo_attachment(gl_info, target, GL_DEPTH_ATTACHMENT, "Depth attachment"); + context_dump_fbo_attachment(gl_info, target, GL_STENCIL_ATTACHMENT, "Stencil attachment"); - /* Dump the FBO attachments */ for (i = 0; i < gl_info->limits.buffers; ++i) { - attachment = context->current_fbo->render_targets[i]; - if (attachment) - { - FIXME("\tColor attachment %d: (%p) %s %ux%u %u samples.\n", - i, attachment, debug_d3dformat(attachment->resource.format->id), - attachment->pow2Width, attachment->pow2Height, attachment->resource.multisample_type); - } - } - attachment = context->current_fbo->depth_stencil; - if (attachment) - { - FIXME("\tDepth attachment: (%p) %s %ux%u %u samples.\n", - attachment, debug_d3dformat(attachment->resource.format->id), - attachment->pow2Width, attachment->pow2Height, attachment->resource.multisample_type); + char name[32]; + sprintf(name, "Color attachment %u", i); + context_dump_fbo_attachment(gl_info, target, GL_COLOR_ATTACHMENT0 + i, name); } + checkGLcall("Dump FBO attachments"); } } @@ -306,19 +348,74 @@ static inline DWORD context_generate_rt_mask_from_surface(const struct wined3d_s return (1u << 31) | surface_get_gl_buffer(target); } +static inline void context_set_fbo_key_for_surface(struct wined3d_fbo_entry_key *key, UINT idx, + struct wined3d_surface *surface, DWORD location) +{ + if (!surface) + { + key->objects[idx].object = 0; + key->objects[idx].level = key->objects[idx].target = 0; + } + else + { + switch (location) + { + case WINED3D_LOCATION_TEXTURE_RGB: + key->objects[idx].object = surface->container->texture_rgb.name; + key->objects[idx].level = surface->texture_level; + key->objects[idx].target = surface->texture_target; + break; + + case WINED3D_LOCATION_TEXTURE_SRGB: + key->objects[idx].object = surface->container->texture_srgb.name; + key->objects[idx].level = surface->texture_level; + key->objects[idx].target = surface->texture_target; + break; + + case WINED3D_LOCATION_RB_MULTISAMPLE: + key->objects[idx].object = surface->rb_multisample; + key->objects[idx].level = key->objects[idx].target = 0; + key->rb_namespace |= 1 << idx; + break; + + case WINED3D_LOCATION_RB_RESOLVED: + key->objects[idx].object = surface->rb_resolved; + key->objects[idx].level = key->objects[idx].target = 0; + key->rb_namespace |= 1 << idx; + break; + } + } +} + +static inline void context_create_fbo_key(struct wined3d_fbo_entry_key *key, + struct wined3d_surface **render_targets, struct wined3d_surface *depth_stencil, + DWORD color_location, DWORD ds_location, UINT color_buffers) +{ + UINT i; + + key->rb_namespace = 0; + context_set_fbo_key_for_surface(key, 0, depth_stencil, ds_location); + + for (i = 0; i < color_buffers; ++i) + context_set_fbo_key_for_surface(key, i + 1, render_targets[i], color_location); +} + static struct fbo_entry *context_create_fbo_entry(const struct wined3d_context *context, struct wined3d_surface **render_targets, struct wined3d_surface *depth_stencil, DWORD color_location, DWORD ds_location) { const struct wined3d_gl_info *gl_info = context->gl_info; struct fbo_entry *entry; - - entry = HeapAlloc(GetProcessHeap(), 0, sizeof(*entry)); - entry->render_targets = HeapAlloc(GetProcessHeap(), 0, gl_info->limits.buffers * sizeof(*entry->render_targets)); - memcpy(entry->render_targets, render_targets, gl_info->limits.buffers * sizeof(*entry->render_targets)); - entry->depth_stencil = depth_stencil; - entry->color_location = color_location; - entry->ds_location = ds_location; + UINT object_count = gl_info->limits.buffers + 1; + + entry = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, + FIELD_OFFSET(struct fbo_entry, key.objects[object_count])); + entry->d3d_render_targets = HeapAlloc(GetProcessHeap(), 0, + gl_info->limits.buffers * sizeof(*entry->d3d_render_targets)); + context_create_fbo_key(&entry->key, render_targets, depth_stencil, color_location, ds_location, + gl_info->limits.buffers); + memcpy(entry->d3d_render_targets, render_targets, sizeof(*entry->d3d_render_targets) * gl_info->limits.buffers); + entry->d3d_depth_stencil = depth_stencil; entry->rt_mask = context_generate_rt_mask(GL_COLOR_ATTACHMENT0); entry->attached = FALSE; gl_info->fbo_ops.glGenFramebuffers(1, &entry->id); @@ -338,10 +435,10 @@ static void context_reuse_fbo_entry(struct wined3d_context *context, GLenum targ context_bind_fbo(context, target, entry->id); context_clean_fbo_attachments(gl_info, target); - memcpy(entry->render_targets, render_targets, gl_info->limits.buffers * sizeof(*entry->render_targets)); - entry->depth_stencil = depth_stencil; - entry->color_location = color_location; - entry->ds_location = ds_location; + context_create_fbo_key(&entry->key, render_targets, depth_stencil, color_location, ds_location, + gl_info->limits.buffers); + memcpy(entry->d3d_render_targets, render_targets, sizeof(*entry->d3d_render_targets) * gl_info->limits.buffers); + entry->d3d_depth_stencil = depth_stencil; entry->attached = FALSE; } @@ -355,7 +452,7 @@ static void context_destroy_fbo_entry(struct wined3d_context *context, struct fb } --context->fbo_entry_count; list_remove(&entry->entry); - HeapFree(GetProcessHeap(), 0, entry->render_targets); + HeapFree(GetProcessHeap(), 0, entry->d3d_render_targets); HeapFree(GetProcessHeap(), 0, entry); } @@ -366,6 +463,8 @@ static struct fbo_entry *context_find_fbo_entry(struct wined3d_context *context, { const struct wined3d_gl_info *gl_info = context->gl_info; struct fbo_entry *entry; + UINT object_count = gl_info->limits.buffers + 1; + unsigned int i; if (depth_stencil && render_targets && render_targets[0]) { @@ -377,19 +476,44 @@ static struct fbo_entry *context_find_fbo_entry(struct wined3d_context *context, } } - LIST_FOR_EACH_ENTRY(entry, &context->fbo_list, struct fbo_entry, entry) + context_create_fbo_key(context->fbo_key, render_targets, depth_stencil, color_location, + ds_location, gl_info->limits.buffers); + + if (TRACE_ON(d3d)) { - if (!memcmp(entry->render_targets, - render_targets, gl_info->limits.buffers * sizeof(*entry->render_targets)) - && entry->depth_stencil == depth_stencil && entry->color_location == color_location - && entry->ds_location == ds_location) + TRACE("Dumping FBO attachments:\n"); + for (i = 0; i < gl_info->limits.buffers; ++i) { - list_remove(&entry->entry); - list_add_head(&context->fbo_list, &entry->entry); - return entry; + if (render_targets[i]) + { + TRACE("\tColor attachment %u: (%p) %s gl obj %u(%s) %ux%u %u samples.\n", + i, render_targets[i], debug_d3dformat(render_targets[i]->resource.format->id), + context->fbo_key->objects[i + 1].object, + context->fbo_key->rb_namespace & (1 << (i + 1)) ? "rb" : "texure", + render_targets[i]->pow2Width, render_targets[i]->pow2Height, + render_targets[i]->resource.multisample_type); + } + } + if (depth_stencil) + { + TRACE("\tDepth attachment: (%p) %s gl obj %u(%s) %ux%u %u samples.\n", + depth_stencil, debug_d3dformat(depth_stencil->resource.format->id), + context->fbo_key->objects[0].object, + context->fbo_key->rb_namespace & (1 << 0) ? "rb" : "texure", + depth_stencil->pow2Width, depth_stencil->pow2Height, depth_stencil->resource.multisample_type); } } + LIST_FOR_EACH_ENTRY(entry, &context->fbo_list, struct fbo_entry, entry) + { + if (memcmp(context->fbo_key, &entry->key, FIELD_OFFSET(struct wined3d_fbo_entry_key, objects[object_count]))) + continue; + + list_remove(&entry->entry); + list_add_head(&context->fbo_list, &entry->entry); + return entry; + } + if (context->fbo_entry_count < WINED3D_MAX_FBO_ENTRIES) { entry = context_create_fbo_entry(context, render_targets, depth_stencil, color_location, ds_location); @@ -413,7 +537,7 @@ static void context_apply_fbo_entry(struct wined3d_context *context, GLenum targ const struct wined3d_gl_info *gl_info = context->gl_info; unsigned int i; GLuint read_binding, draw_binding; - struct wined3d_surface *depth_stencil = entry->depth_stencil; + struct wined3d_surface *depth_stencil = entry->d3d_depth_stencil; if (entry->attached) { @@ -428,25 +552,36 @@ static void context_apply_fbo_entry(struct wined3d_context *context, GLenum targ /* Apply render targets */ for (i = 0; i < gl_info->limits.buffers; ++i) { - context_attach_surface_fbo(context, target, i, entry->render_targets[i], entry->color_location); + context_attach_surface_fbo(context, target, i, &entry->key.objects[i + 1], + entry->key.rb_namespace & (1 << (i + 1))); } - if (depth_stencil && entry->render_targets[0] + if (depth_stencil && entry->d3d_render_targets[0] && (depth_stencil->resource.multisample_type - != entry->render_targets[0]->resource.multisample_type + != entry->d3d_render_targets[0]->resource.multisample_type || depth_stencil->resource.multisample_quality - != entry->render_targets[0]->resource.multisample_quality)) + != entry->d3d_render_targets[0]->resource.multisample_quality)) { WARN("Color multisample type %u and quality %u, depth stencil has %u and %u, disabling ds buffer.\n", - entry->render_targets[0]->resource.multisample_quality, - entry->render_targets[0]->resource.multisample_type, + entry->d3d_render_targets[0]->resource.multisample_quality, + entry->d3d_render_targets[0]->resource.multisample_type, depth_stencil->resource.multisample_quality, depth_stencil->resource.multisample_type); depth_stencil = NULL; } if (depth_stencil) - surface_set_compatible_renderbuffer(depth_stencil, entry->render_targets[0]); - context_attach_depth_stencil_fbo(context, target, depth_stencil, entry->ds_location); + { + DWORD format_flags = depth_stencil->container->resource.format_flags; + surface_set_compatible_renderbuffer(depth_stencil, entry->d3d_render_targets[0]); + context_attach_depth_stencil_fbo(context, target, &entry->key.objects[0], + entry->key.rb_namespace & 0x1, format_flags, + depth_stencil->current_renderbuffer ? depth_stencil->current_renderbuffer->id : 0); + } + else + { + struct wined3d_fbo_resource resource = {0}; + context_attach_depth_stencil_fbo(context, target, &resource, FALSE, 0, 0); + } /* Set valid read and draw buffer bindings to satisfy pedantic pre-ES2_compatibility * GL contexts requirements. */ @@ -695,7 +830,7 @@ static void context_enum_surface_fbo_entries(const struct wined3d_device *device { UINT j; - if (entry->depth_stencil == surface) + if (entry->d3d_depth_stencil == surface) { callback(context, entry); continue; @@ -703,7 +838,7 @@ static void context_enum_surface_fbo_entries(const struct wined3d_device *device for (j = 0; j < gl_info->limits.buffers; ++j) { - if (entry->render_targets[j] == surface) + if (entry->d3d_render_targets[j] == surface) { callback(context, entry); break; @@ -764,21 +899,16 @@ void context_surface_update(struct wined3d_context *context, const struct wined3 if (!entry || context->rebind_fbo) return; - for (i = 0; i < gl_info->limits.buffers; ++i) + for (i = 0; i < gl_info->limits.buffers + 1; ++i) { - if (surface == entry->render_targets[i]) + if (surface->container->texture_rgb.name == entry->key.objects[i].object || + surface->container->texture_srgb.name == entry->key.objects[i].object) { - TRACE("Updated surface %p is bound as color attachment %u to the current FBO.\n", surface, i); + TRACE("Updated surface %p is bound as attachment %u to the current FBO.\n", surface, i); context->rebind_fbo = TRUE; return; } } - - if (surface == entry->depth_stencil) - { - TRACE("Updated surface %p is bound as depth attachment to the current FBO.\n", surface); - context->rebind_fbo = TRUE; - } } static BOOL context_restore_pixel_format(struct wined3d_context *ctx) @@ -1480,6 +1610,11 @@ struct wined3d_context *context_create(struct wined3d_swapchain *swapchain, if (!ret->draw_buffers) goto out; + ret->fbo_key = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, + FIELD_OFFSET(struct wined3d_fbo_entry_key, objects[gl_info->limits.buffers + 1])); + if (!ret->fbo_key) + goto out; + ret->free_timestamp_query_size = 4; ret->free_timestamp_queries = HeapAlloc(GetProcessHeap(), 0, ret->free_timestamp_query_size * sizeof(*ret->free_timestamp_queries)); @@ -1832,6 +1967,7 @@ out: HeapFree(GetProcessHeap(), 0, ret->free_event_queries); HeapFree(GetProcessHeap(), 0, ret->free_occlusion_queries); HeapFree(GetProcessHeap(), 0, ret->free_timestamp_queries); + HeapFree(GetProcessHeap(), 0, ret->fbo_key); HeapFree(GetProcessHeap(), 0, ret->draw_buffers); HeapFree(GetProcessHeap(), 0, ret->blit_targets); HeapFree(GetProcessHeap(), 0, ret); @@ -1863,6 +1999,7 @@ void context_destroy(struct wined3d_device *device, struct wined3d_context *cont device->shader_backend->shader_free_context_data(context); device->adapter->fragment_pipe->free_context_data(context); + HeapFree(GetProcessHeap(), 0, context->fbo_key); HeapFree(GetProcessHeap(), 0, context->draw_buffers); HeapFree(GetProcessHeap(), 0, context->blit_targets); device_context_remove(device, context); diff --git a/dlls/wined3d/wined3d_private.h b/dlls/wined3d/wined3d_private.h index fd7bbc8..50952db 100644 --- a/dlls/wined3d/wined3d_private.h +++ b/dlls/wined3d/wined3d_private.h @@ -1229,6 +1229,7 @@ struct wined3d_context GLuint fbo_read_binding; GLuint fbo_draw_binding; struct wined3d_surface **blit_targets; + struct wined3d_fbo_entry_key *fbo_key; GLenum *draw_buffers; DWORD draw_buffers_mask; /* Enabled draw buffers, 31 max. */ @@ -2374,15 +2375,25 @@ struct wined3d_renderbuffer_entry UINT height; }; +struct wined3d_fbo_resource +{ + GLuint object; + GLuint level, target; +}; + struct fbo_entry { struct list entry; - struct wined3d_surface **render_targets; - struct wined3d_surface *depth_stencil; - DWORD color_location, ds_location; + struct wined3d_surface **d3d_render_targets; + struct wined3d_surface *d3d_depth_stencil; DWORD rt_mask; BOOL attached; GLuint id; + struct wined3d_fbo_entry_key + { + DWORD rb_namespace; + struct wined3d_fbo_resource objects[1]; + } key; }; struct wined3d_surface_ops -- 2.4.10