1 /* Direct3D Common functions
2 * Copyright (c) 1998 Lionel ULMER
4 * This file contains all common miscellaneous code that spans
7 * This library is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU Lesser General Public
9 * License as published by the Free Software Foundation; either
10 * version 2.1 of the License, or (at your option) any later version.
12 * This library is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * Lesser General Public License for more details.
17 * You should have received a copy of the GNU Lesser General Public
18 * License along with this library; if not, write to the Free Software
19 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
24 #define NONAMELESSUNION
25 #define NONAMELESSSTRUCT
32 #include "wine/debug.h"
34 #include "d3d_private.h"
36 WINE_DEFAULT_DEBUG_CHANNEL(ddraw
);
38 const char *_get_renderstate(D3DRENDERSTATETYPE type
) {
39 static const char * const states
[] = {
41 "D3DRENDERSTATE_TEXTUREHANDLE",
42 "D3DRENDERSTATE_ANTIALIAS",
43 "D3DRENDERSTATE_TEXTUREADDRESS",
44 "D3DRENDERSTATE_TEXTUREPERSPECTIVE",
45 "D3DRENDERSTATE_WRAPU",
46 "D3DRENDERSTATE_WRAPV",
47 "D3DRENDERSTATE_ZENABLE",
48 "D3DRENDERSTATE_FILLMODE",
49 "D3DRENDERSTATE_SHADEMODE",
50 "D3DRENDERSTATE_LINEPATTERN",
51 "D3DRENDERSTATE_MONOENABLE",
52 "D3DRENDERSTATE_ROP2",
53 "D3DRENDERSTATE_PLANEMASK",
54 "D3DRENDERSTATE_ZWRITEENABLE",
55 "D3DRENDERSTATE_ALPHATESTENABLE",
56 "D3DRENDERSTATE_LASTPIXEL",
57 "D3DRENDERSTATE_TEXTUREMAG",
58 "D3DRENDERSTATE_TEXTUREMIN",
59 "D3DRENDERSTATE_SRCBLEND",
60 "D3DRENDERSTATE_DESTBLEND",
61 "D3DRENDERSTATE_TEXTUREMAPBLEND",
62 "D3DRENDERSTATE_CULLMODE",
63 "D3DRENDERSTATE_ZFUNC",
64 "D3DRENDERSTATE_ALPHAREF",
65 "D3DRENDERSTATE_ALPHAFUNC",
66 "D3DRENDERSTATE_DITHERENABLE",
67 "D3DRENDERSTATE_ALPHABLENDENABLE",
68 "D3DRENDERSTATE_FOGENABLE",
69 "D3DRENDERSTATE_SPECULARENABLE",
70 "D3DRENDERSTATE_ZVISIBLE",
71 "D3DRENDERSTATE_SUBPIXEL",
72 "D3DRENDERSTATE_SUBPIXELX",
73 "D3DRENDERSTATE_STIPPLEDALPHA",
74 "D3DRENDERSTATE_FOGCOLOR",
75 "D3DRENDERSTATE_FOGTABLEMODE",
76 "D3DRENDERSTATE_FOGTABLESTART",
77 "D3DRENDERSTATE_FOGTABLEEND",
78 "D3DRENDERSTATE_FOGTABLEDENSITY",
79 "D3DRENDERSTATE_STIPPLEENABLE",
80 "D3DRENDERSTATE_EDGEANTIALIAS",
81 "D3DRENDERSTATE_COLORKEYENABLE",
83 "D3DRENDERSTATE_BORDERCOLOR",
84 "D3DRENDERSTATE_TEXTUREADDRESSU",
85 "D3DRENDERSTATE_TEXTUREADDRESSV",
86 "D3DRENDERSTATE_MIPMAPLODBIAS",
87 "D3DRENDERSTATE_ZBIAS",
88 "D3DRENDERSTATE_RANGEFOGENABLE",
89 "D3DRENDERSTATE_ANISOTROPY",
90 "D3DRENDERSTATE_FLUSHBATCH",
91 "D3DRENDERSTATE_TRANSLUCENTSORTINDEPENDENT",
92 "D3DRENDERSTATE_STENCILENABLE",
93 "D3DRENDERSTATE_STENCILFAIL",
94 "D3DRENDERSTATE_STENCILZFAIL",
95 "D3DRENDERSTATE_STENCILPASS",
96 "D3DRENDERSTATE_STENCILFUNC",
97 "D3DRENDERSTATE_STENCILREF",
98 "D3DRENDERSTATE_STENCILMASK",
99 "D3DRENDERSTATE_STENCILWRITEMASK",
100 "D3DRENDERSTATE_TEXTUREFACTOR",
104 "D3DRENDERSTATE_STIPPLEPATTERN00",
105 "D3DRENDERSTATE_STIPPLEPATTERN01",
106 "D3DRENDERSTATE_STIPPLEPATTERN02",
107 "D3DRENDERSTATE_STIPPLEPATTERN03",
108 "D3DRENDERSTATE_STIPPLEPATTERN04",
109 "D3DRENDERSTATE_STIPPLEPATTERN05",
110 "D3DRENDERSTATE_STIPPLEPATTERN06",
111 "D3DRENDERSTATE_STIPPLEPATTERN07",
112 "D3DRENDERSTATE_STIPPLEPATTERN08",
113 "D3DRENDERSTATE_STIPPLEPATTERN09",
114 "D3DRENDERSTATE_STIPPLEPATTERN10",
115 "D3DRENDERSTATE_STIPPLEPATTERN11",
116 "D3DRENDERSTATE_STIPPLEPATTERN12",
117 "D3DRENDERSTATE_STIPPLEPATTERN13",
118 "D3DRENDERSTATE_STIPPLEPATTERN14",
119 "D3DRENDERSTATE_STIPPLEPATTERN15",
120 "D3DRENDERSTATE_STIPPLEPATTERN16",
121 "D3DRENDERSTATE_STIPPLEPATTERN17",
122 "D3DRENDERSTATE_STIPPLEPATTERN18",
123 "D3DRENDERSTATE_STIPPLEPATTERN19",
124 "D3DRENDERSTATE_STIPPLEPATTERN20",
125 "D3DRENDERSTATE_STIPPLEPATTERN21",
126 "D3DRENDERSTATE_STIPPLEPATTERN22",
127 "D3DRENDERSTATE_STIPPLEPATTERN23",
128 "D3DRENDERSTATE_STIPPLEPATTERN24",
129 "D3DRENDERSTATE_STIPPLEPATTERN25",
130 "D3DRENDERSTATE_STIPPLEPATTERN26",
131 "D3DRENDERSTATE_STIPPLEPATTERN27",
132 "D3DRENDERSTATE_STIPPLEPATTERN28",
133 "D3DRENDERSTATE_STIPPLEPATTERN29",
134 "D3DRENDERSTATE_STIPPLEPATTERN30",
135 "D3DRENDERSTATE_STIPPLEPATTERN31"
137 static const char * const states_2
[] = {
138 "D3DRENDERSTATE_WRAP0",
139 "D3DRENDERSTATE_WRAP1",
140 "D3DRENDERSTATE_WRAP2",
141 "D3DRENDERSTATE_WRAP3",
142 "D3DRENDERSTATE_WRAP4",
143 "D3DRENDERSTATE_WRAP5",
144 "D3DRENDERSTATE_WRAP6",
145 "D3DRENDERSTATE_WRAP7",
146 "D3DRENDERSTATE_CLIPPING",
147 "D3DRENDERSTATE_LIGHTING",
148 "D3DRENDERSTATE_EXTENTS",
149 "D3DRENDERSTATE_AMBIENT",
150 "D3DRENDERSTATE_FOGVERTEXMODE",
151 "D3DRENDERSTATE_COLORVERTEX",
152 "D3DRENDERSTATE_LOCALVIEWER",
153 "D3DRENDERSTATE_NORMALIZENORMALS",
154 "D3DRENDERSTATE_COLORKEYBLENDENABLE",
155 "D3DRENDERSTATE_DIFFUSEMATERIALSOURCE",
156 "D3DRENDERSTATE_SPECULARMATERIALSOURCE",
157 "D3DRENDERSTATE_AMBIENTMATERIALSOURCE",
158 "D3DRENDERSTATE_EMISSIVEMATERIALSOURCE",
161 "D3DRENDERSTATE_VERTEXBLEND",
162 "D3DRENDERSTATE_CLIPPLANEENABLE",
164 if (type
>= D3DRENDERSTATE_WRAP0
) {
165 type
-= D3DRENDERSTATE_WRAP0
;
166 if (type
>= (sizeof(states_2
) / sizeof(states_2
[0]))) return "ERR";
167 return states_2
[type
];
169 if (type
>= (sizeof(states
) / sizeof(states
[0]))) return "ERR";
174 dump_D3DCOLORVALUE(D3DCOLORVALUE
*lpCol
)
176 DPRINTF("%f %f %f %f", lpCol
->u1
.r
, lpCol
->u2
.g
, lpCol
->u3
.b
, lpCol
->u4
.a
);
180 dump_D3DVECTOR(D3DVECTOR
*lpVec
)
182 DPRINTF("%f %f %f", lpVec
->u1
.x
, lpVec
->u2
.y
, lpVec
->u3
.z
);
186 dump_D3DMATERIAL7(LPD3DMATERIAL7 lpMat
)
188 DPRINTF(" - diffuse : "); dump_D3DCOLORVALUE(&(lpMat
->u
.diffuse
)); DPRINTF("\n");
189 DPRINTF(" - ambient : "); dump_D3DCOLORVALUE(&(lpMat
->u1
.ambient
)); DPRINTF("\n");
190 DPRINTF(" - specular : "); dump_D3DCOLORVALUE(&(lpMat
->u2
.specular
)); DPRINTF("\n");
191 DPRINTF(" - emissive : "); dump_D3DCOLORVALUE(&(lpMat
->u3
.emissive
)); DPRINTF("\n");
192 DPRINTF(" - power : %f\n", lpMat
->u4
.power
);
196 dump_D3DLIGHT7(LPD3DLIGHT7 lpLight
)
198 DPRINTF(" - light type : %s\n", (lpLight
->dltType
== D3DLIGHT_POINT
? "D3DLIGHT_POINT" :
199 (lpLight
->dltType
== D3DLIGHT_SPOT
? "D3DLIGHT_SPOT" :
200 (lpLight
->dltType
== D3DLIGHT_DIRECTIONAL
? "D3DLIGHT_DIRECTIONAL" :
202 DPRINTF(" - diffuse : "); dump_D3DCOLORVALUE(&(lpLight
->dcvDiffuse
)); DPRINTF("\n");
203 DPRINTF(" - specular : "); dump_D3DCOLORVALUE(&(lpLight
->dcvSpecular
)); DPRINTF("\n");
204 DPRINTF(" - ambient : "); dump_D3DCOLORVALUE(&(lpLight
->dcvAmbient
)); DPRINTF("\n");
205 DPRINTF(" - position : "); dump_D3DVECTOR(&(lpLight
->dvPosition
)); DPRINTF("\n");
206 DPRINTF(" - direction : "); dump_D3DVECTOR(&(lpLight
->dvDirection
)); DPRINTF("\n");
207 DPRINTF(" - dvRange : %f\n", lpLight
->dvRange
);
208 DPRINTF(" - dvFalloff : %f\n", lpLight
->dvFalloff
);
209 DPRINTF(" - dvAttenuation : %f %f %f\n", lpLight
->dvAttenuation0
, lpLight
->dvAttenuation1
, lpLight
->dvAttenuation2
);
210 DPRINTF(" - dvTheta : %f\n", lpLight
->dvTheta
);
211 DPRINTF(" - dvPhi : %f\n", lpLight
->dvPhi
);
215 dump_DPFLAGS(DWORD dwFlags
)
217 static const flag_info flags
[] =
220 FE(D3DDP_OUTOFORDER
),
222 FE(D3DDP_DONOTUPDATEEXTENTS
),
226 DDRAW_dump_flags(dwFlags
, flags
, sizeof(flags
)/sizeof(flags
[0]));
230 dump_D3DMATRIX(D3DMATRIX
*mat
)
232 DPRINTF(" %f %f %f %f\n", mat
->_11
, mat
->_12
, mat
->_13
, mat
->_14
);
233 DPRINTF(" %f %f %f %f\n", mat
->_21
, mat
->_22
, mat
->_23
, mat
->_24
);
234 DPRINTF(" %f %f %f %f\n", mat
->_31
, mat
->_32
, mat
->_33
, mat
->_34
);
235 DPRINTF(" %f %f %f %f\n", mat
->_41
, mat
->_42
, mat
->_43
, mat
->_44
);
238 DWORD
get_flexible_vertex_size(DWORD d3dvtVertexType
)
243 if (d3dvtVertexType
& D3DFVF_NORMAL
) size
+= 3 * sizeof(D3DVALUE
);
244 if (d3dvtVertexType
& D3DFVF_DIFFUSE
) size
+= sizeof(DWORD
);
245 if (d3dvtVertexType
& D3DFVF_SPECULAR
) size
+= sizeof(DWORD
);
246 if (d3dvtVertexType
& D3DFVF_RESERVED1
) size
+= sizeof(DWORD
);
247 switch (d3dvtVertexType
& D3DFVF_POSITION_MASK
) {
248 case D3DFVF_XYZ
: size
+= 3 * sizeof(D3DVALUE
); break;
249 case D3DFVF_XYZRHW
: size
+= 4 * sizeof(D3DVALUE
); break;
250 default: TRACE(" matrix weighting not handled yet...\n");
252 for (i
= 0; i
< GET_TEXCOUNT_FROM_FVF(d3dvtVertexType
); i
++) {
253 size
+= GET_TEXCOORD_SIZE_FROM_FVF(d3dvtVertexType
, i
) * sizeof(D3DVALUE
);
259 void dump_flexible_vertex(DWORD d3dvtVertexType
)
261 static const flag_info flags
[] = {
263 FE(D3DFVF_RESERVED1
),
269 if (d3dvtVertexType
& D3DFVF_RESERVED0
) DPRINTF("D3DFVF_RESERVED0 ");
270 switch (d3dvtVertexType
& D3DFVF_POSITION_MASK
) {
271 #define GEN_CASE(a) case a: DPRINTF(#a " "); break
272 GEN_CASE(D3DFVF_XYZ
);
273 GEN_CASE(D3DFVF_XYZRHW
);
274 GEN_CASE(D3DFVF_XYZB1
);
275 GEN_CASE(D3DFVF_XYZB2
);
276 GEN_CASE(D3DFVF_XYZB3
);
277 GEN_CASE(D3DFVF_XYZB4
);
278 GEN_CASE(D3DFVF_XYZB5
);
280 DDRAW_dump_flags_(d3dvtVertexType
, flags
, sizeof(flags
)/sizeof(flags
[0]), FALSE
);
281 switch (d3dvtVertexType
& D3DFVF_TEXCOUNT_MASK
) {
282 GEN_CASE(D3DFVF_TEX0
);
283 GEN_CASE(D3DFVF_TEX1
);
284 GEN_CASE(D3DFVF_TEX2
);
285 GEN_CASE(D3DFVF_TEX3
);
286 GEN_CASE(D3DFVF_TEX4
);
287 GEN_CASE(D3DFVF_TEX5
);
288 GEN_CASE(D3DFVF_TEX6
);
289 GEN_CASE(D3DFVF_TEX7
);
290 GEN_CASE(D3DFVF_TEX8
);
293 for (i
= 0; i
< GET_TEXCOUNT_FROM_FVF(d3dvtVertexType
); i
++) {
294 DPRINTF(" T%d-s%ld", i
+ 1, GET_TEXCOORD_SIZE_FROM_FVF(d3dvtVertexType
, i
));
300 convert_FVF_to_strided_data(DWORD d3dvtVertexType
, LPVOID lpvVertices
, D3DDRAWPRIMITIVESTRIDEDDATA
*strided
, DWORD dwStartVertex
)
302 int current_offset
= 0;
303 unsigned int tex_index
;
304 int size
= get_flexible_vertex_size(d3dvtVertexType
);
306 lpvVertices
= ((BYTE
*) lpvVertices
) + (size
* dwStartVertex
);
308 if ((d3dvtVertexType
& D3DFVF_POSITION_MASK
) == D3DFVF_XYZ
) {
309 strided
->position
.lpvData
= lpvVertices
;
310 current_offset
+= 3 * sizeof(D3DVALUE
);
312 strided
->position
.lpvData
= lpvVertices
;
313 current_offset
+= 4 * sizeof(D3DVALUE
);
315 if (d3dvtVertexType
& D3DFVF_RESERVED1
) {
316 current_offset
+= sizeof(DWORD
);
318 if (d3dvtVertexType
& D3DFVF_NORMAL
) {
319 strided
->normal
.lpvData
= ((char *) lpvVertices
) + current_offset
;
320 current_offset
+= 3 * sizeof(D3DVALUE
);
322 if (d3dvtVertexType
& D3DFVF_DIFFUSE
) {
323 strided
->diffuse
.lpvData
= ((char *) lpvVertices
) + current_offset
;
324 current_offset
+= sizeof(DWORD
);
326 if (d3dvtVertexType
& D3DFVF_SPECULAR
) {
327 strided
->specular
.lpvData
= ((char *) lpvVertices
) + current_offset
;
328 current_offset
+= sizeof(DWORD
);
330 for (tex_index
= 0; tex_index
< GET_TEXCOUNT_FROM_FVF(d3dvtVertexType
); tex_index
++) {
331 strided
->textureCoords
[tex_index
].lpvData
= ((char *) lpvVertices
) + current_offset
;
332 current_offset
+= GET_TEXCOORD_SIZE_FROM_FVF(d3dvtVertexType
, tex_index
) * sizeof(D3DVALUE
);
334 strided
->position
.dwStride
= current_offset
;
335 strided
->normal
.dwStride
= current_offset
;
336 strided
->diffuse
.dwStride
= current_offset
;
337 strided
->specular
.dwStride
= current_offset
;
338 for (tex_index
= 0; tex_index
< ((d3dvtVertexType
& D3DFVF_TEXCOUNT_MASK
) >> D3DFVF_TEXCOUNT_SHIFT
); tex_index
++)
339 strided
->textureCoords
[tex_index
].dwStride
= current_offset
;
343 dump_D3DVOP(DWORD dwVertexOp
)
345 static const flag_info flags
[] =
352 DDRAW_dump_flags(dwVertexOp
, flags
, sizeof(flags
)/sizeof(flags
[0]));
356 dump_D3DPV(DWORD dwFlags
)
358 if (dwFlags
== D3DPV_DONOTCOPYDATA
) DPRINTF("D3DPV_DONOTCOPYDATA\n");
359 else if (dwFlags
!= 0) DPRINTF("Unknown !!!\n");
363 void multiply_matrix(LPD3DMATRIX dest
, LPD3DMATRIX src1
, LPD3DMATRIX src2
)
367 /* Now do the multiplication 'by hand'.
368 I know that all this could be optimised, but this will be done later :-) */
369 temp
._11
= (src1
->_11
* src2
->_11
) + (src1
->_21
* src2
->_12
) + (src1
->_31
* src2
->_13
) + (src1
->_41
* src2
->_14
);
370 temp
._21
= (src1
->_11
* src2
->_21
) + (src1
->_21
* src2
->_22
) + (src1
->_31
* src2
->_23
) + (src1
->_41
* src2
->_24
);
371 temp
._31
= (src1
->_11
* src2
->_31
) + (src1
->_21
* src2
->_32
) + (src1
->_31
* src2
->_33
) + (src1
->_41
* src2
->_34
);
372 temp
._41
= (src1
->_11
* src2
->_41
) + (src1
->_21
* src2
->_42
) + (src1
->_31
* src2
->_43
) + (src1
->_41
* src2
->_44
);
374 temp
._12
= (src1
->_12
* src2
->_11
) + (src1
->_22
* src2
->_12
) + (src1
->_32
* src2
->_13
) + (src1
->_42
* src2
->_14
);
375 temp
._22
= (src1
->_12
* src2
->_21
) + (src1
->_22
* src2
->_22
) + (src1
->_32
* src2
->_23
) + (src1
->_42
* src2
->_24
);
376 temp
._32
= (src1
->_12
* src2
->_31
) + (src1
->_22
* src2
->_32
) + (src1
->_32
* src2
->_33
) + (src1
->_42
* src2
->_34
);
377 temp
._42
= (src1
->_12
* src2
->_41
) + (src1
->_22
* src2
->_42
) + (src1
->_32
* src2
->_43
) + (src1
->_42
* src2
->_44
);
379 temp
._13
= (src1
->_13
* src2
->_11
) + (src1
->_23
* src2
->_12
) + (src1
->_33
* src2
->_13
) + (src1
->_43
* src2
->_14
);
380 temp
._23
= (src1
->_13
* src2
->_21
) + (src1
->_23
* src2
->_22
) + (src1
->_33
* src2
->_23
) + (src1
->_43
* src2
->_24
);
381 temp
._33
= (src1
->_13
* src2
->_31
) + (src1
->_23
* src2
->_32
) + (src1
->_33
* src2
->_33
) + (src1
->_43
* src2
->_34
);
382 temp
._43
= (src1
->_13
* src2
->_41
) + (src1
->_23
* src2
->_42
) + (src1
->_33
* src2
->_43
) + (src1
->_43
* src2
->_44
);
384 temp
._14
= (src1
->_14
* src2
->_11
) + (src1
->_24
* src2
->_12
) + (src1
->_34
* src2
->_13
) + (src1
->_44
* src2
->_14
);
385 temp
._24
= (src1
->_14
* src2
->_21
) + (src1
->_24
* src2
->_22
) + (src1
->_34
* src2
->_23
) + (src1
->_44
* src2
->_24
);
386 temp
._34
= (src1
->_14
* src2
->_31
) + (src1
->_24
* src2
->_32
) + (src1
->_34
* src2
->_33
) + (src1
->_44
* src2
->_34
);
387 temp
._44
= (src1
->_14
* src2
->_41
) + (src1
->_24
* src2
->_42
) + (src1
->_34
* src2
->_43
) + (src1
->_44
* src2
->_44
);
389 /* And copy the new matrix in the good storage.. */
390 memcpy(dest
, &temp
, 16 * sizeof(D3DVALUE
));