- beginning of Material and Light support for D3D7
[wine/multimedia.git] / dlls / ddraw / d3ddevice / mesa.c
blobb62236cda979581a4f958c9ef0160e607baeb4f3
1 /* Direct3D Device
2 * Copyright (c) 1998 Lionel ULMER
4 * This file contains the MESA implementation of all the D3D devices that
5 * Wine supports.
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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
22 #include "config.h"
24 #include <string.h>
26 #include "windef.h"
27 #include "winerror.h"
28 #include "objbase.h"
29 #include "ddraw.h"
30 #include "d3d.h"
31 #include "wine/debug.h"
33 #include "mesa_private.h"
34 #include "main.h"
36 #include "x11drv.h"
38 WINE_DEFAULT_DEBUG_CHANNEL(ddraw);
40 /* They are non-static as they are used by Direct3D in the creation function */
41 const GUID IID_D3DDEVICE_OpenGL = {
42 0x31416d44,
43 0x86ae,
44 0x11d2,
45 { 0x82,0x2d,0xa8,0xd5,0x31,0x87,0xca,0xfa }
48 #ifndef HAVE_GLEXT_PROTOTYPES
49 /* This is for non-OpenGL ABI compliant glext.h headers :-) */
50 typedef void (* PFNGLCOLORTABLEEXTPROC) (GLenum target, GLenum internalFormat,
51 GLsizei width, GLenum format, GLenum type,
52 const GLvoid *table);
53 #endif
55 static const float id_mat[16] = {
56 1.0, 0.0, 0.0, 0.0,
57 0.0, 1.0, 0.0, 0.0,
58 0.0, 0.0, 1.0, 0.0,
59 0.0, 0.0, 0.0, 1.0
62 static void draw_primitive_strided_7(IDirect3DDeviceImpl *This,
63 D3DPRIMITIVETYPE d3dptPrimitiveType,
64 DWORD d3dvtVertexType,
65 LPD3DDRAWPRIMITIVESTRIDEDDATA lpD3DDrawPrimStrideData,
66 DWORD dwStartVertex,
67 DWORD dwVertexCount,
68 LPWORD dwIndices,
69 DWORD dwIndexCount,
70 DWORD dwFlags) ;
72 /* retrieve the X display to use on a given DC */
73 inline static Display *get_display( HDC hdc )
75 Display *display;
76 enum x11drv_escape_codes escape = X11DRV_GET_DISPLAY;
78 if (!ExtEscape( hdc, X11DRV_ESCAPE, sizeof(escape), (LPCSTR)&escape,
79 sizeof(display), (LPSTR)&display )) display = NULL;
81 return display;
85 /* retrieve the X drawable to use on a given DC */
86 inline static Drawable get_drawable( HDC hdc )
88 Drawable drawable;
89 enum x11drv_escape_codes escape = X11DRV_GET_DRAWABLE;
91 if (!ExtEscape( hdc, X11DRV_ESCAPE, sizeof(escape), (LPCSTR)&escape,
92 sizeof(drawable), (LPSTR)&drawable )) drawable = 0;
94 return drawable;
98 static BOOL opengl_flip( LPVOID display, LPVOID drawable)
100 TRACE("(%p, %ld)\n",(Display*)display,(Drawable)drawable);
101 ENTER_GL();
102 glXSwapBuffers((Display*)display,(Drawable)drawable);
103 LEAVE_GL();
104 return TRUE;
108 /*******************************************************************************
109 * OpenGL static functions
111 static void set_context(IDirect3DDeviceImpl* This)
113 IDirect3DDeviceGLImpl* glThis = (IDirect3DDeviceGLImpl*) This;
115 ENTER_GL();
116 TRACE("glxMakeCurrent %p, %ld, %p\n",glThis->display,glThis->drawable, glThis->gl_context);
117 if (glXMakeCurrent(glThis->display, glThis->drawable, glThis->gl_context) == False) {
118 ERR("Error in setting current context (context %p drawable %ld)!\n",
119 glThis->gl_context, glThis->drawable);
121 LEAVE_GL();
124 static void fill_opengl_primcaps(D3DPRIMCAPS *pc)
126 pc->dwSize = sizeof(*pc);
127 pc->dwMiscCaps = D3DPMISCCAPS_CONFORMANT | D3DPMISCCAPS_CULLCCW | D3DPMISCCAPS_CULLCW |
128 D3DPMISCCAPS_LINEPATTERNREP | D3DPMISCCAPS_MASKZ;
129 pc->dwRasterCaps = D3DPRASTERCAPS_DITHER | D3DPRASTERCAPS_FOGRANGE | D3DPRASTERCAPS_FOGTABLE |
130 D3DPRASTERCAPS_FOGVERTEX | D3DPRASTERCAPS_STIPPLE | D3DPRASTERCAPS_ZBIAS | D3DPRASTERCAPS_ZTEST | D3DPRASTERCAPS_SUBPIXEL;
131 pc->dwZCmpCaps = D3DPCMPCAPS_ALWAYS | D3DPCMPCAPS_EQUAL | D3DPCMPCAPS_GREATER | D3DPCMPCAPS_GREATEREQUAL |
132 D3DPCMPCAPS_LESS | D3DPCMPCAPS_LESSEQUAL | D3DPCMPCAPS_NEVER | D3DPCMPCAPS_NOTEQUAL;
133 pc->dwSrcBlendCaps = D3DPBLENDCAPS_ZERO | D3DPBLENDCAPS_ONE | D3DPBLENDCAPS_DESTCOLOR | D3DPBLENDCAPS_INVDESTCOLOR |
134 D3DPBLENDCAPS_SRCALPHA | D3DPBLENDCAPS_INVSRCALPHA | D3DPBLENDCAPS_DESTALPHA | D3DPBLENDCAPS_INVDESTALPHA | D3DPBLENDCAPS_SRCALPHASAT |
135 D3DPBLENDCAPS_BOTHSRCALPHA | D3DPBLENDCAPS_BOTHINVSRCALPHA;
136 pc->dwDestBlendCaps = D3DPBLENDCAPS_ZERO | D3DPBLENDCAPS_ONE | D3DPBLENDCAPS_SRCCOLOR | D3DPBLENDCAPS_INVSRCCOLOR |
137 D3DPBLENDCAPS_SRCALPHA | D3DPBLENDCAPS_INVSRCALPHA | D3DPBLENDCAPS_DESTALPHA | D3DPBLENDCAPS_INVDESTALPHA | D3DPBLENDCAPS_SRCALPHASAT |
138 D3DPBLENDCAPS_BOTHSRCALPHA | D3DPBLENDCAPS_BOTHINVSRCALPHA;
139 pc->dwAlphaCmpCaps = D3DPCMPCAPS_ALWAYS | D3DPCMPCAPS_EQUAL | D3DPCMPCAPS_GREATER | D3DPCMPCAPS_GREATEREQUAL |
140 D3DPCMPCAPS_LESS | D3DPCMPCAPS_LESSEQUAL | D3DPCMPCAPS_NEVER | D3DPCMPCAPS_NOTEQUAL;
141 pc->dwShadeCaps = D3DPSHADECAPS_ALPHAFLATBLEND | D3DPSHADECAPS_ALPHAGOURAUDBLEND | D3DPSHADECAPS_COLORFLATRGB | D3DPSHADECAPS_COLORGOURAUDRGB |
142 D3DPSHADECAPS_FOGFLAT | D3DPSHADECAPS_FOGGOURAUD | D3DPSHADECAPS_SPECULARFLATRGB | D3DPSHADECAPS_SPECULARGOURAUDRGB;
143 pc->dwTextureCaps = D3DPTEXTURECAPS_ALPHA | D3DPTEXTURECAPS_ALPHAPALETTE | D3DPTEXTURECAPS_BORDER | D3DPTEXTURECAPS_PERSPECTIVE |
144 D3DPTEXTURECAPS_POW2 | D3DPTEXTURECAPS_TRANSPARENCY;
145 pc->dwTextureFilterCaps = D3DPTFILTERCAPS_LINEAR | D3DPTFILTERCAPS_LINEARMIPLINEAR | D3DPTFILTERCAPS_LINEARMIPNEAREST |
146 D3DPTFILTERCAPS_MIPLINEAR | D3DPTFILTERCAPS_MIPNEAREST | D3DPTFILTERCAPS_NEAREST;
147 pc->dwTextureBlendCaps = D3DPTBLENDCAPS_ADD | D3DPTBLENDCAPS_COPY | D3DPTBLENDCAPS_DECAL | D3DPTBLENDCAPS_DECALALPHA | D3DPTBLENDCAPS_DECALMASK |
148 D3DPTBLENDCAPS_MODULATE | D3DPTBLENDCAPS_MODULATEALPHA | D3DPTBLENDCAPS_MODULATEMASK;
149 pc->dwTextureAddressCaps = D3DPTADDRESSCAPS_BORDER | D3DPTADDRESSCAPS_CLAMP | D3DPTADDRESSCAPS_WRAP | D3DPTADDRESSCAPS_INDEPENDENTUV;
150 pc->dwStippleWidth = 32;
151 pc->dwStippleHeight = 32;
154 static void fill_opengl_caps(D3DDEVICEDESC *d1)
156 /* GLint maxlight; */
158 d1->dwSize = sizeof(*d1);
159 d1->dwFlags = D3DDD_DEVCAPS | D3DDD_BCLIPPING | D3DDD_COLORMODEL | D3DDD_DEVICERENDERBITDEPTH | D3DDD_DEVICEZBUFFERBITDEPTH
160 | D3DDD_LIGHTINGCAPS | D3DDD_LINECAPS | D3DDD_MAXBUFFERSIZE | D3DDD_MAXVERTEXCOUNT | D3DDD_TRANSFORMCAPS | D3DDD_TRICAPS;
161 d1->dcmColorModel = D3DCOLOR_RGB;
162 d1->dwDevCaps = D3DDEVCAPS_CANRENDERAFTERFLIP | D3DDEVCAPS_DRAWPRIMTLVERTEX | D3DDEVCAPS_EXECUTESYSTEMMEMORY |
163 D3DDEVCAPS_EXECUTEVIDEOMEMORY | D3DDEVCAPS_FLOATTLVERTEX | D3DDEVCAPS_TEXTURENONLOCALVIDMEM | D3DDEVCAPS_TEXTURESYSTEMMEMORY |
164 D3DDEVCAPS_TEXTUREVIDEOMEMORY | D3DDEVCAPS_TLVERTEXSYSTEMMEMORY | D3DDEVCAPS_TLVERTEXVIDEOMEMORY |
165 /* D3D 7 capabilities */
166 D3DDEVCAPS_DRAWPRIMITIVES2 | D3DDEVCAPS_HWTRANSFORMANDLIGHT | D3DDEVCAPS_HWRASTERIZATION;
167 d1->dtcTransformCaps.dwSize = sizeof(D3DTRANSFORMCAPS);
168 d1->dtcTransformCaps.dwCaps = D3DTRANSFORMCAPS_CLIP;
169 d1->bClipping = TRUE;
170 d1->dlcLightingCaps.dwSize = sizeof(D3DLIGHTINGCAPS);
171 d1->dlcLightingCaps.dwCaps = D3DLIGHTCAPS_DIRECTIONAL | D3DLIGHTCAPS_PARALLELPOINT | D3DLIGHTCAPS_POINT | D3DLIGHTCAPS_SPOT;
172 d1->dlcLightingCaps.dwLightingModel = D3DLIGHTINGMODEL_RGB;
173 d1->dlcLightingCaps.dwNumLights = 16; /* glGetIntegerv(GL_MAX_LIGHTS, &maxlight); d1->dlcLightingCaps.dwNumLights = maxlight; */
174 fill_opengl_primcaps(&(d1->dpcLineCaps));
175 fill_opengl_primcaps(&(d1->dpcTriCaps));
176 d1->dwDeviceRenderBitDepth = DDBD_16|DDBD_24|DDBD_32;
177 d1->dwDeviceZBufferBitDepth = DDBD_16|DDBD_24|DDBD_32;
178 d1->dwMaxBufferSize = 0;
179 d1->dwMaxVertexCount = 65536;
180 d1->dwMinTextureWidth = 1;
181 d1->dwMinTextureHeight = 1;
182 d1->dwMaxTextureWidth = 1024;
183 d1->dwMaxTextureHeight = 1024;
184 d1->dwMinStippleWidth = 1;
185 d1->dwMinStippleHeight = 1;
186 d1->dwMaxStippleWidth = 32;
187 d1->dwMaxStippleHeight = 32;
188 d1->dwMaxTextureRepeat = 16;
189 d1->dwMaxTextureAspectRatio = 1024;
190 d1->dwMaxAnisotropy = 0;
191 d1->dvGuardBandLeft = 0.0;
192 d1->dvGuardBandRight = 0.0;
193 d1->dvGuardBandTop = 0.0;
194 d1->dvGuardBandBottom = 0.0;
195 d1->dvExtentsAdjust = 0.0;
196 d1->dwStencilCaps = D3DSTENCILCAPS_DECRSAT | D3DSTENCILCAPS_INCRSAT | D3DSTENCILCAPS_INVERT | D3DSTENCILCAPS_KEEP |
197 D3DSTENCILCAPS_REPLACE | D3DSTENCILCAPS_ZERO;
198 d1->dwFVFCaps = D3DFVFCAPS_DONOTSTRIPELEMENTS | 1;
199 d1->dwTextureOpCaps = 0; /* TODO add proper caps according to OpenGL multi-texture stuff */
200 d1->wMaxTextureBlendStages = 1; /* TODO add proper caps according to OpenGL multi-texture stuff */
201 d1->wMaxSimultaneousTextures = 1; /* TODO add proper caps according to OpenGL multi-texture stuff */
204 static void fill_opengl_caps_7(D3DDEVICEDESC7 *d)
206 D3DDEVICEDESC d1;
208 /* Copy first D3D1/2/3 capabilities */
209 fill_opengl_caps(&d1);
211 /* And fill the D3D7 one with it */
212 d->dwDevCaps = d1.dwDevCaps;
213 d->dpcLineCaps = d1.dpcLineCaps;
214 d->dpcTriCaps = d1.dpcTriCaps;
215 d->dwDeviceRenderBitDepth = d1.dwDeviceRenderBitDepth;
216 d->dwDeviceZBufferBitDepth = d1.dwDeviceZBufferBitDepth;
217 d->dwMinTextureWidth = d1.dwMinTextureWidth;
218 d->dwMinTextureHeight = d1.dwMinTextureHeight;
219 d->dwMaxTextureWidth = d1.dwMaxTextureWidth;
220 d->dwMaxTextureHeight = d1.dwMaxTextureHeight;
221 d->dwMaxTextureRepeat = d1.dwMaxTextureRepeat;
222 d->dwMaxTextureAspectRatio = d1.dwMaxTextureAspectRatio;
223 d->dwMaxAnisotropy = d1.dwMaxAnisotropy;
224 d->dvGuardBandLeft = d1.dvGuardBandLeft;
225 d->dvGuardBandTop = d1.dvGuardBandTop;
226 d->dvGuardBandRight = d1.dvGuardBandRight;
227 d->dvGuardBandBottom = d1.dvGuardBandBottom;
228 d->dvExtentsAdjust = d1.dvExtentsAdjust;
229 d->dwStencilCaps = d1.dwStencilCaps;
230 d->dwFVFCaps = d1.dwFVFCaps;
231 d->dwTextureOpCaps = d1.dwTextureOpCaps;
232 d->wMaxTextureBlendStages = d1.wMaxTextureBlendStages;
233 d->wMaxSimultaneousTextures = d1.wMaxSimultaneousTextures;
234 d->dwMaxActiveLights = d1.dlcLightingCaps.dwNumLights;
235 d->dvMaxVertexW = 100000000.0; /* No idea exactly what to put here... */
236 d->deviceGUID = IID_IDirect3DTnLHalDevice;
237 d->wMaxUserClipPlanes = 1;
238 d->wMaxVertexBlendMatrices = 0;
239 d->dwVertexProcessingCaps = D3DVTXPCAPS_TEXGEN | D3DVTXPCAPS_MATERIALSOURCE7 | D3DVTXPCAPS_VERTEXFOG | D3DVTXPCAPS_DIRECTIONALLIGHTS |
240 D3DVTXPCAPS_POSITIONALLIGHTS | D3DVTXPCAPS_LOCALVIEWER;
241 d->dwReserved1 = 0;
242 d->dwReserved2 = 0;
243 d->dwReserved3 = 0;
244 d->dwReserved4 = 0;
247 #if 0 /* TODO : fix this and add multitexturing and other needed stuff */
248 static void fill_device_capabilities(IDirectDrawImpl* ddraw)
250 x11_dd_private *private = (x11_dd_private *) ddraw->d->private;
251 const char *ext_string;
252 Mesa_DeviceCapabilities *devcap;
254 private->device_capabilities = HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,sizeof(Mesa_DeviceCapabilities));
255 devcap = (Mesa_DeviceCapabilities *) private->device_capabilities;
257 ENTER_GL();
258 ext_string = glGetString(GL_EXTENSIONS);
259 /* Query for the ColorTable Extension */
260 if (strstr(ext_string, "GL_EXT_paletted_texture")) {
261 devcap->ptr_ColorTableEXT = (PFNGLCOLORTABLEEXTPROC) glXGetProcAddressARB("glColorTableEXT");
262 TRACE("Color table extension supported (function at %p)\n", devcap->ptr_ColorTableEXT);
263 } else {
264 TRACE("Color table extension not found.\n");
266 LEAVE_GL();
268 #endif
272 HRESULT d3ddevice_enumerate(LPD3DENUMDEVICESCALLBACK cb, LPVOID context)
274 D3DDEVICEDESC d1, d2;
276 fill_opengl_caps(&d1);
277 d2 = d1;
279 TRACE(" enumerating OpenGL D3DDevice interface (IID %s).\n", debugstr_guid(&IID_D3DDEVICE_OpenGL));
280 return cb((LPIID) &IID_D3DDEVICE_OpenGL, "WINE Direct3DX using OpenGL", "direct3d", &d1, &d2, context);
283 HRESULT d3ddevice_enumerate7(LPD3DENUMDEVICESCALLBACK7 cb, LPVOID context)
285 D3DDEVICEDESC7 ddesc;
287 fill_opengl_caps_7(&ddesc);
289 TRACE(" enumerating OpenGL D3DDevice7 interface.\n");
291 return cb("WINE Direct3D7 using OpenGL", "Wine D3D7 device", &ddesc, context);
294 ULONG WINAPI
295 GL_IDirect3DDeviceImpl_7_3T_2T_1T_Release(LPDIRECT3DDEVICE7 iface)
297 ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice7, iface);
298 IDirect3DDeviceGLImpl *glThis = (IDirect3DDeviceGLImpl *) This;
300 TRACE("(%p/%p)->() decrementing from %lu.\n", This, iface, This->ref);
301 if (!--(This->ref)) {
302 /* Release texture associated with the device */
303 if (This->current_texture[0] != NULL)
304 IDirect3DTexture2_Release(ICOM_INTERFACE(This->current_texture[0], IDirect3DTexture2));
306 /* And warn the D3D object that this device is no longer active... */
307 This->d3d->removed_device(This->d3d, This);
309 HeapFree(GetProcessHeap(), 0, This->world_mat);
310 HeapFree(GetProcessHeap(), 0, This->view_mat);
311 HeapFree(GetProcessHeap(), 0, This->proj_mat);
313 ENTER_GL();
314 glXDestroyContext(glThis->display, glThis->gl_context);
315 LEAVE_GL();
317 HeapFree(GetProcessHeap(), 0, This);
318 return 0;
320 return This->ref;
323 HRESULT WINAPI
324 GL_IDirect3DDeviceImpl_3_2T_1T_GetCaps(LPDIRECT3DDEVICE3 iface,
325 LPD3DDEVICEDESC lpD3DHWDevDesc,
326 LPD3DDEVICEDESC lpD3DHELDevDesc)
328 ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice3, iface);
329 D3DDEVICEDESC desc;
330 DWORD dwSize;
332 TRACE("(%p/%p)->(%p,%p)\n", This, iface, lpD3DHWDevDesc, lpD3DHELDevDesc);
334 fill_opengl_caps(&desc);
335 dwSize = lpD3DHWDevDesc->dwSize;
336 memset(lpD3DHWDevDesc, 0, dwSize);
337 memcpy(lpD3DHWDevDesc, &desc, (dwSize <= desc.dwSize ? dwSize : desc.dwSize));
339 dwSize = lpD3DHELDevDesc->dwSize;
340 memset(lpD3DHELDevDesc, 0, dwSize);
341 memcpy(lpD3DHELDevDesc, &desc, (dwSize <= desc.dwSize ? dwSize : desc.dwSize));
343 TRACE(" returning caps : (no dump function yet)\n");
345 return DD_OK;
348 static HRESULT enum_texture_format_OpenGL(LPD3DENUMTEXTUREFORMATSCALLBACK cb_1,
349 LPD3DENUMPIXELFORMATSCALLBACK cb_2,
350 LPVOID context)
352 DDSURFACEDESC sdesc;
353 LPDDPIXELFORMAT pformat;
355 /* Do the texture enumeration */
356 sdesc.dwSize = sizeof(DDSURFACEDESC);
357 sdesc.dwFlags = DDSD_PIXELFORMAT | DDSD_CAPS;
358 sdesc.ddsCaps.dwCaps = DDSCAPS_TEXTURE;
359 pformat = &(sdesc.ddpfPixelFormat);
360 pformat->dwSize = sizeof(DDPIXELFORMAT);
361 pformat->dwFourCC = 0;
363 TRACE("Enumerating GL_RGBA unpacked (32)\n");
364 pformat->dwFlags = DDPF_RGB | DDPF_ALPHAPIXELS;
365 pformat->u1.dwRGBBitCount = 32;
366 pformat->u2.dwRBitMask = 0xFF000000;
367 pformat->u3.dwGBitMask = 0x00FF0000;
368 pformat->u4.dwBBitMask = 0x0000FF00;
369 pformat->u5.dwRGBAlphaBitMask = 0x000000FF;
370 if (cb_1) if (cb_1(&sdesc , context) == 0) return DD_OK;
371 if (cb_2) if (cb_2(pformat, context) == 0) return DD_OK;
373 TRACE("Enumerating GL_RGB unpacked (24)\n");
374 pformat->dwFlags = DDPF_RGB;
375 pformat->u1.dwRGBBitCount = 24;
376 pformat->u2.dwRBitMask = 0x00FF0000;
377 pformat->u3.dwGBitMask = 0x0000FF00;
378 pformat->u4.dwBBitMask = 0x000000FF;
379 pformat->u5.dwRGBAlphaBitMask = 0x00000000;
380 if (cb_1) if (cb_1(&sdesc , context) == 0) return DD_OK;
381 if (cb_2) if (cb_2(pformat, context) == 0) return DD_OK;
383 TRACE("Enumerating GL_RGB packed GL_UNSIGNED_SHORT_5_6_5 (16)\n");
384 pformat->dwFlags = DDPF_RGB;
385 pformat->u1.dwRGBBitCount = 16;
386 pformat->u2.dwRBitMask = 0x0000F800;
387 pformat->u3.dwGBitMask = 0x000007E0;
388 pformat->u4.dwBBitMask = 0x0000001F;
389 pformat->u5.dwRGBAlphaBitMask = 0x00000000;
390 if (cb_1) if (cb_1(&sdesc , context) == 0) return DD_OK;
391 if (cb_2) if (cb_2(pformat, context) == 0) return DD_OK;
393 TRACE("Enumerating GL_RGBA packed GL_UNSIGNED_SHORT_5_5_5_1 (16)\n");
394 pformat->dwFlags = DDPF_RGB | DDPF_ALPHAPIXELS;
395 pformat->u1.dwRGBBitCount = 16;
396 pformat->u2.dwRBitMask = 0x0000F800;
397 pformat->u3.dwGBitMask = 0x000007C0;
398 pformat->u4.dwBBitMask = 0x0000003E;
399 pformat->u5.dwRGBAlphaBitMask = 0x00000001;
400 if (cb_1) if (cb_1(&sdesc , context) == 0) return DD_OK;
401 if (cb_2) if (cb_2(pformat, context) == 0) return DD_OK;
403 TRACE("Enumerating GL_RGBA packed GL_UNSIGNED_SHORT_4_4_4_4 (16)\n");
404 pformat->dwFlags = DDPF_RGB | DDPF_ALPHAPIXELS;
405 pformat->u1.dwRGBBitCount = 16;
406 pformat->u2.dwRBitMask = 0x0000F000;
407 pformat->u3.dwGBitMask = 0x00000F00;
408 pformat->u4.dwBBitMask = 0x000000F0;
409 pformat->u5.dwRGBAlphaBitMask = 0x0000000F;
410 if (cb_1) if (cb_1(&sdesc , context) == 0) return DD_OK;
411 if (cb_2) if (cb_2(pformat, context) == 0) return DD_OK;
413 TRACE("Enumerating GL_RGBA packed GL_UNSIGNED_SHORT_1_5_5_5 (16)\n");
414 pformat->dwFlags = DDPF_RGB | DDPF_ALPHAPIXELS;
415 pformat->u1.dwRGBBitCount = 16;
416 pformat->u2.dwRBitMask = 0x00007C00;
417 pformat->u3.dwGBitMask = 0x000003E0;
418 pformat->u4.dwBBitMask = 0x0000001F;
419 pformat->u5.dwRGBAlphaBitMask = 0x00008000;
420 if (cb_1) if (cb_1(&sdesc , context) == 0) return DD_OK;
421 if (cb_2) if (cb_2(pformat, context) == 0) return DD_OK;
423 TRACE("Enumerating GL_RGBA packed GL_UNSIGNED_SHORT_4_4_4_4 (ARGB) (16)\n");
424 pformat->dwFlags = DDPF_RGB | DDPF_ALPHAPIXELS;
425 pformat->u1.dwRGBBitCount = 16;
426 pformat->u2.dwRBitMask = 0x00000F00;
427 pformat->u3.dwGBitMask = 0x000000F0;
428 pformat->u4.dwBBitMask = 0x0000000F;
429 pformat->u5.dwRGBAlphaBitMask = 0x0000F000;
430 if (cb_1) if (cb_1(&sdesc , context) == 0) return DD_OK;
431 if (cb_2) if (cb_2(pformat, context) == 0) return DD_OK;
433 TRACE("Enumerating GL_RGB packed GL_UNSIGNED_BYTE_3_3_2 (8)\n");
434 pformat->dwFlags = DDPF_RGB;
435 pformat->u1.dwRGBBitCount = 8;
436 pformat->u2.dwRBitMask = 0x000000E0;
437 pformat->u3.dwGBitMask = 0x0000001C;
438 pformat->u4.dwBBitMask = 0x00000003;
439 pformat->u5.dwRGBAlphaBitMask = 0x00000000;
440 if (cb_1) if (cb_1(&sdesc , context) == 0) return DD_OK;
441 if (cb_2) if (cb_2(pformat, context) == 0) return DD_OK;
443 TRACE("Enumerating GL_ARGB (no direct OpenGL equivalent - conversion needed)\n");
444 pformat->dwFlags = DDPF_RGB | DDPF_ALPHAPIXELS;
445 pformat->u1.dwRGBBitCount = 16;
446 pformat->u2.dwRBitMask = 0x00007C00;
447 pformat->u3.dwGBitMask = 0x000003E0;
448 pformat->u4.dwBBitMask = 0x0000001F;
449 pformat->u5.dwRGBAlphaBitMask = 0x00008000;
450 if (cb_1) if (cb_1(&sdesc , context) == 0) return DD_OK;
451 if (cb_2) if (cb_2(pformat, context) == 0) return DD_OK;
453 TRACE("Enumerating Paletted (8)\n");
454 pformat->dwFlags = DDPF_PALETTEINDEXED8;
455 pformat->u1.dwRGBBitCount = 8;
456 pformat->u2.dwRBitMask = 0x00000000;
457 pformat->u3.dwGBitMask = 0x00000000;
458 pformat->u4.dwBBitMask = 0x00000000;
459 pformat->u5.dwRGBAlphaBitMask = 0x00000000;
460 if (cb_1) if (cb_1(&sdesc , context) == 0) return DD_OK;
461 if (cb_2) if (cb_2(pformat, context) == 0) return DD_OK;
463 TRACE("End of enumeration\n");
464 return DD_OK;
468 HRESULT
469 d3ddevice_find(IDirect3DImpl *d3d,
470 LPD3DFINDDEVICESEARCH lpD3DDFS,
471 LPD3DFINDDEVICERESULT lplpD3DDevice)
473 D3DDEVICEDESC desc;
475 if ((lpD3DDFS->dwFlags & D3DFDS_COLORMODEL) &&
476 (lpD3DDFS->dcmColorModel != D3DCOLOR_RGB)) {
477 TRACE(" trying to request a non-RGB D3D color model. Not supported.\n");
478 return DDERR_INVALIDPARAMS; /* No real idea what to return here :-) */
480 if (lpD3DDFS->dwFlags & D3DFDS_GUID) {
481 TRACE(" trying to match guid %s.\n", debugstr_guid(&(lpD3DDFS->guid)));
482 if ((IsEqualGUID( &IID_D3DDEVICE_OpenGL, &(lpD3DDFS->guid)) == 0) &&
483 (IsEqualGUID(&IID_IDirect3DHALDevice, &(lpD3DDFS->guid)) == 0)) {
484 TRACE(" no match for this GUID.\n");
485 return DDERR_INVALIDPARAMS;
489 /* Now return our own GUID */
490 lplpD3DDevice->guid = IID_D3DDEVICE_OpenGL;
491 fill_opengl_caps(&desc);
492 lplpD3DDevice->ddHwDesc = desc;
493 lplpD3DDevice->ddSwDesc = desc;
495 TRACE(" returning Wine's OpenGL device with (undumped) capabilities\n");
497 return D3D_OK;
500 HRESULT WINAPI
501 GL_IDirect3DDeviceImpl_2_1T_EnumTextureFormats(LPDIRECT3DDEVICE2 iface,
502 LPD3DENUMTEXTUREFORMATSCALLBACK lpD3DEnumTextureProc,
503 LPVOID lpArg)
505 ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice2, iface);
506 TRACE("(%p/%p)->(%p,%p)\n", This, iface, lpD3DEnumTextureProc, lpArg);
507 return enum_texture_format_OpenGL(lpD3DEnumTextureProc, NULL, lpArg);
510 HRESULT WINAPI
511 GL_IDirect3DDeviceImpl_7_3T_EnumTextureFormats(LPDIRECT3DDEVICE7 iface,
512 LPD3DENUMPIXELFORMATSCALLBACK lpD3DEnumPixelProc,
513 LPVOID lpArg)
515 ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice7, iface);
516 TRACE("(%p/%p)->(%p,%p)\n", This, iface, lpD3DEnumPixelProc, lpArg);
517 return enum_texture_format_OpenGL(NULL, lpD3DEnumPixelProc, lpArg);
520 HRESULT WINAPI
521 GL_IDirect3DDeviceImpl_7_3T_2T_SetRenderState(LPDIRECT3DDEVICE7 iface,
522 D3DRENDERSTATETYPE dwRenderStateType,
523 DWORD dwRenderState)
525 ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice7, iface);
526 IDirect3DDeviceGLImpl *glThis = (IDirect3DDeviceGLImpl *) This;
527 TRACE("(%p/%p)->(%08x,%08lx)\n", This, iface, dwRenderStateType, dwRenderState);
529 /* Call the render state functions */
530 set_render_state(dwRenderStateType, dwRenderState, &(glThis->render_state));
532 return DD_OK;
535 HRESULT WINAPI
536 GL_IDirect3DDeviceImpl_3_2T_SetLightState(LPDIRECT3DDEVICE3 iface,
537 D3DLIGHTSTATETYPE dwLightStateType,
538 DWORD dwLightState)
540 ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice3, iface);
541 IDirect3DDeviceGLImpl *glThis = (IDirect3DDeviceGLImpl *) This;
543 TRACE("(%p/%p)->(%08x,%08lx)\n", This, iface, dwLightStateType, dwLightState);
545 switch (dwLightStateType) {
546 case D3DLIGHTSTATE_MATERIAL: { /* 1 */
547 IDirect3DMaterialImpl *mat = (IDirect3DMaterialImpl *) dwLightState;
549 if (mat != NULL) {
550 ENTER_GL();
551 mat->activate(mat);
552 LEAVE_GL();
553 } else {
554 ERR(" D3DLIGHTSTATE_MATERIAL called with NULL material !!!\n");
556 } break;
558 case D3DLIGHTSTATE_AMBIENT: /* 2 */
559 /* Call the render_state function... */
560 set_render_state(D3DRENDERSTATE_AMBIENT, dwLightState, &(glThis->render_state));
561 break;
563 #define UNSUP(x) case D3DLIGHTSTATE_##x: FIXME("unsupported D3DLIGHTSTATE_" #x "!\n");break;
564 UNSUP(COLORMODEL);
565 UNSUP(FOGMODE);
566 UNSUP(FOGSTART);
567 UNSUP(FOGEND);
568 UNSUP(FOGDENSITY);
569 UNSUP(COLORVERTEX);
570 #undef UNSUP
572 default:
573 TRACE("Unexpected Light State Type\n");
574 return DDERR_INVALIDPARAMS;
577 return DD_OK;
580 HRESULT WINAPI
581 GL_IDirect3DDeviceImpl_7_3T_2T_SetTransform(LPDIRECT3DDEVICE7 iface,
582 D3DTRANSFORMSTATETYPE dtstTransformStateType,
583 LPD3DMATRIX lpD3DMatrix)
585 ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice7, iface);
586 IDirect3DDeviceGLImpl *glThis = (IDirect3DDeviceGLImpl *) This;
588 TRACE("(%p/%p)->(%08x,%p)\n", This, iface, dtstTransformStateType, lpD3DMatrix);
590 ENTER_GL();
592 /* Using a trial and failure approach, I found that the order of
593 Direct3D transformations that works best is :
595 ScreenCoord = ProjectionMat * ViewMat * WorldMat * ObjectCoord
597 As OpenGL uses only two matrices, I combined PROJECTION and VIEW into
598 OpenGL's GL_PROJECTION matrix and the WORLD into GL_MODELVIEW.
600 If anyone has a good explanation of the three different matrices in
601 the SDK online documentation, feel free to point it to me. For example,
602 which matrices transform lights ? In OpenGL only the PROJECTION matrix
603 transform the lights, not the MODELVIEW. Using the matrix names, I
604 supposed that PROJECTION and VIEW (all 'camera' related names) do
605 transform lights, but WORLD do not. It may be wrong though... */
607 /* After reading through both OpenGL and Direct3D documentations, I
608 thought that D3D matrices were written in 'line major mode' transposed
609 from OpenGL's 'column major mode'. But I found out that a simple memcpy
610 works fine to transfer one matrix format to the other (it did not work
611 when transposing)....
613 So :
614 1) are the documentations wrong
615 2) does the matrix work even if they are not read correctly
616 3) is Mesa's implementation of OpenGL not compliant regarding Matrix
617 loading using glLoadMatrix ?
619 Anyway, I always use 'conv_mat' to transfer the matrices from one format
620 to the other so that if I ever find out that I need to transpose them, I
621 will able to do it quickly, only by changing the macro conv_mat. */
623 switch (dtstTransformStateType) {
624 case D3DTRANSFORMSTATE_WORLD: {
625 TRACE(" D3DTRANSFORMSTATE_WORLD :\n");
626 conv_mat(lpD3DMatrix, This->world_mat);
627 if (glThis->last_vertices_transformed == FALSE) {
628 glMatrixMode(GL_MODELVIEW);
629 glLoadMatrixf((float *) This->view_mat);
630 glMultMatrixf((float *) This->world_mat);
632 } break;
634 case D3DTRANSFORMSTATE_VIEW: {
635 TRACE(" D3DTRANSFORMSTATE_VIEW :\n");
636 conv_mat(lpD3DMatrix, This->view_mat);
637 if (glThis->last_vertices_transformed == FALSE) {
638 glMatrixMode(GL_MODELVIEW);
639 glLoadMatrixf((float *) This->view_mat);
640 glMultMatrixf((float *) This->world_mat);
642 } break;
644 case D3DTRANSFORMSTATE_PROJECTION: {
645 TRACE(" D3DTRANSFORMSTATE_PROJECTION :\n");
646 conv_mat(lpD3DMatrix, This->proj_mat);
647 if (glThis->last_vertices_transformed == FALSE) {
648 glMatrixMode(GL_PROJECTION);
649 glLoadMatrixf((float *) This->proj_mat);
651 } break;
653 default:
654 ERR("Unknown transform type %08x !!!\n", dtstTransformStateType);
655 break;
657 LEAVE_GL();
659 return DD_OK;
662 static void draw_primitive_start_GL(D3DPRIMITIVETYPE d3dpt)
664 switch (d3dpt) {
665 case D3DPT_POINTLIST:
666 TRACE("Start POINTS\n");
667 glBegin(GL_POINTS);
668 break;
670 case D3DPT_LINELIST:
671 TRACE("Start LINES\n");
672 glBegin(GL_LINES);
673 break;
675 case D3DPT_LINESTRIP:
676 TRACE("Start LINE_STRIP\n");
677 glBegin(GL_LINE_STRIP);
678 break;
680 case D3DPT_TRIANGLELIST:
681 TRACE("Start TRIANGLES\n");
682 glBegin(GL_TRIANGLES);
683 break;
685 case D3DPT_TRIANGLESTRIP:
686 TRACE("Start TRIANGLE_STRIP\n");
687 glBegin(GL_TRIANGLE_STRIP);
688 break;
690 case D3DPT_TRIANGLEFAN:
691 TRACE("Start TRIANGLE_FAN\n");
692 glBegin(GL_TRIANGLE_FAN);
693 break;
695 default:
696 TRACE("Unhandled primitive\n");
697 break;
701 static void draw_primitive_handle_GL_state(IDirect3DDeviceImpl *This,
702 BOOLEAN vertex_transformed,
703 BOOLEAN vertex_lit) {
704 IDirect3DDeviceGLImpl* glThis = (IDirect3DDeviceGLImpl*) This;
706 /* Puts GL in the correct lighting / transformation mode */
707 if ((vertex_transformed == FALSE) &&
708 (glThis->last_vertices_transformed == TRUE)) {
709 /* Need to put the correct transformation again if we go from Transformed
710 vertices to non-transformed ones.
712 glMatrixMode(GL_MODELVIEW);
713 glLoadMatrixf((float *) This->view_mat);
714 glMultMatrixf((float *) This->world_mat);
715 glMatrixMode(GL_PROJECTION);
716 glLoadMatrixf((float *) This->proj_mat);
718 if (glThis->render_state.fog_on == TRUE) glEnable(GL_FOG);
719 } else if ((vertex_transformed == TRUE) &&
720 (glThis->last_vertices_transformed == FALSE)) {
721 GLfloat height, width;
722 GLfloat trans_mat[16];
724 width = glThis->parent.surface->surface_desc.dwWidth;
725 height = glThis->parent.surface->surface_desc.dwHeight;
727 /* The X axis is straighforward.. For the Y axis, we need to convert 'D3D' screen coordinates
728 to OpenGL screen coordinates (ie the upper left corner is not the same).
729 For Z, the mystery is what should it be mapped to ? Ie should the resulting range be between
730 -1.0 and 1.0 (as the X and Y coordinates) or between 0.0 and 1.0 ? */
731 trans_mat[ 0] = 2.0 / width; trans_mat[ 4] = 0.0; trans_mat[ 8] = 0.0; trans_mat[12] = -1.0;
732 trans_mat[ 1] = 0.0; trans_mat[ 5] = -2.0 / height; trans_mat[ 9] = 0.0; trans_mat[13] = 1.0;
733 trans_mat[ 2] = 0.0; trans_mat[ 6] = 0.0; trans_mat[10] = 1.0; trans_mat[14] = -1.0;
734 trans_mat[ 3] = 0.0; trans_mat[ 7] = 0.0; trans_mat[11] = 0.0; trans_mat[15] = 1.0;
736 glMatrixMode(GL_MODELVIEW);
737 glLoadIdentity();
738 glMatrixMode(GL_PROJECTION);
739 glLoadMatrixf(trans_mat);
741 /* Remove also fogging... */
742 glDisable(GL_FOG);
745 if ((glThis->last_vertices_lit == TRUE) && (vertex_lit == FALSE)) {
746 glEnable(GL_LIGHTING);
747 } else if ((glThis->last_vertices_lit == TRUE) && (vertex_lit == TRUE)) {
748 glDisable(GL_LIGHTING);
751 /* And save the current state */
752 glThis->last_vertices_transformed = vertex_transformed;
753 glThis->last_vertices_lit = vertex_lit;
757 inline static void draw_primitive(IDirect3DDeviceImpl *This, DWORD maxvert, WORD *index,
758 D3DVERTEXTYPE d3dvt, D3DPRIMITIVETYPE d3dpt, void *lpvertex)
760 D3DDRAWPRIMITIVESTRIDEDDATA strided;
762 switch (d3dvt) {
763 case D3DVT_VERTEX: {
764 strided.position.lpvData = &((D3DVERTEX *) lpvertex)->u1.x;
765 strided.position.dwStride = sizeof(D3DVERTEX);
766 strided.normal.lpvData = &((D3DVERTEX *) lpvertex)->u4.nx;
767 strided.normal.dwStride = sizeof(D3DVERTEX);
768 strided.textureCoords[0].lpvData = &((D3DVERTEX *) lpvertex)->u7.tu;
769 strided.textureCoords[0].dwStride = sizeof(D3DVERTEX);
770 draw_primitive_strided_7(This, d3dpt, D3DFVF_VERTEX, &strided, 0, 0 /* Unused */, index, maxvert, 0 /* Unused */);
771 } break;
773 case D3DVT_LVERTEX: {
774 strided.position.lpvData = &((D3DLVERTEX *) lpvertex)->u1.x;
775 strided.position.dwStride = sizeof(D3DLVERTEX);
776 strided.diffuse.lpvData = &((D3DLVERTEX *) lpvertex)->u4.color;
777 strided.diffuse.dwStride = sizeof(D3DLVERTEX);
778 strided.specular.lpvData = &((D3DLVERTEX *) lpvertex)->u5.specular;
779 strided.specular.dwStride = sizeof(D3DLVERTEX);
780 strided.textureCoords[0].lpvData = &((D3DLVERTEX *) lpvertex)->u6.tu;
781 strided.textureCoords[0].dwStride = sizeof(D3DLVERTEX);
782 draw_primitive_strided_7(This, d3dpt, D3DFVF_LVERTEX, &strided, 0, 0 /* Unused */, index, maxvert, 0 /* Unused */);
783 } break;
785 case D3DVT_TLVERTEX: {
786 strided.position.lpvData = &((D3DTLVERTEX *) lpvertex)->u1.sx;
787 strided.position.dwStride = sizeof(D3DTLVERTEX);
788 strided.diffuse.lpvData = &((D3DTLVERTEX *) lpvertex)->u5.color;
789 strided.diffuse.dwStride = sizeof(D3DTLVERTEX);
790 strided.specular.lpvData = &((D3DTLVERTEX *) lpvertex)->u6.specular;
791 strided.specular.dwStride = sizeof(D3DTLVERTEX);
792 strided.textureCoords[0].lpvData = &((D3DTLVERTEX *) lpvertex)->u7.tu;
793 strided.textureCoords[0].dwStride = sizeof(D3DTLVERTEX);
794 draw_primitive_strided_7(This, d3dpt, D3DFVF_TLVERTEX, &strided, 0, 0 /* Unused */, index, maxvert, 0 /* Unused */);
795 } break;
797 default:
798 FIXME("Unhandled vertex type\n");
799 break;
803 HRESULT WINAPI
804 GL_IDirect3DDeviceImpl_2_DrawPrimitive(LPDIRECT3DDEVICE2 iface,
805 D3DPRIMITIVETYPE d3dptPrimitiveType,
806 D3DVERTEXTYPE d3dvtVertexType,
807 LPVOID lpvVertices,
808 DWORD dwVertexCount,
809 DWORD dwFlags)
811 ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice2, iface);
812 TRACE("(%p/%p)->(%08x,%08x,%p,%08lx,%08lx)\n", This, iface, d3dptPrimitiveType, d3dvtVertexType, lpvVertices, dwVertexCount, dwFlags);
814 ENTER_GL();
815 draw_primitive(This, dwVertexCount, NULL, d3dvtVertexType, d3dptPrimitiveType, lpvVertices);
816 LEAVE_GL();
818 return DD_OK;
821 HRESULT WINAPI
822 GL_IDirect3DDeviceImpl_2_DrawIndexedPrimitive(LPDIRECT3DDEVICE2 iface,
823 D3DPRIMITIVETYPE d3dptPrimitiveType,
824 D3DVERTEXTYPE d3dvtVertexType,
825 LPVOID lpvVertices,
826 DWORD dwVertexCount,
827 LPWORD dwIndices,
828 DWORD dwIndexCount,
829 DWORD dwFlags)
831 ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice2, iface);
832 TRACE("(%p/%p)->(%08x,%08x,%p,%08lx,%p,%08lx,%08lx)\n", This, iface, d3dptPrimitiveType, d3dvtVertexType, lpvVertices, dwVertexCount, dwIndices, dwIndexCount, dwFlags);
834 ENTER_GL();
835 draw_primitive(This, dwIndexCount, dwIndices, d3dvtVertexType, d3dptPrimitiveType, lpvVertices);
836 LEAVE_GL();
838 return DD_OK;
841 HRESULT WINAPI
842 GL_IDirect3DDeviceImpl_1_CreateExecuteBuffer(LPDIRECT3DDEVICE iface,
843 LPD3DEXECUTEBUFFERDESC lpDesc,
844 LPDIRECT3DEXECUTEBUFFER* lplpDirect3DExecuteBuffer,
845 IUnknown* pUnkOuter)
847 ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice, iface);
848 IDirect3DExecuteBufferImpl *ret;
849 HRESULT ret_value;
851 TRACE("(%p/%p)->(%p,%p,%p)\n", This, iface, lpDesc, lplpDirect3DExecuteBuffer, pUnkOuter);
853 ret_value = d3dexecutebuffer_create(&ret, This->d3d, This, lpDesc);
854 *lplpDirect3DExecuteBuffer = ICOM_INTERFACE(ret, IDirect3DExecuteBuffer);
856 TRACE(" returning %p.\n", *lplpDirect3DExecuteBuffer);
858 return ret_value;
861 DWORD get_flexible_vertex_size(DWORD d3dvtVertexType, DWORD *elements)
863 DWORD size = 0;
864 DWORD elts = 0;
866 if (d3dvtVertexType & D3DFVF_NORMAL) { size += 3 * sizeof(D3DVALUE); elts += 1; }
867 if (d3dvtVertexType & D3DFVF_DIFFUSE) { size += sizeof(DWORD); elts += 1; }
868 if (d3dvtVertexType & D3DFVF_SPECULAR) { size += sizeof(DWORD); elts += 1; }
869 switch (d3dvtVertexType & D3DFVF_POSITION_MASK) {
870 case D3DFVF_XYZ: size += 3 * sizeof(D3DVALUE); elts += 1; break;
871 case D3DFVF_XYZRHW: size += 4 * sizeof(D3DVALUE); elts += 1; break;
872 default: TRACE(" matrix weighting not handled yet...\n");
874 size += 2 * sizeof(D3DVALUE) * ((d3dvtVertexType & D3DFVF_TEXCOUNT_MASK) >> D3DFVF_TEXCOUNT_SHIFT);
875 elts += (d3dvtVertexType & D3DFVF_TEXCOUNT_MASK) >> D3DFVF_TEXCOUNT_SHIFT;
877 if (elements) *elements = elts;
879 return size;
882 void dump_flexible_vertex(DWORD d3dvtVertexType)
884 static const flag_info flags[] = {
885 FE(D3DFVF_NORMAL),
886 FE(D3DFVF_RESERVED1),
887 FE(D3DFVF_DIFFUSE),
888 FE(D3DFVF_SPECULAR)
890 if (d3dvtVertexType & D3DFVF_RESERVED0) DPRINTF("D3DFVF_RESERVED0 ");
891 switch (d3dvtVertexType & D3DFVF_POSITION_MASK) {
892 #define GEN_CASE(a) case a: DPRINTF(#a " "); break
893 GEN_CASE(D3DFVF_XYZ);
894 GEN_CASE(D3DFVF_XYZRHW);
895 GEN_CASE(D3DFVF_XYZB1);
896 GEN_CASE(D3DFVF_XYZB2);
897 GEN_CASE(D3DFVF_XYZB3);
898 GEN_CASE(D3DFVF_XYZB4);
899 GEN_CASE(D3DFVF_XYZB5);
901 DDRAW_dump_flags_(d3dvtVertexType, flags, sizeof(flags)/sizeof(flags[0]), FALSE);
902 switch (d3dvtVertexType & D3DFVF_TEXCOUNT_MASK) {
903 GEN_CASE(D3DFVF_TEX0);
904 GEN_CASE(D3DFVF_TEX1);
905 GEN_CASE(D3DFVF_TEX2);
906 GEN_CASE(D3DFVF_TEX3);
907 GEN_CASE(D3DFVF_TEX4);
908 GEN_CASE(D3DFVF_TEX5);
909 GEN_CASE(D3DFVF_TEX6);
910 GEN_CASE(D3DFVF_TEX7);
911 GEN_CASE(D3DFVF_TEX8);
913 #undef GEN_CASE
914 DPRINTF("\n");
917 /* These are the various handler used in the generic path */
918 inline static void handle_xyz(D3DVALUE *coords) {
919 glVertex3fv(coords);
921 inline static void handle_xyzrhw(D3DVALUE *coords) {
922 if (coords[3] < 1e-8)
923 glVertex3fv(coords);
924 else {
925 GLfloat w = 1.0 / coords[3];
927 glVertex4f(coords[0] * w,
928 coords[1] * w,
929 coords[2] * w,
933 inline static void handle_normal(D3DVALUE *coords) {
934 glNormal3fv(coords);
936 inline static void handle_specular(DWORD *color) {
937 /* Specular not handled yet properly... */
939 inline static void handle_diffuse(DWORD *color) {
940 glColor4ub((*color >> 16) & 0xFF,
941 (*color >> 8) & 0xFF,
942 (*color >> 0) & 0xFF,
943 (*color >> 24) & 0xFF);
945 inline static void handle_diffuse_and_specular(DWORD *color_d, DWORD *color_s) {
946 handle_diffuse(color_d);
948 inline static void handle_diffuse_no_alpha(DWORD *color) {
949 glColor3ub((*color >> 16) & 0xFF,
950 (*color >> 8) & 0xFF,
951 (*color >> 0) & 0xFF);
953 inline static void handle_diffuse_and_specular_no_alpha(DWORD *color_d, DWORD *color_s) {
954 handle_diffuse_no_alpha(color_d);
956 inline static void handle_texture(D3DVALUE *coords) {
957 glTexCoord2fv(coords);
959 inline static void handle_textures(D3DVALUE *coords, int tex_index) {
960 /* For the moment, draw only the first texture.. */
961 if (tex_index == 0) glTexCoord2fv(coords);
964 static void draw_primitive_strided_7(IDirect3DDeviceImpl *This,
965 D3DPRIMITIVETYPE d3dptPrimitiveType,
966 DWORD d3dvtVertexType,
967 LPD3DDRAWPRIMITIVESTRIDEDDATA lpD3DDrawPrimStrideData,
968 DWORD dwStartVertex,
969 DWORD dwVertexCount,
970 LPWORD dwIndices,
971 DWORD dwIndexCount,
972 DWORD dwFlags)
974 IDirect3DDeviceGLImpl* glThis = (IDirect3DDeviceGLImpl*) This;
975 if (TRACE_ON(ddraw)) {
976 TRACE(" Vertex format : "); dump_flexible_vertex(d3dvtVertexType);
979 ENTER_GL();
980 draw_primitive_handle_GL_state(This,
981 (d3dvtVertexType & D3DFVF_POSITION_MASK) != D3DFVF_XYZ,
982 (d3dvtVertexType & D3DFVF_NORMAL) == 0);
983 draw_primitive_start_GL(d3dptPrimitiveType);
985 /* Some fast paths first before the generic case.... */
986 if (d3dvtVertexType == D3DFVF_VERTEX) {
987 int index;
989 for (index = 0; index < dwIndexCount; index++) {
990 int i = (dwIndices == NULL) ? index : dwIndices[index];
991 D3DVALUE *normal =
992 (D3DVALUE *) (((char *) lpD3DDrawPrimStrideData->normal.lpvData) + i * lpD3DDrawPrimStrideData->normal.dwStride);
993 D3DVALUE *tex_coord =
994 (D3DVALUE *) (((char *) lpD3DDrawPrimStrideData->textureCoords[0].lpvData) + i * lpD3DDrawPrimStrideData->textureCoords[0].dwStride);
995 D3DVALUE *position =
996 (D3DVALUE *) (((char *) lpD3DDrawPrimStrideData->position.lpvData) + i * lpD3DDrawPrimStrideData->position.dwStride);
998 handle_normal(normal);
999 handle_texture(tex_coord);
1000 handle_xyz(position);
1002 TRACE(" %f %f %f / %f %f %f (%f %f)\n",
1003 position[0], position[1], position[2],
1004 normal[0], normal[1], normal[2],
1005 tex_coord[0], tex_coord[1]);
1007 } else if (d3dvtVertexType == D3DFVF_TLVERTEX) {
1008 int index;
1010 for (index = 0; index < dwIndexCount; index++) {
1011 int i = (dwIndices == NULL) ? index : dwIndices[index];
1012 DWORD *color_d =
1013 (DWORD *) (((char *) lpD3DDrawPrimStrideData->diffuse.lpvData) + i * lpD3DDrawPrimStrideData->diffuse.dwStride);
1014 DWORD *color_s =
1015 (DWORD *) (((char *) lpD3DDrawPrimStrideData->specular.lpvData) + i * lpD3DDrawPrimStrideData->specular.dwStride);
1016 D3DVALUE *tex_coord =
1017 (D3DVALUE *) (((char *) lpD3DDrawPrimStrideData->textureCoords[0].lpvData) + i * lpD3DDrawPrimStrideData->textureCoords[0].dwStride);
1018 D3DVALUE *position =
1019 (D3DVALUE *) (((char *) lpD3DDrawPrimStrideData->position.lpvData) + i * lpD3DDrawPrimStrideData->position.dwStride);
1021 if (glThis->render_state.alpha_blend_enable == TRUE)
1022 handle_diffuse_and_specular(color_d, color_s);
1023 else
1024 handle_diffuse_and_specular_no_alpha(color_d, color_s);
1025 handle_texture(tex_coord);
1026 handle_xyzrhw(position);
1028 TRACE(" %f %f %f %f / %02lx %02lx %02lx %02lx - %02lx %02lx %02lx %02lx (%f %f)\n",
1029 position[0], position[1], position[2], position[3],
1030 (*color_d >> 16) & 0xFF,
1031 (*color_d >> 8) & 0xFF,
1032 (*color_d >> 0) & 0xFF,
1033 (*color_d >> 24) & 0xFF,
1034 (*color_s >> 16) & 0xFF,
1035 (*color_s >> 8) & 0xFF,
1036 (*color_s >> 0) & 0xFF,
1037 (*color_s >> 24) & 0xFF,
1038 tex_coord[0], tex_coord[1]);
1040 } else if (((d3dvtVertexType & D3DFVF_POSITION_MASK) == D3DFVF_XYZ) ||
1041 ((d3dvtVertexType & D3DFVF_POSITION_MASK) == D3DFVF_XYZRHW)) {
1042 /* This is the 'slow path' but that should support all possible vertex formats out there...
1043 Note that people should write a fast path for all vertex formats out there...
1045 int index;
1046 for (index = 0; index < dwIndexCount; index++) {
1047 int i = (dwIndices == NULL) ? index : dwIndices[index];
1049 if (d3dvtVertexType & D3DFVF_NORMAL) {
1050 D3DVALUE *normal =
1051 (D3DVALUE *) (((char *) lpD3DDrawPrimStrideData->normal.lpvData) + i * lpD3DDrawPrimStrideData->normal.dwStride);
1052 handle_normal(normal);
1054 if ((d3dvtVertexType & (D3DFVF_DIFFUSE|D3DFVF_SPECULAR)) == (D3DFVF_DIFFUSE|D3DFVF_SPECULAR)) {
1055 DWORD *color_d =
1056 (DWORD *) (((char *) lpD3DDrawPrimStrideData->diffuse.lpvData) + i * lpD3DDrawPrimStrideData->diffuse.dwStride);
1057 DWORD *color_s =
1058 (DWORD *) (((char *) lpD3DDrawPrimStrideData->specular.lpvData) + i * lpD3DDrawPrimStrideData->specular.dwStride);
1059 if (glThis->render_state.alpha_blend_enable == TRUE)
1060 handle_diffuse_and_specular(color_d, color_s);
1061 else
1062 handle_diffuse_and_specular_no_alpha(color_d, color_s);
1063 } else {
1064 if (d3dvtVertexType & D3DFVF_SPECULAR) {
1065 DWORD *color_s =
1066 (DWORD *) (((char *) lpD3DDrawPrimStrideData->specular.lpvData) + i * lpD3DDrawPrimStrideData->specular.dwStride);
1067 handle_specular(color_s);
1068 } else if (d3dvtVertexType & D3DFVF_DIFFUSE) {
1069 DWORD *color_d =
1070 (DWORD *) (((char *) lpD3DDrawPrimStrideData->diffuse.lpvData) + i * lpD3DDrawPrimStrideData->diffuse.dwStride);
1071 if (glThis->render_state.alpha_blend_enable == TRUE)
1072 handle_diffuse(color_d);
1073 else
1074 handle_diffuse_no_alpha(color_d);
1078 if (((d3dvtVertexType & D3DFVF_TEXCOUNT_MASK) >> D3DFVF_TEXCOUNT_SHIFT) == 1) {
1079 /* Special case for single texture... */
1080 D3DVALUE *tex_coord =
1081 (D3DVALUE *) (((char *) lpD3DDrawPrimStrideData->textureCoords[0].lpvData) + i * lpD3DDrawPrimStrideData->textureCoords[0].dwStride);
1082 handle_texture(tex_coord);
1083 } else {
1084 int tex_index;
1085 for (tex_index = 0; tex_index < ((d3dvtVertexType & D3DFVF_TEXCOUNT_MASK) >> D3DFVF_TEXCOUNT_SHIFT); tex_index++) {
1086 D3DVALUE *tex_coord =
1087 (D3DVALUE *) (((char *) lpD3DDrawPrimStrideData->textureCoords[tex_index].lpvData) +
1088 i * lpD3DDrawPrimStrideData->textureCoords[tex_index].dwStride);
1089 handle_textures(tex_coord, tex_index);
1092 if ((d3dvtVertexType & D3DFVF_POSITION_MASK) == D3DFVF_XYZ) {
1093 D3DVALUE *position =
1094 (D3DVALUE *) (((char *) lpD3DDrawPrimStrideData->position.lpvData) + i * lpD3DDrawPrimStrideData->position.dwStride);
1095 handle_xyz(position);
1096 } else if ((d3dvtVertexType & D3DFVF_POSITION_MASK) == D3DFVF_XYZRHW) {
1097 D3DVALUE *position =
1098 (D3DVALUE *) (((char *) lpD3DDrawPrimStrideData->position.lpvData) + i * lpD3DDrawPrimStrideData->position.dwStride);
1099 handle_xyzrhw(position);
1102 if (TRACE_ON(ddraw)) {
1103 int tex_index;
1105 if ((d3dvtVertexType & D3DFVF_POSITION_MASK) == D3DFVF_XYZ) {
1106 D3DVALUE *position =
1107 (D3DVALUE *) (((char *) lpD3DDrawPrimStrideData->position.lpvData) + i * lpD3DDrawPrimStrideData->position.dwStride);
1108 TRACE(" %f %f %f", position[0], position[1], position[2]);
1109 } else if ((d3dvtVertexType & D3DFVF_POSITION_MASK) == D3DFVF_XYZRHW) {
1110 D3DVALUE *position =
1111 (D3DVALUE *) (((char *) lpD3DDrawPrimStrideData->position.lpvData) + i * lpD3DDrawPrimStrideData->position.dwStride);
1112 TRACE(" %f %f %f %f", position[0], position[1], position[2], position[3]);
1114 if (d3dvtVertexType & D3DFVF_NORMAL) {
1115 D3DVALUE *normal =
1116 (D3DVALUE *) (((char *) lpD3DDrawPrimStrideData->normal.lpvData) + i * lpD3DDrawPrimStrideData->normal.dwStride);
1117 DPRINTF(" / %f %f %f", normal[0], normal[1], normal[2]);
1119 if (d3dvtVertexType & D3DFVF_DIFFUSE) {
1120 DWORD *color_d =
1121 (DWORD *) (((char *) lpD3DDrawPrimStrideData->diffuse.lpvData) + i * lpD3DDrawPrimStrideData->diffuse.dwStride);
1122 DPRINTF(" / %02lx %02lx %02lx %02lx",
1123 (*color_d >> 16) & 0xFF,
1124 (*color_d >> 8) & 0xFF,
1125 (*color_d >> 0) & 0xFF,
1126 (*color_d >> 24) & 0xFF);
1128 if (d3dvtVertexType & D3DFVF_SPECULAR) {
1129 DWORD *color_s =
1130 (DWORD *) (((char *) lpD3DDrawPrimStrideData->specular.lpvData) + i * lpD3DDrawPrimStrideData->specular.dwStride);
1131 DPRINTF(" / %02lx %02lx %02lx %02lx",
1132 (*color_s >> 16) & 0xFF,
1133 (*color_s >> 8) & 0xFF,
1134 (*color_s >> 0) & 0xFF,
1135 (*color_s >> 24) & 0xFF);
1137 for (tex_index = 0; tex_index < ((d3dvtVertexType & D3DFVF_TEXCOUNT_MASK) >> D3DFVF_TEXCOUNT_SHIFT); tex_index++) {
1138 D3DVALUE *tex_coord =
1139 (D3DVALUE *) (((char *) lpD3DDrawPrimStrideData->textureCoords[tex_index].lpvData) +
1140 i * lpD3DDrawPrimStrideData->textureCoords[tex_index].dwStride);
1141 DPRINTF(" / %f %f", tex_coord[0], tex_coord[1]);
1143 DPRINTF("\n");
1146 } else {
1147 ERR(" matrix weighting not handled yet....\n");
1150 glEnd();
1151 LEAVE_GL();
1152 TRACE("End\n");
1155 static void draw_primitive_7(IDirect3DDeviceImpl *This,
1156 D3DPRIMITIVETYPE d3dptPrimitiveType,
1157 DWORD d3dvtVertexType,
1158 LPVOID lpvVertices,
1159 DWORD dwStartVertex,
1160 DWORD dwVertexCount,
1161 LPWORD dwIndices,
1162 DWORD dwIndexCount,
1163 DWORD dwFlags)
1165 D3DDRAWPRIMITIVESTRIDEDDATA strided;
1166 int current_offset = 0;
1167 int tex_index;
1169 if ((d3dvtVertexType & D3DFVF_POSITION_MASK) == D3DFVF_XYZ) {
1170 strided.position.lpvData = lpvVertices;
1171 current_offset += 3 * sizeof(D3DVALUE);
1172 } else {
1173 strided.position.lpvData = lpvVertices;
1174 current_offset += 4 * sizeof(D3DVALUE);
1176 if (d3dvtVertexType & D3DFVF_NORMAL) {
1177 strided.normal.lpvData = ((char *) lpvVertices) + current_offset;
1178 current_offset += 3 * sizeof(D3DVALUE);
1180 if (d3dvtVertexType & D3DFVF_DIFFUSE) {
1181 strided.diffuse.lpvData = ((char *) lpvVertices) + current_offset;
1182 current_offset += sizeof(DWORD);
1184 if (d3dvtVertexType & D3DFVF_SPECULAR) {
1185 strided.specular.lpvData = ((char *) lpvVertices) + current_offset;
1186 current_offset += sizeof(DWORD);
1188 for (tex_index = 0; tex_index < ((d3dvtVertexType & D3DFVF_TEXCOUNT_MASK) >> D3DFVF_TEXCOUNT_SHIFT); tex_index++) {
1189 strided.textureCoords[tex_index].lpvData = ((char *) lpvVertices) + current_offset;
1190 current_offset += 2 * sizeof(D3DVALUE);
1192 strided.position.dwStride = current_offset;
1193 strided.normal.dwStride = current_offset;
1194 strided.diffuse.dwStride = current_offset;
1195 strided.specular.dwStride = current_offset;
1196 for (tex_index = 0; tex_index < ((d3dvtVertexType & D3DFVF_TEXCOUNT_MASK) >> D3DFVF_TEXCOUNT_SHIFT); tex_index++)
1197 strided.textureCoords[tex_index].dwStride = current_offset;
1199 draw_primitive_strided_7(This, d3dptPrimitiveType, d3dvtVertexType, &strided, dwStartVertex, dwVertexCount, dwIndices, dwIndexCount, dwFlags);
1202 HRESULT WINAPI
1203 GL_IDirect3DDeviceImpl_7_3T_DrawPrimitive(LPDIRECT3DDEVICE7 iface,
1204 D3DPRIMITIVETYPE d3dptPrimitiveType,
1205 DWORD d3dvtVertexType,
1206 LPVOID lpvVertices,
1207 DWORD dwVertexCount,
1208 DWORD dwFlags)
1210 ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice7, iface);
1211 TRACE("(%p/%p)->(%08x,%08lx,%p,%08lx,%08lx)\n", This, iface, d3dptPrimitiveType, d3dvtVertexType, lpvVertices, dwVertexCount, dwFlags);
1213 draw_primitive_7(This, d3dptPrimitiveType, d3dvtVertexType, lpvVertices, 0, dwVertexCount, NULL, dwVertexCount, dwFlags);
1215 return DD_OK;
1218 HRESULT WINAPI
1219 GL_IDirect3DDeviceImpl_7_3T_DrawIndexedPrimitive(LPDIRECT3DDEVICE7 iface,
1220 D3DPRIMITIVETYPE d3dptPrimitiveType,
1221 DWORD d3dvtVertexType,
1222 LPVOID lpvVertices,
1223 DWORD dwVertexCount,
1224 LPWORD dwIndices,
1225 DWORD dwIndexCount,
1226 DWORD dwFlags)
1228 ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice7, iface);
1229 TRACE("(%p/%p)->(%08x,%08lx,%p,%08lx,%p,%08lx,%08lx)\n", This, iface, d3dptPrimitiveType, d3dvtVertexType, lpvVertices, dwVertexCount, dwIndices, dwIndexCount, dwFlags);
1231 draw_primitive_7(This, d3dptPrimitiveType, d3dvtVertexType, lpvVertices, 0, dwVertexCount, dwIndices, dwIndexCount, dwFlags);
1233 return DD_OK;
1236 HRESULT WINAPI
1237 GL_IDirect3DDeviceImpl_7_3T_DrawPrimitiveStrided(LPDIRECT3DDEVICE7 iface,
1238 D3DPRIMITIVETYPE d3dptPrimitiveType,
1239 DWORD dwVertexType,
1240 LPD3DDRAWPRIMITIVESTRIDEDDATA lpD3DDrawPrimStrideData,
1241 DWORD dwVertexCount,
1242 DWORD dwFlags)
1244 ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice7, iface);
1245 TRACE("(%p/%p)->(%08x,%08lx,%p,%08lx,%08lx)\n", This, iface, d3dptPrimitiveType, dwVertexType, lpD3DDrawPrimStrideData, dwVertexCount, dwFlags);
1246 draw_primitive_strided_7(This, d3dptPrimitiveType, dwVertexType, lpD3DDrawPrimStrideData, 0, dwVertexCount, NULL, dwVertexCount, dwFlags);
1247 return DD_OK;
1250 HRESULT WINAPI
1251 GL_IDirect3DDeviceImpl_7_3T_DrawIndexedPrimitiveStrided(LPDIRECT3DDEVICE7 iface,
1252 D3DPRIMITIVETYPE d3dptPrimitiveType,
1253 DWORD dwVertexType,
1254 LPD3DDRAWPRIMITIVESTRIDEDDATA lpD3DDrawPrimStrideData,
1255 DWORD dwVertexCount,
1256 LPWORD lpIndex,
1257 DWORD dwIndexCount,
1258 DWORD dwFlags)
1260 ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice7, iface);
1261 TRACE("(%p/%p)->(%08x,%08lx,%p,%08lx,%p,%08lx,%08lx)\n", This, iface, d3dptPrimitiveType, dwVertexType, lpD3DDrawPrimStrideData, dwVertexCount, lpIndex, dwIndexCount, dwFlags);
1262 draw_primitive_strided_7(This, d3dptPrimitiveType, dwVertexType, lpD3DDrawPrimStrideData, 0, dwVertexCount, lpIndex, dwIndexCount, dwFlags);
1263 return DD_OK;
1266 HRESULT WINAPI
1267 GL_IDirect3DDeviceImpl_7_3T_DrawPrimitiveVB(LPDIRECT3DDEVICE7 iface,
1268 D3DPRIMITIVETYPE d3dptPrimitiveType,
1269 LPDIRECT3DVERTEXBUFFER7 lpD3DVertexBuf,
1270 DWORD dwStartVertex,
1271 DWORD dwNumVertices,
1272 DWORD dwFlags)
1274 ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice7, iface);
1275 IDirect3DVertexBufferImpl *vb_impl = ICOM_OBJECT(IDirect3DVertexBufferImpl, IDirect3DVertexBuffer7, lpD3DVertexBuf);
1277 TRACE("(%p/%p)->(%08x,%p,%08lx,%08lx,%08lx)\n", This, iface, d3dptPrimitiveType, lpD3DVertexBuf, dwStartVertex, dwNumVertices, dwFlags);
1279 draw_primitive_7(This, d3dptPrimitiveType, vb_impl->desc.dwFVF, vb_impl->vertices, dwStartVertex, dwNumVertices, NULL, dwNumVertices, dwFlags);
1281 return DD_OK;
1284 HRESULT WINAPI
1285 GL_IDirect3DDeviceImpl_7_3T_DrawIndexedPrimitiveVB(LPDIRECT3DDEVICE7 iface,
1286 D3DPRIMITIVETYPE d3dptPrimitiveType,
1287 LPDIRECT3DVERTEXBUFFER7 lpD3DVertexBuf,
1288 DWORD dwStartVertex,
1289 DWORD dwNumVertices,
1290 LPWORD lpwIndices,
1291 DWORD dwIndexCount,
1292 DWORD dwFlags)
1294 ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice7, iface);
1295 IDirect3DVertexBufferImpl *vb_impl = ICOM_OBJECT(IDirect3DVertexBufferImpl, IDirect3DVertexBuffer7, lpD3DVertexBuf);
1297 TRACE("(%p/%p)->(%08x,%p,%08lx,%08lx,%p,%08lx,%08lx)\n", This, iface, d3dptPrimitiveType, lpD3DVertexBuf, dwStartVertex, dwNumVertices, lpwIndices, dwIndexCount, dwFlags);
1299 draw_primitive_7(This, d3dptPrimitiveType, vb_impl->desc.dwFVF, vb_impl->vertices, dwStartVertex, dwNumVertices, lpwIndices, dwIndexCount, dwFlags);
1301 return DD_OK;
1304 HRESULT WINAPI
1305 GL_IDirect3DDeviceImpl_7_3T_SetTextureStageState(LPDIRECT3DDEVICE7 iface,
1306 DWORD dwStage,
1307 D3DTEXTURESTAGESTATETYPE d3dTexStageStateType,
1308 DWORD dwState)
1310 ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice7, iface);
1311 IDirect3DDeviceGLImpl *glThis = (IDirect3DDeviceGLImpl *) This;
1312 GLenum gl_state;
1314 TRACE("(%p/%p)->(%08lx,%08x,%08lx)\n", This, iface, dwStage, d3dTexStageStateType, dwState);
1316 if (TRACE_ON(ddraw)) {
1317 TRACE(" Stage type is : ");
1318 switch (d3dTexStageStateType) {
1319 #define GEN_CASE(a) case a: DPRINTF(#a " "); break
1320 GEN_CASE(D3DTSS_COLOROP);
1321 GEN_CASE(D3DTSS_COLORARG1);
1322 GEN_CASE(D3DTSS_COLORARG2);
1323 GEN_CASE(D3DTSS_ALPHAOP);
1324 GEN_CASE(D3DTSS_ALPHAARG1);
1325 GEN_CASE(D3DTSS_ALPHAARG2);
1326 GEN_CASE(D3DTSS_BUMPENVMAT00);
1327 GEN_CASE(D3DTSS_BUMPENVMAT01);
1328 GEN_CASE(D3DTSS_BUMPENVMAT10);
1329 GEN_CASE(D3DTSS_BUMPENVMAT11);
1330 GEN_CASE(D3DTSS_TEXCOORDINDEX);
1331 GEN_CASE(D3DTSS_ADDRESS);
1332 GEN_CASE(D3DTSS_ADDRESSU);
1333 GEN_CASE(D3DTSS_ADDRESSV);
1334 GEN_CASE(D3DTSS_BORDERCOLOR);
1335 GEN_CASE(D3DTSS_MAGFILTER);
1336 GEN_CASE(D3DTSS_MINFILTER);
1337 GEN_CASE(D3DTSS_MIPFILTER);
1338 GEN_CASE(D3DTSS_MIPMAPLODBIAS);
1339 GEN_CASE(D3DTSS_MAXMIPLEVEL);
1340 GEN_CASE(D3DTSS_MAXANISOTROPY);
1341 GEN_CASE(D3DTSS_BUMPENVLSCALE);
1342 GEN_CASE(D3DTSS_BUMPENVLOFFSET);
1343 GEN_CASE(D3DTSS_TEXTURETRANSFORMFLAGS);
1344 #undef GEN_CASE
1345 default: DPRINTF("UNKNOWN !!!");
1347 DPRINTF(" => ");
1350 switch (d3dTexStageStateType) {
1351 case D3DTSS_MINFILTER:
1352 switch ((D3DTEXTUREMINFILTER) dwState) {
1353 case D3DTFN_POINT:
1354 if (TRACE_ON(ddraw)) DPRINTF("D3DTFN_POINT\n");
1355 gl_state = GL_NEAREST;
1356 break;
1357 case D3DTFN_LINEAR:
1358 if (TRACE_ON(ddraw)) DPRINTF("D3DTFN_LINEAR\n");
1359 gl_state = GL_LINEAR;
1360 break;
1361 default:
1362 if (TRACE_ON(ddraw)) DPRINTF(" state unhandled (%ld).\n", dwState);
1363 gl_state = GL_LINEAR;
1364 break;
1366 glThis->render_state.min = gl_state;
1367 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, gl_state);
1368 break;
1370 case D3DTSS_MAGFILTER:
1371 switch ((D3DTEXTUREMAGFILTER) dwState) {
1372 case D3DTFG_POINT:
1373 if (TRACE_ON(ddraw)) DPRINTF("D3DTFG_POINT\n");
1374 gl_state = GL_NEAREST;
1375 break;
1376 case D3DTFG_LINEAR:
1377 if (TRACE_ON(ddraw)) DPRINTF("D3DTFG_LINEAR\n");
1378 gl_state = GL_LINEAR;
1379 break;
1380 default:
1381 if (TRACE_ON(ddraw)) DPRINTF(" state unhandled (%ld).\n", dwState);
1382 gl_state = GL_LINEAR;
1383 break;
1385 glThis->render_state.mag = gl_state;
1386 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, gl_state);
1387 break;
1389 case D3DTSS_ADDRESS:
1390 case D3DTSS_ADDRESSU:
1391 case D3DTSS_ADDRESSV: {
1392 GLenum arg = GL_REPEAT; /* Default value */
1393 switch ((D3DTEXTUREADDRESS) dwState) {
1394 case D3DTADDRESS_WRAP: if (TRACE_ON(ddraw)) DPRINTF("D3DTADDRESS_WRAP\n"); arg = GL_REPEAT; break;
1395 case D3DTADDRESS_CLAMP: if (TRACE_ON(ddraw)) DPRINTF("D3DTADDRESS_CLAMP\n"); arg = GL_CLAMP; break;
1396 case D3DTADDRESS_BORDER: if (TRACE_ON(ddraw)) DPRINTF("D3DTADDRESS_BORDER\n"); arg = GL_CLAMP_TO_EDGE; break;
1397 default: DPRINTF(" state unhandled (%ld).\n", dwState);
1399 if ((d3dTexStageStateType == D3DTSS_ADDRESS) ||
1400 (d3dTexStageStateType == D3DTSS_ADDRESSU))
1401 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, arg);
1402 if ((d3dTexStageStateType == D3DTSS_ADDRESS) ||
1403 (d3dTexStageStateType == D3DTSS_ADDRESSV))
1404 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, arg);
1405 } break;
1407 default:
1408 if (TRACE_ON(ddraw)) DPRINTF(" unhandled.\n");
1411 return DD_OK;
1414 HRESULT WINAPI
1415 GL_IDirect3DDeviceImpl_7_3T_SetTexture(LPDIRECT3DDEVICE7 iface,
1416 DWORD dwStage,
1417 LPDIRECTDRAWSURFACE7 lpTexture2)
1419 ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice7, iface);
1420 IDirect3DDeviceGLImpl *glThis = (IDirect3DDeviceGLImpl *) This;
1422 TRACE("(%p/%p)->(%08lx,%p)\n", This, iface, dwStage, lpTexture2);
1424 if (This->current_texture[dwStage] != NULL) {
1425 /* Seems that this is not right... Need to test in real Windows
1426 IDirect3DTexture2_Release(ICOM_INTERFACE(This->current_texture[dwStage], IDirect3DTexture2)); */
1429 ENTER_GL();
1430 if (lpTexture2 == NULL) {
1431 TRACE(" disabling 2D texturing.\n");
1432 glBindTexture(GL_TEXTURE_2D, 0);
1433 glDisable(GL_TEXTURE_2D);
1434 } else {
1435 IDirectDrawSurfaceImpl *tex_impl = ICOM_OBJECT(IDirectDrawSurfaceImpl, IDirectDrawSurface7, lpTexture2);
1436 IDirect3DTextureGLImpl *tex_glimpl = (IDirect3DTextureGLImpl *) tex_impl->tex_private;
1438 This->current_texture[dwStage] = tex_impl;
1439 IDirectDrawSurface7_AddRef(ICOM_INTERFACE(tex_impl, IDirectDrawSurface7)); /* Not sure about this either */
1441 TRACE(" activating OpenGL texture %d.\n", tex_glimpl->tex_name);
1443 glEnable(GL_TEXTURE_2D);
1444 glBindTexture(GL_TEXTURE_2D, tex_glimpl->tex_name);
1445 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, glThis->render_state.mag);
1446 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, glThis->render_state.min);
1448 LEAVE_GL();
1450 return DD_OK;
1453 HRESULT WINAPI
1454 GL_IDirect3DDeviceImpl_7_GetCaps(LPDIRECT3DDEVICE7 iface,
1455 LPD3DDEVICEDESC7 lpD3DHELDevDesc)
1457 ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice7, iface);
1458 TRACE("(%p/%p)->(%p)\n", This, iface, lpD3DHELDevDesc);
1460 fill_opengl_caps_7(lpD3DHELDevDesc);
1462 TRACE(" returning caps : no dump function yet.\n");
1464 return DD_OK;
1467 HRESULT WINAPI
1468 GL_IDirect3DDeviceImpl_7_SetMaterial(LPDIRECT3DDEVICE7 iface,
1469 LPD3DMATERIAL7 lpMat)
1471 ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice7, iface);
1472 TRACE("(%p/%p)->(%p)\n", This, iface, lpMat);
1474 if (TRACE_ON(ddraw)) {
1475 TRACE(" material is : \n");
1476 dump_D3DMATERIAL7(lpMat);
1479 This->current_material = *lpMat;
1481 glMaterialfv(GL_FRONT,
1482 GL_DIFFUSE,
1483 (float *) &(This->current_material.u.diffuse));
1484 glMaterialfv(GL_FRONT,
1485 GL_AMBIENT,
1486 (float *) &(This->current_material.u1.ambient));
1487 glMaterialfv(GL_FRONT,
1488 GL_SPECULAR,
1489 (float *) &(This->current_material.u2.specular));
1490 glMaterialfv(GL_FRONT,
1491 GL_EMISSION,
1492 (float *) &(This->current_material.u3.emissive));
1493 glMaterialf(GL_FRONT,
1494 GL_SHININESS,
1495 This->current_material.u4.power); /* Not sure about this... */
1497 return DD_OK;
1501 HRESULT WINAPI
1502 GL_IDirect3DDeviceImpl_7_SetLight(LPDIRECT3DDEVICE7 iface,
1503 DWORD dwLightIndex,
1504 LPD3DLIGHT7 lpLight)
1506 ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice7, iface);
1507 TRACE("(%p/%p)->(%08lx,%p)\n", This, iface, dwLightIndex, lpLight);
1509 if (TRACE_ON(ddraw)) {
1510 TRACE(" setting light : \n");
1511 dump_D3DLIGHT7(lpLight);
1514 if (dwLightIndex > MAX_LIGHTS) return DDERR_INVALIDPARAMS;
1515 This->set_lights |= 0x00000001 << dwLightIndex;
1516 This->light_parameters[dwLightIndex] = *lpLight;
1518 switch (lpLight->dltType) {
1519 case D3DLIGHT_DIRECTIONAL: { /* 3 */
1520 float direction[4];
1522 glLightfv(GL_LIGHT0 + dwLightIndex, GL_AMBIENT, (float *) &(lpLight->dcvAmbient));
1523 glLightfv(GL_LIGHT0 + dwLightIndex, GL_DIFFUSE, (float *) &(lpLight->dcvDiffuse));
1524 glLightfv(GL_LIGHT0 + dwLightIndex, GL_SPECULAR, (float *) &(lpLight->dcvSpecular));
1526 direction[0] = lpLight->dvDirection.u1.x;
1527 direction[1] = lpLight->dvDirection.u2.y;
1528 direction[2] = lpLight->dvDirection.u3.z;
1529 direction[3] = 0.0; /* This is a directional light */
1531 glLightfv(GL_LIGHT0 + dwLightIndex, GL_POSITION, (float *) direction);
1532 } break;
1534 default: WARN(" light type not handled yet...\n");
1537 return DD_OK;
1540 HRESULT WINAPI
1541 GL_IDirect3DDeviceImpl_7_LightEnable(LPDIRECT3DDEVICE7 iface,
1542 DWORD dwLightIndex,
1543 BOOL bEnable)
1545 ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice7, iface);
1546 TRACE("(%p/%p)->(%08lx,%d)\n", This, iface, dwLightIndex, bEnable);
1548 if (dwLightIndex > MAX_LIGHTS) return DDERR_INVALIDPARAMS;
1550 if (bEnable) {
1551 if (((0x00000001 << dwLightIndex) & This->set_lights) == 0) {
1552 /* Set the default parameters.. */
1553 TRACE(" setting default light parameters...\n");
1554 GL_IDirect3DDeviceImpl_7_SetLight(iface, dwLightIndex, &(This->light_parameters[dwLightIndex]));
1556 glEnable(GL_LIGHT0 + dwLightIndex);
1557 } else {
1558 glDisable(GL_LIGHT0 + dwLightIndex);
1561 return DD_OK;
1564 #if !defined(__STRICT_ANSI__) && defined(__GNUC__)
1565 # define XCAST(fun) (typeof(VTABLE_IDirect3DDevice7.fun))
1566 #else
1567 # define XCAST(fun) (void*)
1568 #endif
1570 ICOM_VTABLE(IDirect3DDevice7) VTABLE_IDirect3DDevice7 =
1572 ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
1573 XCAST(QueryInterface) Main_IDirect3DDeviceImpl_7_3T_2T_1T_QueryInterface,
1574 XCAST(AddRef) Main_IDirect3DDeviceImpl_7_3T_2T_1T_AddRef,
1575 XCAST(Release) GL_IDirect3DDeviceImpl_7_3T_2T_1T_Release,
1576 XCAST(GetCaps) GL_IDirect3DDeviceImpl_7_GetCaps,
1577 XCAST(EnumTextureFormats) GL_IDirect3DDeviceImpl_7_3T_EnumTextureFormats,
1578 XCAST(BeginScene) Main_IDirect3DDeviceImpl_7_3T_2T_1T_BeginScene,
1579 XCAST(EndScene) Main_IDirect3DDeviceImpl_7_3T_2T_1T_EndScene,
1580 XCAST(GetDirect3D) Main_IDirect3DDeviceImpl_7_3T_2T_1T_GetDirect3D,
1581 XCAST(SetRenderTarget) Main_IDirect3DDeviceImpl_7_3T_2T_SetRenderTarget,
1582 XCAST(GetRenderTarget) Main_IDirect3DDeviceImpl_7_3T_2T_GetRenderTarget,
1583 XCAST(Clear) Main_IDirect3DDeviceImpl_7_Clear,
1584 XCAST(SetTransform) GL_IDirect3DDeviceImpl_7_3T_2T_SetTransform,
1585 XCAST(GetTransform) Main_IDirect3DDeviceImpl_7_3T_2T_GetTransform,
1586 XCAST(SetViewport) Main_IDirect3DDeviceImpl_7_SetViewport,
1587 XCAST(MultiplyTransform) Main_IDirect3DDeviceImpl_7_3T_2T_MultiplyTransform,
1588 XCAST(GetViewport) Main_IDirect3DDeviceImpl_7_GetViewport,
1589 XCAST(SetMaterial) GL_IDirect3DDeviceImpl_7_SetMaterial,
1590 XCAST(GetMaterial) Main_IDirect3DDeviceImpl_7_GetMaterial,
1591 XCAST(SetLight) GL_IDirect3DDeviceImpl_7_SetLight,
1592 XCAST(GetLight) Main_IDirect3DDeviceImpl_7_GetLight,
1593 XCAST(SetRenderState) GL_IDirect3DDeviceImpl_7_3T_2T_SetRenderState,
1594 XCAST(GetRenderState) Main_IDirect3DDeviceImpl_7_3T_2T_GetRenderState,
1595 XCAST(BeginStateBlock) Main_IDirect3DDeviceImpl_7_BeginStateBlock,
1596 XCAST(EndStateBlock) Main_IDirect3DDeviceImpl_7_EndStateBlock,
1597 XCAST(PreLoad) Main_IDirect3DDeviceImpl_7_PreLoad,
1598 XCAST(DrawPrimitive) GL_IDirect3DDeviceImpl_7_3T_DrawPrimitive,
1599 XCAST(DrawIndexedPrimitive) GL_IDirect3DDeviceImpl_7_3T_DrawIndexedPrimitive,
1600 XCAST(SetClipStatus) Main_IDirect3DDeviceImpl_7_3T_2T_SetClipStatus,
1601 XCAST(GetClipStatus) Main_IDirect3DDeviceImpl_7_3T_2T_GetClipStatus,
1602 XCAST(DrawPrimitiveStrided) GL_IDirect3DDeviceImpl_7_3T_DrawPrimitiveStrided,
1603 XCAST(DrawIndexedPrimitiveStrided) GL_IDirect3DDeviceImpl_7_3T_DrawIndexedPrimitiveStrided,
1604 XCAST(DrawPrimitiveVB) GL_IDirect3DDeviceImpl_7_3T_DrawPrimitiveVB,
1605 XCAST(DrawIndexedPrimitiveVB) GL_IDirect3DDeviceImpl_7_3T_DrawIndexedPrimitiveVB,
1606 XCAST(ComputeSphereVisibility) Main_IDirect3DDeviceImpl_7_3T_ComputeSphereVisibility,
1607 XCAST(GetTexture) Main_IDirect3DDeviceImpl_7_3T_GetTexture,
1608 XCAST(SetTexture) GL_IDirect3DDeviceImpl_7_3T_SetTexture,
1609 XCAST(GetTextureStageState) Main_IDirect3DDeviceImpl_7_3T_GetTextureStageState,
1610 XCAST(SetTextureStageState) GL_IDirect3DDeviceImpl_7_3T_SetTextureStageState,
1611 XCAST(ValidateDevice) Main_IDirect3DDeviceImpl_7_3T_ValidateDevice,
1612 XCAST(ApplyStateBlock) Main_IDirect3DDeviceImpl_7_ApplyStateBlock,
1613 XCAST(CaptureStateBlock) Main_IDirect3DDeviceImpl_7_CaptureStateBlock,
1614 XCAST(DeleteStateBlock) Main_IDirect3DDeviceImpl_7_DeleteStateBlock,
1615 XCAST(CreateStateBlock) Main_IDirect3DDeviceImpl_7_CreateStateBlock,
1616 XCAST(Load) Main_IDirect3DDeviceImpl_7_Load,
1617 XCAST(LightEnable) GL_IDirect3DDeviceImpl_7_LightEnable,
1618 XCAST(GetLightEnable) Main_IDirect3DDeviceImpl_7_GetLightEnable,
1619 XCAST(SetClipPlane) Main_IDirect3DDeviceImpl_7_SetClipPlane,
1620 XCAST(GetClipPlane) Main_IDirect3DDeviceImpl_7_GetClipPlane,
1621 XCAST(GetInfo) Main_IDirect3DDeviceImpl_7_GetInfo,
1624 #if !defined(__STRICT_ANSI__) && defined(__GNUC__)
1625 #undef XCAST
1626 #endif
1629 #if !defined(__STRICT_ANSI__) && defined(__GNUC__)
1630 # define XCAST(fun) (typeof(VTABLE_IDirect3DDevice3.fun))
1631 #else
1632 # define XCAST(fun) (void*)
1633 #endif
1635 ICOM_VTABLE(IDirect3DDevice3) VTABLE_IDirect3DDevice3 =
1637 ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
1638 XCAST(QueryInterface) Thunk_IDirect3DDeviceImpl_3_QueryInterface,
1639 XCAST(AddRef) Thunk_IDirect3DDeviceImpl_3_AddRef,
1640 XCAST(Release) Thunk_IDirect3DDeviceImpl_3_Release,
1641 XCAST(GetCaps) GL_IDirect3DDeviceImpl_3_2T_1T_GetCaps,
1642 XCAST(GetStats) Main_IDirect3DDeviceImpl_3_2T_1T_GetStats,
1643 XCAST(AddViewport) Main_IDirect3DDeviceImpl_3_2T_1T_AddViewport,
1644 XCAST(DeleteViewport) Main_IDirect3DDeviceImpl_3_2T_1T_DeleteViewport,
1645 XCAST(NextViewport) Main_IDirect3DDeviceImpl_3_2T_1T_NextViewport,
1646 XCAST(EnumTextureFormats) Thunk_IDirect3DDeviceImpl_3_EnumTextureFormats,
1647 XCAST(BeginScene) Thunk_IDirect3DDeviceImpl_3_BeginScene,
1648 XCAST(EndScene) Thunk_IDirect3DDeviceImpl_3_EndScene,
1649 XCAST(GetDirect3D) Thunk_IDirect3DDeviceImpl_3_GetDirect3D,
1650 XCAST(SetCurrentViewport) Main_IDirect3DDeviceImpl_3_2T_SetCurrentViewport,
1651 XCAST(GetCurrentViewport) Main_IDirect3DDeviceImpl_3_2T_GetCurrentViewport,
1652 XCAST(SetRenderTarget) Thunk_IDirect3DDeviceImpl_3_SetRenderTarget,
1653 XCAST(GetRenderTarget) Thunk_IDirect3DDeviceImpl_3_GetRenderTarget,
1654 XCAST(Begin) Main_IDirect3DDeviceImpl_3_Begin,
1655 XCAST(BeginIndexed) Main_IDirect3DDeviceImpl_3_BeginIndexed,
1656 XCAST(Vertex) Main_IDirect3DDeviceImpl_3_2T_Vertex,
1657 XCAST(Index) Main_IDirect3DDeviceImpl_3_2T_Index,
1658 XCAST(End) Main_IDirect3DDeviceImpl_3_2T_End,
1659 XCAST(GetRenderState) Thunk_IDirect3DDeviceImpl_3_GetRenderState,
1660 XCAST(SetRenderState) Thunk_IDirect3DDeviceImpl_3_SetRenderState,
1661 XCAST(GetLightState) Main_IDirect3DDeviceImpl_3_2T_GetLightState,
1662 XCAST(SetLightState) GL_IDirect3DDeviceImpl_3_2T_SetLightState,
1663 XCAST(SetTransform) Thunk_IDirect3DDeviceImpl_3_SetTransform,
1664 XCAST(GetTransform) Thunk_IDirect3DDeviceImpl_3_GetTransform,
1665 XCAST(MultiplyTransform) Thunk_IDirect3DDeviceImpl_3_MultiplyTransform,
1666 XCAST(DrawPrimitive) Thunk_IDirect3DDeviceImpl_3_DrawPrimitive,
1667 XCAST(DrawIndexedPrimitive) Thunk_IDirect3DDeviceImpl_3_DrawIndexedPrimitive,
1668 XCAST(SetClipStatus) Thunk_IDirect3DDeviceImpl_3_SetClipStatus,
1669 XCAST(GetClipStatus) Thunk_IDirect3DDeviceImpl_3_GetClipStatus,
1670 XCAST(DrawPrimitiveStrided) Thunk_IDirect3DDeviceImpl_3_DrawPrimitiveStrided,
1671 XCAST(DrawIndexedPrimitiveStrided) Thunk_IDirect3DDeviceImpl_3_DrawIndexedPrimitiveStrided,
1672 XCAST(DrawPrimitiveVB) Thunk_IDirect3DDeviceImpl_3_DrawPrimitiveVB,
1673 XCAST(DrawIndexedPrimitiveVB) Thunk_IDirect3DDeviceImpl_3_DrawIndexedPrimitiveVB,
1674 XCAST(ComputeSphereVisibility) Thunk_IDirect3DDeviceImpl_3_ComputeSphereVisibility,
1675 XCAST(GetTexture) Thunk_IDirect3DDeviceImpl_3_GetTexture,
1676 XCAST(SetTexture) Thunk_IDirect3DDeviceImpl_3_SetTexture,
1677 XCAST(GetTextureStageState) Thunk_IDirect3DDeviceImpl_3_GetTextureStageState,
1678 XCAST(SetTextureStageState) Thunk_IDirect3DDeviceImpl_3_SetTextureStageState,
1679 XCAST(ValidateDevice) Thunk_IDirect3DDeviceImpl_3_ValidateDevice,
1682 #if !defined(__STRICT_ANSI__) && defined(__GNUC__)
1683 #undef XCAST
1684 #endif
1687 #if !defined(__STRICT_ANSI__) && defined(__GNUC__)
1688 # define XCAST(fun) (typeof(VTABLE_IDirect3DDevice2.fun))
1689 #else
1690 # define XCAST(fun) (void*)
1691 #endif
1693 ICOM_VTABLE(IDirect3DDevice2) VTABLE_IDirect3DDevice2 =
1695 ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
1696 XCAST(QueryInterface) Thunk_IDirect3DDeviceImpl_2_QueryInterface,
1697 XCAST(AddRef) Thunk_IDirect3DDeviceImpl_2_AddRef,
1698 XCAST(Release) Thunk_IDirect3DDeviceImpl_2_Release,
1699 XCAST(GetCaps) Thunk_IDirect3DDeviceImpl_2_GetCaps,
1700 XCAST(SwapTextureHandles) Main_IDirect3DDeviceImpl_2_SwapTextureHandles,
1701 XCAST(GetStats) Thunk_IDirect3DDeviceImpl_2_GetStats,
1702 XCAST(AddViewport) Thunk_IDirect3DDeviceImpl_2_AddViewport,
1703 XCAST(DeleteViewport) Thunk_IDirect3DDeviceImpl_2_DeleteViewport,
1704 XCAST(NextViewport) Thunk_IDirect3DDeviceImpl_2_NextViewport,
1705 XCAST(EnumTextureFormats) GL_IDirect3DDeviceImpl_2_1T_EnumTextureFormats,
1706 XCAST(BeginScene) Thunk_IDirect3DDeviceImpl_2_BeginScene,
1707 XCAST(EndScene) Thunk_IDirect3DDeviceImpl_2_EndScene,
1708 XCAST(GetDirect3D) Thunk_IDirect3DDeviceImpl_2_GetDirect3D,
1709 XCAST(SetCurrentViewport) Thunk_IDirect3DDeviceImpl_2_SetCurrentViewport,
1710 XCAST(GetCurrentViewport) Thunk_IDirect3DDeviceImpl_2_GetCurrentViewport,
1711 XCAST(SetRenderTarget) Thunk_IDirect3DDeviceImpl_2_SetRenderTarget,
1712 XCAST(GetRenderTarget) Thunk_IDirect3DDeviceImpl_2_GetRenderTarget,
1713 XCAST(Begin) Main_IDirect3DDeviceImpl_2_Begin,
1714 XCAST(BeginIndexed) Main_IDirect3DDeviceImpl_2_BeginIndexed,
1715 XCAST(Vertex) Thunk_IDirect3DDeviceImpl_2_Vertex,
1716 XCAST(Index) Thunk_IDirect3DDeviceImpl_2_Index,
1717 XCAST(End) Thunk_IDirect3DDeviceImpl_2_End,
1718 XCAST(GetRenderState) Thunk_IDirect3DDeviceImpl_2_GetRenderState,
1719 XCAST(SetRenderState) Thunk_IDirect3DDeviceImpl_2_SetRenderState,
1720 XCAST(GetLightState) Thunk_IDirect3DDeviceImpl_2_GetLightState,
1721 XCAST(SetLightState) Thunk_IDirect3DDeviceImpl_2_SetLightState,
1722 XCAST(SetTransform) Thunk_IDirect3DDeviceImpl_2_SetTransform,
1723 XCAST(GetTransform) Thunk_IDirect3DDeviceImpl_2_GetTransform,
1724 XCAST(MultiplyTransform) Thunk_IDirect3DDeviceImpl_2_MultiplyTransform,
1725 XCAST(DrawPrimitive) GL_IDirect3DDeviceImpl_2_DrawPrimitive,
1726 XCAST(DrawIndexedPrimitive) GL_IDirect3DDeviceImpl_2_DrawIndexedPrimitive,
1727 XCAST(SetClipStatus) Thunk_IDirect3DDeviceImpl_2_SetClipStatus,
1728 XCAST(GetClipStatus) Thunk_IDirect3DDeviceImpl_2_GetClipStatus,
1731 #if !defined(__STRICT_ANSI__) && defined(__GNUC__)
1732 #undef XCAST
1733 #endif
1736 #if !defined(__STRICT_ANSI__) && defined(__GNUC__)
1737 # define XCAST(fun) (typeof(VTABLE_IDirect3DDevice.fun))
1738 #else
1739 # define XCAST(fun) (void*)
1740 #endif
1742 ICOM_VTABLE(IDirect3DDevice) VTABLE_IDirect3DDevice =
1744 ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
1745 XCAST(QueryInterface) Thunk_IDirect3DDeviceImpl_1_QueryInterface,
1746 XCAST(AddRef) Thunk_IDirect3DDeviceImpl_1_AddRef,
1747 XCAST(Release) Thunk_IDirect3DDeviceImpl_1_Release,
1748 XCAST(Initialize) Main_IDirect3DDeviceImpl_1_Initialize,
1749 XCAST(GetCaps) Thunk_IDirect3DDeviceImpl_1_GetCaps,
1750 XCAST(SwapTextureHandles) Main_IDirect3DDeviceImpl_1_SwapTextureHandles,
1751 XCAST(CreateExecuteBuffer) GL_IDirect3DDeviceImpl_1_CreateExecuteBuffer,
1752 XCAST(GetStats) Thunk_IDirect3DDeviceImpl_1_GetStats,
1753 XCAST(Execute) Main_IDirect3DDeviceImpl_1_Execute,
1754 XCAST(AddViewport) Thunk_IDirect3DDeviceImpl_1_AddViewport,
1755 XCAST(DeleteViewport) Thunk_IDirect3DDeviceImpl_1_DeleteViewport,
1756 XCAST(NextViewport) Thunk_IDirect3DDeviceImpl_1_NextViewport,
1757 XCAST(Pick) Main_IDirect3DDeviceImpl_1_Pick,
1758 XCAST(GetPickRecords) Main_IDirect3DDeviceImpl_1_GetPickRecords,
1759 XCAST(EnumTextureFormats) Thunk_IDirect3DDeviceImpl_1_EnumTextureFormats,
1760 XCAST(CreateMatrix) Main_IDirect3DDeviceImpl_1_CreateMatrix,
1761 XCAST(SetMatrix) Main_IDirect3DDeviceImpl_1_SetMatrix,
1762 XCAST(GetMatrix) Main_IDirect3DDeviceImpl_1_GetMatrix,
1763 XCAST(DeleteMatrix) Main_IDirect3DDeviceImpl_1_DeleteMatrix,
1764 XCAST(BeginScene) Thunk_IDirect3DDeviceImpl_1_BeginScene,
1765 XCAST(EndScene) Thunk_IDirect3DDeviceImpl_1_EndScene,
1766 XCAST(GetDirect3D) Thunk_IDirect3DDeviceImpl_1_GetDirect3D,
1769 #if !defined(__STRICT_ANSI__) && defined(__GNUC__)
1770 #undef XCAST
1771 #endif
1773 static HRESULT d3ddevice_clear(IDirect3DDeviceImpl *This,
1774 DWORD dwCount,
1775 LPD3DRECT lpRects,
1776 DWORD dwFlags,
1777 DWORD dwColor,
1778 D3DVALUE dvZ,
1779 DWORD dwStencil)
1781 GLboolean ztest;
1782 GLfloat old_z_clear_value;
1783 GLbitfield bitfield = 0;
1784 GLint old_stencil_clear_value;
1785 GLfloat old_color_clear_value[4];
1787 TRACE("(%p)->(%08lx,%p,%08lx,%08lx,%f,%08lx)\n", This, dwCount, lpRects, dwFlags, dwColor, dvZ, dwStencil);
1788 if (TRACE_ON(ddraw)) {
1789 if (dwCount > 0) {
1790 int i;
1791 TRACE(" rectangles : \n");
1792 for (i = 0; i < dwCount; i++) {
1793 TRACE(" - %ld x %ld %ld x %ld\n", lpRects[i].u1.x1, lpRects[i].u2.y1, lpRects[i].u3.x2, lpRects[i].u4.y2);
1798 if (dwCount > 1) {
1799 WARN(" Warning, this function only for now clears the whole screen...\n");
1802 /* Clears the screen */
1803 ENTER_GL();
1804 if (dwFlags & D3DCLEAR_ZBUFFER) {
1805 bitfield |= GL_DEPTH_BUFFER_BIT;
1806 glGetBooleanv(GL_DEPTH_WRITEMASK, &ztest);
1807 glDepthMask(GL_TRUE); /* Enables Z writing to be sure to delete also the Z buffer */
1808 glGetFloatv(GL_DEPTH_CLEAR_VALUE, &old_z_clear_value);
1809 glClearDepth(dvZ);
1810 TRACE(" depth value : %f\n", dvZ);
1812 if (dwFlags & D3DCLEAR_STENCIL) {
1813 bitfield |= GL_STENCIL_BUFFER_BIT;
1814 glGetIntegerv(GL_STENCIL_CLEAR_VALUE, &old_stencil_clear_value);
1815 glClearStencil(dwStencil);
1816 TRACE(" stencil value : %ld\n", dwStencil);
1818 if (dwFlags & D3DCLEAR_TARGET) {
1819 bitfield |= GL_COLOR_BUFFER_BIT;
1820 glGetFloatv(GL_COLOR_CLEAR_VALUE, old_color_clear_value);
1821 glClearColor(((dwColor >> 16) & 0xFF) / 255.0,
1822 ((dwColor >> 8) & 0xFF) / 255.0,
1823 ((dwColor >> 0) & 0xFF) / 255.0,
1824 ((dwColor >> 24) & 0xFF) / 255.0);
1825 TRACE(" color value (ARGB) : %08lx\n", dwColor);
1828 glClear(bitfield);
1830 if (dwFlags & D3DCLEAR_ZBUFFER) {
1831 glDepthMask(ztest);
1832 glClearDepth(old_z_clear_value);
1834 if (dwFlags & D3DCLEAR_STENCIL) {
1835 bitfield |= GL_STENCIL_BUFFER_BIT;
1836 glClearStencil(old_stencil_clear_value);
1838 if (dwFlags & D3DCLEAR_TARGET) {
1839 bitfield |= GL_COLOR_BUFFER_BIT;
1840 glClearColor(old_color_clear_value[0],
1841 old_color_clear_value[1],
1842 old_color_clear_value[2],
1843 old_color_clear_value[3]);
1846 LEAVE_GL();
1848 return DD_OK;
1851 HRESULT
1852 d3ddevice_blt(IDirectDrawSurfaceImpl *This, LPRECT rdst,
1853 LPDIRECTDRAWSURFACE7 src, LPRECT rsrc,
1854 DWORD dwFlags, LPDDBLTFX lpbltfx)
1856 if (dwFlags & DDBLT_COLORFILL) {
1857 /* This is easy to handle for the D3D Device... */
1858 DWORD color = lpbltfx->u5.dwFillColor;
1859 TRACE(" executing D3D Device override.\n");
1860 d3ddevice_clear(This->d3ddevice, 0, NULL, D3DCLEAR_TARGET, color, 0.0, 0x00000000);
1861 return DD_OK;
1863 return DDERR_INVALIDPARAMS;
1866 HRESULT
1867 d3ddevice_bltfast(IDirectDrawSurfaceImpl *This, DWORD dstx,
1868 DWORD dsty, LPDIRECTDRAWSURFACE7 src,
1869 LPRECT rsrc, DWORD trans)
1871 return DDERR_INVALIDPARAMS;
1875 /* TODO for both these functions :
1876 - change / restore OpenGL parameters for pictures transfers in case they are ever modified
1877 by other OpenGL code in D3D
1878 - handle the case where no 'Begin / EndScene' was done between two locks
1879 - handle the rectangles in the unlock too
1880 - handle pitch correctly...
1882 static void d3ddevice_lock_update(IDirectDrawSurfaceImpl* This, LPCRECT pRect, DWORD dwFlags)
1884 /* First, check if we need to do anything */
1885 if ((This->lastlocktype & DDLOCK_WRITEONLY) == 0) {
1886 GLenum buffer_type;
1887 GLenum prev_read;
1888 RECT loc_rect;
1890 ENTER_GL();
1892 glGetIntegerv(GL_READ_BUFFER, &prev_read);
1893 glFlush();
1895 WARN(" application does a lock on a 3D surface - expect slow downs.\n");
1896 if ((This->surface_desc.ddsCaps.dwCaps & (DDSCAPS_FRONTBUFFER|DDSCAPS_PRIMARYSURFACE)) != 0) {
1897 /* Application wants to lock the front buffer */
1898 glReadBuffer(GL_FRONT);
1899 } else if ((This->surface_desc.ddsCaps.dwCaps & (DDSCAPS_BACKBUFFER)) == (DDSCAPS_BACKBUFFER)) {
1900 /* Application wants to lock the back buffer */
1901 glReadBuffer(GL_BACK);
1902 } else {
1903 WARN(" do not support 3D surface locking for this surface type - trying to use default buffer.\n");
1906 if (This->surface_desc.u4.ddpfPixelFormat.u1.dwRGBBitCount == 16) {
1907 buffer_type = GL_UNSIGNED_SHORT_5_6_5;
1908 } else {
1909 WARN(" unsupported pixel format.\n");
1910 LEAVE_GL();
1911 return;
1913 if (pRect == NULL) {
1914 loc_rect.top = 0;
1915 loc_rect.left = 0;
1916 loc_rect.bottom = This->surface_desc.dwHeight;
1917 loc_rect.right = This->surface_desc.dwWidth;
1918 } else {
1919 loc_rect = *pRect;
1921 glReadPixels(loc_rect.left, loc_rect.top, loc_rect.right, loc_rect.bottom,
1922 GL_RGB, buffer_type, ((char *)This->surface_desc.lpSurface
1923 + loc_rect.top * This->surface_desc.u1.lPitch
1924 + loc_rect.left * GET_BPP(This->surface_desc)));
1925 glReadBuffer(prev_read);
1926 LEAVE_GL();
1930 static void d3ddevice_unlock_update(IDirectDrawSurfaceImpl* This, LPCRECT pRect)
1932 /* First, check if we need to do anything */
1933 if ((This->lastlocktype & DDLOCK_READONLY) == 0) {
1934 GLenum buffer_type;
1935 GLenum prev_draw;
1937 ENTER_GL();
1939 glGetIntegerv(GL_DRAW_BUFFER, &prev_draw);
1941 WARN(" application does an unlock on a 3D surface - expect slow downs.\n");
1942 if ((This->surface_desc.ddsCaps.dwCaps & (DDSCAPS_FRONTBUFFER|DDSCAPS_PRIMARYSURFACE)) != 0) {
1943 /* Application wants to lock the front buffer */
1944 glDrawBuffer(GL_FRONT);
1945 } else if ((This->surface_desc.ddsCaps.dwCaps & (DDSCAPS_BACKBUFFER)) == (DDSCAPS_BACKBUFFER)) {
1946 /* Application wants to lock the back buffer */
1947 glDrawBuffer(GL_BACK);
1948 } else {
1949 WARN(" do not support 3D surface unlocking for this surface type - trying to use default buffer.\n");
1952 if (This->surface_desc.u4.ddpfPixelFormat.u1.dwRGBBitCount == 16) {
1953 buffer_type = GL_UNSIGNED_SHORT_5_6_5;
1954 } else {
1955 WARN(" unsupported pixel format.\n");
1956 LEAVE_GL();
1957 return;
1959 glRasterPos2f(0.0, 0.0);
1960 glDrawPixels(This->surface_desc.dwWidth, This->surface_desc.dwHeight,
1961 GL_RGB, buffer_type, This->surface_desc.lpSurface);
1962 glDrawBuffer(prev_draw);
1964 LEAVE_GL();
1968 HRESULT
1969 d3ddevice_create(IDirect3DDeviceImpl **obj, IDirect3DImpl *d3d, IDirectDrawSurfaceImpl *surface)
1971 IDirect3DDeviceImpl *object;
1972 IDirect3DDeviceGLImpl *gl_object;
1973 IDirectDrawSurfaceImpl *surf;
1974 HDC device_context;
1975 XVisualInfo *vis;
1976 int num;
1977 XVisualInfo template;
1978 GLenum buffer;
1979 int light;
1981 object = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(IDirect3DDeviceGLImpl));
1982 if (object == NULL) return DDERR_OUTOFMEMORY;
1984 gl_object = (IDirect3DDeviceGLImpl *) object;
1986 object->ref = 1;
1987 object->d3d = d3d;
1988 object->surface = surface;
1989 object->set_context = set_context;
1990 object->clear = d3ddevice_clear;
1992 TRACE(" creating OpenGL device for surface = %p, d3d = %p\n", surface, d3d);
1994 device_context = GetDC(surface->ddraw_owner->window);
1995 gl_object->display = get_display(device_context);
1996 gl_object->drawable = get_drawable(device_context);
1997 ReleaseDC(surface->ddraw_owner->window,device_context);
1999 ENTER_GL();
2000 template.visualid = (VisualID)GetPropA( GetDesktopWindow(), "__wine_x11_visual_id" );
2001 vis = XGetVisualInfo(gl_object->display, VisualIDMask, &template, &num);
2002 if (vis == NULL) {
2003 HeapFree(GetProcessHeap(), 0, object);
2004 ERR("No visual found !\n");
2005 LEAVE_GL();
2006 return DDERR_INVALIDPARAMS;
2007 } else {
2008 TRACE(" visual found\n");
2011 gl_object->gl_context = glXCreateContext(gl_object->display, vis,
2012 NULL, GL_TRUE);
2014 if (gl_object->gl_context == NULL) {
2015 HeapFree(GetProcessHeap(), 0, object);
2016 ERR("Error in context creation !\n");
2017 LEAVE_GL();
2018 return DDERR_INVALIDPARAMS;
2019 } else {
2020 TRACE(" context created (%p)\n", gl_object->gl_context);
2023 /* Look for the front buffer and override its surface's Flip method (if in double buffering) */
2024 for (surf = surface; surf != NULL; surf = surf->surface_owner) {
2025 if ((surf->surface_desc.ddsCaps.dwCaps&(DDSCAPS_FLIP|DDSCAPS_FRONTBUFFER)) == (DDSCAPS_FLIP|DDSCAPS_FRONTBUFFER)) {
2026 surf->aux_ctx = (LPVOID) gl_object->display;
2027 surf->aux_data = (LPVOID) gl_object->drawable;
2028 surf->aux_flip = opengl_flip;
2029 buffer = GL_BACK;
2030 break;
2033 /* We are not doing any double buffering.. Then force OpenGL to draw on the front buffer */
2034 if (surf == NULL) {
2035 TRACE(" no double buffering : drawing on the front buffer\n");
2036 buffer = GL_FRONT;
2039 for (surf = surface; surf->prev_attached != NULL; surf = surf->prev_attached) ;
2040 for (; surf != NULL; surf = surf->next_attached) {
2041 if (((surf->surface_desc.ddsCaps.dwCaps & (DDSCAPS_3DDEVICE)) == (DDSCAPS_3DDEVICE)) &&
2042 ((surf->surface_desc.ddsCaps.dwCaps & (DDSCAPS_ZBUFFER)) != (DDSCAPS_ZBUFFER))) {
2043 /* Override the Lock / Unlock function for all these surfaces */
2044 surf->lock_update = d3ddevice_lock_update;
2045 surf->unlock_update = d3ddevice_unlock_update;
2046 /* And install also the blt / bltfast overrides */
2047 surf->aux_blt = d3ddevice_blt;
2048 surf->aux_bltfast = d3ddevice_bltfast;
2050 surf->d3ddevice = object;
2053 gl_object->render_state.src = GL_ONE;
2054 gl_object->render_state.dst = GL_ZERO;
2055 gl_object->render_state.mag = GL_NEAREST;
2056 gl_object->render_state.min = GL_NEAREST;
2057 gl_object->render_state.alpha_ref = 0.0; /* No actual idea about the real default value... */
2058 gl_object->render_state.alpha_func = GL_ALWAYS; /* Here either but it seems logical */
2059 gl_object->render_state.alpha_blend_enable = FALSE;
2060 gl_object->render_state.fog_on = FALSE;
2061 gl_object->render_state.stencil_func = GL_ALWAYS;
2062 gl_object->render_state.stencil_mask = 0xFFFFFFFF;
2063 gl_object->render_state.stencil_ref = 0;
2064 gl_object->render_state.stencil_enable = FALSE;
2065 gl_object->render_state.stencil_fail = GL_KEEP;
2066 gl_object->render_state.stencil_zfail = GL_KEEP;
2067 gl_object->render_state.stencil_pass = GL_KEEP;
2068 gl_object->render_state.lighting_enable = FALSE;
2069 gl_object->render_state.specular_enable = FALSE;
2070 gl_object->render_state.color_diffuse = D3DMCS_COLOR1;
2071 gl_object->render_state.color_specular = D3DMCS_COLOR2;
2072 gl_object->render_state.color_ambient = D3DMCS_COLOR2;
2073 gl_object->render_state.color_emissive = D3DMCS_MATERIAL;
2075 /* Set the various light parameters */
2076 for (light = 0; light < MAX_LIGHTS; light++) {
2077 /* Only set the fields that are not zero-created */
2078 object->light_parameters[light].dltType = D3DLIGHT_DIRECTIONAL;
2079 object->light_parameters[light].dcvDiffuse.u1.r = 1.0;
2080 object->light_parameters[light].dcvDiffuse.u2.g = 1.0;
2081 object->light_parameters[light].dcvDiffuse.u3.b = 1.0;
2082 object->light_parameters[light].dvDirection.u3.z = 1.0;
2085 /* Allocate memory for the matrices */
2086 object->world_mat = (D3DMATRIX *) HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, 16 * sizeof(float));
2087 object->view_mat = (D3DMATRIX *) HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, 16 * sizeof(float));
2088 object->proj_mat = (D3DMATRIX *) HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, 16 * sizeof(float));
2089 memcpy(object->world_mat, id_mat, 16 * sizeof(float));
2090 memcpy(object->view_mat , id_mat, 16 * sizeof(float));
2091 memcpy(object->proj_mat , id_mat, 16 * sizeof(float));
2093 /* Initialisation */
2094 TRACE(" setting current context\n");
2095 LEAVE_GL();
2096 object->set_context(object);
2097 ENTER_GL();
2098 TRACE(" current context set\n");
2099 glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST);
2100 glClearColor(0.0, 0.0, 0.0, 0.0);
2101 glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
2102 glDrawBuffer(buffer);
2103 glReadBuffer(buffer);
2104 /* glDisable(GL_DEPTH_TEST); Need here to check for the presence of a ZBuffer and to reenable it when the ZBuffer is attached */
2105 LEAVE_GL();
2107 /* fill_device_capabilities(d3d->ddraw); */
2109 ICOM_INIT_INTERFACE(object, IDirect3DDevice, VTABLE_IDirect3DDevice);
2110 ICOM_INIT_INTERFACE(object, IDirect3DDevice2, VTABLE_IDirect3DDevice2);
2111 ICOM_INIT_INTERFACE(object, IDirect3DDevice3, VTABLE_IDirect3DDevice3);
2112 ICOM_INIT_INTERFACE(object, IDirect3DDevice7, VTABLE_IDirect3DDevice7);
2114 *obj = object;
2116 TRACE(" creating implementation at %p.\n", *obj);
2118 /* And finally warn D3D that this device is now present */
2119 object->d3d->added_device(object->d3d, object);
2121 return DD_OK;