WineD3D patches for review and discussion - not to be applied as-is.
Jason Green
jave27 at gmail.com
Fri May 26 01:17:41 CDT 2006
All of these apply to the latest Git tree, and should come after my
last patch submission to wine-patches, but it shouldn't matter. I'm
just looking for a little more feedback on these before I submit.
This should lay the groundwork to begin implementing GLSL opcode
generation. I've hacked around with some of them, and this will
succesfully generate a GLSL shader program if the opcodes are
implemented properly.
Please let me know if any of my ideas here are fundamentally flawed.
We've worked a bunch of it out on IRC, but this should be a nicer
version to look at than my stuff at pastebin. :-)
None of this code changes anything for the end-result
ARB_vertex/fragment_program. It only generates GLSL if you have this
regkey:
HKLU\Software\Wine\Direct3D\UseGLSL = "enabled"
-------------- next part --------------
>From nobody Mon Sep 17 00:00:00 2001
From: Jason Green <jave27 at gmail.com>
Date: Fri, 26 May 2006 01:04:37 -0400
To: wine-patches <wine-patches at winehq.org>
Subject: [PATCH 1/5] Add ability to generate GLSL shader objects for vertex and pixel shaders.
- Also modifies the baseshader declarations, and a few minor trace/formatting cleanups.
---
dlls/wined3d/baseshader.c | 26 ++++++++++++++++++++++----
dlls/wined3d/pixelshader.c | 25 +++++++++++++++++++++++--
dlls/wined3d/vertexshader.c | 31 +++++++++++++++++++++++++++++--
3 files changed, 74 insertions(+), 8 deletions(-)
77c5f0e5fc62b66943b762730d927ee2553ef842
diff --git a/dlls/wined3d/baseshader.c b/dlls/wined3d/baseshader.c
index 4e30421..cba12f5 100644
--- a/dlls/wined3d/baseshader.c
+++ b/dlls/wined3d/baseshader.c
@@ -549,8 +549,28 @@ void generate_glsl_declarations(
shader_reg_maps* reg_maps,
SHADER_BUFFER* buffer) {
+ IWineD3DBaseShaderImpl* This = (IWineD3DBaseShaderImpl*) iface;
+ int i;
+
FIXME("GLSL not fully implemented yet.\n");
+ /* Declare the constants (aka uniforms) */
+ shader_addline(buffer, "uniform vec4 C[%u];\n", This->baseShader.limits.constant_float);
+
+ /* Declare address variables */
+ for (i = 0; i < This->baseShader.limits.address; i++) {
+ if (reg_maps->address & (1 << i))
+ shader_addline(buffer, "ivec4 A%ld;\n", i);
+ }
+
+ /* Declare temporary variables */
+ for(i = 0; i < This->baseShader.limits.temporary; i++) {
+ if (reg_maps->temporary & (1 << i))
+ shader_addline(buffer, "vec4 R%lu;\n", i);
+ }
+
+ /* Start the main program */
+ shader_addline(buffer, "void main() {\n");
}
/** Shared code in order to generate the bulk of the shader string.
@@ -585,7 +605,6 @@ void generate_base_shader(
/* Pre-declare registers */
if (wined3d_settings.shader_mode == SHADER_GLSL) {
generate_glsl_declarations(iface, ®_maps, buffer);
- shader_addline(buffer, "void main() {\n");
} else {
generate_arb_declarations(iface, ®_maps, buffer);
}
@@ -680,8 +699,7 @@ void generate_base_shader(
/** Prints the GLSL info log which will contain error messages if they exist */
void print_glsl_info_log(
WineD3D_GL_Info *gl_info,
- GLhandleARB obj)
-{
+ GLhandleARB obj) {
int infologLength = 0;
char *infoLog;
@@ -693,7 +711,7 @@ void print_glsl_info_log(
{
infoLog = (char *)HeapAlloc(GetProcessHeap(), 0, infologLength);
GL_EXTCALL(glGetInfoLogARB(obj, infologLength, NULL, infoLog));
- FIXME("Error received from GLSL shader #%u: %s", obj, debugstr_a(infoLog));
+ FIXME("Error received from GLSL shader #%u: %s\n", obj, debugstr_a(infoLog));
HeapFree(GetProcessHeap(), 0, infoLog);
}
}
diff --git a/dlls/wined3d/pixelshader.c b/dlls/wined3d/pixelshader.c
index be4fbb8..5720ea0 100644
--- a/dlls/wined3d/pixelshader.c
+++ b/dlls/wined3d/pixelshader.c
@@ -1298,8 +1298,29 @@ #endif
buffer.bsize = 0;
buffer.lineNo = 0;
- /* TODO: Optionally, generate the GLSL shader instead */
- if (GL_SUPPORT(ARB_VERTEX_PROGRAM)) {
+ if (wined3d_settings.shader_mode == SHADER_GLSL) {
+
+ /* Create the hw GLSL shader object and assign it as the baseShader.prgId */
+ GLhandleARB shader_obj = GL_EXTCALL(glCreateShaderObjectARB(GL_FRAGMENT_SHADER_ARB));
+ int success_flag = 0;
+
+ /* Generate the bulk of the shader code */
+ generate_base_shader( (IWineD3DBaseShader*) This, &buffer, pFunction);
+
+ shader_addline(&buffer, "}\n\0");
+
+ TRACE("Compiling shader object %u\n", shader_obj);
+ GL_EXTCALL(glShaderSourceARB(shader_obj, 1, (const char**)&buffer.buffer, NULL));
+ GL_EXTCALL(glCompileShaderARB(shader_obj));
+ GL_EXTCALL(glGetObjectParameterivARB(shader_obj,
+ GL_OBJECT_COMPILE_STATUS_ARB, &success_flag));
+ if (success_flag == FALSE) /* Print any compile errors in our shader */
+ print_glsl_info_log(&GLINFO_LOCATION, shader_obj);
+
+ /* Store the shader object */
+ This->baseShader.prgId = shader_obj;
+
+ } else if (wined3d_settings.shader_mode == SHADER_ARB) {
/* Create the hw ARB shader */
shader_addline(&buffer, "!!ARBfp1.0\n");
diff --git a/dlls/wined3d/vertexshader.c b/dlls/wined3d/vertexshader.c
index cb8d973..03f0ce0 100644
--- a/dlls/wined3d/vertexshader.c
+++ b/dlls/wined3d/vertexshader.c
@@ -1063,8 +1063,35 @@ #endif
buffer.bsize = 0;
buffer.lineNo = 0;
- /* TODO: Optionally, generate the GLSL shader instead */
- if (GL_SUPPORT(ARB_VERTEX_PROGRAM)) {
+ if (wined3d_settings.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));
+ int i;
+ int success_flag = 0;
+
+ /* Declare all named attributes (TODO: Add this to the reg_maps and only declare those that are needed)*/
+ for (i = 0; i < 16; ++i)
+ shader_addline(&buffer, "attribute vec4 attrib%i;\n", i);
+
+ /* Generate the bulk of the shader code */
+ generate_base_shader( (IWineD3DBaseShader*) This, &buffer, pFunction);
+
+ shader_addline(&buffer, "}\n\0");
+
+ TRACE("Compiling shader object %u\n", shader_obj);
+ GL_EXTCALL(glShaderSourceARB(shader_obj, 1, (const char**)&buffer.buffer, NULL));
+ GL_EXTCALL(glCompileShaderARB(shader_obj));
+ GL_EXTCALL(glGetObjectParameterivARB(shader_obj,
+ GL_OBJECT_COMPILE_STATUS_ARB, &success_flag));
+ if (success_flag == FALSE) /* Print any compile errors in our shader */
+ print_glsl_info_log(&GLINFO_LOCATION, shader_obj);
+
+ /* Store the shader object */
+ This->baseShader.prgId = shader_obj;
+
+ } else if (wined3d_settings.shader_mode == SHADER_ARB) {
+
/* Create the hw ARB shader */
shader_addline(&buffer, "!!ARBvp1.0\n");
--
1.3.3
-------------- next part --------------
>From nobody Mon Sep 17 00:00:00 2001
From: Jason Green <jave27 at gmail.com>
Date: Fri, 26 May 2006 01:46:29 -0400
To: wine-patches <wine-patches at winehq.org>
Subject: [PATCH 5/5] Add ability to store the GLSL Shader Program Object on the stateblock
- When the app calls SetPixelShader or SetVertexShader, those functions will now either:
- Create a new Program object and attach themselves to it,
- or attach themselves to the existing object
- Then, they will link into that object.
- They will Detach old objects if necessary.
---
dlls/wined3d/device.c | 82 ++++++++++++++++++++++++++++++++++++++++
dlls/wined3d/stateblock.c | 14 +++++++
dlls/wined3d/wined3d_private.h | 3 +
3 files changed, 99 insertions(+), 0 deletions(-)
c7bdccd97e7bd53a5b49bbce454c7628016b820b
diff --git a/dlls/wined3d/device.c b/dlls/wined3d/device.c
index eff9504..ff2b8c9 100644
--- a/dlls/wined3d/device.c
+++ b/dlls/wined3d/device.c
@@ -27,9 +27,11 @@ #include "config.h"
#ifdef HAVE_FLOAT_H
# include <float.h>
#endif
+#include <stdio.h>
#include "wined3d_private.h"
WINE_DEFAULT_DEBUG_CHANNEL(d3d);
+WINE_DECLARE_DEBUG_CHANNEL(d3d_shader);
#define GLINFO_LOCATION ((IWineD3DImpl *)(This->wineD3D))->gl_info
/* x11drv GDI escapes */
@@ -4341,6 +4343,51 @@ HRESULT WINAPI IWineD3DDeviceImpl_SetVer
IWineD3DVertexShader_Release(oldShader);
}
+ /* If we're using GLSL, we need to possibly create a Shader Program at this point,
+ * unless one is already set, then we need to attach the vertex shader object to it */
+ if (NULL != pShader && wined3d_settings.shader_mode == SHADER_GLSL
+ && oldShader != pShader) {
+
+ GLhandleARB programId = This->updateStateBlock->shaderPrgId;
+ GLhandleARB shaderObj = ((IWineD3DVertexShaderImpl*)pShader)->baseShader.prgId;
+ int success_flag = 0;
+
+ if (programId == 0) {
+ /* No shader program is set, create a new program */
+ programId = GL_EXTCALL(glCreateProgramObjectARB());
+ TRACE_(d3d_shader)("Creating new shader program %u\n", programId);
+
+ /* Store this programId on the stateblock */
+ This->updateStateBlock->shaderPrgId = programId;
+ } else if (oldShader != NULL) {
+ /* Detach the old shader object */
+ TRACE_(d3d_shader)("Detaching shader object %u from program %u\n",
+ ((IWineD3DVertexShaderImpl*)oldShader)->baseShader.prgId, programId);
+ GL_EXTCALL(glDetachObjectARB(programId, shaderObj));
+ checkGLcall("glDetachObjectARB");
+ }
+
+ TRACE_(d3d_shader)("Attaching shader object %u to program %u\n", shaderObj, programId);
+ GL_EXTCALL(glAttachObjectARB(programId, shaderObj));
+ checkGLcall("glAttachObjectARB");
+ GL_EXTCALL(glLinkProgramARB(programId));
+ GL_EXTCALL(glGetObjectParameterivARB(programId,
+ GL_OBJECT_LINK_STATUS_ARB, &success_flag));
+ if (!success_flag) {
+ /* Print any linking errors in our shader */
+ print_glsl_info_log(&GLINFO_LOCATION, programId);
+ } else {
+ /* Bind vertex attributes to a corresponding index number */
+ int i;
+ char tmp_name[10];
+ for (i = 0; i < 16; ++i) {
+ sprintf(tmp_name, "attrib%i", i);
+ glBindAttribLocationARB(programId, i, tmp_name);
+ }
+ checkGLcall("glBindAttribLocationARB");
+ }
+ }
+
if (pShader != NULL && ((IWineD3DVertexShaderImpl *)pShader)->vertexDeclaration != NULL) {
TRACE("(%p) : setting vertexDeclaration(%p)\n", This, ((IWineD3DVertexShaderImpl *)pShader)->vertexDeclaration);
IWineD3DDevice_SetVertexDeclaration(iface, ((IWineD3DVertexShaderImpl *)pShader)->vertexDeclaration);
@@ -4522,6 +4569,41 @@ HRESULT WINAPI IWineD3DDeviceImpl_SetPix
IWineD3DPixelShader_Release(oldShader);
}
+ /* If we're using GLSL, we need to possibly create a Shader Program at this point,
+ * unless one is already set, then we need to attach the pixel shader object to it */
+ if (NULL != pShader && wined3d_settings.shader_mode == SHADER_GLSL) {
+
+ GLhandleARB programId = This->updateStateBlock->shaderPrgId;
+ GLhandleARB shaderObj = ((IWineD3DPixelShaderImpl*)pShader)->baseShader.prgId;
+ int success_flag = 0;
+
+ if (programId == 0) {
+ /* No shader program is set, create a new program */
+ programId = GL_EXTCALL(glCreateProgramObjectARB());
+ TRACE_(d3d_shader)("Creating new shader program %u\n", programId);
+
+ /* Store this programId on the stateblock */
+ This->updateStateBlock->shaderPrgId = programId;
+ } else if (oldShader != NULL) {
+ /* Detach the old shader object */
+ TRACE_(d3d_shader)("Detaching shader object %u from program %u\n",
+ ((IWineD3DPixelShaderImpl*)oldShader)->baseShader.prgId, programId);
+ GL_EXTCALL(glDetachObjectARB(programId, shaderObj));
+ checkGLcall("glDetachObjectARB");
+ }
+
+ TRACE_(d3d_shader)("Attaching shader object %u to program %u\n", shaderObj, programId);
+ GL_EXTCALL(glAttachObjectARB(programId, shaderObj));
+ checkGLcall("glAttachObjectARB");
+ GL_EXTCALL(glLinkProgramARB(programId));
+ GL_EXTCALL(glGetObjectParameterivARB(programId,
+ GL_OBJECT_LINK_STATUS_ARB, &success_flag));
+ if (!success_flag) {
+ /* Print any linking errors in our shader */
+ print_glsl_info_log(&GLINFO_LOCATION, programId);
+ }
+ }
+
TRACE("(%p) : setting pShader(%p)\n", This, pShader);
/**
* TODO: merge HAL shaders context switching from prototype
diff --git a/dlls/wined3d/stateblock.c b/dlls/wined3d/stateblock.c
index af1a265..79e5a61 100644
--- a/dlls/wined3d/stateblock.c
+++ b/dlls/wined3d/stateblock.c
@@ -24,6 +24,7 @@ #include "config.h"
#include "wined3d_private.h"
WINE_DEFAULT_DEBUG_CHANNEL(d3d);
+WINE_DECLARE_DEBUG_CHANNEL(d3d_shader);
#define GLINFO_LOCATION ((IWineD3DImpl *)(((IWineD3DDeviceImpl *)This->wineD3DDevice)->wineD3D))->gl_info
/**********************************************************
@@ -85,6 +86,14 @@ ULONG WINAPI IWineD3DStateBlockImpl_Rele
IWineD3DVertexShader_Release(This->vertexShader);
}
+ if ((NULL != This->pixelShader || NULL != This->vertexShader) && This->shaderPrgId != 0) {
+ ENTER_GL();
+ TRACE_(d3d_shader)("Deleting GLSL shader program %u\n", This->shaderPrgId);
+ GL_EXTCALL(glDeleteObjectARB(This->shaderPrgId));
+ checkGLcall("glDeleteObjectARB");
+ LEAVE_GL();
+ }
+
if (NULL != This->vertexDecl) {
IWineD3DVertexDeclaration_Release(This->vertexDecl);
}
@@ -164,6 +173,7 @@ HRESULT WINAPI IWineD3DStateBlockImpl_Ca
}
This->vertexShader = targetStateBlock->vertexShader;
+ This->shaderPrgId = targetStateBlock->shaderPrgId;
}
/* Vertex Shader Constants */
@@ -228,6 +238,7 @@ HRESULT WINAPI IWineD3DStateBlockImpl_Ca
}
This->pixelShader = targetStateBlock->pixelShader;
+ This->shaderPrgId = targetStateBlock->shaderPrgId;
}
/* Pixel Shader Constants */
@@ -853,6 +864,9 @@ #endif
}
This->wineD3DDevice->currentPalette = 0;
+ /* Set default GLSL program ID to 0 */
+ This->shaderPrgId = 0;
+
TRACE("-----------------------> Device defaults now set up...\n");
return WINED3D_OK;
}
diff --git a/dlls/wined3d/wined3d_private.h b/dlls/wined3d/wined3d_private.h
index 3e3bf80..47b9583 100644
--- a/dlls/wined3d/wined3d_private.h
+++ b/dlls/wined3d/wined3d_private.h
@@ -1071,6 +1071,9 @@ struct IWineD3DStateBlockImpl
DWORD textureState[MAX_TEXTURES][WINED3D_HIGHEST_TEXTURE_STATE + 1];
/* Sampler States */
DWORD samplerState[MAX_SAMPLERS][WINED3D_HIGHEST_SAMPLER_STATE + 1];
+
+ /* GLSL Shader program ID */
+ GLhandleARB shaderPrgId;
};
--
1.3.3
-------------- next part --------------
>From nobody Mon Sep 17 00:00:00 2001
From: Jason Green <jave27 at gmail.com>
Date: Fri, 26 May 2006 01:22:53 -0400
To: wine-patches <wine-patches at winehq.org>
Subject: [PATCH 3/5] Add ability to draw primitives with GLSL shaders.
- If wined3d_settings.shader_mode == SHADER_GLSL, then Wine will now attempt to generate a GLSL shader program.
- Breaks out constant/uniform loading into a separate function
- Fixed up a little bit of whitespace for readability.
---
dlls/wined3d/drawprim.c | 249 +++++++++++++++++++++++++++--------------------
1 files changed, 145 insertions(+), 104 deletions(-)
ae930222ec5ac9d6a02ef866779859de49284c79
diff --git a/dlls/wined3d/drawprim.c b/dlls/wined3d/drawprim.c
index 9f5994a..27f0e51 100644
--- a/dlls/wined3d/drawprim.c
+++ b/dlls/wined3d/drawprim.c
@@ -28,9 +28,7 @@ WINE_DEFAULT_DEBUG_CHANNEL(d3d_draw);
WINE_DECLARE_DEBUG_CHANNEL(d3d_shader);
#define GLINFO_LOCATION ((IWineD3DImpl *)(This->wineD3D))->gl_info
-#ifdef SHOW_FRAME_MAKEUP
#include <stdio.h>
-#endif
#if 0 /* TODO */
extern IWineD3DVertexShaderImpl* VertexShaders[64];
@@ -1694,10 +1692,67 @@ void drawStridedSoftwareVS(IWineD3DDevic
#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) {
+/* Load the given constants into either GLSL or ARB shader programs.
+ * TODO: Add support for ints & bools, too. */
+void loadConstants(IWineD3DDevice *iface,
+ GLenum target_type,
+ float* constants,
+ WINESHADERCNST* constant_types,
+ unsigned max_constants,
+ GLhandleARB programId,
+ BOOL skip_type_compare) {
+
IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
+ int i;
+ char tmp_name[7];
+ GLuint tmp_loc;
+
+ if (wined3d_settings.shader_mode == SHADER_GLSL) {
+ /* TODO: Benchmark and see if it would be beneficial to store the
+ * locations of the constants to avoid looking up each time */
+ for (i=0; i<max_constants; ++i) {
+ if (skip_type_compare || WINESHADERCNST_FLOAT == constant_types[i]) {
+ TRACE_(d3d_shader)("Loading constants %i: %f, %f, %f, %f\n",
+ i, constants[i*4], constants[i*4+1], constants[i*4+2], constants[i*4+3]);
+
+ sprintf(tmp_name, "C[%i]", i);
+ tmp_loc = GL_EXTCALL(glGetUniformLocationARB(programId, tmp_name));
+ GL_EXTCALL(glUniform4fvARB(tmp_loc, 1, &constants[i*4]));
+ checkGLcall("glUniform4fv");
+ }
+ }
+ } else if (wined3d_settings.shader_mode == SHADER_ARB) {
+ for (i=0; i<max_constants; ++i) {
+ if (skip_type_compare || WINESHADERCNST_FLOAT == constant_types[i]) {
+ TRACE_(d3d_shader)("Loading constants %i: %f, %f, %f, %f\n",
+ i, constants[i*4], constants[i*4+1], constants[i*4+2], constants[i*4+3]);
+
+ GL_EXTCALL(glProgramEnvParameter4fvARB(target_type, i, &constants[i*4]));
+ checkGLcall("glProgramEnvParameter4fvARB");
+ }
+ }
+ } else {
+ /* We should never get here */
+ ERR("Cannot load constants\n");
+ }
+}
+
+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) {
+ IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
+ GLhandleARB programId = This->stateBlock->shaderPrgId;
+
/* Now draw the graphics to the screen */
if (FALSE /* disable software vs for now */ && useVertexShaderFunction && !useHW) {
FIXME("drawing using software vertex shaders (line %d)\n", __LINE__);
@@ -1768,131 +1823,110 @@ #if 0/* TODO: Vertex fixups (diffuse and
fixupVertices(This, dataLocations, &transformedDataLocations, 1 + endStride - startStride, startStride);
#endif
- /* vertex shaders */
-
- /* 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.diffuse.lpData == NULL && dataLocations->u.s.specular.lpData == NULL)
- || (useVertexShaderFunction && ((IWineD3DVertexShaderImpl *)This->stateBlock->vertexShader)->namedArrays && !((IWineD3DVertexShaderImpl *)This->stateBlock->vertexShader)->declaredArrays)) {
-
- /* Load the vertex data using named arrays */
- TRACE("(%p) Loading vertex data\n", This);
- loadVertexData(iface, dataLocations);
+ /* vertex shaders */
+ if ((!useVertexShaderFunction && dataLocations->u.s.pSize.lpData == NULL
+ && dataLocations->u.s.diffuse.lpData == NULL
+ && dataLocations->u.s.specular.lpData == NULL)
+ || (useVertexShaderFunction && ((IWineD3DVertexShaderImpl *)This->stateBlock->vertexShader)->namedArrays
+ && !((IWineD3DVertexShaderImpl *)This->stateBlock->vertexShader)->declaredArrays)) {
+ /* The only vertex data used by the shader is supported by OpenGL */
+
+ /* Load the vertex data using named arrays */
+ TRACE("(%p) Loading vertex data\n", This);
+ loadVertexData(iface, dataLocations);
+
+ } else if(useVertexShaderFunction && ((IWineD3DVertexShaderImpl *)This->stateBlock->vertexShader)->declaredArrays) {
+ /* load the array data using ordinal mapping */
+ loadNumberedArrays(iface, dataLocations, ((IWineD3DVertexShaderImpl *)This->stateBlock->vertexShader)->arrayUsageMap);
- } else /* Otherwise */
- if(useVertexShaderFunction && ((IWineD3DVertexShaderImpl *)This->stateBlock->vertexShader)->declaredArrays) {
-
- /* load the array data using ordinal mapping */
- loadNumberedArrays(iface, dataLocations, ((IWineD3DVertexShaderImpl *)This->stateBlock->vertexShader)->arrayUsageMap);
-
- } else { /* If this happens we must drawStridedSlow later on */
- TRACE("Not loading vertex data\n");
- }
+ } else {
+ /* If this happens we must drawStridedSlow later on */
+ TRACE("Not loading vertex data\n");
+ }
- TRACE("Loaded arrays\n");
+ TRACE("Loaded arrays\n");
- if (useVertexShaderFunction) {
- IWineD3DVertexDeclarationImpl *vertexDeclaration;
- int i;
+ /* We need to use a single shader program if we are using GLSL and either pixel or vertex shaders */
+ if (wined3d_settings.shader_mode == SHADER_GLSL &&
+ (useVertexShaderFunction || usePixelShaderFunction)) {
+ GL_EXTCALL(glUseProgramObjectARB(programId));
+ checkGLcall("glUseProgramObjectARB");
+ }
+
+ if (useVertexShaderFunction) {
+ IWineD3DVertexDeclarationImpl *vertexDeclaration;
- TRACE("Using vertex shader\n");
+ TRACE("Using vertex shader\n");
+ if (wined3d_settings.shader_mode == SHADER_ARB) {
/* Bind the vertex program */
GL_EXTCALL(glBindProgramARB(GL_VERTEX_PROGRAM_ARB,
- ((IWineD3DVertexShaderImpl *)This->stateBlock->vertexShader)->baseShader.prgId));
+ ((IWineD3DVertexShaderImpl *)This->stateBlock->vertexShader)->baseShader.prgId));
checkGLcall("glBindProgramARB(GL_VERTEX_PROGRAM_ARB, vertexShader->prgId);");
/* Enable OpenGL vertex programs */
glEnable(GL_VERTEX_PROGRAM_ARB);
checkGLcall("glEnable(GL_VERTEX_PROGRAM_ARB);");
TRACE_(d3d_shader)("(%p) : Bound vertex program %u and enabled GL_VERTEX_PROGRAM_ARB\n",
- This, ((IWineD3DVertexShaderImpl *)This->stateBlock->vertexShader)->baseShader.prgId);
-
- /* Vertex Shader 8 constants */
- vertexDeclaration = (IWineD3DVertexDeclarationImpl *)
+ This, ((IWineD3DVertexShaderImpl *)This->stateBlock->vertexShader)->baseShader.prgId);
+ }
+
+ /* Vertex Shader 8 constants */
+ vertexDeclaration = (IWineD3DVertexDeclarationImpl *)
((IWineD3DVertexShaderImpl *)This->stateBlock->vertexShader)->vertexDeclaration;
- if (vertexDeclaration != NULL) {
- float *constants = vertexDeclaration->constants;
- if (constants != NULL) {
- for (i = 0; i <= WINED3D_VSHADER_MAX_CONSTANTS; ++i) {
- TRACE_(d3d_shader)("Not loading constants %u = %f %f %f %f\n", i,
- constants[i * 4], constants[i * 4 + 1], constants[i * 4 + 2], constants[i * 4 + 3]);
- GL_EXTCALL(glProgramEnvParameter4fvARB(GL_VERTEX_PROGRAM_ARB, i, &constants[i * 4]));
- }
- }
- }
+ if (vertexDeclaration != NULL && vertexDeclaration->constants != NULL) {
+ float *constants = vertexDeclaration->constants;
+ loadConstants(iface, GL_VERTEX_PROGRAM_ARB, constants, NULL, WINED3D_VSHADER_MAX_CONSTANTS, programId, TRUE);
+ }
- /* Update the constants */
- for (i = 0; i < WINED3D_VSHADER_MAX_CONSTANTS; ++i) {
- /* TODO: add support for Integer and Boolean constants */
- if (WINESHADERCNST_FLOAT == This->stateBlock->vertexShaderConstantT[i]) {
+ /* Update the constants */
+ loadConstants(iface, GL_VERTEX_PROGRAM_ARB, This->stateBlock->vertexShaderConstantF,
+ This->stateBlock->vertexShaderConstantT, WINED3D_VSHADER_MAX_CONSTANTS, programId, FALSE);
+ }
- GL_EXTCALL(glProgramEnvParameter4fvARB(GL_VERTEX_PROGRAM_ARB, i,
- &This->stateBlock->vertexShaderConstantF[i * 4]));
+ if (usePixelShaderFunction) {
- TRACE_(d3d_shader)("Loading constants %u = %f %f %f %f\n", i,
- This->stateBlock->vertexShaderConstantF[i * 4],
- This->stateBlock->vertexShaderConstantF[i * 4 + 1],
- This->stateBlock->vertexShaderConstantF[i * 4 + 2],
- This->stateBlock->vertexShaderConstantF[i * 4 + 3]);
- checkGLcall("glProgramEnvParameter4fvARB(GL_VERTEX_PROGRAM_ARB");
- }
- }
- }
+ TRACE("Using pixel shader\n");
- if (usePixelShaderFunction) {
- int i;
-
- TRACE("Using pixel shader\n");
-
- /* Bind the fragment program */
- GL_EXTCALL(glBindProgramARB(GL_FRAGMENT_PROGRAM_ARB,
- ((IWineD3DPixelShaderImpl *)This->stateBlock->pixelShader)->baseShader.prgId));
- checkGLcall("glBindProgramARB(GL_FRAGMENT_PROGRAM_ARB, pixelShader->prgId);");
-
- /* Enable OpenGL fragment programs */
- glEnable(GL_FRAGMENT_PROGRAM_ARB);
- checkGLcall("glEnable(GL_FRAGMENT_PROGRAM_ARB);");
- TRACE_(d3d_shader)("(%p) : Bound fragment program %u and enabled GL_FRAGMENT_PROGRAM_ARB\n",
- This, ((IWineD3DPixelShaderImpl *)This->stateBlock->pixelShader)->baseShader.prgId);
-
- /* Update the constants */
- for (i = 0; i < WINED3D_PSHADER_MAX_CONSTANTS; ++i) {
- /* TODO: add support for Integer and Boolean constants */
- if (WINESHADERCNST_FLOAT == This->stateBlock->pixelShaderConstantT[i]) {
- GL_EXTCALL(glProgramEnvParameter4fvARB(GL_FRAGMENT_PROGRAM_ARB, i,
- &This->stateBlock->pixelShaderConstantF[i * 4]));
- TRACE_(d3d_shader)("Loading constants %u = %f %f %f %f\n", i,
- This->stateBlock->pixelShaderConstantF[i * 4],
- This->stateBlock->pixelShaderConstantF[i * 4 + 1],
- This->stateBlock->pixelShaderConstantF[i * 4 + 2],
- This->stateBlock->pixelShaderConstantF[i * 4 + 3]);
- checkGLcall("glProgramEnvParameter4fvARB(GL_VERTEX_PROGRAM_ARB");
- }
- }
+ if (wined3d_settings.shader_mode == SHADER_ARB) {
+ /* Bind the fragment program */
+ GL_EXTCALL(glBindProgramARB(GL_FRAGMENT_PROGRAM_ARB,
+ ((IWineD3DPixelShaderImpl *)This->stateBlock->pixelShader)->baseShader.prgId));
+ checkGLcall("glBindProgramARB(GL_FRAGMENT_PROGRAM_ARB, pixelShader->prgId);");
+
+ /* Enable OpenGL fragment programs */
+ glEnable(GL_FRAGMENT_PROGRAM_ARB);
+ checkGLcall("glEnable(GL_FRAGMENT_PROGRAM_ARB);");
+ TRACE_(d3d_shader)("(%p) : Bound fragment program %u and enabled GL_FRAGMENT_PROGRAM_ARB\n",
+ This, ((IWineD3DPixelShaderImpl *)This->stateBlock->pixelShader)->baseShader.prgId);
}
- /* 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))) {
- /* TODO: replace drawStridedSlow with veretx fixups */
+ /* Update the constants */
+ loadConstants(iface, GL_FRAGMENT_PROGRAM_ARB, This->stateBlock->pixelShaderConstantF,
+ This->stateBlock->pixelShaderConstantT, WINED3D_PSHADER_MAX_CONSTANTS, programId, FALSE);
+ }
- drawStridedSlow(iface, dataLocations, numberOfIndicies, glPrimType,
- idxData, idxSize, minIndex, StartIdx);
+ /* 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))) {
+ /* TODO: replace drawStridedSlow with vertex fixups */
+
+ drawStridedSlow(iface, dataLocations, numberOfIndicies, glPrimType,
+ idxData, idxSize, minIndex, StartIdx);
} else {
/* OpenGL can manage everything in hardware so we can use drawStridedFast */
drawStridedFast(iface, numberOfIndicies, glPrimType,
- idxData, idxSize, minIndex, StartIdx);
+ idxData, idxSize, minIndex, StartIdx);
}
/* Cleanup vertex program */
- if (useVertexShaderFunction) {
- /* disable any attribs */
+ if (useVertexShaderFunction && wined3d_settings.shader_mode != SHADER_SW) {
+ /* disable any attribs (Since we bind "attribN" to index #N for GLSL, this works in GLSL & ARB */
if(((IWineD3DVertexShaderImpl *)This->stateBlock->vertexShader)->declaredArrays) {
GLint maxAttribs;
int i;
@@ -1900,20 +1934,27 @@ #endif
glGetIntegerv(GL_MAX_VERTEX_ATTRIBS_ARB, &maxAttribs);
/* MESA does not support it right not */
if (glGetError() != GL_NO_ERROR)
- maxAttribs = 16;
+ maxAttribs = 16;
for (i = 0; i < maxAttribs; ++i) {
GL_EXTCALL(glDisableVertexAttribArrayARB(i));
checkGLcall("glDisableVertexAttribArrayARB(reg);");
}
}
- glDisable(GL_VERTEX_PROGRAM_ARB);
+ if (wined3d_settings.shader_mode == SHADER_ARB)
+ glDisable(GL_VERTEX_PROGRAM_ARB);
}
/* Cleanup fragment program */
- if (usePixelShaderFunction) {
+ if (usePixelShaderFunction && wined3d_settings.shader_mode == SHADER_ARB) {
glDisable(GL_FRAGMENT_PROGRAM_ARB);
}
+
+ /* Cleanup GLSL program */
+ if (wined3d_settings.shader_mode == SHADER_GLSL &&
+ (usePixelShaderFunction || useVertexShaderFunction)) {
+ GL_EXTCALL(glUseProgramObjectARB(0));
+ }
}
}
--
1.3.3
More information about the wine-devel
mailing list