Implement render targets using either textures, swapchains or
standalone surfaces.
This commit is contained in:
parent
e419cb8869
commit
8a6799d47d
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
@ -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 **)¤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;
|
||||
|
||||
FIXME("(%p) : stub\n", This);
|
||||
return D3D_OK;
|
||||
}
|
||||
|
||||
HRESULT WINAPI IWineD3DDeviceImpl_SetCursorProperties(IWineD3DDevice* iface, UINT XHotSpot,
|
||||
|
|
|
@ -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;
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
*
|
||||
|
|
Loading…
Reference in New Issue