📄 drawprim.c
字号:
/*
* WINED3D draw functions
*
* Copyright 2002-2004 Jason Edmeades
* Copyright 2002-2004 Raphael Junqueira
* Copyright 2004 Christian Costa
* Copyright 2005 Oliver Stieber
* Copyright 2006 Henri Verbeet
* Copyright 2007 Stefan D鰏inger for CodeWeavers
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
*/
#include "config.h"
#include "wined3d_private.h"
WINE_DEFAULT_DEBUG_CHANNEL(d3d_draw);
#define GLINFO_LOCATION This->adapter->gl_info
#include <stdio.h>
#if 0 /* TODO */
extern IWineD3DVertexShaderImpl* VertexShaders[64];
extern IWineD3DVertexDeclarationImpl* VertexShaderDeclarations[64];
extern IWineD3DPixelShaderImpl* PixelShaders[64];
#undef GL_VERSION_1_4 /* To be fixed, caused by mesa headers */
#endif
/* Issues the glBegin call for gl given the primitive type and count */
static DWORD primitiveToGl(WINED3DPRIMITIVETYPE PrimitiveType,
DWORD NumPrimitives,
GLenum *primType)
{
DWORD NumVertexes = NumPrimitives;
switch (PrimitiveType) {
case WINED3DPT_POINTLIST:
TRACE("POINTS\n");
*primType = GL_POINTS;
NumVertexes = NumPrimitives;
break;
case WINED3DPT_LINELIST:
TRACE("LINES\n");
*primType = GL_LINES;
NumVertexes = NumPrimitives * 2;
break;
case WINED3DPT_LINESTRIP:
TRACE("LINE_STRIP\n");
*primType = GL_LINE_STRIP;
NumVertexes = NumPrimitives + 1;
break;
case WINED3DPT_TRIANGLELIST:
TRACE("TRIANGLES\n");
*primType = GL_TRIANGLES;
NumVertexes = NumPrimitives * 3;
break;
case WINED3DPT_TRIANGLESTRIP:
TRACE("TRIANGLE_STRIP\n");
*primType = GL_TRIANGLE_STRIP;
NumVertexes = NumPrimitives + 2;
break;
case WINED3DPT_TRIANGLEFAN:
TRACE("TRIANGLE_FAN\n");
*primType = GL_TRIANGLE_FAN;
NumVertexes = NumPrimitives + 2;
break;
default:
FIXME("Unhandled primitive\n");
*primType = GL_POINTS;
break;
}
return NumVertexes;
}
static BOOL fixed_get_input(
BYTE usage, BYTE usage_idx,
unsigned int* regnum) {
*regnum = -1;
/* Those positions must have the order in the
* named part of the strided data */
if ((usage == WINED3DDECLUSAGE_POSITION || usage == WINED3DDECLUSAGE_POSITIONT) && usage_idx == 0)
*regnum = 0;
else if (usage == WINED3DDECLUSAGE_BLENDWEIGHT && usage_idx == 0)
*regnum = 1;
else if (usage == WINED3DDECLUSAGE_BLENDINDICES && usage_idx == 0)
*regnum = 2;
else if (usage == WINED3DDECLUSAGE_NORMAL && usage_idx == 0)
*regnum = 3;
else if (usage == WINED3DDECLUSAGE_PSIZE && usage_idx == 0)
*regnum = 4;
else if (usage == WINED3DDECLUSAGE_COLOR && usage_idx == 0)
*regnum = 5;
else if (usage == WINED3DDECLUSAGE_COLOR && usage_idx == 1)
*regnum = 6;
else if (usage == WINED3DDECLUSAGE_TEXCOORD && usage_idx < WINED3DDP_MAXTEXCOORD)
*regnum = 7 + usage_idx;
else if ((usage == WINED3DDECLUSAGE_POSITION || usage == WINED3DDECLUSAGE_POSITIONT) && usage_idx == 1)
*regnum = 7 + WINED3DDP_MAXTEXCOORD;
else if (usage == WINED3DDECLUSAGE_NORMAL && usage_idx == 1)
*regnum = 8 + WINED3DDP_MAXTEXCOORD;
else if (usage == WINED3DDECLUSAGE_TANGENT && usage_idx == 0)
*regnum = 9 + WINED3DDP_MAXTEXCOORD;
else if (usage == WINED3DDECLUSAGE_BINORMAL && usage_idx == 0)
*regnum = 10 + WINED3DDP_MAXTEXCOORD;
else if (usage == WINED3DDECLUSAGE_TESSFACTOR && usage_idx == 0)
*regnum = 11 + WINED3DDP_MAXTEXCOORD;
else if (usage == WINED3DDECLUSAGE_FOG && usage_idx == 0)
*regnum = 12 + WINED3DDP_MAXTEXCOORD;
else if (usage == WINED3DDECLUSAGE_DEPTH && usage_idx == 0)
*regnum = 13 + WINED3DDP_MAXTEXCOORD;
else if (usage == WINED3DDECLUSAGE_SAMPLE && usage_idx == 0)
*regnum = 14 + WINED3DDP_MAXTEXCOORD;
if (*regnum < 0) {
FIXME("Unsupported input stream [usage=%s, usage_idx=%u]\n",
debug_d3ddeclusage(usage), usage_idx);
return FALSE;
}
return TRUE;
}
void primitiveDeclarationConvertToStridedData(
IWineD3DDevice *iface,
BOOL useVertexShaderFunction,
WineDirect3DVertexStridedData *strided,
BOOL *fixup) {
/* We need to deal with frequency data!*/
BYTE *data = NULL;
IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
IWineD3DVertexDeclarationImpl* vertexDeclaration = (IWineD3DVertexDeclarationImpl *)This->stateBlock->vertexDecl;
int i;
WINED3DVERTEXELEMENT *element;
DWORD stride;
int reg;
DWORD numPreloadStreams = This->stateBlock->streamIsUP ? 0 : vertexDeclaration->num_streams;
DWORD *streams = vertexDeclaration->streams;
/* Check for transformed vertices, disable vertex shader if present */
strided->u.s.position_transformed = vertexDeclaration->position_transformed;
if(vertexDeclaration->position_transformed) {
useVertexShaderFunction = FALSE;
}
/* Translate the declaration into strided data */
for (i = 0 ; i < vertexDeclaration->declarationWNumElements - 1; ++i) {
GLint streamVBO = 0;
BOOL stride_used;
unsigned int idx;
element = vertexDeclaration->pDeclarationWine + i;
TRACE("%p Element %p (%d of %d)\n", vertexDeclaration->pDeclarationWine,
element, i + 1, vertexDeclaration->declarationWNumElements - 1);
if (This->stateBlock->streamSource[element->Stream] == NULL)
continue;
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];
} 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, &streamVBO);
if(fixup) {
if( streamVBO != 0) *fixup = TRUE;
else if(*fixup && !useVertexShaderFunction &&
(element->Usage == WINED3DDECLUSAGE_COLOR ||
element->Usage == WINED3DDECLUSAGE_POSITIONT)) {
/* This may be bad with the fixed function pipeline */
FIXME("Missing vbo streams with unfixed colors or transformed position, expect problems\n");
}
}
}
stride = This->stateBlock->streamStride[element->Stream];
data += element->Offset;
reg = element->Reg;
TRACE("Offset %d Stream %d UsageIndex %d\n", element->Offset, element->Stream, element->UsageIndex);
if (useVertexShaderFunction)
stride_used = vshader_get_input(This->stateBlock->vertexShader,
element->Usage, element->UsageIndex, &idx);
else
stride_used = fixed_get_input(element->Usage, element->UsageIndex, &idx);
if (stride_used) {
TRACE("Loaded %s array %u [usage=%s, usage_idx=%u, "
"stream=%u, offset=%u, stride=%u, type=%s, VBO=%u]\n",
useVertexShaderFunction? "shader": "fixed function", idx,
debug_d3ddeclusage(element->Usage), element->UsageIndex,
element->Stream, element->Offset, stride, debug_d3ddecltype(element->Type), streamVBO);
strided->u.input[idx].lpData = data;
strided->u.input[idx].dwType = element->Type;
strided->u.input[idx].dwStride = stride;
strided->u.input[idx].VBO = streamVBO;
strided->u.input[idx].streamNo = element->Stream;
}
}
/* Now call PreLoad on all the vertex buffers. In the very rare case
* that the buffers stopps converting PreLoad will dirtify the VDECL again.
* The vertex buffer can now use the strided structure in the device instead of finding its
* own again.
*
* NULL streams won't be recorded in the array, UP streams won't be either. A stream is only
* once in there.
*/
for(i=0; i < numPreloadStreams; i++) {
IWineD3DVertexBuffer_PreLoad(This->stateBlock->streamSource[streams[i]]);
}
}
static void drawStridedFast(IWineD3DDevice *iface,UINT numberOfVertices, GLenum glPrimitiveType,
const void *idxData, short idxSize, ULONG minIndex, ULONG startIdx, ULONG startVertex) {
IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
if (idxSize != 0 /* This crashes sometimes!*/) {
TRACE("(%p) : glElements(%x, %d, %d, ...)\n", This, glPrimitiveType, numberOfVertices, minIndex);
idxData = idxData == (void *)-1 ? NULL : idxData;
#if 1
glDrawElements(glPrimitiveType, numberOfVertices, idxSize == 2 ? GL_UNSIGNED_SHORT : GL_UNSIGNED_INT,
(const char *)idxData+(idxSize * startIdx));
checkGLcall("glDrawElements");
#else /* using drawRangeElements may be faster */
glDrawRangeElements(glPrimitiveType, minIndex, minIndex + numberOfVertices - 1, numberOfVertices,
idxSize == 2 ? GL_UNSIGNED_SHORT : GL_UNSIGNED_INT,
(const char *)idxData+(idxSize * startIdx));
checkGLcall("glDrawRangeElements");
#endif
} else {
/* Note first is now zero as we shuffled along earlier */
TRACE("(%p) : glDrawArrays(%x, 0, %d)\n", This, glPrimitiveType, numberOfVertices);
glDrawArrays(glPrimitiveType, startVertex, numberOfVertices);
checkGLcall("glDrawArrays");
}
return;
}
/*
* Actually draw using the supplied information.
* Slower GL version which extracts info about each vertex in turn
*/
static void drawStridedSlow(IWineD3DDevice *iface, WineDirect3DVertexStridedData *sd,
UINT NumVertexes, GLenum glPrimType,
const void *idxData, short idxSize, ULONG minIndex, ULONG startIdx, ULONG startVertex) {
unsigned int textureNo = 0;
const WORD *pIdxBufS = NULL;
const DWORD *pIdxBufL = NULL;
LONG vx_index;
float x = 0.0f, y = 0.0f, z = 0.0f; /* x,y,z coordinates */
float rhw = 0.0f; /* rhw */
DWORD diffuseColor = 0xFFFFFFFF; /* Diffuse Color */
DWORD specularColor = 0; /* Specular Color */
IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
UINT *streamOffset = This->stateBlock->streamOffset;
DWORD SkipnStrides = startVertex + This->stateBlock->loadBaseVertexIndex;
BYTE *texCoords[WINED3DDP_MAXTEXCOORD];
BYTE *diffuse = NULL, *specular = NULL, *normal = NULL, *position = NULL;
TRACE("Using slow vertex array code\n");
/* Variable Initialization */
if (idxSize != 0) {
/* Immediate mode drawing can't make use of indices in a vbo - get the data from the index buffer.
* If the index buffer has no vbo(not supported or other reason), or with user pointer drawing
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -