Implemented fast rendering to a texture using glCopyTexImage2D
Fixed SetViewport. Fixed SetRenderTarget (based on Jason Edmeades' work). Improved trace.
This commit is contained in:
parent
c5580b0355
commit
15ccb11ea5
|
@ -393,6 +393,8 @@ struct IDirect3DDevice8Impl
|
|||
|
||||
UINT dummyTextureName[8];
|
||||
|
||||
/* For rendering to a texture using glCopyTexImage */
|
||||
BOOL renderUpsideDown;
|
||||
};
|
||||
|
||||
/* IUnknown: */
|
||||
|
@ -627,6 +629,8 @@ struct IDirect3DSurface8Impl
|
|||
RECT lockedRect;
|
||||
RECT dirtyRect;
|
||||
BOOL Dirty;
|
||||
BOOL inTexture;
|
||||
BOOL inPBuffer;
|
||||
};
|
||||
|
||||
/* IUnknown: */
|
||||
|
|
|
@ -1221,38 +1221,39 @@ HRESULT WINAPI IDirect3DDevice8Impl_GetFrontBuffer(LPDIRECT3DDEVICE8 iface, ID
|
|||
return hr;
|
||||
}
|
||||
HRESULT WINAPI IDirect3DDevice8Impl_SetRenderTarget(LPDIRECT3DDEVICE8 iface, IDirect3DSurface8* pRenderTarget, IDirect3DSurface8* pNewZStencil) {
|
||||
HRESULT hr;
|
||||
HRESULT hr = D3D_OK;
|
||||
D3DVIEWPORT8 viewport;
|
||||
|
||||
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) {
|
||||
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);
|
||||
|
||||
if ((IDirect3DSurface8Impl*) pRenderTarget == This->frontBuffer && (IDirect3DSurface8Impl*) pNewZStencil == This->depthStencilBuffer) {
|
||||
IDirect3DSurface8Impl* tmp;
|
||||
|
||||
TRACE("retoring SetRenderTarget defaults\n");
|
||||
|
||||
tmp = This->renderTarget;
|
||||
This->renderTarget = (IDirect3DSurface8Impl*) This->frontBuffer;
|
||||
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;
|
||||
hr = IDirect3DDevice8Impl_ActiveRender(iface, pRenderTarget, pNewZStencil);
|
||||
}
|
||||
|
||||
FIXME("(%p) : expect crash newRender@%p newZStencil@%p\n", This, pRenderTarget, pNewZStencil);
|
||||
|
||||
hr = IDirect3DDevice8Impl_ActiveRender(iface, pRenderTarget, pNewZStencil);
|
||||
if (SUCCEEDED(hr)) {
|
||||
/* Finally, reset the viewport as the MSDN states. */
|
||||
viewport.Height = ((IDirect3DSurface8Impl*)pRenderTarget)->myDesc.Height;
|
||||
viewport.Width = ((IDirect3DSurface8Impl*)pRenderTarget)->myDesc.Width;
|
||||
viewport.X = 0;
|
||||
viewport.Y = 0;
|
||||
viewport.MaxZ = 1.0f;
|
||||
viewport.MinZ = 0.0f;
|
||||
IDirect3DDevice8Impl_SetViewport(iface, &viewport);
|
||||
}
|
||||
|
||||
return hr;
|
||||
}
|
||||
|
@ -1285,6 +1286,7 @@ HRESULT WINAPI IDirect3DDevice8Impl_BeginScene(LPDIRECT3DDEVICE8 iface) {
|
|||
TRACE("(%p) : stub\n", This);
|
||||
return D3D_OK;
|
||||
}
|
||||
|
||||
HRESULT WINAPI IDirect3DDevice8Impl_EndScene(LPDIRECT3DDEVICE8 iface) {
|
||||
IDirect3DBaseTexture8* cont = NULL;
|
||||
HRESULT hr;
|
||||
|
@ -1296,12 +1298,13 @@ HRESULT WINAPI IDirect3DDevice8Impl_EndScene(LPDIRECT3DDEVICE8 iface) {
|
|||
glFlush();
|
||||
checkGLcall("glFlush");
|
||||
|
||||
/* Useful for debugging sometimes!
|
||||
#if 0 /* Useful for debugging sometimes! */
|
||||
printf("Hit Enter ...\n");
|
||||
getchar(); */
|
||||
getchar();
|
||||
#endif
|
||||
|
||||
if (This->frontBuffer != This->renderTarget) {
|
||||
{
|
||||
#if 0
|
||||
GLenum prev_read;
|
||||
glGetIntegerv(GL_READ_BUFFER, &prev_read);
|
||||
vcheckGLcall("glIntegerv");
|
||||
|
@ -1327,13 +1330,16 @@ HRESULT WINAPI IDirect3DDevice8Impl_EndScene(LPDIRECT3DDEVICE8 iface) {
|
|||
}
|
||||
glReadBuffer(prev_read);
|
||||
vcheckGLcall("glReadBuffer");
|
||||
}
|
||||
#endif
|
||||
|
||||
hr = IDirect3DSurface8_GetContainer((LPDIRECT3DSURFACE8) This->renderTarget, &IID_IDirect3DBaseTexture8, (void**) &cont);
|
||||
if (SUCCEEDED(hr) && NULL != cont) {
|
||||
/** always dirtify for now. we must find a better way to see that surface have been modified */
|
||||
This->renderTarget->inPBuffer = TRUE;
|
||||
This->renderTarget->inTexture = FALSE;
|
||||
IDirect3DBaseTexture8Impl_SetDirty(cont, TRUE);
|
||||
IDirect3DBaseTexture8_PreLoad(cont);
|
||||
This->renderTarget->inPBuffer = FALSE;
|
||||
IDirect3DBaseTexture8Impl_Release(cont);
|
||||
cont = NULL;
|
||||
}
|
||||
|
@ -1640,7 +1646,7 @@ HRESULT WINAPI IDirect3DDevice8Impl_SetViewport(LPDIRECT3DDEVICE8 iface, CONST
|
|||
glDepthRange(pViewport->MinZ, pViewport->MaxZ);
|
||||
checkGLcall("glDepthRange");
|
||||
/* 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);
|
||||
checkGLcall("glViewport");
|
||||
|
||||
|
@ -2256,15 +2262,25 @@ HRESULT WINAPI IDirect3DDevice8Impl_SetRenderState(LPDIRECT3DDEVICE8 iface, D3
|
|||
case D3DCULL_CW:
|
||||
glEnable(GL_CULL_FACE);
|
||||
checkGLcall("glEnable GL_CULL_FACE");
|
||||
if (This->renderUpsideDown) {
|
||||
glFrontFace(GL_CW);
|
||||
checkGLcall("glFrontFace GL_CW");
|
||||
} else {
|
||||
glFrontFace(GL_CCW);
|
||||
checkGLcall("glFrontFace GL_CCW");
|
||||
}
|
||||
glCullFace(GL_BACK);
|
||||
break;
|
||||
case D3DCULL_CCW:
|
||||
glEnable(GL_CULL_FACE);
|
||||
checkGLcall("glEnable GL_CULL_FACE");
|
||||
if (This->renderUpsideDown) {
|
||||
glFrontFace(GL_CCW);
|
||||
checkGLcall("glFrontFace GL_CCW");
|
||||
} else {
|
||||
glFrontFace(GL_CW);
|
||||
checkGLcall("glFrontFace GL_CW");
|
||||
}
|
||||
glCullFace(GL_BACK);
|
||||
break;
|
||||
default:
|
||||
|
@ -4403,7 +4419,7 @@ HRESULT WINAPI IDirect3DDevice8Impl_ActiveRender(LPDIRECT3DDEVICE8 iface,
|
|||
#define PUSH1(att) attribs[nAttribs++] = (att);
|
||||
#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_DOUBLEBUFFER, TRUE);
|
||||
|
||||
|
@ -4503,7 +4519,7 @@ HRESULT WINAPI IDirect3DDevice8Impl_ActiveRender(LPDIRECT3DDEVICE8 iface,
|
|||
#endif
|
||||
|
||||
if (NULL != This->renderTarget) {
|
||||
GLenum prev_read;
|
||||
/*GLenum prev_read; */
|
||||
glFlush();
|
||||
vcheckGLcall("glFlush");
|
||||
|
||||
|
@ -4514,6 +4530,7 @@ HRESULT WINAPI IDirect3DDevice8Impl_ActiveRender(LPDIRECT3DDEVICE8 iface,
|
|||
getchar();
|
||||
#endif
|
||||
|
||||
#if 0
|
||||
glGetIntegerv(GL_READ_BUFFER, &prev_read);
|
||||
vcheckGLcall("glIntegerv");
|
||||
glReadBuffer(GL_BACK);
|
||||
|
@ -4538,6 +4555,7 @@ HRESULT WINAPI IDirect3DDevice8Impl_ActiveRender(LPDIRECT3DDEVICE8 iface,
|
|||
}
|
||||
glReadBuffer(prev_read);
|
||||
vcheckGLcall("glReadBuffer");
|
||||
#endif
|
||||
}
|
||||
|
||||
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 != 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;
|
||||
|
||||
} else {
|
||||
|
|
|
@ -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.
|
||||
Only unlit if Normals are supplied
|
||||
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) */
|
||||
glTranslatef(0.5, 0.5, 0);
|
||||
checkGLcall("glTranslatef(0.5, 0.5, 0)");
|
||||
if (This->renderUpsideDown) {
|
||||
glMultMatrixf(invymat);
|
||||
checkGLcall("glMultMatrixf(invymat)");
|
||||
}
|
||||
}
|
||||
|
||||
} else {
|
||||
|
@ -311,6 +321,11 @@ BOOL primitiveInitState(LPDIRECT3DDEVICE8 iface, BOOL vtx_transformed, BOOL vtx_
|
|||
glLoadIdentity();
|
||||
glTranslatef(1.0/This->StateBlock->viewport.Width, -1.0/This->StateBlock->viewport.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]);
|
||||
checkGLcall("glLoadMatrixf");
|
||||
}
|
||||
|
@ -330,6 +345,10 @@ BOOL primitiveInitState(LPDIRECT3DDEVICE8 iface, BOOL vtx_transformed, BOOL vtx_
|
|||
a pixel (See comment above glTranslate above) */
|
||||
glTranslatef(1.0/This->StateBlock->viewport.Width, -1.0/This->StateBlock->viewport.Height, 0);
|
||||
checkGLcall("glTranslatef (1.0/width, -1.0/height, 0)");
|
||||
if (This->renderUpsideDown) {
|
||||
glMultMatrixf(invymat);
|
||||
checkGLcall("glMultMatrixf(invymat)");
|
||||
}
|
||||
This->modelview_valid = FALSE;
|
||||
This->proj_valid = FALSE;
|
||||
}
|
||||
|
|
|
@ -129,6 +129,11 @@ HRESULT WINAPI IDirect3DSurface8Impl_LockRect(LPDIRECT3DSURFACE8 iface, D3DLOCKE
|
|||
ICOM_THIS(IDirect3DSurface8Impl,iface);
|
||||
|
||||
/* 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) {
|
||||
/* Note: UpdateTextures calls CopyRects which calls this routine to populate the
|
||||
|
@ -474,6 +479,33 @@ ICOM_VTABLE(IDirect3DSurface8) Direct3DSurface8_Vtbl =
|
|||
HRESULT WINAPI IDirect3DSurface8Impl_LoadTexture(LPDIRECT3DSURFACE8 iface, GLenum gl_target, GLenum gl_level) {
|
||||
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) &&
|
||||
!GL_SUPPORT_DEV(EXT_PALETTED_TEXTURE, This->Device)) {
|
||||
/**
|
||||
|
|
|
@ -653,14 +653,17 @@ void GetSrcAndOpFromValue(DWORD iValue, BOOL isAlphaArg, GLenum* source, GLenum*
|
|||
case D3DTA_TFACTOR: *source = GL_CONSTANT_EXT;
|
||||
break;
|
||||
case D3DTA_SPECULAR:
|
||||
/**
|
||||
/*
|
||||
* According to the GL_ARB_texture_env_combine specs, SPECULAR is
|
||||
* 'Secondary color' and isn't supported until base GL supports it
|
||||
* 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:
|
||||
FIXME("Unrecognized or unhandled texture arg %ld\n", iValue);
|
||||
FIXME("Unrecognized texture arg %ld\n", iValue);
|
||||
*source = GL_TEXTURE;
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue