Implement render targets using either textures, swapchains or
standalone surfaces.
diff --git a/dlls/d3d9/device.c b/dlls/d3d9/device.c
index d57f989..e1f3f67 100644
--- a/dlls/d3d9/device.c
+++ b/dlls/d3d9/device.c
@@ -374,53 +374,61 @@
/* TODO: move to wineD3D */
HRESULT WINAPI IDirect3DDevice9Impl_SetRenderTarget(LPDIRECT3DDEVICE9 iface, DWORD RenderTargetIndex, IDirect3DSurface9* pRenderTarget) {
IDirect3DDevice9Impl *This = (IDirect3DDevice9Impl *)iface;
- HRESULT hr = S_OK;
-
- /* If pRenderTarget == NULL, it seems to default to back buffer */
- if (pRenderTarget == NULL) pRenderTarget = (IDirect3DSurface9*) This->backBuffer;
-
- /* If we are trying to set what we already have, don't bother */
- if ((IDirect3DSurface9Impl*) pRenderTarget == This->renderTarget) {
- TRACE("Trying to do a NOP SetRenderTarget operation\n");
- } else {
- /* Otherwise, set the render target up */
- TRACE("(%p) : newRender@%p (default is backbuffer=(%p))\n", This, pRenderTarget, This->backBuffer);
- hr = E_FAIL; /* not supported yet */
- }
-
- return hr;
+ IDirect3DSurface9Impl *pSurface = (IDirect3DSurface9Impl*)pRenderTarget;
+ TRACE("(%p) Relay\n" , This);
+ return IWineD3DDevice_SetRenderTarget(This->WineD3DDevice,RenderTargetIndex,(IWineD3DSurface*)pSurface->wineD3DSurface);
}
-/* TODO: move to wineD3D */
-HRESULT WINAPI IDirect3DDevice9Impl_GetRenderTarget(LPDIRECT3DDEVICE9 iface, DWORD RenderTargetIndex, IDirect3DSurface9** ppRenderTarget) {
+HRESULT WINAPI IDirect3DDevice9Impl_GetRenderTarget(LPDIRECT3DDEVICE9 iface, DWORD RenderTargetIndex, IDirect3DSurface9 **ppRenderTarget) {
IDirect3DDevice9Impl *This = (IDirect3DDevice9Impl *)iface;
- TRACE("(%p)->returning (%p) default is backbuffer=(%p)\n", This, This->renderTarget, This->backBuffer);
- *ppRenderTarget = (LPDIRECT3DSURFACE9) This->renderTarget;
- IDirect3DSurface9Impl_AddRef((LPDIRECT3DSURFACE9) *ppRenderTarget);
- return D3D_OK;
+ HRESULT hr = D3D_OK;
+ IWineD3DSurface *pRenderTarget;
+
+ TRACE("(%p) Relay\n" , This);
+
+ if (ppRenderTarget == NULL) {
+ return D3DERR_INVALIDCALL;
+ }
+ hr=IWineD3DDevice_GetRenderTarget(This->WineD3DDevice,RenderTargetIndex,&pRenderTarget);
+
+ if (hr == D3D_OK && pRenderTarget != NULL) {
+ IWineD3DResource_GetParent((IWineD3DResource *)pRenderTarget,(IUnknown**)ppRenderTarget);
+ IWineD3DResource_Release((IWineD3DResource *)pRenderTarget);
+ } else {
+ FIXME("Call to IWineD3DDevice_GetRenderTarget failed\n");
+ *ppRenderTarget = NULL;
+ }
+ return hr;
}
-/* TODO: move to wineD3D */
HRESULT WINAPI IDirect3DDevice9Impl_SetDepthStencilSurface(LPDIRECT3DDEVICE9 iface, IDirect3DSurface9* pZStencilSurface) {
IDirect3DDevice9Impl *This = (IDirect3DDevice9Impl *)iface;
- HRESULT hr = S_OK;
- /* If we are trying to set what we already have, don't bother */
- if ((IDirect3DSurface9Impl*) pZStencilSurface == This->stencilBufferTarget) {
- TRACE("Trying to do a NOP SetDepthStencilSurface operation\n");
- } else {
- /* Otherwise, set the target up */
- TRACE("(%p) : newDepthStencil@%p (default is stencilbuffer=(%p))\n", This, pZStencilSurface, This->depthStencilBuffer);
- hr = E_FAIL; /* not supported yet */
- }
- return D3D_OK;
+ IDirect3DSurface9Impl *pSurface;
+
+ TRACE("(%p) Relay\n" , This);
+
+ pSurface = (IDirect3DSurface9Impl*)pZStencilSurface;
+ return IWineD3DDevice_SetDepthStencilSurface(This->WineD3DDevice,NULL==pSurface?NULL:(IWineD3DSurface*)pSurface->wineD3DSurface);
}
-/* TODO: move to wineD3D */
-HRESULT WINAPI IDirect3DDevice9Impl_GetDepthStencilSurface(LPDIRECT3DDEVICE9 iface, IDirect3DSurface9** ppZStencilSurface) {
+HRESULT WINAPI IDirect3DDevice9Impl_GetDepthStencilSurface(LPDIRECT3DDEVICE9 iface, IDirect3DSurface9 **ppZStencilSurface) {
IDirect3DDevice9Impl *This = (IDirect3DDevice9Impl *)iface;
- TRACE("(%p)->returning (%p) default is stencilbuffer=(%p)\n", This, This->stencilBufferTarget, This->depthStencilBuffer);
- *ppZStencilSurface = (LPDIRECT3DSURFACE9) This->stencilBufferTarget;
- if (NULL != *ppZStencilSurface) IDirect3DSurface9Impl_AddRef((LPDIRECT3DSURFACE9) *ppZStencilSurface);
+ HRESULT hr = D3D_OK;
+ IWineD3DSurface *pZStencilSurface;
+
+ TRACE("(%p) Relay\n" , This);
+ if(ppZStencilSurface == NULL){
+ return D3DERR_INVALIDCALL;
+ }
+
+ hr=IWineD3DDevice_GetDepthStencilSurface(This->WineD3DDevice,&pZStencilSurface);
+ if(hr == D3D_OK && pZStencilSurface != NULL){
+ IWineD3DResource_GetParent((IWineD3DResource *)pZStencilSurface,(IUnknown**)ppZStencilSurface);
+ IWineD3DResource_Release((IWineD3DResource *)pZStencilSurface);
+ }else{
+ FIXME("Call to IWineD3DDevice_GetRenderTarget failed\n");
+ *ppZStencilSurface = NULL;
+ }
return D3D_OK;
}
diff --git a/dlls/wined3d/device.c b/dlls/wined3d/device.c
index cd4ad15..5c226f3 100644
--- a/dlls/wined3d/device.c
+++ b/dlls/wined3d/device.c
@@ -4355,7 +4355,7 @@
/* If the container of the rendertarget is a texture then we need to save the data from the pbuffer */
IUnknown *targetContainer = NULL;
if (D3D_OK == IWineD3DSurface_GetContainer(This->renderTarget, &IID_IWineD3DBaseTexture, (void **)&targetContainer)) {
- TRACE("RenderTarget is either standalone of a texture.\n");
+ 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
switching to render-to-texture should remove the overhead though.
@@ -4365,6 +4365,15 @@
IWineD3DBaseTexture_PreLoad((IWineD3DBaseTexture *)targetContainer);
IWineD3DSurface_SetPBufferState(This->renderTarget, FALSE /* inPBuffer */, FALSE /* inTexture */);
IUnknown_Release(targetContainer);
+ } else
+ if (D3D_OK == IWineD3DSurface_GetContainer(This->renderTarget, &IID_IWineD3DDevice, (void **)&targetContainer)){
+ /* The surface is stand-alone, so doesn't currently have a context of it's own */
+ TRACE("(%p) : standalone rendertarget %p\n", This, This->renderTarget);
+ IWineD3DSurface_SetPBufferState(This->renderTarget, TRUE /* inPBuffer */, FALSE /* inTexture */);
+ IWineD3DSurface_AddDirtyRect(This->renderTarget, NULL);
+ IWineD3DSurface_PreLoad(This->renderTarget);
+ IWineD3DSurface_SetPBufferState(This->renderTarget, FALSE /* inPBuffer */, FALSE /* inTexture */);
+ IUnknown_Release(targetContainer);
}
}
@@ -4804,18 +4813,486 @@
return D3D_OK;
}
-HRESULT WINAPI IWineD3DDeviceImpl_SetRenderTarget(IWineD3DDevice *iface, DWORD RenderTargetIndex, IWineD3DSurface *pRenderTarget){
- IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *) iface;
+/* internal static helper functions */
+HRESULT WINAPI static IWineD3DDeviceImpl_ActiveRender(IWineD3DDevice* iface,
+ IWineD3DSurface *RenderSurface);
- FIXME("(%p) : stub\n", This);
- return D3D_OK;
+HRESULT WINAPI static IWineD3DDeviceImpl_CleanRender(IWineD3DDevice* iface, IWineD3DSwapChainImpl *swapchain);
+
+HRESULT WINAPI IWineD3DDeviceImpl_SetRenderTarget(IWineD3DDevice *iface, DWORD RenderTargetIndex, IWineD3DSurface *pRenderTarget){
+ IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
+ HRESULT hr = D3D_OK;
+ WINED3DVIEWPORT viewport;
+
+ TRACE("(%p) Swapping rendertarget\n",This);
+ if (RenderTargetIndex>0) {
+ FIXME("(%p) Render targets other than the first are not supported\n",This);
+ RenderTargetIndex=0;
+ }
+
+ /* MSDN says that null disables the render target
+ but a device must always be associatated with a render target
+ nope MSDN says that we return invalid call to a null rendertarget with an index of 0
+
+ see http://msdn.microsoft.com/library/default.asp?url=/library/en-us/directx9_c/directx/graphics/programmingguide/AdvancedTopics/PixelPipe/MultipleRenderTarget.asp
+ for more details
+ */
+ if (RenderTargetIndex == 0 && pRenderTarget == NULL) {
+ FIXME("Trying to set render target 0 to NULL\n");
+ return D3DERR_INVALIDCALL;
+ }
+ /* TODO: raplce Impl* usage with interface usage */
+ if (!((IWineD3DSurfaceImpl *)pRenderTarget)->resource.usage & D3DUSAGE_RENDERTARGET) {
+ FIXME("(%p)Trying to set the render target to a surface(%p) that wasn't created with a usage of D3DUSAGE_RENDERTARGET\n",This ,pRenderTarget);
+ return D3DERR_INVALIDCALL;
+ }
+ /** TODO: check that the depth stencil format matches the render target, this is only done in debug
+ * builds, but I think wine counts as a 'debug' build for now.
+ ******************************/
+ /* If we are trying to set what we already have, don't bother */
+ if (pRenderTarget == This->renderTarget) {
+ TRACE("Trying to do a NOP SetRenderTarget operation\n");
+ } else {
+ /* Otherwise, set the render target up */
+ TRACE("clearing renderer\n");
+ /* IWineD3DDeviceImpl_CleanRender(iface); */
+ /* OpenGL doesn't support 'sharing' of the stencilBuffer so we may incure an extra memory overhead
+ depending on the renter target implemenattion being used.
+ A shared context implementation will share all buffers between all rendertargets (including swapchains),
+ implemenations that use serperate pbuffers for different swapchains or rendertargets will have to duplicate the
+ stencil buffer and incure an extra memory overhead */
+ hr = IWineD3DDeviceImpl_ActiveRender(iface, pRenderTarget);
+ }
+
+ if (SUCCEEDED(hr)) {
+ /* Finally, reset the viewport as the MSDN states. */
+ /* TODO: Repalace impl usage */
+ viewport.Height = ((IWineD3DSurfaceImpl *)This->renderTarget)->currentDesc.Height;
+ viewport.Width = ((IWineD3DSurfaceImpl *)This->renderTarget)->currentDesc.Width;
+ viewport.X = 0;
+ viewport.Y = 0;
+ viewport.MaxZ = 1.0f;
+ viewport.MinZ = 0.0f;
+ IWineD3DDeviceImpl_SetViewport(iface, &viewport);
+ }else{
+ FIXME("Unknown error setting the render target\n");
+ }
+ return hr;
}
HRESULT WINAPI IWineD3DDeviceImpl_SetDepthStencilSurface(IWineD3DDevice *iface, IWineD3DSurface *pNewZStencil){
- IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *) iface;
+ IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
+ HRESULT hr = D3D_OK;
+ WINED3DVIEWPORT viewport;
+ IWineD3DSurface *tmp;
- FIXME("(%p) : stub\n", This);
- return D3D_OK;
+ 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 implemenattion being used.
+ * A shared context implementation will share all buffers between all rendertargets (including swapchains),
+ * implemenations that use serperate 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 = D3D_OK;
+ /** TODO: glEnable/glDisable on depth/stencil depending on
+ * pNewZStencil is NULL and the depth/stencil is enabled in d3d
+ **********************************************************/
+ }
+
+ if (SUCCEEDED(hr)) {
+ /* Finally, reset the viewport as the MSDN states.*/
+ /* TODO: get ridd of Impl usage */
+ viewport.Height = ((IWineD3DSurfaceImpl *)This->renderTarget)->currentDesc.Height;
+ viewport.Width = ((IWineD3DSurfaceImpl *)This->renderTarget)->currentDesc.Width;
+ viewport.X = 0;
+ viewport.Y = 0;
+ viewport.MaxZ = 1.0f;
+ viewport.MinZ = 0.0f;
+ IWineD3DDeviceImpl_SetViewport(iface, &viewport);
+ }
+
+ return hr;
+}
+
+
+/* Internal functions not in DirectX */
+ /** TODO: move this off to the opengl context manager
+ *(the swapchain doesn't need to know anything about offscreen rendering!)
+ ****************************************************/
+
+HRESULT WINAPI IWineD3DDeviceImpl_CleanRender(IWineD3DDevice* iface, IWineD3DSwapChainImpl *swapchain)
+{
+ IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
+#if defined(GL_VERSION_1_3) /* @see comments on ActiveRender */
+
+ TRACE("(%p), %p\n", This, swapchain);
+
+ if (swapchain->win != swapchain->drawable) {
+ ENTER_GL();
+ if (swapchain->glCtx != swapchain->render_ctx) {
+ FIXME("Destroying context %p \n", swapchain->render_ctx);
+ glXDestroyContext(swapchain->display, swapchain->render_ctx);
+
+ }
+ FIXME("glXDestroyPbuffer %ld \n", swapchain->drawable);
+ glXDestroyPbuffer(swapchain->display, swapchain->drawable);
+#endif
+ LEAVE_GL();
+ /* Set everything back to the way that it ws */
+ swapchain->render_ctx = swapchain->glCtx;
+ swapchain->drawable = swapchain->win;
+ }
+ return D3D_OK;
+}
+
+/** FIXME: This is currently used called whenever SetRenderTarget or SetStencilBuffer are called
+* the functiolaity needs splitting up so that we don't do more than we should do.
+* this only seems to affect performance a little.
+ ******************************/
+HRESULT WINAPI IWineD3DDeviceImpl_ActiveRender(IWineD3DDevice* iface,
+ IWineD3DSurface *RenderSurface) {
+ IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
+#ifndef USE_RENDER_MANAGER
+
+ IWineD3DSurface *StencilSurface = This->stencilBufferTarget;
+ HRESULT ret = D3DERR_INVALIDCALL;
+ /**
+ * Currently only active for GLX >= 1.3
+ * for others versions we'll have to use GLXPixmaps
+ *
+ * normally we must test GLX_VERSION_1_3 but nvidia headers are not correct
+ * as they implements GLX 1.3 but only define GLX_VERSION_1_2
+ * so only check OpenGL version
+ * ..........................
+ * I don't belive that it is a problem with NVidia headers,
+ * XFree only supports GLX1.2, nVidia (and ATI to some extent) provide 1.3 functions
+ * in GLX 1.2, there is no mention of the correct way to tell if the extensions are provided.
+ * ATI Note:
+ * Your application will report GLX version 1.2 on glXQueryVersion.
+ * However, it is safe to call the GLX 1.3 functions as described below.
+ */
+#if defined(GL_VERSION_1_3)
+
+ /** TODO: we only need to look up the configuration !IF! we are setting the target to a texture **/
+ GLXFBConfig* cfgs = NULL;
+ int nCfgs = 0;
+ int attribs[256];
+ int nAttribs = 0;
+ IWineD3DSwapChain *currentSwapchain;
+ IWineD3DSwapChainImpl *swapchain;
+ /** TODO: get rid of Impl usage we should always create a zbuffer/stencil with our contexts if pussible,
+ * but switch them off if the StencilSurface is set to NULL
+ ** *********************************************************/
+ D3DFORMAT BackBufferFormat = ((IWineD3DSurfaceImpl *) RenderSurface)->resource.format;
+ D3DFORMAT StencilBufferFormat = (NULL != StencilSurface) ? ((IWineD3DSurfaceImpl *) StencilSurface)->resource.format : 0;
+#if 0
+ UINT Width = ((IWineD3DSurfaceImpl *) RenderSurface)->currentDesc.Width;
+ UINT Height = ((IWineD3DSurfaceImpl *) RenderSurface)->currentDesc.Height;
+#endif
+ IWineD3DSurface *tmp;
+
+ /**TODO:
+ if StencilSurface == NULL && zBufferTarget != NULL then swtich the zbuffer off,
+ it StencilSurface != NULL && zBufferTarget == NULL switch it on
+ */
+
+#define PUSH1(att) attribs[nAttribs++] = (att);
+#define PUSH2(att,value) attribs[nAttribs++] = (att); attribs[nAttribs++] = (value);
+
+ /* PUSH2(GLX_BIND_TO_TEXTURE_RGBA_ATI, True); examples of this are few and far between (but I've got a nice working one!)*/
+
+ /** TODO: remove the reff to Impl (context manager should fis this!) **/
+ IWineD3DSwapChainImpl *impSwapChain;
+ IWineD3DDevice_GetSwapChain(iface, 0, (IWineD3DSwapChain **)&impSwapChain);
+ if (NULL == impSwapChain){ /* NOTE: This should NEVER fail */
+ ERR("(%p) Failed to get a the implicite swapchain\n", iface);
+ }
+
+ ENTER_GL();
+
+ PUSH2(GLX_DRAWABLE_TYPE, GLX_PBUFFER_BIT);
+ PUSH2(GLX_X_RENDERABLE, TRUE);
+ PUSH2(GLX_DOUBLEBUFFER, TRUE);
+ TRACE("calling makeglcfg\n");
+ D3DFmtMakeGlCfg(BackBufferFormat, StencilBufferFormat, attribs, &nAttribs, FALSE /* alternate */);
+
+ PUSH1(None);
+
+
+ TRACE("calling chooseFGConfig\n");
+ cfgs = glXChooseFBConfig(impSwapChain->display, DefaultScreen(impSwapChain->display),
+ attribs, &nCfgs);
+
+ if (!cfgs){ /* OK we didn't find the exact config, so use any reasonably match */
+ /* TODO: fill in the 'requested' and 'current' depths, also make sure that's
+ why we failed and only show this message once! */
+ MESSAGE("Failed to find exact match, finding alternative but you may suffer performance issues, try changing xfree's depth to match the requested depth\n"); /**/
+ nAttribs = 0;
+ PUSH2(GLX_DRAWABLE_TYPE, GLX_PBUFFER_BIT | GLX_WINDOW_BIT);
+ /* PUSH2(GLX_X_RENDERABLE, TRUE); */
+ PUSH2(GLX_RENDER_TYPE, GLX_RGBA_BIT);
+ PUSH2(GLX_DOUBLEBUFFER, FALSE);
+ TRACE("calling makeglcfg\n");
+ D3DFmtMakeGlCfg(BackBufferFormat, StencilBufferFormat, attribs, &nAttribs, TRUE /* alternate */);
+ PUSH1(None);
+ cfgs = glXChooseFBConfig(impSwapChain->display, DefaultScreen(impSwapChain->display),
+ attribs, &nCfgs);
+ }
+
+#if 0
+#ifdef EXTRA_TRACES
+ int i;
+ for (i = 0; i < nCfgs; ++i) {
+ TRACE("for (%u,%s)/(%u,%s) found config[%d]@%p\n", BackBufferFormat,
+ debug_d3dformat(BackBufferFormat), StencilBufferFormat,
+ debug_d3dformat(StencilBufferFormat), i, cfgs[i]);
+ }
+#endif
+#endif
+ if (NULL != This->renderTarget) {
+#ifdef EXTRA_TRACES
+ glFlush();
+ vcheckGLcall("glFlush");
+ /** This is only usefuly if the old render target was a swapchain,
+ * we need to supercede this with a function that displays
+ * the current buffer on the screen. This is easy to do in glx1.3 but
+ * we need to do copy-write pixels in glx 1.2.
+ ************************************************/
+ glXSwapBuffers(impSwapChain->display, impSwapChain->drawable);
+
+ printf("Hit Enter to get next frame ...\n");
+ getchar();
+#endif
+ }
+
+ if (IWineD3DSurface_GetContainer(This->renderTarget, &IID_IWineD3DSwapChain, (void **)¤tSwapchain) != D3D_OK){
+ /* the selected render target doesn't belong to a swapchain, so use the devices implicite swapchain */
+ IWineD3DDevice_GetSwapChain(iface, 0, ¤tSwapchain);
+ }
+
+ /**
+ * TODO: remove the use of IWineD3DSwapChainImpl, a context manager will help since it will replace the
+ * renderTarget = swapchain->backBuffer bit and anything to do with *glContexts
+ **********************************************************************/
+ if (IWineD3DSurface_GetContainer(RenderSurface, &IID_IWineD3DSwapChain, (void **)&swapchain) == D3D_OK){
+ /* We also need to make sure that the lights &co are also in the context of the swapchains */
+ /* FIXME: If the render target gets sent to the frontBuffer should be be presenting it raw? */
+ TRACE("making swapchain active\n");
+ if (RenderSurface != This->renderTarget){
+ if (RenderSurface == swapchain->backBuffer){
+ } else {
+ /* This could be flagged so that some operations work directly with the front buffer */
+ FIXME("Attempting to set the renderTarget to the frontBuffer\n");
+ }
+ if (glXMakeCurrent(swapchain->display, swapchain->win, swapchain->glCtx)
+ == False) {
+ TRACE("Error in setting current context: context %p drawable %ld !\n",
+ impSwapChain->glCtx, impSwapChain->win);
+ }
+
+
+#if 0 /* TODO: apply the state block to the 'possibly' new context. */
+ BOOL oldRecording;
+ IWineD3DStateBlockImpl *oldUpdateStateBlock;
+ oldUpdateStateBlock = This->updateStateBlock;
+ oldRecording= This->isRecordingState;
+ This->isRecordingState = FALSE;
+ This->updateStateBlock = This->stateBlock;
+ IWineD3DStateBlock_Apply((IWineD3DStateBlock *)This->stateBlock);
+
+ This->isRecordingState = oldRecording;
+ This->updateStateBlock = oldUpdateStateBlock;
+#endif
+
+ IWineD3DDeviceImpl_CleanRender(iface, (IWineD3DSwapChainImpl *)currentSwapchain);
+ }
+ checkGLcall("glXMakeContextCurrent");
+
+ IWineD3DSwapChain_Release((IWineD3DSwapChain *)swapchain);
+ }
+#if 0
+ else
+ if (NULL != cfgs &&
+ (((IWineD3DSwapChainImpl *)currentSwapchain)->drawable == ((IWineD3DSwapChainImpl *)currentSwapchain)->win
+ || BackBufferFormat != ((IWineD3DSurfaceImpl *)This->renderTarget)->currentDesc.Format
+ || (Width > ((IWineD3DSurfaceImpl *)This->renderTarget)->currentDesc.Width
+ || Height > ((IWineD3DSurfaceImpl *)This->renderTarget)->currentDesc.Height))) {
+
+ /** ********************************************************************
+ * This code is far too leaky to be usefull IWineD3DDeviceImpl_CleanRender
+ * doesn't seem to work properly and creating a new context Every time is 'extream' overkill.
+ * The code does however work, and should be moved to a context manager to
+ * manage caching of pbuffers or render to texture are appropriate.
+ *
+ * There are some real speed vs compatability issues here:
+ * we should really use a new context for every texture, but that eats ram.
+ * we should also be restoring the texture to the pbuffer but that eats CPU
+ * we can also 'reuse' the current pbuffer if the size is larger than the requested buffer,
+ * but if this means reusing the display backbuffer then we need to make sure that
+ * states are correctly preserved.
+ * In many cases I would expect that we can 'skip' some functions, such as preserving states,
+ * and gain a good performance increase at the cost of compatability.
+ * I would suggest that, when this is the case, a user configurable flag be made
+ * available, alowing the user to choose the best emmulated experiance for them.
+ *********************************************************************/
+
+ /**
+ * TODO: support for faces of cube textures, possibly volumes
+ * (this should be easy for ATI as I have examples)
+ **/
+
+ GLXContext newContext;
+ Drawable newDrawable;
+ XVisualInfo *visinfo;
+
+ TRACE("making new buffer\n");
+ nAttribs = 0;
+ PUSH2(GLX_PBUFFER_WIDTH, Width);
+ PUSH2(GLX_PBUFFER_HEIGHT, Height);
+
+#if 0 /* ATI render to texture support */
+ PUSH2(GLX_LARGEST_PBUFFER, True);/* This is ignored by ATI */
+ PUSH2(GLX_TEXTURE_FORMAT_ATI, GLX_TEXTURE_RGBA_ATI);
+ PUSH2(GLX_TEXTURE_TARGET_ATI, cubemap? GLX_TEXTURE_CUBE_MAP_ATI : GLX_TEXTURE_2D_ATI);
+ PUSH2(GLX_MIPMAP_TEXTURE_ATI, mipmapped? True : False);
+#endif
+
+#if 0
+ /* TODO: discardable Pbuffer */
+ PUSH2(GLX_PRESERVED_CONTENTS, FALSE);
+#endif
+
+ PUSH1(None);
+ newDrawable = glXCreatePbuffer(impSwapChain->display, cfgs[0], attribs);
+
+ /** ****************************************
+ *GLX1.3 isn't supported by XFree 'yet' untill that point ATI emulates pBuffers
+ *they note:
+ * In future releases, we may provide the calls glXCreateNewContext,
+ * glXQueryDrawable and glXMakeContextCurrent.
+ * so until then we have to use glXGetVisualFromFBConfig &co..
+ ********************************************/
+
+
+ visinfo = glXGetVisualFromFBConfig(impSwapChain->display, cfgs[0]);
+ if (!visinfo) {
+ ERR("Error: couldn't get an RGBA, double-buffered visual\n");
+ }
+ newContext = glXCreateContext(impSwapChain->display, visinfo, impSwapChain->glCtx, GL_TRUE);
+ XFree(visinfo);
+
+ /* Make sure that the sorface exists as a glTexture */
+ IWineD3DSurface_PreLoad(RenderSurface);
+
+ newContext = glXCreateNewContext(impSwapChain->display, cfgs[0], GLX_RGBA_TYPE, impSwapChain->glCtx, TRUE);
+
+ if (NULL == newContext) {
+ ERR("cannot create glxContext\n");
+ }else{
+ /* Debug logging, (this function leaks), change to a TRACE when the leak is plugged */
+ FIXME("Created context %p drawable %ld \n", newContext, newDrawable);
+
+ if (glXMakeCurrent(impSwapChain->display, newDrawable, newContext) == False) {
+
+ TRACE("Error in setting current context: context %p drawable %ld\n", newContext, newDrawable);
+ }
+
+ /* TODO: find out what of the current context needs to be coppied accross */
+
+ checkGLcall("glXMakeContextCurrent");
+
+ /* clean renderer should become part of the context manager so I'm not goint to put in in SwapChain just to remove it */
+ IWineD3DDeviceImpl_CleanRender(iface, (IWineD3DSwapChainImpl *)currentSwapchain);
+ /** TODO: We may need to copy the bits into the buffer,
+ * this should !!ONLY!! be done if an operation is performed on the target
+ * without it being cleared and the buffer is not discardable.
+ * (basicly only bother preserving the contents if there's a possiblity that it will be reused)
+ ** *********************************************************************/
+ impSwapChain->drawable = newDrawable;
+ impSwapChain->render_ctx = newContext;
+
+ }
+
+ }
+#endif
+ /* clean up the current rendertargets swapchain (if it belonged to one) */
+ if (currentSwapchain != NULL){
+ IWineD3DSwapChain_Release((IWineD3DSwapChain *)currentSwapchain);
+ }
+
+ /* Were done with the opengl context management, setup the rendertargets */
+
+ tmp = This->renderTarget;
+ This->renderTarget = RenderSurface;
+ IWineD3DSurface_AddRef(This->renderTarget);
+ IWineD3DSurface_Release(tmp);
+
+
+
+ {
+ DWORD value;
+ /* The surface must be rendered upside down to cancel the flip produce by glCopyTexImage */
+ /* Check that the container is not a swapchain member */
+
+ IWineD3DSwapChain *tmpSwapChain;
+ if (D3D_OK != IWineD3DSurface_GetContainer(This->renderTarget, &IID_IWineD3DSwapChain, (void **)&tmpSwapChain)){
+ This->renderUpsideDown = TRUE;
+ }else{
+ This->renderUpsideDown = FALSE;
+ IWineD3DSwapChain_Release(tmpSwapChain);
+ }
+ /* Force updating the cull mode */
+ TRACE("setting render state\n");
+ IWineD3DDevice_GetRenderState(iface, WINED3DRS_CULLMODE, &value);
+ IWineD3DDevice_SetRenderState(iface, WINED3DRS_CULLMODE, value);
+
+ /* Force updating projection matrix */
+ This->last_was_rhw = FALSE;
+ This->proj_valid = FALSE;
+ }
+
+ ret = D3D_OK;
+
+ if (cfgs != NULL){
+ XFree(cfgs);
+ } else {
+ ERR("cannot get valides GLXFBConfig for (%u,%s)/(%u,%s)\n", BackBufferFormat,
+ debug_d3dformat(BackBufferFormat), StencilBufferFormat, debug_d3dformat(StencilBufferFormat));
+ }
+
+#undef PUSH1
+#undef PUSH2
+ if ( NULL != impSwapChain) {
+ IWineD3DSwapChain_Release((IWineD3DSwapChain *)impSwapChain);
+ }
+ LEAVE_GL();
+
+#endif
+#else
+
+ IWineD3DSurface *tmp;
+ /* This should be handled outside of this function */
+ tmp = This->renderTarget;
+ This->renderTarget = RenderSurface;
+ IWineD3DSurface_AddRef(This->renderTarget);
+ IWineD3DSurface_Release( tmp);
+ tmp = This->stencilBufferTarget;
+ This->stencilBufferTarget = StencilSurface;
+
+#endif
+ return ret;
+
}
HRESULT WINAPI IWineD3DDeviceImpl_SetCursorProperties(IWineD3DDevice* iface, UINT XHotSpot,
diff --git a/dlls/wined3d/directx.c b/dlls/wined3d/directx.c
index 4938c88..d77151c 100644
--- a/dlls/wined3d/directx.c
+++ b/dlls/wined3d/directx.c
@@ -1572,7 +1572,6 @@
object->createParms.BehaviorFlags = BehaviourFlags;
/* Initialize other useful values */
- object->presentParms.BackBufferCount = 1; /* Opengl only supports one? */
object->adapterNo = Adapter;
object->devType = DeviceType;
diff --git a/dlls/wined3d/surface.c b/dlls/wined3d/surface.c
index 9b9a2c5..7b4d4df 100644
--- a/dlls/wined3d/surface.c
+++ b/dlls/wined3d/surface.c
@@ -201,6 +201,9 @@
HRESULT WINAPI IWineD3DSurfaceImpl_LockRect(IWineD3DSurface *iface, D3DLOCKED_RECT* pLockedRect, CONST RECT* pRect, DWORD Flags) {
IWineD3DSurfaceImpl *This = (IWineD3DSurfaceImpl *)iface;
+ IWineD3DDeviceImpl *myDevice = This->resource.wineD3DDevice;
+ IWineD3DSwapChainImpl *swapchain = NULL;
+ static UINT messages = 0; /* holds flags to disable fixme messages */
/* fixme: should we really lock as such? */
if (This->inTexture && This->inPBuffer) {
@@ -217,17 +220,23 @@
/*return D3DERR_INVALIDCALL; */
}
- if (iface == This->resource.wineD3DDevice->backBuffer || iface == This->resource.wineD3DDevice->renderTarget ||
- iface == This->resource.wineD3DDevice->frontBuffer || iface == This->resource.wineD3DDevice->depthStencilBuffer) {
- if (iface == This->resource.wineD3DDevice->backBuffer) {
+ IWineD3DSurface_GetContainer(iface, &IID_IWineD3DSwapChain, (void **)&swapchain);
+
+ if (swapchain != NULL || iface == myDevice->renderTarget || iface == myDevice->depthStencilBuffer) {
+ if (swapchain != NULL && iface == swapchain->backBuffer) {
TRACE("(%p, backBuffer) : rect@%p flags(%08lx), output lockedRect@%p, memory@%p\n", This, pRect, Flags, pLockedRect, This->resource.allocatedMemory);
- } else if (iface == This->resource.wineD3DDevice->frontBuffer) {
+ } else if (swapchain != NULL && iface == swapchain->frontBuffer) {
TRACE("(%p, frontBuffer) : rect@%p flags(%08lx), output lockedRect@%p, memory@%p\n", This, pRect, Flags, pLockedRect, This->resource.allocatedMemory);
- } else if (iface == This->resource.wineD3DDevice->renderTarget) {
+ } else if (iface == myDevice->renderTarget) {
TRACE("(%p, renderTarget) : rect@%p flags(%08lx), output lockedRect@%p, memory@%p\n", This, pRect, Flags, pLockedRect, This->resource.allocatedMemory);
- } else if (iface == This->resource.wineD3DDevice->depthStencilBuffer) {
+ } else if (iface == myDevice->depthStencilBuffer) {
TRACE("(%p, stencilBuffer) : rect@%p flags(%08lx), output lockedRect@%p, memory@%p\n", This, pRect, Flags, pLockedRect, This->resource.allocatedMemory);
}
+
+ if (NULL != swapchain) {
+ IWineD3DSwapChain_Release((IWineD3DSwapChain *)swapchain);
+ }
+ swapchain = NULL;
} else {
TRACE("(%p) : rect@%p flags(%08lx), output lockedRect@%p, memory@%p\n", This, pRect, Flags, pLockedRect, This->resource.allocatedMemory);
}
@@ -240,7 +249,7 @@
else if (This->resource.format == WINED3DFMT_DXT3 || This->resource.format == WINED3DFMT_DXT5) /* DXT3/5 is 16 bytes per block */
pLockedRect->Pitch = (This->currentDesc.Width >> 2) << 4;
else
- pLockedRect->Pitch = This->bytesPerPixel * This->currentDesc.Width; /* Bytes / row */
+ pLockedRect->Pitch = This->bytesPerPixel * This->currentDesc.Width; /* Bytes / row */
if (NULL == pRect) {
pLockedRect->pBits = This->resource.allocatedMemory;
@@ -270,38 +279,129 @@
} else if (D3DUSAGE_RENDERTARGET & This->resource.usage && !(Flags&D3DLOCK_DISCARD)) { /* render surfaces */
- if (iface == This->resource.wineD3DDevice->backBuffer || iface == This->resource.wineD3DDevice->renderTarget || iface == This->resource.wineD3DDevice->frontBuffer) {
- GLint prev_store;
- GLenum prev_read;
+ GLint prev_store;
+ GLenum prev_read;
+ BOOL notInContext = FALSE;
+ IWineD3DSwapChainImpl *targetSwapChain = NULL;
- ENTER_GL();
+
+ ENTER_GL();
/**
* for render->surface copy begin to begin of allocatedMemory
* unlock can be more easy
*/
- pLockedRect->pBits = This->resource.allocatedMemory;
- glFlush();
- vcheckGLcall("glFlush");
- glGetIntegerv(GL_READ_BUFFER, &prev_read);
- vcheckGLcall("glIntegerv");
- glGetIntegerv(GL_PACK_SWAP_BYTES, &prev_store);
- vcheckGLcall("glIntegerv");
+ TRACE("locking a render target\n");
- if (iface == This->resource.wineD3DDevice->backBuffer) {
- glReadBuffer(GL_BACK);
- } else if (iface == This->resource.wineD3DDevice->frontBuffer || iface == This->resource.wineD3DDevice->renderTarget) {
- glReadBuffer(GL_FRONT);
- } else if (iface == This->resource.wineD3DDevice->depthStencilBuffer) {
- ERR("Stencil Buffer lock unsupported for now\n");
+ if (This->resource.allocatedMemory == NULL)
+ This->resource.allocatedMemory = HeapAlloc(GetProcessHeap() ,0 ,This->resource.size);
+
+ pLockedRect->pBits = This->resource.allocatedMemory;
+
+ glFlush();
+ vcheckGLcall("glFlush");
+ glGetIntegerv(GL_READ_BUFFER, &prev_read);
+ vcheckGLcall("glIntegerv");
+ glGetIntegerv(GL_PACK_SWAP_BYTES, &prev_store);
+ vcheckGLcall("glIntegerv");
+
+ /* Here's what we have to do:
+ See if the swapchain has the same context as the renderTarget or the surface is the render target.
+ Otherwise, see if were sharing a context with the implicite swapchain (because were using a shared context model!)
+ and use the fron back buffer as required.
+ if not, we need to switch contexts and then switchback at the end.
+ */
+ IWineD3DSurface_GetContainer(iface, &IID_IWineD3DSwapChain, (void **)&swapchain);
+ IWineD3DSurface_GetContainer(myDevice->renderTarget, &IID_IWineD3DSwapChain, (void **)&targetSwapChain);
+
+ /* NOTE: In a shared context environment the renderTarget will use the same context as the implicite swapchain (we're not in a shared environment yet! */
+ if ((swapchain == targetSwapChain && targetSwapChain != NULL) || iface == myDevice->renderTarget) {
+ if (iface == myDevice->renderTarget || iface == swapchain->backBuffer) {
+ TRACE("locking back buffer\n");
+ glReadBuffer(GL_BACK);
+ }else if (iface == swapchain->frontBuffer) {
+ TRACE("locking front\n");
+ glReadBuffer(GL_FRONT);
+ }else if (iface == myDevice->depthStencilBuffer) {
+ FIXME("Stencil Buffer lock unsupported for now\n");
+ } else{
+ FIXME("(%p) Shouldn't have got here!\n", This);
+ glReadBuffer(GL_BACK);
+ }
+ }else if (swapchain != NULL) {
+ IWineD3DSwapChainImpl *implSwapChain;
+ IWineD3DDevice_GetSwapChain((IWineD3DDevice *)myDevice, 0, (IWineD3DSwapChain **)&implSwapChain);
+ if (swapchain->glCtx == implSwapChain->render_ctx && swapchain->drawable == implSwapChain->win) {
+ /* This will fail for the implicite swapchain, which is why there needs to be a context manager */
+ if (iface == swapchain->backBuffer) {
+ glReadBuffer(GL_BACK);
+ }else if (iface == swapchain->frontBuffer) {
+ glReadBuffer(GL_FRONT);
+ } else if (iface == myDevice->depthStencilBuffer) {
+ FIXME("Stencil Buffer lock unsupported for now\n");
+ } else{
+ FIXME("Should have got here!\n");
+ glReadBuffer(GL_BACK);
+ }
+ }else{
+ /* We need to switch contexts to be able to read the buffer!!! */
+ FIXME("The buffer requested isn't in the current openGL context\n");
+ notInContext = TRUE;
+ /* TODO: check the contexts, to see if were shared with the current context */
}
- vcheckGLcall("glReadBuffer");
+ IWineD3DSwapChain_Release((IWineD3DSwapChain *)implSwapChain);
+ }
+ if (swapchain != NULL) IWineD3DSwapChain_Release((IWineD3DSwapChain *)swapchain);
+ if (targetSwapChain != NULL) IWineD3DSwapChain_Release((IWineD3DSwapChain *)targetSwapChain);
- {
- long j;
- GLenum format = D3DFmt2GLFmt(This->resource.wineD3DDevice, This->resource.format);
- GLenum type = D3DFmt2GLType(This->resource.wineD3DDevice, This->resource.format);
+
+ /** the depth stencil in openGL has a format of GL_FLOAT
+ * which should be good for WINED3DFMT_D16_LOCKABLE
+ * and WINED3DFMT_D16
+ * it is unclear what format the stencil buffer is in except.
+ * 'Each index is converted to fixed point...
+ * If GL_MAP_STENCIL is GL_TRUE, indices are replaced by their
+ * mappings in the table GL_PIXEL_MAP_S_TO_S.
+ * glReadPixels(This->lockedRect.left,
+ * This->lockedRect.bottom - j - 1,
+ * This->lockedRect.right - This->lockedRect.left,
+ * 1,
+ * GL_DEPTH_COMPONENT,
+ * type,
+ * (char *)pLockedRect->pBits + (pLockedRect->Pitch * (j-This->lockedRect.top)));
+ *****************************************/
+ if (!notInContext) { /* Only read the buffer if it's in the current context */
+ long j;
+ GLenum format = D3DFmt2GLFmt(myDevice, This->resource.format);
+ GLenum type = D3DFmt2GLType(myDevice, This->resource.format);
+#if 0
+ /* Bizarly it's takes 120 millseconds to get an 800x600 region a line at a time, but only 10 to get the whole lot every time,
+ * This is on an ATI9600, and may be format dependant, anyhow this hack makes this demo dx9_2d_demo_game
+ * run ten times faster!
+ * ************************************/
+ BOOL ati_performance_hack = FALSE;
+ ati_performance_hack = (This->lockedRect.bottom - This->lockedRect.top > 10) || (This->lockedRect.right - This->lockedRect.left > 10)? TRUE: FALSE;
+#endif
+ if ((This->lockedRect.left ==0 && This->lockedRect.top ==0 &&
+ This->lockedRect.right == This->currentDesc.Width
+ && This->lockedRect.bottom == This->currentDesc.Height)) {
+ glReadPixels(0, 0,
+ This->currentDesc.Width,
+ This->currentDesc.Height,
+ format,
+ type,
+ (char *)pLockedRect->pBits);
+ }else if (This->lockedRect.left ==0 && This->lockedRect.right == This->currentDesc.Width) {
+ glReadPixels(0,
+ This->lockedRect.top,
+ This->currentDesc.Width,
+ This->currentDesc.Height,
+ format,
+ type,
+ (char *)pLockedRect->pBits);
+ } else{
+
for (j = This->lockedRect.top; j < This->lockedRect.bottom - This->lockedRect.top; ++j) {
glReadPixels(This->lockedRect.left,
This->lockedRect.bottom - j - 1,
@@ -310,23 +410,32 @@
format,
type,
(char *)pLockedRect->pBits + (pLockedRect->Pitch * (j-This->lockedRect.top)));
- vcheckGLcall("glReadPixels");
+
}
}
-
+ vcheckGLcall("glReadPixels");
+ TRACE("Resetting buffer\n");
glReadBuffer(prev_read);
vcheckGLcall("glReadBuffer");
-
- LEAVE_GL();
-
- } else {
- FIXME("unsupported locking to Rendering surface surf@%p usage(%lu)\n", This, This->resource.usage);
}
+ LEAVE_GL();
} else if (D3DUSAGE_DEPTHSTENCIL & This->resource.usage) { /* stencil surfaces */
- FIXME("TODO stencil depth surface locking surf@%p usage(%lu)\n", This, This->resource.usage);
+ if(!messages & 1){
+ FIXME("TODO stencil depth surface locking surf%p usage(%lu)\n", This, This->resource.usage);
+ /*
+ glReadPixels(This->lockedRect.left,
+ This->lockedRect.bottom - j - 1,
+ This->lockedRect.right - This->lockedRect.left,
+ 1,
+ GL_STENCIL_INDEX or GL_DEPTH_COMPONENT
+
+ )
+ */
+ messages |=1;
+ }
} else {
FIXME("unsupported locking to surface surf@%p usage(%lu)\n", This, This->resource.usage);
}
@@ -341,10 +450,10 @@
*/
IWineD3DSurface_AddDirtyRect(iface, &This->lockedRect);
- /** Dirtify Container if needed */
+ /** Dirtify Container if needed */
if (D3D_OK == IWineD3DSurface_GetContainer(iface, &IID_IWineD3DBaseTexture, (void **)&pBaseTexture) && pBaseTexture != NULL) {
TRACE("Making container dirty\n");
- IWineD3DBaseTexture_SetDirty(pBaseTexture, TRUE);
+ IWineD3DBaseTexture_SetDirty(pBaseTexture, TRUE);
IWineD3DBaseTexture_Release(pBaseTexture);
}else{
TRACE("Surface is standalone, no need to dirty the container\n");
@@ -360,27 +469,33 @@
HRESULT WINAPI IWineD3DSurfaceImpl_UnlockRect(IWineD3DSurface *iface) {
GLint skipBytes = 0;
IWineD3DSurfaceImpl *This = (IWineD3DSurfaceImpl *)iface;
+ IWineD3DDeviceImpl *myDevice = This->resource.wineD3DDevice;
+ const char *buffername = "";
+ IWineD3DSwapChainImpl *swapchain = NULL;
if (FALSE == This->locked) {
- ERR("trying to Unlock an unlocked surf@%p\n", This);
+ WARN("trying to Unlock an unlocked surf@%p\n", This);
return D3DERR_INVALIDCALL;
}
- if (iface== This->resource.wineD3DDevice->backBuffer || iface == This->resource.wineD3DDevice->frontBuffer ||
- iface == This->resource.wineD3DDevice->depthStencilBuffer || iface == This->resource.wineD3DDevice->renderTarget) {
- if (iface == This->resource.wineD3DDevice->backBuffer) {
- TRACE("(%p, backBuffer) : dirtyfied(%d)\n", This, This->Dirty);
- } else if (iface == This->resource.wineD3DDevice->frontBuffer) {
- TRACE("(%p, frontBuffer) : dirtyfied(%d)\n", This, This->Dirty);
- } else if (iface == This->resource.wineD3DDevice->depthStencilBuffer) {
- TRACE("(%p, stencilBuffer) : dirtyfied(%d)\n", This, This->Dirty);
- } else if (iface == This->resource.wineD3DDevice->renderTarget) {
- TRACE("(%p, renderTarget) : dirtyfied(%d)\n", This, This->Dirty);
- }
- } else {
- TRACE("(%p) : dirtyfied(%d)\n", This, This->Dirty);
+ IWineD3DSurface_GetContainer(iface, &IID_IWineD3DSwapChain, (void **)&swapchain);
+
+ if ((swapchain != NULL) && iface == swapchain->backBuffer) {
+ buffername = "backBuffer";
+ } else if ((swapchain != NULL) && iface == swapchain->frontBuffer) {
+ buffername = "frontBuffer";
+ } else if (iface == myDevice->depthStencilBuffer) {
+ buffername = "depthStencilBuffer";
+ } else if (iface == myDevice->renderTarget) {
+ buffername = "renderTarget";
}
+ if (swapchain != NULL) {
+ IWineD3DSwapChain_Release((IWineD3DSwapChain *)swapchain);
+ }
+
+ TRACE("(%p %s) : dirtyfied(%d)\n", This, buffername, This->Dirty);
+
if (FALSE == This->Dirty) {
TRACE("(%p) : Not Dirtified so nothing to do, return now\n", This);
goto unlock_end;
@@ -393,7 +508,16 @@
*/
} else if (D3DUSAGE_RENDERTARGET & This->resource.usage) { /* render surfaces */
- if (iface == This->resource.wineD3DDevice->backBuffer || iface == This->resource.wineD3DDevice->frontBuffer || iface == This->resource.wineD3DDevice->renderTarget) {
+ /****************************
+ * TODO: Render targets are 'special' and
+ * ?some? locking needs to be passed onto the context manager
+ * so that it becomes possible to use auxilary buffers, pbuffers
+ * render-to-texture, shared, cached contexts etc...
+ * ****************************/
+ IWineD3DSwapChainImpl *implSwapChain;
+ IWineD3DDevice_GetSwapChain((IWineD3DDevice *)myDevice, 0, (IWineD3DSwapChain **)&implSwapChain);
+
+ if (iface == implSwapChain->backBuffer || iface == implSwapChain->frontBuffer || iface == myDevice->renderTarget) {
GLint prev_store;
GLenum prev_draw;
GLint prev_rasterpos[4];
@@ -414,10 +538,10 @@
/* glDrawPixels transforms the raster position as though it was a vertex -
we want to draw at screen position 0,0 - Set up ortho (rhw) mode as
per drawprim (and leave set - it will sort itself out due to last_was_rhw */
- if (!This->resource.wineD3DDevice->last_was_rhw) {
+ if (!myDevice->last_was_rhw) {
double X, Y, height, width, minZ, maxZ;
- This->resource.wineD3DDevice->last_was_rhw = TRUE;
+ myDevice->last_was_rhw = TRUE;
/* Transformed already into viewport coordinates, so we do not need transform
matrices. Reset all matrices to identity and leave the default matrix in world
@@ -433,12 +557,12 @@
checkGLcall("glLoadIdentity");
/* Set up the viewport to be full viewport */
- X = This->resource.wineD3DDevice->stateBlock->viewport.X;
- Y = This->resource.wineD3DDevice->stateBlock->viewport.Y;
- height = This->resource.wineD3DDevice->stateBlock->viewport.Height;
- width = This->resource.wineD3DDevice->stateBlock->viewport.Width;
- minZ = This->resource.wineD3DDevice->stateBlock->viewport.MinZ;
- maxZ = This->resource.wineD3DDevice->stateBlock->viewport.MaxZ;
+ X = myDevice->stateBlock->viewport.X;
+ Y = myDevice->stateBlock->viewport.Y;
+ height = myDevice->stateBlock->viewport.Height;
+ width = myDevice->stateBlock->viewport.Width;
+ minZ = myDevice->stateBlock->viewport.MinZ;
+ maxZ = myDevice->stateBlock->viewport.MaxZ;
TRACE("Calling glOrtho with %f, %f, %f, %f\n", width, height, -minZ, -maxZ);
glOrtho(X, X + width, Y + height, Y, -minZ, -maxZ);
checkGLcall("glOrtho");
@@ -449,11 +573,12 @@
checkGLcall("glTranslatef(0.5, 0.5, 0)");
}
- if (iface == This->resource.wineD3DDevice->backBuffer) {
+ if (iface == implSwapChain->backBuffer || iface == myDevice->renderTarget) {
glDrawBuffer(GL_BACK);
- } else if (iface == This->resource.wineD3DDevice->frontBuffer || iface == This->resource.wineD3DDevice->renderTarget) {
+ } else if (iface == implSwapChain->frontBuffer) {
glDrawBuffer(GL_FRONT);
}
+
vcheckGLcall("glDrawBuffer");
/* If not fullscreen, we need to skip a number of bytes to find the next row of data */
@@ -505,7 +630,7 @@
/* Reset to previous pack row length / blending state */
glPixelStorei(GL_UNPACK_ROW_LENGTH, skipBytes);
- if (This->resource.wineD3DDevice->stateBlock->renderState[D3DRS_ALPHABLENDENABLE]) glEnable(GL_BLEND);
+ if (myDevice->stateBlock->renderState[D3DRS_ALPHABLENDENABLE]) glEnable(GL_BLEND);
LEAVE_GL();
@@ -515,10 +640,11 @@
} else {
FIXME("unsupported unlocking to Rendering surface surf@%p usage(%lu)\n", This, This->resource.usage);
}
+ IWineD3DSwapChain_Release((IWineD3DSwapChain *)implSwapChain);
} else if (D3DUSAGE_DEPTHSTENCIL & This->resource.usage) { /* stencil surfaces */
- if (iface == This->resource.wineD3DDevice->depthStencilBuffer) {
+ if (iface == myDevice->depthStencilBuffer) {
FIXME("TODO stencil depth surface unlocking surf@%p usage(%lu)\n", This, This->resource.usage);
} else {
FIXME("unsupported unlocking to StencilDepth surface surf@%p usage(%lu)\n", This, This->resource.usage);
@@ -699,7 +825,7 @@
++gen;
if ((gen % 10) == 0) {
snprintf(buffer, sizeof(buffer), "/tmp/surface%p_type%u_level%u_%u.ppm", This, gl_target, gl_level, gen);
- IWineD3DSurfaceImpl_SaveSnapshot((LPDIRECT3DSURFACE8) This, buffer);
+ IWineD3DSurfaceImpl_SaveSnapshot((IWineD3DSurface *) This, buffer);
}
/*
* debugging crash code
diff --git a/dlls/wined3d/utils.c b/dlls/wined3d/utils.c
index 5df2f2e..ad15e72 100644
--- a/dlls/wined3d/utils.c
+++ b/dlls/wined3d/utils.c
@@ -1761,4 +1761,138 @@
TRACE("bytes/Pxl for fmt(%u,%s) = %d\n", fmt, debug_d3dformat(fmt), retVal);
return retVal;
}
+
+/* Convertes a D3D format into a OpenGL configuration format */
+int D3DFmtMakeGlCfg(D3DFORMAT BackBufferFormat, D3DFORMAT StencilBufferFormat, int *attribs, int* nAttribs, BOOL alternate){
+#define PUSH1(att) attribs[(*nAttribs)++] = (att);
+#define PUSH2(att,value) attribs[(*nAttribs)++] = (att); attribs[(*nAttribs)++] = (value);
+ /*We need to do some Card specific stuff in here at some point,
+ D3D now support floating point format buffers, and their are a number of different OpelGl ways on managing thease e.g.
+ GLX_ATI_pixel_format_float
+ */
+ switch (BackBufferFormat) {
+ /* color buffer */
+ case WINED3DFMT_P8:
+ PUSH2(GLX_RENDER_TYPE, GLX_COLOR_INDEX_BIT);
+ PUSH2(GLX_BUFFER_SIZE, 8);
+ PUSH2(GLX_DOUBLEBUFFER, TRUE);
+ break;
+
+ case WINED3DFMT_R3G3B2:
+ PUSH2(GLX_RENDER_TYPE, GLX_RGBA_BIT);
+ PUSH2(GLX_RED_SIZE, 3);
+ PUSH2(GLX_GREEN_SIZE, 3);
+ PUSH2(GLX_BLUE_SIZE, 2);
+ break;
+
+ case WINED3DFMT_A1R5G5B5:
+ PUSH2(GLX_ALPHA_SIZE, 1);
+ case WINED3DFMT_X1R5G5B5:
+ PUSH2(GLX_RED_SIZE, 5);
+ PUSH2(GLX_GREEN_SIZE, 5);
+ PUSH2(GLX_BLUE_SIZE, 5);
+ break;
+
+ case WINED3DFMT_R5G6B5:
+ PUSH2(GLX_RED_SIZE, 5);
+ PUSH2(GLX_GREEN_SIZE, 6);
+ PUSH2(GLX_BLUE_SIZE, 5);
+ break;
+
+ case WINED3DFMT_A4R4G4B4:
+ PUSH2(GLX_ALPHA_SIZE, 4);
+ case WINED3DFMT_X4R4G4B4:
+ PUSH2(GLX_RED_SIZE, 4);
+ PUSH2(GLX_GREEN_SIZE, 4);
+ PUSH2(GLX_BLUE_SIZE, 4);
+ break;
+
+ case WINED3DFMT_A8R8G8B8:
+ PUSH2(GLX_ALPHA_SIZE, 8);
+ case WINED3DFMT_R8G8B8:
+ case WINED3DFMT_X8R8G8B8:
+ PUSH2(GLX_RED_SIZE, 8);
+ PUSH2(GLX_GREEN_SIZE, 8);
+ PUSH2(GLX_BLUE_SIZE, 8);
+ break;
+
+ default:
+ break;
+ }
+ if(!alternate){
+ switch (StencilBufferFormat) {
+ case WINED3DFMT_D16_LOCKABLE:
+ case WINED3DFMT_D16:
+ PUSH2(GLX_DEPTH_SIZE, 16);
+ break;
+
+ case WINED3DFMT_D15S1:
+ PUSH2(GLX_DEPTH_SIZE, 15);
+ PUSH2(GLX_STENCIL_SIZE, 1);
+ /*Does openGl support a 1bit stencil?, I've seen it used elsewhere
+ e.g. http://www.ks.uiuc.edu/Research/vmd/doxygen/OpenGLDisplayDevice_8C-source.html*/
+ break;
+
+ case WINED3DFMT_D24X8:
+ PUSH2(GLX_DEPTH_SIZE, 24);
+ break;
+
+ case WINED3DFMT_D24X4S4:
+ PUSH2(GLX_DEPTH_SIZE, 24);
+ PUSH2(GLX_STENCIL_SIZE, 4);
+ break;
+
+ case WINED3DFMT_D24S8:
+ PUSH2(GLX_DEPTH_SIZE, 24);
+ PUSH2(GLX_STENCIL_SIZE, 8);
+ break;
+
+ case WINED3DFMT_D32:
+ PUSH2(GLX_DEPTH_SIZE, 32);
+ break;
+
+ default:
+ break;
+ }
+
+ }else{ /* it the device doesn't support the 'exact' format, try to find something close */
+ switch (StencilBufferFormat) {
+ case WINED3DFMT_D16_LOCKABLE:
+ case WINED3DFMT_D16:
+ PUSH2(GLX_DEPTH_SIZE, 1);
+ break;
+
+ case WINED3DFMT_D15S1:
+ PUSH2(GLX_DEPTH_SIZE, 1);
+ PUSH2(GLX_STENCIL_SIZE, 1);
+ /*Does openGl support a 1bit stencil?, I've seen it used elsewhere
+ e.g. http://www.ks.uiuc.edu/Research/vmd/doxygen/OpenGLDisplayDevice_8C-source.html*/
+ break;
+
+ case WINED3DFMT_D24X8:
+ PUSH2(GLX_DEPTH_SIZE, 1);
+ break;
+
+ case WINED3DFMT_D24X4S4:
+ PUSH2(GLX_DEPTH_SIZE, 1);
+ PUSH2(GLX_STENCIL_SIZE, 1);
+ break;
+
+ case WINED3DFMT_D24S8:
+ PUSH2(GLX_DEPTH_SIZE, 1);
+ PUSH2(GLX_STENCIL_SIZE, 1);
+ break;
+
+ case WINED3DFMT_D32:
+ PUSH2(GLX_DEPTH_SIZE, 1);
+ break;
+
+ default:
+ break;
+ }
+ }
+
+ return *nAttribs;
+}
+
#undef GLINFO_LOCATION
diff --git a/dlls/wined3d/wined3d_private.h b/dlls/wined3d/wined3d_private.h
index e634437..4513697 100644
--- a/dlls/wined3d/wined3d_private.h
+++ b/dlls/wined3d/wined3d_private.h
@@ -394,7 +394,6 @@
/* Internal use fields */
D3DDEVICE_CREATION_PARAMETERS createParms;
- D3DPRESENT_PARAMETERS presentParms;
UINT adapterNo;
D3DDEVTYPE devType;
@@ -403,8 +402,6 @@
int numberOfSwapChains;
/* Render Target Support */
- IWineD3DSurface *frontBuffer;
- IWineD3DSurface *backBuffer;
IWineD3DSurface *depthStencilBuffer;
IWineD3DSurface *renderTarget;
@@ -850,6 +847,9 @@
GLenum D3DFmt2GLType(IWineD3DDeviceImpl *This, D3DFORMAT fmt);
GLint D3DFmt2GLIntFmt(IWineD3DDeviceImpl* This, D3DFORMAT fmt);
+int D3DFmtMakeGlCfg(D3DFORMAT BackBufferFormat, D3DFORMAT StencilBufferFormat, int *attribs, int* nAttribs, BOOL alternate);
+
+
/*****************************************************************************
* To enable calling of inherited functions, requires prototypes
*