wined3d: Track FBOs per-context.
Although sharing FBOs across contexts is allowed by EXT_framebuffer_object (issue 76), it causes issues with nVidia drivers. Considering the GL 3 spec explicitly disallows sharing of FBOs accross contexts (Appendix D), this patch is probably the right thing to do.
This commit is contained in:
parent
2f99bcdde2
commit
05931f4a5a
|
@ -485,6 +485,13 @@ WineD3DContext *CreateContext(IWineD3DDeviceImpl *This, IWineD3DSurfaceImpl *tar
|
|||
|
||||
TRACE("Successfully created new context %p\n", ret);
|
||||
|
||||
ret->fbo_color_attachments = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(IWineD3DSurface *) * GL_LIMITS(buffers));
|
||||
if (!ret->fbo_color_attachments)
|
||||
{
|
||||
ERR("Out of memory!\n");
|
||||
goto out;
|
||||
}
|
||||
|
||||
/* Set up the context defaults */
|
||||
oldCtx = pwglGetCurrentContext();
|
||||
oldDrawable = pwglGetCurrentDC();
|
||||
|
@ -576,8 +583,11 @@ WineD3DContext *CreateContext(IWineD3DDeviceImpl *This, IWineD3DSurfaceImpl *tar
|
|||
}
|
||||
This->frag_pipe->enable_extension((IWineD3DDevice *) This, TRUE);
|
||||
|
||||
out:
|
||||
return ret;
|
||||
|
||||
out:
|
||||
HeapFree(GetProcessHeap(), 0, ret->fbo_color_attachments);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/*****************************************************************************
|
||||
|
@ -642,6 +652,20 @@ void DestroyContext(IWineD3DDeviceImpl *This, WineD3DContext *context) {
|
|||
last_device = NULL;
|
||||
}
|
||||
|
||||
/* FIXME: We probably need an active context to do this... */
|
||||
if (context->fbo) {
|
||||
GL_EXTCALL(glDeleteFramebuffersEXT(1, &context->fbo));
|
||||
}
|
||||
if (context->src_fbo) {
|
||||
GL_EXTCALL(glDeleteFramebuffersEXT(1, &context->src_fbo));
|
||||
}
|
||||
if (context->dst_fbo) {
|
||||
GL_EXTCALL(glDeleteFramebuffersEXT(1, &context->dst_fbo));
|
||||
}
|
||||
|
||||
HeapFree(GetProcessHeap(), 0, context->fbo_color_attachments);
|
||||
context->fbo_color_attachments = NULL;
|
||||
|
||||
if(context->isPBuffer) {
|
||||
GL_EXTCALL(wglReleasePbufferDCARB(context->pbuffer, context->hdc));
|
||||
GL_EXTCALL(wglDestroyPbufferARB(context->pbuffer));
|
||||
|
@ -1195,7 +1219,7 @@ void ActivateContext(IWineD3DDeviceImpl *This, IWineD3DSurface *target, ContextU
|
|||
if (wined3d_settings.offscreen_rendering_mode == ORM_FBO) {
|
||||
if (This->render_offscreen) {
|
||||
FIXME("Activating for CTXUSAGE_BLIT for an offscreen target with ORM_FBO. This should be avoided.\n");
|
||||
bind_fbo((IWineD3DDevice *)This, GL_FRAMEBUFFER_EXT, &This->dst_fbo);
|
||||
bind_fbo((IWineD3DDevice *)This, GL_FRAMEBUFFER_EXT, &context->dst_fbo);
|
||||
attach_surface_fbo(This, GL_FRAMEBUFFER_EXT, 0, target);
|
||||
GL_EXTCALL(glFramebufferRenderbufferEXT(GL_FRAMEBUFFER_EXT, GL_DEPTH_ATTACHMENT_EXT, GL_RENDERBUFFER_EXT, 0));
|
||||
checkGLcall("glFramebufferRenderbufferEXT");
|
||||
|
|
|
@ -7,7 +7,7 @@
|
|||
* Copyright 2004 Christian Costa
|
||||
* Copyright 2005 Oliver Stieber
|
||||
* Copyright 2006-2008 Stefan Dösinger for CodeWeavers
|
||||
* Copyright 2006-2007 Henri Verbeet
|
||||
* Copyright 2006-2008 Henri Verbeet
|
||||
* Copyright 2007 Andrew Riedi
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
|
@ -163,16 +163,6 @@ static ULONG WINAPI IWineD3DDeviceImpl_Release(IWineD3DDevice *iface) {
|
|||
TRACE("(%p) : Releasing from %d\n", This, refCount + 1);
|
||||
|
||||
if (!refCount) {
|
||||
if (This->fbo) {
|
||||
GL_EXTCALL(glDeleteFramebuffersEXT(1, &This->fbo));
|
||||
}
|
||||
if (This->src_fbo) {
|
||||
GL_EXTCALL(glDeleteFramebuffersEXT(1, &This->src_fbo));
|
||||
}
|
||||
if (This->dst_fbo) {
|
||||
GL_EXTCALL(glDeleteFramebuffersEXT(1, &This->dst_fbo));
|
||||
}
|
||||
|
||||
/* TODO: Clean up all the surfaces and textures! */
|
||||
/* NOTE: You must release the parent if the object was created via a callback
|
||||
** ***************************/
|
||||
|
@ -2091,12 +2081,11 @@ static HRESULT WINAPI IWineD3DDeviceImpl_Init3D(IWineD3DDevice *iface, WINED3DPR
|
|||
}
|
||||
|
||||
This->render_targets = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(IWineD3DSurface *) * GL_LIMITS(buffers));
|
||||
This->fbo_color_attachments = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(IWineD3DSurface *) * GL_LIMITS(buffers));
|
||||
This->draw_buffers = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(GLenum) * GL_LIMITS(buffers));
|
||||
|
||||
This->NumberOfPalettes = 1;
|
||||
This->palettes = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(PALETTEENTRY*));
|
||||
if(!This->palettes || !This->render_targets || !This->fbo_color_attachments || !This->draw_buffers) {
|
||||
if(!This->palettes || !This->render_targets || !This->draw_buffers) {
|
||||
ERR("Out of memory!\n");
|
||||
goto err_out;
|
||||
}
|
||||
|
@ -2242,7 +2231,6 @@ static HRESULT WINAPI IWineD3DDeviceImpl_Init3D(IWineD3DDevice *iface, WINED3DPR
|
|||
|
||||
err_out:
|
||||
HeapFree(GetProcessHeap(), 0, This->render_targets);
|
||||
HeapFree(GetProcessHeap(), 0, This->fbo_color_attachments);
|
||||
HeapFree(GetProcessHeap(), 0, This->draw_buffers);
|
||||
HeapFree(GetProcessHeap(), 0, This->swapchains);
|
||||
This->NumberOfSwapChains = 0;
|
||||
|
@ -2425,10 +2413,8 @@ static HRESULT WINAPI IWineD3DDeviceImpl_Uninit3D(IWineD3DDevice *iface, D3DCB_D
|
|||
This->NumberOfPalettes = 0;
|
||||
|
||||
HeapFree(GetProcessHeap(), 0, This->render_targets);
|
||||
HeapFree(GetProcessHeap(), 0, This->fbo_color_attachments);
|
||||
HeapFree(GetProcessHeap(), 0, This->draw_buffers);
|
||||
This->render_targets = NULL;
|
||||
This->fbo_color_attachments = NULL;
|
||||
This->draw_buffers = NULL;
|
||||
|
||||
This->d3d_initialized = FALSE;
|
||||
|
@ -6217,7 +6203,7 @@ static void color_fill_fbo(IWineD3DDevice *iface, IWineD3DSurface *surface, CONS
|
|||
|
||||
ActivateContext(This, This->lastActiveRenderTarget, CTXUSAGE_RESOURCELOAD);
|
||||
ENTER_GL();
|
||||
bind_fbo(iface, GL_FRAMEBUFFER_EXT, &This->dst_fbo);
|
||||
bind_fbo(iface, GL_FRAMEBUFFER_EXT, &This->activeContext->dst_fbo);
|
||||
attach_surface_fbo(This, GL_FRAMEBUFFER_EXT, 0, surface);
|
||||
GL_EXTCALL(glFramebufferRenderbufferEXT(GL_FRAMEBUFFER_EXT, GL_DEPTH_ATTACHMENT_EXT, GL_RENDERBUFFER_EXT, 0));
|
||||
checkGLcall("glFramebufferRenderbufferEXT");
|
||||
|
@ -6249,7 +6235,7 @@ static void color_fill_fbo(IWineD3DDevice *iface, IWineD3DSurface *surface, CONS
|
|||
checkGLcall("glClear");
|
||||
|
||||
if (This->render_offscreen) {
|
||||
bind_fbo(iface, GL_FRAMEBUFFER_EXT, &This->fbo);
|
||||
bind_fbo(iface, GL_FRAMEBUFFER_EXT, &This->activeContext->fbo);
|
||||
} else {
|
||||
GL_EXTCALL(glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0));
|
||||
checkGLcall("glBindFramebuffer()");
|
||||
|
@ -6557,13 +6543,13 @@ static void check_fbo_status(IWineD3DDevice *iface) {
|
|||
|
||||
/* Dump the FBO attachments */
|
||||
for (i = 0; i < GL_LIMITS(buffers); ++i) {
|
||||
attachment = (IWineD3DSurfaceImpl *)This->fbo_color_attachments[i];
|
||||
attachment = (IWineD3DSurfaceImpl *)This->activeContext->fbo_color_attachments[i];
|
||||
if (attachment) {
|
||||
FIXME("\tColor attachment %d: (%p) %s %ux%u\n", i, attachment, debug_d3dformat(attachment->resource.format),
|
||||
attachment->pow2Width, attachment->pow2Height);
|
||||
}
|
||||
}
|
||||
attachment = (IWineD3DSurfaceImpl *)This->fbo_depth_attachment;
|
||||
attachment = (IWineD3DSurfaceImpl *)This->activeContext->fbo_depth_attachment;
|
||||
if (attachment) {
|
||||
FIXME("\tDepth attachment: (%p) %s %ux%u\n", attachment, debug_d3dformat(attachment->resource.format),
|
||||
attachment->pow2Width, attachment->pow2Height);
|
||||
|
@ -6589,22 +6575,23 @@ static BOOL depth_mismatch_fbo(IWineD3DDevice *iface) {
|
|||
|
||||
void apply_fbo_state(IWineD3DDevice *iface) {
|
||||
IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
|
||||
WineD3DContext *context = This->activeContext;
|
||||
unsigned int i;
|
||||
|
||||
if (This->render_offscreen) {
|
||||
bind_fbo(iface, GL_FRAMEBUFFER_EXT, &This->fbo);
|
||||
bind_fbo(iface, GL_FRAMEBUFFER_EXT, &context->fbo);
|
||||
|
||||
/* Apply render targets */
|
||||
for (i = 0; i < GL_LIMITS(buffers); ++i) {
|
||||
IWineD3DSurface *render_target = This->render_targets[i];
|
||||
if (This->fbo_color_attachments[i] != render_target) {
|
||||
if (context->fbo_color_attachments[i] != render_target) {
|
||||
set_render_target_fbo(iface, i, render_target);
|
||||
This->fbo_color_attachments[i] = render_target;
|
||||
context->fbo_color_attachments[i] = render_target;
|
||||
}
|
||||
}
|
||||
|
||||
/* Apply depth targets */
|
||||
if (This->fbo_depth_attachment != This->stencilBufferTarget || depth_mismatch_fbo(iface)) {
|
||||
if (context->fbo_depth_attachment != This->stencilBufferTarget || depth_mismatch_fbo(iface)) {
|
||||
unsigned int w = ((IWineD3DSurfaceImpl *)This->render_targets[0])->pow2Width;
|
||||
unsigned int h = ((IWineD3DSurfaceImpl *)This->render_targets[0])->pow2Height;
|
||||
|
||||
|
@ -6612,7 +6599,7 @@ void apply_fbo_state(IWineD3DDevice *iface) {
|
|||
surface_set_compatible_renderbuffer(This->stencilBufferTarget, w, h);
|
||||
}
|
||||
set_depth_stencil_fbo(iface, This->stencilBufferTarget);
|
||||
This->fbo_depth_attachment = This->stencilBufferTarget;
|
||||
context->fbo_depth_attachment = This->stencilBufferTarget;
|
||||
}
|
||||
} else {
|
||||
GL_EXTCALL(glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0));
|
||||
|
@ -6679,7 +6666,7 @@ void stretch_rect_fbo(IWineD3DDevice *iface, IWineD3DSurface *src_surface, WINED
|
|||
} else {
|
||||
TRACE("Source surface %p is offscreen\n", src_surface);
|
||||
ENTER_GL();
|
||||
bind_fbo(iface, GL_READ_FRAMEBUFFER_EXT, &This->src_fbo);
|
||||
bind_fbo(iface, GL_READ_FRAMEBUFFER_EXT, &This->activeContext->src_fbo);
|
||||
attach_surface_fbo(This, GL_READ_FRAMEBUFFER_EXT, 0, src_surface);
|
||||
glReadBuffer(GL_COLOR_ATTACHMENT0_EXT);
|
||||
checkGLcall("glReadBuffer()");
|
||||
|
@ -6727,7 +6714,7 @@ void stretch_rect_fbo(IWineD3DDevice *iface, IWineD3DSurface *src_surface, WINED
|
|||
}
|
||||
|
||||
ENTER_GL();
|
||||
bind_fbo(iface, GL_DRAW_FRAMEBUFFER_EXT, &This->dst_fbo);
|
||||
bind_fbo(iface, GL_DRAW_FRAMEBUFFER_EXT, &This->activeContext->dst_fbo);
|
||||
attach_surface_fbo(This, GL_DRAW_FRAMEBUFFER_EXT, 0, dst_surface);
|
||||
glDrawBuffer(GL_COLOR_ATTACHMENT0_EXT);
|
||||
checkGLcall("glDrawBuffer()");
|
||||
|
@ -6750,7 +6737,7 @@ void stretch_rect_fbo(IWineD3DDevice *iface, IWineD3DSurface *src_surface, WINED
|
|||
IWineD3DSurface_ModifyLocation(dst_surface, SFLAG_INDRAWABLE, TRUE);
|
||||
|
||||
if (This->render_offscreen) {
|
||||
bind_fbo(iface, GL_FRAMEBUFFER_EXT, &This->fbo);
|
||||
bind_fbo(iface, GL_FRAMEBUFFER_EXT, &This->activeContext->fbo);
|
||||
} else {
|
||||
GL_EXTCALL(glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0));
|
||||
checkGLcall("glBindFramebuffer()");
|
||||
|
@ -7151,35 +7138,6 @@ static HRESULT WINAPI reset_unload_resources(IWineD3DResource *resource, void *d
|
|||
return S_OK;
|
||||
}
|
||||
|
||||
static void reset_fbo_state(IWineD3DDevice *iface) {
|
||||
IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *) iface;
|
||||
unsigned int i;
|
||||
|
||||
ENTER_GL();
|
||||
GL_EXTCALL(glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0));
|
||||
checkGLcall("glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0)");
|
||||
|
||||
if (This->fbo) {
|
||||
GL_EXTCALL(glDeleteFramebuffersEXT(1, &This->fbo));
|
||||
This->fbo = 0;
|
||||
}
|
||||
if (This->src_fbo) {
|
||||
GL_EXTCALL(glDeleteFramebuffersEXT(1, &This->src_fbo));
|
||||
This->src_fbo = 0;
|
||||
}
|
||||
if (This->dst_fbo) {
|
||||
GL_EXTCALL(glDeleteFramebuffersEXT(1, &This->dst_fbo));
|
||||
This->dst_fbo = 0;
|
||||
}
|
||||
checkGLcall("Tear down FBOs\n");
|
||||
LEAVE_GL();
|
||||
|
||||
for (i = 0; i < GL_LIMITS(buffers); ++i) {
|
||||
This->fbo_color_attachments[i] = NULL;
|
||||
}
|
||||
This->fbo_depth_attachment = NULL;
|
||||
}
|
||||
|
||||
static BOOL is_display_mode_supported(IWineD3DDeviceImpl *This, WINED3DPRESENT_PARAMETERS *pp) {
|
||||
UINT i, count;
|
||||
WINED3DDISPLAYMODE m;
|
||||
|
@ -7212,10 +7170,6 @@ void delete_opengl_contexts(IWineD3DDevice *iface, IWineD3DSwapChain *swapchain_
|
|||
UINT i;
|
||||
IWineD3DBaseShaderImpl *shader;
|
||||
|
||||
if (wined3d_settings.offscreen_rendering_mode == ORM_FBO) {
|
||||
reset_fbo_state((IWineD3DDevice *) This);
|
||||
}
|
||||
|
||||
IWineD3DDevice_EnumResources(iface, reset_unload_resources, NULL);
|
||||
LIST_FOR_EACH_ENTRY(shader, &This->shaders, IWineD3DBaseShaderImpl, baseShader.shader_list_entry) {
|
||||
This->shader_backend->shader_destroy((IWineD3DBaseShader *) shader);
|
||||
|
@ -7574,20 +7528,26 @@ static void WINAPI IWineD3DDeviceImpl_ResourceReleased(IWineD3DDevice *iface, IW
|
|||
}
|
||||
}
|
||||
|
||||
ENTER_GL();
|
||||
for (i = 0; i < GL_LIMITS(buffers); ++i) {
|
||||
if (This->fbo_color_attachments[i] == (IWineD3DSurface *)resource) {
|
||||
bind_fbo(iface, GL_FRAMEBUFFER_EXT, &This->fbo);
|
||||
set_render_target_fbo(iface, i, NULL);
|
||||
This->fbo_color_attachments[i] = NULL;
|
||||
if (This->render_targets[i] == (IWineD3DSurface *)resource) {
|
||||
This->render_targets[i] = NULL;
|
||||
}
|
||||
}
|
||||
if (This->fbo_depth_attachment == (IWineD3DSurface *)resource) {
|
||||
bind_fbo(iface, GL_FRAMEBUFFER_EXT, &This->fbo);
|
||||
set_depth_stencil_fbo(iface, NULL);
|
||||
This->fbo_depth_attachment = NULL;
|
||||
if (This->stencilBufferTarget == (IWineD3DSurface *)resource) {
|
||||
This->stencilBufferTarget = NULL;
|
||||
}
|
||||
|
||||
for (i = 0; i < This->numContexts; ++i) {
|
||||
int j;
|
||||
for (j = 0; j < GL_LIMITS(buffers); ++j) {
|
||||
if (This->contexts[i]->fbo_color_attachments[j] == (IWineD3DSurface *)resource) {
|
||||
This->contexts[i]->fbo_color_attachments[j] = NULL;
|
||||
}
|
||||
}
|
||||
if (This->contexts[i]->fbo_depth_attachment == (IWineD3DSurface *)resource) {
|
||||
This->contexts[i]->fbo_depth_attachment = NULL;
|
||||
}
|
||||
}
|
||||
LEAVE_GL();
|
||||
}
|
||||
|
||||
break;
|
||||
|
|
|
@ -4027,7 +4027,7 @@ void surface_load_ds_location(IWineD3DSurface *iface, DWORD location) {
|
|||
device->depth_blt_rb_h = This->currentDesc.Height;
|
||||
}
|
||||
|
||||
bind_fbo((IWineD3DDevice *)device, GL_FRAMEBUFFER_EXT, &device->dst_fbo);
|
||||
bind_fbo((IWineD3DDevice *)device, GL_FRAMEBUFFER_EXT, &device->activeContext->dst_fbo);
|
||||
GL_EXTCALL(glFramebufferRenderbufferEXT(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT, GL_RENDERBUFFER_EXT, device->depth_blt_rb));
|
||||
checkGLcall("glFramebufferRenderbufferEXT");
|
||||
attach_depth_stencil_fbo(device, GL_FRAMEBUFFER_EXT, iface, FALSE);
|
||||
|
@ -4037,7 +4037,7 @@ void surface_load_ds_location(IWineD3DSurface *iface, DWORD location) {
|
|||
checkGLcall("depth_blt");
|
||||
|
||||
if (device->render_offscreen) {
|
||||
bind_fbo((IWineD3DDevice *)device, GL_FRAMEBUFFER_EXT, &device->fbo);
|
||||
bind_fbo((IWineD3DDevice *)device, GL_FRAMEBUFFER_EXT, &device->activeContext->fbo);
|
||||
} else {
|
||||
GL_EXTCALL(glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0));
|
||||
checkGLcall("glBindFramebuffer()");
|
||||
|
@ -4059,7 +4059,7 @@ void surface_load_ds_location(IWineD3DSurface *iface, DWORD location) {
|
|||
checkGLcall("depth_blt");
|
||||
|
||||
if (device->render_offscreen) {
|
||||
GL_EXTCALL(glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, device->fbo));
|
||||
GL_EXTCALL(glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, device->activeContext->fbo));
|
||||
checkGLcall("glBindFramebuffer()");
|
||||
}
|
||||
|
||||
|
|
|
@ -629,6 +629,13 @@ struct WineD3DContext {
|
|||
HPBUFFERARB pbuffer;
|
||||
BOOL isPBuffer;
|
||||
GLint aux_buffers;
|
||||
|
||||
/* FBOs */
|
||||
IWineD3DSurface **fbo_color_attachments;
|
||||
IWineD3DSurface *fbo_depth_attachment;
|
||||
GLuint fbo;
|
||||
GLuint src_fbo;
|
||||
GLuint dst_fbo;
|
||||
};
|
||||
|
||||
typedef enum ContextUsage {
|
||||
|
@ -880,9 +887,6 @@ struct IWineD3DDeviceImpl
|
|||
/* Render Target Support */
|
||||
IWineD3DSurface **render_targets;
|
||||
IWineD3DSurface *auto_depth_stencil_buffer;
|
||||
IWineD3DSurface **fbo_color_attachments;
|
||||
IWineD3DSurface *fbo_depth_attachment;
|
||||
|
||||
IWineD3DSurface *stencilBufferTarget;
|
||||
|
||||
/* Caches to avoid unneeded context changes */
|
||||
|
@ -897,9 +901,6 @@ struct IWineD3DDeviceImpl
|
|||
|
||||
/* For rendering to a texture using glCopyTexImage */
|
||||
BOOL render_offscreen;
|
||||
GLuint fbo;
|
||||
GLuint src_fbo;
|
||||
GLuint dst_fbo;
|
||||
GLenum *draw_buffers;
|
||||
GLuint depth_blt_texture;
|
||||
GLuint depth_blt_rb;
|
||||
|
|
Loading…
Reference in New Issue