Commit 2d8e05f8 authored by Jason Green's avatar Jason Green Committed by Alexandre Julliard

wined3d: Move constant loading into target-specific files.

- Moves GLSL constant loading code into glsl_shader.c and out of the over-populated drawprim.c. - Creates a new file named arb_program_shader.c which will hold code specific to ARB_vertex_program & ARB_fragment_program. - Remove the constant loading calls from drawprim.c
parent 7f18b4e5
......@@ -9,6 +9,7 @@ EXTRAINCL = @X_CFLAGS@
EXTRALIBS = -luuid @X_LIBS@ @X_PRE_LIBS@ @XLIB@ @X_EXTRA_LIBS@ @OPENGL_LIBS@
C_SRCS = \
arb_program_shader.c \
baseshader.c \
basetexture.c \
cubetexture.c \
......
/*
* Pixel and vertex shaders implementation using ARB_vertex_program
* and ARB_fragment_program GL extensions.
*
* Copyright 2002-2003 Jason Edmeades
* Copyright 2002-2003 Raphael Junqueira
* Copyright 2005 Oliver Stieber
* Copyright 2006 Ivan Gyurdiev
* Copyright 2006 Jason Green
*
* 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 <math.h>
#include <stdio.h>
#include "wined3d_private.h"
WINE_DEFAULT_DEBUG_CHANNEL(d3d_shader);
#define GLINFO_LOCATION (*gl_info)
/********************************************************
* ARB_[vertex/fragment]_program helper functions follow
********************************************************/
/**
* Loads floating point constants into the currently set ARB_vertex/fragment_program.
* When @constants_set == NULL, it will load all the constants.
*
* @target_type should be either GL_VERTEX_PROGRAM_ARB (for vertex shaders)
* or GL_FRAGMENT_PROGRAM_ARB (for pixel shaders)
*/
void shader_arb_load_constantsF(
WineD3D_GL_Info *gl_info,
GLuint target_type,
unsigned max_constants,
float* constants,
BOOL* constants_set) {
int i;
for (i=0; i<max_constants; ++i) {
if (NULL == constants_set || constants_set[i]) {
TRACE("Loading constants %i: %f, %f, %f, %f\n", i,
constants[i * sizeof(float) + 0], constants[i * sizeof(float) + 1],
constants[i * sizeof(float) + 2], constants[i * sizeof(float) + 3]);
GL_EXTCALL(glProgramEnvParameter4fvARB(target_type, i, &constants[i * sizeof(float)]));
checkGLcall("glProgramEnvParameter4fvARB");
}
}
}
/**
* Loads the app-supplied constants into the currently set ARB_[vertex/fragment]_programs.
*
* We only support float constants in ARB at the moment, so don't
* worry about the Integers or Booleans
*/
void shader_arb_load_constants(
IWineD3DStateBlock* iface,
char usePixelShader,
char useVertexShader) {
IWineD3DStateBlockImpl* stateBlock = (IWineD3DStateBlockImpl*) iface;
WineD3D_GL_Info *gl_info = &((IWineD3DImpl*)stateBlock->wineD3DDevice->wineD3D)->gl_info;
if (useVertexShader) {
IWineD3DVertexShaderImpl* vshader = (IWineD3DVertexShaderImpl*) stateBlock->vertexShader;
IWineD3DVertexDeclarationImpl* vertexDeclaration =
(IWineD3DVertexDeclarationImpl*) vshader->vertexDeclaration;
if (NULL != vertexDeclaration && NULL != vertexDeclaration->constants) {
/* Load DirectX 8 float constants for vertex shader */
shader_arb_load_constantsF(gl_info, GL_VERTEX_PROGRAM_ARB,
WINED3D_VSHADER_MAX_CONSTANTS,
vertexDeclaration->constants, NULL);
}
/* Load DirectX 9 float constants for vertex shader */
shader_arb_load_constantsF(gl_info, GL_VERTEX_PROGRAM_ARB,
WINED3D_VSHADER_MAX_CONSTANTS,
stateBlock->vertexShaderConstantF,
stateBlock->set.vertexShaderConstantsF);
}
if (usePixelShader) {
/* Load DirectX 9 float constants for pixel shader */
shader_arb_load_constantsF(gl_info, GL_FRAGMENT_PROGRAM_ARB, WINED3D_PSHADER_MAX_CONSTANTS,
stateBlock->pixelShaderConstantF,
stateBlock->set.pixelShaderConstantsF);
}
}
/* TODO: Add more ARB_[vertex/fragment]_program specific code here */
......@@ -1742,174 +1742,6 @@ void drawStridedSoftwareVS(IWineD3DDevice *iface, WineDirect3DVertexStridedData
#endif
/**
* Loads (pixel shader) samplers
*/
void drawPrimLoadPSamplersGLSL(
IWineD3DDevice* iface) {
IWineD3DDeviceImpl* This = (IWineD3DDeviceImpl *)iface;
GLhandleARB programId = This->stateBlock->shaderPrgId;
GLhandleARB name_loc;
int i;
char sampler_name[20];
if (programId == 0) {
/* No GLSL program set - nothing to do. */
return;
}
for (i=0; i< GL_LIMITS(textures); ++i) {
if (This->stateBlock->textures[i] != NULL) {
snprintf(sampler_name, sizeof(sampler_name), "psampler%d", i);
name_loc = GL_EXTCALL(glGetUniformLocationARB(programId, sampler_name));
if (name_loc != -1) {
TRACE_(d3d_shader)("Loading %s for texture %d\n", sampler_name, i);
GL_EXTCALL(glUniform1iARB(name_loc, i));
checkGLcall("glUniform1iARB");
}
}
}
}
/**
* Loads floating point constants (aka uniforms) into the currently set GLSL program.
* When @constants_set == NULL, it will load all the constants.
*/
void drawPrimLoadConstantsGLSL_F(IWineD3DDevice* iface,
unsigned max_constants,
float* constants,
BOOL* constants_set,
char is_pshader) {
IWineD3DDeviceImpl* This = (IWineD3DDeviceImpl *)iface;
GLhandleARB programId = This->stateBlock->shaderPrgId;
GLhandleARB tmp_loc;
int i;
char tmp_name[7];
if (programId == 0) {
/* No GLSL program set - nothing to do. */
return;
}
for (i=0; i<max_constants; ++i) {
if (NULL == constants_set || constants_set[i]) {
const char* prefix = is_pshader? "PC":"VC";
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]);
/* TODO: Benchmark and see if it would be beneficial to store the
* locations of the constants to avoid looking up each time */
snprintf(tmp_name, sizeof(tmp_name), "%s[%i]", prefix, i);
tmp_loc = GL_EXTCALL(glGetUniformLocationARB(programId, tmp_name));
if (tmp_loc != -1) {
/* We found this uniform name in the program - go ahead and send the data */
GL_EXTCALL(glUniform4fvARB(tmp_loc, 1, &constants[i*4]));
checkGLcall("glUniform4fvARB");
}
}
}
}
/**
* Loads floating point constants into the currently set ARB_vertex/fragment_program.
* When @constants_set == NULL, it will load all the constants.
*
* @target_type should be either GL_VERTEX_PROGRAM_ARB (for vertex shaders)
* or GL_FRAGMENT_PROGRAM_ARB (for pixel shaders)
*/
void drawPrimLoadConstantsARB_F(IWineD3DDevice* iface,
GLuint target_type,
unsigned max_constants,
float* constants,
BOOL* constants_set) {
IWineD3DDeviceImpl* This = (IWineD3DDeviceImpl *)iface;
int i;
for (i=0; i<max_constants; ++i) {
if (NULL == constants_set || constants_set[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");
}
}
}
/* Load the constants/uniforms which were passed by the application into either GLSL or ARB shader programs. */
void drawPrimLoadConstants(IWineD3DDevice *iface,
BOOL useVertexShader,
BOOL usePixelShader) {
IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
IWineD3DVertexShaderImpl *vshader = (IWineD3DVertexShaderImpl*) This->stateBlock->vertexShader;
if (wined3d_settings.shader_mode == SHADER_GLSL) {
if (useVertexShader) {
IWineD3DVertexDeclarationImpl* vertexDeclaration =
(IWineD3DVertexDeclarationImpl*) vshader->vertexDeclaration;
if (NULL != vertexDeclaration && NULL != vertexDeclaration->constants) {
/* Load DirectX 8 float constants/uniforms for vertex shader */
drawPrimLoadConstantsGLSL_F(iface, WINED3D_VSHADER_MAX_CONSTANTS,
vertexDeclaration->constants, NULL, 0);
}
/* Load DirectX 9 float constants/uniforms for vertex shader */
drawPrimLoadConstantsGLSL_F(iface, WINED3D_VSHADER_MAX_CONSTANTS,
This->stateBlock->vertexShaderConstantF,
This->stateBlock->set.vertexShaderConstantsF, 0);
/* TODO: Load boolean & integer constants for vertex shader */
}
if (usePixelShader) {
/* Load pixel shader samplers */
drawPrimLoadPSamplersGLSL(iface);
/* Load DirectX 9 float constants/uniforms for pixel shader */
drawPrimLoadConstantsGLSL_F(iface, WINED3D_PSHADER_MAX_CONSTANTS,
This->stateBlock->pixelShaderConstantF,
This->stateBlock->set.pixelShaderConstantsF, 1);
/* TODO: Load boolean & integer constants for pixel shader */
}
} else if (wined3d_settings.shader_mode == SHADER_ARB) {
/* We only support float constants in ARB at the moment, so don't
* worry about the Integers or Booleans */
if (useVertexShader) {
IWineD3DVertexDeclarationImpl* vertexDeclaration =
(IWineD3DVertexDeclarationImpl*) vshader->vertexDeclaration;
if (NULL != vertexDeclaration && NULL != vertexDeclaration->constants) {
/* Load DirectX 8 float constants for vertex shader */
drawPrimLoadConstantsARB_F(iface, GL_VERTEX_PROGRAM_ARB, WINED3D_VSHADER_MAX_CONSTANTS,
vertexDeclaration->constants, NULL);
}
/* Load DirectX 9 float constants for vertex shader */
drawPrimLoadConstantsARB_F(iface, GL_VERTEX_PROGRAM_ARB, WINED3D_VSHADER_MAX_CONSTANTS,
This->stateBlock->vertexShaderConstantF,
This->stateBlock->set.vertexShaderConstantsF);
}
if (usePixelShader) {
/* Load DirectX 9 float constants for pixel shader */
drawPrimLoadConstantsARB_F(iface, GL_FRAGMENT_PROGRAM_ARB, WINED3D_PSHADER_MAX_CONSTANTS,
This->stateBlock->pixelShaderConstantF,
This->stateBlock->set.pixelShaderConstantsF);
}
}
}
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;
......@@ -2055,7 +1887,11 @@ UINT numberOfvertices, UINT numberOfIndicies, GLenum glPrimType, const void *idx
}
/* Load any global constants/uniforms that may have been set by the application */
drawPrimLoadConstants(iface, useVertexShaderFunction, usePixelShaderFunction);
if (wined3d_settings.shader_mode == SHADER_GLSL)
shader_glsl_load_constants((IWineD3DStateBlock*)This->stateBlock, usePixelShaderFunction, useVertexShaderFunction);
else if (wined3d_settings.shader_mode == SHADER_ARB)
shader_arb_load_constants((IWineD3DStateBlock*)This->stateBlock, usePixelShaderFunction, useVertexShaderFunction);
/* DirectX colours are in a different format to opengl colours
* so if diffuse or specular are used then we need to use drawStridedSlow
......
......@@ -47,6 +47,119 @@ void print_glsl_info_log(WineD3D_GL_Info *gl_info, GLhandleARB obj) {
}
}
/**
* Loads (pixel shader) samplers
*/
void shader_glsl_load_psamplers(
WineD3D_GL_Info *gl_info,
IWineD3DStateBlock* iface) {
IWineD3DStateBlockImpl* stateBlock = (IWineD3DStateBlockImpl*) iface;
GLhandleARB programId = stateBlock->shaderPrgId;
GLhandleARB name_loc;
int i;
char sampler_name[20];
for (i=0; i< GL_LIMITS(textures); ++i) {
if (stateBlock->textures[i] != NULL) {
snprintf(sampler_name, sizeof(sampler_name), "psampler%d", i);
name_loc = GL_EXTCALL(glGetUniformLocationARB(programId, sampler_name));
if (name_loc != -1) {
TRACE_(d3d_shader)("Loading %s for texture %d\n", sampler_name, i);
GL_EXTCALL(glUniform1iARB(name_loc, i));
checkGLcall("glUniform1iARB");
}
}
}
}
/**
* Loads floating point constants (aka uniforms) into the currently set GLSL program.
* When @constants_set == NULL, it will load all the constants.
*/
void shader_glsl_load_constantsF(
WineD3D_GL_Info *gl_info,
GLhandleARB programId,
unsigned max_constants,
float* constants,
BOOL* constants_set,
char is_pshader) {
GLhandleARB tmp_loc;
int i;
char tmp_name[7];
const char* prefix = is_pshader? "PC":"VC";
for (i=0; i<max_constants; ++i) {
if (NULL == constants_set || constants_set[i]) {
TRACE("Loading constants %i: %f, %f, %f, %f\n", i,
constants[i * sizeof(float) + 0], constants[i * sizeof(float) + 1],
constants[i * sizeof(float) + 2], constants[i * sizeof(float) + 3]);
/* TODO: Benchmark and see if it would be beneficial to store the
* locations of the constants to avoid looking up each time */
snprintf(tmp_name, sizeof(tmp_name), "%s[%i]", prefix, i);
tmp_loc = GL_EXTCALL(glGetUniformLocationARB(programId, tmp_name));
if (tmp_loc != -1) {
/* We found this uniform name in the program - go ahead and send the data */
GL_EXTCALL(glUniform4fvARB(tmp_loc, 1, &constants[i * sizeof(float)]));
checkGLcall("glUniform4fvARB");
}
}
}
}
/**
* Loads the app-supplied constants into the currently set GLSL program.
*/
void shader_glsl_load_constants(
IWineD3DStateBlock* iface,
char usePixelShader,
char useVertexShader) {
IWineD3DStateBlockImpl* stateBlock = (IWineD3DStateBlockImpl*) iface;
WineD3D_GL_Info *gl_info = &((IWineD3DImpl*)stateBlock->wineD3DDevice->wineD3D)->gl_info;
GLhandleARB programId = stateBlock->shaderPrgId;
if (programId == 0) {
/* No GLSL program set - nothing to do. */
return;
}
if (useVertexShader) {
IWineD3DVertexShaderImpl* vshader = (IWineD3DVertexShaderImpl*) stateBlock->vertexShader;
IWineD3DVertexDeclarationImpl* vertexDeclaration =
(IWineD3DVertexDeclarationImpl*) vshader->vertexDeclaration;
if (NULL != vertexDeclaration && NULL != vertexDeclaration->constants) {
/* Load DirectX 8 float constants/uniforms for vertex shader */
shader_glsl_load_constantsF(gl_info, programId, WINED3D_VSHADER_MAX_CONSTANTS,
vertexDeclaration->constants, NULL, 0);
}
/* Load DirectX 9 float constants/uniforms for vertex shader */
shader_glsl_load_constantsF(gl_info, programId, WINED3D_VSHADER_MAX_CONSTANTS,
stateBlock->vertexShaderConstantF,
stateBlock->set.vertexShaderConstantsF, 0);
/* TODO: Load boolean & integer constants for vertex shader */
}
if (usePixelShader) {
/* Load pixel shader samplers */
shader_glsl_load_psamplers(gl_info, iface);
/* Load DirectX 9 float constants/uniforms for pixel shader */
shader_glsl_load_constantsF(gl_info, programId, WINED3D_PSHADER_MAX_CONSTANTS,
stateBlock->pixelShaderConstantF,
stateBlock->set.pixelShaderConstantsF, 1);
/* TODO: Load boolean & integer constants for pixel shader */
}
}
/*****************************************************************************
* Functions to generate GLSL strings from DirectX Shader bytecode begin here.
*
......
......@@ -1344,12 +1344,22 @@ extern const SHADER_OPCODE* shader_get_opcode(
IWineD3DBaseShader *iface,
const DWORD code);
/* ARB_[vertex/fragment]_program helper functions */
extern void shader_arb_load_constants(
IWineD3DStateBlock* iface,
char usePixelShader,
char useVertexShader);
/* ARB shader program Prototypes */
extern void shader_hw_def(SHADER_OPCODE_ARG *arg);
/* GLSL helper functions */
extern void set_glsl_shader_program(IWineD3DDevice *iface);
extern void shader_glsl_add_instruction_modifiers(SHADER_OPCODE_ARG *arg);
extern void shader_glsl_load_constants(
IWineD3DStateBlock* iface,
char usePixelShader,
char useVertexShader);
/** The following translate DirectX pixel/vertex shader opcodes to GLSL lines */
extern void shader_glsl_map2gl(SHADER_OPCODE_ARG* arg);
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment