static unsigned int shader_arb_load_constantsF(IWineD3DBaseShaderImpl* This, const WineD3D_GL_Info *gl_info,
GLuint target_type, unsigned int max_constants, const float *constants, char *dirty_consts)
{
+ DWORD shader_version = This->baseShader.reg_maps.shader_version;
local_constant* lconst;
DWORD i, j;
unsigned int ret;
}
}
/* In 1.X pixel shaders constants are implicitly clamped in the range [-1;1] */
- if(target_type == GL_FRAGMENT_PROGRAM_ARB &&
- WINED3DSHADER_VERSION_MAJOR(This->baseShader.hex_version) == 1) {
+ if (target_type == GL_FRAGMENT_PROGRAM_ARB && WINED3DSHADER_VERSION_MAJOR(shader_version) == 1)
+ {
float lcl_const[4];
for(i = 0; i < max_constants; i++) {
if(!dirty_consts[i]) continue;
}
}
+static void shader_arb_update_float_vertex_constants(IWineD3DDevice *iface, UINT start, UINT count)
+{
+ IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
+
+ /* We don't want shader constant dirtification to be an O(contexts), so just dirtify the active
+ * context. On a context switch the old context will be fully dirtified */
+ memset(This->activeContext->vshader_const_dirty + start, 1,
+ sizeof(*This->activeContext->vshader_const_dirty) * count);
+ This->highest_dirty_vs_const = max(This->highest_dirty_vs_const, start + count + 1);
+}
+
+static void shader_arb_update_float_pixel_constants(IWineD3DDevice *iface, UINT start, UINT count)
+{
+ IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
+
+ /* We don't want shader constant dirtification to be an O(contexts), so just dirtify the active
+ * context. On a context switch the old context will be fully dirtified */
+ memset(This->activeContext->pshader_const_dirty + start, 1,
+ sizeof(*This->activeContext->pshader_const_dirty) * count);
+ This->highest_dirty_ps_const = max(This->highest_dirty_ps_const, start + count + 1);
+}
+
/* Generate the variable & register declarations for the ARB_vertex_program output target */
static void shader_generate_arb_declarations(IWineD3DBaseShader *iface, const shader_reg_maps *reg_maps,
SHADER_BUFFER *buffer, const WineD3D_GL_Info *gl_info)
IWineD3DBaseShaderImpl* This = (IWineD3DBaseShaderImpl*) iface;
IWineD3DDeviceImpl *device = (IWineD3DDeviceImpl *) This->baseShader.device;
DWORD i, cur;
- char pshader = shader_is_pshader_version(This->baseShader.hex_version);
+ char pshader = shader_is_pshader_version(reg_maps->shader_version);
unsigned max_constantsF = min(This->baseShader.limits.constant_float,
(pshader ? GL_LIMITS(pshader_constantsF) : GL_LIMITS(vshader_constantsF)));
UINT extra_constants_needed = 0;
FIXME("No free constant to load the luminance parameters\n");
}
} else {
- FIXME("No free constant found to load environemnt bump mapping matrix into the shader. texbem instruction will not apply bump mapping\n");
+ FIXME("No free constant found to load environment bump mapping matrix into the shader. texbem instruction will not apply bump mapping\n");
}
ps->numbumpenvmatconsts = cur + 1;
static void shader_arb_get_write_mask(const SHADER_OPCODE_ARG *arg, const DWORD param, char *write_mask)
{
- IWineD3DBaseShaderImpl *This = (IWineD3DBaseShaderImpl *) arg->shader;
char *ptr = write_mask;
- char vshader = shader_is_vshader_version(This->baseShader.hex_version);
+ char vshader = shader_is_vshader_version(arg->reg_maps->shader_version);
if(vshader && shader_get_regtype(param) == WINED3DSPR_ADDR) {
*ptr++ = '.';
break;
case WINED3DSPR_INPUT:
- if (vshader_input_is_color((IWineD3DVertexShader*) This, reg))
- is_color = TRUE;
+ if (This->swizzle_map & (1 << reg)) is_color = TRUE;
sprintf(tmpReg, "vertex.attrib[%u]", reg);
strcat(hwLine, tmpReg);
static void pshader_hw_cnd(const SHADER_OPCODE_ARG *arg)
{
- IWineD3DBaseShaderImpl* shader = (IWineD3DBaseShaderImpl*) arg->shader;
SHADER_BUFFER* buffer = arg->buffer;
char dst_wmask[20];
char dst_name[50];
pshader_gen_input_modifier_line(arg->shader, buffer, arg->src[2], 2, src_name[2]);
/* The coissue flag changes the semantic of the cnd instruction in <= 1.3 shaders */
- if (shader->baseShader.hex_version <= WINED3DPS_VERSION(1, 3) &&
- arg->opcode_token & WINED3DSI_COISSUE) {
+ if (arg->reg_maps->shader_version <= WINED3DPS_VERSION(1, 3) && arg->opcode_token & WINED3DSI_COISSUE)
+ {
shader_addline(buffer, "MOV%s %s%s, %s;\n", sat ? "_SAT" : "", dst_name, dst_wmask, src_name[1]);
} else {
shader_addline(buffer, "ADD TMP, -%s, coefdiv.x;\n", src_name[0]);
/* Map the opcode 1-to-1 to the GL code */
static void shader_hw_map2gl(const SHADER_OPCODE_ARG *arg)
{
- IWineD3DBaseShaderImpl *shader = (IWineD3DBaseShaderImpl*)arg->shader;
CONST SHADER_OPCODE* curOpcode = arg->opcode;
SHADER_BUFFER* buffer = arg->buffer;
DWORD dst = arg->dst;
const DWORD *src = arg->src;
+ const char *instruction;
char arguments[256];
unsigned int i;
- if (shader_is_pshader_version(shader->baseShader.hex_version))
+ switch (curOpcode->opcode)
+ {
+ case WINED3DSIO_ABS: instruction = "ABS"; break;
+ case WINED3DSIO_ADD: instruction = "ADD"; break;
+ case WINED3DSIO_CRS: instruction = "XPD"; break;
+ case WINED3DSIO_DP3: instruction = "DP3"; break;
+ case WINED3DSIO_DP4: instruction = "DP4"; break;
+ case WINED3DSIO_DST: instruction = "DST"; break;
+ case WINED3DSIO_EXP: instruction = "EX2"; break;
+ case WINED3DSIO_EXPP: instruction = "EXP"; break;
+ case WINED3DSIO_FRC: instruction = "FRC"; break;
+ case WINED3DSIO_LIT: instruction = "LIT"; break;
+ case WINED3DSIO_LOG: instruction = "LG2"; break;
+ case WINED3DSIO_LOGP: instruction = "LOG"; break;
+ case WINED3DSIO_LRP: instruction = "LRP"; break;
+ case WINED3DSIO_MAD: instruction = "MAD"; break;
+ case WINED3DSIO_MAX: instruction = "MAX"; break;
+ case WINED3DSIO_MIN: instruction = "MIN"; break;
+ case WINED3DSIO_MOV: instruction = "MOV"; break;
+ case WINED3DSIO_MUL: instruction = "MUL"; break;
+ case WINED3DSIO_NOP: instruction = "NOP"; break;
+ case WINED3DSIO_POW: instruction = "POW"; break;
+ case WINED3DSIO_SGE: instruction = "SGE"; break;
+ case WINED3DSIO_SLT: instruction = "SLT"; break;
+ case WINED3DSIO_SUB: instruction = "SUB"; break;
+ default: instruction = "";
+ FIXME("Unhandled opcode %s\n", curOpcode->name);
+ break;
+ }
+
+ if (shader_is_pshader_version(arg->reg_maps->shader_version))
{
/* Output token related */
char output_rname[256];
strcat(arguments, ", ");
strcat(arguments, operands[i]);
}
- shader_addline(buffer, "%s%s %s;\n", curOpcode->glname, modifier, arguments);
+ shader_addline(buffer, "%s%s %s;\n", instruction, modifier, arguments);
/* A shift requires another line. */
if (shift) pshader_gen_output_modifier_line(buffer, saturate, output_wmask, shift, output_rname);
vshader_program_add_param(arg, src[i-1], TRUE, arguments);
}
}
- shader_addline(buffer, "%s%s;\n", curOpcode->glname, arguments);
+ shader_addline(buffer, "%s%s;\n", instruction, arguments);
}
}
{
IWineD3DBaseShaderImpl *shader = (IWineD3DBaseShaderImpl*)arg->shader;
- if ((WINED3DSHADER_VERSION_MAJOR(shader->baseShader.hex_version) == 1
- && !shader_is_pshader_version(shader->baseShader.hex_version)
+ if ((WINED3DSHADER_VERSION_MAJOR(arg->reg_maps->shader_version) == 1
+ && !shader_is_pshader_version(arg->reg_maps->shader_version)
&& shader_get_regtype(arg->dst) == WINED3DSPR_ADDR)
|| arg->opcode->opcode == WINED3DSIO_MOVA)
{
static void pshader_hw_texkill(const SHADER_OPCODE_ARG *arg)
{
- IWineD3DPixelShaderImpl* This = (IWineD3DPixelShaderImpl*) arg->shader;
- DWORD hex_version = This->baseShader.hex_version;
+ DWORD shader_version = arg->reg_maps->shader_version;
SHADER_BUFFER* buffer = arg->buffer;
char reg_dest[40];
*/
pshader_get_register_name(arg->shader, arg->dst, reg_dest);
- if(hex_version >= WINED3DPS_VERSION(2,0)) {
+ if (shader_version >= WINED3DPS_VERSION(2,0))
+ {
/* The arb backend doesn't claim ps 2.0 support, but try to eat what the app feeds to us */
shader_addline(buffer, "KIL %s;\n", reg_dest);
} else {
DWORD dst = arg->dst;
const DWORD *src = arg->src;
SHADER_BUFFER* buffer = arg->buffer;
- DWORD hex_version = This->baseShader.hex_version;
+ DWORD shader_version = arg->reg_maps->shader_version;
BOOL projected = FALSE, bias = FALSE;
char reg_dest[40];
/* 1.0-1.3: Use destination register as coordinate source.
1.4+: Use provided coordinate source register. */
- if (hex_version < WINED3DPS_VERSION(1,4))
+ if (shader_version < WINED3DPS_VERSION(1,4))
strcpy(reg_coord, reg_dest);
else
pshader_gen_input_modifier_line(arg->shader, buffer, src[0], 0, reg_coord);
/* 1.0-1.4: Use destination register number as texture code.
2.0+: Use provided sampler number as texure code. */
- if (hex_version < WINED3DPS_VERSION(2,0))
+ if (shader_version < WINED3DPS_VERSION(2,0))
reg_sampler_code = reg_dest_code;
else
reg_sampler_code = src[1] & WINED3DSP_REGNUM_MASK;
* 1.4: Use WINED3DSPSM_DZ or WINED3DSPSM_DW on src[0]
* 2.0+: Use WINED3DSI_TEXLD_PROJECT on the opcode
*/
- if(hex_version < WINED3DPS_VERSION(1,4)) {
+ if (shader_version < WINED3DPS_VERSION(1,4))
+ {
DWORD flags = 0;
if(reg_sampler_code < MAX_TEXTURES) {
flags = deviceImpl->stateBlock->textureState[reg_sampler_code][WINED3DTSS_TEXTURETRANSFORMFLAGS];
if (flags & WINED3DTTFF_PROJECTED) {
projected = TRUE;
}
- } else if(hex_version < WINED3DPS_VERSION(2,0)) {
+ }
+ else if (shader_version < WINED3DPS_VERSION(2,0))
+ {
DWORD src_mod = arg->src[0] & WINED3DSP_SRCMOD_MASK;
if (src_mod == WINED3DSPSM_DZ) {
projected = TRUE;
static void pshader_hw_texcoord(const SHADER_OPCODE_ARG *arg)
{
- IWineD3DPixelShaderImpl* This = (IWineD3DPixelShaderImpl*) arg->shader;
DWORD dst = arg->dst;
SHADER_BUFFER* buffer = arg->buffer;
- DWORD hex_version = This->baseShader.hex_version;
char tmp[20];
shader_arb_get_write_mask(arg, dst, tmp);
- if (hex_version != WINED3DPS_VERSION(1,4)) {
+ if (arg->reg_maps->shader_version != WINED3DPS_VERSION(1,4))
+ {
DWORD reg = dst & WINED3DSP_REGNUM_MASK;
shader_addline(buffer, "MOV_SAT T%u%s, fragment.texcoord[%u];\n", reg, tmp, reg);
} else {
sprintf(dst_str, "T%u", reg1);
pshader_gen_input_modifier_line(arg->shader, buffer, arg->src[0], 0, src_str);
- shader_addline(buffer, "MOV TMP.r, %s.a;\n", src_str);
- shader_addline(buffer, "MOV TMP.g, %s.r;\n", src_str);
+ shader_addline(buffer, "MOV TMP.x, %s.w;\n", src_str);
+ shader_addline(buffer, "MOV TMP.y, %s.x;\n", src_str);
flags = reg1 < MAX_TEXTURES ? deviceImpl->stateBlock->textureState[reg1][WINED3DTSS_TEXTURETRANSFORMFLAGS] : 0;
shader_hw_sample(arg, reg1, dst_str, "TMP", flags & WINED3DTTFF_PROJECTED, FALSE);
}
sprintf(dst_str, "T%u", reg1);
pshader_gen_input_modifier_line(arg->shader, buffer, arg->src[0], 0, src_str);
- shader_addline(buffer, "MOV TMP.r, %s.g;\n", src_str);
- shader_addline(buffer, "MOV TMP.g, %s.b;\n", src_str);
+ shader_addline(buffer, "MOV TMP.x, %s.y;\n", src_str);
+ shader_addline(buffer, "MOV TMP.y, %s.z;\n", src_str);
shader_hw_sample(arg, reg1, dst_str, "TMP", FALSE, FALSE);
}
/* Sampling the perturbation map in Tsrc was done already, including the signedness correction if needed */
shader_addline(buffer, "SWZ TMP2, bumpenvmat%d, x, z, 0, 0;\n", reg_dest_code);
- shader_addline(buffer, "DP3 TMP.r, TMP2, T%u;\n", src);
+ shader_addline(buffer, "DP3 TMP.x, TMP2, T%u;\n", src);
shader_addline(buffer, "SWZ TMP2, bumpenvmat%d, y, w, 0, 0;\n", reg_dest_code);
- shader_addline(buffer, "DP3 TMP.g, TMP2, T%u;\n", src);
+ shader_addline(buffer, "DP3 TMP.y, TMP2, T%u;\n", src);
/* with projective textures, texbem only divides the static texture coord, not the displacement,
* so we can't let the GL handle this.
*/
if (((IWineD3DDeviceImpl*) This->baseShader.device)->stateBlock->textureState[reg_dest_code][WINED3DTSS_TEXTURETRANSFORMFLAGS]
& WINED3DTTFF_PROJECTED) {
- shader_addline(buffer, "RCP TMP2.a, %s.a;\n", reg_coord);
- shader_addline(buffer, "MUL TMP2.rg, %s, TMP2.a;\n", reg_coord);
- shader_addline(buffer, "ADD TMP.rg, TMP, TMP2;\n");
+ shader_addline(buffer, "RCP TMP2.w, %s.w;\n", reg_coord);
+ shader_addline(buffer, "MUL TMP2.xy, %s, TMP2.w;\n", reg_coord);
+ shader_addline(buffer, "ADD TMP.xy, TMP, TMP2;\n");
} else {
- shader_addline(buffer, "ADD TMP.rg, TMP, %s;\n", reg_coord);
+ shader_addline(buffer, "ADD TMP.xy, TMP, %s;\n", reg_coord);
}
shader_hw_sample(arg, reg_dest_code, reg_coord, "TMP", FALSE, FALSE);
/* According to the msdn, the source register(must be r5) is unusable after
* the texdepth instruction, so we're free to modify it
*/
- shader_addline(buffer, "MIN %s.g, %s.g, one.g;\n", dst_name, dst_name);
+ shader_addline(buffer, "MIN %s.y, %s.y, one.y;\n", dst_name, dst_name);
/* How to deal with the special case dst_name.g == 0? if r != 0, then
* the r * (1 / 0) will give infinity, which is clamped to 1.0, the correct
* result. But if r = 0.0, then 0 * inf = 0, which is incorrect.
*/
- shader_addline(buffer, "RCP %s.g, %s.g;\n", dst_name, dst_name);
- shader_addline(buffer, "MUL TMP.x, %s.r, %s.g;\n", dst_name, dst_name);
- shader_addline(buffer, "MIN TMP.x, TMP.x, one.r;\n");
+ shader_addline(buffer, "RCP %s.y, %s.y;\n", dst_name, dst_name);
+ shader_addline(buffer, "MUL TMP.x, %s.x, %s.y;\n", dst_name, dst_name);
+ shader_addline(buffer, "MIN TMP.x, TMP.x, one.x;\n");
shader_addline(buffer, "MAX result.depth, TMP.x, 0.0;\n");
}
*/
shader_addline(buffer, "RCP TMP.y, TMP.y;\n");
shader_addline(buffer, "MUL TMP.x, TMP.x, TMP.y;\n");
- shader_addline(buffer, "MIN TMP.x, TMP.x, one.r;\n");
+ shader_addline(buffer, "MIN TMP.x, TMP.x, one.x;\n");
shader_addline(buffer, "MAX result.depth, TMP.x, 0.0;\n");
}
SHADER_OPCODE_ARG tmpArg;
IWineD3DBaseShaderImpl *shader = (IWineD3DBaseShaderImpl *)arg->shader;
const SHADER_OPCODE *opcode_table = shader->baseShader.shader_ins;
- DWORD shader_version = shader->baseShader.hex_version;
+ DWORD shader_version = arg->reg_maps->shader_version;
memset(&tmpArg, 0, sizeof(SHADER_OPCODE_ARG));
DWORD dst = arg->dst;
DWORD src = arg->src[0];
DWORD swizzle = (src & WINED3DSP_SWIZZLE_MASK) >> WINED3DSP_SWIZZLE_SHIFT;
+ const char *instruction;
char tmpLine[256];
- strcpy(tmpLine, curOpcode->glname); /* Opcode */
+ switch(curOpcode->opcode)
+ {
+ case WINED3DSIO_RSQ: instruction = "RSQ"; break;
+ case WINED3DSIO_RCP: instruction = "RCP"; break;
+ default: instruction = "";
+ FIXME("Unhandled opcode %s\n", curOpcode->name);
+ break;
+ }
+
+ strcpy(tmpLine, instruction);
vshader_program_add_param(arg, dst, FALSE, tmpLine); /* Destination */
strcat(tmpLine, ",");
vshader_program_add_param(arg, src, TRUE, tmpLine);
static GLuint create_arb_blt_fragment_program(const WineD3D_GL_Info *gl_info, enum tex_types tex_type)
{
GLuint program_id = 0;
- const char *blt_fprograms[tex_type_count] =
+ static const char * const blt_fprograms[tex_type_count] =
{
/* tex_1d */
NULL,
}
}
-static void shader_arb_cleanup(IWineD3DDevice *iface) {
- IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
- const WineD3D_GL_Info *gl_info = &This->adapter->gl_info;
- if (GL_SUPPORT(ARB_VERTEX_PROGRAM)) glDisable(GL_VERTEX_PROGRAM_ARB);
- if (GL_SUPPORT(ARB_FRAGMENT_PROGRAM)) glDisable(GL_FRAGMENT_PROGRAM_ARB);
-}
-
static void shader_arb_destroy(IWineD3DBaseShader *iface) {
IWineD3DBaseShaderImpl *baseShader = (IWineD3DBaseShaderImpl *) iface;
const WineD3D_GL_Info *gl_info = &((IWineD3DDeviceImpl *)baseShader->baseShader.device)->adapter->gl_info;
- char pshader = shader_is_pshader_version(baseShader->baseShader.hex_version);
- if(pshader) {
+ if (shader_is_pshader_version(baseShader->baseShader.reg_maps.shader_version))
+ {
IWineD3DPixelShaderImpl *This = (IWineD3DPixelShaderImpl *) iface;
UINT i;
/* [0.0;1.0] clamping. Not needed, this is done implicitly */
}
-static GLuint shader_arb_generate_pshader(IWineD3DPixelShader *iface, SHADER_BUFFER *buffer) {
+static GLuint shader_arb_generate_pshader(IWineD3DPixelShader *iface, SHADER_BUFFER *buffer, const struct ps_compile_args *args) {
IWineD3DPixelShaderImpl *This = (IWineD3DPixelShaderImpl *)iface;
const shader_reg_maps* reg_maps = &This->baseShader.reg_maps;
CONST DWORD *function = This->baseShader.function;
- const char *fragcolor;
+ DWORD shader_version = reg_maps->shader_version;
const WineD3D_GL_Info *gl_info = &((IWineD3DDeviceImpl *)This->baseShader.device)->adapter->gl_info;
const local_constant *lconst;
GLuint retval;
+ const char *fragcolor;
/* Create the hw ARB shader */
shader_addline(buffer, "!!ARBfp1.0\n");
+ if (shader_version < WINED3DPS_VERSION(3,0)) {
+ switch(args->fog) {
+ case FOG_OFF:
+ break;
+ case FOG_LINEAR:
+ shader_addline(buffer, "OPTION ARB_fog_linear;\n");
+ break;
+ case FOG_EXP:
+ shader_addline(buffer, "OPTION ARB_fog_exp;\n");
+ break;
+ case FOG_EXP2:
+ shader_addline(buffer, "OPTION ARB_fog_exp2;\n");
+ break;
+ }
+ }
+
shader_addline(buffer, "TEMP TMP;\n"); /* Used in matrix ops */
shader_addline(buffer, "TEMP TMP2;\n"); /* Used in matrix ops */
shader_addline(buffer, "TEMP TA;\n"); /* Used for modifiers */
shader_addline(buffer, "PARAM coefmul = { 2, 4, 8, 16 };\n");
shader_addline(buffer, "PARAM one = { 1.0, 1.0, 1.0, 1.0 };\n");
- /* Base Declarations */
- shader_generate_arb_declarations( (IWineD3DBaseShader*) This, reg_maps, buffer, &GLINFO_LOCATION);
-
- /* We need two variables for fog blending */
- shader_addline(buffer, "TEMP TMP_FOG;\n");
- if (This->baseShader.hex_version >= WINED3DPS_VERSION(2,0)) {
+ if (shader_version < WINED3DPS_VERSION(2,0)) {
+ fragcolor = "R0";
+ } else {
shader_addline(buffer, "TEMP TMP_COLOR;\n");
+ fragcolor = "TMP_COLOR";
}
+ /* Base Declarations */
+ shader_generate_arb_declarations( (IWineD3DBaseShader*) This, reg_maps, buffer, &GLINFO_LOCATION);
+
/* Base Shader Body */
shader_generate_main( (IWineD3DBaseShader*) This, buffer, reg_maps, function);
- /* calculate fog and blend it
- * NOTE: state.fog.params.y and state.fog.params.z don't hold fog start s and end e but
- * -1/(e-s) and e/(e-s) respectively.
- */
- shader_addline(buffer, "MAD_SAT TMP_FOG, fragment.fogcoord, state.fog.params.y, state.fog.params.z;\n");
-
- if (This->baseShader.hex_version < WINED3DPS_VERSION(2,0)) {
- fragcolor = "R0";
- } else {
- fragcolor = "TMP_COLOR";
- }
- if(((IWineD3DDeviceImpl *)This->baseShader.device)->stateBlock->renderState[WINED3DRS_SRGBWRITEENABLE]) {
+ if(args->srgb_correction) {
arbfp_add_sRGB_correction(buffer, fragcolor, "TMP", "TMP2", "TA", "TB");
}
- if (This->baseShader.hex_version < WINED3DPS_VERSION(3,0)) {
- shader_addline(buffer, "LRP result.color.rgb, TMP_FOG.x, %s, state.fog.color;\n", fragcolor);
- shader_addline(buffer, "MOV result.color.a, %s.a;\n", fragcolor);
- }
-
+ shader_addline(buffer, "MOV result.color, %s;\n", fragcolor);
shader_addline(buffer, "END\n");
/* TODO: change to resource.glObjectHandle or something like that */
shader_arb_select,
shader_arb_select_depth_blt,
shader_arb_deselect_depth_blt,
+ shader_arb_update_float_vertex_constants,
+ shader_arb_update_float_pixel_constants,
shader_arb_load_constants,
- shader_arb_cleanup,
shader_arb_color_correction,
shader_arb_destroy,
shader_arb_alloc,
* application provided constants
*/
if(device->shader_backend == &arb_program_shader_backend) {
- if(use_ps(device)) return;
+ if (use_ps(stateblock)) return;
device = stateblock->wineD3DDevice;
device->activeContext->pshader_const_dirty[ARB_FFP_CONST_TFACTOR] = 1;
* application provided constants
*/
if(device->shader_backend == &arb_program_shader_backend) {
- if(use_ps(device)) return;
+ if (use_ps(stateblock)) return;
device = stateblock->wineD3DDevice;
device->activeContext->pshader_const_dirty[ARB_FFP_CONST_SPECULAR_ENABLE] = 1;
}
static void set_bumpmat_arbfp(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
- DWORD stage = (state - STATE_TEXTURESTAGE(0, 0)) / WINED3D_HIGHEST_TEXTURE_STATE;
+ DWORD stage = (state - STATE_TEXTURESTAGE(0, 0)) / (WINED3D_HIGHEST_TEXTURE_STATE + 1);
IWineD3DDeviceImpl *device = stateblock->wineD3DDevice;
float mat[2][2];
- if(use_ps(device)) {
+ if (use_ps(stateblock))
+ {
if(stage != 0 &&
((IWineD3DPixelShaderImpl *) stateblock->pixelShader)->baseShader.reg_maps.bumpmat[stage]) {
/* The pixel shader has to know the bump env matrix. Do a constants update if it isn't scheduled
}
static void tex_bumpenvlum_arbfp(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
- DWORD stage = (state - STATE_TEXTURESTAGE(0, 0)) / WINED3D_HIGHEST_TEXTURE_STATE;
+ DWORD stage = (state - STATE_TEXTURESTAGE(0, 0)) / (WINED3D_HIGHEST_TEXTURE_STATE + 1);
IWineD3DDeviceImpl *device = stateblock->wineD3DDevice;
float param[4];
- if(use_ps(device)) {
+ if (use_ps(stateblock))
+ {
if(stage != 0 &&
((IWineD3DPixelShaderImpl *) stateblock->pixelShader)->baseShader.reg_maps.luminanceparams[stage]) {
/* The pixel shader has to know the luminance offset. Do a constants update if it
if(argnum == 2) ret = "arg2";
}
if(arg & WINED3DTA_ALPHAREPLICATE) {
- shader_addline(buffer, "MOV arg%u, %s.a;\n", argnum, ret);
+ shader_addline(buffer, "MOV arg%u, %s.w;\n", argnum, ret);
if(argnum == 0) ret = "arg0";
if(argnum == 1) ret = "arg1";
if(argnum == 2) ret = "arg2";
BOOL mul_final_dest = FALSE;
if(color && alpha) dstmask = "";
- else if(color) dstmask = ".rgb";
- else dstmask = ".a";
+ else if(color) dstmask = ".xyz";
+ else dstmask = ".w";
if(dst == tempreg) dstreg = "tempreg";
else dstreg = "ret";
switch(op) {
case WINED3DTOP_DISABLE:
- if(stage == 1) shader_addline(buffer, "MOV %s%s, fragment.color.primary;\n", dstreg, dstmask);
+ if(stage == 0) shader_addline(buffer, "MOV %s%s, fragment.color.primary;\n", dstreg, dstmask);
break;
case WINED3DTOP_SELECTARG2:
case WINED3DTOP_BLENDCURRENTALPHA:
arg0 = get_argreg(buffer, 0, stage, WINED3DTA_CURRENT);
- shader_addline(buffer, "LRP %s%s, %s.a, %s, %s;\n", dstreg, dstmask, arg0, arg1, arg2);
+ shader_addline(buffer, "LRP %s%s, %s.w, %s, %s;\n", dstreg, dstmask, arg0, arg1, arg2);
break;
case WINED3DTOP_BLENDFACTORALPHA:
arg0 = get_argreg(buffer, 0, stage, WINED3DTA_TFACTOR);
- shader_addline(buffer, "LRP %s%s, %s.a, %s, %s;\n", dstreg, dstmask, arg0, arg1, arg2);
+ shader_addline(buffer, "LRP %s%s, %s.w, %s, %s;\n", dstreg, dstmask, arg0, arg1, arg2);
break;
case WINED3DTOP_BLENDTEXTUREALPHA:
arg0 = get_argreg(buffer, 0, stage, WINED3DTA_TEXTURE);
- shader_addline(buffer, "LRP %s%s, %s.a, %s, %s;\n", dstreg, dstmask, arg0, arg1, arg2);
+ shader_addline(buffer, "LRP %s%s, %s.w, %s, %s;\n", dstreg, dstmask, arg0, arg1, arg2);
break;
case WINED3DTOP_BLENDDIFFUSEALPHA:
arg0 = get_argreg(buffer, 0, stage, WINED3DTA_DIFFUSE);
- shader_addline(buffer, "LRP %s%s, %s.a, %s, %s;\n", dstreg, dstmask, arg0, arg1, arg2);
+ shader_addline(buffer, "LRP %s%s, %s.w, %s, %s;\n", dstreg, dstmask, arg0, arg1, arg2);
break;
case WINED3DTOP_BLENDTEXTUREALPHAPM:
arg0 = get_argreg(buffer, 0, stage, WINED3DTA_TEXTURE);
- shader_addline(buffer, "SUB arg0.a, const.x, %s.a;\n", arg0);
- shader_addline(buffer, "MAD_SAT %s%s, %s, arg0.a, %s;\n", dstreg, dstmask, arg2, arg1);
+ shader_addline(buffer, "SUB arg0.w, const.x, %s.w;\n", arg0);
+ shader_addline(buffer, "MAD_SAT %s%s, %s, arg0.w, %s;\n", dstreg, dstmask, arg2, arg1);
break;
/* D3DTOP_PREMODULATE ???? */
case WINED3DTOP_MODULATEINVALPHA_ADDCOLOR:
- shader_addline(buffer, "SUB arg0.a, const.x, %s;\n", arg1);
- shader_addline(buffer, "MAD_SAT %s%s, arg0.a, %s, %s;\n", dstreg, dstmask, arg2, arg1);
+ shader_addline(buffer, "SUB arg0.w, const.x, %s;\n", arg1);
+ shader_addline(buffer, "MAD_SAT %s%s, arg0.w, %s, %s;\n", dstreg, dstmask, arg2, arg1);
break;
case WINED3DTOP_MODULATEALPHA_ADDCOLOR:
- shader_addline(buffer, "MAD_SAT %s%s, %s.a, %s, %s;\n", dstreg, dstmask, arg1, arg2, arg1);
+ shader_addline(buffer, "MAD_SAT %s%s, %s.w, %s, %s;\n", dstreg, dstmask, arg1, arg2, arg1);
break;
case WINED3DTOP_MODULATEINVCOLOR_ADDALPHA:
shader_addline(buffer, "SUB arg0, const.x, %s;\n", arg1);
- shader_addline(buffer, "MAD_SAT %s%s, arg0, %s, %s.a;\n", dstreg, dstmask, arg2, arg1);
+ shader_addline(buffer, "MAD_SAT %s%s, arg0, %s, %s.w;\n", dstreg, dstmask, arg2, arg1);
break;
case WINED3DTOP_MODULATECOLOR_ADDALPHA:
- shader_addline(buffer, "MAD_SAT %s%s, %s, %s, %s.a;\n", dstreg, dstmask, arg1, arg2, arg1);
+ shader_addline(buffer, "MAD_SAT %s%s, %s, %s, %s.w;\n", dstreg, dstmask, arg1, arg2, arg1);
break;
case WINED3DTOP_DOTPRODUCT3:
}
/* Shader header */
- buffer.bsize = 0;
- buffer.lineNo = 0;
- buffer.newline = TRUE;
- buffer.buffer = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, SHADER_PGMSIZE);
+ shader_buffer_init(&buffer);
shader_addline(&buffer, "!!ARBfp1.0\n");
(settings->op[stage - 1].cop == WINED3DTOP_BUMPENVMAP ||
settings->op[stage - 1].cop == WINED3DTOP_BUMPENVMAPLUMINANCE)) {
shader_addline(&buffer, "SWZ arg1, bumpmat%u, x, z, 0, 0;\n", stage - 1);
- shader_addline(&buffer, "DP3 ret.r, arg1, tex%u;\n", stage - 1);
+ shader_addline(&buffer, "DP3 ret.x, arg1, tex%u;\n", stage - 1);
shader_addline(&buffer, "SWZ arg1, bumpmat%u, y, w, 0, 0;\n", stage - 1);
- shader_addline(&buffer, "DP3 ret.g, arg1, tex%u;\n", stage - 1);
+ shader_addline(&buffer, "DP3 ret.y, arg1, tex%u;\n", stage - 1);
/* with projective textures, texbem only divides the static texture coord, not the displacement,
* so multiply the displacement with the dividing parameter before passing it to TXP
*/
if (settings->op[stage].projected != proj_none) {
if(settings->op[stage].projected == proj_count4) {
- shader_addline(&buffer, "MOV ret.a, fragment.texcoord[%u].a;\n", stage);
- shader_addline(&buffer, "MUL ret.rgb, ret, fragment.texcoord[%u].a, fragment.texcoord[%u];\n", stage, stage);
+ shader_addline(&buffer, "MOV ret.w, fragment.texcoord[%u].w;\n", stage);
+ shader_addline(&buffer, "MUL ret.xyz, ret, fragment.texcoord[%u].w, fragment.texcoord[%u];\n", stage, stage);
} else {
- shader_addline(&buffer, "MOV ret.a, fragment.texcoord[%u].b;\n", stage);
- shader_addline(&buffer, "MAD ret.rgb, ret, fragment.texcoord[%u].b, fragment.texcoord[%u];\n", stage, stage);
+ shader_addline(&buffer, "MOV ret.w, fragment.texcoord[%u].z;\n", stage);
+ shader_addline(&buffer, "MAD ret.xyz, ret, fragment.texcoord[%u].z, fragment.texcoord[%u];\n", stage, stage);
}
} else {
shader_addline(&buffer, "ADD ret, ret, fragment.texcoord[%u];\n", stage);
shader_addline(&buffer, "%s%s tex%u, ret, texture[%u], %s;\n",
instr, sat, stage, stage, textype);
if(settings->op[stage - 1].cop == WINED3DTOP_BUMPENVMAPLUMINANCE) {
- shader_addline(&buffer, "MAD_SAT ret.r, tex%u.b, luminance%u.r, luminance%u.g;\n",
+ shader_addline(&buffer, "MAD_SAT ret.x, tex%u.z, luminance%u.x, luminance%u.y;\n",
stage - 1, stage - 1, stage - 1);
- shader_addline(&buffer, "MUL tex%u, tex%u, ret.r;\n", stage, stage);
+ shader_addline(&buffer, "MUL tex%u, tex%u, ret.x;\n", stage, stage);
}
} else if(settings->op[stage].projected == proj_count3) {
shader_addline(&buffer, "MOV ret, fragment.texcoord[%u];\n", stage);
- shader_addline(&buffer, "MOV ret.a, ret.b;\n");
+ shader_addline(&buffer, "MOV ret.w, ret.z;\n");
shader_addline(&buffer, "%s%s tex%u, ret, texture[%u], %s;\n",
instr, sat, stage, stage, textype);
} else {
sprintf(colorcor_dst, "tex%u", stage);
gen_color_correction(&buffer, colorcor_dst, WINED3DSP_WRITEMASK_ALL, "const.x", "const.y",
- settings->op[stage].color_correction);
+ settings->op[stage].color_fixup);
}
/* Generate the main shader */
settings->op[stage].cop, settings->op[stage].carg0,
settings->op[stage].carg1, settings->op[stage].carg2);
if(stage == 0) {
- shader_addline(&buffer, "MOV ret.a, fragment.color.primary.a;\n");
+ shader_addline(&buffer, "MOV ret.w, fragment.color.primary.w;\n");
}
} else if(op_equal) {
gen_ffp_instr(&buffer, stage, TRUE, TRUE, settings->op[stage].dst,
if(settings->sRGB_write) {
shader_addline(&buffer, "MAD ret, fragment.color.secondary, specular_enable, %s;\n", final_combiner_src);
arbfp_add_sRGB_correction(&buffer, "ret", "arg0", "arg1", "arg2", "tempreg");
- shader_addline(&buffer, "MOV result.color.a, ret.a;\n");
+ shader_addline(&buffer, "MOV result.color.w, ret.w;\n");
} else {
shader_addline(&buffer, "MAD result.color, fragment.color.secondary, specular_enable, %s;\n", final_combiner_src);
}
FIXME("Fragment program error at position %d: %s\n", pos,
debugstr_a((const char *)glGetString(GL_PROGRAM_ERROR_STRING_ARB)));
}
- HeapFree(GetProcessHeap(), 0, buffer.buffer);
+ shader_buffer_free(&buffer);
return ret;
}
static void fragment_prog_arbfp(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
IWineD3DDeviceImpl *device = stateblock->wineD3DDevice;
struct shader_arb_priv *priv = (struct shader_arb_priv *) device->fragment_priv;
- BOOL use_pshader = use_ps(device);
- BOOL use_vshader = use_vs(device);
+ BOOL use_pshader = use_ps(stateblock);
+ BOOL use_vshader = use_vs(stateblock);
struct ffp_frag_settings settings;
const struct arbfp_ffp_desc *desc;
unsigned int i;
}
state_texfactor_arbfp(STATE_RENDER(WINED3DRS_TEXTUREFACTOR), stateblock, context);
state_arb_specularenable(STATE_RENDER(WINED3DRS_SPECULARENABLE), stateblock, context);
+ } else if(use_pshader && !isStateDirty(context, device->StateTable[STATE_VSHADER].representative)) {
+ device->shader_backend->shader_select((IWineD3DDevice *)stateblock->wineD3DDevice, use_pshader, use_vshader);
}
return;
}
* fragment_prog_arbfp function being called because FOGENABLE is dirty, which calls this function here
*/
static void state_arbfp_fog(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
+ enum fogsource new_source;
+
if(!isStateDirty(context, STATE_PIXELSHADER)) {
fragment_prog_arbfp(state, stateblock, context);
}
+
+ if(!stateblock->renderState[WINED3DRS_FOGENABLE]) return;
+
+ if(use_vs(stateblock)
+ && ((IWineD3DVertexShaderImpl *)stateblock->vertexShader)->baseShader.reg_maps.fog) {
+ if( stateblock->renderState[WINED3DRS_FOGTABLEMODE] != WINED3DFOG_NONE ) {
+ FIXME("vertex shader with table fog used\n");
+ }
+ context->last_was_foggy_shader = TRUE;
+ new_source = FOGSOURCE_VS;
+ } else if(stateblock->renderState[WINED3DRS_FOGTABLEMODE] == WINED3DFOG_NONE) {
+ context->last_was_foggy_shader = FALSE;
+ if(stateblock->renderState[WINED3DRS_FOGVERTEXMODE] == WINED3DFOG_NONE || context->last_was_rhw) {
+ new_source = FOGSOURCE_COORD;
+ } else {
+ new_source = FOGSOURCE_FFP;
+ }
+ } else {
+ context->last_was_foggy_shader = FALSE;
+ new_source = FOGSOURCE_FFP;
+ }
+ if(new_source != context->fog_source) {
+ context->fog_source = new_source;
+ state_fogstartend(STATE_RENDER(WINED3DRS_FOGSTART), stateblock, context);
+ }
}
static void textransform(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
{ STATE_RENDER(WINED3DRS_FOGENABLE), { STATE_RENDER(WINED3DRS_FOGENABLE), state_arbfp_fog }, 0 },
{ STATE_RENDER(WINED3DRS_FOGTABLEMODE), { STATE_RENDER(WINED3DRS_FOGENABLE), state_arbfp_fog }, 0 },
{ STATE_RENDER(WINED3DRS_FOGVERTEXMODE), { STATE_RENDER(WINED3DRS_FOGENABLE), state_arbfp_fog }, 0 },
+ { STATE_RENDER(WINED3DRS_FOGSTART), { STATE_RENDER(WINED3DRS_FOGSTART), state_fogstartend }, 0 },
+ { STATE_RENDER(WINED3DRS_FOGEND), { STATE_RENDER(WINED3DRS_FOGSTART), state_fogstartend }, 0 },
{ STATE_RENDER(WINED3DRS_SRGBWRITEENABLE), { STATE_PIXELSHADER, fragment_prog_arbfp }, 0 },
+ { STATE_RENDER(WINED3DRS_FOGCOLOR), { STATE_RENDER(WINED3DRS_FOGCOLOR), state_fogcolor }, 0 },
+ { STATE_RENDER(WINED3DRS_FOGDENSITY), { STATE_RENDER(WINED3DRS_FOGDENSITY), state_fogdensity }, 0 },
{STATE_TEXTURESTAGE(0,WINED3DTSS_TEXTURETRANSFORMFLAGS),{STATE_TEXTURESTAGE(0, WINED3DTSS_TEXTURETRANSFORMFLAGS), textransform }, 0 },
{STATE_TEXTURESTAGE(1,WINED3DTSS_TEXTURETRANSFORMFLAGS),{STATE_TEXTURESTAGE(1, WINED3DTSS_TEXTURETRANSFORMFLAGS), textransform }, 0 },
{STATE_TEXTURESTAGE(2,WINED3DTSS_TEXTURETRANSFORMFLAGS),{STATE_TEXTURESTAGE(2, WINED3DTSS_TEXTURETRANSFORMFLAGS), textransform }, 0 },
const char *tex, *texinstr;
if (yuv_fixup == YUV_FIXUP_UYVY) {
- chroma = 'r';
- *luminance = 'a';
+ chroma = 'x';
+ *luminance = 'w';
} else {
- chroma = 'a';
- *luminance = 'r';
+ chroma = 'w';
+ *luminance = 'x';
}
switch(textype) {
case GL_TEXTURE_2D: tex = "2D"; texinstr = "TXP"; break;
* So we have to get the sampling x position in non-normalized coordinates in integers
*/
if(textype != GL_TEXTURE_RECTANGLE_ARB) {
- shader_addline(buffer, "MUL texcrd.rg, fragment.texcoord[0], size.x;\n");
- shader_addline(buffer, "MOV texcrd.a, size.x;\n");
+ shader_addline(buffer, "MUL texcrd.xy, fragment.texcoord[0], size.x;\n");
+ shader_addline(buffer, "MOV texcrd.w, size.x;\n");
} else {
shader_addline(buffer, "MOV texcrd, fragment.texcoord[0];\n");
}
/* Put the value into either of the chroma values */
shader_addline(buffer, "SGE temp.x, texcrd2.x, coef.y;\n");
- shader_addline(buffer, "MUL chroma.r, luminance.%c, temp.x;\n", chroma);
+ shader_addline(buffer, "MUL chroma.x, luminance.%c, temp.x;\n", chroma);
shader_addline(buffer, "SLT temp.x, texcrd2.x, coef.y;\n");
- shader_addline(buffer, "MUL chroma.g, luminance.%c, temp.x;\n", chroma);
+ shader_addline(buffer, "MUL chroma.y, luminance.%c, temp.x;\n", chroma);
/* Sample pixel 2. If we read an even pixel(SLT above returned 1), sample
* the pixel right to the current one. Otherwise, sample the left pixel.
/* Put the value into the other chroma */
shader_addline(buffer, "SGE temp.x, texcrd2.x, coef.y;\n");
- shader_addline(buffer, "MAD chroma.g, luminance.%c, temp.x, chroma.g;\n", chroma);
+ shader_addline(buffer, "MAD chroma.y, luminance.%c, temp.x, chroma.y;\n", chroma);
shader_addline(buffer, "SLT temp.x, texcrd2.x, coef.y;\n");
- shader_addline(buffer, "MAD chroma.r, luminance.%c, temp.x, chroma.r;\n", chroma);
+ shader_addline(buffer, "MAD chroma.x, luminance.%c, temp.x, chroma.x;\n", chroma);
/* TODO: If filtering is enabled, sample a 2nd pair of pixels left or right of
* the current one and lerp the two U and V values
}
/* Read the texture, put the result into the output register */
shader_addline(buffer, "TEX temp, texcrd, texture[0], %s;\n", tex);
- shader_addline(buffer, "MOV chroma.r, temp.a;\n");
+ shader_addline(buffer, "MOV chroma.x, temp.w;\n");
/* The other chroma value is 1/6th of the texture lower, from 5/6th to 6/6th
* No need to clamp because we're just reusing the already clamped value from above
shader_addline(buffer, "MAD texcrd.y, size.y, coef.w, texcrd.y;\n");
}
shader_addline(buffer, "TEX temp, texcrd, texture[0], %s;\n", tex);
- shader_addline(buffer, "MOV chroma.g, temp.a;\n");
+ shader_addline(buffer, "MOV chroma.y, temp.w;\n");
/* Sample the luminance value. It is in the top 2/3rd of the texture, so scale the y coordinate.
* Clamp the y coordinate to prevent the chroma values from bleeding into the sampled luminance
shader_addline(buffer, "MIN texcrd.y, temp.y, texcrd.y;\n");
shader_addline(buffer, "TEX luminance, texcrd, texture[0], %s;\n", tex);
} else {
- /* Reading from texture_rectangles is pretty streightforward, just use the unmodified
+ /* Reading from texture_rectangles is pretty straightforward, just use the unmodified
* texture coordinate. It is still a good idea to clamp it though, since the opengl texture
* is bigger
*/
struct arbfp_blit_priv *priv = (struct arbfp_blit_priv *) device->blit_priv;
/* Shader header */
- buffer.bsize = 0;
- buffer.lineNo = 0;
- buffer.newline = TRUE;
- buffer.buffer = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, SHADER_PGMSIZE);
+ shader_buffer_init(&buffer);
ENTER_GL();
GL_EXTCALL(glGenProgramsARB(1, &shader));
checkGLcall("glBindProgramARB(GL_FRAGMENT_PROGRAM_ARB, shader)");
LEAVE_GL();
if(!shader) {
- HeapFree(GetProcessHeap(), 0, buffer.buffer);
+ shader_buffer_free(&buffer);
return 0;
}
* contains the luminance and alpha the chroma. With UYVY it is vice versa. Thus
* take the format into account when generating the read swizzles
*
- * Reading the Y value is streightforward - just sample the texture. The hardware
+ * Reading the Y value is straightforward - just sample the texture. The hardware
* takes care of filtering in the horizontal and vertical direction.
*
* Reading the U and V values is harder. We have to avoid filtering horizontally,
case YUV_FIXUP_YUY2:
if (!gen_planar_yuv_read(&buffer, yuv_fixup, textype, &luminance_component))
{
- HeapFree(GetProcessHeap(), 0, buffer.buffer);
+ shader_buffer_free(&buffer);
return 0;
}
break;
case YUV_FIXUP_YV12:
if (!gen_yv12_read(&buffer, textype, &luminance_component))
{
- HeapFree(GetProcessHeap(), 0, buffer.buffer);
+ shader_buffer_free(&buffer);
return 0;
}
break;
default:
FIXME("Unsupported YUV fixup %#x\n", yuv_fixup);
- HeapFree(GetProcessHeap(), 0, buffer.buffer);
+ shader_buffer_free(&buffer);
return 0;
}
* http://www.fourcc.org/fccyvrgb.php. Note that the chroma
* ranges from -0.5 to 0.5
*/
- shader_addline(&buffer, "SUB chroma.rg, chroma, coef.y;\n");
+ shader_addline(&buffer, "SUB chroma.xy, chroma, coef.y;\n");
- shader_addline(&buffer, "MAD result.color.r, chroma.r, yuv_coef.x, luminance.%c;\n", luminance_component);
- shader_addline(&buffer, "MAD temp.r, -chroma.g, yuv_coef.y, luminance.%c;\n", luminance_component);
- shader_addline(&buffer, "MAD result.color.g, -chroma.r, yuv_coef.z, temp.r;\n");
- shader_addline(&buffer, "MAD result.color.b, chroma.g, yuv_coef.w, luminance.%c;\n", luminance_component);
+ shader_addline(&buffer, "MAD result.color.x, chroma.x, yuv_coef.x, luminance.%c;\n", luminance_component);
+ shader_addline(&buffer, "MAD temp.x, -chroma.y, yuv_coef.y, luminance.%c;\n", luminance_component);
+ shader_addline(&buffer, "MAD result.color.y, -chroma.x, yuv_coef.z, temp.x;\n");
+ shader_addline(&buffer, "MAD result.color.z, chroma.y, yuv_coef.w, luminance.%c;\n", luminance_component);
shader_addline(&buffer, "END\n");
ENTER_GL();
FIXME("Fragment program error at position %d: %s\n", pos,
debugstr_a((const char *)glGetString(GL_PROGRAM_ERROR_STRING_ARB)));
}
- HeapFree(GetProcessHeap(), 0, buffer.buffer);
+ shader_buffer_free(&buffer);
LEAVE_GL();
switch (yuv_fixup)
}
}
+static const char *debug_op(GLuint op) {
+ switch(op) {
+ case GL_MOV_ATI: return "GL_MOV_ATI";
+ case GL_ADD_ATI: return "GL_ADD_ATI";
+ case GL_MUL_ATI: return "GL_MUL_ATI";
+ case GL_SUB_ATI: return "GL_SUB_ATI";
+ case GL_DOT3_ATI: return "GL_DOT3_ATI";
+ case GL_DOT4_ATI: return "GL_DOT4_ATI";
+ case GL_MAD_ATI: return "GL_MAD_ATI";
+ case GL_LERP_ATI: return "GL_LERP_ATI";
+ case GL_CND_ATI: return "GL_CND_ATI";
+ case GL_CND0_ATI: return "GL_CND0_ATI";
+ case GL_DOT2_ADD_ATI: return "GL_DOT2_ADD_ATI";
+ default: return "unexpected op";
+ }
+}
+
+static const char *debug_mask(GLuint mask) {
+ switch(mask) {
+ case GL_NONE: return "GL_NONE";
+ case GL_RED_BIT_ATI: return "GL_RED_BIT_ATI";
+ case GL_GREEN_BIT_ATI: return "GL_GREEN_BIT_ATI";
+ case GL_BLUE_BIT_ATI: return "GL_BLUE_BIT_ATI";
+ case GL_RED_BIT_ATI | GL_GREEN_BIT_ATI: return "GL_RED_BIT_ATI | GL_GREEN_BIT_ATI";
+ case GL_RED_BIT_ATI | GL_BLUE_BIT_ATI: return "GL_RED_BIT_ATI | GL_BLUE_BIT_ATI";
+ case GL_GREEN_BIT_ATI | GL_BLUE_BIT_ATI:return "GL_GREEN_BIT_ATI | GL_BLUE_BIT_ATI";
+ case GL_RED_BIT_ATI | GL_GREEN_BIT_ATI | GL_BLUE_BIT_ATI:return "GL_RED_BIT_ATI | GL_GREEN_BIT_ATI | GL_BLUE_BIT_ATI";
+ default: return "Unexpected writemask";
+ }
+}
#define GLINFO_LOCATION (*gl_info)
+
+static void wrap_op1(const WineD3D_GL_Info *gl_info, GLuint op, GLuint dst, GLuint dstMask, GLuint dstMod,
+ GLuint arg1, GLuint arg1Rep, GLuint arg1Mod) {
+ if(dstMask == GL_ALPHA) {
+ TRACE("glAlphaFragmentOp1ATI(%s, %s, %s, %s, %s, %s)\n", debug_op(op), debug_register(dst), debug_dstmod(dstMod),
+ debug_register(arg1), debug_rep(arg1Rep), debug_argmod(arg1Mod));
+ GL_EXTCALL(glAlphaFragmentOp1ATI(op, dst, dstMod, arg1, arg1Rep, arg1Mod));
+ } else {
+ TRACE("glColorFragmentOp1ATI(%s, %s, %s, %s, %s, %s, %s)\n", debug_op(op), debug_register(dst),
+ debug_mask(dstMask), debug_dstmod(dstMod),
+ debug_register(arg1), debug_rep(arg1Rep), debug_argmod(arg1Mod));
+ GL_EXTCALL(glColorFragmentOp1ATI(op, dst, dstMask, dstMod, arg1, arg1Rep, arg1Mod));
+ }
+}
+
+static void wrap_op2(const WineD3D_GL_Info *gl_info, GLuint op, GLuint dst, GLuint dstMask, GLuint dstMod,
+ GLuint arg1, GLuint arg1Rep, GLuint arg1Mod,
+ GLuint arg2, GLuint arg2Rep, GLuint arg2Mod) {
+ if(dstMask == GL_ALPHA) {
+ TRACE("glAlphaFragmentOp2ATI(%s, %s, %s, %s, %s, %s, %s, %s, %s)\n", debug_op(op), debug_register(dst), debug_dstmod(dstMod),
+ debug_register(arg1), debug_rep(arg1Rep), debug_argmod(arg1Mod),
+ debug_register(arg2), debug_rep(arg2Rep), debug_argmod(arg2Mod));
+ GL_EXTCALL(glAlphaFragmentOp2ATI(op, dst, dstMod, arg1, arg1Rep, arg1Mod, arg2, arg2Rep, arg2Mod));
+ } else {
+ TRACE("glColorFragmentOp2ATI(%s, %s, %s, %s, %s, %s, %s, %s, %s, %s)\n", debug_op(op), debug_register(dst),
+ debug_mask(dstMask), debug_dstmod(dstMod),
+ debug_register(arg1), debug_rep(arg1Rep), debug_argmod(arg1Mod),
+ debug_register(arg2), debug_rep(arg2Rep), debug_argmod(arg2Mod));
+ GL_EXTCALL(glColorFragmentOp2ATI(op, dst, dstMask, dstMod, arg1, arg1Rep, arg1Mod, arg2, arg2Rep, arg2Mod));
+ }
+}
+
+static void wrap_op3(const WineD3D_GL_Info *gl_info, GLuint op, GLuint dst, GLuint dstMask, GLuint dstMod,
+ GLuint arg1, GLuint arg1Rep, GLuint arg1Mod,
+ GLuint arg2, GLuint arg2Rep, GLuint arg2Mod,
+ GLuint arg3, GLuint arg3Rep, GLuint arg3Mod) {
+ if(dstMask == GL_ALPHA) {
+ /* Leave some free space to fit "GL_NONE, " in to align most alpha and color op lines */
+ TRACE("glAlphaFragmentOp3ATI(%s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s)\n", debug_op(op), debug_register(dst), debug_dstmod(dstMod),
+ debug_register(arg1), debug_rep(arg1Rep), debug_argmod(arg1Mod),
+ debug_register(arg2), debug_rep(arg2Rep), debug_argmod(arg2Mod),
+ debug_register(arg3), debug_rep(arg3Rep), debug_argmod(arg3Mod));
+ GL_EXTCALL(glAlphaFragmentOp3ATI(op, dst, dstMod,
+ arg1, arg1Rep, arg1Mod,
+ arg2, arg2Rep, arg2Mod,
+ arg3, arg3Rep, arg3Mod));
+ } else {
+ TRACE("glColorFragmentOp3ATI(%s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s)\n", debug_op(op), debug_register(dst),
+ debug_mask(dstMask), debug_dstmod(dstMod),
+ debug_register(arg1), debug_rep(arg1Rep), debug_argmod(arg1Mod),
+ debug_register(arg2), debug_rep(arg2Rep), debug_argmod(arg2Mod),
+ debug_register(arg3), debug_rep(arg3Rep), debug_argmod(arg3Mod));
+ GL_EXTCALL(glColorFragmentOp3ATI(op, dst, dstMask, dstMod,
+ arg1, arg1Rep, arg1Mod,
+ arg2, arg2Rep, arg2Mod,
+ arg3, arg3Rep, arg3Mod));
+ }
+}
+
static GLuint register_for_arg(DWORD arg, const WineD3D_GL_Info *gl_info,
unsigned int stage, GLuint *mod, GLuint *rep, GLuint tmparg)
{
if(op[stage].cop != WINED3DTOP_BUMPENVMAP &&
op[stage].cop != WINED3DTOP_BUMPENVMAPLUMINANCE) continue;
+ fixup = op[stage].color_fixup;
if (fixup.x_source != CHANNEL_SOURCE_X || fixup.y_source != CHANNEL_SOURCE_Y)
{
FIXME("Swizzles not implemented\n");
argmodextra_y = fixup.y_sign_fixup ? GL_2X_BIT_ATI | GL_BIAS_BIT_ATI : GL_NONE;
}
- TRACE("glColorFragmentOp3ATI(GL_DOT2_ADD_ATI, GL_REG_%d_ATI, GL_RED_BIT_ATI, GL_NONE, GL_REG_%d_ATI, GL_NONE, %s, ATI_FFP_CONST_BUMPMAT(%d), GL_NONE, GL_NONE, GL_REG_%d_ATI, GL_RED, GL_NONE)\n",
- stage + 1, stage, debug_argmod(argmodextra_x), stage, stage + 1);
- GL_EXTCALL(glColorFragmentOp3ATI(GL_DOT2_ADD_ATI, GL_REG_0_ATI + stage + 1, GL_RED_BIT_ATI, GL_NONE,
- GL_REG_0_ATI + stage, GL_NONE, argmodextra_x,
- ATI_FFP_CONST_BUMPMAT(stage), GL_NONE, GL_2X_BIT_ATI | GL_BIAS_BIT_ATI,
- GL_REG_0_ATI + stage + 1, GL_RED, GL_NONE));
+ wrap_op3(gl_info, GL_DOT2_ADD_ATI, GL_REG_0_ATI + stage + 1, GL_RED_BIT_ATI, GL_NONE,
+ GL_REG_0_ATI + stage, GL_NONE, argmodextra_x,
+ ATI_FFP_CONST_BUMPMAT(stage), GL_NONE, GL_2X_BIT_ATI | GL_BIAS_BIT_ATI,
+ GL_REG_0_ATI + stage + 1, GL_RED, GL_NONE);
/* FIXME: How can I make GL_DOT2_ADD_ATI read the factors from blue and alpha? It defaults to red and green,
* and it is fairly easy to make it read GL_BLUE or BL_ALPHA, but I can't get an R * B + G * A. So we're wasting
* NOTE: GL_BLUE | GL_ALPHA is not possible. It doesn't throw a compilation error, but an OR operation on the
* constants doesn't make sense, considering their values.
*/
- TRACE("glColorFragmentOp1ATI(GL_MOV_ATI, GL_REG_5_ATI, GL_RED_BIT_ATI, GL_NONE, ATI_FFP_CONST_BUMPMAT(%d), GL_BLUE, GL_NONE)\n", stage);
- GL_EXTCALL(glColorFragmentOp1ATI(GL_MOV_ATI, GL_REG_5_ATI, GL_RED_BIT_ATI, GL_NONE,
- ATI_FFP_CONST_BUMPMAT(stage), GL_BLUE, GL_NONE));
- TRACE("glColorFragmentOp1ATI(GL_MOV_ATI, GL_REG_5_ATI, GL_GREEN_BIT_ATI, GL_NONE, ATI_FFP_CONST_BUMPMAT(%d), GL_ALPHA, GL_NONE)\n", stage);
- GL_EXTCALL(glColorFragmentOp1ATI(GL_MOV_ATI, GL_REG_5_ATI, GL_GREEN_BIT_ATI, GL_NONE,
- ATI_FFP_CONST_BUMPMAT(stage), GL_ALPHA, GL_NONE));
- TRACE("glColorFragmentOp3ATI(GL_DOT2_ADD_ATI, GL_REG_%d_ATI, GL_GREEN_BIT_ATI, GL_NONE, GL_REG_%d_ATI, GL_NONE, %s, GL_REG_5_ATI, GL_NONE, GL_NONE, GL_REG_%d_ATI, GL_GREEN, GL_NONE)\n",
- stage + 1, stage, debug_argmod(argmodextra_y), stage + 1);
- GL_EXTCALL(glColorFragmentOp3ATI(GL_DOT2_ADD_ATI, GL_REG_0_ATI + stage + 1, GL_GREEN_BIT_ATI, GL_NONE,
- GL_REG_0_ATI + stage, GL_NONE, argmodextra_y,
- GL_REG_5_ATI, GL_NONE, GL_2X_BIT_ATI | GL_BIAS_BIT_ATI,
- GL_REG_0_ATI + stage + 1, GL_GREEN, GL_NONE));
+ wrap_op1(gl_info, GL_MOV_ATI, GL_REG_5_ATI, GL_RED_BIT_ATI, GL_NONE,
+ ATI_FFP_CONST_BUMPMAT(stage), GL_BLUE, GL_NONE);
+ wrap_op1(gl_info, GL_MOV_ATI, GL_REG_5_ATI, GL_GREEN_BIT_ATI, GL_NONE,
+ ATI_FFP_CONST_BUMPMAT(stage), GL_ALPHA, GL_NONE);
+ wrap_op3(gl_info, GL_DOT2_ADD_ATI, GL_REG_0_ATI + stage + 1, GL_GREEN_BIT_ATI, GL_NONE,
+ GL_REG_0_ATI + stage, GL_NONE, argmodextra_y,
+ GL_REG_5_ATI, GL_NONE, GL_2X_BIT_ATI | GL_BIAS_BIT_ATI,
+ GL_REG_0_ATI + stage + 1, GL_GREEN, GL_NONE);
}
/* Pass 3: Generate sampling instructions for regular textures */
if(op[stage].cop == WINED3DTOP_DISABLE) {
if(stage == 0) {
/* Handle complete texture disabling gracefully */
- TRACE("glColorFragmentOp1ATI(GL_MOV_ATI, GL_REG_0_ATI, GL_NONE, GL_NONE, GL_PRIMARY_COLOR, GL_NONE, GL_NONE)\n");
- GL_EXTCALL(glColorFragmentOp1ATI(GL_MOV_ATI, GL_REG_0_ATI, GL_NONE, GL_NONE,
- GL_PRIMARY_COLOR, GL_NONE, GL_NONE));
- TRACE("glAlphaFragmentOp1ATI(GL_MOV_ATI, GL_REG_0_ATI, GL_NONE, GL_PRIMARY_COLOR, GL_NONE, GL_NONE)\n");
- GL_EXTCALL(glAlphaFragmentOp1ATI(GL_MOV_ATI, GL_REG_0_ATI, GL_NONE,
- GL_PRIMARY_COLOR, GL_NONE, GL_NONE));
+ wrap_op1(gl_info, GL_MOV_ATI, GL_REG_0_ATI, GL_NONE, GL_NONE,
+ GL_PRIMARY_COLOR, GL_NONE, GL_NONE);
+ wrap_op1(gl_info, GL_MOV_ATI, GL_REG_0_ATI, GL_ALPHA, GL_NONE,
+ GL_PRIMARY_COLOR, GL_NONE, GL_NONE);
}
break;
}
argmod1 = argmod2;
rep1 = rep2;
case WINED3DTOP_SELECTARG1:
- TRACE("glColorFragmentOp1ATI(GL_MOV_ATI, %s, GL_NONE, GL_NONE, %s, %s, %s)\n",
- debug_register(dstreg), debug_register(arg1), debug_rep(rep1), debug_argmod(argmod1));
- GL_EXTCALL(glColorFragmentOp1ATI(GL_MOV_ATI, dstreg, GL_NONE, GL_NONE,
- arg1, rep1, argmod1));
+ wrap_op1(gl_info, GL_MOV_ATI, dstreg, GL_NONE, GL_NONE,
+ arg1, rep1, argmod1);
break;
case WINED3DTOP_MODULATE4X:
if(dstmod == GL_NONE) dstmod = GL_2X_BIT_ATI;
dstmod |= GL_SATURATE_BIT_ATI;
case WINED3DTOP_MODULATE:
- TRACE("glColorFragmentOp2ATI(GL_MUL_ATI, %s, GL_NONE, %s, %s, %s, %s, %s, %s, %s)\n",
- debug_register(dstreg), debug_dstmod(dstmod),
- debug_register(arg1), debug_rep(rep1), debug_argmod(argmod1),
- debug_register(arg2), debug_rep(rep2), debug_argmod(argmod2));
- GL_EXTCALL(glColorFragmentOp2ATI(GL_MUL_ATI, dstreg, GL_NONE, dstmod,
- arg1, rep1, argmod1,
- arg2, rep2, argmod2));
+ wrap_op2(gl_info, GL_MUL_ATI, dstreg, GL_NONE, dstmod,
+ arg1, rep1, argmod1,
+ arg2, rep2, argmod2);
break;
case WINED3DTOP_ADDSIGNED2X:
argmodextra = GL_BIAS_BIT_ATI;
case WINED3DTOP_ADD:
dstmod |= GL_SATURATE_BIT_ATI;
- TRACE("glColorFragmentOp2ATI(GL_ADD_ATI, %s, GL_NONE, %s, %s, %s, %s, %s, %s, %s)\n",
- debug_register(dstreg), debug_dstmod(dstmod),
- debug_register(arg1), debug_rep(rep1), debug_argmod(argmod1),
- debug_register(arg2), debug_rep(rep2), debug_argmod(argmodextra | argmod2));
- GL_EXTCALL(glColorFragmentOp2ATI(GL_ADD_ATI, GL_REG_0_ATI, GL_NONE, dstmod,
- arg1, rep1, argmod1,
- arg2, rep2, argmodextra | argmod2));
+ wrap_op2(gl_info, GL_ADD_ATI, GL_REG_0_ATI, GL_NONE, dstmod,
+ arg1, rep1, argmod1,
+ arg2, rep2, argmodextra | argmod2);
break;
case WINED3DTOP_SUBTRACT:
dstmod |= GL_SATURATE_BIT_ATI;
- TRACE("glColorFragmentOp2ATI(GL_SUB_ATI, %s, GL_NONE, %s, %s, %s, %s, %s, %s, %s)\n",
- debug_register(dstreg), debug_dstmod(dstmod),
- debug_register(arg1), debug_rep(rep1), debug_argmod(argmod1),
- debug_register(arg2), debug_rep(rep2), debug_argmod(argmod2));
- GL_EXTCALL(glColorFragmentOp2ATI(GL_SUB_ATI, dstreg, GL_NONE, dstmod,
- arg1, rep1, argmod1,
- arg2, rep2, argmod2));
+ wrap_op2(gl_info, GL_SUB_ATI, dstreg, GL_NONE, dstmod,
+ arg1, rep1, argmod1,
+ arg2, rep2, argmod2);
break;
case WINED3DTOP_ADDSMOOTH:
argmodextra = argmod1 & GL_COMP_BIT_ATI ? argmod1 & ~GL_COMP_BIT_ATI : argmod1 | GL_COMP_BIT_ATI;
- TRACE("glColorFragmentOp3ATI(GL_MAD_ATI, %s, GL_NONE, GL_SATURATE_BIT_ATI, %s, %s, %s, %s, %s, %s, %s, %s, %s)\n",
- debug_register(dstreg),
- debug_register(arg2), debug_rep(rep2), debug_argmod(argmod2),
- debug_register(arg1), debug_rep(rep1), debug_argmod(argmodextra),
- debug_register(arg1), debug_rep(rep1), debug_argmod(argmod1));
/* Dst = arg1 + * arg2(1 -arg 1)
* = arg2 * (1 - arg1) + arg1
*/
- GL_EXTCALL(glColorFragmentOp3ATI(GL_MAD_ATI, dstreg, GL_NONE, GL_SATURATE_BIT_ATI,
- arg2, rep2, argmod2,
- arg1, rep1, argmodextra,
- arg1, rep1, argmod1));
+ wrap_op3(gl_info, GL_MAD_ATI, dstreg, GL_NONE, GL_SATURATE_BIT_ATI,
+ arg2, rep2, argmod2,
+ arg1, rep1, argmodextra,
+ arg1, rep1, argmod1);
break;
case WINED3DTOP_BLENDCURRENTALPHA:
if(extrarg == GL_NONE) extrarg = register_for_arg(WINED3DTA_TEXTURE, gl_info, stage, NULL, NULL, -1);
case WINED3DTOP_BLENDDIFFUSEALPHA:
if(extrarg == GL_NONE) extrarg = register_for_arg(WINED3DTA_DIFFUSE, gl_info, stage, NULL, NULL, -1);
- TRACE("glColorFragmentOp3ATI(GL_LERP_ATI, %s, GL_NONE, GL_NONE, %s, GL_ALPHA, GL_NONE, %s, %s, %s, %s, %s, %s)\n",
- debug_register(dstreg),
- debug_register(extrarg),
- debug_register(arg1), debug_rep(rep1), debug_argmod(argmod1),
- debug_register(arg2), debug_rep(rep2), debug_argmod(argmod2));
- GL_EXTCALL(glColorFragmentOp3ATI(GL_LERP_ATI, dstreg, GL_NONE, GL_NONE,
- extrarg, GL_ALPHA, GL_NONE,
- arg1, rep1, argmod1,
- arg2, rep2, argmod2));
+ wrap_op3(gl_info, GL_LERP_ATI, dstreg, GL_NONE, GL_NONE,
+ extrarg, GL_ALPHA, GL_NONE,
+ arg1, rep1, argmod1,
+ arg2, rep2, argmod2);
break;
case WINED3DTOP_BLENDTEXTUREALPHAPM:
arg0 = register_for_arg(WINED3DTA_TEXTURE, gl_info, stage, NULL, NULL, -1);
- TRACE("glColorFragmentOp3ATI(GL_MAD_ATI, %s, GL_NONE, GL_NONE, %s, %s, %s, %s, GL_ALPHA, GL_COMP_BIT_ATI, %s, %s, %s)\n",
- debug_register(dstreg),
- debug_register(arg2), debug_rep(rep2), debug_argmod(argmod2),
- debug_register(arg0),
- debug_register(arg1), debug_rep(rep1), debug_argmod(argmod1));
- GL_EXTCALL(glColorFragmentOp3ATI(GL_MAD_ATI, dstreg, GL_NONE, GL_NONE,
- arg2, rep2, argmod2,
- arg0, GL_ALPHA, GL_COMP_BIT_ATI,
- arg1, rep1, argmod1));
+ wrap_op3(gl_info, GL_MAD_ATI, dstreg, GL_NONE, GL_NONE,
+ arg2, rep2, argmod2,
+ arg0, GL_ALPHA, GL_COMP_BIT_ATI,
+ arg1, rep1, argmod1);
break;
/* D3DTOP_PREMODULATE ???? */
argmodextra = argmod1 & GL_COMP_BIT_ATI ? argmod1 & ~GL_COMP_BIT_ATI : argmod1 | GL_COMP_BIT_ATI;
case WINED3DTOP_MODULATEALPHA_ADDCOLOR:
if(!argmodextra) argmodextra = argmod1;
- TRACE("glColorFragmentOp3ATI(GL_MAD_ATI, %s, GL_NONE, GL_SATURATE_BIT_ATI, %s, %s, %s, %s, GL_ALPHA, %s, %s, %s, %s)\n",
- debug_register(dstreg),
- debug_register(arg2), debug_rep(rep2), debug_argmod(argmod2),
- debug_register(arg1), debug_argmod(argmodextra), debug_register(arg1), debug_rep(rep1), debug_argmod(arg1));
- GL_EXTCALL(glColorFragmentOp3ATI(GL_MAD_ATI, dstreg, GL_NONE, GL_SATURATE_BIT_ATI,
- arg2, rep2, argmod2,
- arg1, GL_ALPHA, argmodextra,
- arg1, rep1, argmod1));
+ wrap_op3(gl_info, GL_MAD_ATI, dstreg, GL_NONE, GL_SATURATE_BIT_ATI,
+ arg2, rep2, argmod2,
+ arg1, GL_ALPHA, argmodextra,
+ arg1, rep1, argmod1);
break;
case WINED3DTOP_MODULATEINVCOLOR_ADDALPHA:
argmodextra = argmod1 & GL_COMP_BIT_ATI ? argmod1 & ~GL_COMP_BIT_ATI : argmod1 | GL_COMP_BIT_ATI;
case WINED3DTOP_MODULATECOLOR_ADDALPHA:
if(!argmodextra) argmodextra = argmod1;
- TRACE("glColorFragmentOp3ATI(GL_MAD_ATI, %s, GL_NONE, GL_SATURATE_BIT_ATI, %s, %s, %s, %s, %s, %s, %s, GL_ALPHA, %s)\n",
- debug_register(dstreg),
- debug_register(arg2), debug_rep(rep2), debug_argmod(argmod2),
- debug_register(arg1), debug_rep(rep1), debug_argmod(argmodextra),
- debug_register(arg1), debug_argmod(argmod1));
- GL_EXTCALL(glColorFragmentOp3ATI(GL_MAD_ATI, dstreg, GL_NONE, GL_SATURATE_BIT_ATI,
- arg2, rep2, argmod2,
- arg1, rep1, argmodextra,
- arg1, GL_ALPHA, argmod1));
+ wrap_op3(gl_info, GL_MAD_ATI, dstreg, GL_NONE, GL_SATURATE_BIT_ATI,
+ arg2, rep2, argmod2,
+ arg1, rep1, argmodextra,
+ arg1, GL_ALPHA, argmod1);
break;
case WINED3DTOP_DOTPRODUCT3:
- TRACE("glColorFragmentOp2ATI(GL_DOT3_ATI, %s, GL_NONE, GL_4X_BIT_ATI | GL_SATURATE_BIT_ATI, %s, %s, %s, %s, %s, %s)\n",
- debug_register(dstreg),
- debug_register(arg1), debug_rep(rep1), debug_argmod(argmod1 | GL_BIAS_BIT_ATI),
- debug_register(arg2), debug_rep(rep2), debug_argmod(argmod2 | GL_BIAS_BIT_ATI));
- GL_EXTCALL(glColorFragmentOp2ATI(GL_DOT3_ATI, dstreg, GL_NONE, GL_4X_BIT_ATI | GL_SATURATE_BIT_ATI,
- arg1, rep1, argmod1 | GL_BIAS_BIT_ATI,
- arg2, rep2, argmod2 | GL_BIAS_BIT_ATI));
+ wrap_op2(gl_info, GL_DOT3_ATI, dstreg, GL_NONE, GL_4X_BIT_ATI | GL_SATURATE_BIT_ATI,
+ arg1, rep1, argmod1 | GL_BIAS_BIT_ATI,
+ arg2, rep2, argmod2 | GL_BIAS_BIT_ATI);
break;
case WINED3DTOP_MULTIPLYADD:
- TRACE("glColorFragmentOp3ATI(GL_MAD_ATI, %s, GL_NONE, GL_SATURATE_BIT_ATI, %s, %s, %s, %s, %s, %s, %s, %s, %s)\n",
- debug_register(dstreg),
- debug_register(arg1), debug_rep(rep1), debug_argmod(argmod1),
- debug_register(arg2), debug_rep(rep2), debug_argmod(argmod2),
- debug_register(arg0), debug_rep(rep0), debug_argmod(argmod0));
- GL_EXTCALL(glColorFragmentOp3ATI(GL_MAD_ATI, dstreg, GL_NONE, GL_SATURATE_BIT_ATI,
- arg1, rep1, argmod1,
- arg2, rep2, argmod2,
- arg0, rep0, argmod0));
+ wrap_op3(gl_info, GL_MAD_ATI, dstreg, GL_NONE, GL_SATURATE_BIT_ATI,
+ arg1, rep1, argmod1,
+ arg2, rep2, argmod2,
+ arg0, rep0, argmod0);
break;
case WINED3DTOP_LERP:
- TRACE("glColorFragmentOp3ATI(GL_LERP_ATI, %s, GL_NONE, GL_NONE, %s, %s, %s, %s, %s, %s, %s, %s, %s)\n",
- debug_register(dstreg),
- debug_register(arg1), debug_rep(rep1), debug_argmod(argmod1),
- debug_register(arg2), debug_rep(rep2), debug_argmod(argmod2),
- debug_register(arg0), debug_rep(rep0), debug_argmod(argmod0));
- GL_EXTCALL(glColorFragmentOp3ATI(GL_LERP_ATI, dstreg, GL_NONE, GL_NONE,
- arg0, rep0, argmod0,
- arg1, rep1, argmod1,
- arg2, rep2, argmod2));
+ wrap_op3(gl_info, GL_LERP_ATI, dstreg, GL_NONE, GL_NONE,
+ arg0, rep0, argmod0,
+ arg1, rep1, argmod1,
+ arg2, rep2, argmod2);
break;
case WINED3DTOP_BUMPENVMAP:
case WINED3DTOP_DISABLE:
/* Get the primary color to the output if on stage 0, otherwise leave register 0 untouched */
if(stage == 0) {
- TRACE("glAlphaFragmentOp1ATI(GL_MOV_ATI, GL_REG_0_ATI, GL_NONE, GL_PRIMARY_COLOR, GL_NONE, GL_NONE)\n");
- GL_EXTCALL(glAlphaFragmentOp1ATI(GL_MOV_ATI, GL_REG_0_ATI, GL_NONE,
- GL_PRIMARY_COLOR, GL_NONE, GL_NONE));
+ wrap_op1(gl_info, GL_MOV_ATI, GL_REG_0_ATI, GL_ALPHA, GL_NONE,
+ GL_PRIMARY_COLOR, GL_NONE, GL_NONE);
}
break;
arg1 = arg2;
argmod1 = argmod2;
case WINED3DTOP_SELECTARG1:
- TRACE("glAlphaFragmentOp1ATI(GL_MOV_ATI, %s, GL_NONE, %s, GL_NONE, %s)\n",
- debug_register(dstreg),
- debug_register(arg1), debug_argmod(argmod1));
- GL_EXTCALL(glAlphaFragmentOp1ATI(GL_MOV_ATI, dstreg, GL_NONE,
- arg1, GL_NONE, argmod1));
+ wrap_op1(gl_info, GL_MOV_ATI, dstreg, GL_ALPHA, GL_NONE,
+ arg1, GL_NONE, argmod1);
break;
case WINED3DTOP_MODULATE4X:
if(dstmod == GL_NONE) dstmod = GL_2X_BIT_ATI;
dstmod |= GL_SATURATE_BIT_ATI;
case WINED3DTOP_MODULATE:
- TRACE("glAlphaFragmentOp2ATI(GL_MUL_ATI, %s, %s, %s, GL_NONE, %s, %s, GL_NONE, %s)\n",
- debug_register(dstreg), debug_dstmod(dstmod),
- debug_register(arg1), debug_argmod(argmod1),
- debug_register(arg2), debug_argmod(argmod2));
- GL_EXTCALL(glAlphaFragmentOp2ATI(GL_MUL_ATI, dstreg, dstmod,
- arg1, GL_NONE, argmod1,
- arg2, GL_NONE, argmod2));
+ wrap_op2(gl_info, GL_MUL_ATI, dstreg, GL_ALPHA, dstmod,
+ arg1, GL_NONE, argmod1,
+ arg2, GL_NONE, argmod2);
break;
case WINED3DTOP_ADDSIGNED2X:
argmodextra = GL_BIAS_BIT_ATI;
case WINED3DTOP_ADD:
dstmod |= GL_SATURATE_BIT_ATI;
- TRACE("glAlphaFragmentOp2ATI(GL_ADD_ATI, %s, %s, %s, GL_NONE, %s, %s, GL_NONE, %s)\n",
- debug_register(dstreg), debug_dstmod(dstmod),
- debug_register(arg1), debug_argmod(argmod1),
- debug_register(arg2), debug_argmod(argmodextra | argmod2));
- GL_EXTCALL(glAlphaFragmentOp2ATI(GL_ADD_ATI, dstreg, dstmod,
- arg1, GL_NONE, argmod1,
- arg2, GL_NONE, argmodextra | argmod2));
+ wrap_op2(gl_info, GL_ADD_ATI, dstreg, GL_ALPHA, dstmod,
+ arg1, GL_NONE, argmod1,
+ arg2, GL_NONE, argmodextra | argmod2);
break;
case WINED3DTOP_SUBTRACT:
dstmod |= GL_SATURATE_BIT_ATI;
- TRACE("glAlphaFragmentOp2ATI(GL_SUB_ATI, %s, GL_NONE, %s, %s, GL_NONE, %s, %s, GL_NONE, %s)\n",
- debug_register(dstreg), debug_dstmod(dstmod),
- debug_register(arg1), debug_argmod(argmod1),
- debug_register(arg2), debug_argmod(argmod2));
- GL_EXTCALL(glAlphaFragmentOp2ATI(GL_SUB_ATI, dstreg, dstmod,
- arg1, GL_NONE, argmod1,
- arg2, GL_NONE, argmod2));
+ wrap_op2(gl_info, GL_SUB_ATI, dstreg, GL_ALPHA, dstmod,
+ arg1, GL_NONE, argmod1,
+ arg2, GL_NONE, argmod2);
break;
case WINED3DTOP_ADDSMOOTH:
argmodextra = argmod1 & GL_COMP_BIT_ATI ? argmod1 & ~GL_COMP_BIT_ATI : argmod1 | GL_COMP_BIT_ATI;
- TRACE("glAlphaFragmentOp3ATI(GL_MAD_ATI, %s, GL_SATURATE_BIT_ATI, %s, GL_NONE, %s, %s, GL_NONE, %s, %s, GL_NONE, %s)\n",
- debug_register(dstreg),
- debug_register(arg2), debug_argmod(argmod2),
- debug_register(arg1), debug_argmod(argmodextra),
- debug_register(arg1), debug_argmod(argmod1));
/* Dst = arg1 + * arg2(1 -arg 1)
* = arg2 * (1 - arg1) + arg1
*/
- GL_EXTCALL(glAlphaFragmentOp3ATI(GL_MAD_ATI, dstreg, GL_SATURATE_BIT_ATI,
- arg2, GL_NONE, argmod2,
- arg1, GL_NONE, argmodextra,
- arg1, GL_NONE, argmod1));
+ wrap_op3(gl_info, GL_MAD_ATI, dstreg, GL_ALPHA, GL_SATURATE_BIT_ATI,
+ arg2, GL_NONE, argmod2,
+ arg1, GL_NONE, argmodextra,
+ arg1, GL_NONE, argmod1);
break;
case WINED3DTOP_BLENDCURRENTALPHA:
if(extrarg == GL_NONE) extrarg = register_for_arg(WINED3DTA_TEXTURE, gl_info, stage, NULL, NULL, -1);
case WINED3DTOP_BLENDDIFFUSEALPHA:
if(extrarg == GL_NONE) extrarg = register_for_arg(WINED3DTA_DIFFUSE, gl_info, stage, NULL, NULL, -1);
- TRACE("glAlphaFragmentOp3ATI(GL_LERP_ATI, %s, GL_NONE, %s, GL_ALPHA, GL_NONE, %s, GL_NONE, %s, %s, GL_NONE, %s)\n",
- debug_register(dstreg),
- debug_register(extrarg),
- debug_register(arg1), debug_argmod(argmod1),
- debug_register(arg2), debug_argmod(argmod2));
- GL_EXTCALL(glAlphaFragmentOp3ATI(GL_LERP_ATI, dstreg, GL_NONE,
- extrarg, GL_ALPHA, GL_NONE,
- arg1, GL_NONE, argmod1,
- arg2, GL_NONE, argmod2));
+ wrap_op3(gl_info, GL_LERP_ATI, dstreg, GL_ALPHA, GL_NONE,
+ extrarg, GL_ALPHA, GL_NONE,
+ arg1, GL_NONE, argmod1,
+ arg2, GL_NONE, argmod2);
break;
case WINED3DTOP_BLENDTEXTUREALPHAPM:
arg0 = register_for_arg(WINED3DTA_TEXTURE, gl_info, stage, NULL, NULL, -1);
- TRACE("glAlphaFragmentOp3ATI(GL_MAD_ATI, %s, GL_NONE, %s, GL_NONE, %s, %s, GL_ALPHA, GL_COMP_BIT_ATI, %s, GL_NONE, %s)\n",
- debug_register(dstreg),
- debug_register(arg2), debug_argmod(argmod2),
- debug_register(arg0),
- debug_register(arg1), debug_argmod(argmod1));
- GL_EXTCALL(glAlphaFragmentOp3ATI(GL_MAD_ATI, dstreg, GL_NONE,
- arg2, GL_NONE, argmod2,
- arg0, GL_ALPHA, GL_COMP_BIT_ATI,
- arg1, GL_NONE, argmod1));
+ wrap_op3(gl_info, GL_MAD_ATI, dstreg, GL_ALPHA, GL_NONE,
+ arg2, GL_NONE, argmod2,
+ arg0, GL_ALPHA, GL_COMP_BIT_ATI,
+ arg1, GL_NONE, argmod1);
break;
/* D3DTOP_PREMODULATE ???? */
case WINED3DTOP_DOTPRODUCT3:
- TRACE("glAlphaFragmentOp2ATI(GL_DOT3_ATI, %s, GL_4X_BIT_ATI | GL_SATURATE_BIT_ATI, %s, GL_NONE, %s, %s, GL_NONE, %s)\n",
- debug_register(dstreg),
- debug_register(arg1), debug_argmod(argmod1 | GL_BIAS_BIT_ATI),
- debug_register(arg2), debug_argmod(argmod2 | GL_BIAS_BIT_ATI));
- GL_EXTCALL(glAlphaFragmentOp2ATI(GL_DOT3_ATI, dstreg, GL_4X_BIT_ATI | GL_SATURATE_BIT_ATI,
- arg1, GL_NONE, argmod1 | GL_BIAS_BIT_ATI,
- arg2, GL_NONE, argmod2 | GL_BIAS_BIT_ATI));
+ wrap_op2(gl_info, GL_DOT3_ATI, dstreg, GL_ALPHA, GL_4X_BIT_ATI | GL_SATURATE_BIT_ATI,
+ arg1, GL_NONE, argmod1 | GL_BIAS_BIT_ATI,
+ arg2, GL_NONE, argmod2 | GL_BIAS_BIT_ATI);
break;
case WINED3DTOP_MULTIPLYADD:
- TRACE("glAlphaFragmentOp3ATI(GL_MAD_ATI, %s, GL_SATURATE_BIT_ATI, %s, GL_NONE, %s, %s, GL_NONE, %s, %s, GL_NONE, %s)\n",
- debug_register(dstreg),
- debug_register(arg1), debug_argmod(argmod1),
- debug_register(arg2), debug_argmod(argmod2),
- debug_register(arg0), debug_argmod(argmod0));
- GL_EXTCALL(glAlphaFragmentOp3ATI(GL_MAD_ATI, dstreg, GL_SATURATE_BIT_ATI,
- arg1, GL_NONE, argmod1,
- arg2, GL_NONE, argmod2,
- arg0, GL_NONE, argmod0));
+ wrap_op3(gl_info, GL_MAD_ATI, dstreg, GL_ALPHA, GL_SATURATE_BIT_ATI,
+ arg1, GL_NONE, argmod1,
+ arg2, GL_NONE, argmod2,
+ arg0, GL_NONE, argmod0);
break;
case WINED3DTOP_LERP:
- TRACE("glAlphaFragmentOp3ATI(GL_LERP_ATI, %s, GL_SATURATE_BIT_ATI, %s, GL_NONE, %s, %s, GL_NONE, %s, %s, GL_NONE, %s)\n",
- debug_register(dstreg),
- debug_register(arg1), debug_argmod(argmod1),
- debug_register(arg2), debug_argmod(argmod2),
- debug_register(arg0), debug_argmod(argmod0));
- GL_EXTCALL(glAlphaFragmentOp3ATI(GL_LERP_ATI, dstreg, GL_SATURATE_BIT_ATI,
- arg1, GL_NONE, argmod1,
- arg2, GL_NONE, argmod2,
- arg0, GL_NONE, argmod0));
+ wrap_op3(gl_info, GL_LERP_ATI, dstreg, GL_ALPHA, GL_SATURATE_BIT_ATI,
+ arg1, GL_NONE, argmod1,
+ arg2, GL_NONE, argmod2,
+ arg0, GL_NONE, argmod0);
break;
case WINED3DTOP_MODULATEINVALPHA_ADDCOLOR:
}
static void set_bumpmat(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
- DWORD stage = (state - STATE_TEXTURESTAGE(0, 0)) / WINED3D_HIGHEST_TEXTURE_STATE;
+ DWORD stage = (state - STATE_TEXTURESTAGE(0, 0)) / (WINED3D_HIGHEST_TEXTURE_STATE + 1);
float mat[2][2];
mat[0][0] = *((float *) &stateblock->textureState[stage][WINED3DTSS_BUMPENVMAT00]);
}
}
+static void atifs_apply_pixelshader(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
+ IWineD3DDeviceImpl *device = stateblock->wineD3DDevice;
+ BOOL use_vshader = use_vs(stateblock);
+
+ /* The ATIFS code does not support pixel shaders currently, but we have to provide a state handler
+ * to call shader_select to select a vertex shader if one is applied because the vertex shader state
+ * may defer calling the shader backend if the pshader state is dirty.
+ *
+ * In theory the application should not be able to mark the pixel shader dirty because it cannot
+ * create a shader, and thus has no way to set the state to something != NULL. However, a different
+ * pipeline part may link a different state to its pixelshader handler, thus a pshader state exists
+ * and can be dirtified. Also the pshader is always dirtified at startup, and blitting disables all
+ * shaders and dirtifies all shader states. If atifs can deal with this it keeps the rest of the code
+ * simpler.
+ */
+ if(!isStateDirty(context, device->StateTable[STATE_VSHADER].representative)) {
+ device->shader_backend->shader_select((IWineD3DDevice *)stateblock->wineD3DDevice, FALSE, use_vshader);
+
+ if (!isStateDirty(context, STATE_VERTEXSHADERCONSTANT) && use_vshader) {
+ device->StateTable[STATE_VERTEXSHADERCONSTANT].apply(STATE_VERTEXSHADERCONSTANT, stateblock, context);
+ }
+ }
+}
+
#undef GLINFO_LOCATION
static const struct StateEntryTemplate atifs_fragmentstate_template[] = {
{STATE_RENDER(WINED3DRS_TEXTUREFACTOR), { STATE_RENDER(WINED3DRS_TEXTUREFACTOR), state_texfactor_atifs }, 0 },
+ {STATE_RENDER(WINED3DRS_FOGCOLOR), { STATE_RENDER(WINED3DRS_FOGCOLOR), state_fogcolor }, 0 },
+ {STATE_RENDER(WINED3DRS_FOGDENSITY), { STATE_RENDER(WINED3DRS_FOGDENSITY), state_fogdensity }, 0 },
+ {STATE_RENDER(WINED3DRS_FOGENABLE), { STATE_RENDER(WINED3DRS_FOGENABLE), state_fog_fragpart }, 0 },
+ {STATE_RENDER(WINED3DRS_FOGTABLEMODE), { STATE_RENDER(WINED3DRS_FOGENABLE), state_fog_fragpart }, 0 },
+ {STATE_RENDER(WINED3DRS_FOGVERTEXMODE), { STATE_RENDER(WINED3DRS_FOGENABLE), state_fog_fragpart }, 0 },
+ {STATE_RENDER(WINED3DRS_FOGSTART), { STATE_RENDER(WINED3DRS_FOGSTART), state_fogstartend }, 0 },
+ {STATE_RENDER(WINED3DRS_FOGEND), { STATE_RENDER(WINED3DRS_FOGSTART), state_fogstartend }, 0 },
{STATE_TEXTURESTAGE(0, WINED3DTSS_COLOROP), { STATE_TEXTURESTAGE(0, WINED3DTSS_COLOROP), set_tex_op_atifs }, 0 },
{STATE_TEXTURESTAGE(0, WINED3DTSS_COLORARG1), { STATE_TEXTURESTAGE(0, WINED3DTSS_COLOROP), set_tex_op_atifs }, 0 },
{STATE_TEXTURESTAGE(0, WINED3DTSS_COLORARG2), { STATE_TEXTURESTAGE(0, WINED3DTSS_COLOROP), set_tex_op_atifs }, 0 },
{STATE_TEXTURESTAGE(5,WINED3DTSS_TEXTURETRANSFORMFLAGS),{STATE_TEXTURESTAGE(5, WINED3DTSS_TEXTURETRANSFORMFLAGS), textransform }, 0 },
{STATE_TEXTURESTAGE(6,WINED3DTSS_TEXTURETRANSFORMFLAGS),{STATE_TEXTURESTAGE(6, WINED3DTSS_TEXTURETRANSFORMFLAGS), textransform }, 0 },
{STATE_TEXTURESTAGE(7,WINED3DTSS_TEXTURETRANSFORMFLAGS),{STATE_TEXTURESTAGE(7, WINED3DTSS_TEXTURETRANSFORMFLAGS), textransform }, 0 },
+ {STATE_PIXELSHADER, { STATE_PIXELSHADER, atifs_apply_pixelshader }, 0 },
{0 /* Terminate */, { 0, 0 }, 0 },
};
shader_is_vshader_version(token);
}
+void shader_buffer_init(struct SHADER_BUFFER *buffer)
+{
+ buffer->buffer = HeapAlloc(GetProcessHeap(), 0, SHADER_PGMSIZE);
+ buffer->buffer[0] = '\0';
+ buffer->bsize = 0;
+ buffer->lineNo = 0;
+ buffer->newline = TRUE;
+}
+
+void shader_buffer_free(struct SHADER_BUFFER *buffer)
+{
+ HeapFree(GetProcessHeap(), 0, buffer->buffer);
+}
+
int shader_addline(
SHADER_BUFFER* buffer,
const char *format, ...) {
return 0;
}
+void shader_init(struct IWineD3DBaseShaderClass *shader,
+ IWineD3DDevice *device, const SHADER_OPCODE *instruction_table)
+{
+ shader->ref = 1;
+ shader->device = device;
+ shader->shader_ins = instruction_table;
+ list_init(&shader->linked_programs);
+}
+
const SHADER_OPCODE *shader_get_opcode(const SHADER_OPCODE *opcode_table, DWORD shader_version, DWORD code)
{
DWORD i = 0;
}
/* Return the number of parameters to skip for an opcode */
-static inline int shader_skip_opcode(
- IWineD3DBaseShaderImpl* This,
- const SHADER_OPCODE* curOpcode,
- DWORD opcode_token) {
-
+static inline int shader_skip_opcode(const SHADER_OPCODE *curOpcode, DWORD opcode_token, DWORD shader_version)
+{
/* Shaders >= 2.0 may contain address tokens, but fortunately they
* have a useful length mask - use it here. Shaders 1.0 contain no such tokens */
-
- return (WINED3DSHADER_VERSION_MAJOR(This->baseShader.hex_version) >= 2)?
- ((opcode_token & WINED3DSI_INSTLENGTH_MASK) >> WINED3DSI_INSTLENGTH_SHIFT):
- curOpcode->num_params;
+ return (WINED3DSHADER_VERSION_MAJOR(shader_version) >= 2)
+ ? ((opcode_token & WINED3DSI_INSTLENGTH_MASK) >> WINED3DSI_INSTLENGTH_SHIFT) : curOpcode->num_params;
}
/* Read the parameters of an unrecognized opcode from the input stream
/* Note that this does not count the loop register
* as an address register. */
-HRESULT shader_get_registers_used(
- IWineD3DBaseShader *iface,
- shader_reg_maps* reg_maps,
- semantic* semantics_in,
- semantic* semantics_out,
- CONST DWORD* pToken,
- IWineD3DStateBlockImpl *stateBlock) {
-
+HRESULT shader_get_registers_used(IWineD3DBaseShader *iface, struct shader_reg_maps *reg_maps,
+ struct semantic *semantics_in, struct semantic *semantics_out, const DWORD *byte_code)
+{
IWineD3DBaseShaderImpl* This = (IWineD3DBaseShaderImpl*) iface;
const SHADER_OPCODE *shader_ins = This->baseShader.shader_ins;
- DWORD shader_version = This->baseShader.hex_version;
+ DWORD shader_version;
unsigned int cur_loop_depth = 0, max_loop_depth = 0;
+ const DWORD* pToken = byte_code;
+ char pshader;
/* There are some minor differences between pixel and vertex shaders */
- char pshader = shader_is_pshader_version(This->baseShader.hex_version);
memset(reg_maps->bumpmat, 0, sizeof(reg_maps->bumpmat));
memset(reg_maps->luminanceparams, 0, sizeof(reg_maps->luminanceparams));
- if (pToken == NULL)
- return WINED3D_OK;
-
/* get_registers_used is called on every compile on some 1.x shaders, which can result
* in stacking up a collection of local constants. Delete the old constants if existing
*/
shader_delete_constant_list(&This->baseShader.constantsB);
shader_delete_constant_list(&This->baseShader.constantsI);
+ /* The version token is supposed to be the first token */
+ if (!shader_is_version_token(*pToken))
+ {
+ FIXME("First token is not a version token, invalid shader.\n");
+ return WINED3DERR_INVALIDCALL;
+ }
+ reg_maps->shader_version = shader_version = *pToken++;
+ pshader = shader_is_pshader_version(shader_version);
+
while (WINED3DVS_END() != *pToken) {
CONST SHADER_OPCODE* curOpcode;
DWORD opcode_token;
- /* Skip version */
- if (shader_is_version_token(*pToken)) {
- ++pToken;
- continue;
-
/* Skip comments */
- } else if (shader_is_comment(*pToken)) {
+ if (shader_is_comment(*pToken))
+ {
DWORD comment_len = (*pToken & WINED3DSI_COMMENTSIZE_MASK) >> WINED3DSI_COMMENTSIZE_SHIFT;
++pToken;
pToken += comment_len;
memcpy(lconst->value, pToken + 1, 4 * sizeof(DWORD));
/* In pixel shader 1.X shaders, the constants are clamped between [-1;1] */
- if(WINED3DSHADER_VERSION_MAJOR(This->baseShader.hex_version) == 1 && pshader) {
+ if (WINED3DSHADER_VERSION_MAJOR(shader_version) == 1 && pshader)
+ {
float *value = (float *) lconst->value;
if(value[0] < -1.0) value[0] = -1.0;
else if(value[0] > 1.0) value[0] = 1.0;
max_loop_depth = cur_loop_depth;
pToken += curOpcode->num_params;
+ /* Rep and Loop always use an integer constant for the control parameters */
+ This->baseShader.uses_int_consts = TRUE;
} else if (WINED3DSIO_ENDLOOP == curOpcode->opcode ||
WINED3DSIO_ENDREP == curOpcode->opcode) {
cur_loop_depth--;
int i, limit;
/* Declare 1.X samplers implicitly, based on the destination reg. number */
- if (WINED3DSHADER_VERSION_MAJOR(This->baseShader.hex_version) == 1 &&
- pshader /* Filter different instructions with the same enum values in VS */ &&
- (WINED3DSIO_TEX == curOpcode->opcode ||
- WINED3DSIO_TEXBEM == curOpcode->opcode ||
- WINED3DSIO_TEXBEML == curOpcode->opcode ||
- WINED3DSIO_TEXDP3TEX == curOpcode->opcode ||
- WINED3DSIO_TEXM3x2TEX == curOpcode->opcode ||
- WINED3DSIO_TEXM3x3SPEC == curOpcode->opcode ||
- WINED3DSIO_TEXM3x3TEX == curOpcode->opcode ||
- WINED3DSIO_TEXM3x3VSPEC == curOpcode->opcode ||
- WINED3DSIO_TEXREG2AR == curOpcode->opcode ||
- WINED3DSIO_TEXREG2GB == curOpcode->opcode ||
- WINED3DSIO_TEXREG2RGB == curOpcode->opcode)) {
-
+ if (WINED3DSHADER_VERSION_MAJOR(shader_version) == 1
+ && pshader /* Filter different instructions with the same enum values in VS */
+ && (WINED3DSIO_TEX == curOpcode->opcode
+ || WINED3DSIO_TEXBEM == curOpcode->opcode
+ || WINED3DSIO_TEXBEML == curOpcode->opcode
+ || WINED3DSIO_TEXDP3TEX == curOpcode->opcode
+ || WINED3DSIO_TEXM3x2TEX == curOpcode->opcode
+ || WINED3DSIO_TEXM3x3SPEC == curOpcode->opcode
+ || WINED3DSIO_TEXM3x3TEX == curOpcode->opcode
+ || WINED3DSIO_TEXM3x3VSPEC == curOpcode->opcode
+ || WINED3DSIO_TEXREG2AR == curOpcode->opcode
+ || WINED3DSIO_TEXREG2GB == curOpcode->opcode
+ || WINED3DSIO_TEXREG2RGB == curOpcode->opcode))
+ {
/* Fake sampler usage, only set reserved bit and ttype */
DWORD sampler_code = *pToken & WINED3DSP_REGNUM_MASK;
- if(!stateBlock->textures[sampler_code]) {
- ERR("No texture bound to sampler %d\n", sampler_code);
- reg_maps->samplers[sampler_code] = (0x1 << 31) | WINED3DSTT_2D;
- } else {
- int texType = IWineD3DBaseTexture_GetTextureDimensions(stateBlock->textures[sampler_code]);
- switch(texType) {
- /* We have to select between texture rectangles and 2D textures later because 2.0 and
- * 3.0 shaders only have WINED3DSTT_2D as well
- */
- case GL_TEXTURE_RECTANGLE_ARB:
- case GL_TEXTURE_2D:
- reg_maps->samplers[sampler_code] = (0x1 << 31) | WINED3DSTT_2D;
- break;
-
- case GL_TEXTURE_3D:
- reg_maps->samplers[sampler_code] = (0x1 << 31) | WINED3DSTT_VOLUME;
- break;
-
- case GL_TEXTURE_CUBE_MAP_ARB:
- reg_maps->samplers[sampler_code] = (0x1 << 31) | WINED3DSTT_CUBE;
- break;
-
- default:
- ERR("Unexpected gl texture type found: %d\n", texType);
- reg_maps->samplers[sampler_code] = (0x1 << 31) | WINED3DSTT_2D;
- }
- }
+ TRACE("Setting fake 2D sampler for 1.x pixelshader\n");
+ reg_maps->samplers[sampler_code] = (0x1 << 31) | WINED3DSTT_2D;
/* texbem is only valid with < 1.4 pixel shaders */
if(WINED3DSIO_TEXBEM == curOpcode->opcode ||
reg_maps->usesrelconstF = TRUE;
}
}
+ else if(WINED3DSPR_CONSTINT == regtype) {
+ This->baseShader.uses_int_consts = TRUE;
+ }
+ else if(WINED3DSPR_CONSTBOOL == regtype) {
+ This->baseShader.uses_bool_consts = TRUE;
+ }
/* WINED3DSPR_TEXCRDOUT is the same as WINED3DSPR_OUTPUT. _OUTPUT can be > MAX_REG_TEXCRD and is used
* in >= 3.0 shaders. Filter 3.0 shaders to prevent overflows, and also filter pixel shaders because TECRDOUT
* isn't used in them, but future register types might cause issues
*/
- else if(WINED3DSPR_TEXCRDOUT == regtype && i == 0 /* Only look at writes */ &&
- !pshader && WINED3DSHADER_VERSION_MAJOR(This->baseShader.hex_version) < 3) {
+ else if (WINED3DSPR_TEXCRDOUT == regtype && i == 0 /* Only look at writes */
+ && !pshader && WINED3DSHADER_VERSION_MAJOR(shader_version) < 3)
+ {
reg_maps->texcoord_mask[reg] |= shader_get_writemask(param);
}
}
}
}
+ ++pToken;
reg_maps->loop_depth = max_loop_depth;
+ This->baseShader.functionLength = ((char *)pToken - (char *)byte_code);
+
return WINED3D_OK;
}
{
static const char * const rastout_reg_names[] = { "oPos", "oFog", "oPts" };
static const char * const misctype_reg_names[] = { "vPos", "vFace"};
- char swizzle_reg_chars[4];
+ const char *swizzle_reg_chars = "xyzw";
DWORD reg = param & WINED3DSP_REGNUM_MASK;
DWORD regtype = shader_get_regtype(param);
/* There are some minor differences between pixel and vertex shaders */
char pshader = shader_is_pshader_version(shader_version);
- /* For one, we'd prefer color components to be shown for pshaders.
- * FIXME: use the swizzle function for this */
-
- swizzle_reg_chars[0] = pshader? 'r': 'x';
- swizzle_reg_chars[1] = pshader? 'g': 'y';
- swizzle_reg_chars[2] = pshader? 'b': 'z';
- swizzle_reg_chars[3] = pshader? 'a': 'w';
-
if (input) {
if ( (modifier == WINED3DSPSM_NEG) ||
(modifier == WINED3DSPSM_BIASNEG) ||
} else {
/** operand input */
DWORD swizzle = (param & WINED3DSP_SWIZZLE_MASK) >> WINED3DSP_SWIZZLE_SHIFT;
- DWORD swizzle_r = swizzle & 0x03;
- DWORD swizzle_g = (swizzle >> 2) & 0x03;
- DWORD swizzle_b = (swizzle >> 4) & 0x03;
- DWORD swizzle_a = (swizzle >> 6) & 0x03;
+ DWORD swizzle_x = swizzle & 0x03;
+ DWORD swizzle_y = (swizzle >> 2) & 0x03;
+ DWORD swizzle_z = (swizzle >> 4) & 0x03;
+ DWORD swizzle_w = (swizzle >> 6) & 0x03;
if (0 != modifier) {
switch (modifier) {
* RRGGBBAA
*/
if ((WINED3DVS_NOSWIZZLE >> WINED3DVS_SWIZZLE_SHIFT) != swizzle) {
- if (swizzle_r == swizzle_g &&
- swizzle_r == swizzle_b &&
- swizzle_r == swizzle_a) {
- TRACE(".%c", swizzle_reg_chars[swizzle_r]);
+ if (swizzle_x == swizzle_y &&
+ swizzle_x == swizzle_z &&
+ swizzle_x == swizzle_w) {
+ TRACE(".%c", swizzle_reg_chars[swizzle_x]);
} else {
TRACE(".%c%c%c%c",
- swizzle_reg_chars[swizzle_r],
- swizzle_reg_chars[swizzle_g],
- swizzle_reg_chars[swizzle_b],
- swizzle_reg_chars[swizzle_a]);
+ swizzle_reg_chars[swizzle_x],
+ swizzle_reg_chars[swizzle_y],
+ swizzle_reg_chars[swizzle_z],
+ swizzle_reg_chars[swizzle_w]);
}
}
}
}
static void shader_color_correction(IWineD3DBaseShaderImpl *shader,
- IWineD3DDeviceImpl *device, const struct SHADER_OPCODE_ARG *arg)
+ IWineD3DDeviceImpl *device, const struct SHADER_OPCODE_ARG *arg, DWORD shader_version)
{
- DWORD hex_version = shader->baseShader.hex_version;
IWineD3DBaseTextureImpl *texture;
struct color_fixup_desc fixup;
BOOL recorded = FALSE;
switch(arg->opcode->opcode)
{
case WINED3DSIO_TEX:
- if (hex_version < WINED3DPS_VERSION(2,0)) sampler_idx = arg->dst & WINED3DSP_REGNUM_MASK;
+ if (WINED3DSHADER_VERSION_MAJOR(shader_version) < 2) sampler_idx = arg->dst & WINED3DSP_REGNUM_MASK;
else sampler_idx = arg->src[1] & WINED3DSP_REGNUM_MASK;
break;
device->shader_backend->shader_color_correction(arg, fixup);
}
-/** Shared code in order to generate the bulk of the shader string.
- Use the shader_header_fct & shader_footer_fct to add strings
- that are specific to pixel or vertex functions
- NOTE: A description of how to parse tokens can be found on msdn */
+/* Shared code in order to generate the bulk of the shader string.
+ * NOTE: A description of how to parse tokens can be found on msdn */
void shader_generate_main(IWineD3DBaseShader *iface, SHADER_BUFFER* buffer,
const shader_reg_maps* reg_maps, CONST DWORD* pFunction)
{
IWineD3DDeviceImpl *device = (IWineD3DDeviceImpl *) This->baseShader.device; /* To access shader backend callbacks */
const SHADER_OPCODE *opcode_table = This->baseShader.shader_ins;
const SHADER_HANDLER *handler_table = device->shader_backend->shader_instruction_handler_table;
- DWORD shader_version = This->baseShader.hex_version;
+ DWORD shader_version = reg_maps->shader_version;
const DWORD *pToken = pFunction;
- const SHADER_OPCODE *curOpcode = NULL;
- SHADER_HANDLER hw_fct = NULL;
+ const SHADER_OPCODE *curOpcode;
+ SHADER_HANDLER hw_fct;
DWORD i;
SHADER_OPCODE_ARG hw_arg;
hw_arg.reg_maps = reg_maps;
This->baseShader.parse_state.current_row = 0;
- /* Second pass, process opcodes */
- if (NULL != pToken) {
- while (WINED3DPS_END() != *pToken) {
-
- /* Skip version token */
- if (shader_is_version_token(*pToken)) {
- ++pToken;
- continue;
- }
-
- /* Skip comment tokens */
- if (shader_is_comment(*pToken)) {
- DWORD comment_len = (*pToken & WINED3DSI_COMMENTSIZE_MASK) >> WINED3DSI_COMMENTSIZE_SHIFT;
- ++pToken;
- TRACE("#%s\n", (const char*)pToken);
- pToken += comment_len;
- continue;
- }
-
- /* Read opcode */
- hw_arg.opcode_token = *pToken++;
- curOpcode = shader_get_opcode(opcode_table, shader_version, hw_arg.opcode_token);
-
- /* Select handler */
- if (curOpcode == NULL)
- hw_fct = NULL;
- else
- hw_fct = handler_table[curOpcode->handler_idx];
-
- /* Unknown opcode and its parameters */
- if (NULL == curOpcode) {
- FIXME("Unrecognized opcode: token=0x%08x\n", hw_arg.opcode_token);
- pToken += shader_skip_unrecognized(pToken, shader_version);
-
- /* Nothing to do */
- } else if (WINED3DSIO_DCL == curOpcode->opcode ||
- WINED3DSIO_NOP == curOpcode->opcode ||
- WINED3DSIO_DEF == curOpcode->opcode ||
- WINED3DSIO_DEFI == curOpcode->opcode ||
- WINED3DSIO_DEFB == curOpcode->opcode ||
- WINED3DSIO_PHASE == curOpcode->opcode ||
- WINED3DSIO_RET == curOpcode->opcode) {
-
- pToken += shader_skip_opcode(This, curOpcode, hw_arg.opcode_token);
+ while (WINED3DPS_END() != *pToken)
+ {
+ /* Skip version token */
+ if (shader_is_version_token(*pToken))
+ {
+ ++pToken;
+ continue;
+ }
- /* If a generator function is set for current shader target, use it */
- } else if (hw_fct != NULL) {
+ /* Skip comment tokens */
+ if (shader_is_comment(*pToken))
+ {
+ pToken += (*pToken & WINED3DSI_COMMENTSIZE_MASK) >> WINED3DSI_COMMENTSIZE_SHIFT;
+ ++pToken;
+ continue;
+ }
- hw_arg.opcode = curOpcode;
+ /* Read opcode */
+ hw_arg.opcode_token = *pToken++;
+ curOpcode = shader_get_opcode(opcode_table, shader_version, hw_arg.opcode_token);
- /* Destination token */
- if (curOpcode->dst_token) {
+ /* Unknown opcode and its parameters */
+ if (!curOpcode)
+ {
+ FIXME("Unrecognized opcode: token=0x%08x\n", hw_arg.opcode_token);
+ pToken += shader_skip_unrecognized(pToken, shader_version);
+ continue;
+ }
- DWORD param, addr_token = 0;
- pToken += shader_get_param(pToken, shader_version, ¶m, &addr_token);
- hw_arg.dst = param;
- hw_arg.dst_addr = addr_token;
- }
+ /* Nothing to do */
+ if (WINED3DSIO_DCL == curOpcode->opcode
+ || WINED3DSIO_NOP == curOpcode->opcode
+ || WINED3DSIO_DEF == curOpcode->opcode
+ || WINED3DSIO_DEFI == curOpcode->opcode
+ || WINED3DSIO_DEFB == curOpcode->opcode
+ || WINED3DSIO_PHASE == curOpcode->opcode
+ || WINED3DSIO_RET == curOpcode->opcode)
+ {
+ pToken += shader_skip_opcode(curOpcode, hw_arg.opcode_token, shader_version);
+ continue;
+ }
- /* Predication token */
- if (hw_arg.opcode_token & WINED3DSHADER_INSTRUCTION_PREDICATED)
- hw_arg.predicate = *pToken++;
+ /* Select handler */
+ hw_fct = handler_table[curOpcode->handler_idx];
- /* Other source tokens */
- for (i = 0; i < (curOpcode->num_params - curOpcode->dst_token); i++) {
+ /* Unhandled opcode */
+ if (!hw_fct)
+ {
+ FIXME("Can't handle opcode %s in hwShader\n", curOpcode->name);
+ pToken += shader_skip_opcode(curOpcode, hw_arg.opcode_token, shader_version);
+ continue;
+ }
- DWORD param, addr_token = 0;
- pToken += shader_get_param(pToken, shader_version, ¶m, &addr_token);
- hw_arg.src[i] = param;
- hw_arg.src_addr[i] = addr_token;
- }
+ hw_arg.opcode = curOpcode;
- /* Call appropriate function for output target */
- hw_fct(&hw_arg);
+ /* Destination token */
+ if (curOpcode->dst_token)
+ {
+ DWORD param, addr_token = 0;
+ pToken += shader_get_param(pToken, shader_version, ¶m, &addr_token);
+ hw_arg.dst = param;
+ hw_arg.dst_addr = addr_token;
+ }
- /* Add color correction if needed */
- shader_color_correction(This, device, &hw_arg);
+ /* Predication token */
+ if (hw_arg.opcode_token & WINED3DSHADER_INSTRUCTION_PREDICATED) hw_arg.predicate = *pToken++;
- /* Process instruction modifiers for GLSL apps ( _sat, etc. ) */
- /* FIXME: This should be internal to the shader backend.
- * Also, right now this is the only reason "shader_mode" exists. */
- if (This->baseShader.shader_mode == SHADER_GLSL)
- shader_glsl_add_instruction_modifiers(&hw_arg);
+ /* Other source tokens */
+ for (i = 0; i < (curOpcode->num_params - curOpcode->dst_token); ++i)
+ {
+ DWORD param, addr_token = 0;
+ pToken += shader_get_param(pToken, shader_version, ¶m, &addr_token);
+ hw_arg.src[i] = param;
+ hw_arg.src_addr[i] = addr_token;
+ }
- /* Unhandled opcode */
- } else {
+ /* Call appropriate function for output target */
+ hw_fct(&hw_arg);
- FIXME("Can't handle opcode %s in hwShader\n", curOpcode->name);
- pToken += shader_skip_opcode(This, curOpcode, hw_arg.opcode_token);
- }
- }
- /* TODO: What about result.depth? */
+ /* Add color correction if needed */
+ shader_color_correction(This, device, &hw_arg, shader_version);
+ /* Process instruction modifiers for GLSL apps ( _sat, etc. ) */
+ /* FIXME: This should be internal to the shader backend.
+ * Also, right now this is the only reason "shader_mode" exists. */
+ if (This->baseShader.shader_mode == SHADER_GLSL) shader_glsl_add_instruction_modifiers(&hw_arg);
}
}
FIXME("_unrecognized_modifier(%#x)", mmask >> WINED3DSP_DSTMOD_SHIFT);
}
-/* First pass: trace shader, initialize length and version */
-void shader_trace_init(
- IWineD3DBaseShader *iface,
- const DWORD* pFunction) {
-
- IWineD3DBaseShaderImpl *This =(IWineD3DBaseShaderImpl *)iface;
-
+void shader_trace_init(const DWORD *pFunction, const SHADER_OPCODE *opcode_table)
+{
const DWORD* pToken = pFunction;
const SHADER_OPCODE* curOpcode = NULL;
+ DWORD shader_version;
DWORD opcode_token;
- unsigned int len = 0;
DWORD i;
- TRACE("(%p) : Parsing program\n", This);
+ TRACE("Parsing %p\n", pFunction);
- if (!pFunction)
+ /* The version token is supposed to be the first token */
+ if (!shader_is_version_token(*pToken))
{
- WARN("Got a NULL pFunction, returning.\n");
- This->baseShader.functionLength = 1; /* no Function defined use fixed function vertex processing */
+ FIXME("First token is not a version token, invalid shader.\n");
return;
}
+ shader_version = *pToken++;
+ TRACE("%s_%u_%u\n", shader_is_pshader_version(shader_version) ? "ps": "vs",
+ WINED3DSHADER_VERSION_MAJOR(shader_version), WINED3DSHADER_VERSION_MINOR(shader_version));
while (WINED3DVS_END() != *pToken)
{
- if (shader_is_version_token(*pToken)) /* version */
- {
- This->baseShader.hex_version = *pToken;
- TRACE("%s_%u_%u\n", shader_is_pshader_version(This->baseShader.hex_version)? "ps": "vs",
- WINED3DSHADER_VERSION_MAJOR(This->baseShader.hex_version),
- WINED3DSHADER_VERSION_MINOR(This->baseShader.hex_version));
- ++pToken;
- ++len;
- continue;
- }
if (shader_is_comment(*pToken)) /* comment */
{
DWORD comment_len = (*pToken & WINED3DSI_COMMENTSIZE_MASK) >> WINED3DSI_COMMENTSIZE_SHIFT;
++pToken;
TRACE("//%s\n", (const char*)pToken);
pToken += comment_len;
- len += comment_len + 1;
continue;
}
opcode_token = *pToken++;
- curOpcode = shader_get_opcode(This->baseShader.shader_ins, This->baseShader.hex_version, opcode_token);
- len++;
+ curOpcode = shader_get_opcode(opcode_table, shader_version, opcode_token);
if (!curOpcode)
{
int tokens_read;
FIXME("Unrecognized opcode: token=0x%08x\n", opcode_token);
- tokens_read = shader_skip_unrecognized(pToken, This->baseShader.hex_version);
+ tokens_read = shader_skip_unrecognized(pToken, shader_version);
pToken += tokens_read;
- len += tokens_read;
}
else
{
DWORD usage = *pToken;
DWORD param = *(pToken + 1);
- shader_dump_decl_usage(usage, param, This->baseShader.hex_version);
+ shader_dump_decl_usage(usage, param, shader_version);
shader_dump_ins_modifiers(param);
TRACE(" ");
- shader_dump_param(param, 0, 0, This->baseShader.hex_version);
+ shader_dump_param(param, 0, 0, shader_version);
pToken += 2;
- len += 2;
}
else if (curOpcode->opcode == WINED3DSIO_DEF)
{
*(const float *)(pToken + 3),
*(const float *)(pToken + 4));
pToken += 5;
- len += 5;
}
else if (curOpcode->opcode == WINED3DSIO_DEFI)
{
*(pToken + 3),
*(pToken + 4));
pToken += 5;
- len += 5;
}
else if (curOpcode->opcode == WINED3DSIO_DEFB)
{
TRACE("defb b%u = %s", *pToken & WINED3DSP_REGNUM_MASK,
*(pToken + 1)? "true": "false");
pToken += 2;
- len += 2;
}
else
{
if (opcode_token & WINED3DSHADER_INSTRUCTION_PREDICATED)
{
TRACE("(");
- shader_dump_param(*(pToken + 2), 0, 1, This->baseShader.hex_version);
+ shader_dump_param(*(pToken + 2), 0, 1, shader_version);
TRACE(") ");
}
if (opcode_token & WINED3DSI_COISSUE)
}
}
else if (curOpcode->opcode == WINED3DSIO_TEX
- && This->baseShader.hex_version >= WINED3DPS_VERSION(2,0)
+ && shader_version >= WINED3DPS_VERSION(2,0)
&& (opcode_token & WINED3DSI_TEXLD_PROJECT))
{
TRACE("p");
/* Destination token */
if (curOpcode->dst_token)
{
- tokens_read = shader_get_param(pToken, This->baseShader.hex_version, ¶m, &addr_token);
+ tokens_read = shader_get_param(pToken, shader_version, ¶m, &addr_token);
pToken += tokens_read;
- len += tokens_read;
shader_dump_ins_modifiers(param);
TRACE(" ");
- shader_dump_param(param, addr_token, 0, This->baseShader.hex_version);
+ shader_dump_param(param, addr_token, 0, shader_version);
}
/* Predication token - already printed out, just skip it */
if (opcode_token & WINED3DSHADER_INSTRUCTION_PREDICATED)
{
pToken++;
- len++;
}
/* Other source tokens */
for (i = curOpcode->dst_token; i < curOpcode->num_params; ++i)
{
- tokens_read = shader_get_param(pToken, This->baseShader.hex_version, ¶m, &addr_token);
+ tokens_read = shader_get_param(pToken, shader_version, ¶m, &addr_token);
pToken += tokens_read;
- len += tokens_read;
TRACE((i == 0)? " " : ", ");
- shader_dump_param(param, addr_token, 1, This->baseShader.hex_version);
+ shader_dump_param(param, addr_token, 1, shader_version);
}
}
TRACE("\n");
}
}
- This->baseShader.functionLength = (len + 1) * sizeof(DWORD);
+}
+
+void shader_cleanup(IWineD3DBaseShader *iface)
+{
+ IWineD3DBaseShaderImpl *This = (IWineD3DBaseShaderImpl *)iface;
+
+ ((IWineD3DDeviceImpl *)This->baseShader.device)->shader_backend->shader_destroy(iface);
+ HeapFree(GetProcessHeap(), 0, This->baseShader.function);
+ shader_delete_constant_list(&This->baseShader.constantsF);
+ shader_delete_constant_list(&This->baseShader.constantsB);
+ shader_delete_constant_list(&This->baseShader.constantsI);
+ list_remove(&This->baseShader.shader_list_entry);
}
static const SHADER_HANDLER shader_none_instruction_handler_table[WINED3DSIH_TABLE_SIZE] = {0};
static void shader_none_select(IWineD3DDevice *iface, BOOL usePS, BOOL useVS) {}
static void shader_none_select_depth_blt(IWineD3DDevice *iface, enum tex_types tex_type) {}
static void shader_none_deselect_depth_blt(IWineD3DDevice *iface) {}
+static void shader_none_update_float_vertex_constants(IWineD3DDevice *iface, UINT start, UINT count) {}
+static void shader_none_update_float_pixel_constants(IWineD3DDevice *iface, UINT start, UINT count) {}
static void shader_none_load_constants(IWineD3DDevice *iface, char usePS, char useVS) {}
-static void shader_none_cleanup(IWineD3DDevice *iface) {}
static void shader_none_color_correction(const struct SHADER_OPCODE_ARG *arg, struct color_fixup_desc fixup) {}
static void shader_none_destroy(IWineD3DBaseShader *iface) {}
static HRESULT shader_none_alloc(IWineD3DDevice *iface) {return WINED3D_OK;}
static void shader_none_free(IWineD3DDevice *iface) {}
static BOOL shader_none_dirty_const(IWineD3DDevice *iface) {return FALSE;}
-static GLuint shader_none_generate_pshader(IWineD3DPixelShader *iface, SHADER_BUFFER *buffer) {
+static GLuint shader_none_generate_pshader(IWineD3DPixelShader *iface, SHADER_BUFFER *buffer, const struct ps_compile_args *args) {
FIXME("NONE shader backend asked to generate a pixel shader\n");
return 0;
}
shader_none_select,
shader_none_select_depth_blt,
shader_none_deselect_depth_blt,
+ shader_none_update_float_vertex_constants,
+ shader_none_update_float_pixel_constants,
shader_none_load_constants,
- shader_none_cleanup,
shader_none_color_correction,
shader_none_destroy,
shader_none_alloc,
shader_none_get_caps,
shader_none_color_fixup_supported,
};
-
-/* *******************************************
- IWineD3DPixelShader IUnknown parts follow
- ******************************************* */
-HRESULT WINAPI IWineD3DBaseShaderImpl_QueryInterface(IWineD3DBaseShader *iface, REFIID riid, LPVOID *ppobj)
-{
- IWineD3DBaseShaderImpl *This = (IWineD3DBaseShaderImpl *)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_IWineD3DPixelShader)) {
- IUnknown_AddRef(iface);
- *ppobj = This;
- return S_OK;
- }
- *ppobj = NULL;
- return E_NOINTERFACE;
-}
-
-ULONG WINAPI IWineD3DBaseShaderImpl_AddRef(IWineD3DBaseShader *iface) {
- IWineD3DPixelShaderImpl *This = (IWineD3DPixelShaderImpl *)iface;
- TRACE("(%p) : AddRef increasing from %d\n", This, This->baseShader.ref);
- return InterlockedIncrement(&This->baseShader.ref);
-}
-
-ULONG WINAPI IWineD3DBaseShaderImpl_Release(IWineD3DBaseShader *iface) {
- IWineD3DBaseShaderImpl *This = (IWineD3DBaseShaderImpl *)iface;
- IWineD3DDeviceImpl *deviceImpl = (IWineD3DDeviceImpl *) This->baseShader.device;
- ULONG ref;
- TRACE("(%p) : Releasing from %d\n", This, This->baseShader.ref);
- ref = InterlockedDecrement(&This->baseShader.ref);
- if (ref == 0) {
- deviceImpl->shader_backend->shader_destroy(iface);
- HeapFree(GetProcessHeap(), 0, This->baseShader.function);
- shader_delete_constant_list(&This->baseShader.constantsF);
- shader_delete_constant_list(&This->baseShader.constantsB);
- shader_delete_constant_list(&This->baseShader.constantsI);
- list_remove(&This->baseShader.shader_list_entry);
- HeapFree(GetProcessHeap(), 0, This);
- }
- return ref;
-}
WINE_DEFAULT_DEBUG_CHANNEL(d3d_texture);
#define GLINFO_LOCATION This->resource.wineD3DDevice->adapter->gl_info
+void basetexture_init(struct IWineD3DBaseTextureClass *texture, UINT levels, DWORD usage)
+{
+ texture->levels = levels;
+ texture->filterType = (usage & WINED3DUSAGE_AUTOGENMIPMAP) ? WINED3DTEXF_LINEAR : WINED3DTEXF_NONE;
+ texture->LOD = 0;
+ texture->dirty = TRUE;
+ texture->is_srgb = FALSE;
+ texture->srgb_mode_change_count = 0;
+}
+
void basetexture_cleanup(IWineD3DBaseTexture *iface)
{
IWineD3DBaseTextureImpl *This = (IWineD3DBaseTextureImpl *)iface;
glTexParameteri(textureDimensions, GL_TEXTURE_WRAP_R, GL_CLAMP_TO_EDGE);
}
}
-
} else { /* this only happened if we've run out of openGL textures */
WARN("This texture doesn't have an openGL texture assigned to it\n");
hr = WINED3DERR_INVALIDCALL;
checkGLcall("glClear");
- glColor3f(1.0, 1.0, 1.0);
- checkGLcall("glColor3f");
-
- glEnable(GL_LIGHTING);
- checkGLcall("glEnable");
-
glLightModeli(GL_LIGHT_MODEL_LOCAL_VIEWER, GL_TRUE);
checkGLcall("glLightModeli(GL_LIGHT_MODEL_LOCAL_VIEWER, GL_TRUE);");
/* TODO: Use a display list */
/* Disable shaders */
- This->shader_backend->shader_cleanup((IWineD3DDevice *) This);
+ This->shader_backend->shader_select((IWineD3DDevice *)This, FALSE, FALSE);
Context_MarkStateDirty(context, STATE_VSHADER, StateTable);
Context_MarkStateDirty(context, STATE_PIXELSHADER, StateTable);
/* Disable all textures. The caller can then bind a texture it wants to blit
* from
+ *
+ * The blitting code uses (for now) the fixed function pipeline, so make sure to reset all fixed
+ * function texture unit. No need to care for higher samplers
*/
- if (GL_SUPPORT(ARB_MULTITEXTURE)) {
- /* The blitting code uses (for now) the fixed function pipeline, so make sure to reset all fixed
- * function texture unit. No need to care for higher samplers
- */
- for(i = GL_LIMITS(textures) - 1; i > 0 ; i--) {
- sampler = This->rev_tex_unit_map[i];
- GL_EXTCALL(glActiveTextureARB(GL_TEXTURE0_ARB + i));
- checkGLcall("glActiveTextureARB");
-
- if(GL_SUPPORT(ARB_TEXTURE_CUBE_MAP)) {
- glDisable(GL_TEXTURE_CUBE_MAP_ARB);
- checkGLcall("glDisable GL_TEXTURE_CUBE_MAP_ARB");
- }
- glDisable(GL_TEXTURE_3D);
- checkGLcall("glDisable GL_TEXTURE_3D");
- if(GL_SUPPORT(ARB_TEXTURE_RECTANGLE)) {
- glDisable(GL_TEXTURE_RECTANGLE_ARB);
- checkGLcall("glDisable GL_TEXTURE_RECTANGLE_ARB");
- }
- glDisable(GL_TEXTURE_2D);
- checkGLcall("glDisable GL_TEXTURE_2D");
+ for(i = GL_LIMITS(textures) - 1; i > 0 ; i--) {
+ sampler = This->rev_tex_unit_map[i];
+ GL_EXTCALL(glActiveTextureARB(GL_TEXTURE0_ARB + i));
+ checkGLcall("glActiveTextureARB");
- glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);
- checkGLcall("glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);");
+ if(GL_SUPPORT(ARB_TEXTURE_CUBE_MAP)) {
+ glDisable(GL_TEXTURE_CUBE_MAP_ARB);
+ checkGLcall("glDisable GL_TEXTURE_CUBE_MAP_ARB");
+ }
+ glDisable(GL_TEXTURE_3D);
+ checkGLcall("glDisable GL_TEXTURE_3D");
+ if(GL_SUPPORT(ARB_TEXTURE_RECTANGLE)) {
+ glDisable(GL_TEXTURE_RECTANGLE_ARB);
+ checkGLcall("glDisable GL_TEXTURE_RECTANGLE_ARB");
+ }
+ glDisable(GL_TEXTURE_2D);
+ checkGLcall("glDisable GL_TEXTURE_2D");
- if (sampler != -1) {
- if (sampler < MAX_TEXTURES) {
- Context_MarkStateDirty(context, STATE_TEXTURESTAGE(sampler, WINED3DTSS_COLOROP), StateTable);
- }
- Context_MarkStateDirty(context, STATE_SAMPLER(sampler), StateTable);
+ glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);
+ checkGLcall("glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);");
+
+ if (sampler != -1) {
+ if (sampler < MAX_TEXTURES) {
+ Context_MarkStateDirty(context, STATE_TEXTURESTAGE(sampler, WINED3DTSS_COLOROP), StateTable);
}
+ Context_MarkStateDirty(context, STATE_SAMPLER(sampler), StateTable);
}
- GL_EXTCALL(glActiveTextureARB(GL_TEXTURE0_ARB));
- checkGLcall("glActiveTextureARB");
}
+ GL_EXTCALL(glActiveTextureARB(GL_TEXTURE0_ARB));
+ checkGLcall("glActiveTextureARB");
sampler = This->rev_tex_unit_map[0];
glDisable(GL_DEPTH_TEST);
checkGLcall("glDisable GL_DEPTH_TEST");
Context_MarkStateDirty(context, STATE_RENDER(WINED3DRS_ZENABLE), StateTable);
- glDisable(GL_FOG);
+ glDisableWINE(GL_FOG);
checkGLcall("glDisable GL_FOG");
Context_MarkStateDirty(context, STATE_RENDER(WINED3DRS_FOGENABLE), StateTable);
glDisable(GL_BLEND);
FIXME("Unexpected context usage requested\n");
}
}
+
+WineD3DContext *getActiveContext(void) {
+ return last_device->activeContext;
+}
}
}
} else if (srgb_was_toggled) {
- /* Loop is repeated in the else block with the extra AddDirtyRect line to avoid the alternative of
- * checking srgb_was_toggled in every iteration, even when the texture is just dirty
- */
+ /* Loop is repeated in the else block with the extra surface_add_dirty_rect() line to avoid the
+ * alternative of checking srgb_was_toggled in every iteration, even when the texture is just dirty */
if (This->baseTexture.srgb_mode_change_count < 20)
++This->baseTexture.srgb_mode_change_count;
else
for (i = 0; i < This->baseTexture.levels; i++) {
for (j = WINED3DCUBEMAP_FACE_POSITIVE_X; j <= WINED3DCUBEMAP_FACE_NEGATIVE_Z ; j++) {
- IWineD3DSurface_AddDirtyRect(This->surfaces[j][i], NULL);
+ surface_add_dirty_rect(This->surfaces[j][i], NULL);
surface_force_reload(This->surfaces[j][i]);
IWineD3DSurface_LoadTexture(This->surfaces[j][i], srgb_mode);
}
TRACE("(%p) level (%d)\n", This, Level);
return IWineD3DSurface_GetDesc(This->surfaces[0][Level], pDesc);
}
- FIXME("(%p) level(%d) overflow Levels(%d)\n", This, Level, This->baseTexture.levels);
+ WARN("(%p) level(%d) overflow Levels(%d)\n", This, Level, This->baseTexture.levels);
return WINED3DERR_INVALIDCALL;
}
This->baseTexture.dirty = TRUE;
TRACE("(%p) : dirtyfication of faceType(%d) Level (0)\n", This, FaceType);
if (FaceType <= WINED3DCUBEMAP_FACE_NEGATIVE_Z) {
- hr = IWineD3DSurface_AddDirtyRect(This->surfaces[FaceType][0], pDirtyRect);
+ surface_add_dirty_rect(This->surfaces[FaceType][0], pDirtyRect);
+ hr = WINED3D_OK;
} else {
WARN("(%p) overflow FaceType(%d)\n", This, FaceType);
}
/* static function declarations */
static void IWineD3DDeviceImpl_AddResource(IWineD3DDevice *iface, IWineD3DResource *resource);
-/* helper macros */
-#define D3DMEMCHECK(object, ppResult) if(NULL == object) { *ppResult = NULL; WARN("Out of memory\n"); return WINED3DERR_OUTOFVIDEOMEMORY;}
-
-#define D3DCREATEOBJECTINSTANCE(object, type) { \
- object=HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(IWineD3D##type##Impl)); \
- D3DMEMCHECK(object, pp##type); \
- object->lpVtbl = &IWineD3D##type##_Vtbl; \
- object->wineD3DDevice = This; \
- object->parent = parent; \
- object->ref = 1; \
- *pp##type = (IWineD3D##type *) object; \
-}
-
-#define D3DCREATESHADEROBJECTINSTANCE(object, type) { \
- object=HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(IWineD3D##type##Impl)); \
- D3DMEMCHECK(object, pp##type); \
- object->lpVtbl = &IWineD3D##type##_Vtbl; \
- object->parent = parent; \
- object->baseShader.ref = 1; \
- object->baseShader.device = (IWineD3DDevice*) This; \
- list_init(&object->baseShader.linked_programs); \
- *pp##type = (IWineD3D##type *) object; \
-}
-
-#define D3DCREATERESOURCEOBJECTINSTANCE(object, type, d3dtype, _size){ \
- object=HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(IWineD3D##type##Impl)); \
- D3DMEMCHECK(object, pp##type); \
- object->lpVtbl = &IWineD3D##type##_Vtbl; \
- object->resource.wineD3DDevice = This; \
- object->resource.parent = parent; \
- object->resource.resourceType = d3dtype; \
- object->resource.ref = 1; \
- object->resource.pool = Pool; \
- object->resource.format = Format; \
- object->resource.usage = Usage; \
- object->resource.size = _size; \
- object->resource.priority = 0; \
- list_init(&object->resource.privateData); \
- /* Check that we have enough video ram left */ \
- if (Pool == WINED3DPOOL_DEFAULT) { \
- if (IWineD3DDevice_GetAvailableTextureMem(iface) <= _size) { \
- WARN("Out of 'bogus' video memory\n"); \
- HeapFree(GetProcessHeap(), 0, object); \
- *pp##type = NULL; \
- return WINED3DERR_OUTOFVIDEOMEMORY; \
- } \
- WineD3DAdapterChangeGLRam(This, _size); \
- } \
- object->resource.heapMemory = (0 == _size ? NULL : HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, _size + RESOURCE_ALIGNMENT)); \
- if (object->resource.heapMemory == NULL && _size != 0) { \
- FIXME("Out of memory!\n"); \
- HeapFree(GetProcessHeap(), 0, object); \
- *pp##type = NULL; \
- return WINED3DERR_OUTOFVIDEOMEMORY; \
- } \
- object->resource.allocatedMemory = (BYTE *)(((ULONG_PTR) object->resource.heapMemory + (RESOURCE_ALIGNMENT - 1)) & ~(RESOURCE_ALIGNMENT - 1)); \
- *pp##type = (IWineD3D##type *) object; \
- IWineD3DDeviceImpl_AddResource(iface, (IWineD3DResource *)object) ;\
- TRACE("(%p) : Created resource %p\n", This, object); \
-}
-
-#define D3DINITIALIZEBASETEXTURE(_basetexture) { \
- _basetexture.levels = Levels; \
- _basetexture.filterType = (Usage & WINED3DUSAGE_AUTOGENMIPMAP) ? WINED3DTEXF_LINEAR : WINED3DTEXF_NONE; \
- _basetexture.LOD = 0; \
- _basetexture.dirty = TRUE; \
- _basetexture.is_srgb = FALSE; \
- _basetexture.srgb_mode_change_count = 0; \
-}
-
/**********************************************************
* Global variable / Constants follow
**********************************************************/
TRACE("(%p) : Releasing from %d\n", This, refCount + 1);
if (!refCount) {
+ UINT i;
+
+ for (i = 0; i < sizeof(This->multistate_funcs)/sizeof(This->multistate_funcs[0]); ++i) {
+ HeapFree(GetProcessHeap(), 0, This->multistate_funcs[i]);
+ This->multistate_funcs[i] = NULL;
+ }
+
/* TODO: Clean up all the surfaces and textures! */
/* NOTE: You must release the parent if the object was created via a callback
** ***************************/
IWineD3DVertexBufferImpl *object;
WINED3DFORMAT Format = WINED3DFMT_VERTEXDATA; /* Dummy format for now */
int dxVersion = ( (IWineD3DImpl *) This->wineD3D)->dxVersion;
+ HRESULT hr;
BOOL conv;
if(Size == 0) {
return WINED3DERR_INVALIDCALL;
}
- D3DCREATERESOURCEOBJECTINSTANCE(object, VertexBuffer, WINED3DRTYPE_VERTEXBUFFER, Size)
+ object = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*object));
+ if (!object)
+ {
+ ERR("Out of memory\n");
+ *ppVertexBuffer = NULL;
+ return WINED3DERR_OUTOFVIDEOMEMORY;
+ }
+
+ object->lpVtbl = &IWineD3DVertexBuffer_Vtbl;
+ hr = resource_init(&object->resource, WINED3DRTYPE_VERTEXBUFFER, This, Size, Usage, Format, Pool, parent);
+ if (FAILED(hr))
+ {
+ WARN("Failed to initialize resource, returning %#x\n", hr);
+ HeapFree(GetProcessHeap(), 0, object);
+ *ppVertexBuffer = NULL;
+ return hr;
+ }
+
+ TRACE("(%p) : Created resource %p\n", This, object);
+
+ IWineD3DDeviceImpl_AddResource(iface, (IWineD3DResource *)object);
TRACE("(%p) : Size=%d, Usage=0x%08x, FVF=%x, Pool=%d - Memory@%p, Iface@%p\n", This, Size, Usage, FVF, Pool, object->resource.allocatedMemory, object);
*ppVertexBuffer = (IWineD3DVertexBuffer *)object;
HANDLE *sharedHandle, IUnknown *parent) {
IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
IWineD3DIndexBufferImpl *object;
+ HRESULT hr;
+
TRACE("(%p) Creating index buffer\n", This);
/* Allocate the storage for the device */
- D3DCREATERESOURCEOBJECTINSTANCE(object,IndexBuffer,WINED3DRTYPE_INDEXBUFFER, Length)
+ object = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*object));
+ if (!object)
+ {
+ ERR("Out of memory\n");
+ *ppIndexBuffer = NULL;
+ return WINED3DERR_OUTOFVIDEOMEMORY;
+ }
+
+ object->lpVtbl = &IWineD3DIndexBuffer_Vtbl;
+ hr = resource_init(&object->resource, WINED3DRTYPE_INDEXBUFFER, This, Length, Usage, Format, Pool, parent);
+ if (FAILED(hr))
+ {
+ WARN("Failed to initialize resource, returning %#x\n", hr);
+ HeapFree(GetProcessHeap(), 0, object);
+ *ppIndexBuffer = NULL;
+ return hr;
+ }
+
+ TRACE("(%p) : Created resource %p\n", This, object);
+
+ IWineD3DDeviceImpl_AddResource(iface, (IWineD3DResource *)object);
if(Pool != WINED3DPOOL_SYSTEMMEM && !(Usage & WINED3DUSAGE_DYNAMIC) && GL_SUPPORT(ARB_VERTEX_BUFFER_OBJECT)) {
CreateIndexBufferVBO(This, object);
int i, j;
HRESULT temp_result;
- D3DCREATEOBJECTINSTANCE(object, StateBlock)
- object->blockType = Type;
+ object = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*object));
+ if(!object)
+ {
+ ERR("Out of memory\n");
+ *ppStateBlock = NULL;
+ return WINED3DERR_OUTOFVIDEOMEMORY;
+ }
+
+ object->lpVtbl = &IWineD3DStateBlock_Vtbl;
+ object->wineD3DDevice = This;
+ object->parent = parent;
+ object->ref = 1;
+ object->blockType = Type;
+
+ *ppStateBlock = (IWineD3DStateBlock *)object;
for(i = 0; i < LIGHTMAP_SIZE; i++) {
list_init(&object->lightMap[i]);
}
+ temp_result = allocate_shader_constants(object);
+ if (FAILED(temp_result))
+ {
+ HeapFree(GetProcessHeap(), 0, object);
+ return temp_result;
+ }
+
/* Special case - Used during initialization to produce a placeholder stateblock
so other functions called can update a state block */
- if (Type == WINED3DSBT_INIT) {
+ if (Type == WINED3DSBT_INIT || Type == WINED3DSBT_RECORDED)
+ {
/* Don't bother increasing the reference count otherwise a device will never
be freed due to circular dependencies */
return WINED3D_OK;
}
-
- temp_result = allocate_shader_constants(object);
- if (WINED3D_OK != temp_result)
- return temp_result;
/* Otherwise, might as well set the whole state block to the appropriate values */
if (This->stateBlock != NULL)
}
object->num_contained_ps_consts_b = MAX_CONST_B;
for(i = 0; i < MAX_TEXTURES; i++) {
- for(j = 1; j <= WINED3D_HIGHEST_TEXTURE_STATE; j++) {
+ for (j = 0; j <= WINED3D_HIGHEST_TEXTURE_STATE; ++j)
+ {
object->contained_tss_states[object->num_contained_tss_states].stage = i;
object->contained_tss_states[object->num_contained_tss_states].state = j;
object->num_contained_tss_states++;
object->num_contained_ps_consts_i = MAX_CONST_I;
for (i = 0; i < NUM_SAVEDPIXELSTATES_R; i++) {
- object->changed.renderState[SavedPixelStates_R[i]] = TRUE;
- object->contained_render_states[i] = SavedPixelStates_R[i];
+ DWORD rs = SavedPixelStates_R[i];
+ object->changed.renderState[rs >> 5] |= 1 << (rs & 0x1f);
+ object->contained_render_states[i] = rs;
}
object->num_contained_render_states = NUM_SAVEDPIXELSTATES_R;
for (j = 0; j < MAX_TEXTURES; j++) {
for (i = 0; i < NUM_SAVEDPIXELSTATES_T; i++) {
- object->changed.textureState[j][SavedPixelStates_T[i]] = TRUE;
+ DWORD state = SavedPixelStates_T[i];
+ object->changed.textureState[j] |= 1 << state;
object->contained_tss_states[object->num_contained_tss_states].stage = j;
- object->contained_tss_states[object->num_contained_tss_states].state = SavedPixelStates_T[i];
+ object->contained_tss_states[object->num_contained_tss_states].state = state;
object->num_contained_tss_states++;
}
}
for (j = 0 ; j < MAX_COMBINED_SAMPLERS; j++) {
for (i =0; i < NUM_SAVEDPIXELSTATES_S;i++) {
- object->changed.samplerState[j][SavedPixelStates_S[i]] = TRUE;
+ DWORD state = SavedPixelStates_S[i];
+ object->changed.samplerState[j] |= 1 << state;
object->contained_sampler_states[object->num_contained_sampler_states].stage = j;
- object->contained_sampler_states[object->num_contained_sampler_states].state = SavedPixelStates_S[i];
+ object->contained_sampler_states[object->num_contained_sampler_states].state = state;
object->num_contained_sampler_states++;
}
}
}
object->num_contained_vs_consts_i = MAX_CONST_I;
for (i = 0; i < NUM_SAVEDVERTEXSTATES_R; i++) {
- object->changed.renderState[SavedVertexStates_R[i]] = TRUE;
- object->contained_render_states[i] = SavedVertexStates_R[i];
+ DWORD rs = SavedVertexStates_R[i];
+ object->changed.renderState[rs >> 5] |= 1 << (rs & 0x1f);
+ object->contained_render_states[i] = rs;
}
object->num_contained_render_states = NUM_SAVEDVERTEXSTATES_R;
for (j = 0; j < MAX_TEXTURES; j++) {
for (i = 0; i < NUM_SAVEDVERTEXSTATES_T; i++) {
- object->changed.textureState[j][SavedVertexStates_T[i]] = TRUE;
+ DWORD state = SavedVertexStates_T[i];
+ object->changed.textureState[j] |= 1 << state;
object->contained_tss_states[object->num_contained_tss_states].stage = j;
- object->contained_tss_states[object->num_contained_tss_states].state = SavedVertexStates_T[i];
+ object->contained_tss_states[object->num_contained_tss_states].state = state;
object->num_contained_tss_states++;
}
}
for (j = 0 ; j < MAX_COMBINED_SAMPLERS; j++){
for (i =0; i < NUM_SAVEDVERTEXSTATES_S;i++) {
- object->changed.samplerState[j][SavedVertexStates_S[i]] = TRUE;
+ DWORD state = SavedVertexStates_S[i];
+ object->changed.samplerState[j] |= 1 << state;
object->contained_sampler_states[object->num_contained_sampler_states].stage = j;
- object->contained_sampler_states[object->num_contained_sampler_states].state = SavedVertexStates_S[i];
+ object->contained_sampler_states[object->num_contained_sampler_states].state = state;
object->num_contained_sampler_states++;
}
}
return WINED3D_OK;
}
-/* ************************************
-MSDN:
-[in] Render targets are not lockable unless the application specifies TRUE for Lockable. Note that lockable render targets reduce performance on some graphics hardware.
-
-Discard
- [in] Set this flag to TRUE to enable z-buffer discarding, and FALSE otherwise.
-
-If this flag is set, the contents of the depth stencil buffer will be invalid after calling either IDirect3DDevice9::Present or IDirect3DDevice9::SetDepthStencilSurface with a different depth surface.
-
-******************************** */
-
static HRESULT WINAPI IWineD3DDeviceImpl_CreateSurface(IWineD3DDevice *iface, UINT Width, UINT Height, WINED3DFORMAT Format, BOOL Lockable, BOOL Discard, UINT Level, IWineD3DSurface **ppSurface,WINED3DRESOURCETYPE Type, DWORD Usage, WINED3DPOOL Pool, WINED3DMULTISAMPLE_TYPE MultiSample ,DWORD MultisampleQuality, HANDLE* pSharedHandle, WINED3DSURFTYPE Impl, IUnknown *parent) {
IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
IWineD3DSurfaceImpl *object; /*NOTE: impl ref allowed since this is a create function */
const struct GlPixelFormatDesc *glDesc;
const StaticPixelFormatDesc *tableEntry = getFormatDescEntry(Format, &GLINFO_LOCATION, &glDesc);
UINT mul_4w, mul_4h;
- TRACE("(%p) Create surface\n",This);
-
- /** FIXME: Check ranges on the inputs are valid
- * MSDN
- * MultisampleQuality
- * [in] Quality level. The valid range is between zero and one less than the level
- * returned by pQualityLevels used by IDirect3D9::CheckDeviceMultiSampleType.
- * Passing a larger value returns the error WINED3DERR_INVALIDCALL. The MultisampleQuality
- * values of paired render targets, depth stencil surfaces, and the MultiSample type
- * must all match.
- *******************************/
-
+ HRESULT hr;
- /**
- * TODO: Discard MSDN
- * [in] Set this flag to TRUE to enable z-buffer discarding, and FALSE otherwise.
- *
- * If this flag is set, the contents of the depth stencil buffer will be
- * invalid after calling either IDirect3DDevice9::Present or * IDirect3DDevice9::SetDepthStencilSurface
- * with a different depth surface.
- *
- *This flag has the same behavior as the constant, D3DPRESENTFLAG_DISCARD_DEPTHSTENCIL, in D3DPRESENTFLAG.
- ***************************/
+ TRACE("(%p) Create surface\n",This);
if(MultisampleQuality > 0) {
FIXME("MultisampleQuality set to %d, substituting 0\n", MultisampleQuality);
if(glDesc->heightscale != 0.0) Size *= glDesc->heightscale;
/** Create and initialise the surface resource **/
- D3DCREATERESOURCEOBJECTINSTANCE(object,Surface,WINED3DRTYPE_SURFACE, Size)
+ object = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*object));
+ if (!object)
+ {
+ ERR("Out of memory\n");
+ *ppSurface = NULL;
+ return WINED3DERR_OUTOFVIDEOMEMORY;
+ }
+
+ /* Look at the implementation and set the correct Vtable */
+ switch(Impl)
+ {
+ case SURFACE_OPENGL:
+ /* Check if a 3D adapter is available when creating gl surfaces */
+ if (!This->adapter)
+ {
+ ERR("OpenGL surfaces are not available without opengl\n");
+ HeapFree(GetProcessHeap(), 0, object);
+ return WINED3DERR_NOTAVAILABLE;
+ }
+ object->lpVtbl = &IWineD3DSurface_Vtbl;
+ break;
+
+ case SURFACE_GDI:
+ object->lpVtbl = &IWineGDISurface_Vtbl;
+ break;
+
+ default:
+ /* To be sure to catch this */
+ ERR("Unknown requested surface implementation %d!\n", Impl);
+ HeapFree(GetProcessHeap(), 0, object);
+ return WINED3DERR_INVALIDCALL;
+ }
+
+ hr = resource_init(&object->resource, WINED3DRTYPE_SURFACE, This, Size, Usage, Format, Pool, parent);
+ if (FAILED(hr))
+ {
+ WARN("Failed to initialize resource, returning %#x\n", hr);
+ HeapFree(GetProcessHeap(), 0, object);
+ *ppSurface = NULL;
+ return hr;
+ }
+
+ TRACE("(%p) : Created resource %p\n", This, object);
+
+ IWineD3DDeviceImpl_AddResource(iface, (IWineD3DResource *)object);
+
+ *ppSurface = (IWineD3DSurface *)object;
+
/* "Standalone" surface */
IWineD3DSurface_SetContainer((IWineD3DSurface *)object, NULL);
}
/* mark the texture as dirty so that it gets loaded first time around*/
- IWineD3DSurface_AddDirtyRect(*ppSurface, NULL);
+ surface_add_dirty_rect(*ppSurface, NULL);
TRACE("(%p) : w(%d) h(%d) fmt(%d,%s) lockable(%d) surf@%p, surfmem@%p, %d bytes\n",
This, Width, Height, Format, debug_d3dformat(Format),
(WINED3DFMT_D16_LOCKABLE == Format), *ppSurface, object->resource.allocatedMemory, object->resource.size);
- /* Look at the implementation and set the correct Vtable */
- switch(Impl) {
- case SURFACE_OPENGL:
- /* Check if a 3D adapter is available when creating gl surfaces */
- if(!This->adapter) {
- ERR("OpenGL surfaces are not available without opengl\n");
- HeapFree(GetProcessHeap(), 0, object->resource.allocatedMemory);
- HeapFree(GetProcessHeap(), 0, object);
- return WINED3DERR_NOTAVAILABLE;
- }
- break;
-
- case SURFACE_GDI:
- object->lpVtbl = &IWineGDISurface_Vtbl;
- break;
-
- default:
- /* To be sure to catch this */
- ERR("Unknown requested surface implementation %d!\n", Impl);
- IWineD3DSurface_Release((IWineD3DSurface *) object);
- return WINED3DERR_INVALIDCALL;
- }
-
list_init(&object->renderbuffers);
/* Call the private setup routine */
- return IWineD3DSurface_PrivateSetup( (IWineD3DSurface *) object );
+ hr = IWineD3DSurface_PrivateSetup((IWineD3DSurface *)object);
+ if (FAILED(hr))
+ {
+ ERR("Private setup failed, returning %#x\n", hr);
+ IWineD3DSurface_Release(*ppSurface);
+ *ppSurface = NULL;
+ return hr;
+ }
+ return hr;
}
-static HRESULT WINAPI IWineD3DDeviceImpl_CreateTexture(IWineD3DDevice *iface, UINT Width, UINT Height, UINT Levels,
- DWORD Usage, WINED3DFORMAT Format, WINED3DPOOL Pool,
- IWineD3DTexture** ppTexture, HANDLE* pSharedHandle, IUnknown *parent,
- D3DCB_CREATESURFACEFN D3DCB_CreateSurface) {
-
+static HRESULT WINAPI IWineD3DDeviceImpl_CreateTexture(IWineD3DDevice *iface,
+ UINT Width, UINT Height, UINT Levels, DWORD Usage, WINED3DFORMAT Format, WINED3DPOOL Pool,
+ IWineD3DTexture **ppTexture, HANDLE *pSharedHandle, IUnknown *parent)
+{
IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
IWineD3DTextureImpl *object;
unsigned int i;
return WINED3DERR_INVALIDCALL;
}
- D3DCREATERESOURCEOBJECTINSTANCE(object, Texture, WINED3DRTYPE_TEXTURE, 0);
- D3DINITIALIZEBASETEXTURE(object->baseTexture);
- object->width = Width;
- object->height = Height;
-
- if(glDesc->Flags & WINED3DFMT_FLAG_FILTERING) {
- object->baseTexture.minMipLookup = minMipLookup;
- object->baseTexture.magLookup = magLookup;
- } else {
- object->baseTexture.minMipLookup = minMipLookup_noFilter;
- object->baseTexture.magLookup = magLookup_noFilter;
- }
-
- /** Non-power2 support **/
- if (GL_SUPPORT(ARB_TEXTURE_NON_POWER_OF_TWO)) {
+ /* Non-power2 support */
+ if (GL_SUPPORT(ARB_TEXTURE_NON_POWER_OF_TWO))
+ {
pow2Width = Width;
pow2Height = Height;
- } else {
+ }
+ else
+ {
/* Find the nearest pow2 match */
pow2Width = pow2Height = 1;
while (pow2Width < Width) pow2Width <<= 1;
while (pow2Height < Height) pow2Height <<= 1;
- if(pow2Width != Width || pow2Height != Height) {
- if(Levels > 1) {
+ if (pow2Width != Width || pow2Height != Height)
+ {
+ if (Levels > 1)
+ {
WARN("Attempted to create a mipmapped np2 texture without unconditional np2 support\n");
- HeapFree(GetProcessHeap(), 0, object);
- *ppTexture = NULL;
return WINED3DERR_INVALIDCALL;
- } else {
- Levels = 1;
}
+ Levels = 1;
}
}
+ /* Calculate levels for mip mapping */
+ if (Usage & WINED3DUSAGE_AUTOGENMIPMAP)
+ {
+ if (!GL_SUPPORT(SGIS_GENERATE_MIPMAP))
+ {
+ WARN("No mipmap generation support, returning D3DERR_INVALIDCALL\n");
+ return WINED3DERR_INVALIDCALL;
+ }
+
+ if (Levels > 1)
+ {
+ WARN("D3DUSAGE_AUTOGENMIPMAP is set, and level count > 1, returning D3DERR_INVALIDCALL\n");
+ return WINED3DERR_INVALIDCALL;
+ }
+
+ Levels = 1;
+ }
+ else if (!Levels)
+ {
+ Levels = wined3d_log2i(max(Width, Height)) + 1;
+ TRACE("Calculated levels = %d\n", Levels);
+ }
+
+ object = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*object));
+ if (!object)
+ {
+ ERR("Out of memory\n");
+ *ppTexture = NULL;
+ return WINED3DERR_OUTOFVIDEOMEMORY;
+ }
+
+ object->lpVtbl = &IWineD3DTexture_Vtbl;
+ hr = resource_init(&object->resource, WINED3DRTYPE_TEXTURE, This, 0, Usage, Format, Pool, parent);
+ if (FAILED(hr))
+ {
+ WARN("Failed to initialize resource, returning %#x\n", hr);
+ HeapFree(GetProcessHeap(), 0, object);
+ *ppTexture = NULL;
+ return hr;
+ }
+
+ TRACE("(%p) : Created resource %p\n", This, object);
+
+ IWineD3DDeviceImpl_AddResource(iface, (IWineD3DResource *)object);
+
+ *ppTexture = (IWineD3DTexture *)object;
+
+ basetexture_init(&object->baseTexture, Levels, Usage);
+ object->width = Width;
+ object->height = Height;
+
+ if(glDesc->Flags & WINED3DFMT_FLAG_FILTERING) {
+ object->baseTexture.minMipLookup = minMipLookup;
+ object->baseTexture.magLookup = magLookup;
+ } else {
+ object->baseTexture.minMipLookup = minMipLookup_noFilter;
+ object->baseTexture.magLookup = magLookup_noFilter;
+ }
+
/** FIXME: add support for real non-power-two if it's provided by the video card **/
/* Precalculated scaling for 'faked' non power of two texture coords.
Second also don't use ARB_TEXTURE_RECTANGLE in case the surface format is P8 and EXT_PALETTED_TEXTURE
}
TRACE(" xf(%f) yf(%f)\n", object->baseTexture.pow2Matrix[0], object->baseTexture.pow2Matrix[5]);
- /* Calculate levels for mip mapping */
- if (Usage & WINED3DUSAGE_AUTOGENMIPMAP) {
- if(!GL_SUPPORT(SGIS_GENERATE_MIPMAP)) {
- WARN("No mipmap generation support, returning D3DERR_INVALIDCALL\n");
- return WINED3DERR_INVALIDCALL;
- }
- if(Levels > 1) {
- WARN("D3DUSAGE_AUTOGENMIPMAP is set, and level count > 1, returning D3DERR_INVALIDCALL\n");
- return WINED3DERR_INVALIDCALL;
- }
- object->baseTexture.levels = 1;
- } else if (Levels == 0) {
- TRACE("calculating levels %d\n", object->baseTexture.levels);
- object->baseTexture.levels++;
- tmpW = Width;
- tmpH = Height;
- while (tmpW > 1 || tmpH > 1) {
- tmpW = max(1, tmpW >> 1);
- tmpH = max(1, tmpH >> 1);
- object->baseTexture.levels++;
- }
- TRACE("Calculated levels = %d\n", object->baseTexture.levels);
- }
-
/* Generate all the surfaces */
tmpW = Width;
tmpH = Height;
for (i = 0; i < object->baseTexture.levels; i++)
{
/* use the callback to create the texture surface */
- hr = D3DCB_CreateSurface(This->parent, parent, tmpW, tmpH, Format, Usage, Pool, i, WINED3DCUBEMAP_FACE_POSITIVE_X, &object->surfaces[i],NULL);
+ hr = IWineD3DDeviceParent_CreateSurface(This->device_parent, parent, tmpW, tmpH, Format,
+ Usage, Pool, i, WINED3DCUBEMAP_FACE_POSITIVE_X, &object->surfaces[i]);
if (hr!= WINED3D_OK || ( (IWineD3DSurfaceImpl *) object->surfaces[i])->Flags & SFLAG_OVERSIZE) {
FIXME("Failed to create surface %p\n", object);
/* clean up */
}
static HRESULT WINAPI IWineD3DDeviceImpl_CreateVolumeTexture(IWineD3DDevice *iface,
- UINT Width, UINT Height, UINT Depth,
- UINT Levels, DWORD Usage,
- WINED3DFORMAT Format, WINED3DPOOL Pool,
- IWineD3DVolumeTexture **ppVolumeTexture,
- HANDLE *pSharedHandle, IUnknown *parent,
- D3DCB_CREATEVOLUMEFN D3DCB_CreateVolume) {
-
+ UINT Width, UINT Height, UINT Depth, UINT Levels, DWORD Usage, WINED3DFORMAT Format, WINED3DPOOL Pool,
+ IWineD3DVolumeTexture **ppVolumeTexture, HANDLE *pSharedHandle, IUnknown *parent)
+{
IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
IWineD3DVolumeTextureImpl *object;
unsigned int i;
UINT tmpH;
UINT tmpD;
const struct GlPixelFormatDesc *glDesc;
+ HRESULT hr;
getFormatDescEntry(Format, &GLINFO_LOCATION, &glDesc);
return WINED3DERR_INVALIDCALL;
}
- D3DCREATERESOURCEOBJECTINSTANCE(object, VolumeTexture, WINED3DRTYPE_VOLUMETEXTURE, 0);
- D3DINITIALIZEBASETEXTURE(object->baseTexture);
+ /* Calculate levels for mip mapping */
+ if (Usage & WINED3DUSAGE_AUTOGENMIPMAP)
+ {
+ if (!GL_SUPPORT(SGIS_GENERATE_MIPMAP))
+ {
+ WARN("No mipmap generation support, returning D3DERR_INVALIDCALL\n");
+ return WINED3DERR_INVALIDCALL;
+ }
+
+ if (Levels > 1)
+ {
+ WARN("D3DUSAGE_AUTOGENMIPMAP is set, and level count > 1, returning D3DERR_INVALIDCALL\n");
+ return WINED3DERR_INVALIDCALL;
+ }
+
+ Levels = 1;
+ }
+ else if (!Levels)
+ {
+ Levels = wined3d_log2i(max(max(Width, Height), Depth)) + 1;
+ TRACE("Calculated levels = %d\n", Levels);
+ }
+
+ object = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*object));
+ if (!object)
+ {
+ ERR("Out of memory\n");
+ *ppVolumeTexture = NULL;
+ return WINED3DERR_OUTOFVIDEOMEMORY;
+ }
+
+ object->lpVtbl = &IWineD3DVolumeTexture_Vtbl;
+ hr = resource_init(&object->resource, WINED3DRTYPE_VOLUMETEXTURE, This, 0, Usage, Format, Pool, parent);
+ if (FAILED(hr))
+ {
+ WARN("Failed to initialize resource, returning %#x\n", hr);
+ HeapFree(GetProcessHeap(), 0, object);
+ *ppVolumeTexture = NULL;
+ return hr;
+ }
+
+ TRACE("(%p) : Created resource %p\n", This, object);
+
+ IWineD3DDeviceImpl_AddResource(iface, (IWineD3DResource *)object);
+
+ basetexture_init(&object->baseTexture, Levels, Usage);
TRACE("(%p) : W(%d) H(%d) D(%d), Lvl(%d) Usage(%d), Fmt(%u,%s), Pool(%s)\n", This, Width, Height,
Depth, Levels, Usage, Format, debug_d3dformat(Format), debug_d3dpool(Pool));
object->baseTexture.magLookup = magLookup_noFilter;
}
- /* Calculate levels for mip mapping */
- if (Usage & WINED3DUSAGE_AUTOGENMIPMAP) {
- if(!GL_SUPPORT(SGIS_GENERATE_MIPMAP)) {
- WARN("No mipmap generation support, returning D3DERR_INVALIDCALL\n");
- return WINED3DERR_INVALIDCALL;
- }
- if(Levels > 1) {
- WARN("D3DUSAGE_AUTOGENMIPMAP is set, and level count > 1, returning D3DERR_INVALIDCALL\n");
- return WINED3DERR_INVALIDCALL;
- }
- object->baseTexture.levels = 1;
- } else if (Levels == 0) {
- object->baseTexture.levels++;
- tmpW = Width;
- tmpH = Height;
- tmpD = Depth;
- while (tmpW > 1 || tmpH > 1 || tmpD > 1) {
- tmpW = max(1, tmpW >> 1);
- tmpH = max(1, tmpH >> 1);
- tmpD = max(1, tmpD >> 1);
- object->baseTexture.levels++;
- }
- TRACE("Calculated levels = %d\n", object->baseTexture.levels);
- }
-
/* Generate all the surfaces */
tmpW = Width;
tmpH = Height;
{
HRESULT hr;
/* Create the volume */
- hr = D3DCB_CreateVolume(This->parent, parent, tmpW, tmpH, tmpD, Format, Pool, Usage,
- &object->volumes[i], pSharedHandle);
-
+ hr = IWineD3DDeviceParent_CreateVolume(This->device_parent, parent,
+ tmpW, tmpH, tmpD, Format, Pool, Usage, &object->volumes[i]);
if(FAILED(hr)) {
ERR("Creating a volume for the volume texture failed(%08x)\n", hr);
IWineD3DVolumeTexture_Release((IWineD3DVolumeTexture *) object);
IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
IWineD3DVolumeImpl *object; /** NOTE: impl ref allowed since this is a create function **/
const StaticPixelFormatDesc *formatDesc = getFormatDescEntry(Format, NULL, NULL);
+ HRESULT hr;
if(!GL_SUPPORT(EXT_TEXTURE3D)) {
WARN("(%p) : Volume cannot be created - no volume texture support\n", This);
return WINED3DERR_INVALIDCALL;
}
- D3DCREATERESOURCEOBJECTINSTANCE(object, Volume, WINED3DRTYPE_VOLUME, ((Width * formatDesc->bpp) * Height * Depth))
+ object = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*object));
+ if (!object)
+ {
+ ERR("Out of memory\n");
+ *ppVolume = NULL;
+ return WINED3DERR_OUTOFVIDEOMEMORY;
+ }
+
+ object->lpVtbl = &IWineD3DVolume_Vtbl;
+ hr = resource_init(&object->resource, WINED3DRTYPE_VOLUME, This,
+ Width * Height * Depth * formatDesc->bpp, Usage, Format, Pool, parent);
+ if (FAILED(hr))
+ {
+ WARN("Failed to initialize resource, returning %#x\n", hr);
+ HeapFree(GetProcessHeap(), 0, object);
+ *ppVolume = NULL;
+ return hr;
+ }
+
+ TRACE("(%p) : Created resource %p\n", This, object);
+
+ IWineD3DDeviceImpl_AddResource(iface, (IWineD3DResource *)object);
+
+ *ppVolume = (IWineD3DVolume *)object;
TRACE("(%p) : W(%d) H(%d) D(%d), Usage(%d), Fmt(%u,%s), Pool(%s)\n", This, Width, Height,
Depth, Usage, Format, debug_d3dformat(Format), debug_d3dpool(Pool));
memset(&object->lockedBox, 0, sizeof(WINED3DBOX));
object->dirty = TRUE;
- return IWineD3DVolume_AddDirtyBox((IWineD3DVolume *) object, NULL);
-}
+ volume_add_dirty_box((IWineD3DVolume *)object, NULL);
-static HRESULT WINAPI IWineD3DDeviceImpl_CreateCubeTexture(IWineD3DDevice *iface, UINT EdgeLength,
- UINT Levels, DWORD Usage,
- WINED3DFORMAT Format, WINED3DPOOL Pool,
- IWineD3DCubeTexture **ppCubeTexture,
- HANDLE *pSharedHandle, IUnknown *parent,
- D3DCB_CREATESURFACEFN D3DCB_CreateSurface) {
+ return WINED3D_OK;
+}
+static HRESULT WINAPI IWineD3DDeviceImpl_CreateCubeTexture(IWineD3DDevice *iface,
+ UINT EdgeLength, UINT Levels, DWORD Usage, WINED3DFORMAT Format, WINED3DPOOL Pool,
+ IWineD3DCubeTexture **ppCubeTexture, HANDLE *pSharedHandle, IUnknown *parent)
+{
IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
IWineD3DCubeTextureImpl *object; /** NOTE: impl ref allowed since this is a create function **/
unsigned int i, j;
return WINED3DERR_INVALIDCALL;
}
- D3DCREATERESOURCEOBJECTINSTANCE(object, CubeTexture, WINED3DRTYPE_CUBETEXTURE, 0);
- D3DINITIALIZEBASETEXTURE(object->baseTexture);
+ /* Calculate levels for mip mapping */
+ if (Usage & WINED3DUSAGE_AUTOGENMIPMAP)
+ {
+ if (!GL_SUPPORT(SGIS_GENERATE_MIPMAP))
+ {
+ WARN("No mipmap generation support, returning D3DERR_INVALIDCALL\n");
+ return WINED3DERR_INVALIDCALL;
+ }
+
+ if (Levels > 1)
+ {
+ WARN("D3DUSAGE_AUTOGENMIPMAP is set, and level count > 1, returning D3DERR_INVALIDCALL\n");
+ return WINED3DERR_INVALIDCALL;
+ }
+
+ Levels = 1;
+ }
+ else if (!Levels)
+ {
+ Levels = wined3d_log2i(EdgeLength) + 1;
+ TRACE("Calculated levels = %d\n", Levels);
+ }
+
+ object = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*object));
+ if (!object)
+ {
+ ERR("Out of memory\n");
+ *ppCubeTexture = NULL;
+ return WINED3DERR_OUTOFVIDEOMEMORY;
+ }
+
+ object->lpVtbl = &IWineD3DCubeTexture_Vtbl;
+ hr = resource_init(&object->resource, WINED3DRTYPE_CUBETEXTURE, This, 0, Usage, Format, Pool, parent);
+ if (FAILED(hr))
+ {
+ WARN("Failed to initialize resource, returning %#x\n", hr);
+ HeapFree(GetProcessHeap(), 0, object);
+ *ppCubeTexture = NULL;
+ return hr;
+ }
+
+ TRACE("(%p) : Created resource %p\n", This, object);
+
+ IWineD3DDeviceImpl_AddResource(iface, (IWineD3DResource *)object);
+
+ basetexture_init(&object->baseTexture, Levels, Usage);
TRACE("(%p) Create Cube Texture\n", This);
object->baseTexture.magLookup = magLookup_noFilter;
}
- /* Calculate levels for mip mapping */
- if (Usage & WINED3DUSAGE_AUTOGENMIPMAP) {
- if(!GL_SUPPORT(SGIS_GENERATE_MIPMAP)) {
- WARN("No mipmap generation support, returning D3DERR_INVALIDCALL\n");
- HeapFree(GetProcessHeap(), 0, object);
- *ppCubeTexture = NULL;
-
- return WINED3DERR_INVALIDCALL;
- }
- if(Levels > 1) {
- WARN("D3DUSAGE_AUTOGENMIPMAP is set, and level count > 1, returning D3DERR_INVALIDCALL\n");
- HeapFree(GetProcessHeap(), 0, object);
- *ppCubeTexture = NULL;
-
- return WINED3DERR_INVALIDCALL;
- }
- object->baseTexture.levels = 1;
- } else if (Levels == 0) {
- object->baseTexture.levels++;
- tmpW = EdgeLength;
- while (tmpW > 1) {
- tmpW = max(1, tmpW >> 1);
- object->baseTexture.levels++;
- }
- TRACE("Calculated levels = %d\n", object->baseTexture.levels);
- }
-
/* Generate all the surfaces */
tmpW = EdgeLength;
for (i = 0; i < object->baseTexture.levels; i++) {
GL_TEXTURE_CUBE_MAP_NEGATIVE_Z_ARB
};
- hr=D3DCB_CreateSurface(This->parent, parent, tmpW, tmpW, Format, Usage, Pool,
- i /* Level */, j, &object->surfaces[j][i],pSharedHandle);
-
- if(hr!= WINED3D_OK) {
- /* clean up */
- unsigned int k;
- unsigned int l;
- for (l = 0; l < j; l++) {
- IWineD3DSurface_Release(object->surfaces[l][i]);
- }
- for (k = 0; k < i; k++) {
- for (l = 0; l < 6; l++) {
- IWineD3DSurface_Release(object->surfaces[l][k]);
- }
- }
-
+ hr = IWineD3DDeviceParent_CreateSurface(This->device_parent, parent, tmpW, tmpW,
+ Format, Usage, Pool, i /* Level */, j, &object->surfaces[j][i]);
+ if (FAILED(hr))
+ {
FIXME("(%p) Failed to create surface\n",object);
- HeapFree(GetProcessHeap(),0,object);
+ IWineD3DCubeTexture_Release((IWineD3DCubeTexture *)object);
*ppCubeTexture = NULL;
return hr;
}
return hr;
}
- D3DCREATEOBJECTINSTANCE(object, Query)
- object->lpVtbl = vtable;
- object->type = Type;
- object->state = QUERY_CREATED;
+ object = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*object));
+ if(!object)
+ {
+ ERR("Out of memory\n");
+ *ppQuery = NULL;
+ return WINED3DERR_OUTOFVIDEOMEMORY;
+ }
+
+ object->lpVtbl = vtable;
+ object->type = Type;
+ object->state = QUERY_CREATED;
+ object->wineD3DDevice = This;
+ object->parent = parent;
+ object->ref = 1;
+
+ *ppQuery = (IWineD3DQuery *)object;
+
/* allocated the 'extended' data based on the type of query requested */
switch(Type){
case WINED3DQUERYTYPE_OCCLUSION:
}
/* example at http://www.fairyengine.com/articles/dxmultiviews.htm */
-static HRESULT WINAPI IWineD3DDeviceImpl_CreateSwapChain(IWineD3DDevice* iface,
- WINED3DPRESENT_PARAMETERS* pPresentationParameters, IWineD3DSwapChain** ppSwapChain,
- IUnknown* parent, D3DCB_CREATERENDERTARGETFN D3DCB_CreateRenderTarget,
- D3DCB_CREATEDEPTHSTENCILSURFACEFN D3DCB_CreateDepthStencil, WINED3DSURFTYPE surface_type)
+static HRESULT WINAPI IWineD3DDeviceImpl_CreateSwapChain(IWineD3DDevice *iface,
+ WINED3DPRESENT_PARAMETERS *pPresentationParameters, IWineD3DSwapChain **ppSwapChain,
+ IUnknown *parent, WINED3DSURFTYPE surface_type)
{
IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
FIXME("The app requests more than one back buffer, this can't be supported properly. Please configure the application to use double buffering(=1 back buffer) if possible\n");
}
- D3DCREATEOBJECTINSTANCE(object, SwapChain)
+ object = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*object));
+ if(!object)
+ {
+ ERR("Out of memory\n");
+ *ppSwapChain = NULL;
+ return WINED3DERR_OUTOFVIDEOMEMORY;
+ }
+
switch(surface_type) {
case SURFACE_GDI:
object->lpVtbl = &IWineGDISwapChain_Vtbl;
break;
case SURFACE_UNKNOWN:
FIXME("Caller tried to create a SURFACE_UNKNOWN swapchain\n");
+ HeapFree(GetProcessHeap(), 0, object);
return WINED3DERR_INVALIDCALL;
}
+ object->wineD3DDevice = This;
+ object->parent = parent;
+ object->ref = 1;
+
+ *ppSwapChain = (IWineD3DSwapChain *)object;
/*********************
* Lookup the window Handle and the relating X window handle
object->orig_fmt = Mode.Format;
formatDesc = getFormatDescEntry(Mode.Format, NULL, NULL);
- /** MSDN: If Windowed is TRUE and either of the BackBufferWidth/Height values is zero,
- * then the corresponding dimension of the client area of the hDeviceWindow
- * (or the focus window, if hDeviceWindow is NULL) is taken.
- **********************/
-
if (pPresentationParameters->Windowed &&
((pPresentationParameters->BackBufferWidth == 0) ||
(pPresentationParameters->BackBufferHeight == 0) ||
object->presentParms = *pPresentationParameters;
TRACE("calling rendertarget CB\n");
- hr = D3DCB_CreateRenderTarget(This->parent,
- parent,
- object->presentParms.BackBufferWidth,
- object->presentParms.BackBufferHeight,
- object->presentParms.BackBufferFormat,
- object->presentParms.MultiSampleType,
- object->presentParms.MultiSampleQuality,
- TRUE /* Lockable */,
- &object->frontBuffer,
- NULL /* pShared (always null)*/);
+ hr = IWineD3DDeviceParent_CreateRenderTarget(This->device_parent, parent,
+ object->presentParms.BackBufferWidth, object->presentParms.BackBufferHeight,
+ object->presentParms.BackBufferFormat, object->presentParms.MultiSampleType,
+ object->presentParms.MultiSampleQuality, TRUE /* Lockable */, &object->frontBuffer);
if (SUCCEEDED(hr)) {
IWineD3DSurface_SetContainer(object->frontBuffer, (IWineD3DBase *)object);
if(surface_type == SURFACE_OPENGL) {
for(i = 0; i < object->presentParms.BackBufferCount; i++) {
TRACE("calling rendertarget CB\n");
- hr = D3DCB_CreateRenderTarget(This->parent,
- parent,
- object->presentParms.BackBufferWidth,
- object->presentParms.BackBufferHeight,
- object->presentParms.BackBufferFormat,
- object->presentParms.MultiSampleType,
- object->presentParms.MultiSampleQuality,
- TRUE /* Lockable */,
- &object->backBuffer[i],
- NULL /* pShared (always null)*/);
+ hr = IWineD3DDeviceParent_CreateRenderTarget(This->device_parent, parent,
+ object->presentParms.BackBufferWidth, object->presentParms.BackBufferHeight,
+ object->presentParms.BackBufferFormat, object->presentParms.MultiSampleType,
+ object->presentParms.MultiSampleQuality, TRUE /* Lockable */, &object->backBuffer[i]);
if(SUCCEEDED(hr)) {
IWineD3DSurface_SetContainer(object->backBuffer[i], (IWineD3DBase *)object);
} else {
if (pPresentationParameters->EnableAutoDepthStencil && surface_type == SURFACE_OPENGL) {
TRACE("Creating depth stencil buffer\n");
if (This->auto_depth_stencil_buffer == NULL ) {
- hr = D3DCB_CreateDepthStencil(This->parent,
- parent,
- object->presentParms.BackBufferWidth,
- object->presentParms.BackBufferHeight,
- object->presentParms.AutoDepthStencilFormat,
- object->presentParms.MultiSampleType,
- object->presentParms.MultiSampleQuality,
- FALSE /* FIXME: Discard */,
- &This->auto_depth_stencil_buffer,
- NULL /* pShared (always null)*/ );
+ hr = IWineD3DDeviceParent_CreateDepthStencilSurface(This->device_parent, parent,
+ object->presentParms.BackBufferWidth, object->presentParms.BackBufferHeight,
+ object->presentParms.AutoDepthStencilFormat, object->presentParms.MultiSampleType,
+ object->presentParms.MultiSampleQuality, FALSE /* FIXME: Discard */,
+ &This->auto_depth_stencil_buffer);
if (SUCCEEDED(hr)) {
IWineD3DSurface_SetContainer(This->auto_depth_stencil_buffer, 0);
} else {
TRACE("(%p) : directXVersion %u, elements %p, element_count %d, ppDecl=%p\n",
This, ((IWineD3DImpl *)This->wineD3D)->dxVersion, elements, element_count, ppVertexDeclaration);
- D3DCREATEOBJECTINSTANCE(object, VertexDeclaration)
+ object = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*object));
+ if(!object)
+ {
+ ERR("Out of memory\n");
+ *ppVertexDeclaration = NULL;
+ return WINED3DERR_OUTOFVIDEOMEMORY;
+ }
+
+ object->lpVtbl = &IWineD3DVertexDeclaration_Vtbl;
+ object->wineD3DDevice = This;
+ object->parent = parent;
+ object->ref = 1;
+
+ *ppVertexDeclaration = (IWineD3DVertexDeclaration *)object;
hr = IWineD3DVertexDeclaration_SetDeclaration((IWineD3DVertexDeclaration *)object, elements, element_count);
if(FAILED(hr)) {
elements[idx].Type = WINED3DDECLTYPE_FLOAT4;
elements[idx].Usage = WINED3DDECLUSAGE_POSITIONT;
}
+ else if ((fvf & WINED3DFVF_XYZW) == WINED3DFVF_XYZW) {
+ elements[idx].Type = WINED3DDECLTYPE_FLOAT4;
+ elements[idx].Usage = WINED3DDECLUSAGE_POSITION;
+ }
else {
elements[idx].Type = WINED3DDECLTYPE_FLOAT3;
elements[idx].Usage = WINED3DDECLUSAGE_POSITION;
IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
IWineD3DVertexShaderImpl *object; /* NOTE: impl usage is ok, this is a create */
HRESULT hr = WINED3D_OK;
- D3DCREATESHADEROBJECTINSTANCE(object, VertexShader)
- object->baseShader.shader_ins = IWineD3DVertexShaderImpl_shader_ins;
- TRACE("(%p) : Created Vertex shader %p\n", This, *ppVertexShader);
+ if (!pFunction) return WINED3DERR_INVALIDCALL;
+
+ object = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*object));
+ if (!object)
+ {
+ ERR("Out of memory\n");
+ *ppVertexShader = NULL;
+ return WINED3DERR_OUTOFVIDEOMEMORY;
+ }
+
+ object->lpVtbl = &IWineD3DVertexShader_Vtbl;
+ object->parent = parent;
+ shader_init(&object->baseShader, iface, IWineD3DVertexShaderImpl_shader_ins);
+ list_add_head(&This->shaders, &object->baseShader.shader_list_entry);
+ *ppVertexShader = (IWineD3DVertexShader *)object;
+
+ TRACE("(%p) : Created vertex shader %p\n", This, *ppVertexShader);
if (vertex_declaration) {
IWineD3DVertexShader_FakeSemantics(*ppVertexShader, vertex_declaration);
}
hr = IWineD3DVertexShader_SetFunction(*ppVertexShader, pFunction);
-
- if (WINED3D_OK != hr) {
- FIXME("(%p) : Failed to set the function, returning WINED3DERR_INVALIDCALL\n", iface);
+ if (FAILED(hr))
+ {
+ WARN("(%p) : Failed to set function, returning %#x\n", iface, hr);
IWineD3DVertexShader_Release(*ppVertexShader);
- return WINED3DERR_INVALIDCALL;
+ *ppVertexShader = NULL;
+ return hr;
}
- list_add_head(&This->shaders, &object->baseShader.shader_list_entry);
- return WINED3D_OK;
+ return hr;
}
static HRESULT WINAPI IWineD3DDeviceImpl_CreatePixelShader(IWineD3DDevice *iface, CONST DWORD *pFunction, IWineD3DPixelShader **ppPixelShader, IUnknown *parent) {
IWineD3DPixelShaderImpl *object; /* NOTE: impl allowed, this is a create */
HRESULT hr = WINED3D_OK;
- D3DCREATESHADEROBJECTINSTANCE(object, PixelShader)
- object->baseShader.shader_ins = IWineD3DPixelShaderImpl_shader_ins;
+ if (!pFunction) return WINED3DERR_INVALIDCALL;
+
+ object = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*object));
+ if (!object)
+ {
+ ERR("Out of memory\n");
+ *ppPixelShader = NULL;
+ return WINED3DERR_OUTOFVIDEOMEMORY;
+ }
+
+ object->lpVtbl = &IWineD3DPixelShader_Vtbl;
+ object->parent = parent;
+ shader_init(&object->baseShader, iface, IWineD3DPixelShaderImpl_shader_ins);
+ list_add_head(&This->shaders, &object->baseShader.shader_list_entry);
+ *ppPixelShader = (IWineD3DPixelShader *)object;
+
+ TRACE("(%p) : Created pixel shader %p\n", This, *ppPixelShader);
+
hr = IWineD3DPixelShader_SetFunction(*ppPixelShader, pFunction);
- if (WINED3D_OK == hr) {
- TRACE("(%p) : Created Pixel shader %p\n", This, *ppPixelShader);
- list_add_head(&This->shaders, &object->baseShader.shader_list_entry);
- } else {
- WARN("(%p) : Failed to create pixel shader\n", This);
+ if (FAILED(hr))
+ {
+ WARN("(%p) : Failed to set function, returning %#x\n", iface, hr);
+ IWineD3DPixelShader_Release(*ppPixelShader);
+ *ppPixelShader = NULL;
+ return hr;
}
return hr;
object->parent = Parent;
object->wineD3DDevice = This;
object->palNumEntries = IWineD3DPaletteImpl_Size(Flags);
-
object->hpal = CreatePalette((const LOGPALETTE*)&(object->palVersion));
if(!object->hpal) {
GLubyte white = 255;
/* Make appropriate texture active */
- if (GL_SUPPORT(ARB_MULTITEXTURE)) {
- GL_EXTCALL(glActiveTextureARB(GL_TEXTURE0_ARB + i));
- checkGLcall("glActiveTextureARB");
- } else if (i > 0) {
- FIXME("Program using multiple concurrent textures which this opengl implementation doesn't support\n");
- }
+ GL_EXTCALL(glActiveTextureARB(GL_TEXTURE0_ARB + i));
+ checkGLcall("glActiveTextureARB");
/* Generate an opengl texture name */
glGenTextures(1, &This->dummyTextureName[i]);
/* Generate a dummy 2d texture (not using 1d because they cause many
* DRI drivers fall back to sw) */
- This->stateBlock->textureDimensions[i] = GL_TEXTURE_2D;
glBindTexture(GL_TEXTURE_2D, This->dummyTextureName[i]);
checkGLcall("glBindTexture");
LEAVE_GL();
}
-static HRESULT WINAPI IWineD3DDeviceImpl_Init3D(IWineD3DDevice *iface, WINED3DPRESENT_PARAMETERS* pPresentationParameters, D3DCB_CREATESWAPCHAIN D3DCB_CreateSwapChain) {
+static HRESULT WINAPI IWineD3DDeviceImpl_Init3D(IWineD3DDevice *iface,
+ WINED3DPRESENT_PARAMETERS *pPresentationParameters)
+{
IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *) iface;
IWineD3DSwapChainImpl *swapchain = NULL;
HRESULT hr;
DWORD state;
unsigned int i;
- TRACE("(%p)->(%p,%p)\n", This, pPresentationParameters, D3DCB_CreateSwapChain);
+ TRACE("(%p)->(%p)\n", This, pPresentationParameters);
+
if(This->d3d_initialized) return WINED3DERR_INVALIDCALL;
if(!This->adapter->opengl) return WINED3DERR_INVALIDCALL;
This->updateStateBlock = This->stateBlock;
IWineD3DStateBlock_AddRef((IWineD3DStateBlock*)This->updateStateBlock);
- hr = allocate_shader_constants(This->updateStateBlock);
- if (WINED3D_OK != hr) {
- goto err_out;
- }
-
This->render_targets = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(IWineD3DSurface *) * GL_LIMITS(buffers));
This->draw_buffers = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(GLenum) * GL_LIMITS(buffers));
/* Setup the implicit swapchain */
TRACE("Creating implicit swapchain\n");
- hr=D3DCB_CreateSwapChain(This->parent, pPresentationParameters, (IWineD3DSwapChain **)&swapchain);
- if (FAILED(hr) || !swapchain) {
+ hr = IWineD3DDeviceParent_CreateSwapChain(This->device_parent,
+ pPresentationParameters, (IWineD3DSwapChain **)&swapchain);
+ if (FAILED(hr))
+ {
WARN("Failed to create implicit swapchain\n");
goto err_out;
}
ENTER_GL();
- { /* Set a default viewport */
- WINED3DVIEWPORT vp;
- vp.X = 0;
- vp.Y = 0;
- vp.Width = pPresentationParameters->BackBufferWidth;
- vp.Height = pPresentationParameters->BackBufferHeight;
- vp.MinZ = 0.0f;
- vp.MaxZ = 1.0f;
- IWineD3DDevice_SetViewport((IWineD3DDevice *)This, &vp);
- }
-
/* Initialize the current view state */
This->view_ident = 1;
This->contexts[0]->last_was_rhw = 0;
return hr;
}
-static HRESULT WINAPI IWineD3DDeviceImpl_InitGDI(IWineD3DDevice *iface, WINED3DPRESENT_PARAMETERS* pPresentationParameters, D3DCB_CREATESWAPCHAIN D3DCB_CreateSwapChain) {
+static HRESULT WINAPI IWineD3DDeviceImpl_InitGDI(IWineD3DDevice *iface,
+ WINED3DPRESENT_PARAMETERS *pPresentationParameters)
+{
IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *) iface;
IWineD3DSwapChainImpl *swapchain = NULL;
HRESULT hr;
/* Setup the implicit swapchain */
TRACE("Creating implicit swapchain\n");
- hr=D3DCB_CreateSwapChain(This->parent, pPresentationParameters, (IWineD3DSwapChain **)&swapchain);
- if (FAILED(hr) || !swapchain) {
+ hr = IWineD3DDeviceParent_CreateSwapChain(This->device_parent,
+ pPresentationParameters, (IWineD3DSwapChain **)&swapchain);
+ if (FAILED(hr))
+ {
WARN("Failed to create implicit swapchain\n");
goto err_out;
}
return (This->adapter->TextureRam - This->adapter->UsedTextureRam);
}
-
-
-/*****
- * Get / Set FVF
- *****/
-static HRESULT WINAPI IWineD3DDeviceImpl_SetFVF(IWineD3DDevice *iface, DWORD fvf) {
- IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
-
- /* Update the current state block */
- This->updateStateBlock->changed.fvf = TRUE;
-
- if(This->updateStateBlock->fvf == fvf) {
- TRACE("Application is setting the old fvf over, nothing to do\n");
- return WINED3D_OK;
- }
-
- This->updateStateBlock->fvf = fvf;
- TRACE("(%p) : FVF Shader FVF set to %x\n", This, fvf);
- IWineD3DDeviceImpl_MarkStateDirty(This, STATE_VDECL);
- return WINED3D_OK;
-}
-
-
-static HRESULT WINAPI IWineD3DDeviceImpl_GetFVF(IWineD3DDevice *iface, DWORD *pfvf) {
- IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
- TRACE("(%p) : GetFVF returning %x\n", This, This->stateBlock->fvf);
- *pfvf = This->stateBlock->fvf;
- return WINED3D_OK;
-}
-
/*****
* Get / Set Stream Source
*****/
oldSrc = This->updateStateBlock->streamSource[StreamNumber];
TRACE("(%p) : StreamNo: %u, OldStream (%p), NewStream (%p), OffsetInBytes %u, NewStride %u\n", This, StreamNumber, oldSrc, pStreamData, OffsetInBytes, Stride);
- This->updateStateBlock->changed.streamSource[StreamNumber] = TRUE;
+ This->updateStateBlock->changed.streamSource |= 1 << StreamNumber;
if(oldSrc == pStreamData &&
This->updateStateBlock->streamStride[StreamNumber] == Stride &&
return WINED3D_OK;
}
- /* Need to do a getParent and pass the references up */
- /* MSDN says ..... When an application no longer holds a reference to this interface, the interface will automatically be freed.
- which suggests that we shouldn't be ref counting? and do need a _release on the stream source to reset the stream source
- so for now, just count internally */
if (pStreamData != NULL) {
IWineD3DVertexBufferImpl *vbImpl = (IWineD3DVertexBufferImpl *) pStreamData;
InterlockedIncrement(&vbImpl->bindCount);
TRACE("(%p) StreamNumber(%d), Divider(%d)\n", This, StreamNumber, Divider);
This->updateStateBlock->streamFlags[StreamNumber] = Divider & (WINED3DSTREAMSOURCE_INSTANCEDATA | WINED3DSTREAMSOURCE_INDEXEDDATA );
- This->updateStateBlock->changed.streamFreq[StreamNumber] = TRUE;
+ This->updateStateBlock->changed.streamFreq |= 1 << StreamNumber;
This->updateStateBlock->streamFreq[StreamNumber] = Divider & 0x7FFFFF;
if(This->updateStateBlock->streamFreq[StreamNumber] != oldFreq ||
/* Handle recording of state blocks */
if (This->isRecordingState) {
TRACE("Recording... not performing anything\n");
- This->updateStateBlock->changed.transform[d3dts] = TRUE;
+ This->updateStateBlock->changed.transform[d3dts >> 5] |= 1 << (d3dts & 0x1f);
This->updateStateBlock->transforms[d3dts] = *lpmatrix;
return WINED3D_OK;
}
IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
TRACE("(%p) : For state %s\n", This, debug_d3dtstype(State));
- if (State < HIGHEST_TRANSFORMSTATE)
+ if (State <= HIGHEST_TRANSFORMSTATE)
{
mat = &This->updateStateBlock->transforms[State];
} else {
if (rho < 0.0001) rho = 0.0001f;
object->exponent = -0.3/log(cos(rho/2));
}
- if (object->exponent > 128.0) {
- object->exponent = 128.0;
- }
+ if (object->exponent > 128.0) {
+ object->exponent = 128.0;
+ }
object->cutoff = pLight->Phi*90/M_PI;
/* FIXME: Range */
*
* TODO: Test how this affects rendering
*/
- FIXME("Too many concurrently active lights\n");
+ WARN("Too many concurrently active lights\n");
return WINED3D_OK;
}
return WINED3DERR_INVALIDCALL;
}
- This->updateStateBlock->changed.clipplane[Index] = TRUE;
+ This->updateStateBlock->changed.clipplane |= 1 << Index;
if(This->updateStateBlock->clipplane[Index][0] == pPlane[0] &&
This->updateStateBlock->clipplane[Index][1] == pPlane[1] &&
TRACE("(%p)->state = %s(%d), value = %d\n", This, debug_d3drenderstate(State), State, Value);
- This->updateStateBlock->changed.renderState[State] = TRUE;
+ This->updateStateBlock->changed.renderState[State >> 5] |= 1 << (State & 0x1f);
This->updateStateBlock->renderState[State] = Value;
/* Handle recording of state blocks */
oldValue = This->stateBlock->samplerState[Sampler][Type];
This->updateStateBlock->samplerState[Sampler][Type] = Value;
- This->updateStateBlock->changed.samplerState[Sampler][Type] = Value;
+ This->updateStateBlock->changed.samplerState[Sampler] |= 1 << Type;
/* Handle recording of state blocks */
if (This->isRecordingState) {
This->updateStateBlock->changed.vertexShaderConstantsB |= (1 << i);
}
- IWineD3DDeviceImpl_MarkStateDirty(This, STATE_VERTEXSHADERCONSTANT);
+ if (!This->isRecordingState) IWineD3DDeviceImpl_MarkStateDirty(This, STATE_VERTEXSHADERCONSTANT);
return WINED3D_OK;
}
This->updateStateBlock->changed.vertexShaderConstantsI |= (1 << i);
}
- IWineD3DDeviceImpl_MarkStateDirty(This, STATE_VERTEXSHADERCONSTANT);
+ if (!This->isRecordingState) IWineD3DDeviceImpl_MarkStateDirty(This, STATE_VERTEXSHADERCONSTANT);
return WINED3D_OK;
}
int *dstData,
UINT count) {
- IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
- int cnt = min(count, MAX_CONST_I - start);
-
- TRACE("(iface %p, dstData %p, start %d, count %d)\n",
- iface, dstData, start, count);
-
- if (dstData == NULL || ((signed int) MAX_CONST_I - (signed int) start) <= (signed int) 0)
- return WINED3DERR_INVALIDCALL;
-
- memcpy(dstData, &This->stateBlock->vertexShaderConstantI[start * 4], cnt * sizeof(int) * 4);
- return WINED3D_OK;
-}
-
-static HRESULT WINAPI IWineD3DDeviceImpl_SetVertexShaderConstantF(
- IWineD3DDevice *iface,
- UINT start,
- CONST float *srcData,
- UINT count) {
-
- IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
- UINT i;
-
- TRACE("(iface %p, srcData %p, start %d, count %d)\n",
- iface, srcData, start, count);
-
- /* Specifically test start > limit to catch MAX_UINT overflows when adding start + count */
- if (srcData == NULL || start + count > GL_LIMITS(vshader_constantsF) || start > GL_LIMITS(vshader_constantsF))
- return WINED3DERR_INVALIDCALL;
-
- memcpy(&This->updateStateBlock->vertexShaderConstantF[start * 4], srcData, count * sizeof(float) * 4);
- if(TRACE_ON(d3d)) {
- for (i = 0; i < count; i++)
- TRACE("Set FLOAT constant %u to { %f, %f, %f, %f }\n", start + i,
- srcData[i*4], srcData[i*4+1], srcData[i*4+2], srcData[i*4+3]);
- }
+ IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
+ int cnt = min(count, MAX_CONST_I - start);
- for (i = start; i < count + start; ++i) {
- if (!This->updateStateBlock->changed.vertexShaderConstantsF[i]) {
- constants_entry *ptr = LIST_ENTRY(list_head(&This->updateStateBlock->set_vconstantsF), constants_entry, entry);
- if (!ptr || ptr->count >= sizeof(ptr->idx) / sizeof(*ptr->idx)) {
- ptr = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(constants_entry));
- list_add_head(&This->updateStateBlock->set_vconstantsF, &ptr->entry);
- }
- ptr->idx[ptr->count++] = i;
- This->updateStateBlock->changed.vertexShaderConstantsF[i] = TRUE;
- }
- }
+ TRACE("(iface %p, dstData %p, start %d, count %d)\n",
+ iface, dstData, start, count);
- IWineD3DDeviceImpl_MarkStateDirty(This, STATE_VERTEXSHADERCONSTANT);
+ if (dstData == NULL || ((signed int) MAX_CONST_I - (signed int) start) <= (signed int) 0)
+ return WINED3DERR_INVALIDCALL;
+ memcpy(dstData, &This->stateBlock->vertexShaderConstantI[start * 4], cnt * sizeof(int) * 4);
return WINED3D_OK;
}
-static HRESULT WINAPI IWineD3DDeviceImpl_SetVertexShaderConstantF_DirtyConst(
-IWineD3DDevice *iface,
-UINT start,
-CONST float *srcData,
-UINT count) {
+static HRESULT WINAPI IWineD3DDeviceImpl_SetVertexShaderConstantF(
+ IWineD3DDevice *iface,
+ UINT start,
+ CONST float *srcData,
+ UINT count) {
IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
UINT i;
if(TRACE_ON(d3d)) {
for (i = 0; i < count; i++)
TRACE("Set FLOAT constant %u to { %f, %f, %f, %f }\n", start + i,
- srcData[i*4], srcData[i*4+1], srcData[i*4+2], srcData[i*4+3]);
+ srcData[i*4], srcData[i*4+1], srcData[i*4+2], srcData[i*4+3]);
}
- /* We don't want shader constant dirtification to be an O(contexts), so just dirtify the active
- * context. On a context switch the old context will be fully dirtified
- */
- memset(This->activeContext->vshader_const_dirty + start, 1,
- sizeof(*This->activeContext->vshader_const_dirty) * count);
- This->highest_dirty_vs_const = max(This->highest_dirty_vs_const, start+count+1);
+ if (!This->isRecordingState)
+ {
+ This->shader_backend->shader_update_float_vertex_constants(iface, start, count);
+ IWineD3DDeviceImpl_MarkStateDirty(This, STATE_VERTEXSHADERCONSTANT);
+ }
- IWineD3DDeviceImpl_MarkStateDirty(This, STATE_VERTEXSHADERCONSTANT);
+ memset(This->updateStateBlock->changed.vertexShaderConstantsF + start, 1,
+ sizeof(*This->updateStateBlock->changed.vertexShaderConstantsF) * count);
return WINED3D_OK;
}
static inline void markTextureStagesDirty(IWineD3DDeviceImpl *This, DWORD stage) {
DWORD i;
- for(i = 0; i < WINED3D_HIGHEST_TEXTURE_STATE; i++) {
+ for(i = 0; i <= WINED3D_HIGHEST_TEXTURE_STATE; ++i)
+ {
IWineD3DDeviceImpl_MarkStateDirty(This, STATE_TEXTURESTAGE(stage, i));
}
}
static void device_update_fixed_function_usage_map(IWineD3DDeviceImpl *This) {
int i;
+ This->fixed_function_usage_map = 0;
for (i = 0; i < MAX_TEXTURES; ++i) {
WINED3DTEXTUREOP color_op = This->stateBlock->textureState[i][WINED3DTSS_COLOROP];
WINED3DTEXTUREOP alpha_op = This->stateBlock->textureState[i][WINED3DTSS_ALPHAOP];
if (color_op == WINED3DTOP_DISABLE) {
/* Not used, and disable higher stages */
- while (i < MAX_TEXTURES) {
- This->fixed_function_usage_map[i] = FALSE;
- ++i;
- }
break;
}
|| ((alpha_arg1 == WINED3DTA_TEXTURE) && alpha_op != WINED3DTOP_SELECTARG2)
|| ((alpha_arg2 == WINED3DTA_TEXTURE) && alpha_op != WINED3DTOP_SELECTARG1)
|| ((alpha_arg3 == WINED3DTA_TEXTURE) && (alpha_op == WINED3DTOP_MULTIPLYADD || alpha_op == WINED3DTOP_LERP))) {
- This->fixed_function_usage_map[i] = TRUE;
- } else {
- This->fixed_function_usage_map[i] = FALSE;
+ This->fixed_function_usage_map |= (1 << i);
}
if ((color_op == WINED3DTOP_BUMPENVMAP || color_op == WINED3DTOP_BUMPENVMAPLUMINANCE) && i < MAX_TEXTURES - 1) {
- This->fixed_function_usage_map[i+1] = TRUE;
+ This->fixed_function_usage_map |= (1 << (i + 1));
}
}
}
static void device_map_fixed_function_samplers(IWineD3DDeviceImpl *This) {
int i, tex;
+ WORD ffu_map;
device_update_fixed_function_usage_map(This);
+ ffu_map = This->fixed_function_usage_map;
if (This->max_ffp_textures == This->max_ffp_texture_stages ||
- This->stateBlock->lowest_disabled_stage <= This->max_ffp_textures) {
- for (i = 0; i < This->stateBlock->lowest_disabled_stage; ++i) {
- if (!This->fixed_function_usage_map[i]) continue;
+ This->stateBlock->lowest_disabled_stage <= This->max_ffp_textures) {
+ for (i = 0; ffu_map; ffu_map >>= 1, ++i)
+ {
+ if (!(ffu_map & 1)) continue;
if (This->texUnitMap[i] != i) {
device_map_stage(This, i, i);
/* Now work out the mapping */
tex = 0;
- for (i = 0; i < This->stateBlock->lowest_disabled_stage; ++i) {
- if (!This->fixed_function_usage_map[i]) continue;
+ for (i = 0; ffu_map; ffu_map >>= 1, ++i)
+ {
+ if (!(ffu_map & 1)) continue;
if (This->texUnitMap[i] != tex) {
device_map_stage(This, i, tex);
if (!pshader_sampler_tokens) {
/* No pixel shader, check fixed function */
- return current_mapping >= MAX_TEXTURES || !This->fixed_function_usage_map[current_mapping];
+ return current_mapping >= MAX_TEXTURES || !(This->fixed_function_usage_map & (1 << current_mapping));
}
/* Pixel shader, check the shader's sampler map */
if (ps) {
IWineD3DPixelShaderImpl *pshader = (IWineD3DPixelShaderImpl *)This->stateBlock->pixelShader;
- /* Make sure the shader's reg_maps are up to date. This is only relevant for 1.x pixelshaders. */
- IWineD3DPixelShader_UpdateSamplers((IWineD3DPixelShader *)pshader);
+ /* Note that we only care if a sampler is sampled or not, not the sampler's specific type.
+ * Otherwise we'd need to call shader_update_samplers() here for 1.x pixelshaders. */
pshader_sampler_tokens = pshader->baseShader.reg_maps.samplers;
}
}
void IWineD3DDeviceImpl_FindTexUnitMap(IWineD3DDeviceImpl *This) {
- BOOL vs = use_vs(This);
- BOOL ps = use_ps(This);
+ BOOL vs = use_vs(This->stateBlock);
+ BOOL ps = use_ps(This->stateBlock);
/*
* Rules are:
* -> Pixel shaders need a 1:1 map. In theory the shader input could be mapped too, but
This->updateStateBlock->changed.pixelShaderConstantsB |= (1 << i);
}
- IWineD3DDeviceImpl_MarkStateDirty(This, STATE_PIXELSHADERCONSTANT);
+ if (!This->isRecordingState) IWineD3DDeviceImpl_MarkStateDirty(This, STATE_PIXELSHADERCONSTANT);
return WINED3D_OK;
}
This->updateStateBlock->changed.pixelShaderConstantsI |= (1 << i);
}
- IWineD3DDeviceImpl_MarkStateDirty(This, STATE_PIXELSHADERCONSTANT);
+ if (!This->isRecordingState) IWineD3DDeviceImpl_MarkStateDirty(This, STATE_PIXELSHADERCONSTANT);
return WINED3D_OK;
}
srcData[i*4], srcData[i*4+1], srcData[i*4+2], srcData[i*4+3]);
}
- for (i = start; i < count + start; ++i) {
- if (!This->updateStateBlock->changed.pixelShaderConstantsF[i]) {
- constants_entry *ptr = LIST_ENTRY(list_head(&This->updateStateBlock->set_pconstantsF), constants_entry, entry);
- if (!ptr || ptr->count >= sizeof(ptr->idx) / sizeof(*ptr->idx)) {
- ptr = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(constants_entry));
- list_add_head(&This->updateStateBlock->set_pconstantsF, &ptr->entry);
- }
- ptr->idx[ptr->count++] = i;
- This->updateStateBlock->changed.pixelShaderConstantsF[i] = TRUE;
- }
- }
-
- IWineD3DDeviceImpl_MarkStateDirty(This, STATE_PIXELSHADERCONSTANT);
-
- return WINED3D_OK;
-}
-
-static HRESULT WINAPI IWineD3DDeviceImpl_SetPixelShaderConstantF_DirtyConst(
- IWineD3DDevice *iface,
- UINT start,
- CONST float *srcData,
- UINT count) {
-
- IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
- UINT i;
-
- TRACE("(iface %p, srcData %p, start %d, count %d)\n",
- iface, srcData, start, count);
-
- /* Specifically test start > limit to catch MAX_UINT overflows when adding start + count */
- if (srcData == NULL || start + count > GL_LIMITS(pshader_constantsF) || start > GL_LIMITS(pshader_constantsF))
- return WINED3DERR_INVALIDCALL;
-
- memcpy(&This->updateStateBlock->pixelShaderConstantF[start * 4], srcData, count * sizeof(float) * 4);
- if(TRACE_ON(d3d)) {
- for (i = 0; i < count; i++)
- TRACE("Set FLOAT constant %u to { %f, %f, %f, %f }\n", start + i,
- srcData[i*4], srcData[i*4+1], srcData[i*4+2], srcData[i*4+3]);
+ if (!This->isRecordingState)
+ {
+ This->shader_backend->shader_update_float_pixel_constants(iface, start, count);
+ IWineD3DDeviceImpl_MarkStateDirty(This, STATE_PIXELSHADERCONSTANT);
}
- /* We don't want shader constant dirtification to be an O(contexts), so just dirtify the active
- * context. On a context switch the old context will be fully dirtified
- */
- memset(This->activeContext->pshader_const_dirty + start, 1,
- sizeof(*This->activeContext->pshader_const_dirty) * count);
- This->highest_dirty_ps_const = max(This->highest_dirty_ps_const, start+count+1);
-
- IWineD3DDeviceImpl_MarkStateDirty(This, STATE_PIXELSHADERCONSTANT);
+ memset(This->updateStateBlock->changed.pixelShaderConstantsF + start, 1,
+ sizeof(*This->updateStateBlock->changed.pixelShaderConstantsF) * count);
return WINED3D_OK;
}
return WINED3D_OK;
}
- This->updateStateBlock->changed.textureState[Stage][Type] = TRUE;
+ This->updateStateBlock->changed.textureState[Stage] |= 1 << Type;
This->updateStateBlock->textureState[Stage][Type] = Value;
if (This->isRecordingState) {
oldTexture = This->updateStateBlock->textures[Stage];
- if(pTexture != NULL) {
- /* SetTexture isn't allowed on textures in WINED3DPOOL_SCRATCH;
- */
- if(((IWineD3DTextureImpl*)pTexture)->resource.pool == WINED3DPOOL_SCRATCH) {
- WARN("(%p) Attempt to set scratch texture rejected\n", pTexture);
- return WINED3DERR_INVALIDCALL;
- }
- This->stateBlock->textureDimensions[Stage] = IWineD3DBaseTexture_GetTextureDimensions(pTexture);
+ /* SetTexture isn't allowed on textures in WINED3DPOOL_SCRATCH */
+ if (pTexture && ((IWineD3DTextureImpl*)pTexture)->resource.pool == WINED3DPOOL_SCRATCH)
+ {
+ WARN("(%p) Attempt to set scratch texture rejected\n", pTexture);
+ return WINED3DERR_INVALIDCALL;
}
TRACE("GL_LIMITS %d\n",GL_LIMITS(sampler_stages));
TRACE("(%p) : oldtexture(%p)\n", This,oldTexture);
- This->updateStateBlock->changed.textures[Stage] = TRUE;
+ This->updateStateBlock->changed.textures |= 1 << Stage;
TRACE("(%p) : setting new texture to %p\n", This, pTexture);
This->updateStateBlock->textures[Stage] = pTexture;
if (NULL != This->updateStateBlock->textures[Stage]) {
IWineD3DBaseTextureImpl *new = (IWineD3DBaseTextureImpl *) This->updateStateBlock->textures[Stage];
ULONG bindCount = InterlockedIncrement(&new->baseTexture.bindCount);
+ UINT dimensions = IWineD3DBaseTexture_GetTextureDimensions(pTexture);
IWineD3DBaseTexture_AddRef(This->updateStateBlock->textures[Stage]);
+
+ if (!oldTexture || dimensions != IWineD3DBaseTexture_GetTextureDimensions(oldTexture))
+ {
+ IWineD3DDeviceImpl_MarkStateDirty(This, STATE_PIXELSHADER);
+ }
+
if(oldTexture == NULL && Stage < MAX_TEXTURES) {
/* The source arguments for color and alpha ops have different meanings when a NULL texture is bound,
* so the COLOROP and ALPHAOP have to be dirtified.
static HRESULT WINAPI IWineD3DDeviceImpl_BeginStateBlock(IWineD3DDevice *iface) {
IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
- IWineD3DStateBlockImpl *object;
- HRESULT temp_result;
- int i;
+ IWineD3DStateBlock *stateblock;
+ HRESULT hr;
TRACE("(%p)\n", This);
-
- if (This->isRecordingState) {
- return WINED3DERR_INVALIDCALL;
- }
-
- object = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(IWineD3DStateBlockImpl));
- if (NULL == object ) {
- FIXME("(%p)Error allocating memory for stateblock\n", This);
- return E_OUTOFMEMORY;
- }
- TRACE("(%p) created object %p\n", This, object);
- object->wineD3DDevice= This;
- /** FIXME: object->parent = parent; **/
- object->parent = NULL;
- object->blockType = WINED3DSBT_RECORDED;
- object->ref = 1;
- object->lpVtbl = &IWineD3DStateBlock_Vtbl;
- for(i = 0; i < LIGHTMAP_SIZE; i++) {
- list_init(&object->lightMap[i]);
- }
+ if (This->isRecordingState) return WINED3DERR_INVALIDCALL;
- temp_result = allocate_shader_constants(object);
- if (WINED3D_OK != temp_result)
- return temp_result;
+ hr = IWineD3DDeviceImpl_CreateStateBlock(iface, WINED3DSBT_RECORDED, &stateblock, NULL);
+ if (FAILED(hr)) return hr;
IWineD3DStateBlock_Release((IWineD3DStateBlock*)This->updateStateBlock);
- This->updateStateBlock = object;
+ This->updateStateBlock = (IWineD3DStateBlockImpl *)stateblock;
This->isRecordingState = TRUE;
- TRACE("(%p) recording stateblock %p\n",This , object);
+ TRACE("(%p) recording stateblock %p\n", This, stateblock);
+
return WINED3D_OK;
}
IWineD3DStateBlockImpl *object = This->updateStateBlock;
if (!This->isRecordingState) {
- FIXME("(%p) not recording! returning error\n", This);
+ WARN("(%p) not recording! returning error\n", This);
*ppStateBlock = NULL;
return WINED3DERR_INVALIDCALL;
}
- for(i = 1; i <= WINEHIGHEST_RENDER_STATE; i++) {
- if(object->changed.renderState[i]) {
- object->contained_render_states[object->num_contained_render_states] = i;
- object->num_contained_render_states++;
+ for (i = 0; i <= WINEHIGHEST_RENDER_STATE >> 5; ++i)
+ {
+ DWORD map = object->changed.renderState[i];
+ for (j = 0; map; map >>= 1, ++j)
+ {
+ if (!(map & 1)) continue;
+
+ object->contained_render_states[object->num_contained_render_states++] = (i << 5) | j;
}
}
- for(i = 1; i <= HIGHEST_TRANSFORMSTATE; i++) {
- if(object->changed.transform[i]) {
- object->contained_transform_states[object->num_contained_transform_states] = i;
- object->num_contained_transform_states++;
+
+ for (i = 0; i <= HIGHEST_TRANSFORMSTATE >> 5; ++i)
+ {
+ DWORD map = object->changed.transform[i];
+ for (j = 0; map; map >>= 1, ++j)
+ {
+ if (!(map & 1)) continue;
+
+ object->contained_transform_states[object->num_contained_transform_states++] = (i << 5) | j;
}
}
for(i = 0; i < GL_LIMITS(vshader_constantsF); i++) {
object->num_contained_vs_consts_b++;
}
}
+ for (i = 0; i < GL_LIMITS(pshader_constantsF); ++i)
+ {
+ if (object->changed.pixelShaderConstantsF[i])
+ {
+ object->contained_ps_consts_f[object->num_contained_ps_consts_f] = i;
+ ++object->num_contained_ps_consts_f;
+ }
+ }
for(i = 0; i < MAX_CONST_I; i++) {
if (object->changed.pixelShaderConstantsI & (1 << i))
{
}
}
for(i = 0; i < MAX_TEXTURES; i++) {
- for(j = 1; j <= WINED3D_HIGHEST_TEXTURE_STATE; j++) {
- if(object->changed.textureState[i][j]) {
- object->contained_tss_states[object->num_contained_tss_states].stage = i;
- object->contained_tss_states[object->num_contained_tss_states].state = j;
- object->num_contained_tss_states++;
- }
+ DWORD map = object->changed.textureState[i];
+
+ for(j = 0; map; map >>= 1, ++j)
+ {
+ if (!(map & 1)) continue;
+
+ object->contained_tss_states[object->num_contained_tss_states].stage = i;
+ object->contained_tss_states[object->num_contained_tss_states].state = j;
+ ++object->num_contained_tss_states;
}
}
for(i = 0; i < MAX_COMBINED_SAMPLERS; i++){
- for (j = 1; j < WINED3D_HIGHEST_SAMPLER_STATE; j++) {
- if(object->changed.samplerState[i][j]) {
- object->contained_sampler_states[object->num_contained_sampler_states].stage = i;
- object->contained_sampler_states[object->num_contained_sampler_states].state = j;
- object->num_contained_sampler_states++;
- }
+ DWORD map = object->changed.samplerState[i];
+
+ for (j = 0; map; map >>= 1, ++j)
+ {
+ if (!(map & 1)) continue;
+
+ object->contained_sampler_states[object->num_contained_sampler_states].stage = i;
+ object->contained_sampler_states[object->num_contained_sampler_states].state = j;
+ ++object->num_contained_sampler_states;
}
}
IWineD3DDeviceImpl_MarkStateDirty(This, STATE_STREAMSRC);
}
/* Account for the loading offset due to index buffers. Instead of reloading all sources correct it with the startvertex parameter */
- drawPrimitive(iface, PrimitiveType, PrimitiveCount, StartVertex, 0/* NumVertices */, -1 /* indxStart */,
+ drawPrimitive(iface, PrimitiveType, PrimitiveCount, 0/* NumVertices */, StartVertex /* start_idx */,
0 /* indxSize */, NULL /* indxData */, 0 /* minIndex */);
return WINED3D_OK;
}
* without an index buffer set. (The first time at least...)
* D3D8 simply dies, but I doubt it can do much harm to return
* D3DERR_INVALIDCALL there as well. */
- ERR("(%p) : Called without a valid index buffer set, returning WINED3DERR_INVALIDCALL\n", This);
+ WARN("(%p) : Called without a valid index buffer set, returning WINED3DERR_INVALIDCALL\n", This);
return WINED3DERR_INVALIDCALL;
}
IWineD3DDeviceImpl_MarkStateDirty(This, STATE_STREAMSRC);
}
- drawPrimitive(iface, PrimitiveType, primCount, 0, NumVertices, startIndex,
+ drawPrimitive(iface, PrimitiveType, primCount, NumVertices, startIndex,
idxStride, vbo ? NULL : ((IWineD3DIndexBufferImpl *) pIB)->resource.allocatedMemory, minIndex);
return WINED3D_OK;
/* TODO: Only mark dirty if drawing from a different UP address */
IWineD3DDeviceImpl_MarkStateDirty(This, STATE_STREAMSRC);
- drawPrimitive(iface, PrimitiveType, PrimitiveCount, 0 /* start vertex */, 0 /* NumVertices */,
- 0 /* indxStart*/, 0 /* indxSize*/, NULL /* indxData */, 0 /* indxMin */);
+ drawPrimitive(iface, PrimitiveType, PrimitiveCount, 0 /* NumVertices */,
+ 0 /* start_idx */, 0 /* indxSize*/, NULL /* indxData */, 0 /* indxMin */);
/* MSDN specifies stream zero settings must be set to NULL */
This->stateBlock->streamStride[0] = 0;
IWineD3DDeviceImpl_MarkStateDirty(This, STATE_VDECL);
IWineD3DDeviceImpl_MarkStateDirty(This, STATE_INDEXBUFFER);
- drawPrimitive(iface, PrimitiveType, PrimitiveCount, 0 /* vertexStart */, NumVertices, 0 /* indxStart */, idxStride, pIndexData, MinVertexIndex);
+ drawPrimitive(iface, PrimitiveType, PrimitiveCount, NumVertices, 0 /* start_idx */, idxStride, pIndexData, MinVertexIndex);
/* MSDN specifies stream zero settings and index buffer must be set to NULL */
This->stateBlock->streamSource[0] = NULL;
IWineD3DDeviceImpl_MarkStateDirty(This, STATE_INDEXBUFFER);
This->stateBlock->baseVertexIndex = 0;
This->up_strided = DrawPrimStrideData;
- drawPrimitive(iface, PrimitiveType, PrimitiveCount, 0, 0, 0, 0, NULL, 0);
+ drawPrimitive(iface, PrimitiveType, PrimitiveCount, 0, 0, 0, NULL, 0);
This->up_strided = NULL;
return WINED3D_OK;
}
This->stateBlock->streamIsUP = TRUE;
This->stateBlock->baseVertexIndex = 0;
This->up_strided = DrawPrimStrideData;
- drawPrimitive(iface, PrimitiveType, PrimitiveCount, 0 /* startvertexidx */, 0 /* numindices */, 0 /* startidx */, idxSize, pIndexData, 0 /* minindex */);
+ drawPrimitive(iface, PrimitiveType, PrimitiveCount, 0 /* numindices */, 0 /* start_idx */, idxSize, pIndexData, 0 /* minindex */);
This->up_strided = NULL;
return WINED3D_OK;
}
ActivateContext(This, This->lastActiveRenderTarget, CTXUSAGE_RESOURCELOAD);
- if (GL_SUPPORT(ARB_MULTITEXTURE)) {
- ENTER_GL();
- GL_EXTCALL(glActiveTextureARB(GL_TEXTURE0_ARB));
- checkGLcall("glActiveTextureARB");
- LEAVE_GL();
- }
+ ENTER_GL();
+ GL_EXTCALL(glActiveTextureARB(GL_TEXTURE0_ARB));
+ checkGLcall("glActiveTextureARB");
+ LEAVE_GL();
/* Make sure the surface is loaded and up to date */
IWineD3DSurface_PreLoad(pDestinationSurface);
}
/* Make sure that a proper texture unit is selected */
- if (GL_SUPPORT(ARB_MULTITEXTURE)) {
- GL_EXTCALL(glActiveTextureARB(GL_TEXTURE0_ARB));
- checkGLcall("glActiveTextureARB");
- }
+ GL_EXTCALL(glActiveTextureARB(GL_TEXTURE0_ARB));
+ checkGLcall("glActiveTextureARB");
sampler = This->rev_tex_unit_map[0];
if (sampler != -1) {
IWineD3DDeviceImpl_MarkStateDirty(This, STATE_SAMPLER(sampler));
(pPresentationParameters->BackBufferWidth != swapchain->presentParms.BackBufferWidth ||
pPresentationParameters->BackBufferHeight != swapchain->presentParms.BackBufferHeight))
{
- WINED3DVIEWPORT vp;
UINT i;
- vp.X = 0;
- vp.Y = 0;
- vp.Width = pPresentationParameters->BackBufferWidth;
- vp.Height = pPresentationParameters->BackBufferHeight;
- vp.MinZ = 0;
- vp.MaxZ = 1;
-
if(!pPresentationParameters->Windowed) {
DisplayModeChanged = TRUE;
}
if(This->auto_depth_stencil_buffer) {
updateSurfaceDesc((IWineD3DSurfaceImpl *)This->auto_depth_stencil_buffer, pPresentationParameters);
}
-
-
- /* Now set the new viewport */
- IWineD3DDevice_SetViewport(iface, &vp);
}
if((pPresentationParameters->Windowed && !swapchain->presentParms.Windowed) ||
This->exStyle = exStyle;
}
+ TRACE("Resetting stateblock\n");
+ IWineD3DStateBlock_Release((IWineD3DStateBlock *)This->updateStateBlock);
+ IWineD3DStateBlock_Release((IWineD3DStateBlock *)This->stateBlock);
+
+ /* Note: No parent needed for initial internal stateblock */
+ hr = IWineD3DDevice_CreateStateBlock(iface, WINED3DSBT_INIT, (IWineD3DStateBlock **)&This->stateBlock, NULL);
+ if (FAILED(hr)) ERR("Resetting the stateblock failed with error 0x%08x\n", hr);
+ else TRACE("Created stateblock %p\n", This->stateBlock);
+ This->updateStateBlock = This->stateBlock;
+ IWineD3DStateBlock_AddRef((IWineD3DStateBlock *)This->updateStateBlock);
+
hr = IWineD3DStateBlock_InitStartupStateBlock((IWineD3DStateBlock *) This->stateBlock);
if(FAILED(hr)) {
ERR("Resetting the stateblock failed with error 0x%08x\n", hr);
/* TODO: nothing really? */
break;
case WINED3DRTYPE_VERTEXBUFFER:
- /* MSDN: When an application no longer holds a references to this interface, the interface will automatically be freed. */
{
int streamNumber;
TRACE("Cleaning up stream pointers\n");
}
break;
case WINED3DRTYPE_INDEXBUFFER:
- /* MSDN: When an application no longer holds a references to this interface, the interface will automatically be freed.*/
if (This->updateStateBlock != NULL ) { /* ==NULL when device is being destroyed */
if (This->updateStateBlock->pIndexData == (IWineD3DIndexBuffer *)resource) {
This->updateStateBlock->pIndexData = NULL;
IWineD3DDeviceImpl_GetCurrentTexturePalette,
IWineD3DDeviceImpl_SetDepthStencilSurface,
IWineD3DDeviceImpl_GetDepthStencilSurface,
- IWineD3DDeviceImpl_SetFVF,
- IWineD3DDeviceImpl_GetFVF,
IWineD3DDeviceImpl_SetGammaRamp,
IWineD3DDeviceImpl_GetGammaRamp,
IWineD3DDeviceImpl_SetIndices,
IWineD3DDeviceImpl_EnumResources
};
-const IWineD3DDeviceVtbl IWineD3DDevice_DirtyConst_Vtbl =
-{
- /*** IUnknown methods ***/
- IWineD3DDeviceImpl_QueryInterface,
- IWineD3DDeviceImpl_AddRef,
- IWineD3DDeviceImpl_Release,
- /*** IWineD3DDevice methods ***/
- IWineD3DDeviceImpl_GetParent,
- /*** Creation methods**/
- IWineD3DDeviceImpl_CreateVertexBuffer,
- IWineD3DDeviceImpl_CreateIndexBuffer,
- IWineD3DDeviceImpl_CreateStateBlock,
- IWineD3DDeviceImpl_CreateSurface,
- IWineD3DDeviceImpl_CreateTexture,
- IWineD3DDeviceImpl_CreateVolumeTexture,
- IWineD3DDeviceImpl_CreateVolume,
- IWineD3DDeviceImpl_CreateCubeTexture,
- IWineD3DDeviceImpl_CreateQuery,
- IWineD3DDeviceImpl_CreateSwapChain,
- IWineD3DDeviceImpl_CreateVertexDeclaration,
- IWineD3DDeviceImpl_CreateVertexDeclarationFromFVF,
- IWineD3DDeviceImpl_CreateVertexShader,
- IWineD3DDeviceImpl_CreatePixelShader,
- IWineD3DDeviceImpl_CreatePalette,
- /*** Odd functions **/
- IWineD3DDeviceImpl_Init3D,
- IWineD3DDeviceImpl_InitGDI,
- IWineD3DDeviceImpl_Uninit3D,
- IWineD3DDeviceImpl_UninitGDI,
- IWineD3DDeviceImpl_SetMultithreaded,
- IWineD3DDeviceImpl_EvictManagedResources,
- IWineD3DDeviceImpl_GetAvailableTextureMem,
- IWineD3DDeviceImpl_GetBackBuffer,
- IWineD3DDeviceImpl_GetCreationParameters,
- IWineD3DDeviceImpl_GetDeviceCaps,
- IWineD3DDeviceImpl_GetDirect3D,
- IWineD3DDeviceImpl_GetDisplayMode,
- IWineD3DDeviceImpl_SetDisplayMode,
- IWineD3DDeviceImpl_GetNumberOfSwapChains,
- IWineD3DDeviceImpl_GetRasterStatus,
- IWineD3DDeviceImpl_GetSwapChain,
- IWineD3DDeviceImpl_Reset,
- IWineD3DDeviceImpl_SetDialogBoxMode,
- IWineD3DDeviceImpl_SetCursorProperties,
- IWineD3DDeviceImpl_SetCursorPosition,
- IWineD3DDeviceImpl_ShowCursor,
- IWineD3DDeviceImpl_TestCooperativeLevel,
- /*** Getters and setters **/
- IWineD3DDeviceImpl_SetClipPlane,
- IWineD3DDeviceImpl_GetClipPlane,
- IWineD3DDeviceImpl_SetClipStatus,
- IWineD3DDeviceImpl_GetClipStatus,
- IWineD3DDeviceImpl_SetCurrentTexturePalette,
- IWineD3DDeviceImpl_GetCurrentTexturePalette,
- IWineD3DDeviceImpl_SetDepthStencilSurface,
- IWineD3DDeviceImpl_GetDepthStencilSurface,
- IWineD3DDeviceImpl_SetFVF,
- IWineD3DDeviceImpl_GetFVF,
- IWineD3DDeviceImpl_SetGammaRamp,
- IWineD3DDeviceImpl_GetGammaRamp,
- IWineD3DDeviceImpl_SetIndices,
- IWineD3DDeviceImpl_GetIndices,
- IWineD3DDeviceImpl_SetBaseVertexIndex,
- IWineD3DDeviceImpl_GetBaseVertexIndex,
- IWineD3DDeviceImpl_SetLight,
- IWineD3DDeviceImpl_GetLight,
- IWineD3DDeviceImpl_SetLightEnable,
- IWineD3DDeviceImpl_GetLightEnable,
- IWineD3DDeviceImpl_SetMaterial,
- IWineD3DDeviceImpl_GetMaterial,
- IWineD3DDeviceImpl_SetNPatchMode,
- IWineD3DDeviceImpl_GetNPatchMode,
- IWineD3DDeviceImpl_SetPaletteEntries,
- IWineD3DDeviceImpl_GetPaletteEntries,
- IWineD3DDeviceImpl_SetPixelShader,
- IWineD3DDeviceImpl_GetPixelShader,
- IWineD3DDeviceImpl_SetPixelShaderConstantB,
- IWineD3DDeviceImpl_GetPixelShaderConstantB,
- IWineD3DDeviceImpl_SetPixelShaderConstantI,
- IWineD3DDeviceImpl_GetPixelShaderConstantI,
- IWineD3DDeviceImpl_SetPixelShaderConstantF_DirtyConst,
- IWineD3DDeviceImpl_GetPixelShaderConstantF,
- IWineD3DDeviceImpl_SetRenderState,
- IWineD3DDeviceImpl_GetRenderState,
- IWineD3DDeviceImpl_SetRenderTarget,
- IWineD3DDeviceImpl_GetRenderTarget,
- IWineD3DDeviceImpl_SetFrontBackBuffers,
- IWineD3DDeviceImpl_SetSamplerState,
- IWineD3DDeviceImpl_GetSamplerState,
- IWineD3DDeviceImpl_SetScissorRect,
- IWineD3DDeviceImpl_GetScissorRect,
- IWineD3DDeviceImpl_SetSoftwareVertexProcessing,
- IWineD3DDeviceImpl_GetSoftwareVertexProcessing,
- IWineD3DDeviceImpl_SetStreamSource,
- IWineD3DDeviceImpl_GetStreamSource,
- IWineD3DDeviceImpl_SetStreamSourceFreq,
- IWineD3DDeviceImpl_GetStreamSourceFreq,
- IWineD3DDeviceImpl_SetTexture,
- IWineD3DDeviceImpl_GetTexture,
- IWineD3DDeviceImpl_SetTextureStageState,
- IWineD3DDeviceImpl_GetTextureStageState,
- IWineD3DDeviceImpl_SetTransform,
- IWineD3DDeviceImpl_GetTransform,
- IWineD3DDeviceImpl_SetVertexDeclaration,
- IWineD3DDeviceImpl_GetVertexDeclaration,
- IWineD3DDeviceImpl_SetVertexShader,
- IWineD3DDeviceImpl_GetVertexShader,
- IWineD3DDeviceImpl_SetVertexShaderConstantB,
- IWineD3DDeviceImpl_GetVertexShaderConstantB,
- IWineD3DDeviceImpl_SetVertexShaderConstantI,
- IWineD3DDeviceImpl_GetVertexShaderConstantI,
- IWineD3DDeviceImpl_SetVertexShaderConstantF_DirtyConst,
- IWineD3DDeviceImpl_GetVertexShaderConstantF,
- IWineD3DDeviceImpl_SetViewport,
- IWineD3DDeviceImpl_GetViewport,
- IWineD3DDeviceImpl_MultiplyTransform,
- IWineD3DDeviceImpl_ValidateDevice,
- IWineD3DDeviceImpl_ProcessVertices,
- /*** State block ***/
- IWineD3DDeviceImpl_BeginStateBlock,
- IWineD3DDeviceImpl_EndStateBlock,
- /*** Scene management ***/
- IWineD3DDeviceImpl_BeginScene,
- IWineD3DDeviceImpl_EndScene,
- IWineD3DDeviceImpl_Present,
- IWineD3DDeviceImpl_Clear,
- /*** Drawing ***/
- IWineD3DDeviceImpl_DrawPrimitive,
- IWineD3DDeviceImpl_DrawIndexedPrimitive,
- IWineD3DDeviceImpl_DrawPrimitiveUP,
- IWineD3DDeviceImpl_DrawIndexedPrimitiveUP,
- IWineD3DDeviceImpl_DrawPrimitiveStrided,
- IWineD3DDeviceImpl_DrawIndexedPrimitiveStrided,
- IWineD3DDeviceImpl_DrawRectPatch,
- IWineD3DDeviceImpl_DrawTriPatch,
- IWineD3DDeviceImpl_DeletePatch,
- IWineD3DDeviceImpl_ColorFill,
- IWineD3DDeviceImpl_UpdateTexture,
- IWineD3DDeviceImpl_UpdateSurface,
- IWineD3DDeviceImpl_GetFrontBufferData,
- /*** object tracking ***/
- IWineD3DDeviceImpl_ResourceReleased,
- IWineD3DDeviceImpl_EnumResources
-};
-
const DWORD SavedPixelStates_R[NUM_SAVEDPIXELSTATES_R] = {
WINED3DRS_ALPHABLENDENABLE ,
WINED3DRS_ALPHAFUNC ,
};
const DWORD SavedPixelStates_T[NUM_SAVEDPIXELSTATES_T] = {
- WINED3DTSS_ADDRESSW ,
WINED3DTSS_ALPHAARG0 ,
WINED3DTSS_ALPHAARG1 ,
WINED3DTSS_ALPHAARG2 ,
{"GL_ARB_texture_mirrored_repeat", ARB_TEXTURE_MIRRORED_REPEAT, 0 },
{"GL_ARB_texture_non_power_of_two", ARB_TEXTURE_NON_POWER_OF_TWO, MAKEDWORD_VERSION(2, 0) },
{"GL_ARB_texture_rectangle", ARB_TEXTURE_RECTANGLE, 0 },
+ {"GL_ARB_texture_rg", ARB_TEXTURE_RG, 0 },
{"GL_ARB_vertex_blend", ARB_VERTEX_BLEND, 0 },
{"GL_ARB_vertex_buffer_object", ARB_VERTEX_BUFFER_OBJECT, 0 },
{"GL_ARB_vertex_program", ARB_VERTEX_PROGRAM, 0 },
{"GL_EXT_texture_env_combine", EXT_TEXTURE_ENV_COMBINE, 0 },
{"GL_EXT_texture_env_dot3", EXT_TEXTURE_ENV_DOT3, 0 },
{"GL_EXT_texture_sRGB", EXT_TEXTURE_SRGB, 0 },
+ {"GL_EXT_texture_swizzle", EXT_TEXTURE_SWIZZLE, 0 },
{"GL_EXT_texture_filter_anisotropic", EXT_TEXTURE_FILTER_ANISOTROPIC, 0 },
{"GL_EXT_texture_lod", EXT_TEXTURE_LOD, 0 },
{"GL_EXT_texture_lod_bias", EXT_TEXTURE_LOD_BIAS, 0 },
+ {"GL_EXT_vertex_array_bgra", EXT_VERTEX_ARRAY_BGRA, 0 },
{"GL_EXT_vertex_shader", EXT_VERTEX_SHADER, 0 },
{"GL_EXT_gpu_program_parameters", EXT_GPU_PROGRAM_PARAMETERS, 0 },
glAttribFunc specular_funcs[WINED3DDECLTYPE_UNUSED];
glAttribFunc normal_funcs[WINED3DDECLTYPE_UNUSED];
glMultiTexCoordFunc multi_texcoord_funcs[WINED3DDECLTYPE_UNUSED];
-glAttribFunc texcoord_funcs[WINED3DDECLTYPE_UNUSED];
/**
* Note: GL seems to trap if GetDeviceCaps is called before any HWND's created,
ENTER_GL();
gl_string = (const char *) glGetString(GL_RENDERER);
- if (NULL == gl_string)
- gl_string = "None";
+ if (!gl_string) gl_string = "None";
strcpy(gl_info->gl_renderer, gl_string);
gl_string = (const char *) glGetString(GL_VENDOR);
gl_info->max_texture_stages = 1;
gl_info->max_fragment_samplers = 1;
gl_info->max_vertex_samplers = 0;
- gl_info->max_combined_samplers = 0;
+ gl_info->max_combined_samplers = gl_info->max_fragment_samplers + gl_info->max_vertex_samplers;
gl_info->max_sampler_stages = 1;
gl_info->ps_arb_version = PS_VERSION_NOT_SUPPORTED;
gl_info->ps_arb_max_temps = 0;
gl_info->max_texture_size = gl_max;
TRACE_(d3d_caps)("Maximum texture size support - max texture size=%d\n", gl_max);
- glGetFloatv(GL_POINT_SIZE_RANGE, gl_floatv);
+ glGetFloatv(GL_ALIASED_POINT_SIZE_RANGE, gl_floatv);
gl_info->max_pointsizemin = gl_floatv[0];
gl_info->max_pointsize = gl_floatv[1];
TRACE_(d3d_caps)("Maximum point size support - max point size=%f\n", gl_floatv[1]);
}
break;
case VENDOR_INTEL:
- if (strstr(gl_info->gl_renderer, "GMA 950")) {
+ if (strstr(gl_info->gl_renderer, "GMA 950") ||
+ strstr(gl_info->gl_renderer, "945GM")) {
/* MacOS calls the card GMA 950, but everywhere else the PCI ID is named 945GM */
gl_info->gl_card = CARD_INTEL_I945GM;
vidmem = 64;
case WINED3DFMT_G16R16F:
case WINED3DFMT_G32R32F:
+ if(GL_SUPPORT(ARB_TEXTURE_RG)) {
+ TRACE_(d3d_caps)("[OK]\n");
+ return TRUE;
+ }
TRACE_(d3d_caps)("[FAILED]\n");
return FALSE;
pCaps->RasterCaps |= WINED3DPRASTERCAPS_FOGRANGE;
}
/* FIXME Add:
- WINED3DPRASTERCAPS_COLORPERSPECTIVE
- WINED3DPRASTERCAPS_STRETCHBLTMULTISAMPLE
- WINED3DPRASTERCAPS_ANTIALIASEDGES
- WINED3DPRASTERCAPS_ZBUFFERLESSHSR
- WINED3DPRASTERCAPS_WBUFFER */
+ WINED3DPRASTERCAPS_COLORPERSPECTIVE
+ WINED3DPRASTERCAPS_STRETCHBLTMULTISAMPLE
+ WINED3DPRASTERCAPS_ANTIALIASEDGES
+ WINED3DPRASTERCAPS_ZBUFFERLESSHSR
+ WINED3DPRASTERCAPS_WBUFFER */
pCaps->ZCmpCaps = WINED3DPCMPCAPS_ALWAYS |
WINED3DPCMPCAPS_EQUAL |
/* Note due to structure differences between dx8 and dx9 D3DPRESENT_PARAMETERS,
and fields being inserted in the middle, a new structure is used in place */
-static HRESULT WINAPI IWineD3DImpl_CreateDevice(IWineD3D *iface, UINT Adapter, WINED3DDEVTYPE DeviceType, HWND hFocusWindow,
- DWORD BehaviourFlags, IWineD3DDevice** ppReturnedDeviceInterface,
- IUnknown *parent) {
-
+static HRESULT WINAPI IWineD3DImpl_CreateDevice(IWineD3D *iface, UINT Adapter,
+ WINED3DDEVTYPE DeviceType, HWND hFocusWindow, DWORD BehaviourFlags, IUnknown *parent,
+ IWineD3DDeviceParent *device_parent, IWineD3DDevice **ppReturnedDeviceInterface)
+{
IWineD3DDeviceImpl *object = NULL;
IWineD3DImpl *This = (IWineD3DImpl *)iface;
WINED3DDISPLAYMODE mode;
const struct fragment_pipeline *frag_pipeline = NULL;
int i;
struct fragment_caps ffp_caps;
+ HRESULT hr;
/* Validate the adapter number. If no adapters are available(no GL), ignore the adapter
* number and create a device without a 3D adapter for 2D only operation.
object->adapter = numAdapters ? &Adapters[Adapter] : NULL;
IWineD3D_AddRef(object->wineD3D);
object->parent = parent;
+ object->device_parent = device_parent;
list_init(&object->resources);
list_init(&object->shaders);
frag_pipeline->get_caps(DeviceType, &GLINFO_LOCATION, &ffp_caps);
object->max_ffp_textures = ffp_caps.MaxSimultaneousTextures;
object->max_ffp_texture_stages = ffp_caps.MaxTextureBlendStages;
- compile_state_table(object->StateTable, object->multistate_funcs, &GLINFO_LOCATION,
+ hr = compile_state_table(object->StateTable, object->multistate_funcs, &GLINFO_LOCATION,
ffp_vertexstate_template, frag_pipeline, misc_state_template);
- object->blitter = select_blit_implementation(Adapter, DeviceType);
+ if (FAILED(hr)) {
+ IWineD3D_Release(object->wineD3D);
+ HeapFree(GetProcessHeap(), 0, object);
- /* Prefer the vtable with functions optimized for single dirtifyable objects if the shader
- * model can deal with that. It is essentially the same, just with adjusted
- * Set*ShaderConstantF implementations
- */
- if(object->shader_backend->shader_dirtifyable_constants((IWineD3DDevice *) object)) {
- object->lpVtbl = &IWineD3DDevice_DirtyConst_Vtbl;
+ return hr;
}
+ object->blitter = select_blit_implementation(Adapter, DeviceType);
+
/* set the state of the device to valid */
object->state = WINED3D_OK;
multi_texcoord_funcs[WINED3DDECLTYPE_FLOAT16_2] = invalid_texcoord_func;
multi_texcoord_funcs[WINED3DDECLTYPE_FLOAT16_4] = invalid_texcoord_func;
}
-
- texcoord_funcs[WINED3DDECLTYPE_FLOAT1] = (glAttribFunc)glTexCoord1fv;
- texcoord_funcs[WINED3DDECLTYPE_FLOAT2] = (glAttribFunc)glTexCoord2fv;
- texcoord_funcs[WINED3DDECLTYPE_FLOAT3] = (glAttribFunc)glTexCoord3fv;
- texcoord_funcs[WINED3DDECLTYPE_FLOAT4] = (glAttribFunc)glTexCoord4fv;
- texcoord_funcs[WINED3DDECLTYPE_D3DCOLOR] = invalid_func;
- texcoord_funcs[WINED3DDECLTYPE_UBYTE4] = invalid_func;
- texcoord_funcs[WINED3DDECLTYPE_SHORT2] = (glAttribFunc)glTexCoord2sv;
- texcoord_funcs[WINED3DDECLTYPE_SHORT4] = (glAttribFunc)glTexCoord4sv;
- texcoord_funcs[WINED3DDECLTYPE_UBYTE4N] = invalid_func;
- texcoord_funcs[WINED3DDECLTYPE_SHORT2N] = invalid_func;
- texcoord_funcs[WINED3DDECLTYPE_SHORT4N] = invalid_func;
- texcoord_funcs[WINED3DDECLTYPE_USHORT2N] = invalid_func;
- texcoord_funcs[WINED3DDECLTYPE_USHORT4N] = invalid_func;
- texcoord_funcs[WINED3DDECLTYPE_UDEC3] = invalid_func;
- texcoord_funcs[WINED3DDECLTYPE_DEC3N] = invalid_func;
- if (GL_SUPPORT(NV_HALF_FLOAT))
- {
- texcoord_funcs[WINED3DDECLTYPE_FLOAT16_2] = (glAttribFunc)GL_EXTCALL(glTexCoord2hvNV);
- texcoord_funcs[WINED3DDECLTYPE_FLOAT16_4] = (glAttribFunc)GL_EXTCALL(glTexCoord4hvNV);
- } else {
- texcoord_funcs[WINED3DDECLTYPE_FLOAT16_2] = invalid_func;
- texcoord_funcs[WINED3DDECLTYPE_FLOAT16_4] = invalid_func;
- }
}
#define PUSH1(att) attribs[nAttribs++] = (att);
BOOL InitAdapters(void) {
- static HMODULE mod_gl, mod_win32gl;
+ static HMODULE mod_gl;
BOOL ret;
int ps_selected_mode, vs_selected_mode;
ERR("Can't load opengl32.dll!\n");
goto nogl_adapter;
}
- mod_win32gl = mod_gl;
#else
#define USE_GL_FUNC(pfn) pfn = (void*)pwglGetProcAddress(#pfn);
/* To bypass the opengl32 thunks load wglGetProcAddress from gdi32 (glXGetProcAddress wrapper) instead of opengl32's */
mod_gl = GetModuleHandleA("gdi32.dll");
- mod_win32gl = LoadLibraryA("opengl32.dll");
- if(!mod_win32gl) {
- ERR("Can't load opengl32.dll!\n");
- goto nogl_adapter;
- }
#endif
}
/* Load glFinish and glFlush from opengl32.dll even if we're not using WIN32 opengl
* otherwise because we have to use winex11.drv's override
*/
- glFinish = (void*)GetProcAddress(mod_win32gl, "glFinish");
- glFlush = (void*)GetProcAddress(mod_win32gl, "glFlush");
+#ifdef USE_WIN32_OPENGL
+ glFinish = (void*)GetProcAddress(mod_gl, "glFinish");
+ glFlush = (void*)GetProcAddress(mod_gl, "glFlush");
+#else
+ glFinish = (void*)pwglGetProcAddress("wglFinish");
+ glFlush = (void*)pwglGetProcAddress("wglFlush");
+#endif
+
+ glEnableWINE = glEnable;
+ glDisableWINE = glDisable;
/* For now only one default adapter */
{
}
fixup_extensions(&Adapters[0].gl_info);
+ add_gl_compat_wrappers(&Adapters[0].gl_info);
WineD3D_ReleaseFakeGLContext();
const DWORD *streams = vertexDeclaration->streams;
/* Check for transformed vertices, disable vertex shader if present */
- strided->u.s.position_transformed = vertexDeclaration->position_transformed;
+ strided->position_transformed = vertexDeclaration->position_transformed;
if(vertexDeclaration->position_transformed) {
useVertexShaderFunction = FALSE;
}
/* Translate the declaration into strided data */
+ strided->swizzle_map = 0;
for (i = 0 ; i < vertexDeclaration->declarationWNumElements - 1; ++i) {
GLint streamVBO = 0;
BOOL stride_used;
element->Usage == WINED3DDECLUSAGE_POSITIONT)) {
static BOOL warned = FALSE;
if(!warned) {
- /* This may be bad with the fixed function pipeline */
- FIXME("Missing vbo streams with unfixed colors or transformed position, expect problems\n");
+ /* This may be bad with the fixed function pipeline */
+ FIXME("Missing vbo streams with unfixed colors or transformed position, expect problems\n");
warned = TRUE;
}
}
strided->u.input[idx].dwStride = stride;
strided->u.input[idx].VBO = streamVBO;
strided->u.input[idx].streamNo = element->Stream;
+ if (!GL_SUPPORT(EXT_VERTEX_ARRAY_BGRA) && element->Type == WINED3DDECLTYPE_D3DCOLOR)
+ {
+ strided->swizzle_map |= 1 << idx;
+ }
+ strided->use_map |= 1 << idx;
}
}
}
}
}
-static void drawStridedFast(IWineD3DDevice *iface,UINT numberOfVertices, GLenum glPrimitiveType,
- const void *idxData, short idxSize, ULONG minIndex, ULONG startIdx, ULONG startVertex) {
+static void drawStridedFast(IWineD3DDevice *iface, GLenum primitive_type,
+ UINT min_vertex_idx, UINT max_vertex_idx, UINT count, short idx_size,
+ const void *idx_data, UINT start_idx)
+{
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 (idx_size)
+ {
+ TRACE("(%p) : glElements(%x, %d, %d, ...)\n", This, primitive_type, count, min_vertex_idx);
+
#if 1
- glDrawElements(glPrimitiveType, numberOfVertices, idxSize == 2 ? GL_UNSIGNED_SHORT : GL_UNSIGNED_INT,
- (const char *)idxData+(idxSize * startIdx));
+ glDrawElements(primitive_type, count,
+ idx_size == 2 ? GL_UNSIGNED_SHORT : GL_UNSIGNED_INT,
+ (const char *)idx_data + (idx_size * start_idx));
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));
+#else
+ glDrawRangeElements(primitive_type, min_vertex_idx, max_vertex_idx, count,
+ idx_size == 2 ? GL_UNSIGNED_SHORT : GL_UNSIGNED_INT,
+ (const char *)idx_data + (idx_size * start_idx));
checkGLcall("glDrawRangeElements");
#endif
+ }
+ else
+ {
+ TRACE("(%p) : glDrawArrays(%#x, %d, %d)\n", This, primitive_type, start_idx, count);
- } else {
- TRACE("(%p) : glDrawArrays(%#x, %d, %d)\n", This, glPrimitiveType, startVertex, numberOfVertices);
- glDrawArrays(glPrimitiveType, startVertex, numberOfVertices);
+ glDrawArrays(primitive_type, start_idx, count);
checkGLcall("glDrawArrays");
}
-
- return;
}
/*
*/
static void drawStridedSlow(IWineD3DDevice *iface, const WineDirect3DVertexStridedData *sd, UINT NumVertexes,
- GLenum glPrimType, const void *idxData, short idxSize, ULONG minIndex, ULONG startIdx, ULONG startVertex)
+ GLenum glPrimType, const void *idxData, short idxSize, ULONG minIndex, ULONG startIdx)
{
unsigned int textureNo = 0;
const WORD *pIdxBufS = NULL;
ULONG vx_index;
IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
const UINT *streamOffset = This->stateBlock->streamOffset;
- long SkipnStrides = startVertex + This->stateBlock->loadBaseVertexIndex;
- BOOL pixelShader = use_ps(This);
+ long SkipnStrides = startIdx + This->stateBlock->loadBaseVertexIndex;
+ BOOL pixelShader = use_ps(This->stateBlock);
BOOL specular_fog = FALSE;
UINT texture_stages = GL_LIMITS(texture_stages);
const BYTE *texCoords[WINED3DDP_MAXTEXCOORD];
{
int coord_idx;
const void *ptr;
+ int texture_idx;
if (!(tmp_tex_mask & 1)) continue;
coord_idx = This->stateBlock->textureState[texture][WINED3DTSS_TEXCOORDINDEX];
ptr = texCoords[coord_idx] + (SkipnStrides * sd->u.s.texCoords[coord_idx].dwStride);
- if (GL_SUPPORT(ARB_MULTITEXTURE))
- {
- int texture_idx = This->texUnitMap[texture];
- multi_texcoord_funcs[sd->u.s.texCoords[coord_idx].dwType](GL_TEXTURE0_ARB + texture_idx, ptr);
- }
- else
- {
- texcoord_funcs[sd->u.s.texCoords[coord_idx].dwType](ptr);
- }
+ texture_idx = This->texUnitMap[texture];
+ multi_texcoord_funcs[sd->u.s.texCoords[coord_idx].dwType](GL_TEXTURE0_ARB + texture_idx, ptr);
}
/* Diffuse -------------------------------- */
}
static void drawStridedSlowVs(IWineD3DDevice *iface, const WineDirect3DVertexStridedData *sd, UINT numberOfVertices,
- GLenum glPrimitiveType, const void *idxData, short idxSize, ULONG minIndex, ULONG startIdx, ULONG startVertex)
+ GLenum glPrimitiveType, const void *idxData, short idxSize, ULONG minIndex, ULONG startIdx)
{
IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *) iface;
- long SkipnStrides = startVertex + This->stateBlock->loadBaseVertexIndex;
+ long SkipnStrides = startIdx + This->stateBlock->loadBaseVertexIndex;
const WORD *pIdxBufS = NULL;
const DWORD *pIdxBufL = NULL;
ULONG vx_index;
static inline void drawStridedInstanced(IWineD3DDevice *iface, const WineDirect3DVertexStridedData *sd,
UINT numberOfVertices, GLenum glPrimitiveType, const void *idxData, short idxSize, ULONG minIndex,
- ULONG startIdx, ULONG startVertex)
+ ULONG startIdx)
{
UINT numInstances = 0, i;
int numInstancedAttribs = 0, j;
}
TRACE("(%p) : glElements(%x, %d, %d, ...)\n", This, glPrimitiveType, numberOfVertices, minIndex);
- idxData = idxData == (void *)-1 ? NULL : idxData;
/* First, figure out how many instances we have to draw */
for(i = 0; i < MAX_STREAMS; i++) {
}
/* Routine common to the draw primitive and draw indexed primitive routines */
-void drawPrimitive(IWineD3DDevice *iface,
- int PrimitiveType,
- long NumPrimitives,
- /* for Indexed: */
- long StartVertexIndex,
- UINT numberOfVertices,
- long StartIdx,
- short idxSize,
- const void *idxData,
- int minIndex) {
+void drawPrimitive(IWineD3DDevice *iface, int PrimitiveType, long NumPrimitives,
+ UINT numberOfVertices, long StartIdx, short idxSize, const void *idxData, int minIndex)
+{
IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
IWineD3DSurfaceImpl *target;
if (numberOfVertices == 0 )
numberOfVertices = calculatedNumberOfindices;
- if(!use_vs(This)) {
- if(!This->strided_streams.u.s.position_transformed && This->activeContext->num_untracked_materials &&
- This->stateBlock->renderState[WINED3DRS_LIGHTING]) {
+ if (!use_vs(This->stateBlock))
+ {
+ if (!This->strided_streams.position_transformed && This->activeContext->num_untracked_materials
+ && This->stateBlock->renderState[WINED3DRS_LIGHTING])
+ {
static BOOL warned;
if (!warned) {
FIXME("Using software emulation because not all material properties could be tracked\n");
if (This->useDrawStridedSlow || emulation) {
/* Immediate mode drawing */
- if(use_vs(This)) {
+ if (use_vs(This->stateBlock))
+ {
static BOOL warned;
if (!warned) {
FIXME("Using immediate mode with vertex shaders for half float emulation\n");
} else {
TRACE("Using immediate mode with vertex shaders for half float emulation\n");
}
- drawStridedSlowVs(iface, strided, calculatedNumberOfindices, glPrimType,
- idxData, idxSize, minIndex, StartIdx, StartVertexIndex);
+ drawStridedSlowVs(iface, strided, calculatedNumberOfindices,
+ glPrimType, idxData, idxSize, minIndex, StartIdx);
} else {
drawStridedSlow(iface, strided, calculatedNumberOfindices,
- glPrimType, idxData, idxSize, minIndex, StartIdx, StartVertexIndex);
+ glPrimType, idxData, idxSize, minIndex, StartIdx);
}
} else if(This->instancedDraw) {
/* Instancing emulation with mixing immediate mode and arrays */
drawStridedInstanced(iface, &This->strided_streams, calculatedNumberOfindices, glPrimType,
- idxData, idxSize, minIndex, StartIdx, StartVertexIndex);
+ idxData, idxSize, minIndex, StartIdx);
} else {
- drawStridedFast(iface, calculatedNumberOfindices, glPrimType,
- idxData, idxSize, minIndex, StartIdx, StartVertexIndex);
+ drawStridedFast(iface, glPrimType, minIndex, minIndex + numberOfVertices - 1,
+ calculatedNumberOfindices, idxSize, idxData, StartIdx);
}
}
vtxStride * info->StartVertexOffsetWidth;
/* Not entirely sure about what happens with transformed vertices */
- if(strided.u.s.position_transformed) {
- FIXME("Transformed position in rectpatch generation\n");
- }
+ if (strided.position_transformed) FIXME("Transformed position in rectpatch generation\n");
+
if(vtxStride % sizeof(GLfloat)) {
/* glMap2f reads vertex sizes in GLfloats, the d3d stride is in bytes.
* I don't see how the stride could not be a multiple of 4, but make sure
checkGLcall("glPolygonMode(GL_FRONT_AND_BACK, GL_FILL)");
IWineD3DDeviceImpl_MarkStateDirty(This, STATE_RENDER(WINED3DRS_FILLMODE));
if(patch->has_normals) {
- const GLfloat black[4] = {0, 0, 0, 0};
- const GLfloat red[4] = {1, 0, 0, 0};
- const GLfloat green[4] = {0, 1, 0, 0};
- const GLfloat blue[4] = {0, 0, 1, 0};
- const GLfloat white[4] = {1, 1, 1, 1};
+ static const GLfloat black[] = {0, 0, 0, 0};
+ static const GLfloat red[] = {1, 0, 0, 0};
+ static const GLfloat green[] = {0, 1, 0, 0};
+ static const GLfloat blue[] = {0, 0, 1, 0};
+ static const GLfloat white[] = {1, 1, 1, 1};
glEnable(GL_LIGHTING);
checkGLcall("glEnable(GL_LIGHTING)");
glLightModelfv(GL_LIGHT_MODEL_AMBIENT, black);
if(patch->has_normals) {
/* Now do the same with reverse light directions */
- const GLfloat x[4] = {-1, 0, 0, 0};
- const GLfloat y[4] = { 0, -1, 0, 0};
- const GLfloat z[4] = { 0, 0, -1, 0};
+ static const GLfloat x[] = {-1, 0, 0, 0};
+ static const GLfloat y[] = { 0, -1, 0, 0};
+ static const GLfloat z[] = { 0, 0, -1, 0};
glLightfv(GL_LIGHT0, GL_POSITION, x);
glLightfv(GL_LIGHT1, GL_POSITION, y);
glLightfv(GL_LIGHT2, GL_POSITION, z);
--- /dev/null
+/*
+ * Compatibility functions for older GL implementations
+ *
+ * Copyright 2008 Stefan Dösinger 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 <stdio.h>
+#ifdef HAVE_FLOAT_H
+# include <float.h>
+#endif
+#include "wined3d_private.h"
+
+WINE_DEFAULT_DEBUG_CHANNEL(gl_compat);
+
+/* Start GL_ARB_multitexture emulation */
+static void WINE_GLAPI wine_glMultiTexCoord1fARB(GLenum target, GLfloat s) {
+ if(target != GL_TEXTURE0) {
+ ERR("Texture unit > 0 used, but GL_ARB_multitexture is not supported\n");
+ return;
+ }
+ glTexCoord1f(s);
+}
+
+static void WINE_GLAPI wine_glMultiTexCoord1fvARB(GLenum target, const GLfloat *v) {
+ if(target != GL_TEXTURE0) {
+ ERR("Texture unit > 0 used, but GL_ARB_multitexture is not supported\n");
+ return;
+ }
+ glTexCoord1fv(v);
+}
+
+static void WINE_GLAPI wine_glMultiTexCoord2fARB(GLenum target, GLfloat s, GLfloat t) {
+ if(target != GL_TEXTURE0) {
+ ERR("Texture unit > 0 used, but GL_ARB_multitexture is not supported\n");
+ return;
+ }
+ glTexCoord2f(s, t);
+}
+
+static void WINE_GLAPI wine_glMultiTexCoord2fvARB(GLenum target, const GLfloat *v) {
+ if(target != GL_TEXTURE0) {
+ ERR("Texture unit > 0 used, but GL_ARB_multitexture is not supported\n");
+ return;
+ }
+ glTexCoord2fv(v);
+}
+
+static void WINE_GLAPI wine_glMultiTexCoord3fARB(GLenum target, GLfloat s, GLfloat t, GLfloat r) {
+ if(target != GL_TEXTURE0) {
+ ERR("Texture unit > 0 used, but GL_ARB_multitexture is not supported\n");
+ return;
+ }
+ glTexCoord3f(s, t, r);
+}
+
+static void WINE_GLAPI wine_glMultiTexCoord3fvARB(GLenum target, const GLfloat *v) {
+ if(target != GL_TEXTURE0) {
+ ERR("Texture unit > 0 used, but GL_ARB_multitexture is not supported\n");
+ return;
+ }
+ glTexCoord3fv(v);
+}
+
+static void WINE_GLAPI wine_glMultiTexCoord4fARB(GLenum target, GLfloat s, GLfloat t, GLfloat r, GLfloat q) {
+ if(target != GL_TEXTURE0) {
+ ERR("Texture unit > 0 used, but GL_ARB_multitexture is not supported\n");
+ return;
+ }
+ glTexCoord4f(s, t, r, q);
+}
+
+static void WINE_GLAPI wine_glMultiTexCoord4fvARB(GLenum target, const GLfloat *v) {
+ if(target != GL_TEXTURE0) {
+ ERR("Texture unit > 0 used, but GL_ARB_multitexture is not supported\n");
+ return;
+ }
+ glTexCoord4fv(v);
+}
+
+static void WINE_GLAPI wine_glMultiTexCoord2svARB(GLenum target, const GLshort *v) {
+ if(target != GL_TEXTURE0) {
+ ERR("Texture unit > 0 used, but GL_ARB_multitexture is not supported\n");
+ return;
+ }
+ glTexCoord2sv(v);
+}
+
+static void WINE_GLAPI wine_glMultiTexCoord4svARB(GLenum target, const GLshort *v) {
+ if(target != GL_TEXTURE0) {
+ ERR("Texture unit > 0 used, but GL_ARB_multitexture is not supported\n");
+ return;
+ }
+ glTexCoord4sv(v);
+}
+
+static void WINE_GLAPI wine_glActiveTextureARB(GLenum texture) {
+ if(texture != GL_TEXTURE0) {
+ ERR("Texture unit > 0 used, but GL_ARB_multitexture is not supported\n");
+ return;
+ }
+}
+
+static void WINE_GLAPI wine_glClientActiveTextureARB(GLenum texture) {
+ if(texture != GL_TEXTURE0) {
+ ERR("Texture unit > 0 used, but GL_ARB_multitexture is not supported\n");
+ return;
+ }
+}
+
+static void (WINE_GLAPI *old_multitex_glGetIntegerv) (GLenum pname, GLint* params) = NULL;
+static void WINE_GLAPI wine_glGetIntegerv(GLenum pname, GLint* params) {
+ switch(pname) {
+ case GL_ACTIVE_TEXTURE: *params = 0; break;
+ case GL_MAX_TEXTURE_UNITS_ARB: *params = 1; break;
+ default: old_multitex_glGetIntegerv(pname, params);
+ }
+}
+
+static void (WINE_GLAPI *old_multitex_glGetFloatv) (GLenum pname, GLfloat* params) = NULL;
+static void WINE_GLAPI wine_glGetFloatv(GLenum pname, GLfloat* params) {
+ if(pname == GL_ACTIVE_TEXTURE) *params = 0.0;
+ else old_multitex_glGetFloatv(pname, params);
+}
+
+static void (WINE_GLAPI *old_multitex_glGetDoublev) (GLenum pname, GLdouble* params) = NULL;
+static void WINE_GLAPI wine_glGetDoublev(GLenum pname, GLdouble* params) {
+ if(pname == GL_ACTIVE_TEXTURE) *params = 0.0;
+ else old_multitex_glGetDoublev(pname, params);
+}
+
+/* Start GL_EXT_fogcoord emulation */
+static void (WINE_GLAPI *old_fogcoord_glEnable) (GLenum cap) = NULL;
+static void WINE_GLAPI wine_glEnable(GLenum cap) {
+ if(cap == GL_FOG) {
+ WineD3DContext *ctx = getActiveContext();
+ ctx->fog_enabled = 1;
+ if(ctx->gl_fog_source != GL_FRAGMENT_DEPTH_EXT) return;
+ }
+ old_fogcoord_glEnable(cap);
+}
+
+static void (WINE_GLAPI *old_fogcoord_glDisable) (GLenum cap) = NULL;
+static void WINE_GLAPI wine_glDisable(GLenum cap) {
+ if(cap == GL_FOG) {
+ WineD3DContext *ctx = getActiveContext();
+ ctx->fog_enabled = 0;
+ if(ctx->gl_fog_source != GL_FRAGMENT_DEPTH_EXT) return;
+ }
+ old_fogcoord_glDisable(cap);
+}
+
+static void (WINE_GLAPI *old_fogcoord_glFogi) (GLenum pname, GLint param) = NULL;
+static void WINE_GLAPI wine_glFogi(GLenum pname, GLint param) {
+ if(pname == GL_FOG_COORDINATE_SOURCE_EXT) {
+ WineD3DContext *ctx = getActiveContext();
+ ctx->gl_fog_source = param;
+ if(param == GL_FRAGMENT_DEPTH_EXT) {
+ if(ctx->fog_enabled) old_fogcoord_glEnable(GL_FOG);
+ } else {
+ WARN("Fog coords activated, but not supported. Using slow emulation\n");
+ old_fogcoord_glDisable(GL_FOG);
+ }
+ } else {
+ if(pname == GL_FOG_START) {
+ getActiveContext()->fogstart = param;
+ } else if(pname == GL_FOG_END) {
+ getActiveContext()->fogend = param;
+ }
+ old_fogcoord_glFogi(pname, param);
+ }
+}
+
+static void (WINE_GLAPI *old_fogcoord_glFogiv) (GLenum pname, const GLint *param) = NULL;
+static void WINE_GLAPI wine_glFogiv(GLenum pname, const GLint *param) {
+ if(pname == GL_FOG_COORDINATE_SOURCE_EXT) {
+ WineD3DContext *ctx = getActiveContext();
+ ctx->gl_fog_source = *param;
+ if(*param == GL_FRAGMENT_DEPTH_EXT) {
+ if(ctx->fog_enabled) old_fogcoord_glEnable(GL_FOG);
+ } else {
+ WARN("Fog coords activated, but not supported. Using slow emulation\n");
+ old_fogcoord_glDisable(GL_FOG);
+ }
+ } else {
+ if(pname == GL_FOG_START) {
+ getActiveContext()->fogstart = *param;
+ } else if(pname == GL_FOG_END) {
+ getActiveContext()->fogend = *param;
+ }
+ old_fogcoord_glFogiv(pname, param);
+ }
+}
+
+static void (WINE_GLAPI *old_fogcoord_glFogf) (GLenum pname, GLfloat param) = NULL;
+static void WINE_GLAPI wine_glFogf(GLenum pname, GLfloat param) {
+ if(pname == GL_FOG_COORDINATE_SOURCE_EXT) {
+ WineD3DContext *ctx = getActiveContext();
+ ctx->gl_fog_source = (GLint) param;
+ if(param == GL_FRAGMENT_DEPTH_EXT) {
+ if(ctx->fog_enabled) old_fogcoord_glEnable(GL_FOG);
+ } else {
+ WARN("Fog coords activated, but not supported. Using slow emulation\n");
+ old_fogcoord_glDisable(GL_FOG);
+ }
+ } else {
+ if(pname == GL_FOG_START) {
+ getActiveContext()->fogstart = param;
+ } else if(pname == GL_FOG_END) {
+ getActiveContext()->fogend = param;
+ }
+ old_fogcoord_glFogf(pname, param);
+ }
+}
+
+static void (WINE_GLAPI *old_fogcoord_glFogfv) (GLenum pname, const GLfloat *param) = NULL;
+static void WINE_GLAPI wine_glFogfv(GLenum pname, const GLfloat *param) {
+ if(pname == GL_FOG_COORDINATE_SOURCE_EXT) {
+ WineD3DContext *ctx = getActiveContext();
+ ctx->gl_fog_source = (GLint) *param;
+ if(*param == GL_FRAGMENT_DEPTH_EXT) {
+ if(ctx->fog_enabled) old_fogcoord_glEnable(GL_FOG);
+ } else {
+ WARN("Fog coords activated, but not supported. Using slow emulation\n");
+ old_fogcoord_glDisable(GL_FOG);
+ }
+ } else {
+ if(pname == GL_FOG_COLOR) {
+ WineD3DContext *ctx = getActiveContext();
+ ctx->fogcolor[0] = param[0];
+ ctx->fogcolor[1] = param[1];
+ ctx->fogcolor[2] = param[2];
+ ctx->fogcolor[3] = param[3];
+ } else if(pname == GL_FOG_START) {
+ getActiveContext()->fogstart = *param;
+ } else if(pname == GL_FOG_END) {
+ getActiveContext()->fogend = *param;
+ }
+ old_fogcoord_glFogfv(pname, param);
+ }
+}
+
+static void (WINE_GLAPI *old_fogcoord_glVertex4f) (GLfloat x, GLfloat y, GLfloat z, GLfloat w) = NULL;
+static void (WINE_GLAPI *old_fogcoord_glVertex4fv) (const GLfloat *pos) = NULL;
+static void (WINE_GLAPI *old_fogcoord_glVertex3f) (GLfloat x, GLfloat y, GLfloat z) = NULL;
+static void (WINE_GLAPI *old_fogcoord_glVertex3fv) (const GLfloat *pos) = NULL;
+static void (WINE_GLAPI *old_fogcoord_glColor4f) (GLfloat r, GLfloat g, GLfloat b, GLfloat a) = NULL;
+static void (WINE_GLAPI *old_fogcoord_glColor4fv) (const GLfloat *color) = NULL;
+static void (WINE_GLAPI *old_fogcoord_glColor3f) (GLfloat r, GLfloat g, GLfloat b) = NULL;
+static void (WINE_GLAPI *old_fogcoord_glColor3fv) (const GLfloat *color) = NULL;
+static void (WINE_GLAPI *old_fogcoord_glColor4ub) (GLubyte r, GLubyte g, GLubyte b, GLubyte a) = NULL;
+static void (WINE_GLAPI *old_fogcoord_glFogCoordfEXT) (GLfloat f) = NULL;
+static void (WINE_GLAPI *old_fogcoord_glFogCoorddEXT) (GLdouble f) = NULL;
+static void (WINE_GLAPI *old_fogcoord_glFogCoordfvEXT) (const GLfloat *f) = NULL;
+static void (WINE_GLAPI *old_fogcoord_glFogCoorddvEXT) (const GLdouble *f) = NULL;
+
+static void WINE_GLAPI wine_glVertex4f(GLfloat x, GLfloat y, GLfloat z, GLfloat w) {
+ WineD3DContext *ctx = getActiveContext();
+ if(ctx->gl_fog_source == GL_FOG_COORDINATE_EXT && ctx->fog_enabled) {
+ GLfloat c[4] = {ctx->color[0], ctx->color[1], ctx->color[2], ctx->color[3]};
+ GLfloat i;
+
+ i = (ctx->fogend - ctx->fog_coord_value) / (ctx->fogend - ctx->fogstart);
+ c[0] = i * c[0] + (1.0 - i) * ctx->fogcolor[0];
+ c[1] = i * c[1] + (1.0 - i) * ctx->fogcolor[1];
+ c[2] = i * c[2] + (1.0 - i) * ctx->fogcolor[2];
+
+ old_fogcoord_glColor4f(c[0], c[1], c[2], c[3]);
+ old_fogcoord_glVertex4f(x, y, z, w);
+ } else {
+ old_fogcoord_glVertex4f(x, y, z, w);
+ }
+}
+
+static void WINE_GLAPI wine_glVertex4fv(const GLfloat *pos) {
+ wine_glVertex4f(pos[0], pos[1], pos[2], pos[3]);
+}
+
+static void WINE_GLAPI wine_glVertex3f(GLfloat x, GLfloat y, GLfloat z) {
+ wine_glVertex4f(x, y, z, 1.0);
+}
+
+static void WINE_GLAPI wine_glVertex3fv(const GLfloat *pos) {
+ wine_glVertex4f(pos[0], pos[1], pos[2], 1.0);
+}
+
+static void wine_glColor4f(GLfloat r, GLfloat g, GLfloat b, GLfloat a) {
+ WineD3DContext *ctx = getActiveContext();
+ ctx->color[0] = r;
+ ctx->color[1] = g;
+ ctx->color[2] = b;
+ ctx->color[3] = a;
+ old_fogcoord_glColor4f(r, g, b, a);
+}
+
+static void wine_glColor4fv(const GLfloat *c) {
+ wine_glColor4f(c[0], c[1], c[2], c[3]);
+}
+
+static void wine_glColor3f(GLfloat r, GLfloat g, GLfloat b) {
+ wine_glColor4f(r, g, b, 1.0);
+}
+
+static void wine_glColor3fv(const GLfloat *c) {
+ wine_glColor4f(c[0], c[1], c[2], 1.0);
+}
+
+static void wine_glColor4ub(GLubyte r, GLubyte g, GLubyte b, GLubyte a) {
+ wine_glColor4f(r / 255.0, g / 255.0, b / 255.0, a / 255.0);
+}
+
+/* In D3D the fog coord is a UBYTE, so there's no problem with using the single
+ * precision function
+ */
+static void wine_glFogCoordfEXT(GLfloat f) {
+ WineD3DContext *ctx = getActiveContext();
+ ctx->fog_coord_value = f;
+}
+static void wine_glFogCoorddEXT(GLdouble f) {
+ wine_glFogCoordfEXT(f);
+}
+static void wine_glFogCoordfvEXT(const GLfloat *f) {
+ wine_glFogCoordfEXT(*f);
+}
+static void wine_glFogCoorddvEXT(const GLdouble *f) {
+ wine_glFogCoordfEXT(*f);
+}
+
+/* End GL_EXT_fog_coord emulation */
+
+#define GLINFO_LOCATION (*gl_info)
+void add_gl_compat_wrappers(WineD3D_GL_Info *gl_info) {
+ if(!GL_SUPPORT(ARB_MULTITEXTURE)) {
+ TRACE("Applying GL_ARB_multitexture emulation hooks\n");
+ gl_info->glActiveTextureARB = wine_glActiveTextureARB;
+ gl_info->glClientActiveTextureARB = wine_glClientActiveTextureARB;
+ gl_info->glMultiTexCoord1fARB = wine_glMultiTexCoord1fARB;
+ gl_info->glMultiTexCoord1fvARB = wine_glMultiTexCoord1fvARB;
+ gl_info->glMultiTexCoord2fARB = wine_glMultiTexCoord2fARB;
+ gl_info->glMultiTexCoord2fvARB = wine_glMultiTexCoord2fvARB;
+ gl_info->glMultiTexCoord3fARB = wine_glMultiTexCoord3fARB;
+ gl_info->glMultiTexCoord3fvARB = wine_glMultiTexCoord3fvARB;
+ gl_info->glMultiTexCoord4fARB = wine_glMultiTexCoord4fARB;
+ gl_info->glMultiTexCoord4fvARB = wine_glMultiTexCoord4fvARB;
+ gl_info->glMultiTexCoord2svARB = wine_glMultiTexCoord2svARB;
+ gl_info->glMultiTexCoord4svARB = wine_glMultiTexCoord4svARB;
+ if(old_multitex_glGetIntegerv) {
+ FIXME("GL_ARB_multitexture glGetIntegerv hook already applied\n");
+ } else {
+ old_multitex_glGetIntegerv = glGetIntegerv;
+ glGetIntegerv = wine_glGetIntegerv;
+ }
+ if(old_multitex_glGetFloatv) {
+ FIXME("GL_ARB_multitexture glGetGloatv hook already applied\n");
+ } else {
+ old_multitex_glGetFloatv = glGetFloatv;
+ glGetFloatv = wine_glGetFloatv;
+ }
+ if(old_multitex_glGetDoublev) {
+ FIXME("GL_ARB_multitexture glGetDoublev hook already applied\n");
+ } else {
+ old_multitex_glGetDoublev = glGetDoublev;
+ glGetDoublev = wine_glGetDoublev;
+ }
+ gl_info->supported[ARB_MULTITEXTURE] = TRUE;
+ }
+
+ if(!GL_SUPPORT(EXT_FOG_COORD)) {
+ /* This emulation isn't perfect. There are a number of potential problems, but they should
+ * not matter in practise:
+ *
+ * Fog vs fragment shader: If we are using GL_ARB_fragment_program with the fog option, the
+ * glDisable(GL_FOG) here won't matter. However, if we have GL_ARB_fragment_program, it is pretty
+ * unlikely that we don't have GL_EXT_fog_coord. Besides, we probably have GL_ARB_vertex_program
+ * too, which would allow fog coord emulation in a fixed function vertex pipeline replacement.
+ *
+ * Fog vs texture: We apply the fog in the vertex color. An app could set up texturing settings which
+ * ignore the vertex color, thus effectively disabing our fog. However, in D3D this type of fog is
+ * a per-vertex fog too, so the apps shouldn't do that.
+ *
+ * Fog vs lighting: The app could in theory use D3DFOG_NONE table and D3DFOG_NONE vertex fog with
+ * untransformed vertices. That enables lighting and fog coords at the same time, and the lighting
+ * calculations could affect the already blended in fog color. There's nothing we can do against that,
+ * but most apps using fog color do their own lighting too and often even use RHW vertices. So live
+ * with it.
+ */
+ TRACE("Applying GL_ARB_fog_coord emulation hooks\n");
+
+ /* This probably means that the implementation doesn't advertise the extension, but implicitly supports
+ * it via the GL core version, or someone messed around in the extension table in directx.c. Add version-
+ * dependent loading for this extension if we ever hit this situation
+ */
+ if(GL_SUPPORT(ARB_FRAGMENT_PROGRAM)) {
+ FIXME("GL implementation supports GL_ARB_fragment_program but not GL_EXT_fog_coord\n");
+ FIXME("The fog coord emulation will most likely fail\n");
+ } else if(GL_SUPPORT(ARB_FRAGMENT_SHADER)) {
+ FIXME("GL implementation supports GL_ARB_fragment_shader but not GL_EXT_fog_coord\n");
+ FIXME("The fog coord emulation will most likely fail\n");
+ }
+
+ if(old_fogcoord_glFogi) {
+ FIXME("GL_EXT_fogcoord glFogi hook already applied\n");
+ } else {
+ old_fogcoord_glFogi = glFogi;
+ glFogi = wine_glFogi;
+ }
+ if(old_fogcoord_glFogiv) {
+ FIXME("GL_EXT_fogcoord glFogiv hook already applied\n");
+ } else {
+ old_fogcoord_glFogiv = glFogiv;
+ glFogiv = wine_glFogiv;
+ }
+ if(old_fogcoord_glFogf) {
+ FIXME("GL_EXT_fogcoord glFogf hook already applied\n");
+ } else {
+ old_fogcoord_glFogf = glFogf;
+ glFogf = wine_glFogf;
+ }
+ if(old_fogcoord_glFogfv) {
+ FIXME("GL_EXT_fogcoord glFogfv hook already applied\n");
+ } else {
+ old_fogcoord_glFogfv = glFogfv;
+ glFogfv = wine_glFogfv;
+ }
+ if(old_fogcoord_glEnable) {
+ FIXME("GL_EXT_fogcoord glEnable hook already applied\n");
+ } else {
+ old_fogcoord_glEnable = glEnableWINE;
+ glEnableWINE = wine_glEnable;
+ }
+ if(old_fogcoord_glDisable) {
+ FIXME("GL_EXT_fogcoord glDisable hook already applied\n");
+ } else {
+ old_fogcoord_glDisable = glDisableWINE;
+ glDisableWINE = wine_glDisable;
+ }
+
+ if(old_fogcoord_glVertex4f) {
+ FIXME("GL_EXT_fogcoord glVertex4f hook already applied\n");
+ } else {
+ old_fogcoord_glVertex4f = glVertex4f;
+ glVertex4f = wine_glVertex4f;
+ }
+ if(old_fogcoord_glVertex4fv) {
+ FIXME("GL_EXT_fogcoord glVertex4fv hook already applied\n");
+ } else {
+ old_fogcoord_glVertex4fv = glVertex4fv;
+ glVertex4fv = wine_glVertex4fv;
+ }
+ if(old_fogcoord_glVertex3f) {
+ FIXME("GL_EXT_fogcoord glVertex3f hook already applied\n");
+ } else {
+ old_fogcoord_glVertex3f = glVertex3f;
+ glVertex3f = wine_glVertex3f;
+ }
+ if(old_fogcoord_glVertex3fv) {
+ FIXME("GL_EXT_fogcoord glVertex3fv hook already applied\n");
+ } else {
+ old_fogcoord_glVertex3fv = glVertex3fv;
+ glVertex3fv = wine_glVertex3fv;
+ }
+
+ if(old_fogcoord_glColor4f) {
+ FIXME("GL_EXT_fogcoord glColor4f hook already applied\n");
+ } else {
+ old_fogcoord_glColor4f = glColor4f;
+ glColor4f = wine_glColor4f;
+ }
+ if(old_fogcoord_glColor4fv) {
+ FIXME("GL_EXT_fogcoord glColor4fv hook already applied\n");
+ } else {
+ old_fogcoord_glColor4fv = glColor4fv;
+ glColor4fv = wine_glColor4fv;
+ }
+ if(old_fogcoord_glColor3f) {
+ FIXME("GL_EXT_fogcoord glColor3f hook already applied\n");
+ } else {
+ old_fogcoord_glColor3f = glColor3f;
+ glColor3f = wine_glColor3f;
+ }
+ if(old_fogcoord_glColor3fv) {
+ FIXME("GL_EXT_fogcoord glColor3fv hook already applied\n");
+ } else {
+ old_fogcoord_glColor3fv = glColor3fv;
+ glColor3fv = wine_glColor3fv;
+ }
+ if(old_fogcoord_glColor4ub) {
+ FIXME("GL_EXT_fogcoord glColor4ub hook already applied\n");
+ } else {
+ old_fogcoord_glColor4ub = glColor4ub;
+ glColor4ub = wine_glColor4ub;
+ }
+
+ if(old_fogcoord_glFogCoordfEXT) {
+ FIXME("GL_EXT_fogcoord glFogCoordfEXT hook already applied\n");
+ } else {
+ old_fogcoord_glFogCoordfEXT = gl_info->glFogCoordfEXT;
+ gl_info->glFogCoordfEXT = wine_glFogCoordfEXT;
+ }
+ if(old_fogcoord_glFogCoordfvEXT) {
+ FIXME("GL_EXT_fogcoord glFogCoordfvEXT hook already applied\n");
+ } else {
+ old_fogcoord_glFogCoordfvEXT = gl_info->glFogCoordfvEXT;
+ gl_info->glFogCoordfvEXT = wine_glFogCoordfvEXT;
+ }
+ if(old_fogcoord_glFogCoorddEXT) {
+ FIXME("GL_EXT_fogcoord glFogCoorddEXT hook already applied\n");
+ } else {
+ old_fogcoord_glFogCoorddEXT = gl_info->glFogCoorddEXT;
+ gl_info->glFogCoorddEXT = wine_glFogCoorddEXT;
+ }
+ if(old_fogcoord_glFogCoorddvEXT) {
+ FIXME("GL_EXT_fogcoord glFogCoorddvEXT hook already applied\n");
+ } else {
+ old_fogcoord_glFogCoorddvEXT = gl_info->glFogCoorddvEXT;
+ gl_info->glFogCoorddvEXT = wine_glFogCoorddvEXT;
+ }
+ gl_info->supported[EXT_FOG_COORD] = TRUE;
+ }
+}
+#undef GLINFO_LOCATION
*/
#include "config.h"
+#include <limits.h>
#include <stdio.h>
#include "wined3d_private.h"
DWORD coord_mask;
} glsl_sample_function_t;
+enum heap_node_op
+{
+ HEAP_NODE_TRAVERSE_LEFT,
+ HEAP_NODE_TRAVERSE_RIGHT,
+ HEAP_NODE_POP,
+};
+
+struct constant_entry
+{
+ unsigned int idx;
+ unsigned int version;
+};
+
+struct constant_heap
+{
+ struct constant_entry *entries;
+ unsigned int *positions;
+ unsigned int size;
+};
+
/* GLSL shader private data */
struct shader_glsl_priv {
struct hash_table_t *glsl_program_lookup;
- const struct glsl_shader_prog_link *glsl_program;
+ struct glsl_shader_prog_link *glsl_program;
+ struct constant_heap vconst_heap;
+ struct constant_heap pconst_heap;
+ unsigned char *stack;
GLhandleARB depth_blt_program[tex_type_count];
+ UINT next_constant_version;
};
/* Struct to maintain data about a linked GLSL program */
GLhandleARB vshader;
IWineD3DPixelShader *pshader;
struct ps_compile_args ps_args;
+ UINT constant_version;
};
typedef struct {
unsigned int i;
BOOL is_spam;
- const char *spam[] = {
+ static const char * const spam[] =
+ {
"Vertex shader was successfully compiled to run on hardware.\n", /* fglrx */
"Fragment shader was successfully compiled to run on hardware.\n", /* fglrx */
"Fragment shader(s) linked, vertex shader(s) linked. \n ", /* fglrx, with \n */
"Fragment shader(s) linked, vertex shader(s) linked.", /* fglrx, no \n */
"Vertex shader(s) linked, no fragment shader(s) defined. \n ", /* fglrx, with \n */
"Vertex shader(s) linked, no fragment shader(s) defined.", /* fglrx, no \n */
- "Fragment shader was successfully compiled to run on hardware.\nWARNING: 0:1: extension 'GL_ARB_draw_buffers' is not supported",
+ "Fragment shader was successfully compiled to run on hardware.\n"
+ "WARNING: 0:2: extension 'GL_ARB_draw_buffers' is not supported",
"Fragment shader(s) linked, no vertex shader(s) defined.", /* fglrx, no \n */
"Fragment shader(s) linked, no vertex shader(s) defined. \n ", /* fglrx, with \n */
"WARNING: 0:2: extension 'GL_ARB_draw_buffers' is not supported\n" /* MacOS ati */
};
+ if (!TRACE_ON(d3d_shader) && !FIXME_ON(d3d_shader)) return;
+
GL_EXTCALL(glGetObjectParameterivARB(obj,
GL_OBJECT_INFO_LOG_LENGTH_ARB,
&infologLength));
}
}
-/**
- * Loads floating point constants (aka uniforms) into the currently set GLSL program.
- * When constant_list == NULL, it will load all the constants.
- */
-static void shader_glsl_load_constantsF(IWineD3DBaseShaderImpl *This, const WineD3D_GL_Info *gl_info,
- unsigned int max_constants, const float *constants, const GLhandleARB *constant_locations,
- const struct list *constant_list)
+static inline void walk_constant_heap(const WineD3D_GL_Info *gl_info, const float *constants,
+ const GLhandleARB *constant_locations, const struct constant_heap *heap, unsigned char *stack, DWORD version)
{
- const constants_entry *constant;
- const local_constant *lconst;
- GLhandleARB tmp_loc;
- DWORD i, j, k;
- const DWORD *idx;
-
- if (TRACE_ON(d3d_shader)) {
- LIST_FOR_EACH_ENTRY(constant, constant_list, constants_entry, entry) {
- idx = constant->idx;
- j = constant->count;
- while (j--) {
- i = *idx++;
- tmp_loc = constant_locations[i];
- if (tmp_loc != -1) {
- TRACE_(d3d_constants)("Loading constants %i: %f, %f, %f, %f\n", i,
- constants[i * 4 + 0], constants[i * 4 + 1],
- constants[i * 4 + 2], constants[i * 4 + 3]);
+ int stack_idx = 0;
+ unsigned int heap_idx = 1;
+ unsigned int idx;
+
+ if (heap->entries[heap_idx].version <= version) return;
+
+ idx = heap->entries[heap_idx].idx;
+ if (constant_locations[idx] != -1) GL_EXTCALL(glUniform4fvARB(constant_locations[idx], 1, &constants[idx * 4]));
+ stack[stack_idx] = HEAP_NODE_TRAVERSE_LEFT;
+
+ while (stack_idx >= 0)
+ {
+ /* Note that we fall through to the next case statement. */
+ switch(stack[stack_idx])
+ {
+ case HEAP_NODE_TRAVERSE_LEFT:
+ {
+ unsigned int left_idx = heap_idx << 1;
+ if (left_idx < heap->size && heap->entries[left_idx].version > version)
+ {
+ heap_idx = left_idx;
+ idx = heap->entries[heap_idx].idx;
+ if (constant_locations[idx] != -1)
+ GL_EXTCALL(glUniform4fvARB(constant_locations[idx], 1, &constants[idx * 4]));
+
+ stack[stack_idx++] = HEAP_NODE_TRAVERSE_RIGHT;
+ stack[stack_idx] = HEAP_NODE_TRAVERSE_LEFT;
+ break;
}
}
+
+ case HEAP_NODE_TRAVERSE_RIGHT:
+ {
+ unsigned int right_idx = (heap_idx << 1) + 1;
+ if (right_idx < heap->size && heap->entries[right_idx].version > version)
+ {
+ heap_idx = right_idx;
+ idx = heap->entries[heap_idx].idx;
+ if (constant_locations[idx] != -1)
+ GL_EXTCALL(glUniform4fvARB(constant_locations[idx], 1, &constants[idx * 4]));
+
+ stack[stack_idx++] = HEAP_NODE_POP;
+ stack[stack_idx] = HEAP_NODE_TRAVERSE_LEFT;
+ break;
+ }
+ }
+
+ case HEAP_NODE_POP:
+ {
+ heap_idx >>= 1;
+ --stack_idx;
+ break;
+ }
}
}
+ checkGLcall("walk_constant_heap()");
+}
- /* 1.X pshaders have the constants clamped to [-1;1] implicitly. */
- if(WINED3DSHADER_VERSION_MAJOR(This->baseShader.hex_version) == 1 &&
- shader_is_pshader_version(This->baseShader.hex_version)) {
- float lcl_const[4];
-
- LIST_FOR_EACH_ENTRY(constant, constant_list, constants_entry, entry) {
- idx = constant->idx;
- j = constant->count;
- while (j--) {
- i = *idx++;
- tmp_loc = constant_locations[i];
- if (tmp_loc != -1) {
- /* We found this uniform name in the program - go ahead and send the data */
- k = i * 4;
- if(constants[k + 0] < -1.0) lcl_const[0] = -1.0;
- else if(constants[k + 0] > 1.0) lcl_const[0] = 1.0;
- else lcl_const[0] = constants[k + 0];
- if(constants[k + 1] < -1.0) lcl_const[1] = -1.0;
- else if(constants[k + 1] > 1.0) lcl_const[1] = 1.0;
- else lcl_const[1] = constants[k + 1];
- if(constants[k + 2] < -1.0) lcl_const[2] = -1.0;
- else if(constants[k + 2] > 1.0) lcl_const[2] = 1.0;
- else lcl_const[2] = constants[k + 2];
- if(constants[k + 3] < -1.0) lcl_const[3] = -1.0;
- else if(constants[k + 3] > 1.0) lcl_const[3] = 1.0;
- else lcl_const[3] = constants[k + 3];
-
- GL_EXTCALL(glUniform4fvARB(tmp_loc, 1, lcl_const));
+static inline void apply_clamped_constant(const WineD3D_GL_Info *gl_info, GLint location, const GLfloat *data)
+{
+ GLfloat clamped_constant[4];
+
+ if (location == -1) return;
+
+ clamped_constant[0] = data[0] < -1.0f ? -1.0f : data[0] > 1.0 ? 1.0 : data[0];
+ clamped_constant[1] = data[1] < -1.0f ? -1.0f : data[1] > 1.0 ? 1.0 : data[1];
+ clamped_constant[2] = data[2] < -1.0f ? -1.0f : data[2] > 1.0 ? 1.0 : data[2];
+ clamped_constant[3] = data[3] < -1.0f ? -1.0f : data[3] > 1.0 ? 1.0 : data[3];
+
+ GL_EXTCALL(glUniform4fvARB(location, 1, clamped_constant));
+}
+
+static inline void walk_constant_heap_clamped(const WineD3D_GL_Info *gl_info, const float *constants,
+ const GLhandleARB *constant_locations, const struct constant_heap *heap, unsigned char *stack, DWORD version)
+{
+ int stack_idx = 0;
+ unsigned int heap_idx = 1;
+ unsigned int idx;
+
+ if (heap->entries[heap_idx].version <= version) return;
+
+ idx = heap->entries[heap_idx].idx;
+ apply_clamped_constant(gl_info, constant_locations[idx], &constants[idx * 4]);
+ stack[stack_idx] = HEAP_NODE_TRAVERSE_LEFT;
+
+ while (stack_idx >= 0)
+ {
+ /* Note that we fall through to the next case statement. */
+ switch(stack[stack_idx])
+ {
+ case HEAP_NODE_TRAVERSE_LEFT:
+ {
+ unsigned int left_idx = heap_idx << 1;
+ if (left_idx < heap->size && heap->entries[left_idx].version > version)
+ {
+ heap_idx = left_idx;
+ idx = heap->entries[heap_idx].idx;
+ apply_clamped_constant(gl_info, constant_locations[idx], &constants[idx * 4]);
+
+ stack[stack_idx++] = HEAP_NODE_TRAVERSE_RIGHT;
+ stack[stack_idx] = HEAP_NODE_TRAVERSE_LEFT;
+ break;
}
}
- }
- } else {
- LIST_FOR_EACH_ENTRY(constant, constant_list, constants_entry, entry) {
- idx = constant->idx;
- j = constant->count;
- while (j--) {
- i = *idx++;
- tmp_loc = constant_locations[i];
- 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)));
+
+ case HEAP_NODE_TRAVERSE_RIGHT:
+ {
+ unsigned int right_idx = (heap_idx << 1) + 1;
+ if (right_idx < heap->size && heap->entries[right_idx].version > version)
+ {
+ heap_idx = right_idx;
+ idx = heap->entries[heap_idx].idx;
+ apply_clamped_constant(gl_info, constant_locations[idx], &constants[idx * 4]);
+
+ stack[stack_idx++] = HEAP_NODE_POP;
+ stack[stack_idx] = HEAP_NODE_TRAVERSE_LEFT;
+ break;
}
}
+
+ case HEAP_NODE_POP:
+ {
+ heap_idx >>= 1;
+ --stack_idx;
+ break;
+ }
}
}
- checkGLcall("glUniform4fvARB()");
+ checkGLcall("walk_constant_heap_clamped()");
+}
- if(!This->baseShader.load_local_constsF) {
+/* Loads floating point constants (aka uniforms) into the currently set GLSL program. */
+static void shader_glsl_load_constantsF(IWineD3DBaseShaderImpl *This, const WineD3D_GL_Info *gl_info,
+ const float *constants, const GLhandleARB *constant_locations, const struct constant_heap *heap,
+ unsigned char *stack, UINT version)
+{
+ const local_constant *lconst;
+
+ /* 1.X pshaders have the constants clamped to [-1;1] implicitly. */
+ if (WINED3DSHADER_VERSION_MAJOR(This->baseShader.reg_maps.shader_version) == 1
+ && shader_is_pshader_version(This->baseShader.reg_maps.shader_version))
+ walk_constant_heap_clamped(gl_info, constants, constant_locations, heap, stack, version);
+ else
+ walk_constant_heap(gl_info, constants, constant_locations, heap, stack, version);
+
+ if (!This->baseShader.load_local_constsF)
+ {
TRACE("No need to load local float constants for this shader\n");
return;
}
- /* Load immediate constants */
- if (TRACE_ON(d3d_shader)) {
- LIST_FOR_EACH_ENTRY(lconst, &This->baseShader.constantsF, local_constant, entry) {
- tmp_loc = constant_locations[lconst->idx];
- if (tmp_loc != -1) {
- const GLfloat *values = (const GLfloat *)lconst->value;
- TRACE_(d3d_constants)("Loading local constants %i: %f, %f, %f, %f\n", lconst->idx,
- values[0], values[1], values[2], values[3]);
- }
- }
- }
/* Immediate constants are clamped to [-1;1] at shader creation time if needed */
- LIST_FOR_EACH_ENTRY(lconst, &This->baseShader.constantsF, local_constant, entry) {
- tmp_loc = constant_locations[lconst->idx];
- if (tmp_loc != -1) {
- /* We found this uniform name in the program - go ahead and send the data */
- GL_EXTCALL(glUniform4fvARB(tmp_loc, 1, (const GLfloat *)lconst->value));
- }
+ LIST_FOR_EACH_ENTRY(lconst, &This->baseShader.constantsF, local_constant, entry)
+ {
+ GLhandleARB location = constant_locations[lconst->idx];
+ /* We found this uniform name in the program - go ahead and send the data */
+ if (location != -1) GL_EXTCALL(glUniform4fvARB(location, 1, (const GLfloat *)lconst->value));
}
checkGLcall("glUniform4fvARB()");
}
GLhandleARB tmp_loc;
unsigned int i;
char tmp_name[8];
- char is_pshader = shader_is_pshader_version(This->baseShader.hex_version);
+ char is_pshader = shader_is_pshader_version(This->baseShader.reg_maps.shader_version);
const char* prefix = is_pshader? "PB":"VB";
struct list* ptr;
}
}
-
+static void reset_program_constant_version(void *value, void *context)
+{
+ struct glsl_shader_prog_link *entry = (struct glsl_shader_prog_link *)value;
+ entry->constant_version = 0;
+}
/**
* Loads the app-supplied constants into the currently set GLSL program.
char useVertexShader) {
IWineD3DDeviceImpl* deviceImpl = (IWineD3DDeviceImpl*) device;
- const struct shader_glsl_priv *priv = (struct shader_glsl_priv *)deviceImpl->shader_priv;
+ struct shader_glsl_priv *priv = (struct shader_glsl_priv *)deviceImpl->shader_priv;
IWineD3DStateBlockImpl* stateBlock = deviceImpl->stateBlock;
const WineD3D_GL_Info *gl_info = &deviceImpl->adapter->gl_info;
- const GLhandleARB *constant_locations;
- const struct list *constant_list;
GLhandleARB programId;
- const struct glsl_shader_prog_link *prog = priv->glsl_program;
+ struct glsl_shader_prog_link *prog = priv->glsl_program;
+ UINT constant_version;
int i;
if (!prog) {
return;
}
programId = prog->programId;
+ constant_version = prog->constant_version;
if (useVertexShader) {
IWineD3DBaseShaderImpl* vshader = (IWineD3DBaseShaderImpl*) stateBlock->vertexShader;
- constant_locations = prog->vuniformF_locations;
- constant_list = &stateBlock->set_vconstantsF;
-
/* Load DirectX 9 float constants/uniforms for vertex shader */
- shader_glsl_load_constantsF(vshader, gl_info, GL_LIMITS(vshader_constantsF),
- stateBlock->vertexShaderConstantF, constant_locations, constant_list);
+ shader_glsl_load_constantsF(vshader, gl_info, stateBlock->vertexShaderConstantF,
+ prog->vuniformF_locations, &priv->vconst_heap, priv->stack, constant_version);
/* Load DirectX 9 integer constants/uniforms for vertex shader */
- shader_glsl_load_constantsI(vshader, gl_info, prog->vuniformI_locations,
- stateBlock->vertexShaderConstantI, stateBlock->changed.vertexShaderConstantsI);
+ if(vshader->baseShader.uses_int_consts) {
+ shader_glsl_load_constantsI(vshader, gl_info, prog->vuniformI_locations,
+ stateBlock->vertexShaderConstantI, stateBlock->changed.vertexShaderConstantsI);
+ }
/* Load DirectX 9 boolean constants/uniforms for vertex shader */
- shader_glsl_load_constantsB(vshader, gl_info, programId,
- stateBlock->vertexShaderConstantB, stateBlock->changed.vertexShaderConstantsB);
+ if(vshader->baseShader.uses_bool_consts) {
+ shader_glsl_load_constantsB(vshader, gl_info, programId,
+ stateBlock->vertexShaderConstantB, stateBlock->changed.vertexShaderConstantsB);
+ }
/* Upload the position fixup params */
GL_EXTCALL(glUniform4fvARB(prog->posFixup_location, 1, &deviceImpl->posFixup[0]));
IWineD3DBaseShaderImpl* pshader = (IWineD3DBaseShaderImpl*) stateBlock->pixelShader;
- constant_locations = prog->puniformF_locations;
- constant_list = &stateBlock->set_pconstantsF;
-
/* Load DirectX 9 float constants/uniforms for pixel shader */
- shader_glsl_load_constantsF(pshader, gl_info, GL_LIMITS(pshader_constantsF),
- stateBlock->pixelShaderConstantF, constant_locations, constant_list);
+ shader_glsl_load_constantsF(pshader, gl_info, stateBlock->pixelShaderConstantF,
+ prog->puniformF_locations, &priv->pconst_heap, priv->stack, constant_version);
/* Load DirectX 9 integer constants/uniforms for pixel shader */
- shader_glsl_load_constantsI(pshader, gl_info, prog->puniformI_locations,
- stateBlock->pixelShaderConstantI, stateBlock->changed.pixelShaderConstantsI);
+ if(pshader->baseShader.uses_int_consts) {
+ shader_glsl_load_constantsI(pshader, gl_info, prog->puniformI_locations,
+ stateBlock->pixelShaderConstantI, stateBlock->changed.pixelShaderConstantsI);
+ }
/* Load DirectX 9 boolean constants/uniforms for pixel shader */
- shader_glsl_load_constantsB(pshader, gl_info, programId,
- stateBlock->pixelShaderConstantB, stateBlock->changed.pixelShaderConstantsB);
+ if(pshader->baseShader.uses_bool_consts) {
+ shader_glsl_load_constantsB(pshader, gl_info, programId,
+ stateBlock->pixelShaderConstantB, stateBlock->changed.pixelShaderConstantsB);
+ }
/* Upload the environment bump map matrix if needed. The needsbumpmat member specifies the texture stage to load the matrix from.
* It can't be 0 for a valid texbem instruction.
GL_EXTCALL(glUniform4fvARB(prog->ycorrection_location, 1, correction_params));
}
}
+
+ if (priv->next_constant_version == UINT_MAX)
+ {
+ TRACE("Max constant version reached, resetting to 0.\n");
+ hash_table_for_each_entry(priv->glsl_program_lookup, reset_program_constant_version, NULL);
+ priv->next_constant_version = 1;
+ }
+ else
+ {
+ prog->constant_version = priv->next_constant_version++;
+ }
+}
+
+static inline void update_heap_entry(struct constant_heap *heap, unsigned int idx,
+ unsigned int heap_idx, DWORD new_version)
+{
+ struct constant_entry *entries = heap->entries;
+ unsigned int *positions = heap->positions;
+ unsigned int parent_idx;
+
+ while (heap_idx > 1)
+ {
+ parent_idx = heap_idx >> 1;
+
+ if (new_version <= entries[parent_idx].version) break;
+
+ entries[heap_idx] = entries[parent_idx];
+ positions[entries[parent_idx].idx] = heap_idx;
+ heap_idx = parent_idx;
+ }
+
+ entries[heap_idx].version = new_version;
+ entries[heap_idx].idx = idx;
+ positions[idx] = heap_idx;
+}
+
+static void shader_glsl_update_float_vertex_constants(IWineD3DDevice *iface, UINT start, UINT count)
+{
+ IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
+ struct shader_glsl_priv *priv = (struct shader_glsl_priv *)This->shader_priv;
+ struct constant_heap *heap = &priv->vconst_heap;
+ UINT i;
+
+ for (i = start; i < count + start; ++i)
+ {
+ if (!This->stateBlock->changed.vertexShaderConstantsF[i])
+ update_heap_entry(heap, i, heap->size++, priv->next_constant_version);
+ else
+ update_heap_entry(heap, i, heap->positions[i], priv->next_constant_version);
+ }
+}
+
+static void shader_glsl_update_float_pixel_constants(IWineD3DDevice *iface, UINT start, UINT count)
+{
+ IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
+ struct shader_glsl_priv *priv = (struct shader_glsl_priv *)This->shader_priv;
+ struct constant_heap *heap = &priv->pconst_heap;
+ UINT i;
+
+ for (i = start; i < count + start; ++i)
+ {
+ if (!This->stateBlock->changed.pixelShaderConstantsF[i])
+ update_heap_entry(heap, i, heap->size++, priv->next_constant_version);
+ else
+ update_heap_entry(heap, i, heap->positions[i], priv->next_constant_version);
+ }
}
/** Generate the variable & register declarations for the GLSL output target */
static void shader_generate_glsl_declarations(IWineD3DBaseShader *iface, const shader_reg_maps *reg_maps,
- SHADER_BUFFER *buffer, const WineD3D_GL_Info *gl_info)
+ SHADER_BUFFER *buffer, const WineD3D_GL_Info *gl_info,
+ const struct ps_compile_args *ps_args)
{
IWineD3DBaseShaderImpl* This = (IWineD3DBaseShaderImpl*) iface;
IWineD3DDeviceImpl *device = (IWineD3DDeviceImpl *) This->baseShader.device;
+ DWORD shader_version = reg_maps->shader_version;
unsigned int i, extra_constants_needed = 0;
const local_constant *lconst;
/* There are some minor differences between pixel and vertex shaders */
- char pshader = shader_is_pshader_version(This->baseShader.hex_version);
+ char pshader = shader_is_pshader_version(shader_version);
char prefix = pshader ? 'P' : 'V';
/* Prototype the subroutines */
* out. The nvidia driver only does that if the parameter is inout instead of out, hence the
* inout.
*/
- if(This->baseShader.hex_version >= WINED3DVS_VERSION(3, 0)) {
+ if (shader_version >= WINED3DVS_VERSION(3, 0))
+ {
shader_addline(buffer, "void order_ps_input(in vec4[%u]);\n", MAX_REG_OUTPUT);
} else {
shader_addline(buffer, "void order_ps_input();\n");
ps_impl->numbumpenvmatconsts++;
}
- if(device->stateBlock->renderState[WINED3DRS_SRGBWRITEENABLE]) {
+ if(ps_args->srgb_correction) {
shader_addline(buffer, "const vec4 srgb_mul_low = vec4(%f, %f, %f, %f);\n",
srgb_mul_low, srgb_mul_low, srgb_mul_low, srgb_mul_low);
shader_addline(buffer, "const vec4 srgb_comparison = vec4(%f, %f, %f, %f);\n",
/* Declare input register varyings. Only pixel shader, vertex shaders have that declared in the
* helper function shader that is linked in at link time
*/
- if(pshader && This->baseShader.hex_version >= WINED3DPS_VERSION(3, 0)) {
- if(use_vs(device)) {
+ if (pshader && shader_version >= WINED3DPS_VERSION(3, 0))
+ {
+ if (use_vs(device->stateBlock))
+ {
shader_addline(buffer, "varying vec4 IN[%u];\n", GL_LIMITS(glsl_varyings) / 4);
} else {
/* TODO: Write a replacement shader for the fixed function vertex pipeline, so this isn't needed.
IWineD3DBaseShaderImpl* This = (IWineD3DBaseShaderImpl*) arg->shader;
IWineD3DDeviceImpl* deviceImpl = (IWineD3DDeviceImpl*) This->baseShader.device;
const WineD3D_GL_Info* gl_info = &deviceImpl->adapter->gl_info;
-
- char pshader = shader_is_pshader_version(This->baseShader.hex_version);
+ DWORD shader_version = This->baseShader.reg_maps.shader_version;
+ char pshader = shader_is_pshader_version(shader_version);
char tmpStr[150];
*is_color = FALSE;
case WINED3DSPR_INPUT:
if (pshader) {
/* Pixel shaders >= 3.0 */
- if (WINED3DSHADER_VERSION_MAJOR(This->baseShader.hex_version) >= 3) {
+ if (WINED3DSHADER_VERSION_MAJOR(shader_version) >= 3)
+ {
DWORD in_count = GL_LIMITS(glsl_varyings) / 4;
if (param & WINED3DSHADER_ADDRMODE_RELATIVE) {
strcpy(tmpStr, "gl_SecondaryColor");
}
} else {
- if (vshader_input_is_color((IWineD3DVertexShader*) This, reg))
- *is_color = TRUE;
+ if (((IWineD3DVertexShaderImpl *)This)->swizzle_map & (1 << reg)) *is_color = TRUE;
sprintf(tmpStr, "attrib%u", reg);
}
break;
/* Relative addressing on shaders 2.0+ have a relative address token,
* prior to that, it was hard-coded as "A0.x" because there's only 1 register */
- if (WINED3DSHADER_VERSION_MAJOR(This->baseShader.hex_version) >= 2) {
+ if (WINED3DSHADER_VERSION_MAJOR(shader_version) >= 2)
+ {
glsl_src_param_t rel_param;
shader_glsl_add_src_param(arg, addr_token, 0, WINED3DSP_WRITEMASK_0, &rel_param);
if(reg) {
break;
case WINED3DSPR_TEXCRDOUT:
/* Vertex shaders >= 3.0: WINED3DSPR_OUTPUT */
- if (WINED3DSHADER_VERSION_MAJOR(This->baseShader.hex_version) >= 3)
- sprintf(tmpStr, "OUT[%u]", reg);
- else
- sprintf(tmpStr, "gl_TexCoord[%u]", reg);
+ if (WINED3DSHADER_VERSION_MAJOR(shader_version) >= 3) sprintf(tmpStr, "OUT[%u]", reg);
+ else sprintf(tmpStr, "gl_TexCoord[%u]", reg);
break;
case WINED3DSPR_MISCTYPE:
if (reg == 0) {
/* Process the WINED3DSIO_MOV opcode using GLSL (dst = src) */
static void shader_glsl_mov(const SHADER_OPCODE_ARG *arg)
{
- IWineD3DBaseShaderImpl* shader = (IWineD3DBaseShaderImpl*) arg->shader;
SHADER_BUFFER* buffer = arg->buffer;
glsl_src_param_t src0_param;
DWORD write_mask;
/* In vs_1_1 WINED3DSIO_MOV can write to the address register. In later
* shader versions WINED3DSIO_MOVA is used for this. */
- if ((WINED3DSHADER_VERSION_MAJOR(shader->baseShader.hex_version) == 1 &&
- !shader_is_pshader_version(shader->baseShader.hex_version) &&
- shader_get_regtype(arg->dst) == WINED3DSPR_ADDR)) {
+ if ((WINED3DSHADER_VERSION_MAJOR(arg->reg_maps->shader_version) == 1
+ && !shader_is_pshader_version(arg->reg_maps->shader_version)
+ && shader_get_regtype(arg->dst) == WINED3DSPR_ADDR))
+ {
/* This is a simple floor() */
unsigned int mask_size = shader_glsl_get_write_mask_size(write_mask);
if (mask_size > 1) {
*/
static void shader_glsl_expp(const SHADER_OPCODE_ARG *arg)
{
- IWineD3DBaseShaderImpl *shader = (IWineD3DBaseShaderImpl *)arg->shader;
glsl_src_param_t src_param;
shader_glsl_add_src_param(arg, arg->src[0], arg->src_addr[0], WINED3DSP_WRITEMASK_0, &src_param);
- if (shader->baseShader.hex_version < WINED3DPS_VERSION(2,0)) {
+ if (arg->reg_maps->shader_version < WINED3DPS_VERSION(2,0))
+ {
char dst_mask[6];
shader_addline(arg->buffer, "tmp0.x = exp2(floor(%s));\n", src_param.param_str);
* the compare is done per component of src0. */
static void shader_glsl_cnd(const SHADER_OPCODE_ARG *arg)
{
- IWineD3DBaseShaderImpl* shader = (IWineD3DBaseShaderImpl*) arg->shader;
glsl_src_param_t src0_param;
glsl_src_param_t src1_param;
glsl_src_param_t src2_param;
DWORD write_mask, cmp_channel = 0;
unsigned int i, j;
- if (shader->baseShader.hex_version < WINED3DPS_VERSION(1, 4)) {
+ if (arg->reg_maps->shader_version < WINED3DPS_VERSION(1, 4))
+ {
write_mask = shader_glsl_append_dst(arg->buffer, arg);
shader_glsl_add_src_param(arg, arg->src[0], arg->src_addr[0], WINED3DSP_WRITEMASK_0, &src0_param);
shader_glsl_add_src_param(arg, arg->src[1], arg->src_addr[1], write_mask, &src1_param);
{
IWineD3DBaseShaderImpl *shader = (IWineD3DBaseShaderImpl *)arg->shader;
const SHADER_OPCODE *opcode_table = shader->baseShader.shader_ins;
- DWORD shader_version = shader->baseShader.hex_version;
+ DWORD shader_version = arg->reg_maps->shader_version;
int i;
int nComponents = 0;
SHADER_OPCODE_ARG tmpArg;
{
IWineD3DPixelShaderImpl* This = (IWineD3DPixelShaderImpl*) arg->shader;
IWineD3DDeviceImpl* deviceImpl = (IWineD3DDeviceImpl*) This->baseShader.device;
- DWORD hex_version = This->baseShader.hex_version;
+ DWORD shader_version = arg->reg_maps->shader_version;
char dst_swizzle[6];
glsl_sample_function_t sample_function;
DWORD sampler_type;
/* 1.0-1.4: Use destination register as sampler source.
* 2.0+: Use provided sampler source. */
- if (hex_version < WINED3DPS_VERSION(2,0)) {
- sampler_idx = arg->dst & WINED3DSP_REGNUM_MASK;
- } else {
- sampler_idx = arg->src[1] & WINED3DSP_REGNUM_MASK;
- }
+ if (shader_version < WINED3DPS_VERSION(2,0)) sampler_idx = arg->dst & WINED3DSP_REGNUM_MASK;
+ else sampler_idx = arg->src[1] & WINED3DSP_REGNUM_MASK;
sampler_type = arg->reg_maps->samplers[sampler_idx] & WINED3DSP_TEXTURETYPE_MASK;
- if (hex_version < WINED3DPS_VERSION(1,4)) {
+ if (shader_version < WINED3DPS_VERSION(1,4))
+ {
DWORD flags = deviceImpl->stateBlock->textureState[sampler_idx][WINED3DTSS_TEXTURETRANSFORMFLAGS];
/* Projected cube textures don't make a lot of sense, the resulting coordinates stay the same. */
} else {
projected = FALSE;
}
- } else if (hex_version < WINED3DPS_VERSION(2,0)) {
+ }
+ else if (shader_version < WINED3DPS_VERSION(2,0))
+ {
DWORD src_mod = arg->src[0] & WINED3DSP_SRCMOD_MASK;
if (src_mod == WINED3DSPSM_DZ) {
shader_glsl_get_sample_function(sampler_type, projected, texrect, &sample_function);
mask |= sample_function.coord_mask;