Implemented fast rendering to a texture using glCopyTexImage2D

Fixed SetViewport.
Fixed SetRenderTarget (based on Jason Edmeades' work).
Improved trace.
This commit is contained in:
Christian Costa 2004-04-26 23:34:17 +00:00 committed by Alexandre Julliard
parent c5580b0355
commit 15ccb11ea5
5 changed files with 127 additions and 39 deletions

View File

@ -393,6 +393,8 @@ struct IDirect3DDevice8Impl
UINT dummyTextureName[8]; UINT dummyTextureName[8];
/* For rendering to a texture using glCopyTexImage */
BOOL renderUpsideDown;
}; };
/* IUnknown: */ /* IUnknown: */
@ -627,6 +629,8 @@ struct IDirect3DSurface8Impl
RECT lockedRect; RECT lockedRect;
RECT dirtyRect; RECT dirtyRect;
BOOL Dirty; BOOL Dirty;
BOOL inTexture;
BOOL inPBuffer;
}; };
/* IUnknown: */ /* IUnknown: */

View File

@ -1221,38 +1221,39 @@ HRESULT WINAPI IDirect3DDevice8Impl_GetFrontBuffer(LPDIRECT3DDEVICE8 iface, ID
return hr; return hr;
} }
HRESULT WINAPI IDirect3DDevice8Impl_SetRenderTarget(LPDIRECT3DDEVICE8 iface, IDirect3DSurface8* pRenderTarget, IDirect3DSurface8* pNewZStencil) { HRESULT WINAPI IDirect3DDevice8Impl_SetRenderTarget(LPDIRECT3DDEVICE8 iface, IDirect3DSurface8* pRenderTarget, IDirect3DSurface8* pNewZStencil) {
HRESULT hr; HRESULT hr = D3D_OK;
D3DVIEWPORT8 viewport;
ICOM_THIS(IDirect3DDevice8Impl,iface); ICOM_THIS(IDirect3DDevice8Impl,iface);
/* If pRenderTarget == NULL, it seems to default to back buffer */
if (pRenderTarget == NULL) pRenderTarget = (IDirect3DSurface8*)This->backBuffer;
/* For ease of code later on, handle a null depth as leave alone
- Have not tested real d3d for this case but doing this avoids
numerous null pointer checks */
if (pNewZStencil == NULL) pNewZStencil = (IDirect3DSurface8*)This->stencilBufferTarget;
/* If we are trying to set what we already have, dont bother */
if ((IDirect3DSurface8Impl*) pRenderTarget == This->renderTarget && (IDirect3DSurface8Impl*) pNewZStencil == This->stencilBufferTarget) { if ((IDirect3DSurface8Impl*) pRenderTarget == This->renderTarget && (IDirect3DSurface8Impl*) pNewZStencil == This->stencilBufferTarget) {
TRACE("Trying to do a NOP SetRenderTarget operation\n"); TRACE("Trying to do a NOP SetRenderTarget operation\n");
return D3D_OK; } else {
/* Otherwise, set the render target up */
TRACE("(%p) : newRender@%p newZStencil@%p (default is backbuffer=(%p))\n", This, pRenderTarget, pNewZStencil, This->backBuffer);
IDirect3DDevice8Impl_CleanRender(iface);
hr = IDirect3DDevice8Impl_ActiveRender(iface, pRenderTarget, pNewZStencil);
} }
IDirect3DDevice8Impl_CleanRender(iface); if (SUCCEEDED(hr)) {
/* Finally, reset the viewport as the MSDN states. */
if ((IDirect3DSurface8Impl*) pRenderTarget == This->frontBuffer && (IDirect3DSurface8Impl*) pNewZStencil == This->depthStencilBuffer) { viewport.Height = ((IDirect3DSurface8Impl*)pRenderTarget)->myDesc.Height;
IDirect3DSurface8Impl* tmp; viewport.Width = ((IDirect3DSurface8Impl*)pRenderTarget)->myDesc.Width;
viewport.X = 0;
TRACE("retoring SetRenderTarget defaults\n"); viewport.Y = 0;
viewport.MaxZ = 1.0f;
tmp = This->renderTarget; viewport.MinZ = 0.0f;
This->renderTarget = (IDirect3DSurface8Impl*) This->frontBuffer; IDirect3DDevice8Impl_SetViewport(iface, &viewport);
IDirect3DSurface8Impl_AddRef((LPDIRECT3DSURFACE8) This->renderTarget);
IDirect3DSurface8Impl_Release((LPDIRECT3DSURFACE8) tmp);
tmp = This->stencilBufferTarget;
This->stencilBufferTarget = (IDirect3DSurface8Impl*) This->depthStencilBuffer;
if (NULL != This->stencilBufferTarget) IDirect3DSurface8Impl_AddRef((LPDIRECT3DSURFACE8) This->stencilBufferTarget);
if (NULL != tmp) IDirect3DSurface8Impl_Release((LPDIRECT3DSURFACE8) tmp);
return D3D_OK;
} }
FIXME("(%p) : expect crash newRender@%p newZStencil@%p\n", This, pRenderTarget, pNewZStencil);
hr = IDirect3DDevice8Impl_ActiveRender(iface, pRenderTarget, pNewZStencil);
return hr; return hr;
} }
@ -1285,6 +1286,7 @@ HRESULT WINAPI IDirect3DDevice8Impl_BeginScene(LPDIRECT3DDEVICE8 iface) {
TRACE("(%p) : stub\n", This); TRACE("(%p) : stub\n", This);
return D3D_OK; return D3D_OK;
} }
HRESULT WINAPI IDirect3DDevice8Impl_EndScene(LPDIRECT3DDEVICE8 iface) { HRESULT WINAPI IDirect3DDevice8Impl_EndScene(LPDIRECT3DDEVICE8 iface) {
IDirect3DBaseTexture8* cont = NULL; IDirect3DBaseTexture8* cont = NULL;
HRESULT hr; HRESULT hr;
@ -1296,12 +1298,13 @@ HRESULT WINAPI IDirect3DDevice8Impl_EndScene(LPDIRECT3DDEVICE8 iface) {
glFlush(); glFlush();
checkGLcall("glFlush"); checkGLcall("glFlush");
/* Useful for debugging sometimes! #if 0 /* Useful for debugging sometimes! */
printf("Hit Enter ...\n"); printf("Hit Enter ...\n");
getchar(); */ getchar();
#endif
if (This->frontBuffer != This->renderTarget) { if (This->frontBuffer != This->renderTarget) {
{ #if 0
GLenum prev_read; GLenum prev_read;
glGetIntegerv(GL_READ_BUFFER, &prev_read); glGetIntegerv(GL_READ_BUFFER, &prev_read);
vcheckGLcall("glIntegerv"); vcheckGLcall("glIntegerv");
@ -1327,13 +1330,16 @@ HRESULT WINAPI IDirect3DDevice8Impl_EndScene(LPDIRECT3DDEVICE8 iface) {
} }
glReadBuffer(prev_read); glReadBuffer(prev_read);
vcheckGLcall("glReadBuffer"); vcheckGLcall("glReadBuffer");
} #endif
hr = IDirect3DSurface8_GetContainer((LPDIRECT3DSURFACE8) This->renderTarget, &IID_IDirect3DBaseTexture8, (void**) &cont); hr = IDirect3DSurface8_GetContainer((LPDIRECT3DSURFACE8) This->renderTarget, &IID_IDirect3DBaseTexture8, (void**) &cont);
if (SUCCEEDED(hr) && NULL != cont) { if (SUCCEEDED(hr) && NULL != cont) {
/** always dirtify for now. we must find a better way to see that surface have been modified */ /** always dirtify for now. we must find a better way to see that surface have been modified */
IDirect3DBaseTexture8Impl_SetDirty(cont, TRUE); This->renderTarget->inPBuffer = TRUE;
This->renderTarget->inTexture = FALSE;
IDirect3DBaseTexture8Impl_SetDirty(cont, TRUE);
IDirect3DBaseTexture8_PreLoad(cont); IDirect3DBaseTexture8_PreLoad(cont);
This->renderTarget->inPBuffer = FALSE;
IDirect3DBaseTexture8Impl_Release(cont); IDirect3DBaseTexture8Impl_Release(cont);
cont = NULL; cont = NULL;
} }
@ -1640,7 +1646,7 @@ HRESULT WINAPI IDirect3DDevice8Impl_SetViewport(LPDIRECT3DDEVICE8 iface, CONST
glDepthRange(pViewport->MinZ, pViewport->MaxZ); glDepthRange(pViewport->MinZ, pViewport->MaxZ);
checkGLcall("glDepthRange"); checkGLcall("glDepthRange");
/* Note: GL requires lower left, DirectX supplies upper left */ /* Note: GL requires lower left, DirectX supplies upper left */
glViewport(pViewport->X, (This->PresentParms.BackBufferHeight - (pViewport->Y + pViewport->Height)), glViewport(pViewport->X, (This->renderTarget->myDesc.Height - (pViewport->Y + pViewport->Height)),
pViewport->Width, pViewport->Height); pViewport->Width, pViewport->Height);
checkGLcall("glViewport"); checkGLcall("glViewport");
@ -2256,15 +2262,25 @@ HRESULT WINAPI IDirect3DDevice8Impl_SetRenderState(LPDIRECT3DDEVICE8 iface, D3
case D3DCULL_CW: case D3DCULL_CW:
glEnable(GL_CULL_FACE); glEnable(GL_CULL_FACE);
checkGLcall("glEnable GL_CULL_FACE"); checkGLcall("glEnable GL_CULL_FACE");
glFrontFace(GL_CCW); if (This->renderUpsideDown) {
checkGLcall("glFrontFace GL_CCW"); glFrontFace(GL_CW);
checkGLcall("glFrontFace GL_CW");
} else {
glFrontFace(GL_CCW);
checkGLcall("glFrontFace GL_CCW");
}
glCullFace(GL_BACK); glCullFace(GL_BACK);
break; break;
case D3DCULL_CCW: case D3DCULL_CCW:
glEnable(GL_CULL_FACE); glEnable(GL_CULL_FACE);
checkGLcall("glEnable GL_CULL_FACE"); checkGLcall("glEnable GL_CULL_FACE");
glFrontFace(GL_CW); if (This->renderUpsideDown) {
checkGLcall("glFrontFace GL_CW"); glFrontFace(GL_CCW);
checkGLcall("glFrontFace GL_CCW");
} else {
glFrontFace(GL_CW);
checkGLcall("glFrontFace GL_CW");
}
glCullFace(GL_BACK); glCullFace(GL_BACK);
break; break;
default: default:
@ -4403,7 +4419,7 @@ HRESULT WINAPI IDirect3DDevice8Impl_ActiveRender(LPDIRECT3DDEVICE8 iface,
#define PUSH1(att) attribs[nAttribs++] = (att); #define PUSH1(att) attribs[nAttribs++] = (att);
#define PUSH2(att,value) attribs[nAttribs++] = (att); attribs[nAttribs++] = (value); #define PUSH2(att,value) attribs[nAttribs++] = (att); attribs[nAttribs++] = (value);
PUSH2(GLX_DRAWABLE_TYPE, GLX_WINDOW_BIT | GLX_WINDOW | GLX_PBUFFER_BIT); PUSH2(GLX_DRAWABLE_TYPE, GLX_PBUFFER_BIT);
PUSH2(GLX_X_RENDERABLE, TRUE); PUSH2(GLX_X_RENDERABLE, TRUE);
PUSH2(GLX_DOUBLEBUFFER, TRUE); PUSH2(GLX_DOUBLEBUFFER, TRUE);
@ -4503,7 +4519,7 @@ HRESULT WINAPI IDirect3DDevice8Impl_ActiveRender(LPDIRECT3DDEVICE8 iface,
#endif #endif
if (NULL != This->renderTarget) { if (NULL != This->renderTarget) {
GLenum prev_read; /*GLenum prev_read; */
glFlush(); glFlush();
vcheckGLcall("glFlush"); vcheckGLcall("glFlush");
@ -4514,6 +4530,7 @@ HRESULT WINAPI IDirect3DDevice8Impl_ActiveRender(LPDIRECT3DDEVICE8 iface,
getchar(); getchar();
#endif #endif
#if 0
glGetIntegerv(GL_READ_BUFFER, &prev_read); glGetIntegerv(GL_READ_BUFFER, &prev_read);
vcheckGLcall("glIntegerv"); vcheckGLcall("glIntegerv");
glReadBuffer(GL_BACK); glReadBuffer(GL_BACK);
@ -4538,6 +4555,7 @@ HRESULT WINAPI IDirect3DDevice8Impl_ActiveRender(LPDIRECT3DDEVICE8 iface,
} }
glReadBuffer(prev_read); glReadBuffer(prev_read);
vcheckGLcall("glReadBuffer"); vcheckGLcall("glReadBuffer");
#endif
} }
if (BackBufferFormat != This->renderTarget->myDesc.Format && if (BackBufferFormat != This->renderTarget->myDesc.Format &&
@ -4571,6 +4589,18 @@ HRESULT WINAPI IDirect3DDevice8Impl_ActiveRender(LPDIRECT3DDEVICE8 iface,
if (NULL != This->stencilBufferTarget) IDirect3DSurface8Impl_AddRef((LPDIRECT3DSURFACE8) This->stencilBufferTarget); if (NULL != This->stencilBufferTarget) IDirect3DSurface8Impl_AddRef((LPDIRECT3DSURFACE8) This->stencilBufferTarget);
if (NULL != tmp) IDirect3DSurface8Impl_Release((LPDIRECT3DSURFACE8) tmp); if (NULL != tmp) IDirect3DSurface8Impl_Release((LPDIRECT3DSURFACE8) tmp);
{
DWORD value;
/* The surface must be rendered upside down to cancel the flip produce by glCopyTexImage */
This->renderUpsideDown = This->renderTarget != This->frontBuffer;
/* Force updating the cull mode */
IDirect3DDevice8_GetRenderState(iface, D3DRS_CULLMODE, &value);
IDirect3DDevice8_SetRenderState(iface, D3DRS_CULLMODE, value);
/* Force updating projection matrix */
This->last_was_rhw = FALSE;
This->proj_valid = FALSE;
}
ret = D3D_OK; ret = D3D_OK;
} else { } else {

View File

@ -218,6 +218,12 @@ void init_materials(LPDIRECT3DDEVICE8 iface, BOOL isDiffuseSupplied) {
} }
static GLfloat invymat[16]={
1.0f, 0.0f, 0.0f, 0.0f,
0.0f, -1.0f, 0.0f, 0.0f,
0.0f, 0.0f, 1.0f, 0.0f,
0.0f, 0.0f, 0.0f, 1.0f};
/* Setup views - Transformed & lit if RHW, else untransformed. /* Setup views - Transformed & lit if RHW, else untransformed.
Only unlit if Normals are supplied Only unlit if Normals are supplied
Returns: Whether to restore lighting afterwards */ Returns: Whether to restore lighting afterwards */
@ -271,6 +277,10 @@ BOOL primitiveInitState(LPDIRECT3DDEVICE8 iface, BOOL vtx_transformed, BOOL vtx_
a pixel (See comment above glTranslate below) */ a pixel (See comment above glTranslate below) */
glTranslatef(0.5, 0.5, 0); glTranslatef(0.5, 0.5, 0);
checkGLcall("glTranslatef(0.5, 0.5, 0)"); checkGLcall("glTranslatef(0.5, 0.5, 0)");
if (This->renderUpsideDown) {
glMultMatrixf(invymat);
checkGLcall("glMultMatrixf(invymat)");
}
} }
} else { } else {
@ -311,6 +321,11 @@ BOOL primitiveInitState(LPDIRECT3DDEVICE8 iface, BOOL vtx_transformed, BOOL vtx_
glLoadIdentity(); glLoadIdentity();
glTranslatef(1.0/This->StateBlock->viewport.Width, -1.0/This->StateBlock->viewport.Height, 0); glTranslatef(1.0/This->StateBlock->viewport.Width, -1.0/This->StateBlock->viewport.Height, 0);
checkGLcall("glTranslatef (1.0/width, -1.0/height, 0)"); checkGLcall("glTranslatef (1.0/width, -1.0/height, 0)");
if (This->renderUpsideDown) {
glMultMatrixf(invymat);
checkGLcall("glMultMatrixf(invymat)");
}
glMultMatrixf((float *) &This->StateBlock->transforms[D3DTS_PROJECTION].u.m[0][0]); glMultMatrixf((float *) &This->StateBlock->transforms[D3DTS_PROJECTION].u.m[0][0]);
checkGLcall("glLoadMatrixf"); checkGLcall("glLoadMatrixf");
} }
@ -330,6 +345,10 @@ BOOL primitiveInitState(LPDIRECT3DDEVICE8 iface, BOOL vtx_transformed, BOOL vtx_
a pixel (See comment above glTranslate above) */ a pixel (See comment above glTranslate above) */
glTranslatef(1.0/This->StateBlock->viewport.Width, -1.0/This->StateBlock->viewport.Height, 0); glTranslatef(1.0/This->StateBlock->viewport.Width, -1.0/This->StateBlock->viewport.Height, 0);
checkGLcall("glTranslatef (1.0/width, -1.0/height, 0)"); checkGLcall("glTranslatef (1.0/width, -1.0/height, 0)");
if (This->renderUpsideDown) {
glMultMatrixf(invymat);
checkGLcall("glMultMatrixf(invymat)");
}
This->modelview_valid = FALSE; This->modelview_valid = FALSE;
This->proj_valid = FALSE; This->proj_valid = FALSE;
} }

View File

@ -129,7 +129,12 @@ HRESULT WINAPI IDirect3DSurface8Impl_LockRect(LPDIRECT3DSURFACE8 iface, D3DLOCKE
ICOM_THIS(IDirect3DSurface8Impl,iface); ICOM_THIS(IDirect3DSurface8Impl,iface);
/* fixme: should we really lock as such? */ /* fixme: should we really lock as such? */
if (This->inTexture && This->inPBuffer) {
FIXME("Warning: Surface is in texture memory or pbuffer\n");
This->inTexture = 0;
This->inPBuffer = 0;
}
if (FALSE == This->lockable) { if (FALSE == This->lockable) {
/* Note: UpdateTextures calls CopyRects which calls this routine to populate the /* Note: UpdateTextures calls CopyRects which calls this routine to populate the
texture regions, and since the destination is an unlockable region we need texture regions, and since the destination is an unlockable region we need
@ -474,6 +479,33 @@ ICOM_VTABLE(IDirect3DSurface8) Direct3DSurface8_Vtbl =
HRESULT WINAPI IDirect3DSurface8Impl_LoadTexture(LPDIRECT3DSURFACE8 iface, GLenum gl_target, GLenum gl_level) { HRESULT WINAPI IDirect3DSurface8Impl_LoadTexture(LPDIRECT3DSURFACE8 iface, GLenum gl_target, GLenum gl_level) {
ICOM_THIS(IDirect3DSurface8Impl,iface); ICOM_THIS(IDirect3DSurface8Impl,iface);
if (This->inTexture)
return D3D_OK;
if (This->inPBuffer) {
ENTER_GL();
if (gl_level != 0)
FIXME("Surface in texture is only supported for level 0\n");
else if (This->myDesc.Format == D3DFMT_P8 || This->myDesc.Format == D3DFMT_A8P8 ||
This->myDesc.Format == D3DFMT_DXT1 || This->myDesc.Format == D3DFMT_DXT3 ||
This->myDesc.Format == D3DFMT_DXT5)
FIXME("Format %d not supported\n", This->myDesc.Format);
else {
glCopyTexImage2D(gl_target,
0,
D3DFmt2GLIntFmt(This->Device,
This->myDesc.Format),
0,
0,/*This->surfaces[j][i]->myDesc.Height-1,*/
This->myDesc.Width,
This->myDesc.Height,
0);
TRACE("Updating target %d\n", gl_target);
This->inTexture = TRUE;
}
LEAVE_GL();
return D3D_OK;
}
if ((This->myDesc.Format == D3DFMT_P8 || This->myDesc.Format == D3DFMT_A8P8) && if ((This->myDesc.Format == D3DFMT_P8 || This->myDesc.Format == D3DFMT_A8P8) &&
!GL_SUPPORT_DEV(EXT_PALETTED_TEXTURE, This->Device)) { !GL_SUPPORT_DEV(EXT_PALETTED_TEXTURE, This->Device)) {
/** /**

View File

@ -653,14 +653,17 @@ void GetSrcAndOpFromValue(DWORD iValue, BOOL isAlphaArg, GLenum* source, GLenum*
case D3DTA_TFACTOR: *source = GL_CONSTANT_EXT; case D3DTA_TFACTOR: *source = GL_CONSTANT_EXT;
break; break;
case D3DTA_SPECULAR: case D3DTA_SPECULAR:
/** /*
* According to the GL_ARB_texture_env_combine specs, SPECULAR is * According to the GL_ARB_texture_env_combine specs, SPECULAR is
* 'Secondary color' and isn't supported until base GL supports it * 'Secondary color' and isn't supported until base GL supports it
* There is no concept of temp registers as far as I can tell * There is no concept of temp registers as far as I can tell
*/ */
FIXME("Unhandled texture arg D3DTA_SPECULAR\n");
*source = GL_TEXTURE;
break;
default: default:
FIXME("Unrecognized or unhandled texture arg %ld\n", iValue); FIXME("Unrecognized texture arg %ld\n", iValue);
*source = GL_TEXTURE; *source = GL_TEXTURE;
} }
} }