Hi... I've been trying to get FBOs working, but I have extremely limited time to work on such things, so I thought I'd just post my current patch here, and see if people can help me figure out what's wrong with it :)
FBOs (framebuffer objects) are a newer extension, intended to replace pbuffers to accomplish offscreen rendering - so instead of drawing to the screen, you get to draw to other objects, more importantly textures. We currently support pbuffers, but the code is sketchy, and disabled for that reason. SPEC: http://msi.unilim.fr/~porquet/glexts/GL_EXT_framebuffer_object.txt.htm
Known problems with this patch include:
(1) The D3D allows the user to setDepthStencilBuffer. I do no such thing - only a default depth buffer is supported. Neither is sharing this depth buffer between offscreen and onscreen [ requires copying of pixels via lock/unlock ]. Resolution: next revision - we don't support that onscreen in the first place :)
(2) Attempting to bind a framebuffer using GL_RGB32F_ARB, and GL_RGBA32F_ARB formats will fail on my hardware (Nvidia GeForce 6800GS) with error GL_FRAMEBUFFER_UNSUPPORTED_EXT, which means the format combination was invalid for implementation-dependent reasons. However, this doesn't make sense, based on information online, which indicates this should work. See: http://www.mathematik.uni-dortmund.de/~goeddeke/gpgpu/tutorial.htm : "Using textures as render targets".... or google. This is a problem, since certain demos which make use of the R32F format won't work with FBOs - but oddly work with pbuffers. See SoftShadowsII: http://www.humus.ca/index.php?page=3D&&start=8 On the other hand I know R16F -> GL_RGB16F works fine, based on 3Dc demo.
(3) Attempting to use GL_STENCIL_INDEX8_EXT in glRenderbufferStorageEXT will fail on my hardware with GL_INVALID_OPERATION. Why - this should work according to the GL spec. On the other hand this support list says otherwise: http://developer.nvidia.com/object/nv_ogl_texture_formats.html
========= Note that bugs or no bugs, the patch fixes the following (demos from humus.ca):
3Dc demo runs correctly TransparentShadowMapping demo runs correctly Sketch demo runs correctly Half-Life 2 startup screen runs correctly ---- Water demo offscreen content is moved offscreen SoftShadows2 - offscreen content moved offscreen, shows something a lot more correct PhongLighting - offscreen content moved offscreen ---- ...but doesn't quite match pbuffers, because:
SoftShadows2 - works completely in pbuffers (even if slow), has errors in FBOs PhongLighting - has errors in FBOs SelfShadowBump - no shadow artifacts on the wall, but now most of the demo's in shadow.
From 98efb529e850dafb66c331afbc5168f90180650a Mon Sep 17 00:00:00 2001
From: Ivan Gyurdiev ivg2@cornell.edu Date: Thu, 7 Sep 2006 07:17:00 -0400 Subject: [PATCH] Add support for offscreen rendering via FBOs.
This uses: GL_EXT_framebuffer_objects
A select_offscreen_mode() function was added, where FBOs are given precedence over pbuffers - another way to do offscreen rendering, which is older, not as nice, and currently disabled at compile time.
A shared depth buffer between offscreen and onscreen is not currently supported. A custom depth buffer (SetDepthStencil) is not supported (but onscreen doesn't support it either). --- dlls/wined3d/device.c | 201 +++++++++++++++++++++++++++++++++++----- dlls/wined3d/directx.c | 17 +++ dlls/wined3d/utils.c | 38 +++++++- dlls/wined3d/wined3d_private.h | 70 +++++++++----- include/wine/wined3d_gl.h | 1 5 files changed, 275 insertions(+), 52 deletions(-)
diff --git a/dlls/wined3d/device.c b/dlls/wined3d/device.c index 463607f..aeed6b0 100644 --- a/dlls/wined3d/device.c +++ b/dlls/wined3d/device.c @@ -8,6 +8,7 @@ * Copyright 2005 Oliver Stieber * Copyright 2006 Stefan Dösinger for CodeWeavers * Copyright 2006 Henri Verbeet + * Copyright 2006 Ivan Gyurdiev * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -82,6 +83,8 @@ static void WINAPI IWineD3DDeviceImpl_Ad
static void WINAPI IWineD3DDeviceImpl_ApplyTextureUnitState(IWineD3DDevice *iface, DWORD Stage, WINED3DTEXTURESTAGESTATETYPE Type);
+static void device_render_to_texture(IWineD3DDeviceImpl* This, BOOL isTexture); + /* helper macros */ #define D3DMEMCHECK(object, ppResult) if(NULL == object) { *ppResult = NULL; WARN("Out of memory\n"); return WINED3DERR_OUTOFVIDEOMEMORY;}
@@ -239,6 +242,128 @@ static void setup_light(IWineD3DDevice * }
/********************************************************** + * FBO helper functions follow + **********************************************************/ + +static void device_fbo_attach_depthstencil( + IWineD3DDeviceImpl *This) { + + TRACE("Attaching depth stencil to offscreen FBO.\n"); + + /* Attach a default Depth renderbuffer */ + GL_EXTCALL(glFramebufferRenderbufferEXT(GL_FRAMEBUFFER_EXT, GL_DEPTH_ATTACHMENT_EXT, + GL_RENDERBUFFER_EXT, This->offscreenRBO[OFFSCREEN_RBO_DEPTH])); + checkGLcall("glFramebufferRenderbufferEXT(OFFSCREEN_RBO_DEPTH)"); + + /* Attach a default Stencil renderbuffer */ +// GL_EXTCALL(glFramebufferRenderbufferEXT(GL_FRAMEBUFFER_EXT, GL_STENCIL_ATTACHMENT_EXT, +// GL_RENDERBUFFER_EXT, This->offscreenRBO[OFFSCREEN_RBO_STENCIL])); +// checkGLcall("glFramebufferRenderbufferEXT(OFFSCREEN_RBO_STENCIL)"); +} + +static void device_fbo_attach_rendertarget( + IWineD3DDeviceImpl *This, + IWineD3DSurface* surface) { + + glDescriptor* surface_desc; + + TRACE("Attaching render surface %p to offscreen FBO.\n", surface); + + /* Pre-load does some neessary prep., such as filling out the gl descriptor properly */ + IWineD3DSurface_PreLoad(surface); + IWineD3DSurface_GetGlDesc(surface, &surface_desc); + + /* Now attach surface to the FBO */ + GL_EXTCALL(glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT, + surface_desc->target, surface_desc->textureName, surface_desc->level)); + checkGLcall("glFramebufferTexture2DEXT(0)"); + + checkGLfbstatus(); + + /* TODO: MRTs */ +} + +static void device_fbo_render_offscreen( + IWineD3DDeviceImpl *This, + IWineD3DSurface* initialRendertarget, + IWineD3DSurface* initialDepthStencil) { + + UINT render_width, render_height; + WINED3DSURFACE_DESC render_desc; + memset(&render_desc, 0, sizeof(WINED3DSURFACE_DESC)); + render_desc.Width = &render_width; + render_desc.Height = &render_height; + + /* Grab the current rendertarget's width and height */ + IWineD3DSurfaceImpl_GetDesc(initialRendertarget, &render_desc); + + /* The first time offscreen rendering is requested, + * reserve one FBO, and two RBOs, and initialize storage for depth and stencil */ + + if (!This->offscreenFBO) { + GL_EXTCALL(glGenFramebuffersEXT(1, &This->offscreenFBO)); + checkGLcall("glGenFramebuffersEXT"); + + GL_EXTCALL(glGenRenderbuffersEXT(2, This->offscreenRBO)); + checkGLcall("glGenRenderbuffersEXT"); + + GL_EXTCALL(glBindRenderbufferEXT(GL_RENDERBUFFER_EXT, This->offscreenRBO[OFFSCREEN_RBO_DEPTH])); + checkGLcall("glBindRenderbufferEXT(OFFSCREEN_RBO_DEPTH)"); + GL_EXTCALL(glRenderbufferStorageEXT(GL_RENDERBUFFER_EXT, GL_DEPTH_COMPONENT24, + render_width, render_height)); + checkGLcall("glRenderbufferStorageEXT(OFFSCREEN_RBO_DEPTH)"); + +// GL_EXTCALL(glBindRenderbufferEXT(GL_RENDERBUFFER_EXT, This->offscreenRBO[OFFSCREEN_RBO_STENCIL])); +// checkGLcall("glBindRenderbufferEXT(OFFSCREEN_RBO_STENCIL)"); +// GL_EXTCALL(glRenderbufferStorageEXT(GL_RENDERBUFFER_EXT, GL_STENCIL_INDEX4_EXT, +// render_width, render_height)); +// checkGLcall("glRenderbufferStorageEXT(OFFSCREEN_RBO_STENCIL)"); + } + + /* TODO: lock depthstencil */ + + /* Switch to offscreen FBO */ + GL_EXTCALL(glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, This->offscreenFBO)); + checkGLcall("glBindFramebufferEXT"); + + device_fbo_attach_rendertarget(This, initialRendertarget); + device_fbo_attach_depthstencil(This); + + /* TODO: unlock depthstencil */ +} + +static void device_fbo_render_onscreen( + IWineD3DDeviceImpl *This) { + + TRACE("Reverting to onscreen FBO.\n"); + + /* TODO: lock depthstencil */ + + /* Detach color */ + GL_EXTCALL(glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, + GL_COLOR_ATTACHMENT0_EXT, GL_TEXTURE_2D, 0, 0)); + checkGLcall("glFramebufferTexture2DEXT(0)"); + + /* Detach depth */ + GL_EXTCALL(glFramebufferRenderbufferEXT(GL_FRAMEBUFFER_EXT, + GL_DEPTH_ATTACHMENT_EXT, GL_RENDERBUFFER_EXT, 0)); + checkGLcall("glFramebufferRenderbufferEXT(OFFSCREEN_DEPTH_RBO)"); + + /* Detach stencil */ + GL_EXTCALL(glFramebufferRenderbufferEXT(GL_FRAMEBUFFER_EXT, + GL_STENCIL_ATTACHMENT_EXT, GL_RENDERBUFFER_EXT, 0)); + checkGLcall("glFramebufferRenderbufferEXT(OFFSCREEN_STENCIL_RBO)"); + + /* Switch to onscreen FBO */ + GL_EXTCALL(glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0)); + checkGLcall("glBindFramebufferEXT"); + + /* TODO: unlock depthstencil */ + + checkGLfbstatus(); +} + +/********************************************************** * GLSL helper functions follow **********************************************************/
@@ -2141,6 +2266,19 @@ static HRESULT WINAPI IWineD3DDeviceImpl This->cursorTexture = 0; }
+ /* Delete the offscreen FBO (if present), and switch back on-screen */ + if (wined3d_settings.offscreen_selected_mode == OFFSCREEN_FBO && This->offscreenFBO) { + ENTER_GL(); + device_fbo_render_onscreen(This); + device_render_to_texture(This, FALSE); + GL_EXTCALL(glDeleteFramebuffersEXT(1, &This->offscreenFBO)); + checkGLcall("glDeleteFramebuffersEXT"); + GL_EXTCALL(glDeleteRenderbuffersEXT(2, This->offscreenRBO)); + checkGLcall("glDeleteRenderbuffersEXT"); + LEAVE_GL(); + This->offscreenFBO = 0; + } + for(sampler = 0; sampler < GL_LIMITS(sampler_stages); ++sampler) { IWineD3DDevice_SetTexture(iface, sampler, NULL); } @@ -5984,8 +6122,10 @@ static HRESULT WINAPI IWineD3DDeviceImpl
/* If the container of the rendertarget is a texture then we need to save the data from the pbuffer */ IUnknown *targetContainer = NULL; - if (WINED3D_OK == IWineD3DSurface_GetContainer(This->renderTarget, &IID_IWineD3DBaseTexture, (void **)&targetContainer) - || WINED3D_OK == IWineD3DSurface_GetContainer(This->renderTarget, &IID_IWineD3DDevice, (void **)&targetContainer)) { + if (wined3d_settings.offscreen_selected_mode == OFFSCREEN_PBUFFER && + (WINED3D_OK == IWineD3DSurface_GetContainer(This->renderTarget, &IID_IWineD3DBaseTexture, (void **)&targetContainer) + || WINED3D_OK == IWineD3DSurface_GetContainer(This->renderTarget, &IID_IWineD3DDevice, (void **)&targetContainer))) { + TRACE("(%p) : Texture rendertarget %p\n", This ,This->renderTarget); /** always dirtify for now. we must find a better way to see that surface have been modified (Modifications should will only occur via draw-primitive, but we do need better locking @@ -7199,34 +7339,34 @@ static HRESULT WINAPI IWineD3DDeviceImpl
static HRESULT WINAPI IWineD3DDeviceImpl_SetDepthStencilSurface(IWineD3DDevice *iface, IWineD3DSurface *pNewZStencil) { IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface; - HRESULT hr = WINED3D_OK; IWineD3DSurface *tmp;
TRACE("(%p) Swapping z-buffer\n",This);
if (pNewZStencil == This->stencilBufferTarget) { TRACE("Trying to do a NOP SetRenderTarget operation\n"); - } else { - /** OpenGL doesn't support 'sharing' of the stencilBuffer so we may incure an extra memory overhead - * depending on the renter target implementation being used. - * A shared context implementation will share all buffers between all rendertargets (including swapchains), - * implementations that use separate pbuffers for different swapchains or rendertargets will have to duplicate the - * stencil buffer and incure an extra memory overhead - ******************************************************/ - - - tmp = This->stencilBufferTarget; - This->stencilBufferTarget = pNewZStencil; - /* should we be calling the parent or the wined3d surface? */ - if (NULL != This->stencilBufferTarget) IWineD3DSurface_AddRef(This->stencilBufferTarget); - if (NULL != tmp) IWineD3DSurface_Release(tmp); - hr = WINED3D_OK; - /** TODO: glEnable/glDisable on depth/stencil depending on - * pNewZStencil is NULL and the depth/stencil is enabled in d3d - **********************************************************/ + return WINED3D_OK; }
- return hr; + /** OpenGL doesn't support 'sharing' of the stencilBuffer so we may incure an extra memory overhead + * depending on the renter target implementation being used. + * A shared context implementation will share all buffers between all rendertargets (including swapchains), + * implementations that use separate pbuffers for different swapchains or rendertargets will have to duplicate the + * stencil buffer and incure an extra memory overhead + ******************************************************/ + + tmp = This->stencilBufferTarget; + This->stencilBufferTarget = pNewZStencil; + /* should we be calling the parent or the wined3d surface? */ + if (NULL != This->stencilBufferTarget) IWineD3DSurface_AddRef(This->stencilBufferTarget); + if (NULL != tmp) IWineD3DSurface_Release(tmp); + /** TODO: glEnable/glDisable on depth/stencil depending on + * pNewZStencil is NULL and the depth/stencil is enabled in d3d + **********************************************************/ + + /* TODO: Unlock texture */ + + return WINED3D_OK; }
@@ -7334,9 +7474,7 @@ static void device_reapply_stateblock(IW This->updateStateBlock = oldUpdateStateBlock; }
-/* Set the device to render to a texture, or not. - * This involves changing renderUpsideDown */ - +/* Set the device to render to a texture */ static void device_render_to_texture(IWineD3DDeviceImpl* This, BOOL isTexture) {
DWORD cullMode; @@ -7352,6 +7490,7 @@ static void device_render_to_texture(IWi /* Set upside-down rendering, and update the cull mode */ /* The surface must be rendered upside down to cancel the flip produced by glCopyTexImage */ This->renderUpsideDown = isTexture; + This->offscreenRendering = isTexture; This->last_was_rhw = FALSE; This->proj_valid = FALSE; IWineD3DDevice_GetRenderState((IWineD3DDevice*) This, WINED3DRS_CULLMODE, &cullMode); @@ -7540,12 +7679,22 @@ #if defined(GL_VERSION_1_3)
/* Reapply the stateblock, and set the device not to render to texture */ device_reapply_stateblock(This); + + /* If the offscreen FBO is being used, switch to the onscreen FBO */ + if (wined3d_settings.offscreen_selected_mode == OFFSCREEN_FBO && This->offscreenRendering) + device_fbo_render_onscreen(This); device_render_to_texture(This, FALSE); }
+ /* Offscreen rendering: FBOs */ + } else if (wined3d_settings.offscreen_selected_mode == OFFSCREEN_FBO) { + + device_fbo_render_offscreen(This, RenderSurface, This->depthStencilBuffer); + device_render_to_texture(This, TRUE); + /* Offscreen rendering: PBuffers (currently disabled). * Also note that this path is never reached if FBOs are supported */ - } else if (pbuffer_support && + } else if (wined3d_settings.offscreen_selected_mode == OFFSCREEN_PBUFFER && (cfgs = device_find_fbconfigs(This, implicitSwapchainImpl, RenderSurface)) != NULL) {
/** ******************************************************************** diff --git a/dlls/wined3d/directx.c b/dlls/wined3d/directx.c index d4a0e97..ef9cdfb 100644 --- a/dlls/wined3d/directx.c +++ b/dlls/wined3d/directx.c @@ -26,7 +26,6 @@ /* Uncomment this to force only a single display mode to be exposed: */ /*#define DEBUG_SINGLE_MODE*/
- #include "config.h" #include "wined3d_private.h"
@@ -237,6 +236,20 @@ static void select_shader_mode( } }
+/* Select the offscreen mode, based on the given capabilities, and flags */ + +static void select_offscreen_mode( + WineD3D_GL_Info *gl_info, + int* offscreen_selected) { + + if (gl_info->supported[EXT_FRAMEBUFFER_OBJECT]) + *offscreen_selected = OFFSCREEN_FBO; + else if (pbuffer_support) + *offscreen_selected = OFFSCREEN_PBUFFER; + else + *offscreen_selected = OFFSCREEN_NONE; +} + /** Select the number of report maximum shader constants based on the selected shader modes */ void select_shader_max_constants(WineD3D_GL_Info *gl_info) {
@@ -1808,6 +1821,7 @@ static HRESULT WINAPI IWineD3DImpl_GetDe } select_shader_mode(&This->gl_info, DeviceType, &wined3d_settings.ps_selected_mode, &wined3d_settings.vs_selected_mode); + select_offscreen_mode(&This->gl_info, &wined3d_settings.offscreen_selected_mode); select_shader_max_constants(&This->gl_info);
/* ------------------------------------------------ @@ -2398,6 +2412,7 @@ static HRESULT WINAPI IWineD3DImpl_Crea LEAVE_GL(); select_shader_mode(&This->gl_info, DeviceType, &wined3d_settings.ps_selected_mode, &wined3d_settings.vs_selected_mode); + select_offscreen_mode(&This->gl_info, &wined3d_settings.offscreen_selected_mode); select_shader_max_constants(&This->gl_info);
temp_result = allocate_shader_constants(object->updateStateBlock); diff --git a/dlls/wined3d/utils.c b/dlls/wined3d/utils.c index e0778c0..40ae793 100644 --- a/dlls/wined3d/utils.c +++ b/dlls/wined3d/utils.c @@ -6,6 +6,7 @@ * Copyright 2004 Christian Costa * Copyright 2005 Oliver Stieber * Copyright 2006 Henri Verbeet + * Copyright 2006 Ivan Gyurdiev * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -47,7 +48,7 @@ static const PixelFormatDesc formats[] = {WINED3DFMT_G8R8_G8B8 ,0x0 ,0x0 ,0x0 ,0x0 ,1/*?*/ ,TRUE ,0 ,0 ,0 }, {WINED3DFMT_R8G8_B8G8 ,0x0 ,0x0 ,0x0 ,0x0 ,1/*?*/ ,TRUE ,0 ,0 ,0 }, /* IEEE formats */ - {WINED3DFMT_R32F ,0x0 ,0x0 ,0x0 ,0x0 ,4 ,FALSE ,GL_RGB32F_ARB ,GL_RED ,GL_FLOAT }, + {WINED3DFMT_R32F ,0x0 ,0x0 ,0x0 ,0x0 ,4 ,FALSE ,GL_RGB32F_ARB ,GL_RED ,GL_FLOAT }, {WINED3DFMT_G32R32F ,0x0 ,0x0 ,0x0 ,0x0 ,8 ,FALSE ,0 ,0 ,0 }, {WINED3DFMT_A32B32G32R32F,0x0 ,0x0 ,0x0 ,0x0 ,16 ,FALSE ,GL_RGBA32F_ARB ,GL_RGBA ,GL_FLOAT }, /* Hmm? */ @@ -646,6 +647,41 @@ #undef POOL_TO_STR } }
+const char* debug_glerror(GLint err) { + switch (err) { +#define GLERR_TO_STR(p) case p: return #p; + GLERR_TO_STR(GL_NO_ERROR); + GLERR_TO_STR(GL_INVALID_ENUM); + GLERR_TO_STR(GL_INVALID_VALUE); + GLERR_TO_STR(GL_INVALID_OPERATION); + GLERR_TO_STR(GL_STACK_OVERFLOW); + GLERR_TO_STR(GL_STACK_UNDERFLOW); + GLERR_TO_STR(GL_OUT_OF_MEMORY); + GLERR_TO_STR(GL_INVALID_FRAMEBUFFER_OPERATION_EXT); +#undef GLERR_TO_STR + default: + FIXME("Unrecognized %u GL error!\n", err); + return "unrecognized"; + } +} + +const char* debug_fbstatus(GLenum status) { + switch (status) { +#define FBSTATUS_TO_STR(p) case p: return #p; + FBSTATUS_TO_STR(GL_FRAMEBUFFER_COMPLETE_EXT); + FBSTATUS_TO_STR(GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT_EXT); + FBSTATUS_TO_STR(GL_FRAMEBUFFER_INCOMPLETE_DIMENSIONS_EXT); + FBSTATUS_TO_STR(GL_FRAMEBUFFER_INCOMPLETE_FORMATS_EXT); + FBSTATUS_TO_STR(GL_FRAMEBUFFER_INCOMPLETE_DRAW_BUFFER_EXT); + FBSTATUS_TO_STR(GL_FRAMEBUFFER_INCOMPLETE_READ_BUFFER_EXT); + FBSTATUS_TO_STR(GL_FRAMEBUFFER_UNSUPPORTED_EXT); +#undef FBSTATUS_TO_STR + default: + FIXME("Unrecognized %#x FB status!\n", status); + return "unrecognized"; + } +} + /***************************************************************************** * Useful functions mapping GL <-> D3D values */ diff --git a/dlls/wined3d/wined3d_private.h b/dlls/wined3d/wined3d_private.h index f103705..7d22c0f 100644 --- a/dlls/wined3d/wined3d_private.h +++ b/dlls/wined3d/wined3d_private.h @@ -5,6 +5,7 @@ * Copyright 2002-2003 Raphael Junqueira * Copyright 2004 Jason Edmeades * Copyright 2005 Oliver Stieber + * Copyright 2006 Ivan Gyurdiev * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -127,6 +128,10 @@ #define VS_SW 2 #define PS_NONE 0 #define PS_HW 1
+#define OFFSCREEN_NONE 0 +#define OFFSCREEN_PBUFFER 1 +#define OFFSCREEN_FBO 2 + #define VBO_NONE 0 #define VBO_HW 1
@@ -156,6 +161,7 @@ typedef struct wined3d_settings_s { BOOL glslRequested; int vs_selected_mode; int ps_selected_mode; + int offscreen_selected_mode; /* nonpower 2 function */ int nonpower2_mode; int rendertargetlock_mode; @@ -225,18 +231,28 @@ #define MAX_PALETTES 256
/* Checking of API calls */ /* --------------------- */ -#define checkGLcall(A) \ -{ \ - GLint err = glGetError(); \ - if (err == GL_NO_ERROR) { \ - TRACE("%s call ok %s / %d\n", A, __FILE__, __LINE__); \ - \ - } else do { \ - FIXME(">>>>>>>>>>>>>>>>> %x from %s @ %s / %d\n", \ - err, A, __FILE__, __LINE__); \ - err = glGetError(); \ - } while (err != GL_NO_ERROR); \ -} +const char* debug_glerror(GLint err); +#define checkGLcall(A) \ +{ \ + GLint err = glGetError(); \ + if (err == GL_NO_ERROR) { \ + TRACE("%s call ok %s / %d\n", A, __FILE__, __LINE__); \ + \ + } else do { \ + FIXME(">>>>>>>>>>>>>>>>> %s returned from %s @ %s / %d\n", \ + debug_glerror(err), A, __FILE__, __LINE__); \ + err = glGetError(); \ + } while (err != GL_NO_ERROR); \ +} + +const char* debug_fbstatus(GLenum status); +#define checkGLfbstatus() \ +{ \ + GLenum status = GL_EXTCALL(glCheckFramebufferStatusEXT(GL_FRAMEBUFFER_EXT)); \ + if (status != GL_FRAMEBUFFER_COMPLETE_EXT) \ + FIXME(">>>>>>>>>>>>>>>> %s: incomplete framebuffer status\n", \ + debug_fbstatus(status)); \ +}
/* Trace routines / diagnostics */ /* ---------------------------- */ @@ -309,17 +325,17 @@ #endif
/* Checking of per-vertex related GL calls */ /* --------------------- */ -#define vcheckGLcall(A) \ -{ \ - GLint err = glGetError(); \ - if (err == GL_NO_ERROR) { \ - VTRACE(("%s call ok %s / %d\n", A, __FILE__, __LINE__)); \ - \ - } else do { \ - FIXME(">>>>>>>>>>>>>>>>> %x from %s @ %s / %d\n", \ - err, A, __FILE__, __LINE__); \ - err = glGetError(); \ - } while (err != GL_NO_ERROR); \ +#define vcheckGLcall(A) \ +{ \ + GLint err = glGetError(); \ + if (err == GL_NO_ERROR) { \ + VTRACE(("%s call ok %s / %d\n", A, __FILE__, __LINE__)); \ + \ + } else do { \ + FIXME(">>>>>>>>>>>>>>>>> %s returned from %s @ %s / %d\n", \ + debug_glerror(err), A, __FILE__, __LINE__); \ + err = glGetError(); \ + } while (err != GL_NO_ERROR); \ }
/* TODO: Confirm each of these works when wined3d move completed */ @@ -483,6 +499,7 @@ void dumpResources(ResourceList *resourc /***************************************************************************** * IWineD3DDevice implementation structure */ + typedef struct IWineD3DDeviceImpl { /* IUnknown fields */ @@ -562,8 +579,13 @@ #define NEEDS_DI HRESULT state; BOOL d3d_initialized;
- /* Screen buffer resources */ + /* Screen buffer resources. */ glContext contextCache[CONTEXT_CACHE]; + GLuint offscreenFBO; + GLuint offscreenRBO[2]; +#define OFFSCREEN_RBO_DEPTH 0 +#define OFFSCREEN_RBO_STENCIL 1 + BOOL offscreenRendering;
/* A flag to check if endscene has been called before changing the render tartet */ BOOL sceneEnded; diff --git a/include/wine/wined3d_gl.h b/include/wine/wined3d_gl.h index 1a589a5..d570d8c 100644 --- a/include/wine/wined3d_gl.h +++ b/include/wine/wined3d_gl.h @@ -1023,6 +1023,7 @@ #define GL_HILO8_NV #define GL_SIGNED_HILO8_NV 0x885F #define GL_FORCE_BLUE_TO_ONE_NV 0x8860 #endif + /* GL_ATI_texture_env_combine3 */ #ifndef GL_ATI_texture_env_combine3 #define GL_ATI_texture_env_combine3 1
On Thursday 07 September 2006 23:50, Ivan Gyurdiev wrote:
(3) Attempting to use GL_STENCIL_INDEX8_EXT in glRenderbufferStorageEXT will fail on my hardware with GL_INVALID_OPERATION.
I've found that the only way to get a stencil buffer with an FBO is to use a packed stencil/depth buffer. Just create the packed buffer, and set it as both the depth buffer and stencil buffer when needed.
On 08/09/06, Chris Robinson chris.kcat@gmail.com wrote:
On Thursday 07 September 2006 23:50, Ivan Gyurdiev wrote:
(3) Attempting to use GL_STENCIL_INDEX8_EXT in glRenderbufferStorageEXT will fail on my hardware with GL_INVALID_OPERATION.
I've found that the only way to get a stencil buffer with an FBO is to use a packed stencil/depth buffer. Just create the packed buffer, and set it as both the depth buffer and stencil buffer when needed.
Correct. We actually need to do this for D3D anyway.
H. Verbeet wrote:
On 08/09/06, Chris Robinson chris.kcat@gmail.com wrote:
On Thursday 07 September 2006 23:50, Ivan Gyurdiev wrote:
(3) Attempting to use GL_STENCIL_INDEX8_EXT in
glRenderbufferStorageEXT
will fail on my hardware with GL_INVALID_OPERATION.
I've found that the only way to get a stencil buffer with an FBO is to use a packed stencil/depth buffer. Just create the packed buffer, and set it as both the depth buffer and stencil buffer when needed.
Correct. We actually need to do this for D3D anyway.
http://www.opengl.org/registry/specs/NV/packed_depth_stencil.txt This is NV-only, and doesn't seem to describe the proper interaction w/ FBOs (is it supported)?
http://www.opengl.org/registry/specs/EXT/packed_depth_stencil.txt This one's marked "incomplete", and I can't find the relevant constants in the GL headers. [yes, my card supports it, however ]
Which do you suggest we use?
On 08/09/06, Ivan Gyurdiev ivg231@gmail.com wrote:
http://www.opengl.org/registry/specs/NV/packed_depth_stencil.txt This is NV-only, and doesn't seem to describe the proper interaction w/ FBOs (is it supported)? From what I've read about depth/stencil buffers and FBOs,
packed_depth_stencil is currently the only way to attach a depth or stencil buffer to an FBO an have it work. Also see http://www.opengl.org/cgi-bin/ubb/ultimatebb.cgi
http://www.opengl.org/registry/specs/EXT/packed_depth_stencil.txt This one's marked "incomplete", and I can't find the relevant constants in the GL headers. [yes, my card supports it, however ]
Which do you suggest we use?
Typically we should use the EXT version. However, I don't know if ATI supports supports either extension, or if we even need it there.
On Friday 08 September 2006 01:04, H. Verbeet wrote:
packed_depth_stencil is currently the only way to attach a depth or stencil buffer to an FBO an have it work.
I don't believe so. I'm quite sure I was able to use a depth-only buffer and attach it to an FBO. However, I couldn't attach a stencil buffer unless it was a packed depth+stencil buffer (and probably the same buffer that was attached as the depth buffer; though I never tested that).
(2) Attempting to bind a framebuffer using GL_RGB32F_ARB, and GL_RGBA32F_ARB formats will fail on my hardware (Nvidia GeForce 6800GS) with error GL_FRAMEBUFFER_UNSUPPORTED_EXT, which means the format combination was invalid for implementation-dependent reasons. However, this doesn't make sense, based on information online, which indicates this should work. See: http://www.mathematik.uni-dortmund.de/~goeddeke/gpgpu/tutorial.htm : "Using textures as render targets".... or google. This is a problem, since certain demos which make use of the R32F format won't work with FBOs - but oddly work with pbuffers. See SoftShadowsII: http://www.humus.ca/index.php?page=3D&&start=8 On the other hand I know R16F -> GL_RGB16F works fine, based on 3Dc demo.
I'm seeing in quite a few places that this must be done to fix the issue of floating point textures: GL_TEXTURE_WRAP_S -> GL_CLAMP_TO_EDGE GL_TEXTURE_WRAP_T -> GL_CLAMP_TO_EDGE GL_TEXTURE_MIN -> GL_NEAREST GL_TEXTURE_MAG -> GL_NEAREST
Hmmm.. not quite sure where to change it though..