Moved x11drv.h to dlls/x11drv.
[wine/wine-kai.git] / dlls / ddraw / d3ddevice / mesa.c
blob59d823ffd00a6c25fc7005701aef47453553dca6
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>
25 #include <math.h>
27 #define NONAMELESSUNION
28 #define NONAMELESSSTRUCT
29 #include "windef.h"
30 #include "winerror.h"
31 #include "objbase.h"
32 #include "ddraw.h"
33 #include "d3d.h"
34 #include "wine/debug.h"
36 #include "mesa_private.h"
37 #include "main.h"
39 WINE_DEFAULT_DEBUG_CHANNEL(ddraw);
41 /* x11drv GDI escapes */
42 #define X11DRV_ESCAPE 6789
43 enum x11drv_escape_codes
45 X11DRV_GET_DISPLAY, /* get X11 display for a DC */
46 X11DRV_GET_DRAWABLE, /* get current drawable for a DC */
47 X11DRV_GET_FONT, /* get current X font for a DC */
50 /* They are non-static as they are used by Direct3D in the creation function */
51 const GUID IID_D3DDEVICE_OpenGL = {
52 0x31416d44,
53 0x86ae,
54 0x11d2,
55 { 0x82,0x2d,0xa8,0xd5,0x31,0x87,0xca,0xfa }
58 #ifndef HAVE_GLEXT_PROTOTYPES
59 /* This is for non-OpenGL ABI compliant glext.h headers :-) */
60 typedef void (* PFNGLCOLORTABLEEXTPROC) (GLenum target, GLenum internalFormat,
61 GLsizei width, GLenum format, GLenum type,
62 const GLvoid *table);
63 #endif
65 const float id_mat[16] = {
66 1.0, 0.0, 0.0, 0.0,
67 0.0, 1.0, 0.0, 0.0,
68 0.0, 0.0, 1.0, 0.0,
69 0.0, 0.0, 0.0, 1.0
72 static void draw_primitive_strided(IDirect3DDeviceImpl *This,
73 D3DPRIMITIVETYPE d3dptPrimitiveType,
74 DWORD d3dvtVertexType,
75 LPD3DDRAWPRIMITIVESTRIDEDDATA lpD3DDrawPrimStrideData,
76 DWORD dwVertexCount,
77 LPWORD dwIndices,
78 DWORD dwIndexCount,
79 DWORD dwFlags) ;
81 /* retrieve the X display to use on a given DC */
82 inline static Display *get_display( HDC hdc )
84 Display *display;
85 enum x11drv_escape_codes escape = X11DRV_GET_DISPLAY;
87 if (!ExtEscape( hdc, X11DRV_ESCAPE, sizeof(escape), (LPCSTR)&escape,
88 sizeof(display), (LPSTR)&display )) display = NULL;
90 return display;
94 /* retrieve the X drawable to use on a given DC */
95 inline static Drawable get_drawable( HDC hdc )
97 Drawable drawable;
98 enum x11drv_escape_codes escape = X11DRV_GET_DRAWABLE;
100 if (!ExtEscape( hdc, X11DRV_ESCAPE, sizeof(escape), (LPCSTR)&escape,
101 sizeof(drawable), (LPSTR)&drawable )) drawable = 0;
103 return drawable;
107 static BOOL opengl_flip( LPVOID display, LPVOID drawable)
109 TRACE("(%p, %ld)\n",(Display*)display,(Drawable)drawable);
110 ENTER_GL();
111 glXSwapBuffers((Display*)display,(Drawable)drawable);
112 LEAVE_GL();
113 return TRUE;
117 /*******************************************************************************
118 * OpenGL static functions
120 static void set_context(IDirect3DDeviceImpl* This)
122 IDirect3DDeviceGLImpl* glThis = (IDirect3DDeviceGLImpl*) This;
124 ENTER_GL();
125 TRACE("glxMakeCurrent %p, %ld, %p\n",glThis->display,glThis->drawable, glThis->gl_context);
126 if (glXMakeCurrent(glThis->display, glThis->drawable, glThis->gl_context) == False) {
127 ERR("Error in setting current context (context %p drawable %ld)!\n",
128 glThis->gl_context, glThis->drawable);
130 LEAVE_GL();
133 static void fill_opengl_primcaps(D3DPRIMCAPS *pc)
135 pc->dwSize = sizeof(*pc);
136 pc->dwMiscCaps = D3DPMISCCAPS_CONFORMANT | D3DPMISCCAPS_CULLCCW | D3DPMISCCAPS_CULLCW |
137 D3DPMISCCAPS_LINEPATTERNREP | D3DPMISCCAPS_MASKZ;
138 pc->dwRasterCaps = D3DPRASTERCAPS_DITHER | D3DPRASTERCAPS_FOGRANGE | D3DPRASTERCAPS_FOGTABLE |
139 D3DPRASTERCAPS_FOGVERTEX | D3DPRASTERCAPS_STIPPLE | D3DPRASTERCAPS_ZBIAS | D3DPRASTERCAPS_ZTEST | D3DPRASTERCAPS_SUBPIXEL;
140 pc->dwZCmpCaps = D3DPCMPCAPS_ALWAYS | D3DPCMPCAPS_EQUAL | D3DPCMPCAPS_GREATER | D3DPCMPCAPS_GREATEREQUAL |
141 D3DPCMPCAPS_LESS | D3DPCMPCAPS_LESSEQUAL | D3DPCMPCAPS_NEVER | D3DPCMPCAPS_NOTEQUAL;
142 pc->dwSrcBlendCaps = D3DPBLENDCAPS_ZERO | D3DPBLENDCAPS_ONE | D3DPBLENDCAPS_DESTCOLOR | D3DPBLENDCAPS_INVDESTCOLOR |
143 D3DPBLENDCAPS_SRCALPHA | D3DPBLENDCAPS_INVSRCALPHA | D3DPBLENDCAPS_DESTALPHA | D3DPBLENDCAPS_INVDESTALPHA | D3DPBLENDCAPS_SRCALPHASAT |
144 D3DPBLENDCAPS_BOTHSRCALPHA | D3DPBLENDCAPS_BOTHINVSRCALPHA;
145 pc->dwDestBlendCaps = D3DPBLENDCAPS_ZERO | D3DPBLENDCAPS_ONE | D3DPBLENDCAPS_SRCCOLOR | D3DPBLENDCAPS_INVSRCCOLOR |
146 D3DPBLENDCAPS_SRCALPHA | D3DPBLENDCAPS_INVSRCALPHA | D3DPBLENDCAPS_DESTALPHA | D3DPBLENDCAPS_INVDESTALPHA | D3DPBLENDCAPS_SRCALPHASAT |
147 D3DPBLENDCAPS_BOTHSRCALPHA | D3DPBLENDCAPS_BOTHINVSRCALPHA;
148 pc->dwAlphaCmpCaps = D3DPCMPCAPS_ALWAYS | D3DPCMPCAPS_EQUAL | D3DPCMPCAPS_GREATER | D3DPCMPCAPS_GREATEREQUAL |
149 D3DPCMPCAPS_LESS | D3DPCMPCAPS_LESSEQUAL | D3DPCMPCAPS_NEVER | D3DPCMPCAPS_NOTEQUAL;
150 pc->dwShadeCaps = D3DPSHADECAPS_ALPHAFLATBLEND | D3DPSHADECAPS_ALPHAGOURAUDBLEND | D3DPSHADECAPS_COLORFLATRGB | D3DPSHADECAPS_COLORGOURAUDRGB |
151 D3DPSHADECAPS_FOGFLAT | D3DPSHADECAPS_FOGGOURAUD | D3DPSHADECAPS_SPECULARFLATRGB | D3DPSHADECAPS_SPECULARGOURAUDRGB;
152 pc->dwTextureCaps = D3DPTEXTURECAPS_ALPHA | D3DPTEXTURECAPS_ALPHAPALETTE | D3DPTEXTURECAPS_BORDER | D3DPTEXTURECAPS_PERSPECTIVE |
153 D3DPTEXTURECAPS_POW2 | D3DPTEXTURECAPS_TRANSPARENCY;
154 pc->dwTextureFilterCaps = D3DPTFILTERCAPS_LINEAR | D3DPTFILTERCAPS_LINEARMIPLINEAR | D3DPTFILTERCAPS_LINEARMIPNEAREST |
155 D3DPTFILTERCAPS_MIPLINEAR | D3DPTFILTERCAPS_MIPNEAREST | D3DPTFILTERCAPS_NEAREST;
156 pc->dwTextureBlendCaps = D3DPTBLENDCAPS_ADD | D3DPTBLENDCAPS_COPY | D3DPTBLENDCAPS_DECAL | D3DPTBLENDCAPS_DECALALPHA | D3DPTBLENDCAPS_DECALMASK |
157 D3DPTBLENDCAPS_MODULATE | D3DPTBLENDCAPS_MODULATEALPHA | D3DPTBLENDCAPS_MODULATEMASK;
158 pc->dwTextureAddressCaps = D3DPTADDRESSCAPS_BORDER | D3DPTADDRESSCAPS_CLAMP | D3DPTADDRESSCAPS_WRAP | D3DPTADDRESSCAPS_INDEPENDENTUV;
159 pc->dwStippleWidth = 32;
160 pc->dwStippleHeight = 32;
163 static void fill_opengl_caps(D3DDEVICEDESC *d1)
165 /* GLint maxlight; */
167 d1->dwSize = sizeof(*d1);
168 d1->dwFlags = D3DDD_DEVCAPS | D3DDD_BCLIPPING | D3DDD_COLORMODEL | D3DDD_DEVICERENDERBITDEPTH | D3DDD_DEVICEZBUFFERBITDEPTH
169 | D3DDD_LIGHTINGCAPS | D3DDD_LINECAPS | D3DDD_MAXBUFFERSIZE | D3DDD_MAXVERTEXCOUNT | D3DDD_TRANSFORMCAPS | D3DDD_TRICAPS;
170 d1->dcmColorModel = D3DCOLOR_RGB;
171 d1->dwDevCaps = D3DDEVCAPS_CANRENDERAFTERFLIP | D3DDEVCAPS_DRAWPRIMTLVERTEX | D3DDEVCAPS_EXECUTESYSTEMMEMORY |
172 D3DDEVCAPS_EXECUTEVIDEOMEMORY | D3DDEVCAPS_FLOATTLVERTEX | D3DDEVCAPS_TEXTURENONLOCALVIDMEM | D3DDEVCAPS_TEXTURESYSTEMMEMORY |
173 D3DDEVCAPS_TEXTUREVIDEOMEMORY | D3DDEVCAPS_TLVERTEXSYSTEMMEMORY | D3DDEVCAPS_TLVERTEXVIDEOMEMORY |
174 /* D3D 7 capabilities */
175 D3DDEVCAPS_DRAWPRIMITIVES2 | D3DDEVCAPS_HWTRANSFORMANDLIGHT | D3DDEVCAPS_HWRASTERIZATION;
176 d1->dtcTransformCaps.dwSize = sizeof(D3DTRANSFORMCAPS);
177 d1->dtcTransformCaps.dwCaps = D3DTRANSFORMCAPS_CLIP;
178 d1->bClipping = TRUE;
179 d1->dlcLightingCaps.dwSize = sizeof(D3DLIGHTINGCAPS);
180 d1->dlcLightingCaps.dwCaps = D3DLIGHTCAPS_DIRECTIONAL | D3DLIGHTCAPS_PARALLELPOINT | D3DLIGHTCAPS_POINT | D3DLIGHTCAPS_SPOT;
181 d1->dlcLightingCaps.dwLightingModel = D3DLIGHTINGMODEL_RGB;
182 d1->dlcLightingCaps.dwNumLights = 16; /* glGetIntegerv(GL_MAX_LIGHTS, &maxlight); d1->dlcLightingCaps.dwNumLights = maxlight; */
183 fill_opengl_primcaps(&(d1->dpcLineCaps));
184 fill_opengl_primcaps(&(d1->dpcTriCaps));
185 d1->dwDeviceRenderBitDepth = DDBD_16|DDBD_24|DDBD_32;
186 d1->dwDeviceZBufferBitDepth = DDBD_16|DDBD_24|DDBD_32;
187 d1->dwMaxBufferSize = 0;
188 d1->dwMaxVertexCount = 65536;
189 d1->dwMinTextureWidth = 1;
190 d1->dwMinTextureHeight = 1;
191 d1->dwMaxTextureWidth = 1024;
192 d1->dwMaxTextureHeight = 1024;
193 d1->dwMinStippleWidth = 1;
194 d1->dwMinStippleHeight = 1;
195 d1->dwMaxStippleWidth = 32;
196 d1->dwMaxStippleHeight = 32;
197 d1->dwMaxTextureRepeat = 16;
198 d1->dwMaxTextureAspectRatio = 1024;
199 d1->dwMaxAnisotropy = 0;
200 d1->dvGuardBandLeft = 0.0;
201 d1->dvGuardBandRight = 0.0;
202 d1->dvGuardBandTop = 0.0;
203 d1->dvGuardBandBottom = 0.0;
204 d1->dvExtentsAdjust = 0.0;
205 d1->dwStencilCaps = D3DSTENCILCAPS_DECRSAT | D3DSTENCILCAPS_INCRSAT | D3DSTENCILCAPS_INVERT | D3DSTENCILCAPS_KEEP |
206 D3DSTENCILCAPS_REPLACE | D3DSTENCILCAPS_ZERO;
207 d1->dwFVFCaps = D3DFVFCAPS_DONOTSTRIPELEMENTS | 1;
208 d1->dwTextureOpCaps = 0; /* TODO add proper caps according to OpenGL multi-texture stuff */
209 d1->wMaxTextureBlendStages = 1; /* TODO add proper caps according to OpenGL multi-texture stuff */
210 d1->wMaxSimultaneousTextures = 1; /* TODO add proper caps according to OpenGL multi-texture stuff */
213 static void fill_opengl_caps_7(D3DDEVICEDESC7 *d)
215 D3DDEVICEDESC d1;
217 /* Copy first D3D1/2/3 capabilities */
218 fill_opengl_caps(&d1);
220 /* And fill the D3D7 one with it */
221 d->dwDevCaps = d1.dwDevCaps;
222 d->dpcLineCaps = d1.dpcLineCaps;
223 d->dpcTriCaps = d1.dpcTriCaps;
224 d->dwDeviceRenderBitDepth = d1.dwDeviceRenderBitDepth;
225 d->dwDeviceZBufferBitDepth = d1.dwDeviceZBufferBitDepth;
226 d->dwMinTextureWidth = d1.dwMinTextureWidth;
227 d->dwMinTextureHeight = d1.dwMinTextureHeight;
228 d->dwMaxTextureWidth = d1.dwMaxTextureWidth;
229 d->dwMaxTextureHeight = d1.dwMaxTextureHeight;
230 d->dwMaxTextureRepeat = d1.dwMaxTextureRepeat;
231 d->dwMaxTextureAspectRatio = d1.dwMaxTextureAspectRatio;
232 d->dwMaxAnisotropy = d1.dwMaxAnisotropy;
233 d->dvGuardBandLeft = d1.dvGuardBandLeft;
234 d->dvGuardBandTop = d1.dvGuardBandTop;
235 d->dvGuardBandRight = d1.dvGuardBandRight;
236 d->dvGuardBandBottom = d1.dvGuardBandBottom;
237 d->dvExtentsAdjust = d1.dvExtentsAdjust;
238 d->dwStencilCaps = d1.dwStencilCaps;
239 d->dwFVFCaps = d1.dwFVFCaps;
240 d->dwTextureOpCaps = d1.dwTextureOpCaps;
241 d->wMaxTextureBlendStages = d1.wMaxTextureBlendStages;
242 d->wMaxSimultaneousTextures = d1.wMaxSimultaneousTextures;
243 d->dwMaxActiveLights = d1.dlcLightingCaps.dwNumLights;
244 d->dvMaxVertexW = 100000000.0; /* No idea exactly what to put here... */
245 d->deviceGUID = IID_IDirect3DTnLHalDevice;
246 d->wMaxUserClipPlanes = 1;
247 d->wMaxVertexBlendMatrices = 0;
248 d->dwVertexProcessingCaps = D3DVTXPCAPS_TEXGEN | D3DVTXPCAPS_MATERIALSOURCE7 | D3DVTXPCAPS_VERTEXFOG | D3DVTXPCAPS_DIRECTIONALLIGHTS |
249 D3DVTXPCAPS_POSITIONALLIGHTS | D3DVTXPCAPS_LOCALVIEWER;
250 d->dwReserved1 = 0;
251 d->dwReserved2 = 0;
252 d->dwReserved3 = 0;
253 d->dwReserved4 = 0;
256 #if 0 /* TODO : fix this and add multitexturing and other needed stuff */
257 static void fill_device_capabilities(IDirectDrawImpl* ddraw)
259 x11_dd_private *private = (x11_dd_private *) ddraw->d->private;
260 const char *ext_string;
261 Mesa_DeviceCapabilities *devcap;
263 private->device_capabilities = HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,sizeof(Mesa_DeviceCapabilities));
264 devcap = (Mesa_DeviceCapabilities *) private->device_capabilities;
266 ENTER_GL();
267 ext_string = glGetString(GL_EXTENSIONS);
268 /* Query for the ColorTable Extension */
269 if (strstr(ext_string, "GL_EXT_paletted_texture")) {
270 devcap->ptr_ColorTableEXT = (PFNGLCOLORTABLEEXTPROC) glXGetProcAddressARB("glColorTableEXT");
271 TRACE("Color table extension supported (function at %p)\n", devcap->ptr_ColorTableEXT);
272 } else {
273 TRACE("Color table extension not found.\n");
275 LEAVE_GL();
277 #endif
281 HRESULT d3ddevice_enumerate(LPD3DENUMDEVICESCALLBACK cb, LPVOID context)
283 D3DDEVICEDESC dref, d1, d2;
284 HRESULT ret_value;
286 fill_opengl_caps(&dref);
288 TRACE(" enumerating OpenGL D3DDevice interface using reference IID (IID %s).\n", debugstr_guid(&IID_IDirect3DRefDevice));
289 d1 = dref;
290 d2 = dref;
291 ret_value = cb((LPIID) &IID_IDirect3DRefDevice, "WINE Reference Direct3DX using OpenGL", "direct3d", &d1, &d2, context);
292 if (ret_value != D3DENUMRET_OK)
293 return ret_value;
295 TRACE(" enumerating OpenGL D3DDevice interface (IID %s).\n", debugstr_guid(&IID_D3DDEVICE_OpenGL));
296 d1 = dref;
297 d2 = dref;
298 ret_value = cb((LPIID) &IID_D3DDEVICE_OpenGL, "WINE Direct3DX using OpenGL", "direct3d", &d1, &d2, context);
299 if (ret_value != D3DENUMRET_OK)
300 return ret_value;
302 return D3DENUMRET_OK;
305 HRESULT d3ddevice_enumerate7(LPD3DENUMDEVICESCALLBACK7 cb, LPVOID context)
307 D3DDEVICEDESC7 ddesc;
309 fill_opengl_caps_7(&ddesc);
311 TRACE(" enumerating OpenGL D3DDevice7 interface.\n");
313 return cb("WINE Direct3D7 using OpenGL", "Wine D3D7 device", &ddesc, context);
316 ULONG WINAPI
317 GL_IDirect3DDeviceImpl_7_3T_2T_1T_Release(LPDIRECT3DDEVICE7 iface)
319 ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice7, iface);
320 IDirect3DDeviceGLImpl *glThis = (IDirect3DDeviceGLImpl *) This;
322 TRACE("(%p/%p)->() decrementing from %lu.\n", This, iface, This->ref);
323 if (!--(This->ref)) {
324 int i;
325 /* Release texture associated with the device */
326 for (i = 0; i < MAX_TEXTURES; i++)
327 if (This->current_texture[i] != NULL)
328 IDirectDrawSurface7_Release(ICOM_INTERFACE(This->current_texture[i], IDirectDrawSurface7));
330 /* And warn the D3D object that this device is no longer active... */
331 This->d3d->removed_device(This->d3d, This);
333 HeapFree(GetProcessHeap(), 0, This->world_mat);
334 HeapFree(GetProcessHeap(), 0, This->view_mat);
335 HeapFree(GetProcessHeap(), 0, This->proj_mat);
337 ENTER_GL();
338 glXDestroyContext(glThis->display, glThis->gl_context);
339 LEAVE_GL();
340 HeapFree(GetProcessHeap(), 0, This->clipping_planes);
342 HeapFree(GetProcessHeap(), 0, This);
343 return 0;
345 return This->ref;
348 HRESULT WINAPI
349 GL_IDirect3DDeviceImpl_3_2T_1T_GetCaps(LPDIRECT3DDEVICE3 iface,
350 LPD3DDEVICEDESC lpD3DHWDevDesc,
351 LPD3DDEVICEDESC lpD3DHELDevDesc)
353 ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice3, iface);
354 D3DDEVICEDESC desc;
355 DWORD dwSize;
357 TRACE("(%p/%p)->(%p,%p)\n", This, iface, lpD3DHWDevDesc, lpD3DHELDevDesc);
359 fill_opengl_caps(&desc);
360 dwSize = lpD3DHWDevDesc->dwSize;
361 memset(lpD3DHWDevDesc, 0, dwSize);
362 memcpy(lpD3DHWDevDesc, &desc, (dwSize <= desc.dwSize ? dwSize : desc.dwSize));
364 dwSize = lpD3DHELDevDesc->dwSize;
365 memset(lpD3DHELDevDesc, 0, dwSize);
366 memcpy(lpD3DHELDevDesc, &desc, (dwSize <= desc.dwSize ? dwSize : desc.dwSize));
368 TRACE(" returning caps : (no dump function yet)\n");
370 return DD_OK;
373 static HRESULT enum_texture_format_OpenGL(LPD3DENUMTEXTUREFORMATSCALLBACK cb_1,
374 LPD3DENUMPIXELFORMATSCALLBACK cb_2,
375 LPVOID context)
377 DDSURFACEDESC sdesc;
378 LPDDPIXELFORMAT pformat;
380 /* Do the texture enumeration */
381 sdesc.dwSize = sizeof(DDSURFACEDESC);
382 sdesc.dwFlags = DDSD_PIXELFORMAT | DDSD_CAPS;
383 sdesc.ddsCaps.dwCaps = DDSCAPS_TEXTURE;
384 pformat = &(sdesc.ddpfPixelFormat);
385 pformat->dwSize = sizeof(DDPIXELFORMAT);
386 pformat->dwFourCC = 0;
388 TRACE("Enumerating GL_RGBA unpacked (32)\n");
389 pformat->dwFlags = DDPF_RGB | DDPF_ALPHAPIXELS;
390 pformat->u1.dwRGBBitCount = 32;
391 pformat->u2.dwRBitMask = 0xFF000000;
392 pformat->u3.dwGBitMask = 0x00FF0000;
393 pformat->u4.dwBBitMask = 0x0000FF00;
394 pformat->u5.dwRGBAlphaBitMask = 0x000000FF;
395 if (cb_1) if (cb_1(&sdesc , context) == 0) return DD_OK;
396 if (cb_2) if (cb_2(pformat, context) == 0) return DD_OK;
398 TRACE("Enumerating GL_RGB unpacked (24)\n");
399 pformat->dwFlags = DDPF_RGB;
400 pformat->u1.dwRGBBitCount = 24;
401 pformat->u2.dwRBitMask = 0x00FF0000;
402 pformat->u3.dwGBitMask = 0x0000FF00;
403 pformat->u4.dwBBitMask = 0x000000FF;
404 pformat->u5.dwRGBAlphaBitMask = 0x00000000;
405 if (cb_1) if (cb_1(&sdesc , context) == 0) return DD_OK;
406 if (cb_2) if (cb_2(pformat, context) == 0) return DD_OK;
408 TRACE("Enumerating GL_RGB packed GL_UNSIGNED_SHORT_5_6_5 (16)\n");
409 pformat->dwFlags = DDPF_RGB;
410 pformat->u1.dwRGBBitCount = 16;
411 pformat->u2.dwRBitMask = 0x0000F800;
412 pformat->u3.dwGBitMask = 0x000007E0;
413 pformat->u4.dwBBitMask = 0x0000001F;
414 pformat->u5.dwRGBAlphaBitMask = 0x00000000;
415 if (cb_1) if (cb_1(&sdesc , context) == 0) return DD_OK;
416 if (cb_2) if (cb_2(pformat, context) == 0) return DD_OK;
418 /* Note : even if this is an 'emulated' texture format, it needs to be first
419 as some dumb applications seem to rely on that. */
420 TRACE("Enumerating GL_RGBA packed GL_UNSIGNED_SHORT_1_5_5_5 (ARGB) (16)\n");
421 pformat->dwFlags = DDPF_RGB | DDPF_ALPHAPIXELS;
422 pformat->u1.dwRGBBitCount = 16;
423 pformat->u2.dwRBitMask = 0x00007C00;
424 pformat->u3.dwGBitMask = 0x000003E0;
425 pformat->u4.dwBBitMask = 0x0000001F;
426 pformat->u5.dwRGBAlphaBitMask = 0x00008000;
427 if (cb_1) if (cb_1(&sdesc , context) == 0) return DD_OK;
428 if (cb_2) if (cb_2(pformat, context) == 0) return DD_OK;
430 TRACE("Enumerating GL_RGBA packed GL_UNSIGNED_SHORT_4_4_4_4 (ARGB) (16)\n");
431 pformat->dwFlags = DDPF_RGB | DDPF_ALPHAPIXELS;
432 pformat->u1.dwRGBBitCount = 16;
433 pformat->u2.dwRBitMask = 0x00000F00;
434 pformat->u3.dwGBitMask = 0x000000F0;
435 pformat->u4.dwBBitMask = 0x0000000F;
436 pformat->u5.dwRGBAlphaBitMask = 0x0000F000;
437 if (cb_1) if (cb_1(&sdesc , context) == 0) return DD_OK;
438 if (cb_2) if (cb_2(pformat, context) == 0) return DD_OK;
440 #if 0
441 /* This is a compromise : some games choose the first 16 bit texture format with alpha they
442 find enumerated, others the last one. And both want to have the ARGB one.
444 So basically, forget our OpenGL roots and do not even enumerate our RGBA ones.
446 TRACE("Enumerating GL_RGBA packed GL_UNSIGNED_SHORT_4_4_4_4 (16)\n");
447 pformat->dwFlags = DDPF_RGB | DDPF_ALPHAPIXELS;
448 pformat->u1.dwRGBBitCount = 16;
449 pformat->u2.dwRBitMask = 0x0000F000;
450 pformat->u3.dwGBitMask = 0x00000F00;
451 pformat->u4.dwBBitMask = 0x000000F0;
452 pformat->u5.dwRGBAlphaBitMask = 0x0000000F;
453 if (cb_1) if (cb_1(&sdesc , context) == 0) return DD_OK;
454 if (cb_2) if (cb_2(pformat, context) == 0) return DD_OK;
456 TRACE("Enumerating GL_RGBA packed GL_UNSIGNED_SHORT_5_5_5_1 (16)\n");
457 pformat->dwFlags = DDPF_RGB | DDPF_ALPHAPIXELS;
458 pformat->u1.dwRGBBitCount = 16;
459 pformat->u2.dwRBitMask = 0x0000F800;
460 pformat->u3.dwGBitMask = 0x000007C0;
461 pformat->u4.dwBBitMask = 0x0000003E;
462 pformat->u5.dwRGBAlphaBitMask = 0x00000001;
463 if (cb_1) if (cb_1(&sdesc , context) == 0) return DD_OK;
464 if (cb_2) if (cb_2(pformat, context) == 0) return DD_OK;
465 #endif
467 TRACE("Enumerating GL_RGB packed GL_UNSIGNED_BYTE_3_3_2 (8)\n");
468 pformat->dwFlags = DDPF_RGB;
469 pformat->u1.dwRGBBitCount = 8;
470 pformat->u2.dwRBitMask = 0x000000E0;
471 pformat->u3.dwGBitMask = 0x0000001C;
472 pformat->u4.dwBBitMask = 0x00000003;
473 pformat->u5.dwRGBAlphaBitMask = 0x00000000;
474 if (cb_1) if (cb_1(&sdesc , context) == 0) return DD_OK;
475 if (cb_2) if (cb_2(pformat, context) == 0) return DD_OK;
477 TRACE("Enumerating Paletted (8)\n");
478 pformat->dwFlags = DDPF_PALETTEINDEXED8;
479 pformat->u1.dwRGBBitCount = 8;
480 pformat->u2.dwRBitMask = 0x00000000;
481 pformat->u3.dwGBitMask = 0x00000000;
482 pformat->u4.dwBBitMask = 0x00000000;
483 pformat->u5.dwRGBAlphaBitMask = 0x00000000;
484 if (cb_1) if (cb_1(&sdesc , context) == 0) return DD_OK;
485 if (cb_2) if (cb_2(pformat, context) == 0) return DD_OK;
487 TRACE("End of enumeration\n");
488 return DD_OK;
492 HRESULT
493 d3ddevice_find(IDirect3DImpl *d3d,
494 LPD3DFINDDEVICESEARCH lpD3DDFS,
495 LPD3DFINDDEVICERESULT lplpD3DDevice)
497 D3DDEVICEDESC desc;
499 if ((lpD3DDFS->dwFlags & D3DFDS_COLORMODEL) &&
500 (lpD3DDFS->dcmColorModel != D3DCOLOR_RGB)) {
501 TRACE(" trying to request a non-RGB D3D color model. Not supported.\n");
502 return DDERR_INVALIDPARAMS; /* No real idea what to return here :-) */
504 if (lpD3DDFS->dwFlags & D3DFDS_GUID) {
505 TRACE(" trying to match guid %s.\n", debugstr_guid(&(lpD3DDFS->guid)));
506 if ((IsEqualGUID(&IID_D3DDEVICE_OpenGL, &(lpD3DDFS->guid)) == 0) &&
507 (IsEqualGUID(&IID_IDirect3DHALDevice, &(lpD3DDFS->guid)) == 0) &&
508 (IsEqualGUID(&IID_IDirect3DRefDevice, &(lpD3DDFS->guid)) == 0)) {
509 TRACE(" no match for this GUID.\n");
510 return DDERR_INVALIDPARAMS;
514 /* Now return our own GUID */
515 lplpD3DDevice->guid = IID_D3DDEVICE_OpenGL;
516 fill_opengl_caps(&desc);
517 lplpD3DDevice->ddHwDesc = desc;
518 lplpD3DDevice->ddSwDesc = desc;
520 TRACE(" returning Wine's OpenGL device with (undumped) capabilities\n");
522 return D3D_OK;
525 HRESULT WINAPI
526 GL_IDirect3DDeviceImpl_2_1T_EnumTextureFormats(LPDIRECT3DDEVICE2 iface,
527 LPD3DENUMTEXTUREFORMATSCALLBACK lpD3DEnumTextureProc,
528 LPVOID lpArg)
530 ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice2, iface);
531 TRACE("(%p/%p)->(%p,%p)\n", This, iface, lpD3DEnumTextureProc, lpArg);
532 return enum_texture_format_OpenGL(lpD3DEnumTextureProc, NULL, lpArg);
535 HRESULT WINAPI
536 GL_IDirect3DDeviceImpl_7_3T_EnumTextureFormats(LPDIRECT3DDEVICE7 iface,
537 LPD3DENUMPIXELFORMATSCALLBACK lpD3DEnumPixelProc,
538 LPVOID lpArg)
540 ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice7, iface);
541 TRACE("(%p/%p)->(%p,%p)\n", This, iface, lpD3DEnumPixelProc, lpArg);
542 return enum_texture_format_OpenGL(NULL, lpD3DEnumPixelProc, lpArg);
545 HRESULT WINAPI
546 GL_IDirect3DDeviceImpl_7_3T_2T_SetRenderState(LPDIRECT3DDEVICE7 iface,
547 D3DRENDERSTATETYPE dwRenderStateType,
548 DWORD dwRenderState)
550 ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice7, iface);
551 TRACE("(%p/%p)->(%08x,%08lx)\n", This, iface, dwRenderStateType, dwRenderState);
553 /* Call the render state functions */
554 store_render_state(This, dwRenderStateType, dwRenderState, &This->state_block);
555 set_render_state(This, dwRenderStateType, &This->state_block);
557 return DD_OK;
560 HRESULT WINAPI
561 GL_IDirect3DDeviceImpl_7_3T_2T_GetRenderState(LPDIRECT3DDEVICE7 iface,
562 D3DRENDERSTATETYPE dwRenderStateType,
563 LPDWORD lpdwRenderState)
565 ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice7, iface);
566 TRACE("(%p/%p)->(%08x,%p)\n", This, iface, dwRenderStateType, lpdwRenderState);
568 /* Call the render state functions */
569 get_render_state(This, dwRenderStateType, lpdwRenderState, &This->state_block);
571 TRACE(" - asked for rendering state : %s, returning value %08lx.\n", _get_renderstate(dwRenderStateType), *lpdwRenderState);
573 return DD_OK;
576 HRESULT WINAPI
577 GL_IDirect3DDeviceImpl_3_2T_SetLightState(LPDIRECT3DDEVICE3 iface,
578 D3DLIGHTSTATETYPE dwLightStateType,
579 DWORD dwLightState)
581 ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice3, iface);
583 TRACE("(%p/%p)->(%08x,%08lx)\n", This, iface, dwLightStateType, dwLightState);
585 if (!dwLightStateType && (dwLightStateType > D3DLIGHTSTATE_COLORVERTEX))
586 TRACE("Unexpected Light State Type\n");
587 return DDERR_INVALIDPARAMS;
589 if (dwLightStateType == D3DLIGHTSTATE_MATERIAL /* 1 */) {
590 IDirect3DMaterialImpl *mat = (IDirect3DMaterialImpl *) dwLightState;
592 if (mat != NULL) {
593 ENTER_GL();
594 mat->activate(mat);
595 LEAVE_GL();
596 } else {
597 ERR(" D3DLIGHTSTATE_MATERIAL called with NULL material !!!\n");
599 } else if (dwLightStateType == D3DLIGHTSTATE_COLORMODEL /* 3 */) {
600 switch (dwLightState) {
601 case D3DCOLOR_MONO:
602 ERR("DDCOLOR_MONO should not happend!\n");
603 break;
604 case D3DCOLOR_RGB:
605 /* We are already in this mode */
606 break;
607 default:
608 ERR("Unknown color model!\n");
609 break;
611 } else {
612 D3DRENDERSTATETYPE rs;
613 switch (dwLightStateType) {
615 case D3DLIGHTSTATE_AMBIENT: /* 2 */
616 rs = D3DRENDERSTATE_AMBIENT;
617 break;
618 case D3DLIGHTSTATE_FOGMODE: /* 4 */
619 rs = D3DRENDERSTATE_FOGVERTEXMODE;
620 break;
621 case D3DLIGHTSTATE_FOGSTART: /* 5 */
622 rs = D3DRENDERSTATE_FOGSTART;
623 break;
624 case D3DLIGHTSTATE_FOGEND: /* 6 */
625 rs = D3DRENDERSTATE_FOGEND;
626 break;
627 case D3DLIGHTSTATE_FOGDENSITY: /* 7 */
628 rs = D3DRENDERSTATE_FOGDENSITY;
629 break;
630 case D3DLIGHTSTATE_COLORVERTEX: /* 8 */
631 rs = D3DRENDERSTATE_COLORVERTEX;
632 break;
633 default:
634 break;
637 IDirect3DDevice7_SetRenderState(ICOM_INTERFACE(This, IDirect3DDevice7),
638 rs,dwLightState);
641 return DD_OK;
644 static void draw_primitive_start_GL(D3DPRIMITIVETYPE d3dpt)
646 switch (d3dpt) {
647 case D3DPT_POINTLIST:
648 TRACE("Start POINTS\n");
649 glBegin(GL_POINTS);
650 break;
652 case D3DPT_LINELIST:
653 TRACE("Start LINES\n");
654 glBegin(GL_LINES);
655 break;
657 case D3DPT_LINESTRIP:
658 TRACE("Start LINE_STRIP\n");
659 glBegin(GL_LINE_STRIP);
660 break;
662 case D3DPT_TRIANGLELIST:
663 TRACE("Start TRIANGLES\n");
664 glBegin(GL_TRIANGLES);
665 break;
667 case D3DPT_TRIANGLESTRIP:
668 TRACE("Start TRIANGLE_STRIP\n");
669 glBegin(GL_TRIANGLE_STRIP);
670 break;
672 case D3DPT_TRIANGLEFAN:
673 TRACE("Start TRIANGLE_FAN\n");
674 glBegin(GL_TRIANGLE_FAN);
675 break;
677 default:
678 TRACE("Unhandled primitive\n");
679 break;
683 /* This function calculate the Z coordinate from Zproj */
684 static float ZfromZproj(IDirect3DDeviceImpl *This, D3DVALUE Zproj)
686 float a,b,c,d;
687 /* Assume that X = Y = 0 and W = 1 */
688 a = This->proj_mat->_33;
689 b = This->proj_mat->_34;
690 c = This->proj_mat->_43;
691 d = This->proj_mat->_44;
692 /* We have in homogenous coordinates Z' = a * Z + c and W' = b * Z + d
693 * So in non homogenous coordinates we have Zproj = (a * Z + c) / (b * Z + d)
694 * And finally Z = (d * Zproj - c) / (a - b * Zproj)
696 return (d*Zproj - c) / (a - b*Zproj);
699 static void build_fog_table(BYTE *fog_table, DWORD fog_color) {
700 int i;
702 TRACE(" rebuilding fog table (%06lx)...\n", fog_color & 0x00FFFFFF);
704 for (i = 0; i < 3; i++) {
705 BYTE fog_color_component = (fog_color >> (8 * i)) & 0xFF;
706 DWORD elt;
707 for (elt = 0; elt < 0x10000; elt++) {
708 /* We apply the fog transformation and cache the result */
709 DWORD fog_intensity = elt & 0xFF;
710 DWORD vertex_color = (elt >> 8) & 0xFF;
711 fog_table[(i * 0x10000) + elt] = ((fog_intensity * vertex_color) + ((0xFF - fog_intensity) * fog_color_component)) / 0xFF;
716 static void draw_primitive_handle_GL_state(IDirect3DDeviceImpl *This,
717 BOOLEAN vertex_transformed,
718 BOOLEAN vertex_lit) {
719 IDirect3DDeviceGLImpl* glThis = (IDirect3DDeviceGLImpl*) This;
721 /* Puts GL in the correct lighting / transformation mode */
722 if ((vertex_transformed == FALSE) &&
723 (glThis->transform_state != GL_TRANSFORM_NORMAL)) {
724 /* Need to put the correct transformation again if we go from Transformed
725 vertices to non-transformed ones.
727 This->set_matrices(This, VIEWMAT_CHANGED|WORLDMAT_CHANGED|PROJMAT_CHANGED,
728 This->world_mat, This->view_mat, This->proj_mat);
729 glThis->transform_state = GL_TRANSFORM_NORMAL;
731 } else if ((vertex_transformed == TRUE) &&
732 (glThis->transform_state != GL_TRANSFORM_ORTHO)) {
733 /* Set our orthographic projection */
734 glThis->transform_state = GL_TRANSFORM_ORTHO;
735 d3ddevice_set_ortho(This);
738 /* TODO: optimize this to not always reset all the fog stuff on all DrawPrimitive call
739 if no fogging state change occured */
740 if (This->state_block.render_state[D3DRENDERSTATE_FOGENABLE - 1] == TRUE) {
741 if (vertex_transformed == TRUE) {
742 glDisable(GL_FOG);
743 /* Now check if our fog_table still corresponds to the current vertex color.
744 Element '0x..00' is always the fog color as it corresponds to maximum fog intensity */
745 if ((glThis->fog_table[0 * 0x10000 + 0x0000] != ((This->state_block.render_state[D3DRENDERSTATE_FOGCOLOR - 1] >> 0) & 0xFF)) ||
746 (glThis->fog_table[1 * 0x10000 + 0x0000] != ((This->state_block.render_state[D3DRENDERSTATE_FOGCOLOR - 1] >> 8) & 0xFF)) ||
747 (glThis->fog_table[2 * 0x10000 + 0x0000] != ((This->state_block.render_state[D3DRENDERSTATE_FOGCOLOR - 1] >> 16) & 0xFF))) {
748 /* We need to rebuild our fog table.... */
749 build_fog_table(glThis->fog_table, This->state_block.render_state[D3DRENDERSTATE_FOGCOLOR - 1]);
751 } else {
752 if (This->state_block.render_state[D3DRENDERSTATE_FOGTABLEMODE - 1] != D3DFOG_NONE) {
753 switch (This->state_block.render_state[D3DRENDERSTATE_FOGTABLEMODE - 1]) {
754 case D3DFOG_LINEAR: glFogi(GL_FOG_MODE, GL_LINEAR); break;
755 case D3DFOG_EXP: glFogi(GL_FOG_MODE, GL_EXP); break;
756 case D3DFOG_EXP2: glFogi(GL_FOG_MODE, GL_EXP2); break;
758 if (vertex_lit == FALSE) {
759 glFogf(GL_FOG_START, *(float*)&This->state_block.render_state[D3DRENDERSTATE_FOGSTART - 1]);
760 glFogf(GL_FOG_END, *(float*)&This->state_block.render_state[D3DRENDERSTATE_FOGEND - 1]);
761 } else {
762 /* Special case of 'pixel fog' */
763 glFogf(GL_FOG_START, ZfromZproj(This, *(float*)&This->state_block.render_state[D3DRENDERSTATE_FOGSTART - 1]));
764 glFogf(GL_FOG_END, ZfromZproj(This, *(float*)&This->state_block.render_state[D3DRENDERSTATE_FOGEND - 1]));
766 glEnable(GL_FOG);
767 } else {
768 glDisable(GL_FOG);
771 } else {
772 glDisable(GL_FOG);
775 /* Handle the 'no-normal' case */
776 if ((vertex_lit == FALSE) && (This->state_block.render_state[D3DRENDERSTATE_LIGHTING - 1] == TRUE))
777 glEnable(GL_LIGHTING);
778 else
779 glDisable(GL_LIGHTING);
781 /* Handle the code for pre-vertex material properties */
782 if (vertex_transformed == FALSE) {
783 if ((This->state_block.render_state[D3DRENDERSTATE_LIGHTING - 1] == TRUE) &&
784 (This->state_block.render_state[D3DRENDERSTATE_COLORVERTEX - 1] == TRUE)) {
785 if ((This->state_block.render_state[D3DRENDERSTATE_DIFFUSEMATERIALSOURCE - 1] != D3DMCS_MATERIAL) ||
786 (This->state_block.render_state[D3DRENDERSTATE_AMBIENTMATERIALSOURCE - 1] != D3DMCS_MATERIAL) ||
787 (This->state_block.render_state[D3DRENDERSTATE_EMISSIVEMATERIALSOURCE - 1] != D3DMCS_MATERIAL) ||
788 (This->state_block.render_state[D3DRENDERSTATE_SPECULARMATERIALSOURCE - 1] != D3DMCS_MATERIAL)) {
789 glEnable(GL_COLOR_MATERIAL);
796 inline static void draw_primitive(IDirect3DDeviceImpl *This, DWORD maxvert, WORD *index,
797 D3DVERTEXTYPE d3dvt, D3DPRIMITIVETYPE d3dpt, void *lpvertex)
799 D3DDRAWPRIMITIVESTRIDEDDATA strided;
801 switch (d3dvt) {
802 case D3DVT_VERTEX: {
803 strided.position.lpvData = &((D3DVERTEX *) lpvertex)->u1.x;
804 strided.position.dwStride = sizeof(D3DVERTEX);
805 strided.normal.lpvData = &((D3DVERTEX *) lpvertex)->u4.nx;
806 strided.normal.dwStride = sizeof(D3DVERTEX);
807 strided.textureCoords[0].lpvData = &((D3DVERTEX *) lpvertex)->u7.tu;
808 strided.textureCoords[0].dwStride = sizeof(D3DVERTEX);
809 draw_primitive_strided(This, d3dpt, D3DFVF_VERTEX, &strided, 0 /* Unused */, index, maxvert, 0 /* Unused */);
810 } break;
812 case D3DVT_LVERTEX: {
813 strided.position.lpvData = &((D3DLVERTEX *) lpvertex)->u1.x;
814 strided.position.dwStride = sizeof(D3DLVERTEX);
815 strided.diffuse.lpvData = &((D3DLVERTEX *) lpvertex)->u4.color;
816 strided.diffuse.dwStride = sizeof(D3DLVERTEX);
817 strided.specular.lpvData = &((D3DLVERTEX *) lpvertex)->u5.specular;
818 strided.specular.dwStride = sizeof(D3DLVERTEX);
819 strided.textureCoords[0].lpvData = &((D3DLVERTEX *) lpvertex)->u6.tu;
820 strided.textureCoords[0].dwStride = sizeof(D3DLVERTEX);
821 draw_primitive_strided(This, d3dpt, D3DFVF_LVERTEX, &strided, 0 /* Unused */, index, maxvert, 0 /* Unused */);
822 } break;
824 case D3DVT_TLVERTEX: {
825 strided.position.lpvData = &((D3DTLVERTEX *) lpvertex)->u1.sx;
826 strided.position.dwStride = sizeof(D3DTLVERTEX);
827 strided.diffuse.lpvData = &((D3DTLVERTEX *) lpvertex)->u5.color;
828 strided.diffuse.dwStride = sizeof(D3DTLVERTEX);
829 strided.specular.lpvData = &((D3DTLVERTEX *) lpvertex)->u6.specular;
830 strided.specular.dwStride = sizeof(D3DTLVERTEX);
831 strided.textureCoords[0].lpvData = &((D3DTLVERTEX *) lpvertex)->u7.tu;
832 strided.textureCoords[0].dwStride = sizeof(D3DTLVERTEX);
833 draw_primitive_strided(This, d3dpt, D3DFVF_TLVERTEX, &strided, 0 /* Unused */, index, maxvert, 0 /* Unused */);
834 } break;
836 default:
837 FIXME("Unhandled vertex type\n");
838 break;
842 HRESULT WINAPI
843 GL_IDirect3DDeviceImpl_2_DrawPrimitive(LPDIRECT3DDEVICE2 iface,
844 D3DPRIMITIVETYPE d3dptPrimitiveType,
845 D3DVERTEXTYPE d3dvtVertexType,
846 LPVOID lpvVertices,
847 DWORD dwVertexCount,
848 DWORD dwFlags)
850 ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice2, iface);
852 TRACE("(%p/%p)->(%08x,%08x,%p,%08lx,%08lx)\n", This, iface, d3dptPrimitiveType, d3dvtVertexType, lpvVertices, dwVertexCount, dwFlags);
853 if (TRACE_ON(ddraw)) {
854 TRACE(" - flags : "); dump_DPFLAGS(dwFlags);
857 draw_primitive(This, dwVertexCount, NULL, d3dvtVertexType, d3dptPrimitiveType, lpvVertices);
859 return DD_OK;
862 HRESULT WINAPI
863 GL_IDirect3DDeviceImpl_2_DrawIndexedPrimitive(LPDIRECT3DDEVICE2 iface,
864 D3DPRIMITIVETYPE d3dptPrimitiveType,
865 D3DVERTEXTYPE d3dvtVertexType,
866 LPVOID lpvVertices,
867 DWORD dwVertexCount,
868 LPWORD dwIndices,
869 DWORD dwIndexCount,
870 DWORD dwFlags)
872 ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice2, iface);
873 TRACE("(%p/%p)->(%08x,%08x,%p,%08lx,%p,%08lx,%08lx)\n", This, iface, d3dptPrimitiveType, d3dvtVertexType, lpvVertices, dwVertexCount, dwIndices, dwIndexCount, dwFlags);
874 if (TRACE_ON(ddraw)) {
875 TRACE(" - flags : "); dump_DPFLAGS(dwFlags);
878 draw_primitive(This, dwIndexCount, dwIndices, d3dvtVertexType, d3dptPrimitiveType, lpvVertices);
880 return DD_OK;
883 HRESULT WINAPI
884 GL_IDirect3DDeviceImpl_1_CreateExecuteBuffer(LPDIRECT3DDEVICE iface,
885 LPD3DEXECUTEBUFFERDESC lpDesc,
886 LPDIRECT3DEXECUTEBUFFER* lplpDirect3DExecuteBuffer,
887 IUnknown* pUnkOuter)
889 ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice, iface);
890 IDirect3DExecuteBufferImpl *ret;
891 HRESULT ret_value;
893 TRACE("(%p/%p)->(%p,%p,%p)\n", This, iface, lpDesc, lplpDirect3DExecuteBuffer, pUnkOuter);
895 ret_value = d3dexecutebuffer_create(&ret, This->d3d, This, lpDesc);
896 *lplpDirect3DExecuteBuffer = ICOM_INTERFACE(ret, IDirect3DExecuteBuffer);
898 TRACE(" returning %p.\n", *lplpDirect3DExecuteBuffer);
900 return ret_value;
903 /* These are the various handler used in the generic path */
904 inline static void handle_xyz(D3DVALUE *coords) {
905 glVertex3fv(coords);
907 inline static void handle_xyzrhw(D3DVALUE *coords) {
908 if (coords[3] < 1e-8)
909 glVertex3fv(coords);
910 else {
911 GLfloat w = 1.0 / coords[3];
913 glVertex4f(coords[0] * w,
914 coords[1] * w,
915 coords[2] * w,
919 inline static void handle_normal(D3DVALUE *coords) {
920 glNormal3fv(coords);
923 inline static void handle_diffuse_base(STATEBLOCK *sb, DWORD *color) {
924 if ((sb->render_state[D3DRENDERSTATE_ALPHATESTENABLE - 1] == TRUE) ||
925 (sb->render_state[D3DRENDERSTATE_ALPHABLENDENABLE - 1] == TRUE)) {
926 glColor4ub((*color >> 16) & 0xFF,
927 (*color >> 8) & 0xFF,
928 (*color >> 0) & 0xFF,
929 (*color >> 24) & 0xFF);
930 } else {
931 glColor3ub((*color >> 16) & 0xFF,
932 (*color >> 8) & 0xFF,
933 (*color >> 0) & 0xFF);
937 inline static void handle_specular_base(STATEBLOCK *sb, DWORD *color) {
938 glColor4ub((*color >> 16) & 0xFF,
939 (*color >> 8) & 0xFF,
940 (*color >> 0) & 0xFF,
941 (*color >> 24) & 0xFF); /* No idea if the alpha field is really used.. */
944 inline static void handle_diffuse(STATEBLOCK *sb, DWORD *color, BOOLEAN lighted) {
945 if ((lighted == FALSE) &&
946 (sb->render_state[D3DRENDERSTATE_LIGHTING - 1] == TRUE) &&
947 (sb->render_state[D3DRENDERSTATE_COLORVERTEX - 1] == TRUE)) {
948 if (sb->render_state[D3DRENDERSTATE_DIFFUSEMATERIALSOURCE - 1] == D3DMCS_COLOR1) {
949 glColorMaterial(GL_FRONT_AND_BACK, GL_DIFFUSE);
950 handle_diffuse_base(sb, color);
952 if (sb->render_state[D3DRENDERSTATE_AMBIENTMATERIALSOURCE - 1] == D3DMCS_COLOR1) {
953 glColorMaterial(GL_FRONT_AND_BACK, GL_AMBIENT);
954 handle_diffuse_base(sb, color);
956 if ((sb->render_state[D3DRENDERSTATE_SPECULARMATERIALSOURCE - 1] == D3DMCS_COLOR1) &&
957 (sb->render_state[D3DRENDERSTATE_SPECULARENABLE - 1] == TRUE)) {
958 glColorMaterial(GL_FRONT_AND_BACK, GL_SPECULAR);
959 handle_diffuse_base(sb, color);
961 if (sb->render_state[D3DRENDERSTATE_EMISSIVEMATERIALSOURCE - 1] == D3DMCS_COLOR1) {
962 glColorMaterial(GL_FRONT_AND_BACK, GL_EMISSION);
963 handle_diffuse_base(sb, color);
965 } else {
966 handle_diffuse_base(sb, color);
970 inline static void handle_specular(STATEBLOCK *sb, DWORD *color, BOOLEAN lighted) {
971 if ((lighted == FALSE) &&
972 (sb->render_state[D3DRENDERSTATE_LIGHTING - 1] == TRUE) &&
973 (sb->render_state[D3DRENDERSTATE_COLORVERTEX - 1] == TRUE)) {
974 if (sb->render_state[D3DRENDERSTATE_DIFFUSEMATERIALSOURCE - 1] == D3DMCS_COLOR2) {
975 glColorMaterial(GL_FRONT_AND_BACK, GL_DIFFUSE);
976 handle_specular_base(sb, color);
978 if (sb->render_state[D3DRENDERSTATE_AMBIENTMATERIALSOURCE - 1] == D3DMCS_COLOR2) {
979 glColorMaterial(GL_FRONT_AND_BACK, GL_AMBIENT);
980 handle_specular_base(sb, color);
982 if ((sb->render_state[D3DRENDERSTATE_SPECULARMATERIALSOURCE - 1] == D3DMCS_COLOR2) &&
983 (sb->render_state[D3DRENDERSTATE_SPECULARENABLE - 1] == TRUE)) {
984 glColorMaterial(GL_FRONT_AND_BACK, GL_SPECULAR);
985 handle_specular_base(sb, color);
987 if (sb->render_state[D3DRENDERSTATE_EMISSIVEMATERIALSOURCE - 1] == D3DMCS_COLOR2) {
988 glColorMaterial(GL_FRONT_AND_BACK, GL_EMISSION);
989 handle_specular_base(sb, color);
992 /* No else here as we do not know how to handle 'specular' on its own in any case.. */
995 inline static void handle_diffuse_and_specular(STATEBLOCK *sb, BYTE *fog_table, DWORD *color_d, DWORD *color_s, BOOLEAN lighted) {
996 if (lighted == TRUE) {
997 DWORD color = *color_d;
998 if (sb->render_state[D3DRENDERSTATE_FOGENABLE - 1] == TRUE) {
999 /* Special case where the specular value is used to do fogging */
1000 BYTE fog_intensity = *color_s >> 24; /* The alpha value of the specular component is the fog 'intensity' for this vertex */
1001 color &= 0xFF000000; /* Only keep the alpha component */
1002 color |= fog_table[((*color_d >> 0) & 0xFF) << 8 | fog_intensity] << 0;
1003 color |= fog_table[((*color_d >> 8) & 0xFF) << 8 | fog_intensity] << 8;
1004 color |= fog_table[((*color_d >> 16) & 0xFF) << 8 | fog_intensity] << 16;
1006 if (sb->render_state[D3DRENDERSTATE_SPECULARENABLE - 1] == TRUE) {
1007 /* Standard specular value in transformed mode. TODO */
1009 handle_diffuse_base(sb, &color);
1010 } else {
1011 if (sb->render_state[D3DRENDERSTATE_LIGHTING - 1] == TRUE) {
1012 handle_diffuse(sb, color_d, FALSE);
1013 handle_specular(sb, color_s, FALSE);
1014 } else {
1015 /* In that case, only put the diffuse color... */
1016 handle_diffuse_base(sb, color_d);
1021 inline static void handle_texture(D3DVALUE *coords) {
1022 glTexCoord2fv(coords);
1024 inline static void handle_textures(D3DVALUE *coords, int tex_index) {
1025 /* For the moment, draw only the first texture.. */
1026 if (tex_index == 0) glTexCoord2fv(coords);
1029 static void draw_primitive_strided(IDirect3DDeviceImpl *This,
1030 D3DPRIMITIVETYPE d3dptPrimitiveType,
1031 DWORD d3dvtVertexType,
1032 LPD3DDRAWPRIMITIVESTRIDEDDATA lpD3DDrawPrimStrideData,
1033 DWORD dwVertexCount,
1034 LPWORD dwIndices,
1035 DWORD dwIndexCount,
1036 DWORD dwFlags)
1038 BOOLEAN vertex_lighted = FALSE;
1039 IDirect3DDeviceGLImpl* glThis = (IDirect3DDeviceGLImpl*) This;
1041 if (TRACE_ON(ddraw)) {
1042 TRACE(" Vertex format : "); dump_flexible_vertex(d3dvtVertexType);
1045 ENTER_GL();
1047 /* Just a hack for now.. Will have to find better algorithm :-/ */
1048 if ((d3dvtVertexType & D3DFVF_POSITION_MASK) != D3DFVF_XYZ) {
1049 vertex_lighted = TRUE;
1050 } else {
1051 if ((d3dvtVertexType & D3DFVF_NORMAL) == 0) glNormal3f(0.0, 0.0, 0.0);
1054 draw_primitive_handle_GL_state(This,
1055 (d3dvtVertexType & D3DFVF_POSITION_MASK) != D3DFVF_XYZ,
1056 vertex_lighted);
1057 draw_primitive_start_GL(d3dptPrimitiveType);
1059 /* Some fast paths first before the generic case.... */
1060 if (d3dvtVertexType == D3DFVF_VERTEX) {
1061 int index;
1063 for (index = 0; index < dwIndexCount; index++) {
1064 int i = (dwIndices == NULL) ? index : dwIndices[index];
1065 D3DVALUE *normal =
1066 (D3DVALUE *) (((char *) lpD3DDrawPrimStrideData->normal.lpvData) + i * lpD3DDrawPrimStrideData->normal.dwStride);
1067 D3DVALUE *tex_coord =
1068 (D3DVALUE *) (((char *) lpD3DDrawPrimStrideData->textureCoords[0].lpvData) + i * lpD3DDrawPrimStrideData->textureCoords[0].dwStride);
1069 D3DVALUE *position =
1070 (D3DVALUE *) (((char *) lpD3DDrawPrimStrideData->position.lpvData) + i * lpD3DDrawPrimStrideData->position.dwStride);
1072 handle_normal(normal);
1073 handle_texture(tex_coord);
1074 handle_xyz(position);
1076 TRACE(" %f %f %f / %f %f %f (%f %f)\n",
1077 position[0], position[1], position[2],
1078 normal[0], normal[1], normal[2],
1079 tex_coord[0], tex_coord[1]);
1081 } else if (d3dvtVertexType == D3DFVF_TLVERTEX) {
1082 int index;
1084 for (index = 0; index < dwIndexCount; index++) {
1085 int i = (dwIndices == NULL) ? index : dwIndices[index];
1086 DWORD *color_d =
1087 (DWORD *) (((char *) lpD3DDrawPrimStrideData->diffuse.lpvData) + i * lpD3DDrawPrimStrideData->diffuse.dwStride);
1088 DWORD *color_s =
1089 (DWORD *) (((char *) lpD3DDrawPrimStrideData->specular.lpvData) + i * lpD3DDrawPrimStrideData->specular.dwStride);
1090 D3DVALUE *tex_coord =
1091 (D3DVALUE *) (((char *) lpD3DDrawPrimStrideData->textureCoords[0].lpvData) + i * lpD3DDrawPrimStrideData->textureCoords[0].dwStride);
1092 D3DVALUE *position =
1093 (D3DVALUE *) (((char *) lpD3DDrawPrimStrideData->position.lpvData) + i * lpD3DDrawPrimStrideData->position.dwStride);
1095 handle_diffuse_and_specular(&(This->state_block), glThis->fog_table, color_d, color_s, TRUE);
1096 handle_texture(tex_coord);
1097 handle_xyzrhw(position);
1099 TRACE(" %f %f %f %f / %02lx %02lx %02lx %02lx - %02lx %02lx %02lx %02lx (%f %f)\n",
1100 position[0], position[1], position[2], position[3],
1101 (*color_d >> 16) & 0xFF,
1102 (*color_d >> 8) & 0xFF,
1103 (*color_d >> 0) & 0xFF,
1104 (*color_d >> 24) & 0xFF,
1105 (*color_s >> 16) & 0xFF,
1106 (*color_s >> 8) & 0xFF,
1107 (*color_s >> 0) & 0xFF,
1108 (*color_s >> 24) & 0xFF,
1109 tex_coord[0], tex_coord[1]);
1111 } else if (((d3dvtVertexType & D3DFVF_POSITION_MASK) == D3DFVF_XYZ) ||
1112 ((d3dvtVertexType & D3DFVF_POSITION_MASK) == D3DFVF_XYZRHW)) {
1113 /* This is the 'slow path' but that should support all possible vertex formats out there...
1114 Note that people should write a fast path for all vertex formats out there...
1116 int index;
1117 for (index = 0; index < dwIndexCount; index++) {
1118 int i = (dwIndices == NULL) ? index : dwIndices[index];
1120 if (d3dvtVertexType & D3DFVF_NORMAL) {
1121 D3DVALUE *normal =
1122 (D3DVALUE *) (((char *) lpD3DDrawPrimStrideData->normal.lpvData) + i * lpD3DDrawPrimStrideData->normal.dwStride);
1123 handle_normal(normal);
1125 if ((d3dvtVertexType & (D3DFVF_DIFFUSE|D3DFVF_SPECULAR)) == (D3DFVF_DIFFUSE|D3DFVF_SPECULAR)) {
1126 DWORD *color_d =
1127 (DWORD *) (((char *) lpD3DDrawPrimStrideData->diffuse.lpvData) + i * lpD3DDrawPrimStrideData->diffuse.dwStride);
1128 DWORD *color_s =
1129 (DWORD *) (((char *) lpD3DDrawPrimStrideData->specular.lpvData) + i * lpD3DDrawPrimStrideData->specular.dwStride);
1130 handle_diffuse_and_specular(&(This->state_block), glThis->fog_table, color_d, color_s, vertex_lighted);
1131 } else {
1132 if (d3dvtVertexType & D3DFVF_SPECULAR) {
1133 DWORD *color_s =
1134 (DWORD *) (((char *) lpD3DDrawPrimStrideData->specular.lpvData) + i * lpD3DDrawPrimStrideData->specular.dwStride);
1135 handle_specular(&(This->state_block), color_s, vertex_lighted);
1136 } else if (d3dvtVertexType & D3DFVF_DIFFUSE) {
1137 DWORD *color_d =
1138 (DWORD *) (((char *) lpD3DDrawPrimStrideData->diffuse.lpvData) + i * lpD3DDrawPrimStrideData->diffuse.dwStride);
1139 handle_diffuse(&(This->state_block), color_d, vertex_lighted);
1143 if (((d3dvtVertexType & D3DFVF_TEXCOUNT_MASK) >> D3DFVF_TEXCOUNT_SHIFT) == 1) {
1144 /* Special case for single texture... */
1145 D3DVALUE *tex_coord =
1146 (D3DVALUE *) (((char *) lpD3DDrawPrimStrideData->textureCoords[0].lpvData) + i * lpD3DDrawPrimStrideData->textureCoords[0].dwStride);
1147 handle_texture(tex_coord);
1148 } else {
1149 int tex_index;
1150 for (tex_index = 0; tex_index < ((d3dvtVertexType & D3DFVF_TEXCOUNT_MASK) >> D3DFVF_TEXCOUNT_SHIFT); tex_index++) {
1151 D3DVALUE *tex_coord =
1152 (D3DVALUE *) (((char *) lpD3DDrawPrimStrideData->textureCoords[tex_index].lpvData) +
1153 i * lpD3DDrawPrimStrideData->textureCoords[tex_index].dwStride);
1154 handle_textures(tex_coord, tex_index);
1157 if ((d3dvtVertexType & D3DFVF_POSITION_MASK) == D3DFVF_XYZ) {
1158 D3DVALUE *position =
1159 (D3DVALUE *) (((char *) lpD3DDrawPrimStrideData->position.lpvData) + i * lpD3DDrawPrimStrideData->position.dwStride);
1160 handle_xyz(position);
1161 } else if ((d3dvtVertexType & D3DFVF_POSITION_MASK) == D3DFVF_XYZRHW) {
1162 D3DVALUE *position =
1163 (D3DVALUE *) (((char *) lpD3DDrawPrimStrideData->position.lpvData) + i * lpD3DDrawPrimStrideData->position.dwStride);
1164 handle_xyzrhw(position);
1167 if (TRACE_ON(ddraw)) {
1168 int tex_index;
1170 if ((d3dvtVertexType & D3DFVF_POSITION_MASK) == D3DFVF_XYZ) {
1171 D3DVALUE *position =
1172 (D3DVALUE *) (((char *) lpD3DDrawPrimStrideData->position.lpvData) + i * lpD3DDrawPrimStrideData->position.dwStride);
1173 TRACE(" %f %f %f", position[0], position[1], position[2]);
1174 } else if ((d3dvtVertexType & D3DFVF_POSITION_MASK) == D3DFVF_XYZRHW) {
1175 D3DVALUE *position =
1176 (D3DVALUE *) (((char *) lpD3DDrawPrimStrideData->position.lpvData) + i * lpD3DDrawPrimStrideData->position.dwStride);
1177 TRACE(" %f %f %f %f", position[0], position[1], position[2], position[3]);
1179 if (d3dvtVertexType & D3DFVF_NORMAL) {
1180 D3DVALUE *normal =
1181 (D3DVALUE *) (((char *) lpD3DDrawPrimStrideData->normal.lpvData) + i * lpD3DDrawPrimStrideData->normal.dwStride);
1182 TRACE(" / %f %f %f", normal[0], normal[1], normal[2]);
1184 if (d3dvtVertexType & D3DFVF_DIFFUSE) {
1185 DWORD *color_d =
1186 (DWORD *) (((char *) lpD3DDrawPrimStrideData->diffuse.lpvData) + i * lpD3DDrawPrimStrideData->diffuse.dwStride);
1187 TRACE(" / %02lx %02lx %02lx %02lx",
1188 (*color_d >> 16) & 0xFF,
1189 (*color_d >> 8) & 0xFF,
1190 (*color_d >> 0) & 0xFF,
1191 (*color_d >> 24) & 0xFF);
1193 if (d3dvtVertexType & D3DFVF_SPECULAR) {
1194 DWORD *color_s =
1195 (DWORD *) (((char *) lpD3DDrawPrimStrideData->specular.lpvData) + i * lpD3DDrawPrimStrideData->specular.dwStride);
1196 TRACE(" / %02lx %02lx %02lx %02lx",
1197 (*color_s >> 16) & 0xFF,
1198 (*color_s >> 8) & 0xFF,
1199 (*color_s >> 0) & 0xFF,
1200 (*color_s >> 24) & 0xFF);
1202 for (tex_index = 0; tex_index < ((d3dvtVertexType & D3DFVF_TEXCOUNT_MASK) >> D3DFVF_TEXCOUNT_SHIFT); tex_index++) {
1203 D3DVALUE *tex_coord =
1204 (D3DVALUE *) (((char *) lpD3DDrawPrimStrideData->textureCoords[tex_index].lpvData) +
1205 i * lpD3DDrawPrimStrideData->textureCoords[tex_index].dwStride);
1206 TRACE(" / %f %f", tex_coord[0], tex_coord[1]);
1208 TRACE("\n");
1211 } else {
1212 ERR(" matrix weighting not handled yet....\n");
1215 glEnd();
1217 /* Whatever the case, disable the color material stuff */
1218 glDisable(GL_COLOR_MATERIAL);
1220 LEAVE_GL();
1221 TRACE("End\n");
1224 HRESULT WINAPI
1225 GL_IDirect3DDeviceImpl_7_3T_DrawPrimitive(LPDIRECT3DDEVICE7 iface,
1226 D3DPRIMITIVETYPE d3dptPrimitiveType,
1227 DWORD d3dvtVertexType,
1228 LPVOID lpvVertices,
1229 DWORD dwVertexCount,
1230 DWORD dwFlags)
1232 ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice7, iface);
1233 D3DDRAWPRIMITIVESTRIDEDDATA strided;
1235 TRACE("(%p/%p)->(%08x,%08lx,%p,%08lx,%08lx)\n", This, iface, d3dptPrimitiveType, d3dvtVertexType, lpvVertices, dwVertexCount, dwFlags);
1236 if (TRACE_ON(ddraw)) {
1237 TRACE(" - flags : "); dump_DPFLAGS(dwFlags);
1240 convert_FVF_to_strided_data(d3dvtVertexType, lpvVertices, &strided, 0);
1241 draw_primitive_strided(This, d3dptPrimitiveType, d3dvtVertexType, &strided, dwVertexCount, NULL, dwVertexCount, dwFlags);
1243 return DD_OK;
1246 HRESULT WINAPI
1247 GL_IDirect3DDeviceImpl_7_3T_DrawIndexedPrimitive(LPDIRECT3DDEVICE7 iface,
1248 D3DPRIMITIVETYPE d3dptPrimitiveType,
1249 DWORD d3dvtVertexType,
1250 LPVOID lpvVertices,
1251 DWORD dwVertexCount,
1252 LPWORD dwIndices,
1253 DWORD dwIndexCount,
1254 DWORD dwFlags)
1256 ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice7, iface);
1257 D3DDRAWPRIMITIVESTRIDEDDATA strided;
1259 TRACE("(%p/%p)->(%08x,%08lx,%p,%08lx,%p,%08lx,%08lx)\n", This, iface, d3dptPrimitiveType, d3dvtVertexType, lpvVertices, dwVertexCount, dwIndices, dwIndexCount, dwFlags);
1260 if (TRACE_ON(ddraw)) {
1261 TRACE(" - flags : "); dump_DPFLAGS(dwFlags);
1264 convert_FVF_to_strided_data(d3dvtVertexType, lpvVertices, &strided, 0);
1265 draw_primitive_strided(This, d3dptPrimitiveType, d3dvtVertexType, &strided, dwVertexCount, dwIndices, dwIndexCount, dwFlags);
1267 return DD_OK;
1270 HRESULT WINAPI
1271 GL_IDirect3DDeviceImpl_7_3T_DrawPrimitiveStrided(LPDIRECT3DDEVICE7 iface,
1272 D3DPRIMITIVETYPE d3dptPrimitiveType,
1273 DWORD dwVertexType,
1274 LPD3DDRAWPRIMITIVESTRIDEDDATA lpD3DDrawPrimStrideData,
1275 DWORD dwVertexCount,
1276 DWORD dwFlags)
1278 ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice7, iface);
1280 TRACE("(%p/%p)->(%08x,%08lx,%p,%08lx,%08lx)\n", This, iface, d3dptPrimitiveType, dwVertexType, lpD3DDrawPrimStrideData, dwVertexCount, dwFlags);
1281 if (TRACE_ON(ddraw)) {
1282 TRACE(" - flags : "); dump_DPFLAGS(dwFlags);
1284 draw_primitive_strided(This, d3dptPrimitiveType, dwVertexType, lpD3DDrawPrimStrideData, dwVertexCount, NULL, dwVertexCount, dwFlags);
1286 return DD_OK;
1289 HRESULT WINAPI
1290 GL_IDirect3DDeviceImpl_7_3T_DrawIndexedPrimitiveStrided(LPDIRECT3DDEVICE7 iface,
1291 D3DPRIMITIVETYPE d3dptPrimitiveType,
1292 DWORD dwVertexType,
1293 LPD3DDRAWPRIMITIVESTRIDEDDATA lpD3DDrawPrimStrideData,
1294 DWORD dwVertexCount,
1295 LPWORD lpIndex,
1296 DWORD dwIndexCount,
1297 DWORD dwFlags)
1299 ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice7, iface);
1301 TRACE("(%p/%p)->(%08x,%08lx,%p,%08lx,%p,%08lx,%08lx)\n", This, iface, d3dptPrimitiveType, dwVertexType, lpD3DDrawPrimStrideData, dwVertexCount, lpIndex, dwIndexCount, dwFlags);
1302 if (TRACE_ON(ddraw)) {
1303 TRACE(" - flags : "); dump_DPFLAGS(dwFlags);
1306 draw_primitive_strided(This, d3dptPrimitiveType, dwVertexType, lpD3DDrawPrimStrideData, dwVertexCount, lpIndex, dwIndexCount, dwFlags);
1308 return DD_OK;
1311 HRESULT WINAPI
1312 GL_IDirect3DDeviceImpl_7_3T_DrawPrimitiveVB(LPDIRECT3DDEVICE7 iface,
1313 D3DPRIMITIVETYPE d3dptPrimitiveType,
1314 LPDIRECT3DVERTEXBUFFER7 lpD3DVertexBuf,
1315 DWORD dwStartVertex,
1316 DWORD dwNumVertices,
1317 DWORD dwFlags)
1319 ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice7, iface);
1320 IDirect3DVertexBufferImpl *vb_impl = ICOM_OBJECT(IDirect3DVertexBufferImpl, IDirect3DVertexBuffer7, lpD3DVertexBuf);
1321 D3DDRAWPRIMITIVESTRIDEDDATA strided;
1323 TRACE("(%p/%p)->(%08x,%p,%08lx,%08lx,%08lx)\n", This, iface, d3dptPrimitiveType, lpD3DVertexBuf, dwStartVertex, dwNumVertices, dwFlags);
1324 if (TRACE_ON(ddraw)) {
1325 TRACE(" - flags : "); dump_DPFLAGS(dwFlags);
1328 if (vb_impl->processed == TRUE) {
1329 IDirect3DVertexBufferGLImpl *vb_glimp = (IDirect3DVertexBufferGLImpl *) vb_impl;
1330 IDirect3DDeviceGLImpl *glThis = (IDirect3DDeviceGLImpl *) This;
1332 glThis->transform_state = GL_TRANSFORM_VERTEXBUFFER;
1333 This->set_matrices(This, VIEWMAT_CHANGED|WORLDMAT_CHANGED|PROJMAT_CHANGED,
1334 &(vb_glimp->world_mat), &(vb_glimp->view_mat), &(vb_glimp->proj_mat));
1336 convert_FVF_to_strided_data(vb_glimp->dwVertexTypeDesc, vb_glimp->vertices, &strided, dwStartVertex);
1337 draw_primitive_strided(This, d3dptPrimitiveType, vb_glimp->dwVertexTypeDesc, &strided, dwNumVertices, NULL, dwNumVertices, dwFlags);
1339 } else {
1340 convert_FVF_to_strided_data(vb_impl->desc.dwFVF, vb_impl->vertices, &strided, dwStartVertex);
1341 draw_primitive_strided(This, d3dptPrimitiveType, vb_impl->desc.dwFVF, &strided, dwNumVertices, NULL, dwNumVertices, dwFlags);
1344 return DD_OK;
1347 HRESULT WINAPI
1348 GL_IDirect3DDeviceImpl_7_3T_DrawIndexedPrimitiveVB(LPDIRECT3DDEVICE7 iface,
1349 D3DPRIMITIVETYPE d3dptPrimitiveType,
1350 LPDIRECT3DVERTEXBUFFER7 lpD3DVertexBuf,
1351 DWORD dwStartVertex,
1352 DWORD dwNumVertices,
1353 LPWORD lpwIndices,
1354 DWORD dwIndexCount,
1355 DWORD dwFlags)
1357 ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice7, iface);
1358 IDirect3DVertexBufferImpl *vb_impl = ICOM_OBJECT(IDirect3DVertexBufferImpl, IDirect3DVertexBuffer7, lpD3DVertexBuf);
1359 D3DDRAWPRIMITIVESTRIDEDDATA strided;
1361 TRACE("(%p/%p)->(%08x,%p,%08lx,%08lx,%p,%08lx,%08lx)\n", This, iface, d3dptPrimitiveType, lpD3DVertexBuf, dwStartVertex, dwNumVertices, lpwIndices, dwIndexCount, dwFlags);
1362 if (TRACE_ON(ddraw)) {
1363 TRACE(" - flags : "); dump_DPFLAGS(dwFlags);
1366 if (vb_impl->processed == TRUE) {
1367 IDirect3DVertexBufferGLImpl *vb_glimp = (IDirect3DVertexBufferGLImpl *) vb_impl;
1368 IDirect3DDeviceGLImpl *glThis = (IDirect3DDeviceGLImpl *) This;
1370 glThis->transform_state = GL_TRANSFORM_VERTEXBUFFER;
1371 This->set_matrices(This, VIEWMAT_CHANGED|WORLDMAT_CHANGED|PROJMAT_CHANGED,
1372 &(vb_glimp->world_mat), &(vb_glimp->view_mat), &(vb_glimp->proj_mat));
1374 convert_FVF_to_strided_data(vb_glimp->dwVertexTypeDesc, vb_glimp->vertices, &strided, dwStartVertex);
1375 draw_primitive_strided(This, d3dptPrimitiveType, vb_glimp->dwVertexTypeDesc, &strided, dwNumVertices, lpwIndices, dwIndexCount, dwFlags);
1377 } else {
1378 convert_FVF_to_strided_data(vb_impl->desc.dwFVF, vb_impl->vertices, &strided, dwStartVertex);
1379 draw_primitive_strided(This, d3dptPrimitiveType, vb_impl->desc.dwFVF, &strided, dwNumVertices, lpwIndices, dwIndexCount, dwFlags);
1382 return DD_OK;
1385 static GLenum
1386 convert_min_filter_to_GL(D3DTEXTUREMINFILTER dwState)
1388 GLenum gl_state;
1390 switch (dwState) {
1391 case D3DTFN_POINT:
1392 gl_state = GL_NEAREST;
1393 break;
1394 case D3DTFN_LINEAR:
1395 gl_state = GL_LINEAR;
1396 break;
1397 default:
1398 gl_state = GL_LINEAR;
1399 break;
1401 return gl_state;
1404 static GLenum
1405 convert_mag_filter_to_GL(D3DTEXTUREMAGFILTER dwState)
1407 GLenum gl_state;
1409 switch (dwState) {
1410 case D3DTFG_POINT:
1411 gl_state = GL_NEAREST;
1412 break;
1413 case D3DTFG_LINEAR:
1414 gl_state = GL_LINEAR;
1415 break;
1416 default:
1417 gl_state = GL_LINEAR;
1418 break;
1420 return gl_state;
1423 HRESULT WINAPI
1424 GL_IDirect3DDeviceImpl_7_3T_SetTextureStageState(LPDIRECT3DDEVICE7 iface,
1425 DWORD dwStage,
1426 D3DTEXTURESTAGESTATETYPE d3dTexStageStateType,
1427 DWORD dwState)
1429 ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice7, iface);
1431 TRACE("(%p/%p)->(%08lx,%08x,%08lx)\n", This, iface, dwStage, d3dTexStageStateType, dwState);
1433 if (dwStage > 0) return DD_OK; /* We nothing in this case for now */
1435 if (TRACE_ON(ddraw)) {
1436 TRACE(" Stage type is : ");
1437 switch (d3dTexStageStateType) {
1438 #define GEN_CASE(a) case a: TRACE(#a " "); break
1439 GEN_CASE(D3DTSS_COLOROP);
1440 GEN_CASE(D3DTSS_COLORARG1);
1441 GEN_CASE(D3DTSS_COLORARG2);
1442 GEN_CASE(D3DTSS_ALPHAOP);
1443 GEN_CASE(D3DTSS_ALPHAARG1);
1444 GEN_CASE(D3DTSS_ALPHAARG2);
1445 GEN_CASE(D3DTSS_BUMPENVMAT00);
1446 GEN_CASE(D3DTSS_BUMPENVMAT01);
1447 GEN_CASE(D3DTSS_BUMPENVMAT10);
1448 GEN_CASE(D3DTSS_BUMPENVMAT11);
1449 GEN_CASE(D3DTSS_TEXCOORDINDEX);
1450 GEN_CASE(D3DTSS_ADDRESS);
1451 GEN_CASE(D3DTSS_ADDRESSU);
1452 GEN_CASE(D3DTSS_ADDRESSV);
1453 GEN_CASE(D3DTSS_BORDERCOLOR);
1454 GEN_CASE(D3DTSS_MAGFILTER);
1455 GEN_CASE(D3DTSS_MINFILTER);
1456 GEN_CASE(D3DTSS_MIPFILTER);
1457 GEN_CASE(D3DTSS_MIPMAPLODBIAS);
1458 GEN_CASE(D3DTSS_MAXMIPLEVEL);
1459 GEN_CASE(D3DTSS_MAXANISOTROPY);
1460 GEN_CASE(D3DTSS_BUMPENVLSCALE);
1461 GEN_CASE(D3DTSS_BUMPENVLOFFSET);
1462 GEN_CASE(D3DTSS_TEXTURETRANSFORMFLAGS);
1463 #undef GEN_CASE
1464 default: TRACE("UNKNOWN !!!");
1466 TRACE(" => ");
1469 switch (d3dTexStageStateType) {
1470 case D3DTSS_MINFILTER:
1471 if (TRACE_ON(ddraw)) {
1472 switch ((D3DTEXTUREMINFILTER) dwState) {
1473 case D3DTFN_POINT: TRACE("D3DTFN_POINT\n"); break;
1474 case D3DTFN_LINEAR: TRACE("D3DTFN_LINEAR\n"); break;
1475 default: TRACE(" state unhandled (%ld).\n", dwState); break;
1478 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, convert_min_filter_to_GL(dwState));
1479 break;
1481 case D3DTSS_MAGFILTER:
1482 if (TRACE_ON(ddraw)) {
1483 switch ((D3DTEXTUREMAGFILTER) dwState) {
1484 case D3DTFG_POINT: TRACE("D3DTFN_POINT\n"); break;
1485 case D3DTFG_LINEAR: TRACE("D3DTFN_LINEAR\n"); break;
1486 default: TRACE(" state unhandled (%ld).\n", dwState); break;
1489 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, convert_mag_filter_to_GL(dwState));
1490 break;
1492 case D3DTSS_ADDRESS:
1493 case D3DTSS_ADDRESSU:
1494 case D3DTSS_ADDRESSV: {
1495 GLenum arg = GL_REPEAT; /* Default value */
1496 switch ((D3DTEXTUREADDRESS) dwState) {
1497 case D3DTADDRESS_WRAP: if (TRACE_ON(ddraw)) TRACE("D3DTADDRESS_WRAP\n"); arg = GL_REPEAT; break;
1498 case D3DTADDRESS_CLAMP: if (TRACE_ON(ddraw)) TRACE("D3DTADDRESS_CLAMP\n"); arg = GL_CLAMP; break;
1499 case D3DTADDRESS_BORDER: if (TRACE_ON(ddraw)) TRACE("D3DTADDRESS_BORDER\n"); arg = GL_CLAMP_TO_EDGE; break;
1500 default: TRACE(" state unhandled (%ld).\n", dwState);
1502 if ((d3dTexStageStateType == D3DTSS_ADDRESS) ||
1503 (d3dTexStageStateType == D3DTSS_ADDRESSU))
1504 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, arg);
1505 if ((d3dTexStageStateType == D3DTSS_ADDRESS) ||
1506 (d3dTexStageStateType == D3DTSS_ADDRESSV))
1507 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, arg);
1508 } break;
1510 default:
1511 if (TRACE_ON(ddraw)) TRACE(" unhandled.\n");
1514 This->state_block.texture_stage_state[dwStage][d3dTexStageStateType - 1] = dwState;
1515 /* Some special cases when one state modifies more than one... */
1516 if (d3dTexStageStateType == D3DTSS_ADDRESS) {
1517 This->state_block.texture_stage_state[dwStage][D3DTSS_ADDRESSU - 1] = dwState;
1518 This->state_block.texture_stage_state[dwStage][D3DTSS_ADDRESSV - 1] = dwState;
1521 return DD_OK;
1524 HRESULT WINAPI
1525 GL_IDirect3DDeviceImpl_7_3T_SetTexture(LPDIRECT3DDEVICE7 iface,
1526 DWORD dwStage,
1527 LPDIRECTDRAWSURFACE7 lpTexture2)
1529 ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice7, iface);
1531 TRACE("(%p/%p)->(%08lx,%p)\n", This, iface, dwStage, lpTexture2);
1533 if (dwStage > 0) return DD_OK;
1535 if (This->current_texture[dwStage] != NULL) {
1536 IDirectDrawSurface7_Release(ICOM_INTERFACE(This->current_texture[dwStage], IDirectDrawSurface7));
1539 ENTER_GL();
1540 if (lpTexture2 == NULL) {
1541 This->current_texture[dwStage] = NULL;
1543 TRACE(" disabling 2D texturing.\n");
1544 glBindTexture(GL_TEXTURE_2D, 0);
1545 glDisable(GL_TEXTURE_2D);
1546 } else {
1547 IDirectDrawSurfaceImpl *tex_impl = ICOM_OBJECT(IDirectDrawSurfaceImpl, IDirectDrawSurface7, lpTexture2);
1549 This->current_texture[dwStage] = tex_impl;
1550 IDirectDrawSurface7_AddRef(ICOM_INTERFACE(tex_impl, IDirectDrawSurface7)); /* Not sure about this either */
1552 glEnable(GL_TEXTURE_2D);
1553 gltex_upload_texture(tex_impl);
1555 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER,
1556 convert_mag_filter_to_GL(This->state_block.texture_stage_state[dwStage][D3DTSS_MAGFILTER - 1]));
1557 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER,
1558 convert_min_filter_to_GL(This->state_block.texture_stage_state[dwStage][D3DTSS_MINFILTER - 1]));
1560 LEAVE_GL();
1562 return DD_OK;
1565 HRESULT WINAPI
1566 GL_IDirect3DDeviceImpl_7_GetCaps(LPDIRECT3DDEVICE7 iface,
1567 LPD3DDEVICEDESC7 lpD3DHELDevDesc)
1569 ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice7, iface);
1570 TRACE("(%p/%p)->(%p)\n", This, iface, lpD3DHELDevDesc);
1572 fill_opengl_caps_7(lpD3DHELDevDesc);
1574 TRACE(" returning caps : no dump function yet.\n");
1576 return DD_OK;
1579 HRESULT WINAPI
1580 GL_IDirect3DDeviceImpl_7_SetMaterial(LPDIRECT3DDEVICE7 iface,
1581 LPD3DMATERIAL7 lpMat)
1583 ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice7, iface);
1584 TRACE("(%p/%p)->(%p)\n", This, iface, lpMat);
1586 if (TRACE_ON(ddraw)) {
1587 TRACE(" material is : \n");
1588 dump_D3DMATERIAL7(lpMat);
1591 This->current_material = *lpMat;
1593 glMaterialfv(GL_FRONT_AND_BACK,
1594 GL_DIFFUSE,
1595 (float *) &(This->current_material.u.diffuse));
1596 glMaterialfv(GL_FRONT_AND_BACK,
1597 GL_AMBIENT,
1598 (float *) &(This->current_material.u1.ambient));
1599 glMaterialfv(GL_FRONT_AND_BACK,
1600 GL_SPECULAR,
1601 (float *) &(This->current_material.u2.specular));
1602 glMaterialfv(GL_FRONT_AND_BACK,
1603 GL_EMISSION,
1604 (float *) &(This->current_material.u3.emissive));
1605 glMaterialf(GL_FRONT_AND_BACK,
1606 GL_SHININESS,
1607 This->current_material.u4.power); /* Not sure about this... */
1609 return DD_OK;
1613 HRESULT WINAPI
1614 GL_IDirect3DDeviceImpl_7_SetLight(LPDIRECT3DDEVICE7 iface,
1615 DWORD dwLightIndex,
1616 LPD3DLIGHT7 lpLight)
1618 ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice7, iface);
1619 TRACE("(%p/%p)->(%08lx,%p)\n", This, iface, dwLightIndex, lpLight);
1621 if (TRACE_ON(ddraw)) {
1622 TRACE(" setting light : \n");
1623 dump_D3DLIGHT7(lpLight);
1626 if (dwLightIndex > MAX_LIGHTS) return DDERR_INVALIDPARAMS;
1627 This->set_lights |= 0x00000001 << dwLightIndex;
1628 This->light_parameters[dwLightIndex] = *lpLight;
1630 switch (lpLight->dltType) {
1631 case D3DLIGHT_DIRECTIONAL: {
1632 float direction[4];
1633 float cut_off = 180.0;
1635 glLightfv(GL_LIGHT0 + dwLightIndex, GL_AMBIENT, (float *) &(lpLight->dcvAmbient));
1636 glLightfv(GL_LIGHT0 + dwLightIndex, GL_DIFFUSE, (float *) &(lpLight->dcvDiffuse));
1637 glLightfv(GL_LIGHT0 + dwLightIndex, GL_SPECULAR, (float *) &(lpLight->dcvSpecular));
1638 glLightfv(GL_LIGHT0 + dwLightIndex, GL_SPOT_CUTOFF, &cut_off);
1640 direction[0] = lpLight->dvDirection.u1.x;
1641 direction[1] = lpLight->dvDirection.u2.y;
1642 direction[2] = lpLight->dvDirection.u3.z;
1643 direction[3] = 0.0;
1644 glLightfv(GL_LIGHT0 + dwLightIndex, GL_POSITION, (float *) direction);
1645 } break;
1647 case D3DLIGHT_POINT: {
1648 float position[4];
1649 float cut_off = 180.0;
1651 glLightfv(GL_LIGHT0 + dwLightIndex, GL_AMBIENT, (float *) &(lpLight->dcvAmbient));
1652 glLightfv(GL_LIGHT0 + dwLightIndex, GL_DIFFUSE, (float *) &(lpLight->dcvDiffuse));
1653 glLightfv(GL_LIGHT0 + dwLightIndex, GL_SPECULAR, (float *) &(lpLight->dcvSpecular));
1654 position[0] = lpLight->dvPosition.u1.x;
1655 position[1] = lpLight->dvPosition.u2.y;
1656 position[2] = lpLight->dvPosition.u3.z;
1657 position[3] = 1.0;
1658 glLightfv(GL_LIGHT0 + dwLightIndex, GL_POSITION, (float *) position);
1659 glLightfv(GL_LIGHT0 + dwLightIndex, GL_CONSTANT_ATTENUATION, &(lpLight->dvAttenuation0));
1660 glLightfv(GL_LIGHT0 + dwLightIndex, GL_LINEAR_ATTENUATION, &(lpLight->dvAttenuation1));
1661 glLightfv(GL_LIGHT0 + dwLightIndex, GL_QUADRATIC_ATTENUATION, &(lpLight->dvAttenuation2));
1662 glLightfv(GL_LIGHT0 + dwLightIndex, GL_SPOT_CUTOFF, &cut_off);
1663 } break;
1665 case D3DLIGHT_SPOT: {
1666 float direction[4];
1667 float position[4];
1668 float cut_off = 90.0 * (lpLight->dvPhi / M_PI);
1670 glLightfv(GL_LIGHT0 + dwLightIndex, GL_AMBIENT, (float *) &(lpLight->dcvAmbient));
1671 glLightfv(GL_LIGHT0 + dwLightIndex, GL_DIFFUSE, (float *) &(lpLight->dcvDiffuse));
1672 glLightfv(GL_LIGHT0 + dwLightIndex, GL_SPECULAR, (float *) &(lpLight->dcvSpecular));
1674 direction[0] = lpLight->dvDirection.u1.x;
1675 direction[1] = lpLight->dvDirection.u2.y;
1676 direction[2] = lpLight->dvDirection.u3.z;
1677 direction[3] = 0.0;
1678 glLightfv(GL_LIGHT0 + dwLightIndex, GL_SPOT_DIRECTION, (float *) direction);
1679 position[0] = lpLight->dvPosition.u1.x;
1680 position[1] = lpLight->dvPosition.u2.y;
1681 position[2] = lpLight->dvPosition.u3.z;
1682 position[3] = 1.0;
1683 glLightfv(GL_LIGHT0 + dwLightIndex, GL_POSITION, (float *) position);
1684 glLightfv(GL_LIGHT0 + dwLightIndex, GL_CONSTANT_ATTENUATION, &(lpLight->dvAttenuation0));
1685 glLightfv(GL_LIGHT0 + dwLightIndex, GL_LINEAR_ATTENUATION, &(lpLight->dvAttenuation1));
1686 glLightfv(GL_LIGHT0 + dwLightIndex, GL_QUADRATIC_ATTENUATION, &(lpLight->dvAttenuation2));
1687 glLightfv(GL_LIGHT0 + dwLightIndex, GL_SPOT_CUTOFF, &cut_off);
1688 glLightfv(GL_LIGHT0 + dwLightIndex, GL_SPOT_EXPONENT, &(lpLight->dvFalloff));
1689 if ((lpLight->dvTheta != 0.0) || (lpLight->dvTheta != lpLight->dvPhi)) {
1690 WARN("dvTheta not fully supported yet !\n");
1692 } break;
1694 default: WARN(" light type not handled yet...\n");
1697 return DD_OK;
1700 HRESULT WINAPI
1701 GL_IDirect3DDeviceImpl_7_LightEnable(LPDIRECT3DDEVICE7 iface,
1702 DWORD dwLightIndex,
1703 BOOL bEnable)
1705 ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice7, iface);
1706 TRACE("(%p/%p)->(%08lx,%d)\n", This, iface, dwLightIndex, bEnable);
1708 if (dwLightIndex > MAX_LIGHTS) return DDERR_INVALIDPARAMS;
1710 if (bEnable) {
1711 if (((0x00000001 << dwLightIndex) & This->set_lights) == 0) {
1712 /* Set the default parameters.. */
1713 TRACE(" setting default light parameters...\n");
1714 GL_IDirect3DDeviceImpl_7_SetLight(iface, dwLightIndex, &(This->light_parameters[dwLightIndex]));
1716 glEnable(GL_LIGHT0 + dwLightIndex);
1717 } else {
1718 glDisable(GL_LIGHT0 + dwLightIndex);
1721 return DD_OK;
1724 HRESULT WINAPI
1725 GL_IDirect3DDeviceImpl_7_SetClipPlane(LPDIRECT3DDEVICE7 iface, DWORD dwIndex, CONST D3DVALUE* pPlaneEquation)
1727 ICOM_THIS(IDirect3DDeviceImpl,iface);
1728 GLdouble plane[4];
1730 TRACE("(%p)->(%ld,%p)\n", This, dwIndex, pPlaneEquation);
1732 if (dwIndex>=This->max_clipping_planes) {
1733 return DDERR_INVALIDPARAMS;
1736 TRACE(" clip plane %ld : %f %f %f %f\n", dwIndex, pPlaneEquation[0], pPlaneEquation[1], pPlaneEquation[2], pPlaneEquation[3] );
1738 memcpy( This->clipping_planes[dwIndex].plane, pPlaneEquation, sizeof(D3DVALUE[4]));
1739 plane[0] = pPlaneEquation[0];
1740 plane[1] = pPlaneEquation[1];
1741 plane[2] = pPlaneEquation[2];
1742 plane[3] = pPlaneEquation[3];
1744 /* XXX: is here also code needed to handle the transformation of the world? */
1745 glClipPlane( GL_CLIP_PLANE0+dwIndex, (const GLdouble*)(&plane) );
1747 return D3D_OK;
1750 #if !defined(__STRICT_ANSI__) && defined(__GNUC__)
1751 # define XCAST(fun) (typeof(VTABLE_IDirect3DDevice7.fun))
1752 #else
1753 # define XCAST(fun) (void*)
1754 #endif
1756 ICOM_VTABLE(IDirect3DDevice7) VTABLE_IDirect3DDevice7 =
1758 ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
1759 XCAST(QueryInterface) Main_IDirect3DDeviceImpl_7_3T_2T_1T_QueryInterface,
1760 XCAST(AddRef) Main_IDirect3DDeviceImpl_7_3T_2T_1T_AddRef,
1761 XCAST(Release) GL_IDirect3DDeviceImpl_7_3T_2T_1T_Release,
1762 XCAST(GetCaps) GL_IDirect3DDeviceImpl_7_GetCaps,
1763 XCAST(EnumTextureFormats) GL_IDirect3DDeviceImpl_7_3T_EnumTextureFormats,
1764 XCAST(BeginScene) Main_IDirect3DDeviceImpl_7_3T_2T_1T_BeginScene,
1765 XCAST(EndScene) Main_IDirect3DDeviceImpl_7_3T_2T_1T_EndScene,
1766 XCAST(GetDirect3D) Main_IDirect3DDeviceImpl_7_3T_2T_1T_GetDirect3D,
1767 XCAST(SetRenderTarget) Main_IDirect3DDeviceImpl_7_3T_2T_SetRenderTarget,
1768 XCAST(GetRenderTarget) Main_IDirect3DDeviceImpl_7_3T_2T_GetRenderTarget,
1769 XCAST(Clear) Main_IDirect3DDeviceImpl_7_Clear,
1770 XCAST(SetTransform) Main_IDirect3DDeviceImpl_7_3T_2T_SetTransform,
1771 XCAST(GetTransform) Main_IDirect3DDeviceImpl_7_3T_2T_GetTransform,
1772 XCAST(SetViewport) Main_IDirect3DDeviceImpl_7_SetViewport,
1773 XCAST(MultiplyTransform) Main_IDirect3DDeviceImpl_7_3T_2T_MultiplyTransform,
1774 XCAST(GetViewport) Main_IDirect3DDeviceImpl_7_GetViewport,
1775 XCAST(SetMaterial) GL_IDirect3DDeviceImpl_7_SetMaterial,
1776 XCAST(GetMaterial) Main_IDirect3DDeviceImpl_7_GetMaterial,
1777 XCAST(SetLight) GL_IDirect3DDeviceImpl_7_SetLight,
1778 XCAST(GetLight) Main_IDirect3DDeviceImpl_7_GetLight,
1779 XCAST(SetRenderState) GL_IDirect3DDeviceImpl_7_3T_2T_SetRenderState,
1780 XCAST(GetRenderState) GL_IDirect3DDeviceImpl_7_3T_2T_GetRenderState,
1781 XCAST(BeginStateBlock) Main_IDirect3DDeviceImpl_7_BeginStateBlock,
1782 XCAST(EndStateBlock) Main_IDirect3DDeviceImpl_7_EndStateBlock,
1783 XCAST(PreLoad) Main_IDirect3DDeviceImpl_7_PreLoad,
1784 XCAST(DrawPrimitive) GL_IDirect3DDeviceImpl_7_3T_DrawPrimitive,
1785 XCAST(DrawIndexedPrimitive) GL_IDirect3DDeviceImpl_7_3T_DrawIndexedPrimitive,
1786 XCAST(SetClipStatus) Main_IDirect3DDeviceImpl_7_3T_2T_SetClipStatus,
1787 XCAST(GetClipStatus) Main_IDirect3DDeviceImpl_7_3T_2T_GetClipStatus,
1788 XCAST(DrawPrimitiveStrided) GL_IDirect3DDeviceImpl_7_3T_DrawPrimitiveStrided,
1789 XCAST(DrawIndexedPrimitiveStrided) GL_IDirect3DDeviceImpl_7_3T_DrawIndexedPrimitiveStrided,
1790 XCAST(DrawPrimitiveVB) GL_IDirect3DDeviceImpl_7_3T_DrawPrimitiveVB,
1791 XCAST(DrawIndexedPrimitiveVB) GL_IDirect3DDeviceImpl_7_3T_DrawIndexedPrimitiveVB,
1792 XCAST(ComputeSphereVisibility) Main_IDirect3DDeviceImpl_7_3T_ComputeSphereVisibility,
1793 XCAST(GetTexture) Main_IDirect3DDeviceImpl_7_3T_GetTexture,
1794 XCAST(SetTexture) GL_IDirect3DDeviceImpl_7_3T_SetTexture,
1795 XCAST(GetTextureStageState) Main_IDirect3DDeviceImpl_7_3T_GetTextureStageState,
1796 XCAST(SetTextureStageState) GL_IDirect3DDeviceImpl_7_3T_SetTextureStageState,
1797 XCAST(ValidateDevice) Main_IDirect3DDeviceImpl_7_3T_ValidateDevice,
1798 XCAST(ApplyStateBlock) Main_IDirect3DDeviceImpl_7_ApplyStateBlock,
1799 XCAST(CaptureStateBlock) Main_IDirect3DDeviceImpl_7_CaptureStateBlock,
1800 XCAST(DeleteStateBlock) Main_IDirect3DDeviceImpl_7_DeleteStateBlock,
1801 XCAST(CreateStateBlock) Main_IDirect3DDeviceImpl_7_CreateStateBlock,
1802 XCAST(Load) Main_IDirect3DDeviceImpl_7_Load,
1803 XCAST(LightEnable) GL_IDirect3DDeviceImpl_7_LightEnable,
1804 XCAST(GetLightEnable) Main_IDirect3DDeviceImpl_7_GetLightEnable,
1805 XCAST(SetClipPlane) GL_IDirect3DDeviceImpl_7_SetClipPlane,
1806 XCAST(GetClipPlane) Main_IDirect3DDeviceImpl_7_GetClipPlane,
1807 XCAST(GetInfo) Main_IDirect3DDeviceImpl_7_GetInfo,
1810 #if !defined(__STRICT_ANSI__) && defined(__GNUC__)
1811 #undef XCAST
1812 #endif
1815 #if !defined(__STRICT_ANSI__) && defined(__GNUC__)
1816 # define XCAST(fun) (typeof(VTABLE_IDirect3DDevice3.fun))
1817 #else
1818 # define XCAST(fun) (void*)
1819 #endif
1821 ICOM_VTABLE(IDirect3DDevice3) VTABLE_IDirect3DDevice3 =
1823 ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
1824 XCAST(QueryInterface) Thunk_IDirect3DDeviceImpl_3_QueryInterface,
1825 XCAST(AddRef) Thunk_IDirect3DDeviceImpl_3_AddRef,
1826 XCAST(Release) Thunk_IDirect3DDeviceImpl_3_Release,
1827 XCAST(GetCaps) GL_IDirect3DDeviceImpl_3_2T_1T_GetCaps,
1828 XCAST(GetStats) Main_IDirect3DDeviceImpl_3_2T_1T_GetStats,
1829 XCAST(AddViewport) Main_IDirect3DDeviceImpl_3_2T_1T_AddViewport,
1830 XCAST(DeleteViewport) Main_IDirect3DDeviceImpl_3_2T_1T_DeleteViewport,
1831 XCAST(NextViewport) Main_IDirect3DDeviceImpl_3_2T_1T_NextViewport,
1832 XCAST(EnumTextureFormats) Thunk_IDirect3DDeviceImpl_3_EnumTextureFormats,
1833 XCAST(BeginScene) Thunk_IDirect3DDeviceImpl_3_BeginScene,
1834 XCAST(EndScene) Thunk_IDirect3DDeviceImpl_3_EndScene,
1835 XCAST(GetDirect3D) Thunk_IDirect3DDeviceImpl_3_GetDirect3D,
1836 XCAST(SetCurrentViewport) Main_IDirect3DDeviceImpl_3_2T_SetCurrentViewport,
1837 XCAST(GetCurrentViewport) Main_IDirect3DDeviceImpl_3_2T_GetCurrentViewport,
1838 XCAST(SetRenderTarget) Thunk_IDirect3DDeviceImpl_3_SetRenderTarget,
1839 XCAST(GetRenderTarget) Thunk_IDirect3DDeviceImpl_3_GetRenderTarget,
1840 XCAST(Begin) Main_IDirect3DDeviceImpl_3_Begin,
1841 XCAST(BeginIndexed) Main_IDirect3DDeviceImpl_3_BeginIndexed,
1842 XCAST(Vertex) Main_IDirect3DDeviceImpl_3_2T_Vertex,
1843 XCAST(Index) Main_IDirect3DDeviceImpl_3_2T_Index,
1844 XCAST(End) Main_IDirect3DDeviceImpl_3_2T_End,
1845 XCAST(GetRenderState) Thunk_IDirect3DDeviceImpl_3_GetRenderState,
1846 XCAST(SetRenderState) Thunk_IDirect3DDeviceImpl_3_SetRenderState,
1847 XCAST(GetLightState) Main_IDirect3DDeviceImpl_3_2T_GetLightState,
1848 XCAST(SetLightState) GL_IDirect3DDeviceImpl_3_2T_SetLightState,
1849 XCAST(SetTransform) Thunk_IDirect3DDeviceImpl_3_SetTransform,
1850 XCAST(GetTransform) Thunk_IDirect3DDeviceImpl_3_GetTransform,
1851 XCAST(MultiplyTransform) Thunk_IDirect3DDeviceImpl_3_MultiplyTransform,
1852 XCAST(DrawPrimitive) Thunk_IDirect3DDeviceImpl_3_DrawPrimitive,
1853 XCAST(DrawIndexedPrimitive) Thunk_IDirect3DDeviceImpl_3_DrawIndexedPrimitive,
1854 XCAST(SetClipStatus) Thunk_IDirect3DDeviceImpl_3_SetClipStatus,
1855 XCAST(GetClipStatus) Thunk_IDirect3DDeviceImpl_3_GetClipStatus,
1856 XCAST(DrawPrimitiveStrided) Thunk_IDirect3DDeviceImpl_3_DrawPrimitiveStrided,
1857 XCAST(DrawIndexedPrimitiveStrided) Thunk_IDirect3DDeviceImpl_3_DrawIndexedPrimitiveStrided,
1858 XCAST(DrawPrimitiveVB) Thunk_IDirect3DDeviceImpl_3_DrawPrimitiveVB,
1859 XCAST(DrawIndexedPrimitiveVB) Thunk_IDirect3DDeviceImpl_3_DrawIndexedPrimitiveVB,
1860 XCAST(ComputeSphereVisibility) Thunk_IDirect3DDeviceImpl_3_ComputeSphereVisibility,
1861 XCAST(GetTexture) Thunk_IDirect3DDeviceImpl_3_GetTexture,
1862 XCAST(SetTexture) Thunk_IDirect3DDeviceImpl_3_SetTexture,
1863 XCAST(GetTextureStageState) Thunk_IDirect3DDeviceImpl_3_GetTextureStageState,
1864 XCAST(SetTextureStageState) Thunk_IDirect3DDeviceImpl_3_SetTextureStageState,
1865 XCAST(ValidateDevice) Thunk_IDirect3DDeviceImpl_3_ValidateDevice,
1868 #if !defined(__STRICT_ANSI__) && defined(__GNUC__)
1869 #undef XCAST
1870 #endif
1873 #if !defined(__STRICT_ANSI__) && defined(__GNUC__)
1874 # define XCAST(fun) (typeof(VTABLE_IDirect3DDevice2.fun))
1875 #else
1876 # define XCAST(fun) (void*)
1877 #endif
1879 ICOM_VTABLE(IDirect3DDevice2) VTABLE_IDirect3DDevice2 =
1881 ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
1882 XCAST(QueryInterface) Thunk_IDirect3DDeviceImpl_2_QueryInterface,
1883 XCAST(AddRef) Thunk_IDirect3DDeviceImpl_2_AddRef,
1884 XCAST(Release) Thunk_IDirect3DDeviceImpl_2_Release,
1885 XCAST(GetCaps) Thunk_IDirect3DDeviceImpl_2_GetCaps,
1886 XCAST(SwapTextureHandles) Main_IDirect3DDeviceImpl_2_1T_SwapTextureHandles,
1887 XCAST(GetStats) Thunk_IDirect3DDeviceImpl_2_GetStats,
1888 XCAST(AddViewport) Thunk_IDirect3DDeviceImpl_2_AddViewport,
1889 XCAST(DeleteViewport) Thunk_IDirect3DDeviceImpl_2_DeleteViewport,
1890 XCAST(NextViewport) Thunk_IDirect3DDeviceImpl_2_NextViewport,
1891 XCAST(EnumTextureFormats) GL_IDirect3DDeviceImpl_2_1T_EnumTextureFormats,
1892 XCAST(BeginScene) Thunk_IDirect3DDeviceImpl_2_BeginScene,
1893 XCAST(EndScene) Thunk_IDirect3DDeviceImpl_2_EndScene,
1894 XCAST(GetDirect3D) Thunk_IDirect3DDeviceImpl_2_GetDirect3D,
1895 XCAST(SetCurrentViewport) Thunk_IDirect3DDeviceImpl_2_SetCurrentViewport,
1896 XCAST(GetCurrentViewport) Thunk_IDirect3DDeviceImpl_2_GetCurrentViewport,
1897 XCAST(SetRenderTarget) Thunk_IDirect3DDeviceImpl_2_SetRenderTarget,
1898 XCAST(GetRenderTarget) Thunk_IDirect3DDeviceImpl_2_GetRenderTarget,
1899 XCAST(Begin) Main_IDirect3DDeviceImpl_2_Begin,
1900 XCAST(BeginIndexed) Main_IDirect3DDeviceImpl_2_BeginIndexed,
1901 XCAST(Vertex) Thunk_IDirect3DDeviceImpl_2_Vertex,
1902 XCAST(Index) Thunk_IDirect3DDeviceImpl_2_Index,
1903 XCAST(End) Thunk_IDirect3DDeviceImpl_2_End,
1904 XCAST(GetRenderState) Thunk_IDirect3DDeviceImpl_2_GetRenderState,
1905 XCAST(SetRenderState) Thunk_IDirect3DDeviceImpl_2_SetRenderState,
1906 XCAST(GetLightState) Thunk_IDirect3DDeviceImpl_2_GetLightState,
1907 XCAST(SetLightState) Thunk_IDirect3DDeviceImpl_2_SetLightState,
1908 XCAST(SetTransform) Thunk_IDirect3DDeviceImpl_2_SetTransform,
1909 XCAST(GetTransform) Thunk_IDirect3DDeviceImpl_2_GetTransform,
1910 XCAST(MultiplyTransform) Thunk_IDirect3DDeviceImpl_2_MultiplyTransform,
1911 XCAST(DrawPrimitive) GL_IDirect3DDeviceImpl_2_DrawPrimitive,
1912 XCAST(DrawIndexedPrimitive) GL_IDirect3DDeviceImpl_2_DrawIndexedPrimitive,
1913 XCAST(SetClipStatus) Thunk_IDirect3DDeviceImpl_2_SetClipStatus,
1914 XCAST(GetClipStatus) Thunk_IDirect3DDeviceImpl_2_GetClipStatus,
1917 #if !defined(__STRICT_ANSI__) && defined(__GNUC__)
1918 #undef XCAST
1919 #endif
1922 #if !defined(__STRICT_ANSI__) && defined(__GNUC__)
1923 # define XCAST(fun) (typeof(VTABLE_IDirect3DDevice.fun))
1924 #else
1925 # define XCAST(fun) (void*)
1926 #endif
1928 ICOM_VTABLE(IDirect3DDevice) VTABLE_IDirect3DDevice =
1930 ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
1931 XCAST(QueryInterface) Thunk_IDirect3DDeviceImpl_1_QueryInterface,
1932 XCAST(AddRef) Thunk_IDirect3DDeviceImpl_1_AddRef,
1933 XCAST(Release) Thunk_IDirect3DDeviceImpl_1_Release,
1934 XCAST(Initialize) Main_IDirect3DDeviceImpl_1_Initialize,
1935 XCAST(GetCaps) Thunk_IDirect3DDeviceImpl_1_GetCaps,
1936 XCAST(SwapTextureHandles) Thunk_IDirect3DDeviceImpl_1_SwapTextureHandles,
1937 XCAST(CreateExecuteBuffer) GL_IDirect3DDeviceImpl_1_CreateExecuteBuffer,
1938 XCAST(GetStats) Thunk_IDirect3DDeviceImpl_1_GetStats,
1939 XCAST(Execute) Main_IDirect3DDeviceImpl_1_Execute,
1940 XCAST(AddViewport) Thunk_IDirect3DDeviceImpl_1_AddViewport,
1941 XCAST(DeleteViewport) Thunk_IDirect3DDeviceImpl_1_DeleteViewport,
1942 XCAST(NextViewport) Thunk_IDirect3DDeviceImpl_1_NextViewport,
1943 XCAST(Pick) Main_IDirect3DDeviceImpl_1_Pick,
1944 XCAST(GetPickRecords) Main_IDirect3DDeviceImpl_1_GetPickRecords,
1945 XCAST(EnumTextureFormats) Thunk_IDirect3DDeviceImpl_1_EnumTextureFormats,
1946 XCAST(CreateMatrix) Main_IDirect3DDeviceImpl_1_CreateMatrix,
1947 XCAST(SetMatrix) Main_IDirect3DDeviceImpl_1_SetMatrix,
1948 XCAST(GetMatrix) Main_IDirect3DDeviceImpl_1_GetMatrix,
1949 XCAST(DeleteMatrix) Main_IDirect3DDeviceImpl_1_DeleteMatrix,
1950 XCAST(BeginScene) Thunk_IDirect3DDeviceImpl_1_BeginScene,
1951 XCAST(EndScene) Thunk_IDirect3DDeviceImpl_1_EndScene,
1952 XCAST(GetDirect3D) Thunk_IDirect3DDeviceImpl_1_GetDirect3D,
1955 #if !defined(__STRICT_ANSI__) && defined(__GNUC__)
1956 #undef XCAST
1957 #endif
1959 static HRESULT d3ddevice_clear(IDirect3DDeviceImpl *This,
1960 DWORD dwCount,
1961 LPD3DRECT lpRects,
1962 DWORD dwFlags,
1963 DWORD dwColor,
1964 D3DVALUE dvZ,
1965 DWORD dwStencil)
1967 GLboolean ztest;
1968 GLfloat old_z_clear_value;
1969 GLbitfield bitfield = 0;
1970 GLint old_stencil_clear_value;
1971 GLfloat old_color_clear_value[4];
1973 TRACE("(%p)->(%08lx,%p,%08lx,%08lx,%f,%08lx)\n", This, dwCount, lpRects, dwFlags, dwColor, dvZ, dwStencil);
1974 if (TRACE_ON(ddraw)) {
1975 if (dwCount > 0) {
1976 int i;
1977 TRACE(" rectangles : \n");
1978 for (i = 0; i < dwCount; i++) {
1979 TRACE(" - %ld x %ld %ld x %ld\n", lpRects[i].u1.x1, lpRects[i].u2.y1, lpRects[i].u3.x2, lpRects[i].u4.y2);
1984 if (dwCount > 1) {
1985 WARN(" Warning, this function only for now clears the whole screen...\n");
1988 /* Clears the screen */
1989 ENTER_GL();
1990 if (dwFlags & D3DCLEAR_ZBUFFER) {
1991 bitfield |= GL_DEPTH_BUFFER_BIT;
1992 glGetBooleanv(GL_DEPTH_WRITEMASK, &ztest);
1993 glDepthMask(GL_TRUE); /* Enables Z writing to be sure to delete also the Z buffer */
1994 glGetFloatv(GL_DEPTH_CLEAR_VALUE, &old_z_clear_value);
1995 glClearDepth(dvZ);
1996 TRACE(" depth value : %f\n", dvZ);
1998 if (dwFlags & D3DCLEAR_STENCIL) {
1999 bitfield |= GL_STENCIL_BUFFER_BIT;
2000 glGetIntegerv(GL_STENCIL_CLEAR_VALUE, &old_stencil_clear_value);
2001 glClearStencil(dwStencil);
2002 TRACE(" stencil value : %ld\n", dwStencil);
2004 if (dwFlags & D3DCLEAR_TARGET) {
2005 bitfield |= GL_COLOR_BUFFER_BIT;
2006 glGetFloatv(GL_COLOR_CLEAR_VALUE, old_color_clear_value);
2007 glClearColor(((dwColor >> 16) & 0xFF) / 255.0,
2008 ((dwColor >> 8) & 0xFF) / 255.0,
2009 ((dwColor >> 0) & 0xFF) / 255.0,
2010 ((dwColor >> 24) & 0xFF) / 255.0);
2011 TRACE(" color value (ARGB) : %08lx\n", dwColor);
2014 glClear(bitfield);
2016 if (dwFlags & D3DCLEAR_ZBUFFER) {
2017 glDepthMask(ztest);
2018 glClearDepth(old_z_clear_value);
2020 if (dwFlags & D3DCLEAR_STENCIL) {
2021 bitfield |= GL_STENCIL_BUFFER_BIT;
2022 glClearStencil(old_stencil_clear_value);
2024 if (dwFlags & D3DCLEAR_TARGET) {
2025 bitfield |= GL_COLOR_BUFFER_BIT;
2026 glClearColor(old_color_clear_value[0],
2027 old_color_clear_value[1],
2028 old_color_clear_value[2],
2029 old_color_clear_value[3]);
2032 LEAVE_GL();
2034 return DD_OK;
2037 HRESULT
2038 d3ddevice_blt(IDirectDrawSurfaceImpl *This, LPRECT rdst,
2039 LPDIRECTDRAWSURFACE7 src, LPRECT rsrc,
2040 DWORD dwFlags, LPDDBLTFX lpbltfx)
2042 if (dwFlags & DDBLT_COLORFILL) {
2043 /* This is easy to handle for the D3D Device... */
2044 DWORD color = lpbltfx->u5.dwFillColor;
2045 TRACE(" executing D3D Device override.\n");
2046 d3ddevice_clear(This->d3ddevice, 0, NULL, D3DCLEAR_TARGET, color, 0.0, 0x00000000);
2047 return DD_OK;
2049 return DDERR_INVALIDPARAMS;
2052 HRESULT
2053 d3ddevice_bltfast(IDirectDrawSurfaceImpl *This, DWORD dstx,
2054 DWORD dsty, LPDIRECTDRAWSURFACE7 src,
2055 LPRECT rsrc, DWORD trans)
2057 return DDERR_INVALIDPARAMS;
2060 void
2061 d3ddevice_set_ortho(IDirect3DDeviceImpl *This)
2063 GLfloat height, width;
2064 GLfloat trans_mat[16];
2066 width = This->surface->surface_desc.dwWidth;
2067 height = This->surface->surface_desc.dwHeight;
2069 /* The X axis is straighforward.. For the Y axis, we need to convert 'D3D' screen coordinates
2070 to OpenGL screen coordinates (ie the upper left corner is not the same).
2071 For Z, the mystery is what should it be mapped to ? Ie should the resulting range be between
2072 -1.0 and 1.0 (as the X and Y coordinates) or between 0.0 and 1.0 ? */
2073 trans_mat[ 0] = 2.0 / width; trans_mat[ 4] = 0.0; trans_mat[ 8] = 0.0; trans_mat[12] = -1.0;
2074 trans_mat[ 1] = 0.0; trans_mat[ 5] = -2.0 / height; trans_mat[ 9] = 0.0; trans_mat[13] = 1.0;
2075 trans_mat[ 2] = 0.0; trans_mat[ 6] = 0.0; trans_mat[10] = 1.0; trans_mat[14] = -1.0;
2076 trans_mat[ 3] = 0.0; trans_mat[ 7] = 0.0; trans_mat[11] = 0.0; trans_mat[15] = 1.0;
2078 glMatrixMode(GL_MODELVIEW);
2079 glLoadIdentity();
2080 /* See the OpenGL Red Book for an explanation of the following translation (in the OpenGL
2081 Correctness Tips section).
2083 Basically, from what I understood, if the game does not filter the font texture,
2084 as the 'real' pixel will lie at the middle of the two texels, OpenGL may choose the wrong
2085 one and we will have strange artifacts (as the rounding and stuff may give different results
2086 for different pixels, ie sometimes take the left pixel, sometimes the right).
2088 glTranslatef(0.375, 0.375, 0);
2089 glMatrixMode(GL_PROJECTION);
2090 glLoadMatrixf(trans_mat);
2093 void
2094 d3ddevice_set_matrices(IDirect3DDeviceImpl *This, DWORD matrices,
2095 D3DMATRIX *world_mat, D3DMATRIX *view_mat, D3DMATRIX *proj_mat)
2097 if ((matrices & (VIEWMAT_CHANGED|WORLDMAT_CHANGED)) != 0) {
2098 glMatrixMode(GL_MODELVIEW);
2099 glLoadMatrixf((float *) view_mat);
2100 glMultMatrixf((float *) world_mat);
2102 if ((matrices & PROJMAT_CHANGED) != 0) {
2103 glMatrixMode(GL_PROJECTION);
2104 glLoadMatrixf((float *) proj_mat);
2108 void
2109 d3ddevice_matrices_updated(IDirect3DDeviceImpl *This, DWORD matrices)
2111 IDirect3DDeviceGLImpl *glThis = (IDirect3DDeviceGLImpl *) This;
2112 if (glThis->transform_state == GL_TRANSFORM_NORMAL) {
2113 /* This will force an update of the transform state at the next drawing. */
2114 glThis->transform_state = GL_TRANSFORM_NONE;
2118 /* TODO for both these functions :
2119 - change / restore OpenGL parameters for pictures transfers in case they are ever modified
2120 by other OpenGL code in D3D
2121 - handle the case where no 'Begin / EndScene' was done between two locks
2122 - handle the rectangles in the unlock too
2123 - handle pitch correctly...
2125 static void d3ddevice_lock_update(IDirectDrawSurfaceImpl* This, LPCRECT pRect, DWORD dwFlags)
2127 /* First, check if we need to do anything */
2128 if ((This->lastlocktype & DDLOCK_WRITEONLY) == 0) {
2129 GLenum buffer_type;
2130 GLenum prev_read;
2131 RECT loc_rect;
2133 ENTER_GL();
2135 glGetIntegerv(GL_READ_BUFFER, &prev_read);
2136 glFlush();
2138 WARN(" application does a lock on a 3D surface - expect slow downs.\n");
2139 if ((This->surface_desc.ddsCaps.dwCaps & (DDSCAPS_FRONTBUFFER|DDSCAPS_PRIMARYSURFACE)) != 0) {
2140 /* Application wants to lock the front buffer */
2141 glReadBuffer(GL_FRONT);
2142 } else if ((This->surface_desc.ddsCaps.dwCaps & (DDSCAPS_BACKBUFFER)) == (DDSCAPS_BACKBUFFER)) {
2143 /* Application wants to lock the back buffer */
2144 glReadBuffer(GL_BACK);
2145 } else {
2146 WARN(" do not support 3D surface locking for this surface type - trying to use default buffer.\n");
2149 if (This->surface_desc.u4.ddpfPixelFormat.u1.dwRGBBitCount == 16) {
2150 buffer_type = GL_UNSIGNED_SHORT_5_6_5;
2151 } else {
2152 WARN(" unsupported pixel format.\n");
2153 LEAVE_GL();
2154 return;
2156 if (pRect == NULL) {
2157 loc_rect.top = 0;
2158 loc_rect.left = 0;
2159 loc_rect.bottom = This->surface_desc.dwHeight;
2160 loc_rect.right = This->surface_desc.dwWidth;
2161 } else {
2162 loc_rect = *pRect;
2164 glReadPixels(loc_rect.left, loc_rect.top, loc_rect.right, loc_rect.bottom,
2165 GL_RGB, buffer_type, ((char *)This->surface_desc.lpSurface
2166 + loc_rect.top * This->surface_desc.u1.lPitch
2167 + loc_rect.left * GET_BPP(This->surface_desc)));
2168 glReadBuffer(prev_read);
2169 LEAVE_GL();
2173 static void d3ddevice_unlock_update(IDirectDrawSurfaceImpl* This, LPCRECT pRect)
2175 /* First, check if we need to do anything */
2176 if ((This->lastlocktype & DDLOCK_READONLY) == 0) {
2177 GLenum buffer_type;
2178 GLenum prev_draw;
2180 ENTER_GL();
2182 glGetIntegerv(GL_DRAW_BUFFER, &prev_draw);
2184 WARN(" application does an unlock on a 3D surface - expect slow downs.\n");
2185 if ((This->surface_desc.ddsCaps.dwCaps & (DDSCAPS_FRONTBUFFER|DDSCAPS_PRIMARYSURFACE)) != 0) {
2186 /* Application wants to lock the front buffer */
2187 glDrawBuffer(GL_FRONT);
2188 } else if ((This->surface_desc.ddsCaps.dwCaps & (DDSCAPS_BACKBUFFER)) == (DDSCAPS_BACKBUFFER)) {
2189 /* Application wants to lock the back buffer */
2190 glDrawBuffer(GL_BACK);
2191 } else {
2192 WARN(" do not support 3D surface unlocking for this surface type - trying to use default buffer.\n");
2195 if (This->surface_desc.u4.ddpfPixelFormat.u1.dwRGBBitCount == 16) {
2196 buffer_type = GL_UNSIGNED_SHORT_5_6_5;
2197 } else {
2198 WARN(" unsupported pixel format.\n");
2199 LEAVE_GL();
2200 return;
2202 glRasterPos2f(0.0, 0.0);
2203 glDrawPixels(This->surface_desc.dwWidth, This->surface_desc.dwHeight,
2204 GL_RGB, buffer_type, This->surface_desc.lpSurface);
2205 glDrawBuffer(prev_draw);
2207 LEAVE_GL();
2211 HRESULT
2212 d3ddevice_create(IDirect3DDeviceImpl **obj, IDirect3DImpl *d3d, IDirectDrawSurfaceImpl *surface)
2214 IDirect3DDeviceImpl *object;
2215 IDirect3DDeviceGLImpl *gl_object;
2216 IDirectDrawSurfaceImpl *surf;
2217 HDC device_context;
2218 XVisualInfo *vis;
2219 int num;
2220 XVisualInfo template;
2221 GLenum buffer = GL_FRONT;
2222 int light;
2223 GLint max_clipping_planes = 0;
2225 object = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(IDirect3DDeviceGLImpl));
2226 if (object == NULL) return DDERR_OUTOFMEMORY;
2228 gl_object = (IDirect3DDeviceGLImpl *) object;
2230 object->ref = 1;
2231 object->d3d = d3d;
2232 object->surface = surface;
2233 object->set_context = set_context;
2234 object->clear = d3ddevice_clear;
2235 object->set_matrices = d3ddevice_set_matrices;
2236 object->matrices_updated = d3ddevice_matrices_updated;
2238 TRACE(" creating OpenGL device for surface = %p, d3d = %p\n", surface, d3d);
2240 device_context = GetDC(surface->ddraw_owner->window);
2241 gl_object->display = get_display(device_context);
2242 gl_object->drawable = get_drawable(device_context);
2243 ReleaseDC(surface->ddraw_owner->window,device_context);
2245 ENTER_GL();
2246 template.visualid = (VisualID)GetPropA( GetDesktopWindow(), "__wine_x11_visual_id" );
2247 vis = XGetVisualInfo(gl_object->display, VisualIDMask, &template, &num);
2248 if (vis == NULL) {
2249 HeapFree(GetProcessHeap(), 0, object);
2250 ERR("No visual found !\n");
2251 LEAVE_GL();
2252 return DDERR_INVALIDPARAMS;
2253 } else {
2254 TRACE(" visual found\n");
2257 gl_object->gl_context = glXCreateContext(gl_object->display, vis,
2258 NULL, GL_TRUE);
2260 if (gl_object->gl_context == NULL) {
2261 HeapFree(GetProcessHeap(), 0, object);
2262 ERR("Error in context creation !\n");
2263 LEAVE_GL();
2264 return DDERR_INVALIDPARAMS;
2265 } else {
2266 TRACE(" context created (%p)\n", gl_object->gl_context);
2269 /* Look for the front buffer and override its surface's Flip method (if in double buffering) */
2270 for (surf = surface; surf != NULL; surf = surf->surface_owner) {
2271 if ((surf->surface_desc.ddsCaps.dwCaps&(DDSCAPS_FLIP|DDSCAPS_FRONTBUFFER)) == (DDSCAPS_FLIP|DDSCAPS_FRONTBUFFER)) {
2272 surf->aux_ctx = (LPVOID) gl_object->display;
2273 surf->aux_data = (LPVOID) gl_object->drawable;
2274 surf->aux_flip = opengl_flip;
2275 buffer = GL_BACK;
2276 break;
2279 /* We are not doing any double buffering.. Then force OpenGL to draw on the front buffer */
2280 if (surf == NULL) {
2281 TRACE(" no double buffering : drawing on the front buffer\n");
2282 buffer = GL_FRONT;
2285 for (surf = surface; surf->prev_attached != NULL; surf = surf->prev_attached) ;
2286 for (; surf != NULL; surf = surf->next_attached) {
2287 if (((surf->surface_desc.ddsCaps.dwCaps & (DDSCAPS_3DDEVICE)) == (DDSCAPS_3DDEVICE)) &&
2288 ((surf->surface_desc.ddsCaps.dwCaps & (DDSCAPS_ZBUFFER)) != (DDSCAPS_ZBUFFER))) {
2289 /* Override the Lock / Unlock function for all these surfaces */
2290 surf->lock_update = d3ddevice_lock_update;
2291 surf->unlock_update = d3ddevice_unlock_update;
2292 /* And install also the blt / bltfast overrides */
2293 surf->aux_blt = d3ddevice_blt;
2294 surf->aux_bltfast = d3ddevice_bltfast;
2296 surf->d3ddevice = object;
2299 /* Set the various light parameters */
2300 for (light = 0; light < MAX_LIGHTS; light++) {
2301 /* Only set the fields that are not zero-created */
2302 object->light_parameters[light].dltType = D3DLIGHT_DIRECTIONAL;
2303 object->light_parameters[light].dcvDiffuse.u1.r = 1.0;
2304 object->light_parameters[light].dcvDiffuse.u2.g = 1.0;
2305 object->light_parameters[light].dcvDiffuse.u3.b = 1.0;
2306 object->light_parameters[light].dvDirection.u3.z = 1.0;
2309 /* Allocate memory for the matrices */
2310 object->world_mat = (D3DMATRIX *) HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, 16 * sizeof(float));
2311 object->view_mat = (D3DMATRIX *) HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, 16 * sizeof(float));
2312 object->proj_mat = (D3DMATRIX *) HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, 16 * sizeof(float));
2313 memcpy(object->world_mat, id_mat, 16 * sizeof(float));
2314 memcpy(object->view_mat , id_mat, 16 * sizeof(float));
2315 memcpy(object->proj_mat , id_mat, 16 * sizeof(float));
2317 /* allocate the clipping planes */
2318 glGetIntegerv(GL_MAX_CLIP_PLANES,&max_clipping_planes);
2319 if (max_clipping_planes>32) {
2320 object->max_clipping_planes=32;
2321 } else {
2322 object->max_clipping_planes = max_clipping_planes;
2324 TRACE(" capable of %d clipping planes\n", (int)object->max_clipping_planes );
2325 object->clipping_planes = (d3d7clippingplane*)HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, object->max_clipping_planes * sizeof(d3d7clippingplane));
2327 /* Initialisation */
2328 TRACE(" setting current context\n");
2329 LEAVE_GL();
2330 object->set_context(object);
2331 ENTER_GL();
2332 TRACE(" current context set\n");
2334 glHint(GL_FOG_HINT,GL_NICEST);
2335 glClearColor(0.0, 0.0, 0.0, 0.0);
2336 glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
2337 glDrawBuffer(buffer);
2338 glReadBuffer(buffer);
2339 /* glDisable(GL_DEPTH_TEST); Need here to check for the presence of a ZBuffer and to reenable it when the ZBuffer is attached */
2340 LEAVE_GL();
2342 /* fill_device_capabilities(d3d->ddraw); */
2344 ICOM_INIT_INTERFACE(object, IDirect3DDevice, VTABLE_IDirect3DDevice);
2345 ICOM_INIT_INTERFACE(object, IDirect3DDevice2, VTABLE_IDirect3DDevice2);
2346 ICOM_INIT_INTERFACE(object, IDirect3DDevice3, VTABLE_IDirect3DDevice3);
2347 ICOM_INIT_INTERFACE(object, IDirect3DDevice7, VTABLE_IDirect3DDevice7);
2349 *obj = object;
2351 TRACE(" creating implementation at %p.\n", *obj);
2353 /* And finally warn D3D that this device is now present */
2354 object->d3d->added_device(object->d3d, object);
2356 /* FIXME: Should handle other versions than just 7 */
2357 InitDefaultStateBlock(&object->state_block, 7);
2358 /* Apply default render state values */
2359 apply_render_state(object, &object->state_block);
2360 /* FIXME: do something similar for ligh_state and texture_stage_state */
2362 /* And fill the fog table with the default fog value */
2363 build_fog_table(gl_object->fog_table, object->state_block.render_state[D3DRENDERSTATE_FOGCOLOR - 1]);
2365 return DD_OK;