wined3d: Implement vertex blending using GL_ARB_vertex_blend.
This commit is contained in:
parent
6acc0a151d
commit
adb9b13b81
|
@ -359,6 +359,14 @@ WineD3DContext *CreateContext(IWineD3DDeviceImpl *This, IWineD3DSurfaceImpl *tar
|
|||
glPixelStorei(GL_UNPACK_CLIENT_STORAGE_APPLE, GL_TRUE);
|
||||
checkGLcall("glPixelStorei(GL_UNPACK_CLIENT_STORAGE_APPLE, GL_TRUE)");
|
||||
}
|
||||
if(GL_SUPPORT(ARB_VERTEX_BLEND)) {
|
||||
/* Direct3D always uses n-1 weights for n world matrices and uses 1 - sum for the last one
|
||||
* this is equal to GL_WEIGHT_SUM_UNITY_ARB. Enabling it doesn't do anything unless
|
||||
* GL_VERTEX_BLEND_ARB isn't enabled too
|
||||
*/
|
||||
glEnable(GL_WEIGHT_SUM_UNITY_ARB);
|
||||
checkGLcall("glEnable(GL_WEIGHT_SUM_UNITY_ARB)");
|
||||
}
|
||||
|
||||
if(oldDrawable && oldCtx) {
|
||||
glXMakeCurrent(display, oldDrawable, oldCtx);
|
||||
|
|
|
@ -2218,14 +2218,8 @@ static HRESULT WINAPI IWineD3DImpl_GetDeviceCaps(IWineD3D *iface, UINT Adapter,
|
|||
*pCaps->MaxUserClipPlanes = GL_LIMITS(clipplanes);
|
||||
*pCaps->MaxActiveLights = GL_LIMITS(lights);
|
||||
|
||||
|
||||
|
||||
#if 0 /* TODO: Blends support in drawprim */
|
||||
*pCaps->MaxVertexBlendMatrices = GL_LIMITS(blends);
|
||||
#else
|
||||
*pCaps->MaxVertexBlendMatrices = 0;
|
||||
#endif
|
||||
*pCaps->MaxVertexBlendMatrixIndex = 1;
|
||||
*pCaps->MaxVertexBlendMatrixIndex = 0;
|
||||
|
||||
*pCaps->MaxAnisotropy = GL_LIMITS(anisotropy);
|
||||
*pCaps->MaxPointSize = GL_LIMITS(pointsize);
|
||||
|
|
|
@ -261,7 +261,7 @@ void primitiveConvertFVFtoOffset(DWORD thisFVF, DWORD stride, BYTE *data, WineDi
|
|||
strided->u.s.position.VBO = streamVBO;
|
||||
strided->u.s.position.streamNo = streamNo;
|
||||
data += 3 * sizeof(float);
|
||||
if (thisFVF & WINED3DFVF_XYZRHW) {
|
||||
if ((thisFVF & WINED3DFVF_POSITION_MASK) == WINED3DFVF_XYZRHW) {
|
||||
strided->u.s.position.dwType = WINED3DDECLTYPE_FLOAT4;
|
||||
strided->u.s.position_transformed = TRUE;
|
||||
data += sizeof(float);
|
||||
|
@ -274,7 +274,7 @@ void primitiveConvertFVFtoOffset(DWORD thisFVF, DWORD stride, BYTE *data, WineDi
|
|||
numBlends = 1 + (((thisFVF & WINED3DFVF_XYZB5) - WINED3DFVF_XYZB1) >> 1);
|
||||
if(thisFVF & WINED3DFVF_LASTBETA_UBYTE4) numBlends--;
|
||||
|
||||
if ((thisFVF & WINED3DFVF_XYZB5 ) > WINED3DFVF_XYZRHW) {
|
||||
if ((thisFVF & WINED3DFVF_POSITION_MASK ) > WINED3DFVF_XYZRHW) {
|
||||
TRACE("Setting blend Weights to %p\n", data);
|
||||
strided->u.s.blendWeights.lpData = data;
|
||||
strided->u.s.blendWeights.dwType = WINED3DDECLTYPE_FLOAT1 + numBlends - 1;
|
||||
|
|
|
@ -2217,6 +2217,96 @@ static void clipplane(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DCo
|
|||
glPopMatrix();
|
||||
}
|
||||
|
||||
static void transform_worldex(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
|
||||
UINT matrix = state - STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(0));
|
||||
GLenum glMat;
|
||||
TRACE("Setting world matrix %d\n", matrix);
|
||||
|
||||
if(matrix >= GL_LIMITS(blends)) {
|
||||
WARN("Unsupported blend matrix set\n");
|
||||
return;
|
||||
} else if(isStateDirty(context, STATE_TRANSFORM(WINED3DTS_VIEW))) {
|
||||
return;
|
||||
}
|
||||
|
||||
/* GL_MODELVIEW0_ARB: 0x1700
|
||||
* GL_MODELVIEW1_ARB: 0x0x850a
|
||||
* GL_MODELVIEW2_ARB: 0x8722
|
||||
* GL_MODELVIEW3_ARB: 0x8723
|
||||
* etc
|
||||
* GL_MODELVIEW31_ARB: 0x873F
|
||||
*/
|
||||
if(matrix == 1) glMat = GL_MODELVIEW1_ARB;
|
||||
else glMat = GL_MODELVIEW2_ARB - 2 + matrix;
|
||||
|
||||
glMatrixMode(glMat);
|
||||
checkGLcall("glMatrixMode(glMat)");
|
||||
|
||||
/* World matrix 0 is multiplied with the view matrix because d3d uses 3 matrices while gl uses only 2. To avoid
|
||||
* weighting the view matrix incorrectly it has to be multiplied into every gl modelview matrix
|
||||
*/
|
||||
if(stateblock->wineD3DDevice->view_ident) {
|
||||
glLoadMatrixf(&stateblock->transforms[WINED3DTS_WORLDMATRIX(matrix)].u.m[0][0]);
|
||||
checkGLcall("glLoadMatrixf")
|
||||
} else {
|
||||
glLoadMatrixf(&stateblock->transforms[WINED3DTS_VIEW].u.m[0][0]);
|
||||
checkGLcall("glLoadMatrixf")
|
||||
glMultMatrixf(&stateblock->transforms[WINED3DTS_WORLDMATRIX(matrix)].u.m[0][0]);
|
||||
checkGLcall("glMultMatrixf")
|
||||
}
|
||||
}
|
||||
|
||||
static void state_vertexblend(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
|
||||
WINED3DVERTEXBLENDFLAGS val = stateblock->renderState[WINED3DRS_VERTEXBLEND];
|
||||
|
||||
switch(val) {
|
||||
case WINED3DVBF_1WEIGHTS:
|
||||
case WINED3DVBF_2WEIGHTS:
|
||||
case WINED3DVBF_3WEIGHTS:
|
||||
if(GL_SUPPORT(ARB_VERTEX_BLEND)) {
|
||||
glEnable(GL_VERTEX_BLEND_ARB);
|
||||
checkGLcall("glEnable(GL_VERTEX_BLEND_ARB)");
|
||||
|
||||
/* D3D adds one more matrix which has weight (1 - sum(weights)). This is enabled at context
|
||||
* creation with enabling GL_WEIGHT_SUM_UNITY_ARB.
|
||||
*/
|
||||
GL_EXTCALL(glVertexBlendARB(stateblock->renderState[WINED3DRS_VERTEXBLEND] + 1));
|
||||
|
||||
if(!stateblock->wineD3DDevice->vertexBlendUsed) {
|
||||
int i;
|
||||
for(i = 1; i < GL_LIMITS(blends); i++) {
|
||||
if(!isStateDirty(context, STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(i)))) {
|
||||
transform_worldex(STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(i)), stateblock, context);
|
||||
}
|
||||
}
|
||||
stateblock->wineD3DDevice->vertexBlendUsed = TRUE;
|
||||
}
|
||||
} else {
|
||||
/* TODO: Implement vertex blending in drawStridedSlow */
|
||||
FIXME("Vertex blending enabled, but not supported by hardware\n");
|
||||
}
|
||||
break;
|
||||
|
||||
case WINED3DVBF_DISABLE:
|
||||
case WINED3DVBF_0WEIGHTS: /* for Indexed vertex blending - not supported */
|
||||
if(GL_SUPPORT(ARB_VERTEX_BLEND)) {
|
||||
glDisable(GL_VERTEX_BLEND_ARB);
|
||||
checkGLcall("glDisable(GL_VERTEX_BLEND_ARB)");
|
||||
} else {
|
||||
TRACE("Vertex blending disabled\n");
|
||||
}
|
||||
break;
|
||||
|
||||
case WINED3DVBF_TWEENING:
|
||||
/* Just set the vertex weight for weight 0, enable vertex blending and hope the app doesn't have
|
||||
* vertex weights in the vertices?
|
||||
* For now we don't report that as supported, so a warn should suffice
|
||||
*/
|
||||
WARN("Tweening not supported yet\n");
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static void transform_view(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
|
||||
unsigned int k;
|
||||
|
||||
|
@ -2263,10 +2353,15 @@ static void transform_view(DWORD state, IWineD3DStateBlockImpl *stateblock, Wine
|
|||
if(!isStateDirty(context, STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(0)))) {
|
||||
transform_world(STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(0)), stateblock, context);
|
||||
}
|
||||
}
|
||||
|
||||
static void transform_worldex(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
|
||||
WARN("World matrix 1 - 255 not supported yet\n");
|
||||
/* Avoid looping over a number of matrices if the app never used the functionality */
|
||||
if(stateblock->wineD3DDevice->vertexBlendUsed) {
|
||||
for(k = 1; k < GL_LIMITS(blends); k++) {
|
||||
if(!isStateDirty(context, STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(k)))) {
|
||||
transform_worldex(STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(k)), stateblock, context);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static const GLfloat invymat[16] = {
|
||||
|
@ -2528,26 +2623,14 @@ static void loadVertexData(IWineD3DStateBlockImpl *stateblock, WineDirect3DVerte
|
|||
if( (sd->u.s.blendWeights.lpData) || (sd->u.s.blendWeights.VBO) ||
|
||||
(sd->u.s.blendMatrixIndices.lpData) || (sd->u.s.blendMatrixIndices.VBO) ) {
|
||||
|
||||
|
||||
if (GL_SUPPORT(ARB_VERTEX_BLEND)) {
|
||||
|
||||
#if 1
|
||||
glEnableClientState(GL_WEIGHT_ARRAY_ARB);
|
||||
checkGLcall("glEnableClientState(GL_WEIGHT_ARRAY_ARB)");
|
||||
#endif
|
||||
|
||||
TRACE("Blend %d %p %d\n", WINED3D_ATR_SIZE(sd->u.s.blendWeights.dwType),
|
||||
sd->u.s.blendWeights.lpData + stateblock->loadBaseVertexIndex * sd->u.s.blendWeights.dwStride, sd->u.s.blendWeights.dwStride + offset[sd->u.s.blendWeights.streamNo]);
|
||||
/* FIXME("TODO\n");*/
|
||||
/* Note dwType == float3 or float4 == 2 or 3 */
|
||||
|
||||
#if 0
|
||||
/* with this on, the normals appear to be being modified,
|
||||
but the vertices aren't being translated as they should be
|
||||
Maybe the world matrix aren't being setup properly? */
|
||||
glVertexBlendARB(WINED3D_ATR_SIZE(sd->u.s.blendWeights.dwType) + 1);
|
||||
#endif
|
||||
glEnableClientState(GL_WEIGHT_ARRAY_ARB);
|
||||
checkGLcall("glEnableClientState(GL_WEIGHT_ARRAY_ARB)");
|
||||
|
||||
GL_EXTCALL(glVertexBlendARB(WINED3D_ATR_SIZE(sd->u.s.blendWeights.dwType) + 1));
|
||||
|
||||
VTRACE(("glWeightPointerARB(%d, GL_FLOAT, %d, %p)\n",
|
||||
WINED3D_ATR_SIZE(sd->u.s.blendWeights.dwType) ,
|
||||
|
@ -2575,7 +2658,6 @@ static void loadVertexData(IWineD3DStateBlockImpl *stateblock, WineDirect3DVerte
|
|||
showfixme = FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
} else if (GL_SUPPORT(EXT_VERTEX_WEIGHTING)) {
|
||||
/* FIXME("TODO\n");*/
|
||||
#if 0
|
||||
|
@ -2598,10 +2680,11 @@ static void loadVertexData(IWineD3DStateBlockImpl *stateblock, WineDirect3DVerte
|
|||
}
|
||||
} else {
|
||||
if (GL_SUPPORT(ARB_VERTEX_BLEND)) {
|
||||
#if 0 /* TODO: Vertex blending */
|
||||
glDisable(GL_VERTEX_BLEND_ARB);
|
||||
#endif
|
||||
TRACE("ARB_VERTEX_BLEND\n");
|
||||
static const GLbyte one = 1;
|
||||
glDisableClientState(GL_WEIGHT_ARRAY_ARB);
|
||||
checkGLcall("glEnableClientState(GL_WEIGHT_ARRAY_ARB)");
|
||||
GL_EXTCALL(glWeightbvARB(1, &one));
|
||||
checkGLcall("glWeightivARB(GL_LIMITS(blends), weights)");
|
||||
} else if (GL_SUPPORT(EXT_VERTEX_WEIGHTING)) {
|
||||
TRACE(" EXT_VERTEX_WEIGHTING\n");
|
||||
glDisableClientState(GL_VERTEX_WEIGHT_ARRAY_EXT);
|
||||
|
@ -2984,12 +3067,6 @@ static inline void handleStreams(IWineD3DStateBlockImpl *stateblock, BOOL useVer
|
|||
/* Generate some fixme's if unsupported functionality is being used */
|
||||
#define BUFFER_OR_DATA(_attribute) dataLocations->u.s._attribute.lpData
|
||||
/* TODO: Either support missing functionality in fixupVertices or by creating a shader to replace the pipeline. */
|
||||
if (!useVertexShaderFunction &&
|
||||
stateblock->renderState[WINED3DRS_VERTEXBLEND] &&
|
||||
(BUFFER_OR_DATA(blendMatrixIndices) || BUFFER_OR_DATA(blendWeights))) {
|
||||
FIXME("Vertex Blending is not implemented yet %p %p\n",dataLocations->u.s.blendWeights.lpData,dataLocations->u.s.blendWeights.lpData);
|
||||
/* TODO: Implement it using GL_ARB_vertex_blend or software emulation in drawStridedSlow */
|
||||
}
|
||||
if (!useVertexShaderFunction && (BUFFER_OR_DATA(position2) || BUFFER_OR_DATA(normal2))) {
|
||||
FIXME("Tweening is only valid with vertex shaders\n");
|
||||
}
|
||||
|
@ -3461,7 +3538,7 @@ const struct StateEntry StateTable[] =
|
|||
{ /*148, WINED3DRS_EMISSIVEMATERIALSOURCE */ STATE_RENDER(WINED3DRS_COLORVERTEX), state_colormat },
|
||||
{ /*149, Undefined */ 0, state_undefined },
|
||||
{ /*150, Undefined */ 0, state_undefined },
|
||||
{ /*151, WINED3DRS_VERTEXBLEND */ 0, state_nogl },
|
||||
{ /*151, WINED3DRS_VERTEXBLEND */ STATE_RENDER(WINED3DRS_VERTEXBLEND), state_vertexblend },
|
||||
{ /*152, WINED3DRS_CLIPPLANEENABLE */ STATE_RENDER(WINED3DRS_CLIPPING), state_clipping },
|
||||
{ /*153, WINED3DRS_SOFTWAREVERTEXPROCESSING */ 0, state_nogl },
|
||||
{ /*154, WINED3DRS_POINTSIZE */ STATE_RENDER(WINED3DRS_POINTSIZE), state_psize },
|
||||
|
|
|
@ -636,6 +636,7 @@ struct IWineD3DDeviceImpl
|
|||
/* To store */
|
||||
BOOL view_ident; /* true iff view matrix is identity */
|
||||
BOOL untransformed;
|
||||
BOOL vertexBlendUsed; /* To avoid needless setting of the blend matrices */
|
||||
|
||||
/* State block related */
|
||||
BOOL isRecordingState;
|
||||
|
|
Loading…
Reference in New Issue