wined3d: Add support for VBOs to the drawing code.

This commit is contained in:
Stefan Dösinger 2006-06-21 15:01:38 +02:00 committed by Alexandre Julliard
parent a796b8a3f7
commit 7d31ab95e4
5 changed files with 282 additions and 149 deletions

View File

@ -5107,14 +5107,10 @@ static HRESULT WINAPI IWineD3DDeviceImpl_ProcessVertices(IWineD3DDevice *iface,
IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
IWineD3DVertexBufferImpl *SrcImpl = (IWineD3DVertexBufferImpl *) pVertexDecl;
WineDirect3DVertexStridedData strided;
HRESULT hr;
TRACE("(%p)->(%d,%d,%d,%p,%p,%ld\n", This, SrcStartIndex, DestIndex, VertexCount, pDestBuffer, pVertexDecl, Flags);
hr = IWineD3DDevice_SetFVF(iface, SrcImpl->fvf);
hr = IWineD3DDevice_SetStreamSource(iface, 0, pVertexDecl, get_flexible_vertex_size(SrcImpl->fvf) * SrcStartIndex, get_flexible_vertex_size(SrcImpl->fvf));
memset(&strided, 0, sizeof(strided));
primitiveConvertToStridedData(iface, &strided, 0);
primitiveConvertFVFtoOffset(SrcImpl->fvf, get_flexible_vertex_size(SrcImpl->fvf), SrcImpl->resource.allocatedMemory + get_flexible_vertex_size(SrcImpl->fvf) * SrcStartIndex, &strided, 0);
return process_vertices_strided(This, DestIndex, VertexCount, &strided, SrcImpl->fvf, (IWineD3DVertexBufferImpl *) pDestBuffer, Flags);
}

View File

@ -360,7 +360,8 @@ void primitiveDeclarationConvertToStridedData(
BOOL useVertexShaderFunction,
WineDirect3DVertexStridedData *strided,
LONG BaseVertexIndex,
DWORD *fvf) {
DWORD *fvf,
BOOL *fixup) {
/* We need to deal with frequency data!*/
@ -384,15 +385,23 @@ void primitiveDeclarationConvertToStridedData(
/* Translate the declaration into strided data */
for (i = 0 ; i < vertexDeclaration->declarationWNumElements - 1; ++i) {
GLint streamVBO = 0;
element = vertexDeclaration->pDeclarationWine + i;
TRACE("%p Elements %p %d or %d\n", vertexDeclaration->pDeclarationWine, element, i, vertexDeclaration->declarationWNumElements);
if (This->stateBlock->streamIsUP) {
TRACE("Stream is up %d, %p\n", element->Stream, This->stateBlock->streamSource[element->Stream]);
streamVBO = 0;
data = (BYTE *)This->stateBlock->streamSource[element->Stream];
if(fixup && *fixup) FIXME("Missing fixed and unfixed vertices, expect graphics glitches\n");
} else {
TRACE("Stream isn't up %d, %p\n", element->Stream, This->stateBlock->streamSource[element->Stream]);
data = IWineD3DVertexBufferImpl_GetMemory(This->stateBlock->streamSource[element->Stream], 0);
IWineD3DVertexBuffer_PreLoad(This->stateBlock->streamSource[element->Stream]);
data = IWineD3DVertexBufferImpl_GetMemory(This->stateBlock->streamSource[element->Stream], 0, &streamVBO);
if(fixup) {
if( streamVBO != 0) *fixup = TRUE;
else if(*fixup) FIXME("Missing fixed and unfixed vertices, expect graphics glitches\n");
}
}
stride = This->stateBlock->streamStride[element->Stream];
data += (BaseVertexIndex * stride);
@ -401,11 +410,13 @@ void primitiveDeclarationConvertToStridedData(
TRACE("Offset %d Stream %d UsageIndex %d\n", element->Offset, element->Stream, element->UsageIndex);
if (useVertexShaderFunction && reg != -1 && data) {
if (useVertexShaderFunction && reg != -1 && (data || streamVBO) ) {
WINED3DGLTYPE glType = glTypeLookup[element->Type];
TRACE("(%p) : Set vertex attrib pointer: reg 0x%08x, d3d type 0x%08x, stride 0x%08lx, data %p)\n", This, reg, element->Type, stride, data);
GL_EXTCALL(glBindBufferARB(GL_ARRAY_BUFFER_ARB, streamVBO));
checkGLcall("glBindBufferARB");
GL_EXTCALL(glVertexAttribPointerARB(reg, glType.size, glType.glType, glType.normalized, stride, data));
checkGLcall("glVertexAttribPointerARB");
GL_EXTCALL(glEnableVertexAttribArrayARB(reg));
@ -419,6 +430,7 @@ void primitiveDeclarationConvertToStridedData(
strided->u.s.position.lpData = data;
strided->u.s.position.dwType = element->Type;
strided->u.s.position.dwStride = stride;
strided->u.s.position.VBO = streamVBO;
TRACE("Set strided %s. data %p, type %d. stride %ld\n", "position", data, element->Type, stride);
break;
case 1: /* tweened see http://www.gamedev.net/reference/articles/article2017.asp */
@ -426,6 +438,7 @@ void primitiveDeclarationConvertToStridedData(
strided->u.s.position2.lpData = data;
strided->u.s.position2.dwType = element->Type;
strided->u.s.position2.dwStride = stride;
strided->u.s.position2.VBO = streamVBO;
TRACE("Set strided %s. data %p, type %d. stride %ld\n", "position2", data, element->Type, stride);
break;
}
@ -436,6 +449,7 @@ void primitiveDeclarationConvertToStridedData(
strided->u.s.normal.lpData = data;
strided->u.s.normal.dwType = element->Type;
strided->u.s.normal.dwStride = stride;
strided->u.s.normal.VBO = streamVBO;
TRACE("Set strided %s. data %p, type %d. stride %ld\n", "normal", data, element->Type, stride);
break;
case 1: /* skinning */
@ -443,6 +457,7 @@ void primitiveDeclarationConvertToStridedData(
strided->u.s.normal2.lpData = data;
strided->u.s.normal2.dwType = element->Type;
strided->u.s.normal2.dwStride = stride;
strided->u.s.normal2.VBO = streamVBO;
TRACE("Set strided %s. data %p, type %d. stride %ld\n", "normal2", data, element->Type, stride);
break;
}
@ -455,18 +470,21 @@ void primitiveDeclarationConvertToStridedData(
strided->u.s.blendMatrixIndices.lpData = data;
strided->u.s.blendMatrixIndices.dwType = element->Type;
strided->u.s.blendMatrixIndices.dwStride= stride;
strided->u.s.blendMatrixIndices.VBO = streamVBO;
TRACE("Set strided %s. data %p, type %d. stride %ld\n", "blendMatrixIndices", data, element->Type, stride);
break;
case D3DDECLUSAGE_BLENDWEIGHT:
strided->u.s.blendWeights.lpData = data;
strided->u.s.blendWeights.dwType = element->Type;
strided->u.s.blendWeights.dwStride = stride;
strided->u.s.blendWeights.VBO = streamVBO;
TRACE("Set strided %s. data %p, type %d. stride %ld\n", "blendWeights", data, element->Type, stride);
break;
case D3DDECLUSAGE_PSIZE:
strided->u.s.pSize.lpData = data;
strided->u.s.pSize.dwType = element->Type;
strided->u.s.pSize.dwStride = stride;
strided->u.s.pSize.VBO = streamVBO;
TRACE("Set strided %s. data %p, type %d. stride %ld\n", "pSize", data, element->Type, stride);
break;
case D3DDECLUSAGE_COLOR:
@ -475,12 +493,14 @@ void primitiveDeclarationConvertToStridedData(
strided->u.s.diffuse.lpData = data;
strided->u.s.diffuse.dwType = element->Type;
strided->u.s.diffuse.dwStride = stride;
strided->u.s.diffuse.VBO = streamVBO;
TRACE("Set strided %s. data %p, type %d. stride %ld\n", "diffuse", data, element->Type, stride);
break;
case 1: /* specular */
strided->u.s.specular.lpData = data;
strided->u.s.specular.dwType = element->Type;
strided->u.s.specular.dwStride = stride;
strided->u.s.specular.VBO = streamVBO;
TRACE("Set strided %s. data %p, type %d. stride %ld\n", "specular", data, element->Type, stride);
}
@ -493,6 +513,7 @@ void primitiveDeclarationConvertToStridedData(
strided->u.s.texCoords[textureNo].lpData = data;
strided->u.s.texCoords[textureNo].dwType = element->Type;
strided->u.s.texCoords[textureNo].dwStride = stride;
strided->u.s.texCoords[textureNo].VBO = streamVBO;
TRACE("Set strided %s.%d data %p, type %d. stride %ld\n", "texCoords", textureNo, data, element->Type, stride);
++textureNo;
@ -505,6 +526,7 @@ void primitiveDeclarationConvertToStridedData(
strided->u.s.tangent.lpData = data;
strided->u.s.tangent.dwType = element->Type;
strided->u.s.tangent.dwStride = stride;
strided->u.s.tangent.VBO = streamVBO;
TRACE("Set strided %s. data %p, type %d. stride %ld\n", "tangent", data, element->Type, stride);
break;
case D3DDECLUSAGE_BINORMAL:
@ -516,6 +538,7 @@ void primitiveDeclarationConvertToStridedData(
strided->u.s.binormal.lpData = data;
strided->u.s.binormal.dwType = element->Type;
strided->u.s.binormal.dwStride = stride;
strided->u.s.binormal.VBO = streamVBO;
TRACE("Set strided %s. data %p, type %d. stride %ld\n", "binormal", data, element->Type, stride);
break;
case D3DDECLUSAGE_TESSFACTOR:
@ -525,6 +548,7 @@ void primitiveDeclarationConvertToStridedData(
strided->u.s.tessFactor.lpData = data;
strided->u.s.tessFactor.dwType = element->Type;
strided->u.s.tessFactor.dwStride = stride;
strided->u.s.tessFactor.VBO = streamVBO;
TRACE("Set strided %s. data %p, type %d. stride %ld\n", "tessFactor", data, element->Type, stride);
break;
case D3DDECLUSAGE_POSITIONT:
@ -534,6 +558,7 @@ void primitiveDeclarationConvertToStridedData(
strided->u.s.position.lpData = data;
strided->u.s.position.dwType = element->Type;
strided->u.s.position.dwStride = stride;
strided->u.s.position.VBO = streamVBO;
TRACE("Set strided %s. data %p, type %d. stride %ld\n", "positionT", data, element->Type, stride);
break;
case 1: /* skinning */
@ -544,6 +569,7 @@ void primitiveDeclarationConvertToStridedData(
strided->u.s.position2.lpData = data;
strided->u.s.position2.dwType = element->Type;
strided->u.s.position2.dwStride = stride;
strided->u.s.position2.VBO = streamVBO;
TRACE("Set strided %s. data %p, type %d. stride %ld\n", "position2T", data, element->Type, stride);
break;
}
@ -563,6 +589,7 @@ void primitiveDeclarationConvertToStridedData(
strided->u.s.fog.lpData = data;
strided->u.s.fog.dwType = element->Type;
strided->u.s.fog.dwStride = stride;
strided->u.s.fog.VBO = streamVBO;
TRACE("Set strided %s. data %p, type %d. stride %ld\n", "fog", data, element->Type, stride);
break;
case D3DDECLUSAGE_DEPTH:
@ -570,6 +597,7 @@ void primitiveDeclarationConvertToStridedData(
strided->u.s.depth.lpData = data;
strided->u.s.depth.dwType = element->Type;
strided->u.s.depth.dwStride = stride;
strided->u.s.depth.VBO = streamVBO;
TRACE("Set strided %s. data %p, type %d. stride %ld\n", "depth", data, element->Type, stride);
break;
case D3DDECLUSAGE_SAMPLE: /* VertexShader textures */
@ -577,6 +605,7 @@ void primitiveDeclarationConvertToStridedData(
strided->u.s.sample.lpData = data;
strided->u.s.sample.dwType = element->Type;
strided->u.s.sample.dwStride = stride;
strided->u.s.sample.VBO = streamVBO;
TRACE("Set strided %s. data %p, type %d. stride %ld\n", "sample", data, element->Type, stride);
break;
};
@ -585,16 +614,129 @@ void primitiveDeclarationConvertToStridedData(
}
void primitiveConvertToStridedData(IWineD3DDevice *iface, WineDirect3DVertexStridedData *strided, LONG BaseVertexIndex) {
short LoopThroughTo = 0;
short nStream;
void primitiveConvertFVFtoOffset(DWORD thisFVF, DWORD stride, BYTE *data, WineDirect3DVertexStridedData *strided, GLint streamVBO) {
int numBlends;
int numTextures;
int textureNo;
int coordIdxInfo = 0x00; /* Information on number of coords supplied */
int numCoords[8]; /* Holding place for D3DFVF_TEXTUREFORMATx */
/* Either 3 or 4 floats depending on the FVF */
/* FIXME: Can blending data be in a different stream to the position data?
and if so using the fixed pipeline how do we handle it */
if (thisFVF & D3DFVF_POSITION_MASK) {
strided->u.s.position.lpData = data;
strided->u.s.position.dwType = D3DDECLTYPE_FLOAT3;
strided->u.s.position.dwStride = stride;
strided->u.s.position.VBO = streamVBO;
data += 3 * sizeof(float);
if (thisFVF & D3DFVF_XYZRHW) {
strided->u.s.position.dwType = D3DDECLTYPE_FLOAT4;
data += sizeof(float);
}
}
/* Blending is numBlends * FLOATs followed by a DWORD for UBYTE4 */
/** do we have to Check This->stateBlock->renderState[D3DRS_INDEXEDVERTEXBLENDENABLE] ? */
numBlends = 1 + (((thisFVF & D3DFVF_XYZB5) - D3DFVF_XYZB1) >> 1);
if(thisFVF & D3DFVF_LASTBETA_UBYTE4) numBlends--;
if ((thisFVF & D3DFVF_XYZB5 ) > D3DFVF_XYZRHW) {
TRACE("Setting blend Weights to %p\n", data);
strided->u.s.blendWeights.lpData = data;
strided->u.s.blendWeights.dwType = D3DDECLTYPE_FLOAT1 + numBlends - 1;
strided->u.s.blendWeights.dwStride = stride;
strided->u.s.blendWeights.VBO = streamVBO;
data += numBlends * sizeof(FLOAT);
if (thisFVF & D3DFVF_LASTBETA_UBYTE4) {
strided->u.s.blendMatrixIndices.lpData = data;
strided->u.s.blendMatrixIndices.dwType = D3DDECLTYPE_UBYTE4;
strided->u.s.blendMatrixIndices.dwStride= stride;
strided->u.s.blendMatrixIndices.VBO = streamVBO;
data += sizeof(DWORD);
}
}
/* Normal is always 3 floats */
if (thisFVF & D3DFVF_NORMAL) {
strided->u.s.normal.lpData = data;
strided->u.s.normal.dwType = D3DDECLTYPE_FLOAT3;
strided->u.s.normal.dwStride = stride;
strided->u.s.normal.VBO = streamVBO;
data += 3 * sizeof(FLOAT);
}
/* Pointsize is a single float */
if (thisFVF & D3DFVF_PSIZE) {
strided->u.s.pSize.lpData = data;
strided->u.s.pSize.dwType = D3DDECLTYPE_FLOAT1;
strided->u.s.pSize.dwStride = stride;
strided->u.s.pSize.VBO = streamVBO;
data += sizeof(FLOAT);
}
/* Diffuse is 4 unsigned bytes */
if (thisFVF & D3DFVF_DIFFUSE) {
strided->u.s.diffuse.lpData = data;
strided->u.s.diffuse.dwType = D3DDECLTYPE_SHORT4;
strided->u.s.diffuse.dwStride = stride;
strided->u.s.diffuse.VBO = streamVBO;
data += sizeof(DWORD);
}
/* Specular is 4 unsigned bytes */
if (thisFVF & D3DFVF_SPECULAR) {
strided->u.s.specular.lpData = data;
strided->u.s.specular.dwType = D3DDECLTYPE_SHORT4;
strided->u.s.specular.dwStride = stride;
strided->u.s.specular.VBO = streamVBO;
data += sizeof(DWORD);
}
/* Texture coords */
numTextures = (thisFVF & D3DFVF_TEXCOUNT_MASK) >> D3DFVF_TEXCOUNT_SHIFT;
coordIdxInfo = (thisFVF & 0x00FF0000) >> 16; /* 16 is from definition of D3DFVF_TEXCOORDSIZE1, and is 8 (0-7 stages) * 2bits long */
/* numTextures indicates the number of texture coordinates supplied */
/* However, the first set may not be for stage 0 texture - it all */
/* depends on D3DTSS_TEXCOORDINDEX. */
/* The number of bytes for each coordinate set is based off */
/* D3DFVF_TEXCOORDSIZEn, which are the bottom 2 bits */
/* So, for each supplied texture extract the coords */
for (textureNo = 0; textureNo < numTextures; ++textureNo) {
strided->u.s.texCoords[textureNo].lpData = data;
strided->u.s.texCoords[textureNo].dwType = D3DDECLTYPE_FLOAT1;
strided->u.s.texCoords[textureNo].dwStride = stride;
strided->u.s.texCoords[textureNo].VBO = streamVBO;
numCoords[textureNo] = coordIdxInfo & 0x03;
/* Always one set */
data += sizeof(float);
if (numCoords[textureNo] != D3DFVF_TEXTUREFORMAT1) {
strided->u.s.texCoords[textureNo].dwType = D3DDECLTYPE_FLOAT2;
data += sizeof(float);
if (numCoords[textureNo] != D3DFVF_TEXTUREFORMAT2) {
strided->u.s.texCoords[textureNo].dwType = D3DDECLTYPE_FLOAT3;
data += sizeof(float);
if (numCoords[textureNo] != D3DFVF_TEXTUREFORMAT3) {
strided->u.s.texCoords[textureNo].dwType = D3DDECLTYPE_FLOAT4;
data += sizeof(float);
}
}
}
coordIdxInfo = coordIdxInfo >> 2; /* Drop bottom two bits */
}
}
void primitiveConvertToStridedData(IWineD3DDevice *iface, WineDirect3DVertexStridedData *strided, LONG BaseVertexIndex, BOOL *fixup) {
short LoopThroughTo = 0;
short nStream;
GLint streamVBO = 0;
IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
/* OK, Now to setup the data locations
@ -621,9 +763,15 @@ void primitiveConvertToStridedData(IWineD3DDevice *iface, WineDirect3DVertexStri
thisFVF = This->stateBlock->fvf;
/* Handle memory passed directly as well as vertex buffers */
if (This->stateBlock->streamIsUP) {
streamVBO = 0;
data = (BYTE *)This->stateBlock->streamSource[nStream];
} else {
data = IWineD3DVertexBufferImpl_GetMemory(This->stateBlock->streamSource[nStream], 0);
IWineD3DVertexBuffer_PreLoad(This->stateBlock->streamSource[nStream]);
/* GetMemory binds the VBO */
data = IWineD3DVertexBufferImpl_GetMemory(This->stateBlock->streamSource[nStream], 0, &streamVBO);
if(fixup) {
if(streamVBO != 0 ) *fixup = TRUE;
}
}
} else {
#if 0 /* TODO: Vertex shader support */
@ -639,106 +787,7 @@ void primitiveConvertToStridedData(IWineD3DDevice *iface, WineDirect3DVertexStri
/* Shuffle to the beginning of the vertexes to render and index from there */
data = data + (BaseVertexIndex * stride);
/* Either 3 or 4 floats depending on the FVF */
/* FIXME: Can blending data be in a different stream to the position data?
and if so using the fixed pipeline how do we handle it */
if (thisFVF & D3DFVF_POSITION_MASK) {
strided->u.s.position.lpData = data;
strided->u.s.position.dwType = D3DDECLTYPE_FLOAT3;
strided->u.s.position.dwStride = stride;
data += 3 * sizeof(float);
if (thisFVF & D3DFVF_XYZRHW) {
strided->u.s.position.dwType = D3DDECLTYPE_FLOAT4;
data += sizeof(float);
}
}
/* Blending is numBlends * FLOATs followed by a DWORD for UBYTE4 */
/** do we have to Check This->stateBlock->renderState[D3DRS_INDEXEDVERTEXBLENDENABLE] ? */
numBlends = 1 + (((thisFVF & D3DFVF_XYZB5) - D3DFVF_XYZB1) >> 1);
if(thisFVF & D3DFVF_LASTBETA_UBYTE4) numBlends--;
if ((thisFVF & D3DFVF_XYZB5 ) > D3DFVF_XYZRHW) {
TRACE("Setting blend Weights to %p\n", data);
strided->u.s.blendWeights.lpData = data;
strided->u.s.blendWeights.dwType = D3DDECLTYPE_FLOAT1 + numBlends - 1;
strided->u.s.blendWeights.dwStride = stride;
data += numBlends * sizeof(FLOAT);
if (thisFVF & D3DFVF_LASTBETA_UBYTE4) {
strided->u.s.blendMatrixIndices.lpData = data;
strided->u.s.blendMatrixIndices.dwType = D3DDECLTYPE_UBYTE4;
strided->u.s.blendMatrixIndices.dwStride= stride;
data += sizeof(DWORD);
}
}
/* Normal is always 3 floats */
if (thisFVF & D3DFVF_NORMAL) {
strided->u.s.normal.lpData = data;
strided->u.s.normal.dwType = D3DDECLTYPE_FLOAT3;
strided->u.s.normal.dwStride = stride;
data += 3 * sizeof(FLOAT);
}
/* Pointsize is a single float */
if (thisFVF & D3DFVF_PSIZE) {
strided->u.s.pSize.lpData = data;
strided->u.s.pSize.dwType = D3DDECLTYPE_FLOAT1;
strided->u.s.pSize.dwStride = stride;
data += sizeof(FLOAT);
}
/* Diffuse is 4 unsigned bytes */
if (thisFVF & D3DFVF_DIFFUSE) {
strided->u.s.diffuse.lpData = data;
strided->u.s.diffuse.dwType = D3DDECLTYPE_SHORT4;
strided->u.s.diffuse.dwStride = stride;
data += sizeof(DWORD);
}
/* Specular is 4 unsigned bytes */
if (thisFVF & D3DFVF_SPECULAR) {
strided->u.s.specular.lpData = data;
strided->u.s.specular.dwType = D3DDECLTYPE_SHORT4;
strided->u.s.specular.dwStride = stride;
data += sizeof(DWORD);
}
/* Texture coords */
numTextures = (thisFVF & D3DFVF_TEXCOUNT_MASK) >> D3DFVF_TEXCOUNT_SHIFT;
coordIdxInfo = (thisFVF & 0x00FF0000) >> 16; /* 16 is from definition of D3DFVF_TEXCOORDSIZE1, and is 8 (0-7 stages) * 2bits long */
/* numTextures indicates the number of texture coordinates supplied */
/* However, the first set may not be for stage 0 texture - it all */
/* depends on D3DTSS_TEXCOORDINDEX. */
/* The number of bytes for each coordinate set is based off */
/* D3DFVF_TEXCOORDSIZEn, which are the bottom 2 bits */
/* So, for each supplied texture extract the coords */
for (textureNo = 0; textureNo < numTextures; ++textureNo) {
strided->u.s.texCoords[textureNo].lpData = data;
strided->u.s.texCoords[textureNo].dwType = D3DDECLTYPE_FLOAT1;
strided->u.s.texCoords[textureNo].dwStride = stride;
numCoords[textureNo] = coordIdxInfo & 0x03;
/* Always one set */
data += sizeof(float);
if (numCoords[textureNo] != D3DFVF_TEXTUREFORMAT1) {
strided->u.s.texCoords[textureNo].dwType = D3DDECLTYPE_FLOAT2;
data += sizeof(float);
if (numCoords[textureNo] != D3DFVF_TEXTUREFORMAT2) {
strided->u.s.texCoords[textureNo].dwType = D3DDECLTYPE_FLOAT3;
data += sizeof(float);
if (numCoords[textureNo] != D3DFVF_TEXTUREFORMAT3) {
strided->u.s.texCoords[textureNo].dwType = D3DDECLTYPE_FLOAT4;
data += sizeof(float);
}
}
}
coordIdxInfo = coordIdxInfo >> 2; /* Drop bottom two bits */
}
primitiveConvertFVFtoOffset(thisFVF, stride, data, strided, streamVBO);
}
}
@ -879,11 +928,17 @@ void loadNumberedArrays(
DWORD arrayUsageMap[WINED3DSHADERDECLUSAGE_MAX_USAGE]) {
IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
GLint curVBO = -1;
#define LOAD_NUMBERED_ARRAY(_arrayName, _lookupName) \
if (sd->u.s._arrayName.lpData != NULL && arrayUsageMap[WINED3DSHADERDECLUSAGE_##_lookupName]) { \
if ((sd->u.s._arrayName.lpData != NULL || sd->u.s._arrayName.VBO != 0) && arrayUsageMap[WINED3DSHADERDECLUSAGE_##_lookupName]) { \
unsigned int idx = arrayUsageMap[WINED3DSHADERDECLUSAGE_##_lookupName] & D3DSP_REGNUM_MASK; \
TRACE_(d3d_shader)("Loading array %u with data from %s\n", idx, #_arrayName); \
if(curVBO != sd->u.s._arrayName.VBO) { \
GL_EXTCALL(glBindBufferARB(GL_ARRAY_BUFFER_ARB, sd->u.s._arrayName.VBO)); \
checkGLcall("glBindBufferARB"); \
curVBO = sd->u.s._arrayName.VBO; \
} \
GL_EXTCALL(glVertexAttribPointerARB(idx, \
WINED3D_ATR_SIZE(_arrayName), \
WINED3D_ATR_GLTYPE(_arrayName), \
@ -895,9 +950,14 @@ void loadNumberedArrays(
#define LOAD_NUMBERED_POSITION_ARRAY(_lookupNumber) \
if (sd->u.s.position2.lpData != NULL && arrayUsageMap[WINED3DSHADERDECLUSAGE_POSITION2 + _lookupNumber]) { \
if ((sd->u.s.position2.lpData != NULL || sd->u.s.position2.VBO != 0)&& arrayUsageMap[WINED3DSHADERDECLUSAGE_POSITION2 + _lookupNumber]) { \
unsigned int idx = arrayUsageMap[WINED3DSHADERDECLUSAGE_POSITION2 + _lookupNumber] & D3DSP_REGNUM_MASK; \
TRACE_(d3d_shader)("Loading array %u with data from %s\n", idx, "position2"); \
if(curVBO != sd->u.s.position2.VBO) { \
GL_EXTCALL(glBindBufferARB(GL_ARRAY_BUFFER_ARB, sd->u.s.position2.VBO)); \
checkGLcall("glBindBufferARB"); \
curVBO = sd->u.s.position2.VBO; \
} \
GL_EXTCALL(glVertexAttribPointerARB(idx, \
WINED3D_ATR_SIZE(position2), \
WINED3D_ATR_GLTYPE(position2), \
@ -911,7 +971,7 @@ void loadNumberedArrays(
/* Generate some lookup tables */
/* drop the RHW coord, there must be a nicer way of doing this. */
sd->u.s.position.dwType = min(D3DDECLTYPE_FLOAT3, sd->u.s.position.dwType);
sd->u.s.position2.dwType = min(D3DDECLTYPE_FLOAT3, sd->u.s.position.dwType);
sd->u.s.position2.dwType = min(D3DDECLTYPE_FLOAT3, sd->u.s.position2.dwType);
LOAD_NUMBERED_ARRAY(blendWeights,BLENDWEIGHT);
LOAD_NUMBERED_ARRAY(blendMatrixIndices,BLENDINDICES);
@ -965,11 +1025,12 @@ void loadNumberedArrays(
static void loadVertexData(IWineD3DDevice *iface, WineDirect3DVertexStridedData *sd) {
unsigned int textureNo = 0;
IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
GLint curVBO = -1;
TRACE("Using fast vertex array code\n");
/* Blend Data ---------------------------------------------- */
if ((sd->u.s.blendWeights.lpData != NULL) ||
(sd->u.s.blendMatrixIndices.lpData != NULL)) {
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)) {
@ -996,13 +1057,19 @@ static void loadVertexData(IWineD3DDevice *iface, WineDirect3DVertexStridedData
sd->u.s.blendWeights.dwStride,
sd->u.s.blendWeights.lpData));
if(curVBO != sd->u.s.blendWeights.VBO) {
GL_EXTCALL(glBindBufferARB(GL_ARRAY_BUFFER_ARB, sd->u.s.blendWeights.VBO));
checkGLcall("glBindBufferARB");
curVBO = sd->u.s.blendWeights.VBO;
}
GL_EXTCALL(glWeightPointerARB)(WINED3D_ATR_SIZE(blendWeights), WINED3D_ATR_GLTYPE(blendWeights),
sd->u.s.blendWeights.dwStride,
sd->u.s.blendWeights.lpData);
checkGLcall("glWeightPointerARB");
if(sd->u.s.blendMatrixIndices.lpData != NULL){
if((sd->u.s.blendMatrixIndices.lpData) || (sd->u.s.blendMatrixIndices.VBO)){
static BOOL showfixme = TRUE;
if(showfixme){
FIXME("blendMatrixIndices support\n");
@ -1043,7 +1110,7 @@ static void loadVertexData(IWineD3DDevice *iface, WineDirect3DVertexStridedData
}
#if 0 /* FOG ----------------------------------------------*/
if (sd->u.s.fog.lpData != NULL) {
if (sd->u.s.fog.lpData || sd->u.s.fog.VBO) {
/* TODO: fog*/
if (GL_SUPPORT(EXT_FOG_COORD) {
glEnableClientState(GL_FOG_COORDINATE_EXT);
@ -1064,10 +1131,11 @@ static void loadVertexData(IWineD3DDevice *iface, WineDirect3DVertexStridedData
#endif
#if 0 /* tangents ----------------------------------------------*/
if (sd->u.s.tangent.lpData != NULL || sd->u.s.binormal.lpData != NULL) {
if (sd->u.s.tangent.lpData || sd->u.s.tangent.VBO ||
sd->u.s.binormal.lpData || sd->u.s.binormal.VBO) {
/* TODO: tangents*/
if (GL_SUPPORT(EXT_COORDINATE_FRAME) {
if (sd->u.s.tangent.lpData != NULL) {
if (sd->u.s.tangent.lpData || sd->u.s.tangent.VBO) {
glEnable(GL_TANGENT_ARRAY_EXT);
(GL_EXTCALL)(TangentPointerEXT)(WINED3D_ATR_GLTYPE(tangent),
sd->u.s.tangent.dwStride,
@ -1075,7 +1143,7 @@ static void loadVertexData(IWineD3DDevice *iface, WineDirect3DVertexStridedData
} else {
glDisable(GL_TANGENT_ARRAY_EXT);
}
if (sd->u.s.binormal.lpData != NULL) {
if (sd->u.s.binormal.lpData || sd->u.s.binormal.VBO) {
glEnable(GL_BINORMAL_ARRAY_EXT);
(GL_EXTCALL)(BinormalPointerEXT)(WINED3D_ATR_GLTYPE(binormal),
sd->u.s.binormal.dwStride,
@ -1099,7 +1167,7 @@ static void loadVertexData(IWineD3DDevice *iface, WineDirect3DVertexStridedData
#endif
/* Point Size ----------------------------------------------*/
if (sd->u.s.pSize.lpData != NULL) {
if (sd->u.s.pSize.lpData || sd->u.s.pSize.VBO) {
/* no such functionality in the fixed function GL pipeline */
TRACE("Cannot change ptSize here in openGl\n");
@ -1108,20 +1176,34 @@ static void loadVertexData(IWineD3DDevice *iface, WineDirect3DVertexStridedData
}
/* Vertex Pointers -----------------------------------------*/
if (sd->u.s.position.lpData != NULL) {
if (sd->u.s.position.lpData != NULL || sd->u.s.position.VBO != 0) {
/* Note dwType == float3 or float4 == 2 or 3 */
VTRACE(("glVertexPointer(%ld, GL_FLOAT, %ld, %p)\n",
sd->u.s.position.dwStride,
sd->u.s.position.dwType + 1,
sd->u.s.position.lpData));
if(curVBO != sd->u.s.position.VBO) {
GL_EXTCALL(glBindBufferARB(GL_ARRAY_BUFFER_ARB, sd->u.s.position.VBO));
checkGLcall("glBindBufferARB");
curVBO = sd->u.s.position.VBO;
}
/* min(WINED3D_ATR_SIZE(position),3) to Disable RHW mode as 'w' coord
handling for rhw mode should not impact screen position whereas in GL it does.
This may result in very slightly distored textures in rhw mode, but
a very minimal different. There's always the other option of
fixing the view matrix to prevent w from having any effect */
glVertexPointer(3 /* min(WINED3D_ATR_SIZE(position),3) */, WINED3D_ATR_GLTYPE(position),
sd->u.s.position.dwStride, sd->u.s.position.lpData);
fixing the view matrix to prevent w from having any effect
This only applies to user pointer sources, in VBOs the vertices are fixed up
*/
if(sd->u.s.position.VBO == 0) {
glVertexPointer(3 /* min(WINED3D_ATR_SIZE(position),3) */, WINED3D_ATR_GLTYPE(position),
sd->u.s.position.dwStride, sd->u.s.position.lpData);
} else {
glVertexPointer(WINED3D_ATR_SIZE(position), WINED3D_ATR_GLTYPE(position),
sd->u.s.position.dwStride, sd->u.s.position.lpData);
}
checkGLcall("glVertexPointer(...)");
glEnableClientState(GL_VERTEX_ARRAY);
checkGLcall("glEnableClientState(GL_VERTEX_ARRAY)");
@ -1132,11 +1214,16 @@ static void loadVertexData(IWineD3DDevice *iface, WineDirect3DVertexStridedData
}
/* Normals -------------------------------------------------*/
if (sd->u.s.normal.lpData != NULL) {
if (sd->u.s.normal.lpData || sd->u.s.normal.VBO) {
/* Note dwType == float3 or float4 == 2 or 3 */
VTRACE(("glNormalPointer(GL_FLOAT, %ld, %p)\n",
sd->u.s.normal.dwStride,
sd->u.s.normal.lpData));
if(curVBO != sd->u.s.normal.VBO) {
GL_EXTCALL(glBindBufferARB(GL_ARRAY_BUFFER_ARB, sd->u.s.normal.VBO));
checkGLcall("glBindBufferARB");
curVBO = sd->u.s.normal.VBO;
}
glNormalPointer(WINED3D_ATR_GLTYPE(normal),
sd->u.s.normal.dwStride,
sd->u.s.normal.lpData);
@ -1160,12 +1247,17 @@ static void loadVertexData(IWineD3DDevice *iface, WineDirect3DVertexStridedData
/* NOTE: Unless we write a vertex shader to swizel the colour */
/* , or the user doesn't care and wants the speed advantage */
if (sd->u.s.diffuse.lpData != NULL) {
if (sd->u.s.diffuse.lpData || sd->u.s.diffuse.VBO) {
/* Note dwType == float3 or float4 == 2 or 3 */
VTRACE(("glColorPointer(4, GL_UNSIGNED_BYTE, %ld, %p)\n",
sd->u.s.diffuse.dwStride,
sd->u.s.diffuse.lpData));
if(curVBO != sd->u.s.diffuse.VBO) {
GL_EXTCALL(glBindBufferARB(GL_ARRAY_BUFFER_ARB, sd->u.s.diffuse.VBO));
checkGLcall("glBindBufferARB");
curVBO = sd->u.s.diffuse.VBO;
}
glColorPointer(4, GL_UNSIGNED_BYTE,
sd->u.s.diffuse.dwStride,
sd->u.s.diffuse.lpData);
@ -1181,13 +1273,18 @@ static void loadVertexData(IWineD3DDevice *iface, WineDirect3DVertexStridedData
}
/* Specular Colour ------------------------------------------*/
if (sd->u.s.specular.lpData != NULL) {
if (sd->u.s.specular.lpData || sd->u.s.specular.VBO) {
TRACE("setting specular colour\n");
/* Note dwType == float3 or float4 == 2 or 3 */
VTRACE(("glSecondaryColorPointer(4, GL_UNSIGNED_BYTE, %ld, %p)\n",
sd->u.s.specular.dwStride,
sd->u.s.specular.lpData));
if (GL_SUPPORT(EXT_SECONDARY_COLOR)) {
if(curVBO != sd->u.s.specular.VBO) {
GL_EXTCALL(glBindBufferARB(GL_ARRAY_BUFFER_ARB, sd->u.s.specular.VBO));
checkGLcall("glBindBufferARB");
curVBO = sd->u.s.specular.VBO;
}
GL_EXTCALL(glSecondaryColorPointerEXT)(4, GL_UNSIGNED_BYTE,
sd->u.s.specular.dwStride,
sd->u.s.specular.lpData);
@ -1235,13 +1332,17 @@ static void loadVertexData(IWineD3DDevice *iface, WineDirect3DVertexStridedData
glDisableClientState(GL_TEXTURE_COORD_ARRAY);
GL_EXTCALL(glMultiTexCoord4fARB(GL_TEXTURE0_ARB + textureNo, 0, 0, 0, 1));
} else if (sd->u.s.texCoords[coordIdx].lpData == NULL) {
} else if (sd->u.s.texCoords[coordIdx].lpData == NULL && sd->u.s.texCoords[coordIdx].VBO == 0) {
VTRACE(("Bound texture but no texture coordinates supplied, so skipping\n"));
glDisableClientState(GL_TEXTURE_COORD_ARRAY);
GL_EXTCALL(glMultiTexCoord4fARB(GL_TEXTURE0_ARB + textureNo, 0, 0, 0, 1));
} else {
if(curVBO != sd->u.s.texCoords[coordIdx].VBO) {
GL_EXTCALL(glBindBufferARB(GL_ARRAY_BUFFER_ARB, sd->u.s.texCoords[coordIdx].VBO));
checkGLcall("glBindBufferARB");
curVBO = sd->u.s.texCoords[coordIdx].VBO;
}
/* The coords to supply depend completely on the fvf / vertex shader */
glTexCoordPointer(WINED3D_ATR_SIZE(texCoords[coordIdx]), WINED3D_ATR_GLTYPE(texCoords[coordIdx]), sd->u.s.texCoords[coordIdx].dwStride, sd->u.s.texCoords[coordIdx].lpData);
glEnableClientState(GL_TEXTURE_COORD_ARRAY);
@ -1322,6 +1423,10 @@ static void drawStridedSlow(IWineD3DDevice *iface, WineDirect3DVertexStridedData
VTRACE(("glBegin(%x)\n", glPrimType));
glBegin(glPrimType);
/* We shouldn't start this function if any VBO is involved. Should I put a safety check here?
* Guess it's not necessary(we crash then anyway) and would only eat CPU time
*/
/* For each primitive */
for (vx_index = 0; vx_index < NumVertexes; ++vx_index) {
@ -1743,8 +1848,9 @@ void drawStridedSoftwareVS(IWineD3DDevice *iface, WineDirect3DVertexStridedData
#endif
void inline drawPrimitiveDrawStrided(IWineD3DDevice *iface, BOOL useVertexShaderFunction, BOOL usePixelShaderFunction, int useHW, WineDirect3DVertexStridedData *dataLocations,
UINT numberOfvertices, UINT numberOfIndicies, GLenum glPrimType, const void *idxData, short idxSize, int minIndex, long StartIdx) {
UINT numberOfvertices, UINT numberOfIndicies, GLenum glPrimType, const void *idxData, short idxSize, int minIndex, long StartIdx, BOOL fixup) {
IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
BOOL useDrawStridedSlow;
/* Now draw the graphics to the screen */
if (FALSE /* disable software vs for now */ && useVertexShaderFunction && !useHW) {
@ -1818,13 +1924,15 @@ UINT numberOfvertices, UINT numberOfIndicies, GLenum glPrimType, const void *idx
/* If the only vertex data used by the shader is supported by OpenGL then*/
if (!useVertexShaderFunction &&
dataLocations->u.s.pSize.lpData == NULL &&
((dataLocations->u.s.pSize.lpData == NULL &&
dataLocations->u.s.diffuse.lpData == NULL &&
dataLocations->u.s.specular.lpData == NULL) {
dataLocations->u.s.specular.lpData == NULL) ||
fixup) ) {
/* Load the vertex data using named arrays */
TRACE("(%p) Loading vertex data\n", This);
loadVertexData(iface, dataLocations);
useDrawStridedSlow = FALSE;
} else if(useVertexShaderFunction) {
@ -1832,8 +1940,10 @@ UINT numberOfvertices, UINT numberOfIndicies, GLenum glPrimType, const void *idx
loadNumberedArrays(iface, dataLocations,
((IWineD3DVertexShaderImpl *)This->stateBlock->vertexShader)->arrayUsageMap);
useDrawStridedSlow = FALSE;
} else { /* If this happens we must drawStridedSlow later on */
TRACE("Not loading vertex data\n");
useDrawStridedSlow = TRUE;
}
TRACE("Loaded arrays\n");
@ -1896,10 +2006,7 @@ UINT numberOfvertices, UINT numberOfIndicies, GLenum glPrimType, const void *idx
/* DirectX colours are in a different format to opengl colours
* so if diffuse or specular are used then we need to use drawStridedSlow
* to correct the colours */
if (!useVertexShaderFunction &&
((dataLocations->u.s.pSize.lpData != NULL)
|| (dataLocations->u.s.diffuse.lpData != NULL)
|| (dataLocations->u.s.specular.lpData != NULL))) {
if (useDrawStridedSlow) {
/* TODO: replace drawStridedSlow with vertex fixups */
drawStridedSlow(iface, dataLocations, numberOfIndicies, glPrimType,
@ -2091,6 +2198,7 @@ void drawPrimitive(IWineD3DDevice *iface,
WineDirect3DVertexStridedData *dataLocations;
IWineD3DSwapChainImpl *swapchain;
int useHW = FALSE, i;
BOOL fixup = FALSE;
if (This->stateBlock->vertexShader != NULL && wined3d_settings.vs_mode != VS_NONE
&&((IWineD3DVertexShaderImpl *)This->stateBlock->vertexShader)->baseShader.function != NULL
@ -2131,6 +2239,7 @@ void drawPrimitive(IWineD3DDevice *iface,
if(DrawPrimStrideData) {
TRACE("================ Strided Input ===================\n");
dataLocations = DrawPrimStrideData;
fixup = FALSE;
}
else if (This->stateBlock->vertexDecl != NULL || (useVertexShaderFunction && NULL != ((IWineD3DVertexShaderImpl *)This->stateBlock->vertexShader)->vertexDeclaration)) {
@ -2140,7 +2249,7 @@ void drawPrimitive(IWineD3DDevice *iface,
ERR("Out of memory!\n");
return;
}
primitiveDeclarationConvertToStridedData(iface, useVertexShaderFunction, dataLocations, StartVertexIndex, &fvf);
primitiveDeclarationConvertToStridedData(iface, useVertexShaderFunction, dataLocations, StartVertexIndex, &fvf, &fixup);
} else {
TRACE("================ FVF ===================\n");
@ -2149,7 +2258,7 @@ void drawPrimitive(IWineD3DDevice *iface,
ERR("Out of memory!\n");
return;
}
primitiveConvertToStridedData(iface, dataLocations, StartVertexIndex);
primitiveConvertToStridedData(iface, dataLocations, StartVertexIndex, &fixup);
}
/* write out some debug information*/
@ -2171,7 +2280,7 @@ void drawPrimitive(IWineD3DDevice *iface,
}
/* Now initialize the materials state */
init_materials(iface, (dataLocations->u.s.diffuse.lpData != NULL));
init_materials(iface, (dataLocations->u.s.diffuse.lpData != NULL || dataLocations->u.s.diffuse.VBO != 0));
drawPrimitiveUploadTextures(This);
@ -2188,7 +2297,7 @@ void drawPrimitive(IWineD3DDevice *iface,
#endif
if (numberOfVertices == 0 )
numberOfVertices = calculatedNumberOfindices;
drawPrimitiveDrawStrided(iface, useVertexShaderFunction, usePixelShaderFunction, useHW, dataLocations, numberOfVertices, calculatedNumberOfindices, glPrimType, idxData, idxSize, minIndex, StartIdx);
drawPrimitiveDrawStrided(iface, useVertexShaderFunction, usePixelShaderFunction, useHW, dataLocations, numberOfVertices, calculatedNumberOfindices, glPrimType, idxData, idxSize, minIndex, StartIdx, fixup);
}
if(!DrawPrimStrideData) HeapFree(GetProcessHeap(), 0, dataLocations);

View File

@ -152,8 +152,9 @@ const IWineD3DVertexBufferVtbl IWineD3DVertexBuffer_Vtbl =
IWineD3DVertexBufferImpl_GetDesc
};
BYTE* WINAPI IWineD3DVertexBufferImpl_GetMemory(IWineD3DVertexBuffer* iface, DWORD iOffset) {
BYTE* WINAPI IWineD3DVertexBufferImpl_GetMemory(IWineD3DVertexBuffer* iface, DWORD iOffset, GLint *vbo) {
IWineD3DVertexBufferImpl *This = (IWineD3DVertexBufferImpl *)iface;
*vbo = 0;
return This->resource.allocatedMemory + iOffset;
}

View File

@ -357,9 +357,21 @@ void drawPrimitive(IWineD3DDevice *iface,
int minIndex,
WineDirect3DVertexStridedData *DrawPrimStrideData);
void primitiveConvertToStridedData(IWineD3DDevice *iface,
WineDirect3DVertexStridedData *strided,
LONG BaseVertexIndex);
void primitiveConvertToStridedData(IWineD3DDevice *iface, WineDirect3DVertexStridedData *strided, LONG BaseVertexIndex, BOOL *fixup);
void primitiveDeclarationConvertToStridedData(
IWineD3DDevice *iface,
BOOL useVertexShaderFunction,
WineDirect3DVertexStridedData *strided,
LONG BaseVertexIndex,
DWORD *fvf,
BOOL *fixup);
void primitiveConvertFVFtoOffset(DWORD thisFVF,
DWORD stride,
BYTE *data,
WineDirect3DVertexStridedData *strided,
GLint streamVBO);
DWORD get_flexible_vertex_size(DWORD d3dvtVertexType);
@ -615,10 +627,24 @@ typedef struct IWineD3DVertexBufferImpl
/* WineD3DVertexBuffer specifics */
DWORD fvf;
/* Vertex buffer object support */
GLuint vbo;
BYTE Flags;
UINT stream;
UINT dirtystart, dirtyend;
/* Last description of the buffer */
WineDirect3DVertexStridedData strided;
} IWineD3DVertexBufferImpl;
extern const IWineD3DVertexBufferVtbl IWineD3DVertexBuffer_Vtbl;
#define VBFLAG_LOAD 0x01 /* Data is written from allocatedMemory to the VBO */
#define VBFLAG_OPTIMIZED 0x02 /* Optimize has been called for the VB */
#define VBFLAG_DIRTY 0x04 /* Buffer data has been modified */
#define VBFLAG_STREAM 0x08 /* The vertex buffer is in a stream */
#define VBFLAG_HASDESC 0x10 /* A vertex description has been found */
/*****************************************************************************
* IWineD3DIndexBuffer implementation structure (extends IWineD3DResourceImpl)
@ -1220,7 +1246,7 @@ void multiply_matrix(D3DMATRIX *dest, D3DMATRIX *src1, D3DMATRIX *src2);
extern BOOL WINAPI IWineD3DBaseTextureImpl_SetDirty(IWineD3DBaseTexture *iface, BOOL);
extern BOOL WINAPI IWineD3DBaseTextureImpl_GetDirty(IWineD3DBaseTexture *iface);
extern BYTE* WINAPI IWineD3DVertexBufferImpl_GetMemory(IWineD3DVertexBuffer* iface, DWORD iOffset);
extern BYTE* WINAPI IWineD3DVertexBufferImpl_GetMemory(IWineD3DVertexBuffer* iface, DWORD iOffset, GLint *vbo);
extern HRESULT WINAPI IWineD3DVertexBufferImpl_ReleaseMemory(IWineD3DVertexBuffer* iface);
extern HRESULT WINAPI IWineD3DBaseTextureImpl_BindTexture(IWineD3DBaseTexture *iface);
extern HRESULT WINAPI IWineD3DBaseTextureImpl_UnBindTexture(IWineD3DBaseTexture *iface);

View File

@ -898,6 +898,7 @@ typedef struct WineDirect3DStridedData {
BYTE *lpData; /* Pointer to start of data */
DWORD dwStride; /* Stride between occurances of this data */
DWORD dwType; /* Type (as in D3DVSDT_TYPE) */
int VBO; /* Vertex buffer object this data is in */
} WineDirect3DStridedData;
typedef struct WineDirect3DVertexStridedData {