wined3d: Fixed function vertex attribute types are flexible.
diff --git a/dlls/wined3d/directx.c b/dlls/wined3d/directx.c
index 7badb4c..70a21a0 100644
--- a/dlls/wined3d/directx.c
+++ b/dlls/wined3d/directx.c
@@ -143,6 +143,12 @@
DWORD minMipLookup[WINED3DTEXF_ANISOTROPIC + 1][WINED3DTEXF_LINEAR + 1];
+/* drawStridedSlow attributes */
+glAttribFunc position_funcs[WINED3DDECLTYPE_UNUSED];
+glAttribFunc diffuse_funcs[WINED3DDECLTYPE_UNUSED];
+glAttribFunc specular_funcs[WINED3DDECLTYPE_UNUSED];
+glAttribFunc normal_funcs[WINED3DDECLTYPE_UNUSED];
+glTexAttribFunc texcoord_funcs[WINED3DDECLTYPE_UNUSED];
/**
* Note: GL seems to trap if GetDeviceCaps is called before any HWND's created
@@ -2879,8 +2885,139 @@
}
}
-#define PUSH1(att) attribs[nAttribs++] = (att);
+void invalid_func(void *data) {
+ ERR("Invalid vertex attribute function called\n");
+ DebugBreak();
+}
+
#define GLINFO_LOCATION (Adapters[0].gl_info)
+
+/* Helper functions for providing vertex data to opengl. The arrays are initialized based on
+ * the extension detection and are used in drawStridedSlow
+ */
+static void position_d3dcolor(void *data) {
+ DWORD pos = *((DWORD *) data);
+
+ FIXME("Add a test for fixed function position from d3dcolor type\n");
+ glVertex4s(D3DCOLOR_B_R(pos),
+ D3DCOLOR_B_G(pos),
+ D3DCOLOR_B_B(pos),
+ D3DCOLOR_B_A(pos));
+}
+static void position_float4(void *data) {
+ GLfloat *pos = (float *) data;
+ float w = 1.0 / pos[3];
+
+ glVertex4f(pos[0] * w, pos[1] * w, pos[2] * w, w);
+}
+
+static void diffuse_d3dcolor(void *data) {
+ DWORD diffuseColor = *((DWORD *) data);
+
+ glColor4ub(D3DCOLOR_B_R(diffuseColor),
+ D3DCOLOR_B_G(diffuseColor),
+ D3DCOLOR_B_B(diffuseColor),
+ D3DCOLOR_B_A(diffuseColor));
+}
+
+static void specular_d3dcolor(void *data) {
+ DWORD specularColor = *((DWORD *) data);
+
+ GL_EXTCALL(glSecondaryColor3ubEXT)(D3DCOLOR_B_R(specularColor),
+ D3DCOLOR_B_G(specularColor),
+ D3DCOLOR_B_B(specularColor));
+}
+static void warn_no_specular_func(void *data) {
+ WARN("GL_EXT_secondary_color not supported\n");
+}
+
+void fillGLAttribFuncs(WineD3D_GL_Info *gl_info) {
+ position_funcs[WINED3DDECLTYPE_FLOAT1] = (void *) invalid_func;
+ position_funcs[WINED3DDECLTYPE_FLOAT2] = (void *) invalid_func;
+ position_funcs[WINED3DDECLTYPE_FLOAT3] = (void *) glVertex3fv;
+ position_funcs[WINED3DDECLTYPE_FLOAT4] = (void *) position_float4;
+ position_funcs[WINED3DDECLTYPE_D3DCOLOR] = (void *) position_d3dcolor;
+ position_funcs[WINED3DDECLTYPE_UBYTE4] = (void *) invalid_func;
+ position_funcs[WINED3DDECLTYPE_SHORT2] = (void *) invalid_func;
+ position_funcs[WINED3DDECLTYPE_SHORT4] = (void *) glVertex2sv;
+ position_funcs[WINED3DDECLTYPE_UBYTE4N] = (void *) invalid_func;
+ position_funcs[WINED3DDECLTYPE_SHORT2N] = (void *) invalid_func;
+ position_funcs[WINED3DDECLTYPE_SHORT4N] = (void *) invalid_func;
+ position_funcs[WINED3DDECLTYPE_USHORT2N] = (void *) invalid_func;
+ position_funcs[WINED3DDECLTYPE_USHORT4N] = (void *) invalid_func;
+ position_funcs[WINED3DDECLTYPE_UDEC3] = (void *) invalid_func;
+ position_funcs[WINED3DDECLTYPE_DEC3N] = (void *) invalid_func;
+ position_funcs[WINED3DDECLTYPE_FLOAT16_2] = (void *) invalid_func;
+ position_funcs[WINED3DDECLTYPE_FLOAT16_4] = (void *) invalid_func;
+
+ diffuse_funcs[WINED3DDECLTYPE_FLOAT1] = (void *) invalid_func;
+ diffuse_funcs[WINED3DDECLTYPE_FLOAT2] = (void *) invalid_func;
+ diffuse_funcs[WINED3DDECLTYPE_FLOAT3] = (void *) glColor3fv;
+ diffuse_funcs[WINED3DDECLTYPE_FLOAT4] = (void *) glColor4fv;
+ diffuse_funcs[WINED3DDECLTYPE_D3DCOLOR] = (void *) diffuse_d3dcolor;
+ diffuse_funcs[WINED3DDECLTYPE_UBYTE4] = (void *) invalid_func;
+ diffuse_funcs[WINED3DDECLTYPE_SHORT2] = (void *) invalid_func;
+ diffuse_funcs[WINED3DDECLTYPE_SHORT4] = (void *) invalid_func;
+ diffuse_funcs[WINED3DDECLTYPE_UBYTE4N] = (void *) glColor4ubv;
+ diffuse_funcs[WINED3DDECLTYPE_SHORT2N] = (void *) invalid_func;
+ diffuse_funcs[WINED3DDECLTYPE_SHORT4N] = (void *) glColor4sv;
+ diffuse_funcs[WINED3DDECLTYPE_USHORT2N] = (void *) invalid_func;
+ diffuse_funcs[WINED3DDECLTYPE_USHORT4N] = (void *) glColor4usv;
+ diffuse_funcs[WINED3DDECLTYPE_UDEC3] = (void *) invalid_func;
+ diffuse_funcs[WINED3DDECLTYPE_DEC3N] = (void *) invalid_func;
+ diffuse_funcs[WINED3DDECLTYPE_FLOAT16_2] = (void *) invalid_func;
+ diffuse_funcs[WINED3DDECLTYPE_FLOAT16_4] = (void *) invalid_func;
+
+ /* No 4 component entry points here */
+ specular_funcs[WINED3DDECLTYPE_FLOAT1] = (void *) invalid_func;
+ specular_funcs[WINED3DDECLTYPE_FLOAT2] = (void *) invalid_func;
+ if(GL_SUPPORT(EXT_SECONDARY_COLOR)) {
+ specular_funcs[WINED3DDECLTYPE_FLOAT3] = (void *) GL_EXTCALL(glSecondaryColor3fvEXT);
+ } else {
+ specular_funcs[WINED3DDECLTYPE_FLOAT3] = (void *) warn_no_specular_func;
+ }
+ specular_funcs[WINED3DDECLTYPE_FLOAT4] = (void *) invalid_func;
+ if(GL_SUPPORT(EXT_SECONDARY_COLOR)) {
+ specular_funcs[WINED3DDECLTYPE_D3DCOLOR] = (void *) specular_d3dcolor;
+ } else {
+ specular_funcs[WINED3DDECLTYPE_FLOAT3] = (void *) warn_no_specular_func;
+ }
+ specular_funcs[WINED3DDECLTYPE_UBYTE4] = (void *) invalid_func;
+ specular_funcs[WINED3DDECLTYPE_SHORT2] = (void *) invalid_func;
+ specular_funcs[WINED3DDECLTYPE_SHORT4] = (void *) invalid_func;
+ specular_funcs[WINED3DDECLTYPE_UBYTE4N] = (void *) invalid_func;
+ specular_funcs[WINED3DDECLTYPE_SHORT2N] = (void *) invalid_func;
+ specular_funcs[WINED3DDECLTYPE_SHORT4N] = (void *) invalid_func;
+ specular_funcs[WINED3DDECLTYPE_USHORT2N] = (void *) invalid_func;
+ specular_funcs[WINED3DDECLTYPE_USHORT4N] = (void *) invalid_func;
+ specular_funcs[WINED3DDECLTYPE_UDEC3] = (void *) invalid_func;
+ specular_funcs[WINED3DDECLTYPE_DEC3N] = (void *) invalid_func;
+ specular_funcs[WINED3DDECLTYPE_FLOAT16_2] = (void *) invalid_func;
+ specular_funcs[WINED3DDECLTYPE_FLOAT16_4] = (void *) invalid_func;
+
+ /* Only 3 component entry points here. Test how others behave. Float4 normals are used
+ * by one of our tests, trying to pass it to the pixel shader, which fails on Windows.
+ */
+ normal_funcs[WINED3DDECLTYPE_FLOAT1] = (void *) invalid_func;
+ normal_funcs[WINED3DDECLTYPE_FLOAT2] = (void *) invalid_func;
+ normal_funcs[WINED3DDECLTYPE_FLOAT3] = (void *) glNormal3fv;
+ normal_funcs[WINED3DDECLTYPE_FLOAT4] = (void *) glNormal3fv; /* Just ignore the 4th value */
+ normal_funcs[WINED3DDECLTYPE_D3DCOLOR] = (void *) invalid_func;
+ normal_funcs[WINED3DDECLTYPE_UBYTE4] = (void *) invalid_func;
+ normal_funcs[WINED3DDECLTYPE_SHORT2] = (void *) invalid_func;
+ normal_funcs[WINED3DDECLTYPE_SHORT4] = (void *) invalid_func;
+ normal_funcs[WINED3DDECLTYPE_UBYTE4N] = (void *) invalid_func;
+ normal_funcs[WINED3DDECLTYPE_SHORT2N] = (void *) invalid_func;
+ normal_funcs[WINED3DDECLTYPE_SHORT4N] = (void *) invalid_func;
+ normal_funcs[WINED3DDECLTYPE_USHORT2N] = (void *) invalid_func;
+ normal_funcs[WINED3DDECLTYPE_USHORT4N] = (void *) invalid_func;
+ normal_funcs[WINED3DDECLTYPE_UDEC3] = (void *) invalid_func;
+ normal_funcs[WINED3DDECLTYPE_DEC3N] = (void *) invalid_func;
+ normal_funcs[WINED3DDECLTYPE_FLOAT16_2] = (void *) invalid_func;
+ normal_funcs[WINED3DDECLTYPE_FLOAT16_4] = (void *) invalid_func;
+}
+
+#define PUSH1(att) attribs[nAttribs++] = (att);
BOOL InitAdapters(void) {
static HMODULE mod_gl;
BOOL ret;
@@ -3022,6 +3159,7 @@
select_shader_mode(&Adapters[0].gl_info, WINED3DDEVTYPE_HAL, &ps_selected_mode, &vs_selected_mode);
select_shader_max_constants(ps_selected_mode, vs_selected_mode, &Adapters[0].gl_info);
+ fillGLAttribFuncs(&Adapters[0].gl_info);
}
numAdapters = 1;
diff --git a/dlls/wined3d/drawprim.c b/dlls/wined3d/drawprim.c
index 59a952f..aa7dd62 100644
--- a/dlls/wined3d/drawprim.c
+++ b/dlls/wined3d/drawprim.c
@@ -302,8 +302,6 @@
const WORD *pIdxBufS = NULL;
const DWORD *pIdxBufL = NULL;
LONG vx_index;
- float x = 0.0f, y = 0.0f, z = 0.0f; /* x,y,z coordinates */
- float rhw = 0.0f; /* rhw */
DWORD diffuseColor = 0xFFFFFFFF; /* Diffuse Color */
DWORD specularColor = 0; /* Specular Color */
IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
@@ -353,6 +351,32 @@
position = sd->u.s.position.lpData + streamOffset[sd->u.s.position.streamNo];
}
+ /* The texture coordinate types are not so easy to map into a common function signature - we're
+ * not using the vector functions here
+ */
+ if(FIXME_ON(d3d_draw)) {
+ for (textureNo = 0; textureNo < GL_LIMITS(textures); ++textureNo) {
+ DWORD type = sd->u.s.texCoords[textureNo].dwType;
+ if (sd->u.s.texCoords[textureNo].lpData &&
+ type != WINED3DDECLTYPE_FLOAT1 &&
+ type != WINED3DDECLTYPE_FLOAT2 &&
+ type != WINED3DDECLTYPE_FLOAT3 &&
+ type != WINED3DDECLTYPE_FLOAT4) {
+ FIXME("Implement fixed function texture coordinates from %s\n", debug_d3ddecltype(type));
+ }
+ }
+ if(specular && This->stateBlock->renderState[WINED3DRS_FOGENABLE] &&
+ (This->stateBlock->renderState[WINED3DRS_FOGVERTEXMODE] == WINED3DFOG_NONE || sd->u.s.position_transformed )&&
+ This->stateBlock->renderState[WINED3DRS_FOGTABLEMODE] == WINED3DFOG_NONE) {
+ if(GL_SUPPORT(EXT_FOG_COORD) && sd->u.s.specular.dwType != WINED3DDECLTYPE_D3DCOLOR) {
+ FIXME("Implement fog coordinates from %s\n", debug_d3ddecltype(sd->u.s.specular.dwType));
+ }
+ }
+ if(This->activeContext->num_untracked_materials && sd->u.s.diffuse.dwType != WINED3DDECLTYPE_D3DCOLOR) {
+ FIXME("Implement diffuse color tracking from %s\n", debug_d3ddecltype(sd->u.s.diffuse.dwType));
+ }
+ }
+
/* Start drawing in GL */
VTRACE(("glBegin(%x)\n", glPrimType));
glBegin(glPrimType);
@@ -486,22 +510,13 @@
/* Diffuse -------------------------------- */
if (diffuse) {
DWORD *ptrToCoords = (DWORD *)(diffuse + (SkipnStrides * sd->u.s.diffuse.dwStride));
- diffuseColor = ptrToCoords[0];
- VTRACE(("diffuseColor=%lx\n", diffuseColor));
- glColor4ub(D3DCOLOR_B_R(diffuseColor),
- D3DCOLOR_B_G(diffuseColor),
- D3DCOLOR_B_B(diffuseColor),
- D3DCOLOR_B_A(diffuseColor));
- VTRACE(("glColor4ub: r,g,b,a=%lu,%lu,%lu,%lu\n",
- D3DCOLOR_B_R(diffuseColor),
- D3DCOLOR_B_G(diffuseColor),
- D3DCOLOR_B_B(diffuseColor),
- D3DCOLOR_B_A(diffuseColor)));
-
+ diffuse_funcs[sd->u.s.diffuse.dwType]((void *) ptrToCoords);
if(This->activeContext->num_untracked_materials) {
unsigned char i;
float color[4];
+
+ diffuseColor = ptrToCoords[0];
color[0] = D3DCOLOR_B_R(diffuseColor) / 255.0;
color[1] = D3DCOLOR_B_G(diffuseColor) / 255.0;
color[2] = D3DCOLOR_B_B(diffuseColor) / 255.0;
@@ -516,14 +531,13 @@
/* Specular ------------------------------- */
if (specular) {
DWORD *ptrToCoords = (DWORD *)(specular + (SkipnStrides * sd->u.s.specular.dwStride));
- specularColor = ptrToCoords[0];
- VTRACE(("specularColor=%lx\n", specularColor));
/* special case where the fog density is stored in the specular alpha channel */
if(This->stateBlock->renderState[WINED3DRS_FOGENABLE] &&
(This->stateBlock->renderState[WINED3DRS_FOGVERTEXMODE] == WINED3DFOG_NONE || sd->u.s.position.dwType == WINED3DDECLTYPE_FLOAT4 )&&
This->stateBlock->renderState[WINED3DRS_FOGTABLEMODE] == WINED3DFOG_NONE) {
if(GL_SUPPORT(EXT_FOG_COORD)) {
+ specularColor = ptrToCoords[0];
GL_EXTCALL(glFogCoordfEXT(specularColor >> 24));
} else {
static BOOL warned = FALSE;
@@ -535,52 +549,19 @@
}
}
- VTRACE(("glSecondaryColor4ub: r,g,b=%lu,%lu,%lu\n",
- D3DCOLOR_B_R(specularColor),
- D3DCOLOR_B_G(specularColor),
- D3DCOLOR_B_B(specularColor)));
- if (GL_SUPPORT(EXT_SECONDARY_COLOR)) {
- GL_EXTCALL(glSecondaryColor3ubEXT)(
- D3DCOLOR_B_R(specularColor),
- D3DCOLOR_B_G(specularColor),
- D3DCOLOR_B_B(specularColor));
- } else {
- /* Do not worry if specular colour missing and disable request */
- VTRACE(("Specular color extensions not supplied\n"));
- }
+ specular_funcs[sd->u.s.specular.dwType]((void *) ptrToCoords);
}
/* Normal -------------------------------- */
if (normal != NULL) {
float *ptrToCoords = (float *)(normal + (SkipnStrides * sd->u.s.normal.dwStride));
-
- VTRACE(("glNormal:nx,ny,nz=%f,%f,%f\n", ptrToCoords[0], ptrToCoords[1], ptrToCoords[2]));
- glNormal3f(ptrToCoords[0], ptrToCoords[1], ptrToCoords[2]);
+ normal_funcs[sd->u.s.normal.dwType](ptrToCoords);
}
/* Position -------------------------------- */
if (position) {
float *ptrToCoords = (float *)(position + (SkipnStrides * sd->u.s.position.dwStride));
- x = ptrToCoords[0];
- y = ptrToCoords[1];
- z = ptrToCoords[2];
- rhw = 1.0;
- VTRACE(("x,y,z=%f,%f,%f\n", x,y,z));
-
- /* RHW follows, only if transformed, ie 4 floats were provided */
- if (sd->u.s.position_transformed) {
- rhw = ptrToCoords[3];
- VTRACE(("rhw=%f\n", rhw));
- }
-
- if (1.0f == rhw || ((rhw < eps) && (rhw > -eps))) {
- VTRACE(("Vertex: glVertex:x,y,z=%f,%f,%f\n", x,y,z));
- glVertex3f(x, y, z);
- } else {
- GLfloat w = 1.0 / rhw;
- VTRACE(("Vertex: glVertex:x,y,z=%f,%f,%f / rhw=%f\n", x,y,z,rhw));
- glVertex4f(x*w, y*w, z*w, w);
- }
+ position_funcs[sd->u.s.position.dwType](ptrToCoords);
}
/* For non indexed mode, step onto next parts */
diff --git a/dlls/wined3d/state.c b/dlls/wined3d/state.c
index d26b91d..39868cf 100644
--- a/dlls/wined3d/state.c
+++ b/dlls/wined3d/state.c
@@ -3232,7 +3232,9 @@
checkGLcall("glBindBufferARB");
curVBO = sd->u.s.diffuse.VBO;
}
- glColorPointer(4, GL_UNSIGNED_BYTE,
+
+ glColorPointer(WINED3D_ATR_SIZE(sd->u.s.diffuse.dwType),
+ WINED3D_ATR_GLTYPE(sd->u.s.diffuse.dwType),
sd->u.s.diffuse.dwStride,
sd->u.s.diffuse.lpData + stateblock->loadBaseVertexIndex * sd->u.s.diffuse.dwStride + offset[sd->u.s.diffuse.streamNo]);
checkGLcall("glColorPointer(4, GL_UNSIGNED_BYTE, ...)");
@@ -3257,7 +3259,8 @@
checkGLcall("glBindBufferARB");
curVBO = sd->u.s.specular.VBO;
}
- GL_EXTCALL(glSecondaryColorPointerEXT)(4, GL_UNSIGNED_BYTE,
+ GL_EXTCALL(glSecondaryColorPointerEXT)(WINED3D_ATR_SIZE(sd->u.s.specular.dwType),
+ WINED3D_ATR_GLTYPE(sd->u.s.specular.dwType),
sd->u.s.specular.dwStride,
sd->u.s.specular.lpData + stateblock->loadBaseVertexIndex * sd->u.s.specular.dwStride + offset[sd->u.s.specular.streamNo]);
vcheckGLcall("glSecondaryColorPointerEXT(4, GL_UNSIGNED_BYTE, ...)");
diff --git a/dlls/wined3d/wined3d_private.h b/dlls/wined3d/wined3d_private.h
index ad8047c..0934080 100644
--- a/dlls/wined3d/wined3d_private.h
+++ b/dlls/wined3d/wined3d_private.h
@@ -410,6 +410,13 @@
DWORD get_flexible_vertex_size(DWORD d3dvtVertexType);
+typedef void (*glAttribFunc)(void *data);
+typedef void (*glTexAttribFunc)(GLuint unit, void *data);
+extern glAttribFunc position_funcs[WINED3DDECLTYPE_UNUSED];
+extern glAttribFunc diffuse_funcs[WINED3DDECLTYPE_UNUSED];
+extern glAttribFunc specular_funcs[WINED3DDECLTYPE_UNUSED];
+extern glAttribFunc normal_funcs[WINED3DDECLTYPE_UNUSED];
+
#define eps 1e-8
#define GET_TEXCOORD_SIZE_FROM_FVF(d3dvtVertexType, tex_num) \