📄 vertexshader.c
字号:
static void vshader_set_input(
IWineD3DVertexShaderImpl* This,
unsigned int regnum,
BYTE usage, BYTE usage_idx) {
/* Fake usage: set reserved bit, usage, usage_idx */
DWORD usage_token = (0x1 << 31) |
(usage << WINED3DSP_DCL_USAGE_SHIFT) | (usage_idx << WINED3DSP_DCL_USAGEINDEX_SHIFT);
/* Fake register; set reserved bit, regnum, type: input, wmask: all */
DWORD reg_token = (0x1 << 31) |
WINED3DSP_WRITEMASK_ALL | (WINED3DSPR_INPUT << WINED3DSP_REGTYPE_SHIFT) | regnum;
This->semantics_in[regnum].usage = usage_token;
This->semantics_in[regnum].reg = reg_token;
}
static BOOL match_usage(BYTE usage1, BYTE usage_idx1, BYTE usage2, BYTE usage_idx2) {
if (usage_idx1 != usage_idx2) return FALSE;
if (usage1 == usage2) return TRUE;
if (usage1 == WINED3DDECLUSAGE_POSITION && usage2 == WINED3DDECLUSAGE_POSITIONT) return TRUE;
if (usage2 == WINED3DDECLUSAGE_POSITION && usage1 == WINED3DDECLUSAGE_POSITIONT) return TRUE;
return FALSE;
}
BOOL vshader_get_input(
IWineD3DVertexShader* iface,
BYTE usage_req, BYTE usage_idx_req,
unsigned int* regnum) {
IWineD3DVertexShaderImpl* This = (IWineD3DVertexShaderImpl*) iface;
int i;
for (i = 0; i < MAX_ATTRIBS; i++) {
DWORD usage_token = This->semantics_in[i].usage;
DWORD usage = (usage_token & WINED3DSP_DCL_USAGE_MASK) >> WINED3DSP_DCL_USAGE_SHIFT;
DWORD usage_idx = (usage_token & WINED3DSP_DCL_USAGEINDEX_MASK) >> WINED3DSP_DCL_USAGEINDEX_SHIFT;
if (usage_token && match_usage(usage, usage_idx, usage_req, usage_idx_req)) {
*regnum = i;
return TRUE;
}
}
return FALSE;
}
BOOL vshader_input_is_color(
IWineD3DVertexShader* iface,
unsigned int regnum) {
IWineD3DVertexShaderImpl* This = (IWineD3DVertexShaderImpl*) iface;
IWineD3DDeviceImpl* deviceImpl = (IWineD3DDeviceImpl*) This->baseShader.device;
IWineD3DVertexDeclarationImpl *vertexDeclaration = (IWineD3DVertexDeclarationImpl *)deviceImpl->stateBlock->vertexDecl;
DWORD usage_token = This->semantics_in[regnum].usage;
DWORD usage = (usage_token & WINED3DSP_DCL_USAGE_MASK) >> WINED3DSP_DCL_USAGE_SHIFT;
DWORD usage_idx = (usage_token & WINED3DSP_DCL_USAGEINDEX_MASK) >> WINED3DSP_DCL_USAGEINDEX_SHIFT;
if (vertexDeclaration) {
int i;
/* Find the declaration element that matches our register, then check
* if it has D3DCOLOR as it's type. This works for both d3d8 and d3d9. */
for (i = 0; i < vertexDeclaration->declarationWNumElements-1; ++i) {
WINED3DVERTEXELEMENT *element = vertexDeclaration->pDeclarationWine + i;
if (match_usage(element->Usage, element->UsageIndex, usage, usage_idx)) {
return element->Type == WINED3DDECLTYPE_D3DCOLOR;
}
}
}
ERR("Either no vertexdeclaration present, or register not matched. This should never happen.\n");
return FALSE;
}
/** Generate a vertex shader string using either GL_VERTEX_PROGRAM_ARB
or GLSL and send it to the card */
static VOID IWineD3DVertexShaderImpl_GenerateShader(
IWineD3DVertexShader *iface,
shader_reg_maps* reg_maps,
CONST DWORD *pFunction) {
IWineD3DVertexShaderImpl *This = (IWineD3DVertexShaderImpl *)iface;
SHADER_BUFFER buffer;
#if 0 /* FIXME: Use the buffer that is held by the device, this is ok since fixups will be skipped for software shaders
it also requires entering a critical section but cuts down the runtime footprint of wined3d and any memory fragmentation that may occur... */
if (This->device->fixupVertexBufferSize < SHADER_PGMSIZE) {
HeapFree(GetProcessHeap(), 0, This->fixupVertexBuffer);
This->fixupVertexBuffer = HeapAlloc(GetProcessHeap() , 0, SHADER_PGMSIZE);
This->fixupVertexBufferSize = PGMSIZE;
This->fixupVertexBuffer[0] = 0;
}
buffer.buffer = This->device->fixupVertexBuffer;
#else
buffer.buffer = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, SHADER_PGMSIZE);
#endif
buffer.bsize = 0;
buffer.lineNo = 0;
buffer.newline = TRUE;
if (This->baseShader.shader_mode == SHADER_GLSL) {
/* Create the hw GLSL shader program and assign it as the baseShader.prgId */
GLhandleARB shader_obj = GL_EXTCALL(glCreateShaderObjectARB(GL_VERTEX_SHADER_ARB));
/* Base Declarations */
shader_generate_glsl_declarations( (IWineD3DBaseShader*) This, reg_maps, &buffer, &GLINFO_LOCATION);
/* Base Shader Body */
shader_generate_main( (IWineD3DBaseShader*) This, &buffer, reg_maps, pFunction);
/* Unpack 3.0 outputs */
if (This->baseShader.hex_version >= WINED3DVS_VERSION(3,0))
vshader_glsl_output_unpack(&buffer, This->semantics_out);
/* If this shader doesn't use fog copy the z coord to the fog coord so that we can use table fog */
if (!reg_maps->fog)
shader_addline(&buffer, "gl_FogFragCoord = gl_Position.z;\n");
/* Write the final position.
*
* OpenGL coordinates specify the center of the pixel while d3d coords specify
* the corner. The offsets are stored in z and w in the 2nd row of the projection
* matrix to avoid wasting a free shader constant. Add them to the w and z coord
* of the 2nd row
*/
shader_addline(&buffer, "gl_Position.x = gl_Position.x + posFixup[2];\n");
shader_addline(&buffer, "gl_Position.y = gl_Position.y + posFixup[3];\n");
/* Account for any inverted textures (render to texture case) by reversing the y coordinate
* (this is handled in drawPrim() when it sets the MODELVIEW and PROJECTION matrices)
*/
shader_addline(&buffer, "gl_Position.y = gl_Position.y * posFixup[1];\n");
shader_addline(&buffer, "}\n");
TRACE("Compiling shader object %u\n", shader_obj);
GL_EXTCALL(glShaderSourceARB(shader_obj, 1, (const char**)&buffer.buffer, NULL));
GL_EXTCALL(glCompileShaderARB(shader_obj));
print_glsl_info_log(&GLINFO_LOCATION, shader_obj);
/* Store the shader object */
This->baseShader.prgId = shader_obj;
} else if (This->baseShader.shader_mode == SHADER_ARB) {
/* Create the hw ARB shader */
shader_addline(&buffer, "!!ARBvp1.0\n");
/* Mesa supports only 95 constants */
if (GL_VEND(MESA) || GL_VEND(WINE))
This->baseShader.limits.constant_float =
min(95, This->baseShader.limits.constant_float);
/* Base Declarations */
shader_generate_arb_declarations( (IWineD3DBaseShader*) This, reg_maps, &buffer, &GLINFO_LOCATION);
/* We need a constant to fixup the final position */
shader_addline(&buffer, "PARAM posFixup = program.env[%d];\n", ARB_SHADER_PRIVCONST_POS);
/* Base Shader Body */
shader_generate_main( (IWineD3DBaseShader*) This, &buffer, reg_maps, pFunction);
/* If this shader doesn't use fog copy the z coord to the fog coord so that we can use table fog */
if (!reg_maps->fog)
shader_addline(&buffer, "MOV result.fogcoord, TMP_OUT.z;\n");
/* Write the final position.
*
* OpenGL coordinates specify the center of the pixel while d3d coords specify
* the corner. The offsets are stored in the 2nd row of the projection matrix,
* the x offset in z and the y offset in w. Add them to the resulting position
*/
shader_addline(&buffer, "ADD TMP_OUT.x, TMP_OUT.x, posFixup.z;\n");
shader_addline(&buffer, "ADD TMP_OUT.y, TMP_OUT.y, posFixup.w;\n");
/* Account for any inverted textures (render to texture case) by reversing the y coordinate
* (this is handled in drawPrim() when it sets the MODELVIEW and PROJECTION matrices)
*/
shader_addline(&buffer, "MUL TMP_OUT.y, TMP_OUT.y, posFixup.y;\n");
shader_addline(&buffer, "MOV result.position, TMP_OUT;\n");
shader_addline(&buffer, "END\n");
/* TODO: change to resource.glObjectHandle or something like that */
GL_EXTCALL(glGenProgramsARB(1, &This->baseShader.prgId));
TRACE("Creating a hw vertex shader, prg=%d\n", This->baseShader.prgId);
GL_EXTCALL(glBindProgramARB(GL_VERTEX_PROGRAM_ARB, This->baseShader.prgId));
TRACE("Created hw vertex shader, prg=%d\n", This->baseShader.prgId);
/* Create the program and check for errors */
GL_EXTCALL(glProgramStringARB(GL_VERTEX_PROGRAM_ARB, GL_PROGRAM_FORMAT_ASCII_ARB,
buffer.bsize, buffer.buffer));
if (glGetError() == GL_INVALID_OPERATION) {
GLint errPos;
glGetIntegerv(GL_PROGRAM_ERROR_POSITION_ARB, &errPos);
FIXME("HW VertexShader Error at position %d: %s\n",
errPos, debugstr_a((const char *)glGetString(GL_PROGRAM_ERROR_STRING_ARB)));
This->baseShader.prgId = -1;
}
}
#if 1 /* if were using the data buffer of device then we don't need to free it */
HeapFree(GetProcessHeap(), 0, buffer.buffer);
#endif
}
/* *******************************************
IWineD3DVertexShader IUnknown parts follow
******************************************* */
static HRESULT WINAPI IWineD3DVertexShaderImpl_QueryInterface(IWineD3DVertexShader *iface, REFIID riid, LPVOID *ppobj)
{
IWineD3DVertexShaderImpl *This = (IWineD3DVertexShaderImpl *)iface;
TRACE("(%p)->(%s,%p)\n",This,debugstr_guid(riid),ppobj);
if (IsEqualGUID(riid, &IID_IUnknown)
|| IsEqualGUID(riid, &IID_IWineD3DBase)
|| IsEqualGUID(riid, &IID_IWineD3DBaseShader)
|| IsEqualGUID(riid, &IID_IWineD3DVertexShader)) {
IUnknown_AddRef(iface);
*ppobj = This;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -