Implement render targets using either textures, swapchains or

standalone surfaces.
This commit is contained in:
Oliver Stieber 2005-07-07 20:35:05 +00:00 committed by Alexandre Julliard
parent e419cb8869
commit 8a6799d47d
6 changed files with 860 additions and 116 deletions

View File

@ -374,53 +374,61 @@ HRESULT WINAPI IDirect3DDevice9Impl_CreateOffscreenPlainSurface(LPDIRECT3DDEVI
/* 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;
}

View File

@ -4355,7 +4355,7 @@ HRESULT WINAPI IWineD3DDeviceImpl_EndScene(IWineD3DDevice *iface) {
/* 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 @@ HRESULT WINAPI IWineD3DDeviceImpl_EndScene(IWineD3DDevice *iface) {
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 @@ HRESULT WINAPI IWineD3DDeviceImpl_GetDepthStencilSurface(IWineD3DDevice* iface
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;
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 **)&currentSwapchain) != D3D_OK){
/* the selected render target doesn't belong to a swapchain, so use the devices implicite swapchain */
IWineD3DDevice_GetSwapChain(iface, 0, &currentSwapchain);
}
/**
* 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;
FIXME("(%p) : stub\n", This);
return D3D_OK;
}
HRESULT WINAPI IWineD3DDeviceImpl_SetCursorProperties(IWineD3DDevice* iface, UINT XHotSpot,

View File

@ -1572,7 +1572,6 @@ HRESULT WINAPI IWineD3DImpl_CreateDevice(IWineD3D *iface, UINT Adapter, D3DDEV
object->createParms.BehaviorFlags = BehaviourFlags;
/* Initialize other useful values */
object->presentParms.BackBufferCount = 1; /* Opengl only supports one? */
object->adapterNo = Adapter;
object->devType = DeviceType;

View File

@ -201,6 +201,9 @@ HRESULT WINAPI IWineD3DSurfaceImpl_GetDesc(IWineD3DSurface *iface, WINED3DSURFAC
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 @@ HRESULT WINAPI IWineD3DSurfaceImpl_LockRect(IWineD3DSurface *iface, D3DLOCKED_RE
/*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 @@ HRESULT WINAPI IWineD3DSurfaceImpl_LockRect(IWineD3DSurface *iface, D3DLOCKED_RE
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 @@ HRESULT WINAPI IWineD3DSurfaceImpl_LockRect(IWineD3DSurface *iface, D3DLOCKED_RE
} 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);
/** 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{
{
long j;
GLenum format = D3DFmt2GLFmt(This->resource.wineD3DDevice, This->resource.format);
GLenum type = D3DFmt2GLType(This->resource.wineD3DDevice, This->resource.format);
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 @@ HRESULT WINAPI IWineD3DSurfaceImpl_LockRect(IWineD3DSurface *iface, D3DLOCKED_RE
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 @@ HRESULT WINAPI IWineD3DSurfaceImpl_LockRect(IWineD3DSurface *iface, D3DLOCKED_RE
*/
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_LockRect(IWineD3DSurface *iface, D3DLOCKED_RE
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 @@ HRESULT WINAPI IWineD3DSurfaceImpl_UnlockRect(IWineD3DSurface *iface) {
*/
} 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 @@ HRESULT WINAPI IWineD3DSurfaceImpl_UnlockRect(IWineD3DSurface *iface) {
/* 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 @@ HRESULT WINAPI IWineD3DSurfaceImpl_UnlockRect(IWineD3DSurface *iface) {
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 @@ HRESULT WINAPI IWineD3DSurfaceImpl_UnlockRect(IWineD3DSurface *iface) {
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 @@ HRESULT WINAPI IWineD3DSurfaceImpl_UnlockRect(IWineD3DSurface *iface) {
/* 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 @@ HRESULT WINAPI IWineD3DSurfaceImpl_UnlockRect(IWineD3DSurface *iface) {
} 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 @@ HRESULT WINAPI IWineD3DSurfaceImpl_LoadTexture(IWineD3DSurface *iface, GLenum gl
++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

View File

@ -1761,4 +1761,138 @@ SHORT D3DFmtGetBpp(IWineD3DDeviceImpl* This, D3DFORMAT fmt) {
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

View File

@ -394,7 +394,6 @@ typedef struct IWineD3DDeviceImpl
/* Internal use fields */
D3DDEVICE_CREATION_PARAMETERS createParms;
D3DPRESENT_PARAMETERS presentParms;
UINT adapterNo;
D3DDEVTYPE devType;
@ -403,8 +402,6 @@ typedef struct IWineD3DDeviceImpl
int numberOfSwapChains;
/* Render Target Support */
IWineD3DSurface *frontBuffer;
IWineD3DSurface *backBuffer;
IWineD3DSurface *depthStencilBuffer;
IWineD3DSurface *renderTarget;
@ -850,6 +847,9 @@ GLenum D3DFmt2GLFmt(IWineD3DDeviceImpl* This, D3DFORMAT fmt);
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
*