/*
* Copyright 2008 Luis Busquets
* Copyright 2009 Matteo Bruni
+ * Copyright 2010, 2013, 2016 Christian Costa
* Copyright 2011 Travis Athougies
*
* This library is free software; you can redistribute it and/or
*/
#include "d3dx9_36_private.h"
-#include "d3dcompiler.h"
+#include <stdio.h>
+
+#include "d3dcompiler.h"
/* This function is not declared in the SDK headers yet. */
HRESULT WINAPI D3DAssemble(const void *data, SIZE_T datasize, const char *filename,
WideCharToMultiByte(CP_ACP, 0, filename, -1, filename_a, len, NULL, NULL);
EnterCriticalSection(&from_file_mutex);
- hr = ID3DXInclude_Open(include, D3D_INCLUDE_LOCAL, filename_a, NULL, &buffer, &len);
+ hr = ID3DXInclude_Open(include, D3DXINC_LOCAL, filename_a, NULL, &buffer, &len);
if (FAILED(hr))
{
LeaveCriticalSection(&from_file_mutex);
}
}
+ /* Filter out D3DCompile warning messages that are not present with D3DCompileShader */
+ if (SUCCEEDED(hr) && error_msgs && *error_msgs)
+ {
+ char *messages = ID3DXBuffer_GetBufferPointer(*error_msgs);
+ DWORD size = ID3DXBuffer_GetBufferSize(*error_msgs);
+
+ /* Ensure messages are null terminated for safe processing */
+ if (size) messages[size - 1] = 0;
+
+ while (size > 1)
+ {
+ char *prev, *next;
+
+ /* Warning has the form "warning X3206: ... implicit truncation of vector type"
+ but we only search for "X3206:" in case d3dcompiler_43 has localization */
+ prev = next = strstr(messages, "X3206:");
+ if (!prev) break;
+
+ /* get pointer to beginning and end of current line */
+ while (prev > messages && *(prev - 1) != '\n') prev--;
+ while (next < messages + size - 1 && *next != '\n') next++;
+ if (next < messages + size - 1 && *next == '\n') next++;
+
+ memmove(prev, next, messages + size - next);
+ size -= (next - prev);
+ }
+
+ /* Only return a buffer if the resulting string is not empty as some apps depend on that */
+ if (size <= 1)
+ {
+ ID3DXBuffer_Release(*error_msgs);
+ *error_msgs = NULL;
+ }
+ }
+
return hr;
}
WideCharToMultiByte(CP_ACP, 0, filename, -1, filename_a, filename_len, NULL, NULL);
EnterCriticalSection(&from_file_mutex);
- hr = ID3DXInclude_Open(include, D3D_INCLUDE_LOCAL, filename_a, NULL, &buffer, &len);
+ hr = ID3DXInclude_Open(include, D3DXINC_LOCAL, filename_a, NULL, &buffer, &len);
if (FAILED(hr))
{
LeaveCriticalSection(&from_file_mutex);
WideCharToMultiByte(CP_ACP, 0, filename, -1, filename_a, len, NULL, NULL);
EnterCriticalSection(&from_file_mutex);
- hr = ID3DXInclude_Open(include, D3D_INCLUDE_LOCAL, filename_a, NULL, &buffer, &len);
+ hr = ID3DXInclude_Open(include, D3DXINC_LOCAL, filename_a, NULL, &buffer, &len);
if (FAILED(hr))
{
LeaveCriticalSection(&from_file_mutex);
}
-struct ctab_constant {
- D3DXCONSTANT_DESC desc;
- struct ctab_constant *constants;
-};
-
struct ID3DXConstantTableImpl {
ID3DXConstantTable ID3DXConstantTable_iface;
LONG ref;
return D3D_OK;
}
+const struct ctab_constant *d3dx_shader_get_ctab_constant(ID3DXConstantTable *iface, D3DXHANDLE constant)
+{
+ struct ID3DXConstantTableImpl *ctab = impl_from_ID3DXConstantTable(iface);
+
+ return get_valid_constant(ctab, constant);
+}
+
static HRESULT WINAPI ID3DXConstantTableImpl_GetConstantDesc(ID3DXConstantTable *iface, D3DXHANDLE constant,
D3DXCONSTANT_DESC *desc, UINT *count)
{
- struct ID3DXConstantTableImpl *This = impl_from_ID3DXConstantTable(iface);
- struct ctab_constant *c = get_valid_constant(This, constant);
+ struct ID3DXConstantTableImpl *ctab = impl_from_ID3DXConstantTable(iface);
+ struct ctab_constant *c = get_valid_constant(ctab, constant);
- TRACE("(%p)->(%p, %p, %p)\n", This, constant, desc, count);
+ TRACE("(%p)->(%p, %p, %p)\n", ctab, constant, desc, count);
if (!c)
{
offset = min(desc->Elements - 1, offset);
last = offset * desc->Rows * desc->Columns;
- if ((is_pointer || (!is_pointer && inclass == D3DXPC_MATRIX_ROWS)) && desc->RegisterSet != D3DXRS_BOOL)
+ if ((is_pointer || inclass == D3DXPC_MATRIX_ROWS) && desc->RegisterSet != D3DXRS_BOOL)
{
set(table, device, &constant->constants[0], NULL, intype, size, incol, inclass, 0, is_pointer);
}
* E.g.: struct {int i; int n} s;
* SetValue(device, "s", [1, 2], 8) => s = {1, 0};
*/
- else if ((is_pointer || (!is_pointer && inclass == D3DXPC_MATRIX_ROWS)) && desc->RegisterSet != D3DXRS_BOOL)
+ else if ((is_pointer || inclass == D3DXPC_MATRIX_ROWS) && desc->RegisterSet != D3DXRS_BOOL)
{
last = set(table, device, &constant->constants[0], indata, intype, size, incol, inclass,
index + last, is_pointer);
{
object->constants[i].desc.RegisterCount = constant_info[i].RegisterCount;
}
+ object->constants[i].constantinfo_reserved = constant_info[i].Reserved;
}
*constant_table = &object->ID3DXConstantTable_iface;
return D3DXGetShaderConstantTableEx(byte_code, 0, constant_table);
}
+HRESULT WINAPI D3DXCreateFragmentLinker(IDirect3DDevice9 *device, UINT size, ID3DXFragmentLinker **linker)
+{
+ FIXME("device %p, size %u, linker %p: stub.\n", device, size, linker);
+
+ if (linker)
+ *linker = NULL;
+
+
+ return E_NOTIMPL;
+}
+
+HRESULT WINAPI D3DXCreateFragmentLinkerEx(IDirect3DDevice9 *device, UINT size, DWORD flags, ID3DXFragmentLinker **linker)
+{
+ FIXME("device %p, size %u, flags %#x, linker %p: stub.\n", device, size, flags, linker);
+
+ if (linker)
+ *linker = NULL;
+
+ return E_NOTIMPL;
+}
+
HRESULT WINAPI D3DXGetShaderSamplers(const DWORD *byte_code, const char **samplers, UINT *count)
{
UINT i, sampler_count = 0;
return D3D_OK;
}
+
+
+static const char *decl_usage[] = { "position", "blendweight", "blendindices", "normal", "psize", "texcoord",
+ "tangent", "binormal", "tessfactor", "positiont", "color" };
+
+static const char *tex_type[] = { "", "1d", "2d", "cube", "volume" };
+
+static int add_modifier(char *buffer, DWORD param)
+{
+ char *buf = buffer;
+ DWORD dst_mod = param & D3DSP_DSTMOD_MASK;
+
+ if (dst_mod & D3DSPDM_SATURATE)
+ buf += sprintf(buf, "_sat");
+ if (dst_mod & D3DSPDM_PARTIALPRECISION)
+ buf += sprintf(buf, "_pp");
+ if (dst_mod & D3DSPDM_MSAMPCENTROID)
+ buf += sprintf(buf, "_centroid");
+
+ return buf - buffer;
+}
+
+static int add_register(char *buffer, DWORD param, BOOL dst, BOOL ps)
+{
+ char *buf = buffer;
+ DWORD reg_type = ((param & D3DSP_REGTYPE_MASK2) >> D3DSP_REGTYPE_SHIFT2)
+ | ((param & D3DSP_REGTYPE_MASK) >> D3DSP_REGTYPE_SHIFT);
+ DWORD reg_num = param & D3DSP_REGNUM_MASK;
+
+ if (reg_type == D3DSPR_INPUT)
+ buf += sprintf(buf, "v%d", reg_num);
+ else if (reg_type == D3DSPR_CONST)
+ buf += sprintf(buf, "c%d", reg_num);
+ else if (reg_type == D3DSPR_TEMP)
+ buf += sprintf(buf, "r%d", reg_num);
+ else if (reg_type == D3DSPR_ADDR)
+ buf += sprintf(buf, "%s%d", ps ? "t" : "a", reg_num);
+ else if (reg_type == D3DSPR_SAMPLER)
+ buf += sprintf(buf, "s%d", reg_num);
+ else if (reg_type == D3DSPR_RASTOUT)
+ buf += sprintf(buf, "oPos");
+ else if (reg_type == D3DSPR_COLOROUT)
+ buf += sprintf(buf, "oC%d", reg_num);
+ else if (reg_type == D3DSPR_TEXCRDOUT)
+ buf += sprintf(buf, "oT%d", reg_num);
+ else if (reg_type == D3DSPR_ATTROUT)
+ buf += sprintf(buf, "oD%d", reg_num);
+ else
+ buf += sprintf(buf, "? (%d)", reg_type);
+
+ if (dst)
+ {
+ if ((param & D3DSP_WRITEMASK_ALL) != D3DSP_WRITEMASK_ALL)
+ {
+ buf += sprintf(buf, ".%s%s%s%s", param & D3DSP_WRITEMASK_0 ? "x" : "",
+ param & D3DSP_WRITEMASK_1 ? "y" : "",
+ param & D3DSP_WRITEMASK_2 ? "z" : "",
+ param & D3DSP_WRITEMASK_3 ? "w" : "");
+ }
+ }
+ else
+ {
+ if ((param & D3DVS_SWIZZLE_MASK) != D3DVS_NOSWIZZLE)
+ {
+ if ( ((param & D3DSP_SWIZZLE_MASK) == (D3DVS_X_X | D3DVS_Y_X | D3DVS_Z_X | D3DVS_W_X)) ||
+ ((param & D3DSP_SWIZZLE_MASK) == (D3DVS_X_Y | D3DVS_Y_Y | D3DVS_Z_Y | D3DVS_W_Y)) ||
+ ((param & D3DSP_SWIZZLE_MASK) == (D3DVS_X_Z | D3DVS_Y_Z | D3DVS_Z_Z | D3DVS_W_Z)) ||
+ ((param & D3DSP_SWIZZLE_MASK) == (D3DVS_X_W | D3DVS_Y_W | D3DVS_Z_W | D3DVS_W_W)) )
+ buf += sprintf(buf, ".%c", 'w' + (((param >> D3DVS_SWIZZLE_SHIFT) + 1) & 0x3));
+ else
+ buf += sprintf(buf, ".%c%c%c%c", 'w' + (((param >> (D3DVS_SWIZZLE_SHIFT+0)) + 1) & 0x3),
+ 'w' + (((param >> (D3DVS_SWIZZLE_SHIFT+2)) + 1) & 0x3),
+ 'w' + (((param >> (D3DVS_SWIZZLE_SHIFT+4)) + 1) & 0x3),
+ 'w' + (((param >> (D3DVS_SWIZZLE_SHIFT+6)) + 1) & 0x3));
+ }
+ }
+
+ return buf - buffer;
+}
+
+struct instr_info
+{
+ DWORD opcode;
+ const char *name;
+ int length;
+ int (*function)(const struct instr_info *info, DWORD **ptr, char *buffer, BOOL ps);
+ WORD min_version;
+ WORD max_version;
+};
+
+static int instr_comment(const struct instr_info *info, DWORD **ptr, char *buffer, BOOL ps)
+{
+ *ptr += 1 + ((**ptr & D3DSI_COMMENTSIZE_MASK) >> D3DSI_COMMENTSIZE_SHIFT);
+ return 0;
+}
+
+static int instr_def(const struct instr_info *info, DWORD **ptr, char *buffer, BOOL ps)
+{
+ int len = sprintf(buffer, " def c%d, %g, %g, %g, %g\n", *(*ptr+1) & D3DSP_REGNUM_MASK,
+ (double)*(float*)(*ptr+2), (double)*(float*)(*ptr+3),
+ (double)*(float*)(*ptr+4), (double)*(float*)(*ptr+5));
+ *ptr += 6;
+ return len;
+}
+
+static int instr_dcl(const struct instr_info *info, DWORD **ptr, char *buffer, BOOL ps)
+{
+ DWORD param1 = *++*ptr;
+ DWORD param2 = *++*ptr;
+ DWORD usage = (param1 & D3DSP_DCL_USAGE_MASK) >> D3DSP_DCL_USAGE_SHIFT;
+ DWORD usage_index = (param1 & D3DSP_DCL_USAGEINDEX_MASK) >> D3DSP_DCL_USAGEINDEX_SHIFT;
+ char *buf = buffer;
+
+ buf += sprintf(buf, " dcl");
+ if (ps)
+ {
+ if (param1 & D3DSP_TEXTURETYPE_MASK)
+ buf += sprintf(buf, "_%s", (usage <= D3DSTT_VOLUME) ?
+ tex_type[(param1 & D3DSP_TEXTURETYPE_MASK) >> D3DSP_TEXTURETYPE_SHIFT] : "???");
+ }
+ else
+ {
+ buf += sprintf(buf, "_%s", (usage <= D3DDECLUSAGE_COLOR) ? decl_usage[usage] : "???");
+ if (usage_index)
+ buf += sprintf(buf, "%d", usage_index);
+ }
+
+ buf += add_modifier(buf, param2);
+ buf += sprintf(buf, " ");
+ buf += add_register(buf, param2, TRUE, TRUE);
+ buf += sprintf(buf, "\n");
+ (*ptr)++;
+ return buf - buffer;
+}
+
+static int instr_generic(const struct instr_info *info, DWORD **ptr, char *buffer, BOOL ps)
+{
+ char *buf = buffer;
+ int j;
+
+ buf += sprintf(buf, " %s", info->name);
+ (*ptr)++;
+
+ if (info->length)
+ {
+ buf += add_modifier(buf, **ptr);
+
+ for (j = 0; j < info->length; j++)
+ {
+ buf += sprintf(buf, "%s ", j ? "," : "");
+
+ if ((j != 0) && ((**ptr & D3DSP_SRCMOD_MASK) != D3DSPSM_NONE))
+ {
+ if ((**ptr & D3DSP_SRCMOD_MASK) == D3DSPSM_NEG)
+ buf += sprintf(buf, "-");
+ else
+ buf += sprintf(buf, "*");
+ }
+
+ buf += add_register(buf, **ptr, j == 0, ps);
+
+ if (*(*ptr)++ & D3DVS_ADDRESSMODE_MASK)
+ {
+ buf += sprintf(buf, "[");
+ buf += add_register(buf, **ptr, FALSE, FALSE);
+ buf += sprintf(buf, "]");
+ (*ptr)++;
+ }
+ }
+ }
+ buf += sprintf(buf, "\n");
+ return buf - buffer;
+}
+
+const struct instr_info instructions[] =
+{
+ { D3DSIO_NOP, "nop", 0, instr_generic, 0x0100, 0xFFFF },
+ { D3DSIO_MOV, "mov", 2, instr_generic, 0x0100, 0xFFFF },
+ { D3DSIO_ADD, "add", 3, instr_generic, 0x0100, 0xFFFF },
+ { D3DSIO_SUB, "sub", 3, instr_generic, 0x0100, 0xFFFF },
+ { D3DSIO_MAD, "mad", 4, instr_generic, 0x0100, 0xFFFF },
+ { D3DSIO_MUL, "mul", 3, instr_generic, 0x0100, 0xFFFF },
+ { D3DSIO_RCP, "rcp", 2, instr_generic, 0x0100, 0xFFFF }, /* >= 2.0 for PS */
+ { D3DSIO_RSQ, "rsq", 2, instr_generic, 0x0100, 0xFFFF }, /* >= 2.0 for PS */
+ { D3DSIO_DP3, "dp3", 3, instr_generic, 0x0100, 0xFFFF },
+ { D3DSIO_DP4, "dp4", 3, instr_generic, 0x0100, 0xFFFF }, /* >= 1.2 for PS */
+ { D3DSIO_MIN, "min", 3, instr_generic, 0x0100, 0xFFFF }, /* >= 2.0 for PS */
+ { D3DSIO_MAX, "max", 3, instr_generic, 0x0100, 0xFFFF }, /* >= 2.0 for PS */
+ { D3DSIO_SLT, "slt", 3, instr_generic, 0x0100, 0xFFFF },
+ { D3DSIO_SGE, "sge", 3, instr_generic, 0x0100, 0xFFFF }, /* VS only */
+ { D3DSIO_EXP, "exp", 2, instr_generic, 0x0100, 0xFFFF }, /* >= 2.0 for PS */
+ { D3DSIO_LOG, "log", 2, instr_generic, 0x0100, 0xFFFF }, /* >= 2.0 for PS */
+ { D3DSIO_LIT, "lit", 2, instr_generic, 0x0100, 0xFFFF }, /* VS only */
+ { D3DSIO_DST, "dst", 3, instr_generic, 0x0100, 0xFFFF }, /* VS only */
+ { D3DSIO_LRP, "lrp", 4, instr_generic, 0x0100, 0xFFFF }, /* >= 2.0 for VS */
+ { D3DSIO_FRC, "frc", 2, instr_generic, 0x0100, 0xFFFF }, /* >= 2.0 for PS */
+ { D3DSIO_M4x4, "m4x4", 3, instr_generic, 0x0100, 0xFFFF }, /* >= 2.0 for PS */
+ { D3DSIO_M4x3, "m4x3", 3, instr_generic, 0x0100, 0xFFFF }, /* >= 2.0 for PS */
+ { D3DSIO_M3x4, "m3x4", 3, instr_generic, 0x0100, 0xFFFF }, /* >= 2.0 for PS */
+ { D3DSIO_M3x3, "m3x3", 3, instr_generic, 0x0100, 0xFFFF }, /* >= 2.0 for PS */
+ { D3DSIO_M3x2, "m3x2", 3, instr_generic, 0x0100, 0xFFFF }, /* >= 2.0 for PS */
+ { D3DSIO_CALL, "call", 1, instr_generic, 0x0200, 0xFFFF }, /* >= 2.a for PS */
+ { D3DSIO_CALLNZ, "callnz", 2, instr_generic, 0x0200, 0xFFFF }, /* >= 2.a for PS */
+ { D3DSIO_LOOP, "loop", 2, instr_generic, 0x0200, 0xFFFF }, /* >= 3.0 for PS */
+ { D3DSIO_RET, "ret", 0, instr_generic, 0x0200, 0xFFFF }, /* >= 2.a for PS */
+ { D3DSIO_ENDLOOP, "endloop", 1, instr_generic, 0x0200, 0xFFFF }, /* >= 3.0 for PS */
+ { D3DSIO_LABEL, "label", 1, instr_generic, 0x0200, 0xFFFF }, /* >= 2.a for PS */
+ { D3DSIO_DCL, "dcl", 1, instr_dcl, 0x0100, 0xFFFF },
+ { D3DSIO_POW, "pow", 3, instr_generic, 0x0200, 0xFFFF },
+ { D3DSIO_CRS, "crs", 3, instr_generic, 0x0200, 0xFFFF },
+ { D3DSIO_SGN, "sgn", 4, instr_generic, 0x0200, 0xFFFF }, /* VS only */
+ { D3DSIO_ABS, "abs", 2, instr_generic, 0x0200, 0xFFFF },
+ { D3DSIO_NRM, "nrm", 2, instr_generic, 0x0200, 0xFFFF },
+ { D3DSIO_SINCOS, "sincos", 4, instr_generic, 0x0200, 0x02FF },
+ { D3DSIO_SINCOS, "sincos", 2, instr_generic, 0x0300, 0xFFFF },
+ { D3DSIO_REP, "rep", 1, instr_generic, 0x0200, 0xFFFF }, /* >= 2.a for PS */
+ { D3DSIO_ENDREP, "endrep", 0, instr_generic, 0x0200, 0xFFFF }, /* >= 2.a for PS */
+ { D3DSIO_IF, "if", 1, instr_generic, 0x0200, 0xFFFF }, /* >= 2.a for PS */
+ { D3DSIO_IFC, "if_comp", 2, instr_generic, 0x0200, 0xFFFF },
+ { D3DSIO_ELSE, "else", 0, instr_generic, 0x0200, 0xFFFF }, /* >= 2.a for PS */
+ { D3DSIO_ENDIF, "endif", 0, instr_generic, 0x0200, 0xFFFF }, /* >= 2.a for PS */
+ { D3DSIO_BREAK, "break", 0, instr_generic, 0x0201, 0xFFFF },
+ { D3DSIO_BREAKC, "break_comp", 2, instr_generic, 0x0201, 0xFFFF },
+ { D3DSIO_MOVA, "mova", 2, instr_generic, 0x0200, 0xFFFF }, /* VS only */
+ { D3DSIO_DEFB, "defb", 2, instr_generic, 0x0100, 0xFFFF },
+ { D3DSIO_DEFI, "defi", 2, instr_generic, 0x0100, 0xFFFF },
+ { D3DSIO_TEXCOORD, "texcoord", 1, instr_generic, 0x0100, 0x0103 }, /* PS only */
+ { D3DSIO_TEXCOORD, "texcrd", 2, instr_generic, 0x0104, 0x0104 }, /* PS only */
+ { D3DSIO_TEXKILL, "texkill", 1, instr_generic, 0x0100, 0xFFFF }, /* PS only */
+ { D3DSIO_TEX, "tex", 1, instr_generic, 0x0100, 0x0103 }, /* PS only */
+ { D3DSIO_TEX, "texld", 2, instr_generic, 0x0104, 0x0104 }, /* PS only */
+ { D3DSIO_TEX, "texld", 3, instr_generic, 0x0200, 0xFFFF }, /* PS only */
+ { D3DSIO_TEXBEM, "texbem", 2, instr_generic, 0x0100, 0x0103 }, /* PS only */
+ { D3DSIO_TEXBEML, "texbeml", 2, instr_generic, 0x0100, 0x0103 }, /* PS only */
+ { D3DSIO_TEXREG2AR, "texreg2ar", 2, instr_generic, 0x0100, 0x0103 }, /* PS only */
+ { D3DSIO_TEXREG2GB, "texreg2gb", 2, instr_generic, 0x0102, 0x0103 }, /* PS only */
+ { D3DSIO_TEXM3x2PAD, "texm3x2pad", 2, instr_generic, 0x0100, 0x0103 }, /* PS only */
+ { D3DSIO_TEXM3x2TEX, "texm3x2tex", 2, instr_generic, 0x0100, 0x0103 }, /* PS only */
+ { D3DSIO_TEXM3x3PAD, "texm3x3pad", 2, instr_generic, 0x0100, 0x0103 }, /* PS only */
+ { D3DSIO_TEXM3x3TEX, "texm3x3tex", 2, instr_generic, 0x0100, 0x0103 }, /* PS only */
+ { D3DSIO_TEXM3x3DIFF, "texm3x3diff", 2, instr_generic, 0x0100, 0xFFFF }, /* PS only - Not documented */
+ { D3DSIO_TEXM3x3SPEC, "texm3x3spec", 3, instr_generic, 0x0100, 0x0103 }, /* PS only */
+ { D3DSIO_TEXM3x3VSPEC, "texm3x3vspec", 2, instr_generic, 0x0100, 0x0103 }, /* PS only */
+ { D3DSIO_EXPP, "expp", 2, instr_generic, 0x0100, 0xFFFF }, /* VS only */
+ { D3DSIO_LOGP, "logp", 2, instr_generic, 0x0100, 0xFFFF }, /* VS only */
+ { D3DSIO_CND, "cnd", 4, instr_generic, 0x0100, 0x0104 }, /* PS only */
+ { D3DSIO_DEF, "def", 5, instr_def, 0x0100, 0xFFFF },
+ { D3DSIO_TEXREG2RGB, "texreg2rgb", 2, instr_generic, 0x0102, 0x0103 }, /* PS only */
+ { D3DSIO_TEXDP3TEX, "texdp3tex", 2, instr_generic, 0x0102, 0x0103 }, /* PS only */
+ { D3DSIO_TEXM3x2DEPTH, "texm3x2depth", 2, instr_generic, 0x0103, 0x0103 }, /* PS only */
+ { D3DSIO_TEXDP3, "texdp3", 2, instr_generic, 0x0102, 0x0103 }, /* PS only */
+ { D3DSIO_TEXM3x3, "texm3x3", 2, instr_generic, 0x0102, 0x0103 }, /* PS only */
+ { D3DSIO_TEXDEPTH, "texdepth", 1, instr_generic, 0x0104, 0x0104 }, /* PS only */
+ { D3DSIO_CMP, "cmp", 4, instr_generic, 0x0102, 0xFFFF }, /* PS only */
+ { D3DSIO_BEM, "bem", 3, instr_generic, 0x0104, 0x0104 }, /* PS only */
+ { D3DSIO_DP2ADD, "dp2add", 4, instr_generic, 0x0200, 0xFFFF }, /* PS only */
+ { D3DSIO_DSX, "dsx", 2, instr_generic, 0x0201, 0xFFFF }, /* PS only */
+ { D3DSIO_DSY, "dsy", 2, instr_generic, 0x0201, 0xFFFF }, /* PS only */
+ { D3DSIO_TEXLDD, "texldd", 5, instr_generic, 0x0201, 0xFFFF }, /* PS only - not existing for 2.b */
+ { D3DSIO_SETP, "setp_comp", 3, instr_generic, 0x0201, 0xFFFF },
+ { D3DSIO_TEXLDL, "texldl", 3, instr_generic, 0x0300, 0xFFFF },
+ { D3DSIO_BREAKP, "breakp", 1, instr_generic, 0x0201, 0xFFFF },
+ { D3DSIO_PHASE, "phase", 0, instr_generic, 0x0104, 0x0104 }, /* PS only */
+ { D3DSIO_COMMENT, "", 0, instr_comment, 0x0100, 0xFFFF }
+};
+
+HRESULT WINAPI D3DXDisassembleShader(const DWORD *shader, BOOL colorcode, const char *comments, ID3DXBuffer **disassembly)
+{
+ DWORD *ptr = (DWORD *)shader;
+ char *buffer, *buf;
+ UINT capacity = 4096;
+ BOOL ps;
+ WORD version;
+ HRESULT hr;
+
+ TRACE("%p %d %s %p\n", shader, colorcode, debugstr_a(comments), disassembly);
+
+ if (!shader || !disassembly)
+ return D3DERR_INVALIDCALL;
+
+ buf = buffer = HeapAlloc(GetProcessHeap(), 0, capacity);
+ if (!buffer)
+ return E_OUTOFMEMORY;
+
+ ps = (*ptr >> 16) & 1;
+ version = *ptr & 0xFFFF;
+ buf += sprintf(buf, " %s_%d_%d\n", ps ? "ps" : "vs", D3DSHADER_VERSION_MAJOR(*ptr), D3DSHADER_VERSION_MINOR(*ptr));
+ ptr++;
+
+ while (*ptr != D3DSIO_END)
+ {
+ DWORD index;
+
+ if ((buf - buffer + 128) > capacity)
+ {
+ UINT count = buf - buffer;
+ char *new_buffer = HeapReAlloc(GetProcessHeap(), 0, buffer, capacity * 2);
+ if (!new_buffer)
+ {
+ HeapFree(GetProcessHeap(), 0, buffer);
+ return E_OUTOFMEMORY;
+ }
+ capacity *= 2;
+ buffer = new_buffer;
+ buf = buffer + count;
+ }
+
+ for (index = 0; index < sizeof(instructions)/sizeof(instructions[0]); index++)
+ if (((*ptr & D3DSI_OPCODE_MASK) == instructions[index].opcode) &&
+ (version >= instructions[index].min_version) && (version <= instructions[index].max_version))
+ break;
+
+ if (index != sizeof(instructions)/sizeof(instructions[0]))
+ {
+ buf += instructions[index].function(&(instructions[index]), &ptr, buf, ps);
+ }
+ else
+ {
+ buf += sprintf(buf, " ??? (Unknown opcode %x)\n", *ptr);
+ while (*++ptr & (1u << 31));
+ }
+ }
+
+ hr = D3DXCreateBuffer(buf - buffer + 1 , disassembly);
+ if (SUCCEEDED(hr))
+ strcpy(ID3DXBuffer_GetBufferPointer(*disassembly), buffer);
+ HeapFree(GetProcessHeap(), 0, buffer);
+
+ return hr;
+}
+
+struct d3dx9_texture_shader
+{
+ ID3DXTextureShader ID3DXTextureShader_iface;
+ LONG ref;
+};
+
+static inline struct d3dx9_texture_shader *impl_from_ID3DXTextureShader(ID3DXTextureShader *iface)
+{
+ return CONTAINING_RECORD(iface, struct d3dx9_texture_shader, ID3DXTextureShader_iface);
+}
+
+static HRESULT WINAPI d3dx9_texture_shader_QueryInterface(ID3DXTextureShader *iface, REFIID riid, void **out)
+{
+ TRACE("iface %p, riid %s, out %p.\n", iface, debugstr_guid(riid), out);
+
+ if (IsEqualGUID(riid, &IID_IUnknown) ||
+ IsEqualGUID(riid, &IID_ID3DXTextureShader))
+ {
+ iface->lpVtbl->AddRef(iface);
+ *out = iface;
+ return D3D_OK;
+ }
+
+ WARN("Interface %s not found.\n", debugstr_guid(riid));
+ *out = NULL;
+ return E_NOINTERFACE;
+}
+
+static ULONG WINAPI d3dx9_texture_shader_AddRef(ID3DXTextureShader *iface)
+{
+ struct d3dx9_texture_shader *texture_shader = impl_from_ID3DXTextureShader(iface);
+ ULONG refcount = InterlockedIncrement(&texture_shader->ref);
+
+ TRACE("%p increasing refcount to %u.\n", texture_shader, refcount);
+
+ return refcount;
+}
+
+static ULONG WINAPI d3dx9_texture_shader_Release(ID3DXTextureShader *iface)
+{
+ struct d3dx9_texture_shader *texture_shader = impl_from_ID3DXTextureShader(iface);
+ ULONG refcount = InterlockedDecrement(&texture_shader->ref);
+
+ TRACE("%p decreasing refcount to %u.\n", texture_shader, refcount);
+
+ if (!refcount)
+ {
+ HeapFree(GetProcessHeap(), 0, texture_shader);
+ }
+
+ return refcount;
+}
+
+static HRESULT WINAPI d3dx9_texture_shader_GetFunction(ID3DXTextureShader *iface, struct ID3DXBuffer **function)
+{
+ FIXME("iface %p, function %p stub.\n", iface, function);
+
+ return E_NOTIMPL;
+}
+
+static HRESULT WINAPI d3dx9_texture_shader_GetConstantBuffer(ID3DXTextureShader *iface, struct ID3DXBuffer **constant_buffer)
+{
+ FIXME("iface %p, constant_buffer %p stub.\n", iface, constant_buffer);
+
+ return E_NOTIMPL;
+}
+
+static HRESULT WINAPI d3dx9_texture_shader_GetDesc(ID3DXTextureShader *iface, D3DXCONSTANTTABLE_DESC *desc)
+{
+ FIXME("iface %p, desc %p stub.\n", iface, desc);
+
+ return E_NOTIMPL;
+}
+
+static HRESULT WINAPI d3dx9_texture_shader_GetConstantDesc(ID3DXTextureShader *iface, D3DXHANDLE constant, D3DXCONSTANT_DESC *constant_desc, UINT *count)
+{
+ FIXME("iface %p, constant %p, constant_desc %p, count %p stub.\n", iface, constant, constant_desc, count);
+
+ return E_NOTIMPL;
+}
+
+static D3DXHANDLE WINAPI d3dx9_texture_shader_GetConstant(ID3DXTextureShader *iface, D3DXHANDLE constant, UINT index)
+{
+ FIXME("iface %p, constant %p, index %u stub.\n", iface, constant, index);
+
+ return NULL;
+}
+
+static D3DXHANDLE WINAPI d3dx9_texture_shader_GetConstantByName(ID3DXTextureShader *iface, D3DXHANDLE constant, const char *name)
+{
+ FIXME("iface %p, constant %p, name %s stub.\n", iface, constant, debugstr_a(name));
+
+ return NULL;
+}
+
+static D3DXHANDLE WINAPI d3dx9_texture_shader_GetConstantElement(ID3DXTextureShader *iface, D3DXHANDLE constant, UINT index)
+{
+ FIXME("iface %p, constant %p, index %u stub.\n", iface, constant, index);
+
+ return NULL;
+}
+
+static HRESULT WINAPI d3dx9_texture_shader_SetDefaults(ID3DXTextureShader *iface)
+{
+ FIXME("iface %p stub.\n", iface);
+
+ return E_NOTIMPL;
+}
+
+static HRESULT WINAPI d3dx9_texture_shader_SetValue(ID3DXTextureShader *iface, D3DXHANDLE constant, const void *data, UINT bytes)
+{
+ FIXME("iface %p, constant %p, data %p, bytes %u stub.\n", iface, constant, data, bytes);
+
+ return E_NOTIMPL;
+}
+
+static HRESULT WINAPI d3dx9_texture_shader_SetBool(ID3DXTextureShader *iface, D3DXHANDLE constant, BOOL b)
+{
+ FIXME("iface %p, constant %p, b %u stub.\n", iface, constant, b);
+
+ return E_NOTIMPL;
+}
+
+static HRESULT WINAPI d3dx9_texture_shader_SetBoolArray(ID3DXTextureShader *iface, D3DXHANDLE constant, const BOOL *b, UINT count)
+{
+ FIXME("iface %p, constant %p, b %p, count %u stub.\n", iface, constant, b, count);
+
+ return E_NOTIMPL;
+}
+
+static HRESULT WINAPI d3dx9_texture_shader_SetInt(ID3DXTextureShader *iface, D3DXHANDLE constant, INT n)
+{
+ FIXME("iface %p, constant %p, n %d stub.\n", iface, constant, n);
+
+ return E_NOTIMPL;
+}
+
+static HRESULT WINAPI d3dx9_texture_shader_SetIntArray(ID3DXTextureShader *iface, D3DXHANDLE constant, const INT *n, UINT count)
+{
+ FIXME("iface %p, constant %p, n %p, count %u stub.\n", iface, constant, n, count);
+
+ return E_NOTIMPL;
+}
+
+static HRESULT WINAPI d3dx9_texture_shader_SetFloat(ID3DXTextureShader *iface, D3DXHANDLE constant, FLOAT f)
+{
+ FIXME("iface %p, constant %p, f %f stub.\n", iface, constant, f);
+
+ return E_NOTIMPL;
+}
+
+static HRESULT WINAPI d3dx9_texture_shader_SetFloatArray(ID3DXTextureShader *iface, D3DXHANDLE constant, const FLOAT *f, UINT count)
+{
+ FIXME("iface %p, constant %p, f %p, count %u stub.\n", iface, constant, f, count);
+
+ return E_NOTIMPL;
+}
+
+static HRESULT WINAPI d3dx9_texture_shader_SetVector(ID3DXTextureShader *iface, D3DXHANDLE constant, const D3DXVECTOR4 *vector)
+{
+ FIXME("iface %p, constant %p, vector %p stub.\n", iface, constant, vector);
+
+ return E_NOTIMPL;
+}
+
+static HRESULT WINAPI d3dx9_texture_shader_SetVectorArray(ID3DXTextureShader *iface, D3DXHANDLE constant, const D3DXVECTOR4 *vector, UINT count)
+{
+ FIXME("iface %p, constant %p, vector %p, count %u stub.\n", iface, constant, vector, count);
+
+ return E_NOTIMPL;
+}
+
+static HRESULT WINAPI d3dx9_texture_shader_SetMatrix(ID3DXTextureShader *iface, D3DXHANDLE constant, const D3DXMATRIX *matrix)
+{
+ FIXME("iface %p, constant %p, matrix %p stub.\n", iface, constant, matrix);
+
+ return E_NOTIMPL;
+}
+
+static HRESULT WINAPI d3dx9_texture_shader_SetMatrixArray(ID3DXTextureShader *iface, D3DXHANDLE constant, const D3DXMATRIX *matrix, UINT count)
+{
+ FIXME("iface %p, constant %p, matrix %p, count %u stub.\n", iface, constant, matrix, count);
+
+ return E_NOTIMPL;
+}
+
+static HRESULT WINAPI d3dx9_texture_shader_SetMatrixPointerArray(ID3DXTextureShader *iface, D3DXHANDLE constant, const D3DXMATRIX **matrix, UINT count)
+{
+ FIXME("iface %p, constant %p, matrix %p, count %u stub.\n", iface, constant, matrix, count);
+
+ return E_NOTIMPL;
+}
+
+static HRESULT WINAPI d3dx9_texture_shader_SetMatrixTranspose(ID3DXTextureShader *iface, D3DXHANDLE constant, const D3DXMATRIX *matrix)
+{
+ FIXME("iface %p, constant %p, matrix %p stub.\n", iface, constant, matrix);
+
+ return E_NOTIMPL;
+}
+
+static HRESULT WINAPI d3dx9_texture_shader_SetMatrixTransposeArray(ID3DXTextureShader *iface, D3DXHANDLE constant, const D3DXMATRIX *matrix, UINT count)
+{
+ FIXME("iface %p, constant %p, matrix %p, count %u stub.\n", iface, constant, matrix, count);
+
+ return E_NOTIMPL;
+}
+
+static HRESULT WINAPI d3dx9_texture_shader_SetMatrixTransposePointerArray(ID3DXTextureShader *iface, D3DXHANDLE constant, const D3DXMATRIX **matrix, UINT count)
+{
+ FIXME("iface %p, constant %p, matrix %p, count %u stub.\n", iface, constant, matrix, count);
+
+ return E_NOTIMPL;
+}
+
+static const struct ID3DXTextureShaderVtbl d3dx9_texture_shader_vtbl =
+{
+ /*** IUnknown methods ***/
+ d3dx9_texture_shader_QueryInterface,
+ d3dx9_texture_shader_AddRef,
+ d3dx9_texture_shader_Release,
+ /*** ID3DXTextureShader methods ***/
+ d3dx9_texture_shader_GetFunction,
+ d3dx9_texture_shader_GetConstantBuffer,
+ d3dx9_texture_shader_GetDesc,
+ d3dx9_texture_shader_GetConstantDesc,
+ d3dx9_texture_shader_GetConstant,
+ d3dx9_texture_shader_GetConstantByName,
+ d3dx9_texture_shader_GetConstantElement,
+ d3dx9_texture_shader_SetDefaults,
+ d3dx9_texture_shader_SetValue,
+ d3dx9_texture_shader_SetBool,
+ d3dx9_texture_shader_SetBoolArray,
+ d3dx9_texture_shader_SetInt,
+ d3dx9_texture_shader_SetIntArray,
+ d3dx9_texture_shader_SetFloat,
+ d3dx9_texture_shader_SetFloatArray,
+ d3dx9_texture_shader_SetVector,
+ d3dx9_texture_shader_SetVectorArray,
+ d3dx9_texture_shader_SetMatrix,
+ d3dx9_texture_shader_SetMatrixArray,
+ d3dx9_texture_shader_SetMatrixPointerArray,
+ d3dx9_texture_shader_SetMatrixTranspose,
+ d3dx9_texture_shader_SetMatrixTransposeArray,
+ d3dx9_texture_shader_SetMatrixTransposePointerArray
+};
+
+HRESULT WINAPI D3DXCreateTextureShader(const DWORD *function, ID3DXTextureShader **texture_shader)
+{
+ struct d3dx9_texture_shader *object;
+
+ TRACE("function %p, texture_shader %p.\n", function, texture_shader);
+
+ if (!function || !texture_shader)
+ return D3DERR_INVALIDCALL;
+
+ object = HeapAlloc(GetProcessHeap(), 0, sizeof(*object));
+ if (!object)
+ return E_OUTOFMEMORY;
+
+ object->ID3DXTextureShader_iface.lpVtbl = &d3dx9_texture_shader_vtbl;
+ object->ref = 1;
+
+ *texture_shader = &object->ID3DXTextureShader_iface;
+
+ return D3D_OK;
+}
+
+static const DWORD* skip_instruction(const DWORD *byte_code, UINT shader_model)
+{
+ TRACE("Shader model %u\n", shader_model);
+
+ /* Handle all special instructions whose arguments may contain D3DSIO_DCL */
+ if ((*byte_code & D3DSI_OPCODE_MASK) == D3DSIO_COMMENT)
+ {
+ byte_code += 1 + ((*byte_code & D3DSI_COMMENTSIZE_MASK) >> D3DSI_COMMENTSIZE_SHIFT);
+ }
+ else if (shader_model >= 2)
+ {
+ byte_code += 1 + ((*byte_code & D3DSI_INSTLENGTH_MASK) >> D3DSI_INSTLENGTH_SHIFT);
+ }
+ else if ((*byte_code & D3DSI_OPCODE_MASK) == D3DSIO_DEF)
+ {
+ byte_code += 1 + 5;
+ }
+ else
+ {
+ /* Handle remaining safe instructions */
+ while (*++byte_code & (1u << 31));
+ }
+
+ return byte_code;
+}
+
+static UINT get_shader_semantics(const DWORD *byte_code, D3DXSEMANTIC *semantics, DWORD type)
+{
+ const DWORD *ptr = byte_code;
+ UINT shader_model = (*ptr >> 8) & 0xff;
+ UINT i = 0;
+
+ TRACE("Shader version: %#x\n", *ptr);
+ ptr++;
+
+ while (*ptr != D3DSIO_END)
+ {
+ if (*ptr & (1u << 31))
+ {
+ FIXME("Opcode expected but got %#x\n", *ptr);
+ return 0;
+ }
+ else if ((*ptr & D3DSI_OPCODE_MASK) == D3DSIO_DCL)
+ {
+ DWORD param1 = *++ptr;
+ DWORD param2 = *++ptr;
+ DWORD usage = (param1 & D3DSP_DCL_USAGE_MASK) >> D3DSP_DCL_USAGE_SHIFT;
+ DWORD usage_index = (param1 & D3DSP_DCL_USAGEINDEX_MASK) >> D3DSP_DCL_USAGEINDEX_SHIFT;
+ DWORD reg_type = ((param2 & D3DSP_REGTYPE_MASK2) >> D3DSP_REGTYPE_SHIFT2)
+ | ((param2 & D3DSP_REGTYPE_MASK) >> D3DSP_REGTYPE_SHIFT);
+
+ TRACE("D3DSIO_DCL param1: %#x, param2: %#x, usage: %u, usage_index: %u, reg_type: %u\n",
+ param1, param2, usage, usage_index, reg_type);
+
+ if (reg_type == type)
+ {
+ if (semantics)
+ {
+ semantics[i].Usage = usage;
+ semantics[i].UsageIndex = usage_index;
+ }
+ i++;
+ }
+
+ ptr++;
+ }
+ else
+ {
+ ptr = skip_instruction(ptr, shader_model);
+ }
+ }
+
+ return i;
+}
+
+HRESULT WINAPI D3DXGetShaderInputSemantics(const DWORD *byte_code, D3DXSEMANTIC *semantics, UINT *count)
+{
+ UINT nb_semantics;
+
+ TRACE("byte_code %p, semantics %p, count %p\n", byte_code, semantics, count);
+
+ if (!byte_code)
+ return D3DERR_INVALIDCALL;
+
+ nb_semantics = get_shader_semantics(byte_code, semantics, D3DSPR_INPUT);
+
+ if (count)
+ *count = nb_semantics;
+
+ return D3D_OK;
+}
+
+
+HRESULT WINAPI D3DXGetShaderOutputSemantics(const DWORD *byte_code, D3DXSEMANTIC *semantics, UINT *count)
+{
+ UINT nb_semantics;
+
+ TRACE("byte_code %p, semantics %p, count %p\n", byte_code, semantics, count);
+
+ if (!byte_code)
+ return D3DERR_INVALIDCALL;
+
+ nb_semantics = get_shader_semantics(byte_code, semantics, D3DSPR_OUTPUT);
+
+ if (count)
+ *count = nb_semantics;
+
+ return D3D_OK;
+}