Add fps debug channel, so we can see how the d3d code is performing and
their impact of performance changes. SetTransform almost rewritten in a much neater way, and in coordination with drawprim it significantly reduces the number of times that we reload the matrixes.
This commit is contained in:
parent
0a002212c1
commit
564f5828b0
|
@ -326,10 +326,11 @@ struct IDirect3DDevice8Impl
|
||||||
UINT currentPalette;
|
UINT currentPalette;
|
||||||
|
|
||||||
/* Optimization */
|
/* Optimization */
|
||||||
D3DMATRIX lastProj;
|
BOOL modelview_valid;
|
||||||
D3DMATRIX lastView;
|
BOOL proj_valid;
|
||||||
D3DMATRIX lastWorld0;
|
BOOL view_ident; /* true iff view matrix is identity */
|
||||||
D3DMATRIX lastTexTrans[8];
|
BOOL last_was_rhw; /* true iff last draw_primitive was in xyzrhw mode */
|
||||||
|
|
||||||
|
|
||||||
/* OpenGL related */
|
/* OpenGL related */
|
||||||
GLXContext glCtx;
|
GLXContext glCtx;
|
||||||
|
|
|
@ -40,11 +40,13 @@
|
||||||
|
|
||||||
WINE_DEFAULT_DEBUG_CHANNEL(d3d);
|
WINE_DEFAULT_DEBUG_CHANNEL(d3d);
|
||||||
WINE_DECLARE_DEBUG_CHANNEL(d3d_shader);
|
WINE_DECLARE_DEBUG_CHANNEL(d3d_shader);
|
||||||
|
WINE_DECLARE_DEBUG_CHANNEL(fps);
|
||||||
|
|
||||||
IDirect3DVertexShaderImpl* VertexShaders[64];
|
IDirect3DVertexShaderImpl* VertexShaders[64];
|
||||||
IDirect3DVertexShaderDeclarationImpl* VertexShaderDeclarations[64];
|
IDirect3DVertexShaderDeclarationImpl* VertexShaderDeclarations[64];
|
||||||
IDirect3DPixelShaderImpl* PixelShaders[64];
|
IDirect3DPixelShaderImpl* PixelShaders[64];
|
||||||
|
|
||||||
|
/* Debugging aids: */
|
||||||
#ifdef FRAME_DEBUGGING
|
#ifdef FRAME_DEBUGGING
|
||||||
BOOL isOn = FALSE;
|
BOOL isOn = FALSE;
|
||||||
BOOL isDumpingFrames = FALSE;
|
BOOL isDumpingFrames = FALSE;
|
||||||
|
@ -109,6 +111,47 @@ void setupTextureStates(LPDIRECT3DDEVICE8 iface, DWORD Stage) {
|
||||||
TRACE("-----------------------> Updated the texture at stage %ld to have new texture state information\n", Stage);
|
TRACE("-----------------------> Updated the texture at stage %ld to have new texture state information\n", Stage);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Setup this textures matrix */
|
||||||
|
static void set_texture_matrix(float *smat, DWORD flags)
|
||||||
|
{
|
||||||
|
float mat[16];
|
||||||
|
|
||||||
|
glMatrixMode(GL_TEXTURE);
|
||||||
|
|
||||||
|
if (flags == D3DTTFF_DISABLE) {
|
||||||
|
glLoadIdentity();
|
||||||
|
checkGLcall("glLoadIdentity()");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (flags == (D3DTTFF_COUNT1|D3DTTFF_PROJECTED)) {
|
||||||
|
ERR("Invalid texture transform flags: D3DTTFF_COUNT1|D3DTTFF_PROJECTED\n");
|
||||||
|
checkGLcall("glLoadIdentity()");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
memcpy(mat, smat, 16*sizeof(float));
|
||||||
|
|
||||||
|
switch (flags & ~D3DTTFF_PROJECTED) {
|
||||||
|
case D3DTTFF_COUNT1: mat[1] = mat[5] = mat[9] = mat[13] = 0;
|
||||||
|
case D3DTTFF_COUNT2: mat[2] = mat[6] = mat[10] = mat[14] = 0;
|
||||||
|
default: mat[3] = mat[7] = mat[11] = 0, mat[15] = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (flags & D3DTTFF_PROJECTED) switch (flags & ~D3DTTFF_PROJECTED) {
|
||||||
|
case D3DTTFF_COUNT2:
|
||||||
|
mat[3] = mat[1], mat[7] = mat[5], mat[11] = mat[9], mat[15] = mat[13];
|
||||||
|
mat[1] = mat[5] = mat[9] = mat[13] = 0;
|
||||||
|
break;
|
||||||
|
case D3DTTFF_COUNT3:
|
||||||
|
mat[3] = mat[2], mat[7] = mat[6], mat[11] = mat[10], mat[15] = mat[14];
|
||||||
|
mat[2] = mat[6] = mat[10] = mat[14] = 0;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
glLoadMatrixf(mat);
|
||||||
|
checkGLcall("glLoadMatrixf(mat)");
|
||||||
|
}
|
||||||
|
|
||||||
/* IDirect3D IUnknown parts follow: */
|
/* IDirect3D IUnknown parts follow: */
|
||||||
HRESULT WINAPI IDirect3DDevice8Impl_QueryInterface(LPDIRECT3DDEVICE8 iface,REFIID riid,LPVOID *ppobj)
|
HRESULT WINAPI IDirect3DDevice8Impl_QueryInterface(LPDIRECT3DDEVICE8 iface,REFIID riid,LPVOID *ppobj)
|
||||||
{
|
{
|
||||||
|
@ -322,6 +365,21 @@ HRESULT WINAPI IDirect3DDevice8Impl_Present(LPDIRECT3DDEVICE8 iface, CONST REC
|
||||||
/* Dont call checkGLcall, as glGetError is not applicable here */
|
/* Dont call checkGLcall, as glGetError is not applicable here */
|
||||||
TRACE("glXSwapBuffers called, Starting new frame\n");
|
TRACE("glXSwapBuffers called, Starting new frame\n");
|
||||||
|
|
||||||
|
/* FPS support */
|
||||||
|
if (TRACE_ON(fps))
|
||||||
|
{
|
||||||
|
static long prev_time, frames;
|
||||||
|
|
||||||
|
DWORD time = GetTickCount();
|
||||||
|
frames++;
|
||||||
|
/* every 1.5 seconds */
|
||||||
|
if (time - prev_time > 1500) {
|
||||||
|
TRACE_(fps)("@@@ %.2ffps\n", 1000.0*frames/(time - prev_time));
|
||||||
|
prev_time = time;
|
||||||
|
frames = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#if defined(FRAME_DEBUGGING)
|
#if defined(FRAME_DEBUGGING)
|
||||||
{
|
{
|
||||||
if (GetFileAttributesA("C:\\D3DTRACE") != INVALID_FILE_ATTRIBUTES) {
|
if (GetFileAttributesA("C:\\D3DTRACE") != INVALID_FILE_ATTRIBUTES) {
|
||||||
|
@ -1244,268 +1302,110 @@ HRESULT WINAPI IDirect3DDevice8Impl_Clear(LPDIRECT3DDEVICE8 iface, DWORD Count
|
||||||
}
|
}
|
||||||
HRESULT WINAPI IDirect3DDevice8Impl_SetTransform(LPDIRECT3DDEVICE8 iface, D3DTRANSFORMSTATETYPE d3dts, CONST D3DMATRIX* lpmatrix) {
|
HRESULT WINAPI IDirect3DDevice8Impl_SetTransform(LPDIRECT3DDEVICE8 iface, D3DTRANSFORMSTATETYPE d3dts, CONST D3DMATRIX* lpmatrix) {
|
||||||
ICOM_THIS(IDirect3DDevice8Impl,iface);
|
ICOM_THIS(IDirect3DDevice8Impl,iface);
|
||||||
D3DMATRIX m;
|
|
||||||
int k;
|
int k;
|
||||||
float f;
|
|
||||||
BOOL viewChanged = TRUE;
|
|
||||||
int Stage;
|
|
||||||
|
|
||||||
/* Most of this routine, comments included copied from ddraw tree initially: */
|
/* Most of this routine, comments included copied from ddraw tree initially: */
|
||||||
TRACE("(%p) : State=%d\n", This, d3dts);
|
TRACE("(%p) : State=%d\n", This, d3dts);
|
||||||
|
|
||||||
This->UpdateStateBlock->Changed.transform[d3dts] = TRUE;
|
|
||||||
This->UpdateStateBlock->Set.transform[d3dts] = TRUE;
|
|
||||||
memcpy(&This->UpdateStateBlock->transforms[d3dts], lpmatrix, sizeof(D3DMATRIX));
|
|
||||||
|
|
||||||
/* Handle recording of state blocks */
|
/* Handle recording of state blocks */
|
||||||
if (This->isRecordingState) {
|
if (This->isRecordingState) {
|
||||||
TRACE("Recording... not performing anything\n");
|
TRACE("Recording... not performing anything\n");
|
||||||
|
This->UpdateStateBlock->Changed.transform[d3dts] = TRUE;
|
||||||
|
This->UpdateStateBlock->Set.transform[d3dts] = TRUE;
|
||||||
|
memcpy(&This->UpdateStateBlock->transforms[d3dts], lpmatrix, sizeof(D3DMATRIX));
|
||||||
return D3D_OK;
|
return D3D_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
ScreenCoord = ProjectionMat * ViewMat * WorldMat * ObjectCoord
|
* if the new matrix is the same as the current one,
|
||||||
|
* we cut off any further processing. this seems to be a reasonable
|
||||||
where ViewMat = Camera space, WorldMat = world space.
|
* optimization because as was noticed, some apps (warcraft3 for example)
|
||||||
|
* tend towards setting the same matrix repeatedly for some dumb reason.
|
||||||
In OpenGL, camera and world space is combined into GL_MODELVIEW
|
*
|
||||||
matrix. The Projection matrix stay projection matrix. */
|
* From here on we assume that the new matrix is different, wherever it matters
|
||||||
|
* but note
|
||||||
/* After reading through both OpenGL and Direct3D documentations, I
|
*/
|
||||||
thought that D3D matrices were written in 'line major mode' transposed
|
if (!memcmp(&This->StateBlock->transforms[d3dts].u.m[0][0], lpmatrix, sizeof(D3DMATRIX))) {
|
||||||
from OpenGL's 'column major mode'. But I found out that a simple memcpy
|
TRACE("The app is setting the same matrix over again\n");
|
||||||
works fine to transfer one matrix format to the other (it did not work
|
return D3D_OK;
|
||||||
when transposing)....
|
|
||||||
|
|
||||||
So :
|
|
||||||
1) are the documentations wrong
|
|
||||||
2) does the matrix work even if they are not read correctly
|
|
||||||
3) is Mesa's implementation of OpenGL not compliant regarding Matrix
|
|
||||||
loading using glLoadMatrix ?
|
|
||||||
|
|
||||||
Anyway, I always use 'conv_mat' to transfer the matrices from one format
|
|
||||||
to the other so that if I ever find out that I need to transpose them, I
|
|
||||||
will able to do it quickly, only by changing the macro conv_mat. */
|
|
||||||
|
|
||||||
if (d3dts < 256) {
|
|
||||||
switch (d3dts) {
|
|
||||||
case D3DTS_VIEW:
|
|
||||||
conv_mat(lpmatrix, &This->StateBlock->transforms[D3DTS_VIEW]);
|
|
||||||
break;
|
|
||||||
|
|
||||||
case D3DTS_PROJECTION:
|
|
||||||
conv_mat(lpmatrix, &This->StateBlock->transforms[D3DTS_PROJECTION]);
|
|
||||||
break;
|
|
||||||
|
|
||||||
case D3DTS_TEXTURE0:
|
|
||||||
case D3DTS_TEXTURE1:
|
|
||||||
case D3DTS_TEXTURE2:
|
|
||||||
case D3DTS_TEXTURE3:
|
|
||||||
case D3DTS_TEXTURE4:
|
|
||||||
case D3DTS_TEXTURE5:
|
|
||||||
case D3DTS_TEXTURE6:
|
|
||||||
case D3DTS_TEXTURE7:
|
|
||||||
conv_mat(lpmatrix, &This->StateBlock->transforms[d3dts]);
|
|
||||||
break;
|
|
||||||
|
|
||||||
default:
|
|
||||||
FIXME("Unhandled transform state!!\n");
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
} else {
|
} else {
|
||||||
/**
|
conv_mat(lpmatrix, &This->StateBlock->transforms[d3dts].u.m[0][0]);
|
||||||
* Indexed Vertex Blending Matrices 256 -> 511
|
|
||||||
* where WORLDMATRIX(0) == 256!
|
|
||||||
*/
|
|
||||||
/** store it */
|
|
||||||
conv_mat(lpmatrix, &This->StateBlock->transforms[d3dts]);
|
|
||||||
#if 0
|
|
||||||
if (GL_SUPPORT(ARB_VERTEX_BLEND)) {
|
|
||||||
FIXME("TODO\n");
|
|
||||||
} else if (GL_SUPPORT(EXT_VERTEX_WEIGHTING)) {
|
|
||||||
FIXME("TODO\n");
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Move the GL operation to outside of switch to make it work
|
ScreenCoord = ProjectionMat * ViewMat * WorldMat * ObjectCoord
|
||||||
* regardless of transform set order.
|
where ViewMat = Camera space, WorldMat = world space.
|
||||||
|
|
||||||
|
In OpenGL, camera and world space is combined into GL_MODELVIEW
|
||||||
|
matrix. The Projection matrix stay projection matrix.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
/* Capture the times we can just ignore the change */
|
||||||
|
if (d3dts == D3DTS_WORLDMATRIX(0)) {
|
||||||
|
This->modelview_valid = FALSE;
|
||||||
|
return D3D_OK;
|
||||||
|
|
||||||
|
} else if (d3dts == D3DTS_PROJECTION) {
|
||||||
|
This->proj_valid = FALSE;
|
||||||
|
return D3D_OK;
|
||||||
|
|
||||||
|
} else if (d3dts >= D3DTS_WORLDMATRIX(1) && d3dts <= D3DTS_WORLDMATRIX(255)) { /* Indexed Vertex Blending Matrices 256 -> 511 */
|
||||||
|
/* Use arb_vertex_blend or NV_VERTEX_WEIGHTING? */
|
||||||
|
FIXME("D3DTS_WORLDMATRIX(1..255) not handled\n");
|
||||||
|
return D3D_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Chances are we really are going to have to change a matrix */
|
||||||
ENTER_GL();
|
ENTER_GL();
|
||||||
if (memcmp(&This->lastProj, &This->StateBlock->transforms[D3DTS_PROJECTION].u.m[0][0], sizeof(D3DMATRIX))) {
|
|
||||||
glMatrixMode(GL_PROJECTION);
|
|
||||||
checkGLcall("glMatrixMode");
|
|
||||||
glLoadMatrixf((float *) &This->StateBlock->transforms[D3DTS_PROJECTION].u.m[0][0]);
|
|
||||||
checkGLcall("glLoadMatrixf");
|
|
||||||
memcpy(&This->lastProj, &This->StateBlock->transforms[D3DTS_PROJECTION].u.m[0][0], sizeof(D3DMATRIX));
|
|
||||||
} else {
|
|
||||||
TRACE("Skipping as projection already correct\n");
|
|
||||||
}
|
|
||||||
|
|
||||||
glMatrixMode(GL_MODELVIEW);
|
if (d3dts >= D3DTS_TEXTURE0 && d3dts <= D3DTS_TEXTURE7) { /* handle texture matrices */
|
||||||
checkGLcall("glMatrixMode");
|
if (d3dts < GL_LIMITS(textures)) {
|
||||||
viewChanged = FALSE;
|
int tex = d3dts - D3DTS_TEXTURE0;
|
||||||
if (memcmp(&This->lastView, &This->StateBlock->transforms[D3DTS_VIEW].u.m[0][0], sizeof(D3DMATRIX))) {
|
|
||||||
glLoadMatrixf((float *) &This->StateBlock->transforms[D3DTS_VIEW].u.m[0][0]);
|
|
||||||
checkGLcall("glLoadMatrixf");
|
|
||||||
memcpy(&This->lastView, &This->StateBlock->transforms[D3DTS_VIEW].u.m[0][0], sizeof(D3DMATRIX));
|
|
||||||
viewChanged = TRUE;
|
|
||||||
|
|
||||||
/* If we are changing the View matrix, reset the light and clipping planes to the new view */
|
|
||||||
if (d3dts == D3DTS_VIEW) {
|
|
||||||
|
|
||||||
/* NOTE: We have to reset the positions even if the light/plane is not currently
|
|
||||||
enabled, since the call to enable it will not reset the position. */
|
|
||||||
|
|
||||||
/* Reset lights */
|
|
||||||
for (k = 0; k < GL_LIMITS(lights); k++) {
|
|
||||||
glLightfv(GL_LIGHT0 + k, GL_POSITION, &This->lightPosn[k][0]);
|
|
||||||
checkGLcall("glLightfv posn");
|
|
||||||
glLightfv(GL_LIGHT0 + k, GL_SPOT_DIRECTION, &This->lightDirn[k][0]);
|
|
||||||
checkGLcall("glLightfv dirn");
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Reset Clipping Planes if clipping is enabled */
|
|
||||||
for (k = 0; k < GL_LIMITS(clipplanes); k++) {
|
|
||||||
glClipPlane(GL_CLIP_PLANE0 + k, This->StateBlock->clipplane[k]);
|
|
||||||
checkGLcall("glClipPlane");
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Reapply texture transforms as based off modelview when applied */
|
|
||||||
for (Stage = 0; Stage < GL_LIMITS(textures); Stage++) {
|
|
||||||
|
|
||||||
/* Only applicable if the transforms are not disabled */
|
|
||||||
if (This->UpdateStateBlock->texture_state[Stage][D3DTSS_TEXTURETRANSFORMFLAGS] != D3DTTFF_DISABLE)
|
|
||||||
{
|
|
||||||
/* Now apply texture transforms if not applying to the dummy textures */
|
|
||||||
#if defined(GL_VERSION_1_3)
|
#if defined(GL_VERSION_1_3)
|
||||||
glActiveTexture(GL_TEXTURE0 + Stage);
|
glActiveTexture(GL_TEXTURE0 + tex);
|
||||||
#else
|
#else
|
||||||
glActiveTextureARB(GL_TEXTURE0_ARB + Stage);
|
glActiveTextureARB(GL_TEXTURE0_ARB + tex);
|
||||||
#endif
|
#endif
|
||||||
checkGLcall("glActiveTexture(GL_TEXTURE0 + Stage);");
|
set_texture_matrix((float *)lpmatrix, This->UpdateStateBlock->texture_state[tex][D3DTSS_TEXTURETRANSFORMFLAGS]);
|
||||||
|
|
||||||
glMatrixMode(GL_TEXTURE);
|
|
||||||
if (This->StateBlock->textureDimensions[Stage] == GL_TEXTURE_1D) {
|
|
||||||
glLoadIdentity();
|
|
||||||
} else {
|
|
||||||
D3DMATRIX fred;
|
|
||||||
conv_mat(&This->StateBlock->transforms[D3DTS_TEXTURE0+Stage], &fred);
|
|
||||||
glLoadMatrixf((float *) &This->StateBlock->transforms[D3DTS_TEXTURE0+Stage].u.m[0][0]);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
checkGLcall("Load matrix for texture");
|
|
||||||
}
|
|
||||||
glMatrixMode(GL_MODELVIEW); /* Always leave in model view */
|
|
||||||
}
|
|
||||||
} else if ((d3dts >= D3DTS_TEXTURE0 && d3dts <= D3DTS_TEXTURE7) &&
|
|
||||||
(This->UpdateStateBlock->texture_state[d3dts - D3DTS_TEXTURE0][D3DTSS_TEXTURETRANSFORMFLAGS] != D3DTTFF_DISABLE)) {
|
|
||||||
/* Now apply texture transforms if not applying to the dummy textures */
|
|
||||||
Stage = d3dts - D3DTS_TEXTURE0;
|
|
||||||
|
|
||||||
if (memcmp(&This->lastTexTrans[Stage], &This->StateBlock->transforms[D3DTS_TEXTURE0 + Stage].u.m[0][0], sizeof(D3DMATRIX))) {
|
|
||||||
memcpy(&This->lastTexTrans[Stage], &This->StateBlock->transforms[D3DTS_TEXTURE0 + Stage].u.m[0][0], sizeof(D3DMATRIX));
|
|
||||||
|
|
||||||
#if defined(GL_VERSION_1_3)
|
|
||||||
glActiveTexture(GL_TEXTURE0 + Stage);
|
|
||||||
#else
|
|
||||||
glActiveTextureARB(GL_TEXTURE0_ARB + Stage);
|
|
||||||
#endif
|
|
||||||
checkGLcall("glActiveTexture(GL_TEXTURE0 + Stage)");
|
|
||||||
|
|
||||||
glMatrixMode(GL_TEXTURE);
|
|
||||||
if (This->StateBlock->textureDimensions[Stage] == GL_TEXTURE_1D) {
|
|
||||||
glLoadIdentity();
|
|
||||||
} else {
|
|
||||||
D3DMATRIX fred;
|
|
||||||
conv_mat(&This->StateBlock->transforms[D3DTS_TEXTURE0+Stage], &fred);
|
|
||||||
glLoadMatrixf((float *) &This->StateBlock->transforms[D3DTS_TEXTURE0+Stage].u.m[0][0]);
|
|
||||||
}
|
|
||||||
checkGLcall("Load matrix for texture");
|
|
||||||
glMatrixMode(GL_MODELVIEW); /* Always leave in model view */
|
|
||||||
} else {
|
|
||||||
TRACE("Skipping texture transform as already correct\n");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
} else {
|
} else if (d3dts == D3DTS_VIEW) { /* handle the VIEW matrice */
|
||||||
TRACE("Skipping view setup as view already correct\n");
|
float identity[16] = {1,0,0,0, 0,1,0,0, 0,0,1,0, 0,0,0,1};
|
||||||
}
|
This->modelview_valid = FALSE;
|
||||||
|
This->view_ident = !memcmp(lpmatrix, identity, 16*sizeof(float));
|
||||||
/**
|
glMatrixMode(GL_MODELVIEW);
|
||||||
* Vertex Blending as described
|
checkGLcall("glMatrixMode(GL_MODELVIEW)");
|
||||||
* http://msdn.microsoft.com/library/default.asp?url=/library/en-us/directx9_c/directx/graphics/reference/d3d/enums/d3dvertexblendflags.asp
|
glPushMatrix();
|
||||||
*/
|
glLoadMatrixf((float *)lpmatrix);
|
||||||
switch (This->UpdateStateBlock->vertex_blend) {
|
checkGLcall("glLoadMatrixf(...)");
|
||||||
case D3DVBF_DISABLE:
|
|
||||||
{
|
/* If we are changing the View matrix, reset the light and clipping planes to the new view
|
||||||
if (viewChanged == TRUE ||
|
* NOTE: We have to reset the positions even if the light/plane is not currently
|
||||||
(memcmp(&This->lastWorld0, &This->StateBlock->transforms[D3DTS_WORLDMATRIX(0)].u.m[0][0], sizeof(D3DMATRIX)))) {
|
* enabled, since the call to enable it will not reset the position.
|
||||||
memcpy(&This->lastWorld0, &This->StateBlock->transforms[D3DTS_WORLDMATRIX(0)].u.m[0][0], sizeof(D3DMATRIX));
|
* NOTE2: Apparently texture transforms do NOT need reapplying
|
||||||
if (viewChanged == FALSE) {
|
*/
|
||||||
glLoadMatrixf((float *) &This->StateBlock->transforms[D3DTS_VIEW].u.m[0][0]);
|
|
||||||
checkGLcall("glLoadMatrixf");
|
/* Reset lights */
|
||||||
}
|
for (k = 0; k < GL_LIMITS(lights); k++) {
|
||||||
glMultMatrixf((float *) &This->StateBlock->transforms[D3DTS_WORLDMATRIX(0)].u.m[0][0]);
|
glLightfv(GL_LIGHT0 + k, GL_POSITION, This->lightPosn[k]);
|
||||||
checkGLcall("glMultMatrixf");
|
checkGLcall("glLightfv posn");
|
||||||
} else {
|
glLightfv(GL_LIGHT0 + k, GL_SPOT_DIRECTION, This->lightDirn[k]);
|
||||||
TRACE("Skipping as world already correct\n");
|
checkGLcall("glLightfv dirn");
|
||||||
}
|
}
|
||||||
}
|
/* Reset Clipping Planes if clipping is enabled */
|
||||||
break;
|
for (k = 0; k < GL_LIMITS(clipplanes); k++) {
|
||||||
case D3DVBF_1WEIGHTS:
|
glClipPlane(GL_CLIP_PLANE0 + k, This->StateBlock->clipplane[k]);
|
||||||
case D3DVBF_2WEIGHTS:
|
checkGLcall("glClipPlane");
|
||||||
case D3DVBF_3WEIGHTS:
|
}
|
||||||
{
|
glPopMatrix();
|
||||||
FIXME("valid/correct D3DVBF_[1..3]WEIGHTS\n");
|
|
||||||
/*
|
} else { /* What was requested!?? */
|
||||||
* doc seems to say that the weight values must be in vertex data (specified in FVF by D3DFVF_XYZB*)
|
WARN("invalid matrix specified: %i\n", d3dts);
|
||||||
* so waiting for the values before matrix work
|
|
||||||
for (k = 0; k < This->UpdateStateBlock->vertex_blend; ++k) {
|
|
||||||
glMultMatrixf((float *) &This->StateBlock->transforms[D3DTS_WORLDMATRIX(k)].u.m[0][0]);
|
|
||||||
checkGLcall("glMultMatrixf");
|
|
||||||
}
|
|
||||||
*/
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case D3DVBF_TWEENING:
|
|
||||||
{
|
|
||||||
FIXME("valid/correct D3DVBF_TWEENING\n");
|
|
||||||
f = This->UpdateStateBlock->tween_factor;
|
|
||||||
m.u.s._11 = f; m.u.s._12 = f; m.u.s._13 = f; m.u.s._14 = f;
|
|
||||||
m.u.s._21 = f; m.u.s._22 = f; m.u.s._23 = f; m.u.s._24 = f;
|
|
||||||
m.u.s._31 = f; m.u.s._32 = f; m.u.s._33 = f; m.u.s._34 = f;
|
|
||||||
m.u.s._41 = f; m.u.s._42 = f; m.u.s._43 = f; m.u.s._44 = f;
|
|
||||||
if (viewChanged == FALSE) {
|
|
||||||
glLoadMatrixf((float *) &This->StateBlock->transforms[D3DTS_VIEW].u.m[0][0]);
|
|
||||||
checkGLcall("glLoadMatrixf");
|
|
||||||
}
|
|
||||||
glMultMatrixf((float *) &m.u.m[0][0]);
|
|
||||||
checkGLcall("glMultMatrixf");
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case D3DVBF_0WEIGHTS:
|
|
||||||
{
|
|
||||||
FIXME("valid/correct D3DVBF_0WEIGHTS\n");
|
|
||||||
/* single matrix of weight 1.0f */
|
|
||||||
m.u.s._11 = 1.0f; m.u.s._12 = 1.0f; m.u.s._13 = 1.0f; m.u.s._14 = 1.0f;
|
|
||||||
m.u.s._21 = 1.0f; m.u.s._22 = 1.0f; m.u.s._23 = 1.0f; m.u.s._24 = 1.0f;
|
|
||||||
m.u.s._31 = 1.0f; m.u.s._32 = 1.0f; m.u.s._33 = 1.0f; m.u.s._34 = 1.0f;
|
|
||||||
m.u.s._41 = 1.0f; m.u.s._42 = 1.0f; m.u.s._43 = 1.0f; m.u.s._44 = 1.0f;
|
|
||||||
if (viewChanged == FALSE) {
|
|
||||||
glLoadMatrixf((float *) &This->StateBlock->transforms[D3DTS_VIEW].u.m[0][0]);
|
|
||||||
checkGLcall("glLoadMatrixf");
|
|
||||||
}
|
|
||||||
glMultMatrixf((float *) &m.u.m[0][0]);
|
|
||||||
checkGLcall("glMultMatrixf");
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
break; /* stupid compilator */
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Release lock, all done */
|
||||||
LEAVE_GL();
|
LEAVE_GL();
|
||||||
|
|
||||||
return D3D_OK;
|
return D3D_OK;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -1887,9 +1787,9 @@ HRESULT WINAPI IDirect3DDevice8Impl_SetClipPlane(LPDIRECT3DDEVICE8 iface, DWOR
|
||||||
This->UpdateStateBlock->clipplane[Index][2],
|
This->UpdateStateBlock->clipplane[Index][2],
|
||||||
This->UpdateStateBlock->clipplane[Index][3]);
|
This->UpdateStateBlock->clipplane[Index][3]);
|
||||||
glClipPlane(GL_CLIP_PLANE0 + Index, This->UpdateStateBlock->clipplane[Index]);
|
glClipPlane(GL_CLIP_PLANE0 + Index, This->UpdateStateBlock->clipplane[Index]);
|
||||||
|
checkGLcall("glClipPlane");
|
||||||
|
|
||||||
glPopMatrix();
|
glPopMatrix();
|
||||||
checkGLcall("glClipPlane");
|
|
||||||
|
|
||||||
LEAVE_GL();
|
LEAVE_GL();
|
||||||
|
|
||||||
|
@ -3278,30 +3178,7 @@ HRESULT WINAPI IDirect3DDevice8Impl_SetTextureStageState(LPDIRECT3DDEVICE8 ifa
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case D3DTSS_TEXTURETRANSFORMFLAGS :
|
case D3DTSS_TEXTURETRANSFORMFLAGS :
|
||||||
{
|
set_texture_matrix((float *)&This->StateBlock->transforms[D3DTS_TEXTURE0 + Stage].u.m[0][0], Value);
|
||||||
switch (Value & ~D3DTTFF_PROJECTED)
|
|
||||||
{
|
|
||||||
case D3DTTFF_DISABLE: /* Disable transform matrix for this texture by setting up the identity matrix */
|
|
||||||
glMatrixMode(GL_TEXTURE);
|
|
||||||
glLoadIdentity();
|
|
||||||
checkGLcall("Load identity matrix for texture");
|
|
||||||
glMatrixMode(GL_MODELVIEW); /* Always leave in model view */
|
|
||||||
break;
|
|
||||||
|
|
||||||
default: /* Enable it */
|
|
||||||
IDirect3DDevice8Impl_SetTransform(iface, D3DTS_TEXTURE0+Stage, &This->UpdateStateBlock->transforms[D3DTS_TEXTURE0+Stage]);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* From web: <quote source="opengl12.pdf" section="Apendix C, Version 1.1/Other changes"
|
|
||||||
2. Texture coordinates s, t, and r are divided by q during the rasterization
|
|
||||||
of points, pixel rectangles, and bitmaps. This division was documented
|
|
||||||
only for lines and polygons in the 1.0 version. </quote>
|
|
||||||
I interpret this as we can implement projected transforms in slow vertex mode
|
|
||||||
by moving the last coord to the 'q' coord and using one less dimension. The only
|
|
||||||
way to do it in TexCoordPtr would be to massage the data stream to insert extra
|
|
||||||
coords */
|
|
||||||
}
|
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case D3DTSS_MIPMAPLODBIAS :
|
case D3DTSS_MIPMAPLODBIAS :
|
||||||
|
|
|
@ -1083,6 +1083,12 @@ HRESULT WINAPI IDirect3D8Impl_CreateDevice (LPDIRECT3D8 iface,
|
||||||
IDirect3DDevice8Impl_SetViewport((LPDIRECT3DDEVICE8) object, &vp);
|
IDirect3DDevice8Impl_SetViewport((LPDIRECT3DDEVICE8) object, &vp);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Initialize the current view state */
|
||||||
|
object->modelview_valid = 1;
|
||||||
|
object->proj_valid = 0;
|
||||||
|
object->view_ident = 1;
|
||||||
|
object->last_was_rhw = 0;
|
||||||
|
|
||||||
TRACE("(%p,%d) All defaults now set up, leaving CreateDevice\n", This, Adapter);
|
TRACE("(%p,%d) All defaults now set up, leaving CreateDevice\n", This, Adapter);
|
||||||
return D3D_OK;
|
return D3D_OK;
|
||||||
}
|
}
|
||||||
|
|
|
@ -172,67 +172,90 @@ BOOL primitiveInitState(LPDIRECT3DDEVICE8 iface, BOOL vtx_transformed, BOOL vtx_
|
||||||
isLightingOn = glIsEnabled(GL_LIGHTING);
|
isLightingOn = glIsEnabled(GL_LIGHTING);
|
||||||
glDisable(GL_LIGHTING);
|
glDisable(GL_LIGHTING);
|
||||||
checkGLcall("glDisable(GL_LIGHTING);");
|
checkGLcall("glDisable(GL_LIGHTING);");
|
||||||
TRACE("Enabled lighting as no normals supplied, old state = %d\n", isLightingOn);
|
TRACE("Disabled lighting as no normals supplied, old state = %d\n", isLightingOn);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (vtx_transformed) {
|
if (vtx_transformed) {
|
||||||
double X, Y, height, width, minZ, maxZ;
|
|
||||||
|
|
||||||
/* Transformed already into viewport coordinates, so we do not need transform
|
/* If the last draw was transformed as well, no need to reapply all the matrixes */
|
||||||
matrices. Reset all matrices to identity and leave the default matrix in world
|
if (!This->last_was_rhw) {
|
||||||
mode. */
|
|
||||||
glMatrixMode(GL_MODELVIEW);
|
|
||||||
checkGLcall("glMatrixMode");
|
|
||||||
glLoadIdentity();
|
|
||||||
checkGLcall("glLoadIdentity");
|
|
||||||
|
|
||||||
glMatrixMode(GL_PROJECTION);
|
double X, Y, height, width, minZ, maxZ;
|
||||||
checkGLcall("glMatrixMode");
|
This->last_was_rhw = TRUE;
|
||||||
glLoadIdentity();
|
|
||||||
checkGLcall("glLoadIdentity");
|
|
||||||
|
|
||||||
/* Set up the viewport to be full viewport */
|
/* Transformed already into viewport coordinates, so we do not need transform
|
||||||
X = This->StateBlock->viewport.X;
|
matrices. Reset all matrices to identity and leave the default matrix in world
|
||||||
Y = This->StateBlock->viewport.Y;
|
mode. */
|
||||||
height = This->StateBlock->viewport.Height;
|
glMatrixMode(GL_MODELVIEW);
|
||||||
width = This->StateBlock->viewport.Width;
|
checkGLcall("glMatrixMode");
|
||||||
minZ = This->StateBlock->viewport.MinZ;
|
glLoadIdentity();
|
||||||
maxZ = This->StateBlock->viewport.MaxZ;
|
checkGLcall("glLoadIdentity");
|
||||||
TRACE("Calling glOrtho with %f, %f, %f, %f\n", width, height, -minZ, -maxZ);
|
|
||||||
glOrtho(X, X + width, Y + height, Y, -minZ, -maxZ);
|
|
||||||
checkGLcall("glOrtho");
|
|
||||||
|
|
||||||
/* Window Coord 0 is the middle of the first pixel, so translate by half
|
glMatrixMode(GL_PROJECTION);
|
||||||
a pixel (See comment above glTranslate below) */
|
checkGLcall("glMatrixMode");
|
||||||
glTranslatef(0.5, 0.5, 0);
|
glLoadIdentity();
|
||||||
checkGLcall("glTranslatef(0.5, 0.5, 0)");
|
checkGLcall("glLoadIdentity");
|
||||||
|
|
||||||
|
/* Set up the viewport to be full viewport */
|
||||||
|
X = This->StateBlock->viewport.X;
|
||||||
|
Y = This->StateBlock->viewport.Y;
|
||||||
|
height = This->StateBlock->viewport.Height;
|
||||||
|
width = This->StateBlock->viewport.Width;
|
||||||
|
minZ = This->StateBlock->viewport.MinZ;
|
||||||
|
maxZ = This->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");
|
||||||
|
|
||||||
|
/* Window Coord 0 is the middle of the first pixel, so translate by half
|
||||||
|
a pixel (See comment above glTranslate below) */
|
||||||
|
glTranslatef(0.5, 0.5, 0);
|
||||||
|
checkGLcall("glTranslatef(0.5, 0.5, 0)");
|
||||||
|
}
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
|
|
||||||
/* Untransformed, so relies on the view and projection matrices */
|
/* Untransformed, so relies on the view and projection matrices */
|
||||||
glMatrixMode(GL_MODELVIEW);
|
|
||||||
checkGLcall("glMatrixMode");
|
|
||||||
glLoadMatrixf((float *) &This->StateBlock->transforms[D3DTS_VIEW].u.m[0][0]);
|
|
||||||
checkGLcall("glLoadMatrixf");
|
|
||||||
glMultMatrixf((float *) &This->StateBlock->transforms[D3DTS_WORLDMATRIX(0)].u.m[0][0]);
|
|
||||||
checkGLcall("glMultMatrixf");
|
|
||||||
|
|
||||||
glMatrixMode(GL_PROJECTION);
|
if (This->last_was_rhw || !This->modelview_valid) {
|
||||||
checkGLcall("glMatrixMode");
|
/* Only reapply when have to */
|
||||||
|
This->modelview_valid = TRUE;
|
||||||
|
glMatrixMode(GL_MODELVIEW);
|
||||||
|
checkGLcall("glMatrixMode");
|
||||||
|
|
||||||
/* The rule is that the window coordinate 0 does not correspond to the
|
/* In the general case, the view matrix is the identity matrix */
|
||||||
beginning of the first pixel, but the center of the first pixel.
|
if (This->view_ident) {
|
||||||
As a consequence if you want to correctly draw one line exactly from
|
glLoadMatrixf((float *) &This->StateBlock->transforms[D3DTS_WORLDMATRIX(0)].u.m[0][0]);
|
||||||
the left to the right end of the viewport (with all matrices set to
|
checkGLcall("glLoadMatrixf");
|
||||||
be identity), the x coords of both ends of the line would be not
|
} else {
|
||||||
-1 and 1 respectively but (-1-1/viewport_widh) and (1-1/viewport_width)
|
glLoadMatrixf((float *) &This->StateBlock->transforms[D3DTS_VIEW].u.m[0][0]);
|
||||||
instead. */
|
checkGLcall("glLoadMatrixf");
|
||||||
glLoadIdentity();
|
glMultMatrixf((float *) &This->StateBlock->transforms[D3DTS_WORLDMATRIX(0)].u.m[0][0]);
|
||||||
glTranslatef(1.0/This->StateBlock->viewport.Width, -1.0/This->StateBlock->viewport.Height, 0);
|
checkGLcall("glMultMatrixf");
|
||||||
checkGLcall("glTranslatef (1.0/width, -1.0/height, 0)");
|
}
|
||||||
glMultMatrixf((float *) &This->StateBlock->transforms[D3DTS_PROJECTION].u.m[0][0]);
|
}
|
||||||
checkGLcall("glLoadMatrixf");
|
|
||||||
|
|
||||||
|
if (This->last_was_rhw || !This->proj_valid) {
|
||||||
|
/* Only reapply when have to */
|
||||||
|
This->proj_valid = TRUE;
|
||||||
|
glMatrixMode(GL_PROJECTION);
|
||||||
|
checkGLcall("glMatrixMode");
|
||||||
|
|
||||||
|
/* The rule is that the window coordinate 0 does not correspond to the
|
||||||
|
beginning of the first pixel, but the center of the first pixel.
|
||||||
|
As a consequence if you want to correctly draw one line exactly from
|
||||||
|
the left to the right end of the viewport (with all matrices set to
|
||||||
|
be identity), the x coords of both ends of the line would be not
|
||||||
|
-1 and 1 respectively but (-1-1/viewport_widh) and (1-1/viewport_width)
|
||||||
|
instead. */
|
||||||
|
glLoadIdentity();
|
||||||
|
glTranslatef(1.0/This->StateBlock->viewport.Width, -1.0/This->StateBlock->viewport.Height, 0);
|
||||||
|
checkGLcall("glTranslatef (1.0/width, -1.0/height, 0)");
|
||||||
|
glMultMatrixf((float *) &This->StateBlock->transforms[D3DTS_PROJECTION].u.m[0][0]);
|
||||||
|
checkGLcall("glLoadMatrixf");
|
||||||
|
}
|
||||||
|
|
||||||
|
This->last_was_rhw = FALSE;
|
||||||
}
|
}
|
||||||
return isLightingOn;
|
return isLightingOn;
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue