wined3d: Fixup FBO depth attachments when the depth attachment is larger than the render target.
This commit is contained in:
parent
3d4e054b55
commit
c9b178b594
|
@ -768,6 +768,8 @@ static HRESULT WINAPI IWineD3DDeviceImpl_CreateSurface(IWineD3DDevice *iface, U
|
|||
return WINED3DERR_INVALIDCALL;
|
||||
}
|
||||
|
||||
list_init(&object->renderbuffers);
|
||||
|
||||
/* Call the private setup routine */
|
||||
return IWineD3DSurface_PrivateSetup( (IWineD3DSurface *) object );
|
||||
|
||||
|
@ -5110,22 +5112,27 @@ static void set_depth_stencil_fbo(IWineD3DDevice *iface, IWineD3DSurface *depth_
|
|||
TRACE("Set depth stencil to %p\n", depth_stencil);
|
||||
|
||||
if (depth_stencil_impl) {
|
||||
GLenum texttarget, target;
|
||||
GLint old_binding = 0;
|
||||
if (depth_stencil_impl->current_renderbuffer) {
|
||||
GL_EXTCALL(glFramebufferRenderbufferEXT(GL_FRAMEBUFFER_EXT, GL_DEPTH_ATTACHMENT_EXT, GL_RENDERBUFFER_EXT, depth_stencil_impl->current_renderbuffer->id));
|
||||
checkGLcall("glFramebufferRenderbufferEXT()");
|
||||
} else {
|
||||
GLenum texttarget, target;
|
||||
GLint old_binding = 0;
|
||||
|
||||
texttarget = depth_stencil_impl->glDescription.target;
|
||||
target = texttarget == GL_TEXTURE_2D ? GL_TEXTURE_2D : GL_TEXTURE_CUBE_MAP_ARB;
|
||||
glGetIntegerv(texttarget == GL_TEXTURE_2D ? GL_TEXTURE_BINDING_2D : GL_TEXTURE_BINDING_CUBE_MAP_ARB, &old_binding);
|
||||
texttarget = depth_stencil_impl->glDescription.target;
|
||||
target = texttarget == GL_TEXTURE_2D ? GL_TEXTURE_2D : GL_TEXTURE_CUBE_MAP_ARB;
|
||||
glGetIntegerv(texttarget == GL_TEXTURE_2D ? GL_TEXTURE_BINDING_2D : GL_TEXTURE_BINDING_CUBE_MAP_ARB, &old_binding);
|
||||
|
||||
IWineD3DSurface_PreLoad(depth_stencil);
|
||||
IWineD3DSurface_PreLoad(depth_stencil);
|
||||
|
||||
glTexParameteri(target, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
|
||||
glTexParameteri(target, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
|
||||
glTexParameteri(target, GL_DEPTH_TEXTURE_MODE_ARB, GL_LUMINANCE);
|
||||
glBindTexture(target, old_binding);
|
||||
glTexParameteri(target, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
|
||||
glTexParameteri(target, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
|
||||
glTexParameteri(target, GL_DEPTH_TEXTURE_MODE_ARB, GL_LUMINANCE);
|
||||
glBindTexture(target, old_binding);
|
||||
|
||||
GL_EXTCALL(glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_DEPTH_ATTACHMENT_EXT, texttarget, depth_stencil_impl->glDescription.textureName, 0));
|
||||
checkGLcall("glFramebufferTexture2DEXT()");
|
||||
GL_EXTCALL(glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_DEPTH_ATTACHMENT_EXT, texttarget, depth_stencil_impl->glDescription.textureName, 0));
|
||||
checkGLcall("glFramebufferTexture2DEXT()");
|
||||
}
|
||||
} else {
|
||||
GL_EXTCALL(glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_DEPTH_ATTACHMENT_EXT, GL_TEXTURE_2D, 0, 0));
|
||||
checkGLcall("glFramebufferTexture2DEXT()");
|
||||
|
@ -5175,6 +5182,22 @@ static void check_fbo_status(IWineD3DDevice *iface) {
|
|||
}
|
||||
}
|
||||
|
||||
static BOOL depth_mismatch_fbo(IWineD3DDevice *iface) {
|
||||
IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
|
||||
IWineD3DSurfaceImpl *rt_impl = (IWineD3DSurfaceImpl *)This->render_targets[0];
|
||||
IWineD3DSurfaceImpl *ds_impl = (IWineD3DSurfaceImpl *)This->stencilBufferTarget;
|
||||
|
||||
if (!ds_impl) return FALSE;
|
||||
|
||||
if (ds_impl->current_renderbuffer) {
|
||||
return (rt_impl->pow2Width != ds_impl->current_renderbuffer->width ||
|
||||
rt_impl->pow2Height != ds_impl->current_renderbuffer->height);
|
||||
}
|
||||
|
||||
return (rt_impl->pow2Width != ds_impl->pow2Width ||
|
||||
rt_impl->pow2Height != ds_impl->pow2Height);
|
||||
}
|
||||
|
||||
void apply_fbo_state(IWineD3DDevice *iface) {
|
||||
IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
|
||||
unsigned int i;
|
||||
|
@ -5192,7 +5215,13 @@ void apply_fbo_state(IWineD3DDevice *iface) {
|
|||
}
|
||||
|
||||
/* Apply depth targets */
|
||||
if (This->fbo_depth_attachment != This->stencilBufferTarget) {
|
||||
if (This->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;
|
||||
|
||||
if (This->stencilBufferTarget) {
|
||||
surface_set_compatible_renderbuffer(This->stencilBufferTarget, w, h);
|
||||
}
|
||||
set_depth_stencil_fbo(iface, This->stencilBufferTarget);
|
||||
This->fbo_depth_attachment = This->stencilBufferTarget;
|
||||
}
|
||||
|
|
|
@ -804,6 +804,11 @@ static void depth_copy(IWineD3DDevice *iface) {
|
|||
/* TODO: Make this work for modes other than FBO */
|
||||
if (wined3d_settings.offscreen_rendering_mode != ORM_FBO) return;
|
||||
|
||||
if (depth_stencil->current_renderbuffer) {
|
||||
FIXME("Not supported with fixed up depth stencil\n");
|
||||
return;
|
||||
}
|
||||
|
||||
if (This->render_offscreen) {
|
||||
static GLuint tmp_texture = 0;
|
||||
GLint old_binding = 0;
|
||||
|
|
|
@ -8,6 +8,7 @@
|
|||
* Copyright 2004 Christian Costa
|
||||
* Copyright 2005 Oliver Stieber
|
||||
* Copyright 2006 Stefan Dösinger for CodeWeavers
|
||||
* Copyright 2007 Henri Verbeet
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
|
@ -237,6 +238,56 @@ static void surface_allocate_surface(IWineD3DSurfaceImpl *This, GLenum internal,
|
|||
LEAVE_GL();
|
||||
}
|
||||
|
||||
/* 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. */
|
||||
void surface_set_compatible_renderbuffer(IWineD3DSurface *iface, unsigned int width, unsigned int height) {
|
||||
IWineD3DSurfaceImpl *This = (IWineD3DSurfaceImpl *)iface;
|
||||
renderbuffer_entry_t *entry;
|
||||
GLuint renderbuffer = 0;
|
||||
unsigned int src_width, src_height;
|
||||
|
||||
src_width = This->pow2Width;
|
||||
src_height = This->pow2Height;
|
||||
|
||||
/* 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) {
|
||||
This->current_renderbuffer = NULL;
|
||||
return;
|
||||
}
|
||||
|
||||
/* Look if we've already got a renderbuffer of the correct dimensions */
|
||||
LIST_FOR_EACH_ENTRY(entry, &This->renderbuffers, renderbuffer_entry_t, entry) {
|
||||
if (entry->width == width && entry->height == height) {
|
||||
renderbuffer = entry->id;
|
||||
This->current_renderbuffer = entry;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (!renderbuffer) {
|
||||
const PixelFormatDesc *format_entry = getFormatDescEntry(This->resource.format);
|
||||
|
||||
GL_EXTCALL(glGenRenderbuffersEXT(1, &renderbuffer));
|
||||
GL_EXTCALL(glBindRenderbufferEXT(GL_RENDERBUFFER_EXT, renderbuffer));
|
||||
GL_EXTCALL(glRenderbufferStorageEXT(GL_RENDERBUFFER_EXT, format_entry->glFormat, width, height));
|
||||
|
||||
entry = HeapAlloc(GetProcessHeap(), 0, sizeof(renderbuffer_entry_t));
|
||||
entry->width = width;
|
||||
entry->height = height;
|
||||
entry->id = renderbuffer;
|
||||
list_add_head(&This->renderbuffers, &entry->entry);
|
||||
|
||||
This->current_renderbuffer = entry;
|
||||
}
|
||||
|
||||
checkGLcall("set_compatible_renderbuffer");
|
||||
}
|
||||
|
||||
|
||||
/* *******************************************
|
||||
IWineD3DSurface IUnknown parts follow
|
||||
******************************************* */
|
||||
|
@ -271,6 +322,7 @@ ULONG WINAPI IWineD3DSurfaceImpl_Release(IWineD3DSurface *iface) {
|
|||
TRACE("(%p) : Releasing from %d\n", This, ref + 1);
|
||||
if (ref == 0) {
|
||||
IWineD3DDeviceImpl *device = (IWineD3DDeviceImpl *) This->resource.wineD3DDevice;
|
||||
renderbuffer_entry_t *entry, *entry2;
|
||||
TRACE("(%p) : cleaning up\n", This);
|
||||
|
||||
if(iface == device->lastActiveRenderTarget) {
|
||||
|
@ -339,6 +391,11 @@ ULONG WINAPI IWineD3DSurfaceImpl_Release(IWineD3DSurface *iface) {
|
|||
if(iface == device->ddraw_primary)
|
||||
device->ddraw_primary = NULL;
|
||||
|
||||
LIST_FOR_EACH_ENTRY_SAFE(entry, entry2, &This->renderbuffers, renderbuffer_entry_t, entry) {
|
||||
GL_EXTCALL(glDeleteRenderbuffersEXT(1, &entry->id));
|
||||
HeapFree(GetProcessHeap(), 0, entry);
|
||||
}
|
||||
|
||||
TRACE("(%p) Released\n", This);
|
||||
HeapFree(GetProcessHeap(), 0, This);
|
||||
|
||||
|
|
|
@ -1003,6 +1003,13 @@ typedef struct wineD3DSurface_DIB {
|
|||
BOOL client_memory;
|
||||
} wineD3DSurface_DIB;
|
||||
|
||||
typedef struct {
|
||||
struct list entry;
|
||||
GLuint id;
|
||||
UINT width;
|
||||
UINT height;
|
||||
} renderbuffer_entry_t;
|
||||
|
||||
/*****************************************************************************
|
||||
* IWineD3DSurface implementation structure
|
||||
*/
|
||||
|
@ -1054,6 +1061,9 @@ struct IWineD3DSurfaceImpl
|
|||
DWORD CKeyFlags;
|
||||
|
||||
DDCOLORKEY glCKey;
|
||||
|
||||
struct list renderbuffers;
|
||||
renderbuffer_entry_t *current_renderbuffer;
|
||||
};
|
||||
|
||||
extern const IWineD3DSurfaceVtbl IWineD3DSurface_Vtbl;
|
||||
|
@ -1398,6 +1408,8 @@ void set_tex_op(IWineD3DDevice *iface, BOOL isAlpha, int Stage, WINED3DTEXTURE
|
|||
void set_tex_op_nvrc(IWineD3DDevice *iface, BOOL is_alpha, int stage, WINED3DTEXTUREOP op, DWORD arg1, DWORD arg2, DWORD arg3, INT texture_idx);
|
||||
void set_texture_matrix(const float *smat, DWORD flags, BOOL calculatedCoords);
|
||||
|
||||
void surface_set_compatible_renderbuffer(IWineD3DSurface *iface, unsigned int width, unsigned int height);
|
||||
|
||||
int D3DFmtMakeGlCfg(WINED3DFORMAT BackBufferFormat, WINED3DFORMAT StencilBufferFormat, int *attribs, int* nAttribs, BOOL alternate);
|
||||
|
||||
/* Math utils */
|
||||
|
|
Loading…
Reference in New Issue