- protect viewport setting with GL lock
[wine/multimedia.git] / dlls / ddraw / d3ddevice / mesa.c
blobd43978983a95dadc54f2ea154fdda1434062e07c
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);
40 WINE_DECLARE_DEBUG_CHANNEL(ddraw_geom);
42 /* x11drv GDI escapes */
43 #define X11DRV_ESCAPE 6789
44 enum x11drv_escape_codes
46 X11DRV_GET_DISPLAY, /* get X11 display for a DC */
47 X11DRV_GET_DRAWABLE, /* get current drawable for a DC */
48 X11DRV_GET_FONT, /* get current X font for a DC */
51 /* They are non-static as they are used by Direct3D in the creation function */
52 const GUID IID_D3DDEVICE_OpenGL = {
53 0x31416d44,
54 0x86ae,
55 0x11d2,
56 { 0x82,0x2d,0xa8,0xd5,0x31,0x87,0xca,0xfa }
59 #ifndef HAVE_GLEXT_PROTOTYPES
60 /* This is for non-OpenGL ABI compliant glext.h headers :-) */
61 typedef void (* PFNGLCOLORTABLEEXTPROC) (GLenum target, GLenum internalFormat,
62 GLsizei width, GLenum format, GLenum type,
63 const GLvoid *table);
64 #endif
66 const float id_mat[16] = {
67 1.0, 0.0, 0.0, 0.0,
68 0.0, 1.0, 0.0, 0.0,
69 0.0, 0.0, 1.0, 0.0,
70 0.0, 0.0, 0.0, 1.0
73 static void draw_primitive_strided(IDirect3DDeviceImpl *This,
74 D3DPRIMITIVETYPE d3dptPrimitiveType,
75 DWORD d3dvtVertexType,
76 LPD3DDRAWPRIMITIVESTRIDEDDATA lpD3DDrawPrimStrideData,
77 DWORD dwVertexCount,
78 LPWORD dwIndices,
79 DWORD dwIndexCount,
80 DWORD dwFlags) ;
82 /* retrieve the X display to use on a given DC */
83 inline static Display *get_display( HDC hdc )
85 Display *display;
86 enum x11drv_escape_codes escape = X11DRV_GET_DISPLAY;
88 if (!ExtEscape( hdc, X11DRV_ESCAPE, sizeof(escape), (LPCSTR)&escape,
89 sizeof(display), (LPSTR)&display )) display = NULL;
91 return display;
95 /* retrieve the X drawable to use on a given DC */
96 inline static Drawable get_drawable( HDC hdc )
98 Drawable drawable;
99 enum x11drv_escape_codes escape = X11DRV_GET_DRAWABLE;
101 if (!ExtEscape( hdc, X11DRV_ESCAPE, sizeof(escape), (LPCSTR)&escape,
102 sizeof(drawable), (LPSTR)&drawable )) drawable = 0;
104 return drawable;
108 static BOOL opengl_flip( LPVOID dev, LPVOID drawable)
110 IDirect3DDeviceImpl *d3d_dev = (IDirect3DDeviceImpl *) dev;
111 IDirect3DDeviceGLImpl *gl_d3d_dev = (IDirect3DDeviceGLImpl *) dev;
113 TRACE("(%p, %ld)\n", gl_d3d_dev->display,(Drawable)drawable);
114 ENTER_GL();
115 if (gl_d3d_dev->state == SURFACE_MEMORY_DIRTY) {
116 d3d_dev->flush_to_framebuffer(d3d_dev, NULL, gl_d3d_dev->lock_surf);
118 gl_d3d_dev->state = SURFACE_GL;
119 gl_d3d_dev->front_state = SURFACE_GL;
120 glXSwapBuffers(gl_d3d_dev->display, (Drawable)drawable);
121 LEAVE_GL();
123 return TRUE;
127 /*******************************************************************************
128 * OpenGL static functions
130 static void set_context(IDirect3DDeviceImpl* This)
132 IDirect3DDeviceGLImpl* glThis = (IDirect3DDeviceGLImpl*) This;
134 ENTER_GL();
135 TRACE("glxMakeCurrent %p, %ld, %p\n",glThis->display,glThis->drawable, glThis->gl_context);
136 if (glXMakeCurrent(glThis->display, glThis->drawable, glThis->gl_context) == False) {
137 ERR("Error in setting current context (context %p drawable %ld)!\n",
138 glThis->gl_context, glThis->drawable);
140 LEAVE_GL();
143 static void fill_opengl_primcaps(D3DPRIMCAPS *pc)
145 pc->dwSize = sizeof(*pc);
146 pc->dwMiscCaps = D3DPMISCCAPS_CONFORMANT | D3DPMISCCAPS_CULLCCW | D3DPMISCCAPS_CULLCW |
147 D3DPMISCCAPS_LINEPATTERNREP | D3DPMISCCAPS_MASKZ;
148 pc->dwRasterCaps = D3DPRASTERCAPS_DITHER | D3DPRASTERCAPS_FOGRANGE | D3DPRASTERCAPS_FOGTABLE |
149 D3DPRASTERCAPS_FOGVERTEX | D3DPRASTERCAPS_STIPPLE | D3DPRASTERCAPS_ZBIAS | D3DPRASTERCAPS_ZTEST | D3DPRASTERCAPS_SUBPIXEL;
150 pc->dwZCmpCaps = D3DPCMPCAPS_ALWAYS | D3DPCMPCAPS_EQUAL | D3DPCMPCAPS_GREATER | D3DPCMPCAPS_GREATEREQUAL |
151 D3DPCMPCAPS_LESS | D3DPCMPCAPS_LESSEQUAL | D3DPCMPCAPS_NEVER | D3DPCMPCAPS_NOTEQUAL;
152 pc->dwSrcBlendCaps = D3DPBLENDCAPS_ZERO | D3DPBLENDCAPS_ONE | D3DPBLENDCAPS_DESTCOLOR | D3DPBLENDCAPS_INVDESTCOLOR |
153 D3DPBLENDCAPS_SRCALPHA | D3DPBLENDCAPS_INVSRCALPHA | D3DPBLENDCAPS_DESTALPHA | D3DPBLENDCAPS_INVDESTALPHA | D3DPBLENDCAPS_SRCALPHASAT |
154 D3DPBLENDCAPS_BOTHSRCALPHA | D3DPBLENDCAPS_BOTHINVSRCALPHA;
155 pc->dwDestBlendCaps = D3DPBLENDCAPS_ZERO | D3DPBLENDCAPS_ONE | D3DPBLENDCAPS_SRCCOLOR | D3DPBLENDCAPS_INVSRCCOLOR |
156 D3DPBLENDCAPS_SRCALPHA | D3DPBLENDCAPS_INVSRCALPHA | D3DPBLENDCAPS_DESTALPHA | D3DPBLENDCAPS_INVDESTALPHA | D3DPBLENDCAPS_SRCALPHASAT |
157 D3DPBLENDCAPS_BOTHSRCALPHA | D3DPBLENDCAPS_BOTHINVSRCALPHA;
158 pc->dwAlphaCmpCaps = D3DPCMPCAPS_ALWAYS | D3DPCMPCAPS_EQUAL | D3DPCMPCAPS_GREATER | D3DPCMPCAPS_GREATEREQUAL |
159 D3DPCMPCAPS_LESS | D3DPCMPCAPS_LESSEQUAL | D3DPCMPCAPS_NEVER | D3DPCMPCAPS_NOTEQUAL;
160 pc->dwShadeCaps = D3DPSHADECAPS_ALPHAFLATBLEND | D3DPSHADECAPS_ALPHAGOURAUDBLEND | D3DPSHADECAPS_COLORFLATRGB | D3DPSHADECAPS_COLORGOURAUDRGB |
161 D3DPSHADECAPS_FOGFLAT | D3DPSHADECAPS_FOGGOURAUD | D3DPSHADECAPS_SPECULARFLATRGB | D3DPSHADECAPS_SPECULARGOURAUDRGB;
162 pc->dwTextureCaps = D3DPTEXTURECAPS_ALPHA | D3DPTEXTURECAPS_ALPHAPALETTE | D3DPTEXTURECAPS_BORDER | D3DPTEXTURECAPS_PERSPECTIVE |
163 D3DPTEXTURECAPS_POW2 | D3DPTEXTURECAPS_TRANSPARENCY;
164 pc->dwTextureFilterCaps = D3DPTFILTERCAPS_LINEAR | D3DPTFILTERCAPS_LINEARMIPLINEAR | D3DPTFILTERCAPS_LINEARMIPNEAREST |
165 D3DPTFILTERCAPS_MIPLINEAR | D3DPTFILTERCAPS_MIPNEAREST | D3DPTFILTERCAPS_NEAREST;
166 pc->dwTextureBlendCaps = D3DPTBLENDCAPS_ADD | D3DPTBLENDCAPS_COPY | D3DPTBLENDCAPS_DECAL | D3DPTBLENDCAPS_DECALALPHA | D3DPTBLENDCAPS_DECALMASK |
167 D3DPTBLENDCAPS_MODULATE | D3DPTBLENDCAPS_MODULATEALPHA | D3DPTBLENDCAPS_MODULATEMASK;
168 pc->dwTextureAddressCaps = D3DPTADDRESSCAPS_BORDER | D3DPTADDRESSCAPS_CLAMP | D3DPTADDRESSCAPS_WRAP | D3DPTADDRESSCAPS_INDEPENDENTUV;
169 pc->dwStippleWidth = 32;
170 pc->dwStippleHeight = 32;
173 static void fill_opengl_caps(D3DDEVICEDESC *d1)
175 /* GLint maxlight; */
177 d1->dwSize = sizeof(*d1);
178 d1->dwFlags = D3DDD_DEVCAPS | D3DDD_BCLIPPING | D3DDD_COLORMODEL | D3DDD_DEVICERENDERBITDEPTH | D3DDD_DEVICEZBUFFERBITDEPTH
179 | D3DDD_LIGHTINGCAPS | D3DDD_LINECAPS | D3DDD_MAXBUFFERSIZE | D3DDD_MAXVERTEXCOUNT | D3DDD_TRANSFORMCAPS | D3DDD_TRICAPS;
180 d1->dcmColorModel = D3DCOLOR_RGB;
181 d1->dwDevCaps = D3DDEVCAPS_CANRENDERAFTERFLIP | D3DDEVCAPS_DRAWPRIMTLVERTEX | D3DDEVCAPS_EXECUTESYSTEMMEMORY |
182 D3DDEVCAPS_EXECUTEVIDEOMEMORY | D3DDEVCAPS_FLOATTLVERTEX | D3DDEVCAPS_TEXTURENONLOCALVIDMEM | D3DDEVCAPS_TEXTURESYSTEMMEMORY |
183 D3DDEVCAPS_TEXTUREVIDEOMEMORY | D3DDEVCAPS_TLVERTEXSYSTEMMEMORY | D3DDEVCAPS_TLVERTEXVIDEOMEMORY |
184 /* D3D 7 capabilities */
185 D3DDEVCAPS_DRAWPRIMITIVES2 | D3DDEVCAPS_HWTRANSFORMANDLIGHT | D3DDEVCAPS_HWRASTERIZATION;
186 d1->dtcTransformCaps.dwSize = sizeof(D3DTRANSFORMCAPS);
187 d1->dtcTransformCaps.dwCaps = D3DTRANSFORMCAPS_CLIP;
188 d1->bClipping = TRUE;
189 d1->dlcLightingCaps.dwSize = sizeof(D3DLIGHTINGCAPS);
190 d1->dlcLightingCaps.dwCaps = D3DLIGHTCAPS_DIRECTIONAL | D3DLIGHTCAPS_PARALLELPOINT | D3DLIGHTCAPS_POINT | D3DLIGHTCAPS_SPOT;
191 d1->dlcLightingCaps.dwLightingModel = D3DLIGHTINGMODEL_RGB;
192 d1->dlcLightingCaps.dwNumLights = 16; /* glGetIntegerv(GL_MAX_LIGHTS, &maxlight); d1->dlcLightingCaps.dwNumLights = maxlight; */
193 fill_opengl_primcaps(&(d1->dpcLineCaps));
194 fill_opengl_primcaps(&(d1->dpcTriCaps));
195 d1->dwDeviceRenderBitDepth = DDBD_16|DDBD_24|DDBD_32;
196 d1->dwDeviceZBufferBitDepth = DDBD_16|DDBD_24|DDBD_32;
197 d1->dwMaxBufferSize = 0;
198 d1->dwMaxVertexCount = 65536;
199 d1->dwMinTextureWidth = 1;
200 d1->dwMinTextureHeight = 1;
201 d1->dwMaxTextureWidth = 1024;
202 d1->dwMaxTextureHeight = 1024;
203 d1->dwMinStippleWidth = 1;
204 d1->dwMinStippleHeight = 1;
205 d1->dwMaxStippleWidth = 32;
206 d1->dwMaxStippleHeight = 32;
207 d1->dwMaxTextureRepeat = 16;
208 d1->dwMaxTextureAspectRatio = 1024;
209 d1->dwMaxAnisotropy = 0;
210 d1->dvGuardBandLeft = 0.0;
211 d1->dvGuardBandRight = 0.0;
212 d1->dvGuardBandTop = 0.0;
213 d1->dvGuardBandBottom = 0.0;
214 d1->dvExtentsAdjust = 0.0;
215 d1->dwStencilCaps = D3DSTENCILCAPS_DECRSAT | D3DSTENCILCAPS_INCRSAT | D3DSTENCILCAPS_INVERT | D3DSTENCILCAPS_KEEP |
216 D3DSTENCILCAPS_REPLACE | D3DSTENCILCAPS_ZERO;
217 d1->dwFVFCaps = D3DFVFCAPS_DONOTSTRIPELEMENTS | 1;
218 d1->dwTextureOpCaps = 0; /* TODO add proper caps according to OpenGL multi-texture stuff */
219 d1->wMaxTextureBlendStages = 1; /* TODO add proper caps according to OpenGL multi-texture stuff */
220 d1->wMaxSimultaneousTextures = 1; /* TODO add proper caps according to OpenGL multi-texture stuff */
223 static void fill_opengl_caps_7(D3DDEVICEDESC7 *d)
225 D3DDEVICEDESC d1;
227 /* Copy first D3D1/2/3 capabilities */
228 fill_opengl_caps(&d1);
230 /* And fill the D3D7 one with it */
231 d->dwDevCaps = d1.dwDevCaps;
232 d->dpcLineCaps = d1.dpcLineCaps;
233 d->dpcTriCaps = d1.dpcTriCaps;
234 d->dwDeviceRenderBitDepth = d1.dwDeviceRenderBitDepth;
235 d->dwDeviceZBufferBitDepth = d1.dwDeviceZBufferBitDepth;
236 d->dwMinTextureWidth = d1.dwMinTextureWidth;
237 d->dwMinTextureHeight = d1.dwMinTextureHeight;
238 d->dwMaxTextureWidth = d1.dwMaxTextureWidth;
239 d->dwMaxTextureHeight = d1.dwMaxTextureHeight;
240 d->dwMaxTextureRepeat = d1.dwMaxTextureRepeat;
241 d->dwMaxTextureAspectRatio = d1.dwMaxTextureAspectRatio;
242 d->dwMaxAnisotropy = d1.dwMaxAnisotropy;
243 d->dvGuardBandLeft = d1.dvGuardBandLeft;
244 d->dvGuardBandTop = d1.dvGuardBandTop;
245 d->dvGuardBandRight = d1.dvGuardBandRight;
246 d->dvGuardBandBottom = d1.dvGuardBandBottom;
247 d->dvExtentsAdjust = d1.dvExtentsAdjust;
248 d->dwStencilCaps = d1.dwStencilCaps;
249 d->dwFVFCaps = d1.dwFVFCaps;
250 d->dwTextureOpCaps = d1.dwTextureOpCaps;
251 d->wMaxTextureBlendStages = d1.wMaxTextureBlendStages;
252 d->wMaxSimultaneousTextures = d1.wMaxSimultaneousTextures;
253 d->dwMaxActiveLights = d1.dlcLightingCaps.dwNumLights;
254 d->dvMaxVertexW = 100000000.0; /* No idea exactly what to put here... */
255 d->deviceGUID = IID_IDirect3DTnLHalDevice;
256 d->wMaxUserClipPlanes = 1;
257 d->wMaxVertexBlendMatrices = 0;
258 d->dwVertexProcessingCaps = D3DVTXPCAPS_TEXGEN | D3DVTXPCAPS_MATERIALSOURCE7 | D3DVTXPCAPS_VERTEXFOG | D3DVTXPCAPS_DIRECTIONALLIGHTS |
259 D3DVTXPCAPS_POSITIONALLIGHTS | D3DVTXPCAPS_LOCALVIEWER;
260 d->dwReserved1 = 0;
261 d->dwReserved2 = 0;
262 d->dwReserved3 = 0;
263 d->dwReserved4 = 0;
266 #if 0 /* TODO : fix this and add multitexturing and other needed stuff */
267 static void fill_device_capabilities(IDirectDrawImpl* ddraw)
269 x11_dd_private *private = (x11_dd_private *) ddraw->d->private;
270 const char *ext_string;
271 Mesa_DeviceCapabilities *devcap;
273 private->device_capabilities = HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,sizeof(Mesa_DeviceCapabilities));
274 devcap = (Mesa_DeviceCapabilities *) private->device_capabilities;
276 ENTER_GL();
277 ext_string = glGetString(GL_EXTENSIONS);
278 /* Query for the ColorTable Extension */
279 if (strstr(ext_string, "GL_EXT_paletted_texture")) {
280 devcap->ptr_ColorTableEXT = (PFNGLCOLORTABLEEXTPROC) glXGetProcAddressARB("glColorTableEXT");
281 TRACE("Color table extension supported (function at %p)\n", devcap->ptr_ColorTableEXT);
282 } else {
283 TRACE("Color table extension not found.\n");
285 LEAVE_GL();
287 #endif
291 HRESULT d3ddevice_enumerate(LPD3DENUMDEVICESCALLBACK cb, LPVOID context, DWORD version)
293 D3DDEVICEDESC dref, d1, d2;
294 HRESULT ret_value;
296 /* Some games (Motoracer 2 demo) have the bad idea to modify the device name string.
297 Let's put the string in a sufficiently sized array in writable memory. */
298 char device_name[50];
299 strcpy(device_name,"direct3d");
301 fill_opengl_caps(&dref);
303 if (version > 1) {
304 /* It seems that enumerating the reference IID on Direct3D 1 games (AvP / Motoracer2) breaks them */
305 TRACE(" enumerating OpenGL D3DDevice interface using reference IID (IID %s).\n", debugstr_guid(&IID_IDirect3DRefDevice));
306 d1 = dref;
307 d2 = dref;
308 ret_value = cb((LPIID) &IID_IDirect3DRefDevice, "WINE Reference Direct3DX using OpenGL", device_name, &d1, &d2, context);
309 if (ret_value != D3DENUMRET_OK)
310 return ret_value;
313 TRACE(" enumerating OpenGL D3DDevice interface (IID %s).\n", debugstr_guid(&IID_D3DDEVICE_OpenGL));
314 d1 = dref;
315 d2 = dref;
316 ret_value = cb((LPIID) &IID_D3DDEVICE_OpenGL, "WINE Direct3DX using OpenGL", device_name, &d1, &d2, context);
317 if (ret_value != D3DENUMRET_OK)
318 return ret_value;
320 return D3DENUMRET_OK;
323 HRESULT d3ddevice_enumerate7(LPD3DENUMDEVICESCALLBACK7 cb, LPVOID context)
325 D3DDEVICEDESC7 ddesc;
327 fill_opengl_caps_7(&ddesc);
329 TRACE(" enumerating OpenGL D3DDevice7 interface.\n");
331 return cb("WINE Direct3D7 using OpenGL", "Wine D3D7 device", &ddesc, context);
334 ULONG WINAPI
335 GL_IDirect3DDeviceImpl_7_3T_2T_1T_Release(LPDIRECT3DDEVICE7 iface)
337 ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice7, iface);
338 IDirect3DDeviceGLImpl *glThis = (IDirect3DDeviceGLImpl *) This;
340 TRACE("(%p/%p)->() decrementing from %lu.\n", This, iface, This->ref);
341 if (!--(This->ref)) {
342 int i;
343 IDirectDrawSurfaceImpl *surface = This->surface, *surf;
345 /* Release texture associated with the device */
346 for (i = 0; i < MAX_TEXTURES; i++) {
347 if (This->current_texture[i] != NULL)
348 IDirectDrawSurface7_Release(ICOM_INTERFACE(This->current_texture[i], IDirectDrawSurface7));
349 HeapFree(GetProcessHeap(), 0, This->tex_mat[i]);
352 /* Look for the front buffer and override its surface's Flip method (if in double buffering) */
353 for (surf = surface; surf != NULL; surf = surf->surface_owner) {
354 if ((surf->surface_desc.ddsCaps.dwCaps&(DDSCAPS_FLIP|DDSCAPS_FRONTBUFFER)) == (DDSCAPS_FLIP|DDSCAPS_FRONTBUFFER)) {
355 surf->aux_ctx = NULL;
356 surf->aux_data = NULL;
357 surf->aux_flip = NULL;
358 break;
361 for (surf = surface; surf != NULL; surf = surf->surface_owner) {
362 IDirectDrawSurfaceImpl *surf2;
363 for (surf2 = surf; surf2->prev_attached != NULL; surf2 = surf2->prev_attached) ;
364 for (; surf2 != NULL; surf2 = surf2->next_attached) {
365 if (((surf2->surface_desc.ddsCaps.dwCaps & (DDSCAPS_3DDEVICE)) == (DDSCAPS_3DDEVICE)) &&
366 ((surf2->surface_desc.ddsCaps.dwCaps & (DDSCAPS_ZBUFFER)) != (DDSCAPS_ZBUFFER))) {
367 /* Override the Lock / Unlock function for all these surfaces */
368 surf2->lock_update = surf2->lock_update_prev;
369 surf2->unlock_update = surf2->unlock_update_prev;
370 /* And install also the blt / bltfast overrides */
371 surf2->aux_blt = NULL;
372 surf2->aux_bltfast = NULL;
374 surf2->d3ddevice = NULL;
378 /* And warn the D3D object that this device is no longer active... */
379 This->d3d->removed_device(This->d3d, This);
381 HeapFree(GetProcessHeap(), 0, This->world_mat);
382 HeapFree(GetProcessHeap(), 0, This->view_mat);
383 HeapFree(GetProcessHeap(), 0, This->proj_mat);
385 DeleteCriticalSection(&(This->crit));
387 ENTER_GL();
388 if (glThis->unlock_tex)
389 glDeleteTextures(1, &(glThis->unlock_tex));
390 glXDestroyContext(glThis->display, glThis->gl_context);
391 LEAVE_GL();
392 HeapFree(GetProcessHeap(), 0, This->clipping_planes);
394 HeapFree(GetProcessHeap(), 0, This);
395 return 0;
397 return This->ref;
400 HRESULT WINAPI
401 GL_IDirect3DDeviceImpl_3_2T_1T_GetCaps(LPDIRECT3DDEVICE3 iface,
402 LPD3DDEVICEDESC lpD3DHWDevDesc,
403 LPD3DDEVICEDESC lpD3DHELDevDesc)
405 ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice3, iface);
406 D3DDEVICEDESC desc;
407 DWORD dwSize;
409 TRACE("(%p/%p)->(%p,%p)\n", This, iface, lpD3DHWDevDesc, lpD3DHELDevDesc);
411 fill_opengl_caps(&desc);
412 dwSize = lpD3DHWDevDesc->dwSize;
413 memset(lpD3DHWDevDesc, 0, dwSize);
414 memcpy(lpD3DHWDevDesc, &desc, (dwSize <= desc.dwSize ? dwSize : desc.dwSize));
416 dwSize = lpD3DHELDevDesc->dwSize;
417 memset(lpD3DHELDevDesc, 0, dwSize);
418 memcpy(lpD3DHELDevDesc, &desc, (dwSize <= desc.dwSize ? dwSize : desc.dwSize));
420 TRACE(" returning caps : (no dump function yet)\n");
422 return DD_OK;
425 static HRESULT enum_texture_format_OpenGL(LPD3DENUMTEXTUREFORMATSCALLBACK cb_1,
426 LPD3DENUMPIXELFORMATSCALLBACK cb_2,
427 LPVOID context)
429 DDSURFACEDESC sdesc;
430 LPDDPIXELFORMAT pformat;
432 /* Do the texture enumeration */
433 sdesc.dwSize = sizeof(DDSURFACEDESC);
434 sdesc.dwFlags = DDSD_PIXELFORMAT | DDSD_CAPS;
435 sdesc.ddsCaps.dwCaps = DDSCAPS_TEXTURE;
436 pformat = &(sdesc.ddpfPixelFormat);
437 pformat->dwSize = sizeof(DDPIXELFORMAT);
438 pformat->dwFourCC = 0;
440 #if 0
441 /* See argument about the RGBA format for 'packed' texture formats */
442 TRACE("Enumerating GL_RGBA unpacked (32)\n");
443 pformat->dwFlags = DDPF_RGB | DDPF_ALPHAPIXELS;
444 pformat->u1.dwRGBBitCount = 32;
445 pformat->u2.dwRBitMask = 0xFF000000;
446 pformat->u3.dwGBitMask = 0x00FF0000;
447 pformat->u4.dwBBitMask = 0x0000FF00;
448 pformat->u5.dwRGBAlphaBitMask = 0x000000FF;
449 if (cb_1) if (cb_1(&sdesc , context) == 0) return DD_OK;
450 if (cb_2) if (cb_2(pformat, context) == 0) return DD_OK;
451 #endif
453 TRACE("Enumerating GL_RGBA unpacked (32)\n");
454 pformat->dwFlags = DDPF_RGB | DDPF_ALPHAPIXELS;
455 pformat->u1.dwRGBBitCount = 32;
456 pformat->u2.dwRBitMask = 0x00FF0000;
457 pformat->u3.dwGBitMask = 0x0000FF00;
458 pformat->u4.dwBBitMask = 0x000000FF;
459 pformat->u5.dwRGBAlphaBitMask = 0xFF000000;
460 if (cb_1) if (cb_1(&sdesc , context) == 0) return DD_OK;
461 if (cb_2) if (cb_2(pformat, context) == 0) return DD_OK;
463 #if 0 /* Enabling this breaks Tomb Raider 3, need to investigate... */
464 TRACE("Enumerating GL_RGB unpacked (32)\n");
465 pformat->dwFlags = DDPF_RGB;
466 pformat->u1.dwRGBBitCount = 32;
467 pformat->u2.dwRBitMask = 0x00FF0000;
468 pformat->u3.dwGBitMask = 0x0000FF00;
469 pformat->u4.dwBBitMask = 0x000000FF;
470 pformat->u5.dwRGBAlphaBitMask = 0x00000000;
471 if (cb_1) if (cb_1(&sdesc , context) == 0) return DD_OK;
472 if (cb_2) if (cb_2(pformat, context) == 0) return DD_OK;
473 #endif
475 TRACE("Enumerating GL_RGB unpacked (24)\n");
476 pformat->dwFlags = DDPF_RGB;
477 pformat->u1.dwRGBBitCount = 24;
478 pformat->u2.dwRBitMask = 0x00FF0000;
479 pformat->u3.dwGBitMask = 0x0000FF00;
480 pformat->u4.dwBBitMask = 0x000000FF;
481 pformat->u5.dwRGBAlphaBitMask = 0x00000000;
482 if (cb_1) if (cb_1(&sdesc , context) == 0) return DD_OK;
483 if (cb_2) if (cb_2(pformat, context) == 0) return DD_OK;
485 /* Note : even if this is an 'emulated' texture format, it needs to be first
486 as some dumb applications seem to rely on that. */
487 TRACE("Enumerating GL_RGBA packed GL_UNSIGNED_SHORT_1_5_5_5 (ARGB) (16)\n");
488 pformat->dwFlags = DDPF_RGB | DDPF_ALPHAPIXELS;
489 pformat->u1.dwRGBBitCount = 16;
490 pformat->u2.dwRBitMask = 0x00007C00;
491 pformat->u3.dwGBitMask = 0x000003E0;
492 pformat->u4.dwBBitMask = 0x0000001F;
493 pformat->u5.dwRGBAlphaBitMask = 0x00008000;
494 if (cb_1) if (cb_1(&sdesc , context) == 0) return DD_OK;
495 if (cb_2) if (cb_2(pformat, context) == 0) return DD_OK;
497 TRACE("Enumerating GL_RGBA packed GL_UNSIGNED_SHORT_4_4_4_4 (ARGB) (16)\n");
498 pformat->dwFlags = DDPF_RGB | DDPF_ALPHAPIXELS;
499 pformat->u1.dwRGBBitCount = 16;
500 pformat->u2.dwRBitMask = 0x00000F00;
501 pformat->u3.dwGBitMask = 0x000000F0;
502 pformat->u4.dwBBitMask = 0x0000000F;
503 pformat->u5.dwRGBAlphaBitMask = 0x0000F000;
504 if (cb_1) if (cb_1(&sdesc , context) == 0) return DD_OK;
505 if (cb_2) if (cb_2(pformat, context) == 0) return DD_OK;
507 TRACE("Enumerating GL_RGB packed GL_UNSIGNED_SHORT_5_6_5 (16)\n");
508 pformat->dwFlags = DDPF_RGB;
509 pformat->u1.dwRGBBitCount = 16;
510 pformat->u2.dwRBitMask = 0x0000F800;
511 pformat->u3.dwGBitMask = 0x000007E0;
512 pformat->u4.dwBBitMask = 0x0000001F;
513 pformat->u5.dwRGBAlphaBitMask = 0x00000000;
514 if (cb_1) if (cb_1(&sdesc , context) == 0) return DD_OK;
515 if (cb_2) if (cb_2(pformat, context) == 0) return DD_OK;
517 TRACE("Enumerating GL_RGB packed GL_UNSIGNED_SHORT_5_5_5 (16)\n");
518 pformat->dwFlags = DDPF_RGB;
519 pformat->u1.dwRGBBitCount = 16;
520 pformat->u2.dwRBitMask = 0x00007C00;
521 pformat->u3.dwGBitMask = 0x000003E0;
522 pformat->u4.dwBBitMask = 0x0000001F;
523 pformat->u5.dwRGBAlphaBitMask = 0x00000000;
524 if (cb_1) if (cb_1(&sdesc , context) == 0) return DD_OK;
525 if (cb_2) if (cb_2(pformat, context) == 0) return DD_OK;
527 #if 0
528 /* This is a compromise : some games choose the first 16 bit texture format with alpha they
529 find enumerated, others the last one. And both want to have the ARGB one.
531 So basically, forget our OpenGL roots and do not even enumerate our RGBA ones.
533 TRACE("Enumerating GL_RGBA packed GL_UNSIGNED_SHORT_4_4_4_4 (16)\n");
534 pformat->dwFlags = DDPF_RGB | DDPF_ALPHAPIXELS;
535 pformat->u1.dwRGBBitCount = 16;
536 pformat->u2.dwRBitMask = 0x0000F000;
537 pformat->u3.dwGBitMask = 0x00000F00;
538 pformat->u4.dwBBitMask = 0x000000F0;
539 pformat->u5.dwRGBAlphaBitMask = 0x0000000F;
540 if (cb_1) if (cb_1(&sdesc , context) == 0) return DD_OK;
541 if (cb_2) if (cb_2(pformat, context) == 0) return DD_OK;
543 TRACE("Enumerating GL_RGBA packed GL_UNSIGNED_SHORT_5_5_5_1 (16)\n");
544 pformat->dwFlags = DDPF_RGB | DDPF_ALPHAPIXELS;
545 pformat->u1.dwRGBBitCount = 16;
546 pformat->u2.dwRBitMask = 0x0000F800;
547 pformat->u3.dwGBitMask = 0x000007C0;
548 pformat->u4.dwBBitMask = 0x0000003E;
549 pformat->u5.dwRGBAlphaBitMask = 0x00000001;
550 if (cb_1) if (cb_1(&sdesc , context) == 0) return DD_OK;
551 if (cb_2) if (cb_2(pformat, context) == 0) return DD_OK;
552 #endif
554 TRACE("Enumerating GL_RGB packed GL_UNSIGNED_BYTE_3_3_2 (8)\n");
555 pformat->dwFlags = DDPF_RGB;
556 pformat->u1.dwRGBBitCount = 8;
557 pformat->u2.dwRBitMask = 0x000000E0;
558 pformat->u3.dwGBitMask = 0x0000001C;
559 pformat->u4.dwBBitMask = 0x00000003;
560 pformat->u5.dwRGBAlphaBitMask = 0x00000000;
561 if (cb_1) if (cb_1(&sdesc , context) == 0) return DD_OK;
562 if (cb_2) if (cb_2(pformat, context) == 0) return DD_OK;
564 TRACE("Enumerating Paletted (8)\n");
565 pformat->dwFlags = DDPF_PALETTEINDEXED8;
566 pformat->u1.dwRGBBitCount = 8;
567 pformat->u2.dwRBitMask = 0x00000000;
568 pformat->u3.dwGBitMask = 0x00000000;
569 pformat->u4.dwBBitMask = 0x00000000;
570 pformat->u5.dwRGBAlphaBitMask = 0x00000000;
571 if (cb_1) if (cb_1(&sdesc , context) == 0) return DD_OK;
572 if (cb_2) if (cb_2(pformat, context) == 0) return DD_OK;
574 TRACE("End of enumeration\n");
575 return DD_OK;
579 HRESULT
580 d3ddevice_find(IDirect3DImpl *d3d,
581 LPD3DFINDDEVICESEARCH lpD3DDFS,
582 LPD3DFINDDEVICERESULT lplpD3DDevice)
584 D3DDEVICEDESC desc;
586 if ((lpD3DDFS->dwFlags & D3DFDS_COLORMODEL) &&
587 (lpD3DDFS->dcmColorModel != D3DCOLOR_RGB)) {
588 TRACE(" trying to request a non-RGB D3D color model. Not supported.\n");
589 return DDERR_INVALIDPARAMS; /* No real idea what to return here :-) */
591 if (lpD3DDFS->dwFlags & D3DFDS_GUID) {
592 TRACE(" trying to match guid %s.\n", debugstr_guid(&(lpD3DDFS->guid)));
593 if ((IsEqualGUID(&IID_D3DDEVICE_OpenGL, &(lpD3DDFS->guid)) == 0) &&
594 (IsEqualGUID(&IID_IDirect3DHALDevice, &(lpD3DDFS->guid)) == 0) &&
595 (IsEqualGUID(&IID_IDirect3DRefDevice, &(lpD3DDFS->guid)) == 0)) {
596 TRACE(" no match for this GUID.\n");
597 return DDERR_INVALIDPARAMS;
601 /* Now return our own GUID */
602 lplpD3DDevice->guid = IID_D3DDEVICE_OpenGL;
603 fill_opengl_caps(&desc);
604 lplpD3DDevice->ddHwDesc = desc;
605 lplpD3DDevice->ddSwDesc = desc;
607 TRACE(" returning Wine's OpenGL device with (undumped) capabilities\n");
609 return D3D_OK;
612 HRESULT WINAPI
613 GL_IDirect3DDeviceImpl_2_1T_EnumTextureFormats(LPDIRECT3DDEVICE2 iface,
614 LPD3DENUMTEXTUREFORMATSCALLBACK lpD3DEnumTextureProc,
615 LPVOID lpArg)
617 ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice2, iface);
618 TRACE("(%p/%p)->(%p,%p)\n", This, iface, lpD3DEnumTextureProc, lpArg);
619 return enum_texture_format_OpenGL(lpD3DEnumTextureProc, NULL, lpArg);
622 HRESULT WINAPI
623 GL_IDirect3DDeviceImpl_7_3T_EnumTextureFormats(LPDIRECT3DDEVICE7 iface,
624 LPD3DENUMPIXELFORMATSCALLBACK lpD3DEnumPixelProc,
625 LPVOID lpArg)
627 ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice7, iface);
628 TRACE("(%p/%p)->(%p,%p)\n", This, iface, lpD3DEnumPixelProc, lpArg);
629 return enum_texture_format_OpenGL(NULL, lpD3DEnumPixelProc, lpArg);
632 HRESULT WINAPI
633 GL_IDirect3DDeviceImpl_7_3T_2T_SetRenderState(LPDIRECT3DDEVICE7 iface,
634 D3DRENDERSTATETYPE dwRenderStateType,
635 DWORD dwRenderState)
637 ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice7, iface);
638 TRACE("(%p/%p)->(%08x,%08lx)\n", This, iface, dwRenderStateType, dwRenderState);
640 /* Call the render state functions */
641 store_render_state(This, dwRenderStateType, dwRenderState, &This->state_block);
642 set_render_state(This, dwRenderStateType, &This->state_block);
644 return DD_OK;
647 HRESULT WINAPI
648 GL_IDirect3DDeviceImpl_7_3T_2T_GetRenderState(LPDIRECT3DDEVICE7 iface,
649 D3DRENDERSTATETYPE dwRenderStateType,
650 LPDWORD lpdwRenderState)
652 ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice7, iface);
653 TRACE("(%p/%p)->(%08x,%p)\n", This, iface, dwRenderStateType, lpdwRenderState);
655 /* Call the render state functions */
656 get_render_state(This, dwRenderStateType, lpdwRenderState, &This->state_block);
658 TRACE(" - asked for rendering state : %s, returning value %08lx.\n", _get_renderstate(dwRenderStateType), *lpdwRenderState);
660 return DD_OK;
663 HRESULT WINAPI
664 GL_IDirect3DDeviceImpl_3_2T_SetLightState(LPDIRECT3DDEVICE3 iface,
665 D3DLIGHTSTATETYPE dwLightStateType,
666 DWORD dwLightState)
668 ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice3, iface);
670 TRACE("(%p/%p)->(%08x,%08lx)\n", This, iface, dwLightStateType, dwLightState);
672 if (!dwLightStateType && (dwLightStateType > D3DLIGHTSTATE_COLORVERTEX))
673 TRACE("Unexpected Light State Type\n");
674 return DDERR_INVALIDPARAMS;
676 if (dwLightStateType == D3DLIGHTSTATE_MATERIAL /* 1 */) {
677 IDirect3DMaterialImpl *mat = (IDirect3DMaterialImpl *) dwLightState;
679 if (mat != NULL) {
680 ENTER_GL();
681 mat->activate(mat);
682 LEAVE_GL();
683 } else {
684 ERR(" D3DLIGHTSTATE_MATERIAL called with NULL material !!!\n");
686 } else if (dwLightStateType == D3DLIGHTSTATE_COLORMODEL /* 3 */) {
687 switch (dwLightState) {
688 case D3DCOLOR_MONO:
689 ERR("DDCOLOR_MONO should not happen!\n");
690 break;
691 case D3DCOLOR_RGB:
692 /* We are already in this mode */
693 break;
694 default:
695 ERR("Unknown color model!\n");
696 break;
698 } else {
699 D3DRENDERSTATETYPE rs;
700 switch (dwLightStateType) {
702 case D3DLIGHTSTATE_AMBIENT: /* 2 */
703 rs = D3DRENDERSTATE_AMBIENT;
704 break;
705 case D3DLIGHTSTATE_FOGMODE: /* 4 */
706 rs = D3DRENDERSTATE_FOGVERTEXMODE;
707 break;
708 case D3DLIGHTSTATE_FOGSTART: /* 5 */
709 rs = D3DRENDERSTATE_FOGSTART;
710 break;
711 case D3DLIGHTSTATE_FOGEND: /* 6 */
712 rs = D3DRENDERSTATE_FOGEND;
713 break;
714 case D3DLIGHTSTATE_FOGDENSITY: /* 7 */
715 rs = D3DRENDERSTATE_FOGDENSITY;
716 break;
717 case D3DLIGHTSTATE_COLORVERTEX: /* 8 */
718 rs = D3DRENDERSTATE_COLORVERTEX;
719 break;
720 default:
721 break;
724 IDirect3DDevice7_SetRenderState(ICOM_INTERFACE(This, IDirect3DDevice7),
725 rs,dwLightState);
728 return DD_OK;
731 static void draw_primitive_start_GL(D3DPRIMITIVETYPE d3dpt)
733 switch (d3dpt) {
734 case D3DPT_POINTLIST:
735 TRACE("Start POINTS\n");
736 glBegin(GL_POINTS);
737 break;
739 case D3DPT_LINELIST:
740 TRACE("Start LINES\n");
741 glBegin(GL_LINES);
742 break;
744 case D3DPT_LINESTRIP:
745 TRACE("Start LINE_STRIP\n");
746 glBegin(GL_LINE_STRIP);
747 break;
749 case D3DPT_TRIANGLELIST:
750 TRACE("Start TRIANGLES\n");
751 glBegin(GL_TRIANGLES);
752 break;
754 case D3DPT_TRIANGLESTRIP:
755 TRACE("Start TRIANGLE_STRIP\n");
756 glBegin(GL_TRIANGLE_STRIP);
757 break;
759 case D3DPT_TRIANGLEFAN:
760 TRACE("Start TRIANGLE_FAN\n");
761 glBegin(GL_TRIANGLE_FAN);
762 break;
764 default:
765 FIXME("Unhandled primitive %08x\n", d3dpt);
766 break;
770 /* This function calculate the Z coordinate from Zproj */
771 static float ZfromZproj(IDirect3DDeviceImpl *This, D3DVALUE Zproj)
773 float a,b,c,d;
774 /* Assume that X = Y = 0 and W = 1 */
775 a = This->proj_mat->_33;
776 b = This->proj_mat->_34;
777 c = This->proj_mat->_43;
778 d = This->proj_mat->_44;
779 /* We have in homogenous coordinates Z' = a * Z + c and W' = b * Z + d
780 * So in non homogenous coordinates we have Zproj = (a * Z + c) / (b * Z + d)
781 * And finally Z = (d * Zproj - c) / (a - b * Zproj)
783 return (d*Zproj - c) / (a - b*Zproj);
786 static void build_fog_table(BYTE *fog_table, DWORD fog_color) {
787 int i;
789 TRACE(" rebuilding fog table (%06lx)...\n", fog_color & 0x00FFFFFF);
791 for (i = 0; i < 3; i++) {
792 BYTE fog_color_component = (fog_color >> (8 * i)) & 0xFF;
793 DWORD elt;
794 for (elt = 0; elt < 0x10000; elt++) {
795 /* We apply the fog transformation and cache the result */
796 DWORD fog_intensity = elt & 0xFF;
797 DWORD vertex_color = (elt >> 8) & 0xFF;
798 fog_table[(i * 0x10000) + elt] = ((fog_intensity * vertex_color) + ((0xFF - fog_intensity) * fog_color_component)) / 0xFF;
803 static void draw_primitive_handle_GL_state(IDirect3DDeviceImpl *This,
804 BOOLEAN vertex_transformed,
805 BOOLEAN vertex_lit) {
806 IDirect3DDeviceGLImpl* glThis = (IDirect3DDeviceGLImpl*) This;
808 /* Puts GL in the correct lighting / transformation mode */
809 if ((vertex_transformed == FALSE) &&
810 (glThis->transform_state != GL_TRANSFORM_NORMAL)) {
811 /* Need to put the correct transformation again if we go from Transformed
812 vertices to non-transformed ones.
814 This->set_matrices(This, VIEWMAT_CHANGED|WORLDMAT_CHANGED|PROJMAT_CHANGED,
815 This->world_mat, This->view_mat, This->proj_mat);
816 glThis->transform_state = GL_TRANSFORM_NORMAL;
818 } else if ((vertex_transformed == TRUE) &&
819 (glThis->transform_state != GL_TRANSFORM_ORTHO)) {
820 /* Set our orthographic projection */
821 glThis->transform_state = GL_TRANSFORM_ORTHO;
822 d3ddevice_set_ortho(This);
825 /* TODO: optimize this to not always reset all the fog stuff on all DrawPrimitive call
826 if no fogging state change occured */
827 if (This->state_block.render_state[D3DRENDERSTATE_FOGENABLE - 1] == TRUE) {
828 if (vertex_transformed == TRUE) {
829 glDisable(GL_FOG);
830 /* Now check if our fog_table still corresponds to the current vertex color.
831 Element '0x..00' is always the fog color as it corresponds to maximum fog intensity */
832 if ((glThis->fog_table[0 * 0x10000 + 0x0000] != ((This->state_block.render_state[D3DRENDERSTATE_FOGCOLOR - 1] >> 0) & 0xFF)) ||
833 (glThis->fog_table[1 * 0x10000 + 0x0000] != ((This->state_block.render_state[D3DRENDERSTATE_FOGCOLOR - 1] >> 8) & 0xFF)) ||
834 (glThis->fog_table[2 * 0x10000 + 0x0000] != ((This->state_block.render_state[D3DRENDERSTATE_FOGCOLOR - 1] >> 16) & 0xFF))) {
835 /* We need to rebuild our fog table.... */
836 build_fog_table(glThis->fog_table, This->state_block.render_state[D3DRENDERSTATE_FOGCOLOR - 1]);
838 } else {
839 if (This->state_block.render_state[D3DRENDERSTATE_FOGTABLEMODE - 1] != D3DFOG_NONE) {
840 switch (This->state_block.render_state[D3DRENDERSTATE_FOGTABLEMODE - 1]) {
841 case D3DFOG_LINEAR: glFogi(GL_FOG_MODE, GL_LINEAR); break;
842 case D3DFOG_EXP: glFogi(GL_FOG_MODE, GL_EXP); break;
843 case D3DFOG_EXP2: glFogi(GL_FOG_MODE, GL_EXP2); break;
845 if (vertex_lit == FALSE) {
846 glFogf(GL_FOG_START, *(float*)&This->state_block.render_state[D3DRENDERSTATE_FOGSTART - 1]);
847 glFogf(GL_FOG_END, *(float*)&This->state_block.render_state[D3DRENDERSTATE_FOGEND - 1]);
848 } else {
849 /* Special case of 'pixel fog' */
850 glFogf(GL_FOG_START, ZfromZproj(This, *(float*)&This->state_block.render_state[D3DRENDERSTATE_FOGSTART - 1]));
851 glFogf(GL_FOG_END, ZfromZproj(This, *(float*)&This->state_block.render_state[D3DRENDERSTATE_FOGEND - 1]));
853 glEnable(GL_FOG);
854 } else {
855 glDisable(GL_FOG);
858 } else {
859 glDisable(GL_FOG);
862 /* Handle the 'no-normal' case */
863 if ((vertex_lit == FALSE) && (This->state_block.render_state[D3DRENDERSTATE_LIGHTING - 1] == TRUE))
864 glEnable(GL_LIGHTING);
865 else
866 glDisable(GL_LIGHTING);
868 /* Handle the code for pre-vertex material properties */
869 if (vertex_transformed == FALSE) {
870 if ((This->state_block.render_state[D3DRENDERSTATE_LIGHTING - 1] == TRUE) &&
871 (This->state_block.render_state[D3DRENDERSTATE_COLORVERTEX - 1] == TRUE)) {
872 if ((This->state_block.render_state[D3DRENDERSTATE_DIFFUSEMATERIALSOURCE - 1] != D3DMCS_MATERIAL) ||
873 (This->state_block.render_state[D3DRENDERSTATE_AMBIENTMATERIALSOURCE - 1] != D3DMCS_MATERIAL) ||
874 (This->state_block.render_state[D3DRENDERSTATE_EMISSIVEMATERIALSOURCE - 1] != D3DMCS_MATERIAL) ||
875 (This->state_block.render_state[D3DRENDERSTATE_SPECULARMATERIALSOURCE - 1] != D3DMCS_MATERIAL)) {
876 glEnable(GL_COLOR_MATERIAL);
883 inline static void draw_primitive(IDirect3DDeviceImpl *This, DWORD maxvert, WORD *index,
884 D3DVERTEXTYPE d3dvt, D3DPRIMITIVETYPE d3dpt, void *lpvertex)
886 D3DDRAWPRIMITIVESTRIDEDDATA strided;
888 switch (d3dvt) {
889 case D3DVT_VERTEX: {
890 strided.position.lpvData = &((D3DVERTEX *) lpvertex)->u1.x;
891 strided.position.dwStride = sizeof(D3DVERTEX);
892 strided.normal.lpvData = &((D3DVERTEX *) lpvertex)->u4.nx;
893 strided.normal.dwStride = sizeof(D3DVERTEX);
894 strided.textureCoords[0].lpvData = &((D3DVERTEX *) lpvertex)->u7.tu;
895 strided.textureCoords[0].dwStride = sizeof(D3DVERTEX);
896 draw_primitive_strided(This, d3dpt, D3DFVF_VERTEX, &strided, 0 /* Unused */, index, maxvert, 0 /* Unused */);
897 } break;
899 case D3DVT_LVERTEX: {
900 strided.position.lpvData = &((D3DLVERTEX *) lpvertex)->u1.x;
901 strided.position.dwStride = sizeof(D3DLVERTEX);
902 strided.diffuse.lpvData = &((D3DLVERTEX *) lpvertex)->u4.color;
903 strided.diffuse.dwStride = sizeof(D3DLVERTEX);
904 strided.specular.lpvData = &((D3DLVERTEX *) lpvertex)->u5.specular;
905 strided.specular.dwStride = sizeof(D3DLVERTEX);
906 strided.textureCoords[0].lpvData = &((D3DLVERTEX *) lpvertex)->u6.tu;
907 strided.textureCoords[0].dwStride = sizeof(D3DLVERTEX);
908 draw_primitive_strided(This, d3dpt, D3DFVF_LVERTEX, &strided, 0 /* Unused */, index, maxvert, 0 /* Unused */);
909 } break;
911 case D3DVT_TLVERTEX: {
912 strided.position.lpvData = &((D3DTLVERTEX *) lpvertex)->u1.sx;
913 strided.position.dwStride = sizeof(D3DTLVERTEX);
914 strided.diffuse.lpvData = &((D3DTLVERTEX *) lpvertex)->u5.color;
915 strided.diffuse.dwStride = sizeof(D3DTLVERTEX);
916 strided.specular.lpvData = &((D3DTLVERTEX *) lpvertex)->u6.specular;
917 strided.specular.dwStride = sizeof(D3DTLVERTEX);
918 strided.textureCoords[0].lpvData = &((D3DTLVERTEX *) lpvertex)->u7.tu;
919 strided.textureCoords[0].dwStride = sizeof(D3DTLVERTEX);
920 draw_primitive_strided(This, d3dpt, D3DFVF_TLVERTEX, &strided, 0 /* Unused */, index, maxvert, 0 /* Unused */);
921 } break;
923 default:
924 FIXME("Unhandled vertex type %08x\n", d3dvt);
925 break;
929 HRESULT WINAPI
930 GL_IDirect3DDeviceImpl_2_DrawPrimitive(LPDIRECT3DDEVICE2 iface,
931 D3DPRIMITIVETYPE d3dptPrimitiveType,
932 D3DVERTEXTYPE d3dvtVertexType,
933 LPVOID lpvVertices,
934 DWORD dwVertexCount,
935 DWORD dwFlags)
937 ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice2, iface);
939 TRACE("(%p/%p)->(%08x,%08x,%p,%08lx,%08lx)\n", This, iface, d3dptPrimitiveType, d3dvtVertexType, lpvVertices, dwVertexCount, dwFlags);
940 if (TRACE_ON(ddraw)) {
941 TRACE(" - flags : "); dump_DPFLAGS(dwFlags);
944 draw_primitive(This, dwVertexCount, NULL, d3dvtVertexType, d3dptPrimitiveType, lpvVertices);
946 return DD_OK;
949 HRESULT WINAPI
950 GL_IDirect3DDeviceImpl_2_DrawIndexedPrimitive(LPDIRECT3DDEVICE2 iface,
951 D3DPRIMITIVETYPE d3dptPrimitiveType,
952 D3DVERTEXTYPE d3dvtVertexType,
953 LPVOID lpvVertices,
954 DWORD dwVertexCount,
955 LPWORD dwIndices,
956 DWORD dwIndexCount,
957 DWORD dwFlags)
959 ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice2, iface);
960 TRACE("(%p/%p)->(%08x,%08x,%p,%08lx,%p,%08lx,%08lx)\n", This, iface, d3dptPrimitiveType, d3dvtVertexType, lpvVertices, dwVertexCount, dwIndices, dwIndexCount, dwFlags);
961 if (TRACE_ON(ddraw)) {
962 TRACE(" - flags : "); dump_DPFLAGS(dwFlags);
965 draw_primitive(This, dwIndexCount, dwIndices, d3dvtVertexType, d3dptPrimitiveType, lpvVertices);
967 return DD_OK;
970 HRESULT WINAPI
971 GL_IDirect3DDeviceImpl_1_CreateExecuteBuffer(LPDIRECT3DDEVICE iface,
972 LPD3DEXECUTEBUFFERDESC lpDesc,
973 LPDIRECT3DEXECUTEBUFFER* lplpDirect3DExecuteBuffer,
974 IUnknown* pUnkOuter)
976 ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice, iface);
977 IDirect3DExecuteBufferImpl *ret;
978 HRESULT ret_value;
980 TRACE("(%p/%p)->(%p,%p,%p)\n", This, iface, lpDesc, lplpDirect3DExecuteBuffer, pUnkOuter);
982 ret_value = d3dexecutebuffer_create(&ret, This->d3d, This, lpDesc);
983 *lplpDirect3DExecuteBuffer = ICOM_INTERFACE(ret, IDirect3DExecuteBuffer);
985 TRACE(" returning %p.\n", *lplpDirect3DExecuteBuffer);
987 return ret_value;
990 /* These are the various handler used in the generic path */
991 inline static void handle_xyz(D3DVALUE *coords) {
992 glVertex3fv(coords);
994 inline static void handle_xyzrhw(D3DVALUE *coords) {
995 if (coords[3] < 1e-8)
996 glVertex3fv(coords);
997 else {
998 GLfloat w = 1.0 / coords[3];
1000 glVertex4f(coords[0] * w,
1001 coords[1] * w,
1002 coords[2] * w,
1006 inline static void handle_normal(D3DVALUE *coords) {
1007 glNormal3fv(coords);
1010 inline static void handle_diffuse_base(STATEBLOCK *sb, DWORD *color) {
1011 if ((sb->render_state[D3DRENDERSTATE_ALPHATESTENABLE - 1] == TRUE) ||
1012 (sb->render_state[D3DRENDERSTATE_ALPHABLENDENABLE - 1] == TRUE)) {
1013 glColor4ub((*color >> 16) & 0xFF,
1014 (*color >> 8) & 0xFF,
1015 (*color >> 0) & 0xFF,
1016 (*color >> 24) & 0xFF);
1017 } else {
1018 glColor3ub((*color >> 16) & 0xFF,
1019 (*color >> 8) & 0xFF,
1020 (*color >> 0) & 0xFF);
1024 inline static void handle_specular_base(STATEBLOCK *sb, DWORD *color) {
1025 glColor4ub((*color >> 16) & 0xFF,
1026 (*color >> 8) & 0xFF,
1027 (*color >> 0) & 0xFF,
1028 (*color >> 24) & 0xFF); /* No idea if the alpha field is really used.. */
1031 inline static void handle_diffuse(STATEBLOCK *sb, DWORD *color, BOOLEAN lighted) {
1032 if ((lighted == FALSE) &&
1033 (sb->render_state[D3DRENDERSTATE_LIGHTING - 1] == TRUE) &&
1034 (sb->render_state[D3DRENDERSTATE_COLORVERTEX - 1] == TRUE)) {
1035 if (sb->render_state[D3DRENDERSTATE_DIFFUSEMATERIALSOURCE - 1] == D3DMCS_COLOR1) {
1036 glColorMaterial(GL_FRONT_AND_BACK, GL_DIFFUSE);
1037 handle_diffuse_base(sb, color);
1039 if (sb->render_state[D3DRENDERSTATE_AMBIENTMATERIALSOURCE - 1] == D3DMCS_COLOR1) {
1040 glColorMaterial(GL_FRONT_AND_BACK, GL_AMBIENT);
1041 handle_diffuse_base(sb, color);
1043 if ((sb->render_state[D3DRENDERSTATE_SPECULARMATERIALSOURCE - 1] == D3DMCS_COLOR1) &&
1044 (sb->render_state[D3DRENDERSTATE_SPECULARENABLE - 1] == TRUE)) {
1045 glColorMaterial(GL_FRONT_AND_BACK, GL_SPECULAR);
1046 handle_diffuse_base(sb, color);
1048 if (sb->render_state[D3DRENDERSTATE_EMISSIVEMATERIALSOURCE - 1] == D3DMCS_COLOR1) {
1049 glColorMaterial(GL_FRONT_AND_BACK, GL_EMISSION);
1050 handle_diffuse_base(sb, color);
1052 } else {
1053 handle_diffuse_base(sb, color);
1057 inline static void handle_specular(STATEBLOCK *sb, DWORD *color, BOOLEAN lighted) {
1058 if ((lighted == FALSE) &&
1059 (sb->render_state[D3DRENDERSTATE_LIGHTING - 1] == TRUE) &&
1060 (sb->render_state[D3DRENDERSTATE_COLORVERTEX - 1] == TRUE)) {
1061 if (sb->render_state[D3DRENDERSTATE_DIFFUSEMATERIALSOURCE - 1] == D3DMCS_COLOR2) {
1062 glColorMaterial(GL_FRONT_AND_BACK, GL_DIFFUSE);
1063 handle_specular_base(sb, color);
1065 if (sb->render_state[D3DRENDERSTATE_AMBIENTMATERIALSOURCE - 1] == D3DMCS_COLOR2) {
1066 glColorMaterial(GL_FRONT_AND_BACK, GL_AMBIENT);
1067 handle_specular_base(sb, color);
1069 if ((sb->render_state[D3DRENDERSTATE_SPECULARMATERIALSOURCE - 1] == D3DMCS_COLOR2) &&
1070 (sb->render_state[D3DRENDERSTATE_SPECULARENABLE - 1] == TRUE)) {
1071 glColorMaterial(GL_FRONT_AND_BACK, GL_SPECULAR);
1072 handle_specular_base(sb, color);
1074 if (sb->render_state[D3DRENDERSTATE_EMISSIVEMATERIALSOURCE - 1] == D3DMCS_COLOR2) {
1075 glColorMaterial(GL_FRONT_AND_BACK, GL_EMISSION);
1076 handle_specular_base(sb, color);
1079 /* No else here as we do not know how to handle 'specular' on its own in any case.. */
1082 inline static void handle_diffuse_and_specular(STATEBLOCK *sb, BYTE *fog_table, DWORD *color_d, DWORD *color_s, BOOLEAN lighted) {
1083 if (lighted == TRUE) {
1084 DWORD color = *color_d;
1085 if (sb->render_state[D3DRENDERSTATE_FOGENABLE - 1] == TRUE) {
1086 /* Special case where the specular value is used to do fogging */
1087 BYTE fog_intensity = *color_s >> 24; /* The alpha value of the specular component is the fog 'intensity' for this vertex */
1088 color &= 0xFF000000; /* Only keep the alpha component */
1089 color |= fog_table[((*color_d >> 0) & 0xFF) << 8 | fog_intensity] << 0;
1090 color |= fog_table[((*color_d >> 8) & 0xFF) << 8 | fog_intensity] << 8;
1091 color |= fog_table[((*color_d >> 16) & 0xFF) << 8 | fog_intensity] << 16;
1093 if (sb->render_state[D3DRENDERSTATE_SPECULARENABLE - 1] == TRUE) {
1094 /* Standard specular value in transformed mode. TODO */
1096 handle_diffuse_base(sb, &color);
1097 } else {
1098 if (sb->render_state[D3DRENDERSTATE_LIGHTING - 1] == TRUE) {
1099 handle_diffuse(sb, color_d, FALSE);
1100 handle_specular(sb, color_s, FALSE);
1101 } else {
1102 /* In that case, only put the diffuse color... */
1103 handle_diffuse_base(sb, color_d);
1108 inline static void handle_texture(D3DVALUE *coords) {
1109 glTexCoord2fv(coords);
1111 inline static void handle_textures(D3DVALUE *coords, int tex_index) {
1112 /* For the moment, draw only the first texture.. */
1113 if (tex_index == 0) glTexCoord2fv(coords);
1116 static void draw_primitive_strided(IDirect3DDeviceImpl *This,
1117 D3DPRIMITIVETYPE d3dptPrimitiveType,
1118 DWORD d3dvtVertexType,
1119 LPD3DDRAWPRIMITIVESTRIDEDDATA lpD3DDrawPrimStrideData,
1120 DWORD dwVertexCount,
1121 LPWORD dwIndices,
1122 DWORD dwIndexCount,
1123 DWORD dwFlags)
1125 BOOLEAN vertex_lighted = FALSE;
1126 IDirect3DDeviceGLImpl* glThis = (IDirect3DDeviceGLImpl*) This;
1127 int num_active_stages = 0;
1129 ENTER_GL();
1130 if (glThis->state == SURFACE_MEMORY_DIRTY) {
1131 This->flush_to_framebuffer(This, NULL, glThis->lock_surf);
1133 LEAVE_GL();
1135 glThis->state = SURFACE_GL;
1137 /* Compute the number of active texture stages */
1138 while (This->current_texture[num_active_stages] != NULL) num_active_stages++;
1140 /* This is to prevent 'thread contention' between a thread locking the device and another
1141 doing 3D display on it... */
1142 EnterCriticalSection(&(This->crit));
1144 if (TRACE_ON(ddraw)) {
1145 TRACE(" Vertex format : "); dump_flexible_vertex(d3dvtVertexType);
1148 ENTER_GL();
1150 /* Just a hack for now.. Will have to find better algorithm :-/ */
1151 if ((d3dvtVertexType & D3DFVF_POSITION_MASK) != D3DFVF_XYZ) {
1152 vertex_lighted = TRUE;
1153 } else {
1154 if ((d3dvtVertexType & D3DFVF_NORMAL) == 0) glNormal3f(0.0, 0.0, 0.0);
1157 draw_primitive_handle_GL_state(This,
1158 (d3dvtVertexType & D3DFVF_POSITION_MASK) != D3DFVF_XYZ,
1159 vertex_lighted);
1160 draw_primitive_start_GL(d3dptPrimitiveType);
1162 /* Some fast paths first before the generic case.... */
1163 if ((d3dvtVertexType == D3DFVF_VERTEX) && (num_active_stages <= 1)) {
1164 int index;
1166 for (index = 0; index < dwIndexCount; index++) {
1167 int i = (dwIndices == NULL) ? index : dwIndices[index];
1168 D3DVALUE *normal =
1169 (D3DVALUE *) (((char *) lpD3DDrawPrimStrideData->normal.lpvData) + i * lpD3DDrawPrimStrideData->normal.dwStride);
1170 D3DVALUE *tex_coord =
1171 (D3DVALUE *) (((char *) lpD3DDrawPrimStrideData->textureCoords[0].lpvData) + i * lpD3DDrawPrimStrideData->textureCoords[0].dwStride);
1172 D3DVALUE *position =
1173 (D3DVALUE *) (((char *) lpD3DDrawPrimStrideData->position.lpvData) + i * lpD3DDrawPrimStrideData->position.dwStride);
1175 handle_normal(normal);
1176 handle_texture(tex_coord);
1177 handle_xyz(position);
1179 TRACE_(ddraw_geom)(" %f %f %f / %f %f %f (%f %f)\n",
1180 position[0], position[1], position[2],
1181 normal[0], normal[1], normal[2],
1182 tex_coord[0], tex_coord[1]);
1184 } else if ((d3dvtVertexType == D3DFVF_TLVERTEX) && (num_active_stages <= 1)) {
1185 int index;
1187 for (index = 0; index < dwIndexCount; index++) {
1188 int i = (dwIndices == NULL) ? index : dwIndices[index];
1189 DWORD *color_d =
1190 (DWORD *) (((char *) lpD3DDrawPrimStrideData->diffuse.lpvData) + i * lpD3DDrawPrimStrideData->diffuse.dwStride);
1191 DWORD *color_s =
1192 (DWORD *) (((char *) lpD3DDrawPrimStrideData->specular.lpvData) + i * lpD3DDrawPrimStrideData->specular.dwStride);
1193 D3DVALUE *tex_coord =
1194 (D3DVALUE *) (((char *) lpD3DDrawPrimStrideData->textureCoords[0].lpvData) + i * lpD3DDrawPrimStrideData->textureCoords[0].dwStride);
1195 D3DVALUE *position =
1196 (D3DVALUE *) (((char *) lpD3DDrawPrimStrideData->position.lpvData) + i * lpD3DDrawPrimStrideData->position.dwStride);
1198 handle_diffuse_and_specular(&(This->state_block), glThis->fog_table, color_d, color_s, TRUE);
1199 handle_texture(tex_coord);
1200 handle_xyzrhw(position);
1202 TRACE_(ddraw_geom)(" %f %f %f %f / %02lx %02lx %02lx %02lx - %02lx %02lx %02lx %02lx (%f %f)\n",
1203 position[0], position[1], position[2], position[3],
1204 (*color_d >> 16) & 0xFF,
1205 (*color_d >> 8) & 0xFF,
1206 (*color_d >> 0) & 0xFF,
1207 (*color_d >> 24) & 0xFF,
1208 (*color_s >> 16) & 0xFF,
1209 (*color_s >> 8) & 0xFF,
1210 (*color_s >> 0) & 0xFF,
1211 (*color_s >> 24) & 0xFF,
1212 tex_coord[0], tex_coord[1]);
1214 } else if (((d3dvtVertexType & D3DFVF_POSITION_MASK) == D3DFVF_XYZ) ||
1215 ((d3dvtVertexType & D3DFVF_POSITION_MASK) == D3DFVF_XYZRHW)) {
1216 /* This is the 'slow path' but that should support all possible vertex formats out there...
1217 Note that people should write a fast path for all vertex formats out there...
1219 int index;
1220 int num_tex_index = ((d3dvtVertexType & D3DFVF_TEXCOUNT_MASK) >> D3DFVF_TEXCOUNT_SHIFT);
1221 static const D3DVALUE no_index[] = { 0.0, 0.0, 0.0, 0.0 };
1223 for (index = 0; index < dwIndexCount; index++) {
1224 int i = (dwIndices == NULL) ? index : dwIndices[index];
1225 int tex_stage;
1227 if (d3dvtVertexType & D3DFVF_NORMAL) {
1228 D3DVALUE *normal =
1229 (D3DVALUE *) (((char *) lpD3DDrawPrimStrideData->normal.lpvData) + i * lpD3DDrawPrimStrideData->normal.dwStride);
1230 handle_normal(normal);
1232 if ((d3dvtVertexType & (D3DFVF_DIFFUSE|D3DFVF_SPECULAR)) == (D3DFVF_DIFFUSE|D3DFVF_SPECULAR)) {
1233 DWORD *color_d =
1234 (DWORD *) (((char *) lpD3DDrawPrimStrideData->diffuse.lpvData) + i * lpD3DDrawPrimStrideData->diffuse.dwStride);
1235 DWORD *color_s =
1236 (DWORD *) (((char *) lpD3DDrawPrimStrideData->specular.lpvData) + i * lpD3DDrawPrimStrideData->specular.dwStride);
1237 handle_diffuse_and_specular(&(This->state_block), glThis->fog_table, color_d, color_s, vertex_lighted);
1238 } else {
1239 if (d3dvtVertexType & D3DFVF_SPECULAR) {
1240 DWORD *color_s =
1241 (DWORD *) (((char *) lpD3DDrawPrimStrideData->specular.lpvData) + i * lpD3DDrawPrimStrideData->specular.dwStride);
1242 handle_specular(&(This->state_block), color_s, vertex_lighted);
1243 } else if (d3dvtVertexType & D3DFVF_DIFFUSE) {
1244 DWORD *color_d =
1245 (DWORD *) (((char *) lpD3DDrawPrimStrideData->diffuse.lpvData) + i * lpD3DDrawPrimStrideData->diffuse.dwStride);
1246 handle_diffuse(&(This->state_block), color_d, vertex_lighted);
1250 for (tex_stage = 0; tex_stage < num_active_stages; tex_stage++) {
1251 int tex_index = This->state_block.texture_stage_state[tex_stage][D3DTSS_TEXCOORDINDEX - 1] & 0xFFFF000;
1252 if (tex_index >= num_tex_index) {
1253 handle_textures((D3DVALUE *) no_index, tex_stage);
1254 } else {
1255 D3DVALUE *tex_coord =
1256 (D3DVALUE *) (((char *) lpD3DDrawPrimStrideData->textureCoords[tex_index].lpvData) +
1257 i * lpD3DDrawPrimStrideData->textureCoords[tex_index].dwStride);
1258 handle_textures(tex_coord, tex_stage);
1262 if ((d3dvtVertexType & D3DFVF_POSITION_MASK) == D3DFVF_XYZ) {
1263 D3DVALUE *position =
1264 (D3DVALUE *) (((char *) lpD3DDrawPrimStrideData->position.lpvData) + i * lpD3DDrawPrimStrideData->position.dwStride);
1265 handle_xyz(position);
1266 } else if ((d3dvtVertexType & D3DFVF_POSITION_MASK) == D3DFVF_XYZRHW) {
1267 D3DVALUE *position =
1268 (D3DVALUE *) (((char *) lpD3DDrawPrimStrideData->position.lpvData) + i * lpD3DDrawPrimStrideData->position.dwStride);
1269 handle_xyzrhw(position);
1272 if (TRACE_ON(ddraw_geom)) {
1273 int tex_index;
1275 if ((d3dvtVertexType & D3DFVF_POSITION_MASK) == D3DFVF_XYZ) {
1276 D3DVALUE *position =
1277 (D3DVALUE *) (((char *) lpD3DDrawPrimStrideData->position.lpvData) + i * lpD3DDrawPrimStrideData->position.dwStride);
1278 TRACE_(ddraw_geom)(" %f %f %f", position[0], position[1], position[2]);
1279 } else if ((d3dvtVertexType & D3DFVF_POSITION_MASK) == D3DFVF_XYZRHW) {
1280 D3DVALUE *position =
1281 (D3DVALUE *) (((char *) lpD3DDrawPrimStrideData->position.lpvData) + i * lpD3DDrawPrimStrideData->position.dwStride);
1282 TRACE_(ddraw_geom)(" %f %f %f %f", position[0], position[1], position[2], position[3]);
1284 if (d3dvtVertexType & D3DFVF_NORMAL) {
1285 D3DVALUE *normal =
1286 (D3DVALUE *) (((char *) lpD3DDrawPrimStrideData->normal.lpvData) + i * lpD3DDrawPrimStrideData->normal.dwStride);
1287 TRACE_(ddraw_geom)(" / %f %f %f", normal[0], normal[1], normal[2]);
1289 if (d3dvtVertexType & D3DFVF_DIFFUSE) {
1290 DWORD *color_d =
1291 (DWORD *) (((char *) lpD3DDrawPrimStrideData->diffuse.lpvData) + i * lpD3DDrawPrimStrideData->diffuse.dwStride);
1292 TRACE_(ddraw_geom)(" / %02lx %02lx %02lx %02lx",
1293 (*color_d >> 16) & 0xFF,
1294 (*color_d >> 8) & 0xFF,
1295 (*color_d >> 0) & 0xFF,
1296 (*color_d >> 24) & 0xFF);
1298 if (d3dvtVertexType & D3DFVF_SPECULAR) {
1299 DWORD *color_s =
1300 (DWORD *) (((char *) lpD3DDrawPrimStrideData->specular.lpvData) + i * lpD3DDrawPrimStrideData->specular.dwStride);
1301 TRACE_(ddraw_geom)(" / %02lx %02lx %02lx %02lx",
1302 (*color_s >> 16) & 0xFF,
1303 (*color_s >> 8) & 0xFF,
1304 (*color_s >> 0) & 0xFF,
1305 (*color_s >> 24) & 0xFF);
1307 for (tex_index = 0; tex_index < ((d3dvtVertexType & D3DFVF_TEXCOUNT_MASK) >> D3DFVF_TEXCOUNT_SHIFT); tex_index++) {
1308 D3DVALUE *tex_coord =
1309 (D3DVALUE *) (((char *) lpD3DDrawPrimStrideData->textureCoords[tex_index].lpvData) +
1310 i * lpD3DDrawPrimStrideData->textureCoords[tex_index].dwStride);
1311 TRACE_(ddraw_geom)(" / %f %f", tex_coord[0], tex_coord[1]);
1313 TRACE_(ddraw_geom)("\n");
1316 } else {
1317 ERR(" matrix weighting not handled yet....\n");
1320 glEnd();
1322 /* Whatever the case, disable the color material stuff */
1323 glDisable(GL_COLOR_MATERIAL);
1325 LEAVE_GL();
1326 TRACE("End\n");
1328 LeaveCriticalSection(&(This->crit));
1331 HRESULT WINAPI
1332 GL_IDirect3DDeviceImpl_7_3T_DrawPrimitive(LPDIRECT3DDEVICE7 iface,
1333 D3DPRIMITIVETYPE d3dptPrimitiveType,
1334 DWORD d3dvtVertexType,
1335 LPVOID lpvVertices,
1336 DWORD dwVertexCount,
1337 DWORD dwFlags)
1339 ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice7, iface);
1340 D3DDRAWPRIMITIVESTRIDEDDATA strided;
1342 TRACE("(%p/%p)->(%08x,%08lx,%p,%08lx,%08lx)\n", This, iface, d3dptPrimitiveType, d3dvtVertexType, lpvVertices, dwVertexCount, dwFlags);
1343 if (TRACE_ON(ddraw)) {
1344 TRACE(" - flags : "); dump_DPFLAGS(dwFlags);
1347 convert_FVF_to_strided_data(d3dvtVertexType, lpvVertices, &strided, 0);
1348 draw_primitive_strided(This, d3dptPrimitiveType, d3dvtVertexType, &strided, dwVertexCount, NULL, dwVertexCount, dwFlags);
1350 return DD_OK;
1353 HRESULT WINAPI
1354 GL_IDirect3DDeviceImpl_7_3T_DrawIndexedPrimitive(LPDIRECT3DDEVICE7 iface,
1355 D3DPRIMITIVETYPE d3dptPrimitiveType,
1356 DWORD d3dvtVertexType,
1357 LPVOID lpvVertices,
1358 DWORD dwVertexCount,
1359 LPWORD dwIndices,
1360 DWORD dwIndexCount,
1361 DWORD dwFlags)
1363 ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice7, iface);
1364 D3DDRAWPRIMITIVESTRIDEDDATA strided;
1366 TRACE("(%p/%p)->(%08x,%08lx,%p,%08lx,%p,%08lx,%08lx)\n", This, iface, d3dptPrimitiveType, d3dvtVertexType, lpvVertices, dwVertexCount, dwIndices, dwIndexCount, dwFlags);
1367 if (TRACE_ON(ddraw)) {
1368 TRACE(" - flags : "); dump_DPFLAGS(dwFlags);
1371 convert_FVF_to_strided_data(d3dvtVertexType, lpvVertices, &strided, 0);
1372 draw_primitive_strided(This, d3dptPrimitiveType, d3dvtVertexType, &strided, dwVertexCount, dwIndices, dwIndexCount, dwFlags);
1374 return DD_OK;
1377 HRESULT WINAPI
1378 GL_IDirect3DDeviceImpl_7_3T_DrawPrimitiveStrided(LPDIRECT3DDEVICE7 iface,
1379 D3DPRIMITIVETYPE d3dptPrimitiveType,
1380 DWORD dwVertexType,
1381 LPD3DDRAWPRIMITIVESTRIDEDDATA lpD3DDrawPrimStrideData,
1382 DWORD dwVertexCount,
1383 DWORD dwFlags)
1385 ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice7, iface);
1387 TRACE("(%p/%p)->(%08x,%08lx,%p,%08lx,%08lx)\n", This, iface, d3dptPrimitiveType, dwVertexType, lpD3DDrawPrimStrideData, dwVertexCount, dwFlags);
1388 if (TRACE_ON(ddraw)) {
1389 TRACE(" - flags : "); dump_DPFLAGS(dwFlags);
1391 draw_primitive_strided(This, d3dptPrimitiveType, dwVertexType, lpD3DDrawPrimStrideData, dwVertexCount, NULL, dwVertexCount, dwFlags);
1393 return DD_OK;
1396 HRESULT WINAPI
1397 GL_IDirect3DDeviceImpl_7_3T_DrawIndexedPrimitiveStrided(LPDIRECT3DDEVICE7 iface,
1398 D3DPRIMITIVETYPE d3dptPrimitiveType,
1399 DWORD dwVertexType,
1400 LPD3DDRAWPRIMITIVESTRIDEDDATA lpD3DDrawPrimStrideData,
1401 DWORD dwVertexCount,
1402 LPWORD lpIndex,
1403 DWORD dwIndexCount,
1404 DWORD dwFlags)
1406 ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice7, iface);
1408 TRACE("(%p/%p)->(%08x,%08lx,%p,%08lx,%p,%08lx,%08lx)\n", This, iface, d3dptPrimitiveType, dwVertexType, lpD3DDrawPrimStrideData, dwVertexCount, lpIndex, dwIndexCount, dwFlags);
1409 if (TRACE_ON(ddraw)) {
1410 TRACE(" - flags : "); dump_DPFLAGS(dwFlags);
1413 draw_primitive_strided(This, d3dptPrimitiveType, dwVertexType, lpD3DDrawPrimStrideData, dwVertexCount, lpIndex, dwIndexCount, dwFlags);
1415 return DD_OK;
1418 HRESULT WINAPI
1419 GL_IDirect3DDeviceImpl_7_3T_DrawPrimitiveVB(LPDIRECT3DDEVICE7 iface,
1420 D3DPRIMITIVETYPE d3dptPrimitiveType,
1421 LPDIRECT3DVERTEXBUFFER7 lpD3DVertexBuf,
1422 DWORD dwStartVertex,
1423 DWORD dwNumVertices,
1424 DWORD dwFlags)
1426 ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice7, iface);
1427 IDirect3DVertexBufferImpl *vb_impl = ICOM_OBJECT(IDirect3DVertexBufferImpl, IDirect3DVertexBuffer7, lpD3DVertexBuf);
1428 D3DDRAWPRIMITIVESTRIDEDDATA strided;
1430 TRACE("(%p/%p)->(%08x,%p,%08lx,%08lx,%08lx)\n", This, iface, d3dptPrimitiveType, lpD3DVertexBuf, dwStartVertex, dwNumVertices, dwFlags);
1431 if (TRACE_ON(ddraw)) {
1432 TRACE(" - flags : "); dump_DPFLAGS(dwFlags);
1435 if (vb_impl->processed == TRUE) {
1436 IDirect3DVertexBufferGLImpl *vb_glimp = (IDirect3DVertexBufferGLImpl *) vb_impl;
1437 IDirect3DDeviceGLImpl *glThis = (IDirect3DDeviceGLImpl *) This;
1439 glThis->transform_state = GL_TRANSFORM_VERTEXBUFFER;
1440 This->set_matrices(This, VIEWMAT_CHANGED|WORLDMAT_CHANGED|PROJMAT_CHANGED,
1441 &(vb_glimp->world_mat), &(vb_glimp->view_mat), &(vb_glimp->proj_mat));
1443 convert_FVF_to_strided_data(vb_glimp->dwVertexTypeDesc, vb_glimp->vertices, &strided, dwStartVertex);
1444 draw_primitive_strided(This, d3dptPrimitiveType, vb_glimp->dwVertexTypeDesc, &strided, dwNumVertices, NULL, dwNumVertices, dwFlags);
1446 } else {
1447 convert_FVF_to_strided_data(vb_impl->desc.dwFVF, vb_impl->vertices, &strided, dwStartVertex);
1448 draw_primitive_strided(This, d3dptPrimitiveType, vb_impl->desc.dwFVF, &strided, dwNumVertices, NULL, dwNumVertices, dwFlags);
1451 return DD_OK;
1454 HRESULT WINAPI
1455 GL_IDirect3DDeviceImpl_7_3T_DrawIndexedPrimitiveVB(LPDIRECT3DDEVICE7 iface,
1456 D3DPRIMITIVETYPE d3dptPrimitiveType,
1457 LPDIRECT3DVERTEXBUFFER7 lpD3DVertexBuf,
1458 DWORD dwStartVertex,
1459 DWORD dwNumVertices,
1460 LPWORD lpwIndices,
1461 DWORD dwIndexCount,
1462 DWORD dwFlags)
1464 ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice7, iface);
1465 IDirect3DVertexBufferImpl *vb_impl = ICOM_OBJECT(IDirect3DVertexBufferImpl, IDirect3DVertexBuffer7, lpD3DVertexBuf);
1466 D3DDRAWPRIMITIVESTRIDEDDATA strided;
1468 TRACE("(%p/%p)->(%08x,%p,%08lx,%08lx,%p,%08lx,%08lx)\n", This, iface, d3dptPrimitiveType, lpD3DVertexBuf, dwStartVertex, dwNumVertices, lpwIndices, dwIndexCount, dwFlags);
1469 if (TRACE_ON(ddraw)) {
1470 TRACE(" - flags : "); dump_DPFLAGS(dwFlags);
1473 if (vb_impl->processed == TRUE) {
1474 IDirect3DVertexBufferGLImpl *vb_glimp = (IDirect3DVertexBufferGLImpl *) vb_impl;
1475 IDirect3DDeviceGLImpl *glThis = (IDirect3DDeviceGLImpl *) This;
1477 glThis->transform_state = GL_TRANSFORM_VERTEXBUFFER;
1478 This->set_matrices(This, VIEWMAT_CHANGED|WORLDMAT_CHANGED|PROJMAT_CHANGED,
1479 &(vb_glimp->world_mat), &(vb_glimp->view_mat), &(vb_glimp->proj_mat));
1481 convert_FVF_to_strided_data(vb_glimp->dwVertexTypeDesc, vb_glimp->vertices, &strided, dwStartVertex);
1482 draw_primitive_strided(This, d3dptPrimitiveType, vb_glimp->dwVertexTypeDesc, &strided, dwNumVertices, lpwIndices, dwIndexCount, dwFlags);
1484 } else {
1485 convert_FVF_to_strided_data(vb_impl->desc.dwFVF, vb_impl->vertices, &strided, dwStartVertex);
1486 draw_primitive_strided(This, d3dptPrimitiveType, vb_impl->desc.dwFVF, &strided, dwNumVertices, lpwIndices, dwIndexCount, dwFlags);
1489 return DD_OK;
1492 static GLenum
1493 convert_min_filter_to_GL(D3DTEXTUREMINFILTER dwMinState, D3DTEXTUREMIPFILTER dwMipState)
1495 GLenum gl_state;
1497 if (dwMipState == D3DTFP_NONE) {
1498 switch (dwMinState) {
1499 case D3DTFN_POINT: gl_state = GL_NEAREST; break;
1500 case D3DTFN_LINEAR: gl_state = GL_LINEAR; break;
1501 default: gl_state = GL_LINEAR; break;
1503 } else if (dwMipState == D3DTFP_POINT) {
1504 switch (dwMinState) {
1505 case D3DTFN_POINT: gl_state = GL_NEAREST_MIPMAP_NEAREST; break;
1506 case D3DTFN_LINEAR: gl_state = GL_LINEAR_MIPMAP_NEAREST; break;
1507 default: gl_state = GL_LINEAR_MIPMAP_NEAREST; break;
1509 } else {
1510 switch (dwMinState) {
1511 case D3DTFN_POINT: gl_state = GL_NEAREST_MIPMAP_LINEAR; break;
1512 case D3DTFN_LINEAR: gl_state = GL_LINEAR_MIPMAP_LINEAR; break;
1513 default: gl_state = GL_LINEAR_MIPMAP_LINEAR; break;
1516 return gl_state;
1519 static GLenum
1520 convert_mag_filter_to_GL(D3DTEXTUREMAGFILTER dwState)
1522 GLenum gl_state;
1524 switch (dwState) {
1525 case D3DTFG_POINT:
1526 gl_state = GL_NEAREST;
1527 break;
1528 case D3DTFG_LINEAR:
1529 gl_state = GL_LINEAR;
1530 break;
1531 default:
1532 gl_state = GL_LINEAR;
1533 break;
1535 return gl_state;
1538 /* We need a static function for that to handle the 'special' case of 'SELECT_ARG2' */
1539 static BOOLEAN
1540 handle_color_alpha_args(IDirect3DDeviceImpl *This, DWORD dwStage, D3DTEXTURESTAGESTATETYPE d3dTexStageStateType, DWORD dwState, D3DTEXTUREOP tex_op)
1542 BOOLEAN is_complement = FALSE;
1543 BOOLEAN is_alpha_replicate = FALSE;
1544 BOOLEAN handled = TRUE;
1545 GLenum src;
1546 BOOLEAN is_color = ((d3dTexStageStateType == D3DTSS_COLORARG1) || (d3dTexStageStateType == D3DTSS_COLORARG2));
1547 int num;
1549 if (is_color) {
1550 if (d3dTexStageStateType == D3DTSS_COLORARG1) num = 0;
1551 else if (d3dTexStageStateType == D3DTSS_COLORARG2) num = 1;
1552 else {
1553 handled = FALSE;
1554 num = 0;
1556 if (tex_op == D3DTOP_SELECTARG2) {
1557 num = 1 - num;
1559 } else {
1560 if (d3dTexStageStateType == D3DTSS_ALPHAARG1) num = 0;
1561 else if (d3dTexStageStateType == D3DTSS_ALPHAARG2) num = 1;
1562 else {
1563 handled = FALSE;
1564 num = 0;
1566 if (tex_op == D3DTOP_SELECTARG2) {
1567 num = 1 - num;
1571 if (dwState & D3DTA_COMPLEMENT) {
1572 is_complement = TRUE;
1574 if (dwState & D3DTA_ALPHAREPLICATE) {
1575 is_alpha_replicate = TRUE;
1577 dwState &= D3DTA_SELECTMASK;
1578 if ((dwStage == 0) && (dwState == D3DTA_CURRENT)) {
1579 dwState = D3DTA_DIFFUSE;
1582 switch (dwState) {
1583 case D3DTA_CURRENT: src = GL_PREVIOUS_EXT; break;
1584 case D3DTA_DIFFUSE: src = GL_PRIMARY_COLOR_EXT; break;
1585 case D3DTA_TEXTURE: src = GL_TEXTURE; break;
1586 case D3DTA_TFACTOR: {
1587 /* Get the constant value from the current rendering state */
1588 GLfloat color[4];
1589 DWORD col = This->state_block.render_state[D3DRENDERSTATE_TEXTUREFACTOR - 1];
1591 color[0] = ((col >> 16) & 0xFF) / 255.0f;
1592 color[1] = ((col >> 8) & 0xFF) / 255.0f;
1593 color[2] = ((col >> 0) & 0xFF) / 255.0f;
1594 color[3] = ((col >> 24) & 0xFF) / 255.0f;
1595 glTexEnvfv(GL_TEXTURE_ENV, GL_TEXTURE_ENV_COLOR, color);
1597 src = GL_CONSTANT_EXT;
1598 } break;
1599 default: src = GL_TEXTURE; handled = FALSE; break;
1602 if (is_color) {
1603 glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_RGB_EXT + num, src);
1604 if (is_alpha_replicate) {
1605 glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND0_RGB_EXT + num, is_complement ? GL_ONE_MINUS_SRC_ALPHA : GL_SRC_ALPHA);
1606 } else {
1607 glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND0_RGB_EXT + num, is_complement ? GL_ONE_MINUS_SRC_COLOR : GL_SRC_COLOR);
1609 } else {
1610 glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_ALPHA_EXT + num, src);
1611 glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND0_ALPHA_EXT + num, is_complement ? GL_ONE_MINUS_SRC_ALPHA : GL_SRC_ALPHA);
1614 return handled;
1617 HRESULT WINAPI
1618 GL_IDirect3DDeviceImpl_7_3T_SetTextureStageState(LPDIRECT3DDEVICE7 iface,
1619 DWORD dwStage,
1620 D3DTEXTURESTAGESTATETYPE d3dTexStageStateType,
1621 DWORD dwState)
1623 ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice7, iface);
1624 const char *type;
1625 DWORD prev_state;
1627 TRACE("(%p/%p)->(%08lx,%08x,%08lx)\n", This, iface, dwStage, d3dTexStageStateType, dwState);
1629 if (dwStage > 0) return DD_OK; /* We nothing in this case for now */
1631 switch (d3dTexStageStateType) {
1632 #define GEN_CASE(a) case a: type = #a; break
1633 GEN_CASE(D3DTSS_COLOROP);
1634 GEN_CASE(D3DTSS_COLORARG1);
1635 GEN_CASE(D3DTSS_COLORARG2);
1636 GEN_CASE(D3DTSS_ALPHAOP);
1637 GEN_CASE(D3DTSS_ALPHAARG1);
1638 GEN_CASE(D3DTSS_ALPHAARG2);
1639 GEN_CASE(D3DTSS_BUMPENVMAT00);
1640 GEN_CASE(D3DTSS_BUMPENVMAT01);
1641 GEN_CASE(D3DTSS_BUMPENVMAT10);
1642 GEN_CASE(D3DTSS_BUMPENVMAT11);
1643 GEN_CASE(D3DTSS_TEXCOORDINDEX);
1644 GEN_CASE(D3DTSS_ADDRESS);
1645 GEN_CASE(D3DTSS_ADDRESSU);
1646 GEN_CASE(D3DTSS_ADDRESSV);
1647 GEN_CASE(D3DTSS_BORDERCOLOR);
1648 GEN_CASE(D3DTSS_MAGFILTER);
1649 GEN_CASE(D3DTSS_MINFILTER);
1650 GEN_CASE(D3DTSS_MIPFILTER);
1651 GEN_CASE(D3DTSS_MIPMAPLODBIAS);
1652 GEN_CASE(D3DTSS_MAXMIPLEVEL);
1653 GEN_CASE(D3DTSS_MAXANISOTROPY);
1654 GEN_CASE(D3DTSS_BUMPENVLSCALE);
1655 GEN_CASE(D3DTSS_BUMPENVLOFFSET);
1656 GEN_CASE(D3DTSS_TEXTURETRANSFORMFLAGS);
1657 #undef GEN_CASE
1658 default: type = "UNKNOWN";
1661 /* Store the values in the state array */
1662 prev_state = This->state_block.texture_stage_state[dwStage][d3dTexStageStateType - 1];
1663 This->state_block.texture_stage_state[dwStage][d3dTexStageStateType - 1] = dwState;
1664 /* Some special cases when one state modifies more than one... */
1665 if (d3dTexStageStateType == D3DTSS_ADDRESS) {
1666 This->state_block.texture_stage_state[dwStage][D3DTSS_ADDRESSU - 1] = dwState;
1667 This->state_block.texture_stage_state[dwStage][D3DTSS_ADDRESSV - 1] = dwState;
1670 ENTER_GL();
1672 switch (d3dTexStageStateType) {
1673 case D3DTSS_MINFILTER:
1674 case D3DTSS_MIPFILTER:
1675 if (TRACE_ON(ddraw)) {
1676 if (d3dTexStageStateType == D3DTSS_MINFILTER) {
1677 switch ((D3DTEXTUREMINFILTER) dwState) {
1678 case D3DTFN_POINT: TRACE(" Stage type is : D3DTSS_MINFILTER => D3DTFN_POINT\n"); break;
1679 case D3DTFN_LINEAR: TRACE(" Stage type is : D3DTSS_MINFILTER => D3DTFN_LINEAR\n"); break;
1680 default: FIXME(" Unhandled stage type : D3DTSS_MINFILTER => %08lx\n", dwState); break;
1682 } else {
1683 switch ((D3DTEXTUREMIPFILTER) dwState) {
1684 case D3DTFP_NONE: TRACE(" Stage type is : D3DTSS_MIPFILTER => D3DTFP_NONE\n"); break;
1685 case D3DTFP_POINT: TRACE(" Stage type is : D3DTSS_MIPFILTER => D3DTFP_POINT\n"); break;
1686 case D3DTFP_LINEAR: TRACE(" Stage type is : D3DTSS_MIPFILTER => D3DTFP_LINEAR\n"); break;
1687 default: FIXME(" Unhandled stage type : D3DTSS_MIPFILTER => %08lx\n", dwState); break;
1692 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER,
1693 convert_min_filter_to_GL(This->state_block.texture_stage_state[dwStage][D3DTSS_MINFILTER - 1],
1694 This->state_block.texture_stage_state[dwStage][D3DTSS_MIPFILTER - 1]));
1695 break;
1697 case D3DTSS_MAGFILTER:
1698 if (TRACE_ON(ddraw)) {
1699 switch ((D3DTEXTUREMAGFILTER) dwState) {
1700 case D3DTFG_POINT: TRACE(" Stage type is : D3DTSS_MAGFILTER => D3DTFN_POINT\n"); break;
1701 case D3DTFG_LINEAR: TRACE(" Stage type is : D3DTSS_MAGFILTER => D3DTFN_LINEAR\n"); break;
1702 default: FIXME(" Unhandled stage type : D3DTSS_MAGFILTER => %08lx\n", dwState); break;
1705 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, convert_mag_filter_to_GL(dwState));
1706 break;
1708 case D3DTSS_ADDRESS:
1709 case D3DTSS_ADDRESSU:
1710 case D3DTSS_ADDRESSV: {
1711 GLenum arg = GL_REPEAT; /* Default value */
1712 switch ((D3DTEXTUREADDRESS) dwState) {
1713 case D3DTADDRESS_WRAP: TRACE(" Stage type is : %s => D3DTADDRESS_WRAP\n", type); arg = GL_REPEAT; break;
1714 case D3DTADDRESS_CLAMP: TRACE(" Stage type is : %s => D3DTADDRESS_CLAMP\n", type); arg = GL_CLAMP; break;
1715 case D3DTADDRESS_BORDER: TRACE(" Stage type is : %s => D3DTADDRESS_BORDER\n", type); arg = GL_CLAMP_TO_EDGE; break;
1716 #if defined(GL_VERSION_1_4)
1717 case D3DTADDRESS_MIRROR: TRACE(" Stage type is : %s => D3DTADDRESS_MIRROR\n", type); arg = GL_MIRRORED_REPEAT; break;
1718 #elif defined(GL_ARB_texture_mirrored_repeat)
1719 case D3DTADDRESS_MIRROR: TRACE(" Stage type is : %s => D3DTADDRESS_MIRROR\n", type); arg = GL_MIRRORED_REPEAT_ARB; break;
1720 #endif
1721 default: FIXME(" Unhandled stage type : %s => %08lx\n", type, dwState); break;
1723 if ((d3dTexStageStateType == D3DTSS_ADDRESS) ||
1724 (d3dTexStageStateType == D3DTSS_ADDRESSU))
1725 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, arg);
1726 if ((d3dTexStageStateType == D3DTSS_ADDRESS) ||
1727 (d3dTexStageStateType == D3DTSS_ADDRESSV))
1728 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, arg);
1729 } break;
1731 case D3DTSS_ALPHAOP:
1732 case D3DTSS_COLOROP: {
1733 int scale = 1;
1734 GLenum parm = (d3dTexStageStateType == D3DTSS_ALPHAOP) ? GL_COMBINE_ALPHA_EXT : GL_COMBINE_RGB_EXT;
1735 const char *value;
1736 int handled = 1;
1738 switch (dwState) {
1739 #define GEN_CASE(a) case a: value = #a; break
1740 GEN_CASE(D3DTOP_DISABLE);
1741 GEN_CASE(D3DTOP_SELECTARG1);
1742 GEN_CASE(D3DTOP_SELECTARG2);
1743 GEN_CASE(D3DTOP_MODULATE);
1744 GEN_CASE(D3DTOP_MODULATE2X);
1745 GEN_CASE(D3DTOP_MODULATE4X);
1746 GEN_CASE(D3DTOP_ADD);
1747 GEN_CASE(D3DTOP_ADDSIGNED);
1748 GEN_CASE(D3DTOP_ADDSIGNED2X);
1749 GEN_CASE(D3DTOP_SUBTRACT);
1750 GEN_CASE(D3DTOP_ADDSMOOTH);
1751 GEN_CASE(D3DTOP_BLENDDIFFUSEALPHA);
1752 GEN_CASE(D3DTOP_BLENDTEXTUREALPHA);
1753 GEN_CASE(D3DTOP_BLENDFACTORALPHA);
1754 GEN_CASE(D3DTOP_BLENDTEXTUREALPHAPM);
1755 GEN_CASE(D3DTOP_BLENDCURRENTALPHA);
1756 GEN_CASE(D3DTOP_PREMODULATE);
1757 GEN_CASE(D3DTOP_MODULATEALPHA_ADDCOLOR);
1758 GEN_CASE(D3DTOP_MODULATECOLOR_ADDALPHA);
1759 GEN_CASE(D3DTOP_MODULATEINVALPHA_ADDCOLOR);
1760 GEN_CASE(D3DTOP_MODULATEINVCOLOR_ADDALPHA);
1761 GEN_CASE(D3DTOP_BUMPENVMAP);
1762 GEN_CASE(D3DTOP_BUMPENVMAPLUMINANCE);
1763 GEN_CASE(D3DTOP_DOTPRODUCT3);
1764 GEN_CASE(D3DTOP_FORCE_DWORD);
1765 #undef GEN_CASE
1766 default: value = "UNKNOWN";
1769 if ((d3dTexStageStateType == D3DTSS_COLOROP) && (dwState == D3DTOP_DISABLE) && (dwStage == 0)) {
1770 glDisable(GL_TEXTURE_2D);
1771 TRACE(" disabling 2D texturing.\n");
1772 } else {
1773 /* Re-enable texturing */
1774 if ((dwStage == 0) && (This->current_texture[0] != NULL)) {
1775 glEnable(GL_TEXTURE_2D);
1776 TRACE(" enabling 2D texturing.\n");
1779 /* Re-Enable GL_TEXTURE_ENV_MODE, GL_COMBINE_EXT */
1780 if (dwState != D3DTOP_DISABLE) {
1781 glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE_EXT);
1784 /* Now set up the operand correctly */
1785 switch (dwState) {
1786 case D3DTOP_DISABLE:
1787 /* Contrary to the docs, alpha can be disabled when colorop is enabled
1788 and it works, so ignore this op */
1789 TRACE(" Note : disable ALPHAOP but COLOROP enabled!\n");
1790 break;
1792 case D3DTOP_SELECTARG1:
1793 case D3DTOP_SELECTARG2:
1794 glTexEnvi(GL_TEXTURE_ENV, parm, GL_REPLACE);
1795 break;
1797 case D3DTOP_MODULATE4X:
1798 scale = scale * 2; /* Drop through */
1799 case D3DTOP_MODULATE2X:
1800 scale = scale * 2; /* Drop through */
1801 case D3DTOP_MODULATE:
1802 glTexEnvi(GL_TEXTURE_ENV, parm, GL_MODULATE);
1803 break;
1805 case D3DTOP_ADD:
1806 glTexEnvi(GL_TEXTURE_ENV, parm, GL_ADD);
1807 break;
1809 case D3DTOP_ADDSIGNED2X:
1810 scale = scale * 2; /* Drop through */
1811 case D3DTOP_ADDSIGNED:
1812 glTexEnvi(GL_TEXTURE_ENV, parm, GL_ADD_SIGNED_EXT);
1813 break;
1815 /* For the four blending modes, use the Arg2 parameter */
1816 case D3DTOP_BLENDDIFFUSEALPHA:
1817 case D3DTOP_BLENDTEXTUREALPHA:
1818 case D3DTOP_BLENDFACTORALPHA:
1819 case D3DTOP_BLENDCURRENTALPHA: {
1820 GLenum src = GL_PRIMARY_COLOR_EXT; /* Just to prevent a compiler warning.. */
1822 switch (dwState) {
1823 case D3DTOP_BLENDDIFFUSEALPHA: src = GL_PRIMARY_COLOR_EXT;
1824 case D3DTOP_BLENDTEXTUREALPHA: src = GL_TEXTURE;
1825 case D3DTOP_BLENDFACTORALPHA: src = GL_CONSTANT_EXT;
1826 case D3DTOP_BLENDCURRENTALPHA: src = GL_PREVIOUS_EXT;
1829 glTexEnvi(GL_TEXTURE_ENV, parm, GL_INTERPOLATE_EXT);
1830 glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE2_RGB_EXT, src);
1831 glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND2_RGB_EXT, GL_SRC_ALPHA);
1832 glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE2_ALPHA_EXT, src);
1833 glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND2_ALPHA_EXT, GL_SRC_ALPHA);
1834 } break;
1836 default:
1837 handled = FALSE;
1838 break;
1842 if (((prev_state == D3DTOP_SELECTARG2) && (dwState != D3DTOP_SELECTARG2)) ||
1843 ((dwState == D3DTOP_SELECTARG2) && (prev_state != D3DTOP_SELECTARG2))) {
1844 /* Switch the arguments if needed... */
1845 if (d3dTexStageStateType == D3DTSS_COLOROP) {
1846 handle_color_alpha_args(This, dwStage, D3DTSS_COLORARG1,
1847 This->state_block.texture_stage_state[dwStage][D3DTSS_COLORARG1 - 1],
1848 dwState);
1849 handle_color_alpha_args(This, dwStage, D3DTSS_COLORARG2,
1850 This->state_block.texture_stage_state[dwStage][D3DTSS_COLORARG2 - 1],
1851 dwState);
1852 } else {
1853 handle_color_alpha_args(This, dwStage, D3DTSS_ALPHAARG1,
1854 This->state_block.texture_stage_state[dwStage][D3DTSS_ALPHAARG1 - 1],
1855 dwState);
1856 handle_color_alpha_args(This, dwStage, D3DTSS_ALPHAARG2,
1857 This->state_block.texture_stage_state[dwStage][D3DTSS_ALPHAARG2 - 1],
1858 dwState);
1862 if (handled) {
1863 if (d3dTexStageStateType == D3DTSS_ALPHAOP) {
1864 glTexEnvi(GL_TEXTURE_ENV, GL_ALPHA_SCALE, scale);
1865 } else {
1866 glTexEnvi(GL_TEXTURE_ENV, GL_RGB_SCALE_EXT, scale);
1868 TRACE(" Stage type is : %s => %s\n", type, value);
1869 } else {
1870 FIXME(" Unhandled stage type is : %s => %s\n", type, value);
1872 } break;
1874 case D3DTSS_COLORARG1:
1875 case D3DTSS_COLORARG2:
1876 case D3DTSS_ALPHAARG1:
1877 case D3DTSS_ALPHAARG2: {
1878 const char *value, *value_comp = "", *value_alpha = "";
1879 BOOLEAN handled;
1880 D3DTEXTUREOP tex_op;
1882 switch (dwState & D3DTA_SELECTMASK) {
1883 #define GEN_CASE(a) case a: value = #a; break
1884 GEN_CASE(D3DTA_DIFFUSE);
1885 GEN_CASE(D3DTA_CURRENT);
1886 GEN_CASE(D3DTA_TEXTURE);
1887 GEN_CASE(D3DTA_TFACTOR);
1888 GEN_CASE(D3DTA_SPECULAR);
1889 #undef GEN_CASE
1890 default: value = "UNKNOWN";
1892 if (dwState & D3DTA_COMPLEMENT) {
1893 value_comp = " | D3DTA_COMPLEMENT";
1895 if (dwState & D3DTA_ALPHAREPLICATE) {
1896 value_alpha = " | D3DTA_ALPHAREPLICATE";
1899 if ((d3dTexStageStateType == D3DTSS_COLORARG1) || (d3dTexStageStateType == D3DTSS_COLORARG2)) {
1900 tex_op = This->state_block.texture_stage_state[dwStage][D3DTSS_COLOROP - 1];
1901 } else {
1902 tex_op = This->state_block.texture_stage_state[dwStage][D3DTSS_ALPHAOP - 1];
1905 handled = handle_color_alpha_args(This, dwStage, d3dTexStageStateType, dwState, tex_op);
1907 if (handled) {
1908 TRACE(" Stage type : %s => %s%s%s\n", type, value, value_comp, value_alpha);
1909 } else {
1910 FIXME(" Unhandled stage type : %s => %s%s%s\n", type, value, value_comp, value_alpha);
1912 } break;
1914 case D3DTSS_MIPMAPLODBIAS: {
1915 D3DVALUE value = *((D3DVALUE *) &dwState);
1916 BOOLEAN handled = TRUE;
1918 if (value != 0.0)
1919 handled = FALSE;
1921 if (handled) {
1922 TRACE(" Stage type : D3DTSS_MIPMAPLODBIAS => %f\n", value);
1923 } else {
1924 FIXME(" Unhandled stage type : D3DTSS_MIPMAPLODBIAS => %f\n", value);
1926 } break;
1928 case D3DTSS_MAXMIPLEVEL:
1929 if (dwState == 0) {
1930 TRACE(" Stage type : D3DTSS_MAXMIPLEVEL => 0 (disabled) \n");
1931 } else {
1932 FIXME(" Unhandled stage type : D3DTSS_MAXMIPLEVEL => %ld\n", dwState);
1934 break;
1936 case D3DTSS_BORDERCOLOR: {
1937 GLfloat color[4];
1939 color[0] = ((dwState >> 16) & 0xFF) / 255.0;
1940 color[1] = ((dwState >> 8) & 0xFF) / 255.0;
1941 color[2] = ((dwState >> 0) & 0xFF) / 255.0;
1942 color[3] = ((dwState >> 24) & 0xFF) / 255.0;
1944 glTexParameterfv(GL_TEXTURE_2D, GL_TEXTURE_BORDER_COLOR, color);
1946 TRACE(" Stage type : D3DTSS_BORDERCOLOR => %02lx %02lx %02lx %02lx (RGBA)\n",
1947 ((dwState >> 16) & 0xFF),
1948 ((dwState >> 8) & 0xFF),
1949 ((dwState >> 0) & 0xFF),
1950 ((dwState >> 24) & 0xFF));
1951 } break;
1953 case D3DTSS_TEXCOORDINDEX: {
1954 BOOLEAN handled = TRUE;
1955 const char *value;
1957 switch (dwState & 0xFFFF0000) {
1958 #define GEN_CASE(a) case a: value = #a; break
1959 GEN_CASE(D3DTSS_TCI_PASSTHRU);
1960 GEN_CASE(D3DTSS_TCI_CAMERASPACENORMAL);
1961 GEN_CASE(D3DTSS_TCI_CAMERASPACEPOSITION);
1962 GEN_CASE(D3DTSS_TCI_CAMERASPACEREFLECTIONVECTOR);
1963 #undef GEN_CASE
1964 default: value = "UNKNOWN";
1966 if ((dwState & 0xFFFF0000) != D3DTSS_TCI_PASSTHRU)
1967 handled = FALSE;
1969 if (handled) {
1970 TRACE(" Stage type : D3DTSS_TEXCOORDINDEX => %ld | %s\n", dwState & 0x0000FFFF, value);
1971 } else {
1972 FIXME(" Unhandled stage type : D3DTSS_TEXCOORDINDEX => %ld | %s\n", dwState & 0x0000FFFF, value);
1974 } break;
1976 case D3DTSS_TEXTURETRANSFORMFLAGS: {
1977 const char *projected = "", *value;
1978 BOOLEAN handled = TRUE;
1979 switch (dwState & 0xFF) {
1980 #define GEN_CASE(a) case a: value = #a; break
1981 GEN_CASE(D3DTTFF_DISABLE);
1982 GEN_CASE(D3DTTFF_COUNT1);
1983 GEN_CASE(D3DTTFF_COUNT2);
1984 GEN_CASE(D3DTTFF_COUNT3);
1985 GEN_CASE(D3DTTFF_COUNT4);
1986 #undef GEN_CASE
1987 default: value = "UNKNOWN";
1989 if (dwState & D3DTTFF_PROJECTED) {
1990 projected = " | D3DTTFF_PROJECTED";
1991 handled = FALSE;
1994 if ((dwState & 0xFF) != D3DTTFF_DISABLE) {
1995 LEAVE_GL();
1996 This->matrices_updated(This, TEXMAT0_CHANGED << dwStage);
1997 ENTER_GL();
2000 if (handled == TRUE) {
2001 TRACE(" Stage type : D3DTSS_TEXTURETRANSFORMFLAGS => %s%s\n", value, projected);
2002 } else {
2003 FIXME(" Unhandled stage type : D3DTSS_TEXTURETRANSFORMFLAGS => %s%s\n", value, projected);
2005 } break;
2007 default:
2008 FIXME(" Unhandled stage type : %s => %08lx\n", type, dwState);
2009 break;
2012 LEAVE_GL();
2014 return DD_OK;
2017 HRESULT WINAPI
2018 GL_IDirect3DDeviceImpl_7_3T_SetTexture(LPDIRECT3DDEVICE7 iface,
2019 DWORD dwStage,
2020 LPDIRECTDRAWSURFACE7 lpTexture2)
2022 ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice7, iface);
2024 TRACE("(%p/%p)->(%08lx,%p)\n", This, iface, dwStage, lpTexture2);
2026 if (dwStage > 0) return DD_OK;
2028 if (This->current_texture[dwStage] != NULL) {
2029 IDirectDrawSurface7_Release(ICOM_INTERFACE(This->current_texture[dwStage], IDirectDrawSurface7));
2032 ENTER_GL();
2033 if (lpTexture2 == NULL) {
2034 This->current_texture[dwStage] = NULL;
2036 TRACE(" disabling 2D texturing.\n");
2037 glBindTexture(GL_TEXTURE_2D, 0);
2038 glDisable(GL_TEXTURE_2D);
2039 } else {
2040 IDirectDrawSurfaceImpl *tex_impl = ICOM_OBJECT(IDirectDrawSurfaceImpl, IDirectDrawSurface7, lpTexture2);
2041 GLint max_mip_level;
2043 This->current_texture[dwStage] = tex_impl;
2044 IDirectDrawSurface7_AddRef(ICOM_INTERFACE(tex_impl, IDirectDrawSurface7)); /* Not sure about this either */
2046 if (This->state_block.texture_stage_state[dwStage][D3DTSS_COLOROP - 1] != D3DTOP_DISABLE) {
2047 /* Do not re-enable texturing if it was disabled due to the COLOROP code */
2048 glEnable(GL_TEXTURE_2D);
2049 TRACE(" enabling 2D texturing.\n");
2051 gltex_upload_texture(tex_impl);
2053 if ((tex_impl->surface_desc.ddsCaps.dwCaps & DDSCAPS_MIPMAP) == 0) {
2054 max_mip_level = 0;
2055 } else {
2056 max_mip_level = tex_impl->surface_desc.u2.dwMipMapCount - 1;
2059 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER,
2060 convert_mag_filter_to_GL(This->state_block.texture_stage_state[dwStage][D3DTSS_MAGFILTER - 1]));
2061 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER,
2062 convert_min_filter_to_GL(This->state_block.texture_stage_state[dwStage][D3DTSS_MINFILTER - 1],
2063 This->state_block.texture_stage_state[dwStage][D3DTSS_MIPFILTER - 1]));
2064 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LEVEL, max_mip_level);
2066 LEAVE_GL();
2068 return DD_OK;
2071 HRESULT WINAPI
2072 GL_IDirect3DDeviceImpl_7_GetCaps(LPDIRECT3DDEVICE7 iface,
2073 LPD3DDEVICEDESC7 lpD3DHELDevDesc)
2075 ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice7, iface);
2076 TRACE("(%p/%p)->(%p)\n", This, iface, lpD3DHELDevDesc);
2078 fill_opengl_caps_7(lpD3DHELDevDesc);
2080 TRACE(" returning caps : no dump function yet.\n");
2082 return DD_OK;
2085 HRESULT WINAPI
2086 GL_IDirect3DDeviceImpl_7_SetMaterial(LPDIRECT3DDEVICE7 iface,
2087 LPD3DMATERIAL7 lpMat)
2089 ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice7, iface);
2090 TRACE("(%p/%p)->(%p)\n", This, iface, lpMat);
2092 if (TRACE_ON(ddraw)) {
2093 TRACE(" material is : \n");
2094 dump_D3DMATERIAL7(lpMat);
2097 This->current_material = *lpMat;
2099 glMaterialfv(GL_FRONT_AND_BACK,
2100 GL_DIFFUSE,
2101 (float *) &(This->current_material.u.diffuse));
2102 glMaterialfv(GL_FRONT_AND_BACK,
2103 GL_AMBIENT,
2104 (float *) &(This->current_material.u1.ambient));
2105 glMaterialfv(GL_FRONT_AND_BACK,
2106 GL_SPECULAR,
2107 (float *) &(This->current_material.u2.specular));
2108 glMaterialfv(GL_FRONT_AND_BACK,
2109 GL_EMISSION,
2110 (float *) &(This->current_material.u3.emissive));
2111 glMaterialf(GL_FRONT_AND_BACK,
2112 GL_SHININESS,
2113 This->current_material.u4.power); /* Not sure about this... */
2115 return DD_OK;
2119 HRESULT WINAPI
2120 GL_IDirect3DDeviceImpl_7_SetLight(LPDIRECT3DDEVICE7 iface,
2121 DWORD dwLightIndex,
2122 LPD3DLIGHT7 lpLight)
2124 ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice7, iface);
2125 IDirect3DDeviceGLImpl *glThis = (IDirect3DDeviceGLImpl *) This;
2126 TRACE("(%p/%p)->(%08lx,%p)\n", This, iface, dwLightIndex, lpLight);
2128 if (TRACE_ON(ddraw)) {
2129 TRACE(" setting light : \n");
2130 dump_D3DLIGHT7(lpLight);
2133 if (dwLightIndex >= MAX_LIGHTS) return DDERR_INVALIDPARAMS;
2134 This->set_lights |= 0x00000001 << dwLightIndex;
2135 This->light_parameters[dwLightIndex] = *lpLight;
2137 /* Some checks to print out nice warnings :-) */
2138 switch (lpLight->dltType) {
2139 case D3DLIGHT_DIRECTIONAL:
2140 case D3DLIGHT_POINT:
2141 /* These are handled properly... */
2142 break;
2144 case D3DLIGHT_SPOT:
2145 if ((lpLight->dvTheta != 0.0) ||
2146 (lpLight->dvTheta != lpLight->dvPhi)) {
2147 ERR("dvTheta not fully supported yet !\n");
2149 break;
2151 default:
2152 ERR("Light type not handled yet : %08x !\n", lpLight->dltType);
2155 /* This will force the Light setting on next drawing of primitives */
2156 glThis->transform_state = GL_TRANSFORM_NONE;
2158 return DD_OK;
2161 HRESULT WINAPI
2162 GL_IDirect3DDeviceImpl_7_LightEnable(LPDIRECT3DDEVICE7 iface,
2163 DWORD dwLightIndex,
2164 BOOL bEnable)
2166 ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice7, iface);
2167 TRACE("(%p/%p)->(%08lx,%d)\n", This, iface, dwLightIndex, bEnable);
2169 if (dwLightIndex >= MAX_LIGHTS) return DDERR_INVALIDPARAMS;
2171 if (bEnable) {
2172 if (((0x00000001 << dwLightIndex) & This->set_lights) == 0) {
2173 /* Set the default parameters.. */
2174 TRACE(" setting default light parameters...\n");
2175 GL_IDirect3DDeviceImpl_7_SetLight(iface, dwLightIndex, &(This->light_parameters[dwLightIndex]));
2177 glEnable(GL_LIGHT0 + dwLightIndex);
2178 if ((This->active_lights & (0x00000001 << dwLightIndex)) == 0) {
2179 /* This light gets active... Need to update its parameters to GL before the next drawing */
2180 IDirect3DDeviceGLImpl *glThis = (IDirect3DDeviceGLImpl *) This;
2182 This->active_lights |= 0x00000001 << dwLightIndex;
2183 glThis->transform_state = GL_TRANSFORM_NONE;
2185 } else {
2186 glDisable(GL_LIGHT0 + dwLightIndex);
2187 This->active_lights &= ~(0x00000001 << dwLightIndex);
2190 return DD_OK;
2193 HRESULT WINAPI
2194 GL_IDirect3DDeviceImpl_7_SetClipPlane(LPDIRECT3DDEVICE7 iface, DWORD dwIndex, CONST D3DVALUE* pPlaneEquation)
2196 ICOM_THIS(IDirect3DDeviceImpl,iface);
2197 IDirect3DDeviceGLImpl* glThis = (IDirect3DDeviceGLImpl*) This;
2199 TRACE("(%p)->(%ld,%p)\n", This, dwIndex, pPlaneEquation);
2201 if (dwIndex >= This->max_clipping_planes) {
2202 return DDERR_INVALIDPARAMS;
2205 TRACE(" clip plane %ld : %f %f %f %f\n", dwIndex, pPlaneEquation[0], pPlaneEquation[1], pPlaneEquation[2], pPlaneEquation[3] );
2207 memcpy(This->clipping_planes[dwIndex].plane, pPlaneEquation, sizeof(D3DVALUE[4]));
2209 /* This is to force the reset of the transformation matrices on the next drawing.
2210 * This is needed to use the correct matrices for the various clipping planes.
2212 glThis->transform_state = GL_TRANSFORM_NONE;
2214 return D3D_OK;
2217 HRESULT WINAPI
2218 GL_IDirect3DDeviceImpl_7_SetViewport(LPDIRECT3DDEVICE7 iface,
2219 LPD3DVIEWPORT7 lpData)
2221 ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice7, iface);
2222 TRACE("(%p/%p)->(%p)\n", This, iface, lpData);
2224 if (TRACE_ON(ddraw)) {
2225 TRACE(" viewport is : \n");
2226 TRACE(" - dwX = %ld dwY = %ld\n",
2227 lpData->dwX, lpData->dwY);
2228 TRACE(" - dwWidth = %ld dwHeight = %ld\n",
2229 lpData->dwWidth, lpData->dwHeight);
2230 TRACE(" - dvMinZ = %f dvMaxZ = %f\n",
2231 lpData->dvMinZ, lpData->dvMaxZ);
2233 This->active_viewport = *lpData;
2235 ENTER_GL();
2237 /* Set the viewport */
2238 glDepthRange(lpData->dvMinZ, lpData->dvMaxZ);
2239 glViewport(lpData->dwX,
2240 This->surface->surface_desc.dwHeight - (lpData->dwHeight + lpData->dwY),
2241 lpData->dwWidth, lpData->dwHeight);
2243 LEAVE_GL();
2245 return DD_OK;
2248 #if !defined(__STRICT_ANSI__) && defined(__GNUC__)
2249 # define XCAST(fun) (typeof(VTABLE_IDirect3DDevice7.fun))
2250 #else
2251 # define XCAST(fun) (void*)
2252 #endif
2254 ICOM_VTABLE(IDirect3DDevice7) VTABLE_IDirect3DDevice7 =
2256 ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
2257 XCAST(QueryInterface) Main_IDirect3DDeviceImpl_7_3T_2T_1T_QueryInterface,
2258 XCAST(AddRef) Main_IDirect3DDeviceImpl_7_3T_2T_1T_AddRef,
2259 XCAST(Release) GL_IDirect3DDeviceImpl_7_3T_2T_1T_Release,
2260 XCAST(GetCaps) GL_IDirect3DDeviceImpl_7_GetCaps,
2261 XCAST(EnumTextureFormats) GL_IDirect3DDeviceImpl_7_3T_EnumTextureFormats,
2262 XCAST(BeginScene) Main_IDirect3DDeviceImpl_7_3T_2T_1T_BeginScene,
2263 XCAST(EndScene) Main_IDirect3DDeviceImpl_7_3T_2T_1T_EndScene,
2264 XCAST(GetDirect3D) Main_IDirect3DDeviceImpl_7_3T_2T_1T_GetDirect3D,
2265 XCAST(SetRenderTarget) Main_IDirect3DDeviceImpl_7_3T_2T_SetRenderTarget,
2266 XCAST(GetRenderTarget) Main_IDirect3DDeviceImpl_7_3T_2T_GetRenderTarget,
2267 XCAST(Clear) Main_IDirect3DDeviceImpl_7_Clear,
2268 XCAST(SetTransform) Main_IDirect3DDeviceImpl_7_3T_2T_SetTransform,
2269 XCAST(GetTransform) Main_IDirect3DDeviceImpl_7_3T_2T_GetTransform,
2270 XCAST(SetViewport) GL_IDirect3DDeviceImpl_7_SetViewport,
2271 XCAST(MultiplyTransform) Main_IDirect3DDeviceImpl_7_3T_2T_MultiplyTransform,
2272 XCAST(GetViewport) Main_IDirect3DDeviceImpl_7_GetViewport,
2273 XCAST(SetMaterial) GL_IDirect3DDeviceImpl_7_SetMaterial,
2274 XCAST(GetMaterial) Main_IDirect3DDeviceImpl_7_GetMaterial,
2275 XCAST(SetLight) GL_IDirect3DDeviceImpl_7_SetLight,
2276 XCAST(GetLight) Main_IDirect3DDeviceImpl_7_GetLight,
2277 XCAST(SetRenderState) GL_IDirect3DDeviceImpl_7_3T_2T_SetRenderState,
2278 XCAST(GetRenderState) GL_IDirect3DDeviceImpl_7_3T_2T_GetRenderState,
2279 XCAST(BeginStateBlock) Main_IDirect3DDeviceImpl_7_BeginStateBlock,
2280 XCAST(EndStateBlock) Main_IDirect3DDeviceImpl_7_EndStateBlock,
2281 XCAST(PreLoad) Main_IDirect3DDeviceImpl_7_PreLoad,
2282 XCAST(DrawPrimitive) GL_IDirect3DDeviceImpl_7_3T_DrawPrimitive,
2283 XCAST(DrawIndexedPrimitive) GL_IDirect3DDeviceImpl_7_3T_DrawIndexedPrimitive,
2284 XCAST(SetClipStatus) Main_IDirect3DDeviceImpl_7_3T_2T_SetClipStatus,
2285 XCAST(GetClipStatus) Main_IDirect3DDeviceImpl_7_3T_2T_GetClipStatus,
2286 XCAST(DrawPrimitiveStrided) GL_IDirect3DDeviceImpl_7_3T_DrawPrimitiveStrided,
2287 XCAST(DrawIndexedPrimitiveStrided) GL_IDirect3DDeviceImpl_7_3T_DrawIndexedPrimitiveStrided,
2288 XCAST(DrawPrimitiveVB) GL_IDirect3DDeviceImpl_7_3T_DrawPrimitiveVB,
2289 XCAST(DrawIndexedPrimitiveVB) GL_IDirect3DDeviceImpl_7_3T_DrawIndexedPrimitiveVB,
2290 XCAST(ComputeSphereVisibility) Main_IDirect3DDeviceImpl_7_3T_ComputeSphereVisibility,
2291 XCAST(GetTexture) Main_IDirect3DDeviceImpl_7_3T_GetTexture,
2292 XCAST(SetTexture) GL_IDirect3DDeviceImpl_7_3T_SetTexture,
2293 XCAST(GetTextureStageState) Main_IDirect3DDeviceImpl_7_3T_GetTextureStageState,
2294 XCAST(SetTextureStageState) GL_IDirect3DDeviceImpl_7_3T_SetTextureStageState,
2295 XCAST(ValidateDevice) Main_IDirect3DDeviceImpl_7_3T_ValidateDevice,
2296 XCAST(ApplyStateBlock) Main_IDirect3DDeviceImpl_7_ApplyStateBlock,
2297 XCAST(CaptureStateBlock) Main_IDirect3DDeviceImpl_7_CaptureStateBlock,
2298 XCAST(DeleteStateBlock) Main_IDirect3DDeviceImpl_7_DeleteStateBlock,
2299 XCAST(CreateStateBlock) Main_IDirect3DDeviceImpl_7_CreateStateBlock,
2300 XCAST(Load) Main_IDirect3DDeviceImpl_7_Load,
2301 XCAST(LightEnable) GL_IDirect3DDeviceImpl_7_LightEnable,
2302 XCAST(GetLightEnable) Main_IDirect3DDeviceImpl_7_GetLightEnable,
2303 XCAST(SetClipPlane) GL_IDirect3DDeviceImpl_7_SetClipPlane,
2304 XCAST(GetClipPlane) Main_IDirect3DDeviceImpl_7_GetClipPlane,
2305 XCAST(GetInfo) Main_IDirect3DDeviceImpl_7_GetInfo,
2308 #if !defined(__STRICT_ANSI__) && defined(__GNUC__)
2309 #undef XCAST
2310 #endif
2313 #if !defined(__STRICT_ANSI__) && defined(__GNUC__)
2314 # define XCAST(fun) (typeof(VTABLE_IDirect3DDevice3.fun))
2315 #else
2316 # define XCAST(fun) (void*)
2317 #endif
2319 ICOM_VTABLE(IDirect3DDevice3) VTABLE_IDirect3DDevice3 =
2321 ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
2322 XCAST(QueryInterface) Thunk_IDirect3DDeviceImpl_3_QueryInterface,
2323 XCAST(AddRef) Thunk_IDirect3DDeviceImpl_3_AddRef,
2324 XCAST(Release) Thunk_IDirect3DDeviceImpl_3_Release,
2325 XCAST(GetCaps) GL_IDirect3DDeviceImpl_3_2T_1T_GetCaps,
2326 XCAST(GetStats) Main_IDirect3DDeviceImpl_3_2T_1T_GetStats,
2327 XCAST(AddViewport) Main_IDirect3DDeviceImpl_3_2T_1T_AddViewport,
2328 XCAST(DeleteViewport) Main_IDirect3DDeviceImpl_3_2T_1T_DeleteViewport,
2329 XCAST(NextViewport) Main_IDirect3DDeviceImpl_3_2T_1T_NextViewport,
2330 XCAST(EnumTextureFormats) Thunk_IDirect3DDeviceImpl_3_EnumTextureFormats,
2331 XCAST(BeginScene) Thunk_IDirect3DDeviceImpl_3_BeginScene,
2332 XCAST(EndScene) Thunk_IDirect3DDeviceImpl_3_EndScene,
2333 XCAST(GetDirect3D) Thunk_IDirect3DDeviceImpl_3_GetDirect3D,
2334 XCAST(SetCurrentViewport) Main_IDirect3DDeviceImpl_3_2T_SetCurrentViewport,
2335 XCAST(GetCurrentViewport) Main_IDirect3DDeviceImpl_3_2T_GetCurrentViewport,
2336 XCAST(SetRenderTarget) Thunk_IDirect3DDeviceImpl_3_SetRenderTarget,
2337 XCAST(GetRenderTarget) Thunk_IDirect3DDeviceImpl_3_GetRenderTarget,
2338 XCAST(Begin) Main_IDirect3DDeviceImpl_3_Begin,
2339 XCAST(BeginIndexed) Main_IDirect3DDeviceImpl_3_BeginIndexed,
2340 XCAST(Vertex) Main_IDirect3DDeviceImpl_3_2T_Vertex,
2341 XCAST(Index) Main_IDirect3DDeviceImpl_3_2T_Index,
2342 XCAST(End) Main_IDirect3DDeviceImpl_3_2T_End,
2343 XCAST(GetRenderState) Thunk_IDirect3DDeviceImpl_3_GetRenderState,
2344 XCAST(SetRenderState) Thunk_IDirect3DDeviceImpl_3_SetRenderState,
2345 XCAST(GetLightState) Main_IDirect3DDeviceImpl_3_2T_GetLightState,
2346 XCAST(SetLightState) GL_IDirect3DDeviceImpl_3_2T_SetLightState,
2347 XCAST(SetTransform) Thunk_IDirect3DDeviceImpl_3_SetTransform,
2348 XCAST(GetTransform) Thunk_IDirect3DDeviceImpl_3_GetTransform,
2349 XCAST(MultiplyTransform) Thunk_IDirect3DDeviceImpl_3_MultiplyTransform,
2350 XCAST(DrawPrimitive) Thunk_IDirect3DDeviceImpl_3_DrawPrimitive,
2351 XCAST(DrawIndexedPrimitive) Thunk_IDirect3DDeviceImpl_3_DrawIndexedPrimitive,
2352 XCAST(SetClipStatus) Thunk_IDirect3DDeviceImpl_3_SetClipStatus,
2353 XCAST(GetClipStatus) Thunk_IDirect3DDeviceImpl_3_GetClipStatus,
2354 XCAST(DrawPrimitiveStrided) Thunk_IDirect3DDeviceImpl_3_DrawPrimitiveStrided,
2355 XCAST(DrawIndexedPrimitiveStrided) Thunk_IDirect3DDeviceImpl_3_DrawIndexedPrimitiveStrided,
2356 XCAST(DrawPrimitiveVB) Thunk_IDirect3DDeviceImpl_3_DrawPrimitiveVB,
2357 XCAST(DrawIndexedPrimitiveVB) Thunk_IDirect3DDeviceImpl_3_DrawIndexedPrimitiveVB,
2358 XCAST(ComputeSphereVisibility) Thunk_IDirect3DDeviceImpl_3_ComputeSphereVisibility,
2359 XCAST(GetTexture) Thunk_IDirect3DDeviceImpl_3_GetTexture,
2360 XCAST(SetTexture) Thunk_IDirect3DDeviceImpl_3_SetTexture,
2361 XCAST(GetTextureStageState) Thunk_IDirect3DDeviceImpl_3_GetTextureStageState,
2362 XCAST(SetTextureStageState) Thunk_IDirect3DDeviceImpl_3_SetTextureStageState,
2363 XCAST(ValidateDevice) Thunk_IDirect3DDeviceImpl_3_ValidateDevice,
2366 #if !defined(__STRICT_ANSI__) && defined(__GNUC__)
2367 #undef XCAST
2368 #endif
2371 #if !defined(__STRICT_ANSI__) && defined(__GNUC__)
2372 # define XCAST(fun) (typeof(VTABLE_IDirect3DDevice2.fun))
2373 #else
2374 # define XCAST(fun) (void*)
2375 #endif
2377 ICOM_VTABLE(IDirect3DDevice2) VTABLE_IDirect3DDevice2 =
2379 ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
2380 XCAST(QueryInterface) Thunk_IDirect3DDeviceImpl_2_QueryInterface,
2381 XCAST(AddRef) Thunk_IDirect3DDeviceImpl_2_AddRef,
2382 XCAST(Release) Thunk_IDirect3DDeviceImpl_2_Release,
2383 XCAST(GetCaps) Thunk_IDirect3DDeviceImpl_2_GetCaps,
2384 XCAST(SwapTextureHandles) Main_IDirect3DDeviceImpl_2_1T_SwapTextureHandles,
2385 XCAST(GetStats) Thunk_IDirect3DDeviceImpl_2_GetStats,
2386 XCAST(AddViewport) Thunk_IDirect3DDeviceImpl_2_AddViewport,
2387 XCAST(DeleteViewport) Thunk_IDirect3DDeviceImpl_2_DeleteViewport,
2388 XCAST(NextViewport) Thunk_IDirect3DDeviceImpl_2_NextViewport,
2389 XCAST(EnumTextureFormats) GL_IDirect3DDeviceImpl_2_1T_EnumTextureFormats,
2390 XCAST(BeginScene) Thunk_IDirect3DDeviceImpl_2_BeginScene,
2391 XCAST(EndScene) Thunk_IDirect3DDeviceImpl_2_EndScene,
2392 XCAST(GetDirect3D) Thunk_IDirect3DDeviceImpl_2_GetDirect3D,
2393 XCAST(SetCurrentViewport) Thunk_IDirect3DDeviceImpl_2_SetCurrentViewport,
2394 XCAST(GetCurrentViewport) Thunk_IDirect3DDeviceImpl_2_GetCurrentViewport,
2395 XCAST(SetRenderTarget) Thunk_IDirect3DDeviceImpl_2_SetRenderTarget,
2396 XCAST(GetRenderTarget) Thunk_IDirect3DDeviceImpl_2_GetRenderTarget,
2397 XCAST(Begin) Main_IDirect3DDeviceImpl_2_Begin,
2398 XCAST(BeginIndexed) Main_IDirect3DDeviceImpl_2_BeginIndexed,
2399 XCAST(Vertex) Thunk_IDirect3DDeviceImpl_2_Vertex,
2400 XCAST(Index) Thunk_IDirect3DDeviceImpl_2_Index,
2401 XCAST(End) Thunk_IDirect3DDeviceImpl_2_End,
2402 XCAST(GetRenderState) Thunk_IDirect3DDeviceImpl_2_GetRenderState,
2403 XCAST(SetRenderState) Thunk_IDirect3DDeviceImpl_2_SetRenderState,
2404 XCAST(GetLightState) Thunk_IDirect3DDeviceImpl_2_GetLightState,
2405 XCAST(SetLightState) Thunk_IDirect3DDeviceImpl_2_SetLightState,
2406 XCAST(SetTransform) Thunk_IDirect3DDeviceImpl_2_SetTransform,
2407 XCAST(GetTransform) Thunk_IDirect3DDeviceImpl_2_GetTransform,
2408 XCAST(MultiplyTransform) Thunk_IDirect3DDeviceImpl_2_MultiplyTransform,
2409 XCAST(DrawPrimitive) GL_IDirect3DDeviceImpl_2_DrawPrimitive,
2410 XCAST(DrawIndexedPrimitive) GL_IDirect3DDeviceImpl_2_DrawIndexedPrimitive,
2411 XCAST(SetClipStatus) Thunk_IDirect3DDeviceImpl_2_SetClipStatus,
2412 XCAST(GetClipStatus) Thunk_IDirect3DDeviceImpl_2_GetClipStatus,
2415 #if !defined(__STRICT_ANSI__) && defined(__GNUC__)
2416 #undef XCAST
2417 #endif
2420 #if !defined(__STRICT_ANSI__) && defined(__GNUC__)
2421 # define XCAST(fun) (typeof(VTABLE_IDirect3DDevice.fun))
2422 #else
2423 # define XCAST(fun) (void*)
2424 #endif
2426 ICOM_VTABLE(IDirect3DDevice) VTABLE_IDirect3DDevice =
2428 ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
2429 XCAST(QueryInterface) Thunk_IDirect3DDeviceImpl_1_QueryInterface,
2430 XCAST(AddRef) Thunk_IDirect3DDeviceImpl_1_AddRef,
2431 XCAST(Release) Thunk_IDirect3DDeviceImpl_1_Release,
2432 XCAST(Initialize) Main_IDirect3DDeviceImpl_1_Initialize,
2433 XCAST(GetCaps) Thunk_IDirect3DDeviceImpl_1_GetCaps,
2434 XCAST(SwapTextureHandles) Thunk_IDirect3DDeviceImpl_1_SwapTextureHandles,
2435 XCAST(CreateExecuteBuffer) GL_IDirect3DDeviceImpl_1_CreateExecuteBuffer,
2436 XCAST(GetStats) Thunk_IDirect3DDeviceImpl_1_GetStats,
2437 XCAST(Execute) Main_IDirect3DDeviceImpl_1_Execute,
2438 XCAST(AddViewport) Thunk_IDirect3DDeviceImpl_1_AddViewport,
2439 XCAST(DeleteViewport) Thunk_IDirect3DDeviceImpl_1_DeleteViewport,
2440 XCAST(NextViewport) Thunk_IDirect3DDeviceImpl_1_NextViewport,
2441 XCAST(Pick) Main_IDirect3DDeviceImpl_1_Pick,
2442 XCAST(GetPickRecords) Main_IDirect3DDeviceImpl_1_GetPickRecords,
2443 XCAST(EnumTextureFormats) Thunk_IDirect3DDeviceImpl_1_EnumTextureFormats,
2444 XCAST(CreateMatrix) Main_IDirect3DDeviceImpl_1_CreateMatrix,
2445 XCAST(SetMatrix) Main_IDirect3DDeviceImpl_1_SetMatrix,
2446 XCAST(GetMatrix) Main_IDirect3DDeviceImpl_1_GetMatrix,
2447 XCAST(DeleteMatrix) Main_IDirect3DDeviceImpl_1_DeleteMatrix,
2448 XCAST(BeginScene) Thunk_IDirect3DDeviceImpl_1_BeginScene,
2449 XCAST(EndScene) Thunk_IDirect3DDeviceImpl_1_EndScene,
2450 XCAST(GetDirect3D) Thunk_IDirect3DDeviceImpl_1_GetDirect3D,
2453 #if !defined(__STRICT_ANSI__) && defined(__GNUC__)
2454 #undef XCAST
2455 #endif
2457 static HRESULT d3ddevice_clear(IDirect3DDeviceImpl *This,
2458 DWORD dwCount,
2459 LPD3DRECT lpRects,
2460 DWORD dwFlags,
2461 DWORD dwColor,
2462 D3DVALUE dvZ,
2463 DWORD dwStencil)
2465 IDirect3DDeviceGLImpl *glThis = (IDirect3DDeviceGLImpl *) This;
2466 GLboolean ztest;
2467 GLfloat old_z_clear_value;
2468 GLbitfield bitfield = 0;
2469 GLint old_stencil_clear_value;
2470 GLfloat old_color_clear_value[4];
2471 D3DRECT rect;
2472 int i;
2474 TRACE("(%p)->(%08lx,%p,%08lx,%08lx,%f,%08lx)\n", This, dwCount, lpRects, dwFlags, dwColor, dvZ, dwStencil);
2475 if (TRACE_ON(ddraw)) {
2476 if (dwCount > 0) {
2477 int i;
2478 TRACE(" rectangles : \n");
2479 for (i = 0; i < dwCount; i++) {
2480 TRACE(" - %ld x %ld %ld x %ld\n", lpRects[i].u1.x1, lpRects[i].u2.y1, lpRects[i].u3.x2, lpRects[i].u4.y2);
2485 if (dwCount == 0) {
2486 /* Not sure if this is really needed... */
2487 dwCount = 1;
2488 rect.u1.x1 = 0;
2489 rect.u2.y1 = 0;
2490 rect.u3.x2 = This->surface->surface_desc.dwWidth;
2491 rect.u4.y2 = This->surface->surface_desc.dwHeight;
2492 lpRects = &rect;
2495 /* Clears the screen */
2496 ENTER_GL();
2498 if (glThis->state == SURFACE_MEMORY_DIRTY) {
2499 /* TODO: optimize here the case where Clear changes all the screen... */
2500 This->flush_to_framebuffer(This, NULL, glThis->lock_surf);
2502 glThis->state = SURFACE_GL;
2504 if (dwFlags & D3DCLEAR_ZBUFFER) {
2505 bitfield |= GL_DEPTH_BUFFER_BIT;
2506 glGetBooleanv(GL_DEPTH_WRITEMASK, &ztest);
2507 glDepthMask(GL_TRUE); /* Enables Z writing to be sure to delete also the Z buffer */
2508 glGetFloatv(GL_DEPTH_CLEAR_VALUE, &old_z_clear_value);
2509 glClearDepth(dvZ);
2510 TRACE(" depth value : %f\n", dvZ);
2512 if (dwFlags & D3DCLEAR_STENCIL) {
2513 bitfield |= GL_STENCIL_BUFFER_BIT;
2514 glGetIntegerv(GL_STENCIL_CLEAR_VALUE, &old_stencil_clear_value);
2515 glClearStencil(dwStencil);
2516 TRACE(" stencil value : %ld\n", dwStencil);
2518 if (dwFlags & D3DCLEAR_TARGET) {
2519 bitfield |= GL_COLOR_BUFFER_BIT;
2520 glGetFloatv(GL_COLOR_CLEAR_VALUE, old_color_clear_value);
2521 glClearColor(((dwColor >> 16) & 0xFF) / 255.0,
2522 ((dwColor >> 8) & 0xFF) / 255.0,
2523 ((dwColor >> 0) & 0xFF) / 255.0,
2524 ((dwColor >> 24) & 0xFF) / 255.0);
2525 TRACE(" color value (ARGB) : %08lx\n", dwColor);
2528 glEnable(GL_SCISSOR_TEST);
2529 for (i = 0; i < dwCount; i++) {
2530 glScissor(lpRects[i].u1.x1, This->surface->surface_desc.dwHeight - lpRects[i].u4.y2,
2531 lpRects[i].u3.x2 - lpRects[i].u1.x1, lpRects[i].u4.y2 - lpRects[i].u2.y1);
2532 glClear(bitfield);
2534 glDisable(GL_SCISSOR_TEST);
2536 if (dwFlags & D3DCLEAR_ZBUFFER) {
2537 glDepthMask(ztest);
2538 glClearDepth(old_z_clear_value);
2540 if (dwFlags & D3DCLEAR_STENCIL) {
2541 bitfield |= GL_STENCIL_BUFFER_BIT;
2542 glClearStencil(old_stencil_clear_value);
2544 if (dwFlags & D3DCLEAR_TARGET) {
2545 bitfield |= GL_COLOR_BUFFER_BIT;
2546 glClearColor(old_color_clear_value[0],
2547 old_color_clear_value[1],
2548 old_color_clear_value[2],
2549 old_color_clear_value[3]);
2552 LEAVE_GL();
2554 return DD_OK;
2557 HRESULT
2558 d3ddevice_blt(IDirectDrawSurfaceImpl *This, LPRECT rdst,
2559 LPDIRECTDRAWSURFACE7 src, LPRECT rsrc,
2560 DWORD dwFlags, LPDDBLTFX lpbltfx)
2562 if (dwFlags & DDBLT_COLORFILL) {
2563 /* This is easy to handle for the D3D Device... */
2564 DWORD color = lpbltfx->u5.dwFillColor;
2565 D3DRECT rect;
2567 TRACE(" executing D3D Device override.\n");
2569 if (rdst) {
2570 rect.u1.x1 = rdst->left;
2571 rect.u2.y1 = rdst->top;
2572 rect.u3.x2 = rdst->right;
2573 rect.u4.y2 = rdst->bottom;
2575 d3ddevice_clear(This->d3ddevice, rdst != NULL ? 1 : 0, &rect, D3DCLEAR_TARGET, color, 0.0, 0x00000000);
2576 return DD_OK;
2578 return DDERR_INVALIDPARAMS;
2581 HRESULT
2582 d3ddevice_bltfast(IDirectDrawSurfaceImpl *This, DWORD dstx,
2583 DWORD dsty, LPDIRECTDRAWSURFACE7 src,
2584 LPRECT rsrc, DWORD trans)
2586 return DDERR_INVALIDPARAMS;
2589 void
2590 d3ddevice_set_ortho(IDirect3DDeviceImpl *This)
2592 GLfloat height, width;
2593 GLfloat trans_mat[16];
2595 width = This->surface->surface_desc.dwWidth;
2596 height = This->surface->surface_desc.dwHeight;
2598 /* The X axis is straighforward.. For the Y axis, we need to convert 'D3D' screen coordinates
2599 to OpenGL screen coordinates (ie the upper left corner is not the same).
2600 For Z, the mystery is what should it be mapped to ? Ie should the resulting range be between
2601 -1.0 and 1.0 (as the X and Y coordinates) or between 0.0 and 1.0 ? */
2602 trans_mat[ 0] = 2.0 / width; trans_mat[ 4] = 0.0; trans_mat[ 8] = 0.0; trans_mat[12] = -1.0;
2603 trans_mat[ 1] = 0.0; trans_mat[ 5] = -2.0 / height; trans_mat[ 9] = 0.0; trans_mat[13] = 1.0;
2604 trans_mat[ 2] = 0.0; trans_mat[ 6] = 0.0; trans_mat[10] = 1.0; trans_mat[14] = -1.0;
2605 trans_mat[ 3] = 0.0; trans_mat[ 7] = 0.0; trans_mat[11] = 0.0; trans_mat[15] = 1.0;
2607 glMatrixMode(GL_MODELVIEW);
2608 glLoadIdentity();
2609 /* See the OpenGL Red Book for an explanation of the following translation (in the OpenGL
2610 Correctness Tips section).
2612 Basically, from what I understood, if the game does not filter the font texture,
2613 as the 'real' pixel will lie at the middle of the two texels, OpenGL may choose the wrong
2614 one and we will have strange artifacts (as the rounding and stuff may give different results
2615 for different pixels, ie sometimes take the left pixel, sometimes the right).
2617 glTranslatef(0.375, 0.375, 0);
2618 glMatrixMode(GL_PROJECTION);
2619 glLoadMatrixf(trans_mat);
2622 void
2623 d3ddevice_set_matrices(IDirect3DDeviceImpl *This, DWORD matrices,
2624 D3DMATRIX *world_mat, D3DMATRIX *view_mat, D3DMATRIX *proj_mat)
2626 if ((matrices & (VIEWMAT_CHANGED|WORLDMAT_CHANGED)) != 0) {
2627 glMatrixMode(GL_MODELVIEW);
2628 glLoadMatrixf((float *) view_mat);
2630 /* Now also re-loads all the Lights and Clipping Planes using the new matrices */
2631 if (This->state_block.render_state[D3DRENDERSTATE_CLIPPING - 1] != FALSE) {
2632 GLint i;
2633 DWORD runner;
2634 for (i = 0, runner = 0x00000001; i < This->max_clipping_planes; i++, runner <<= 1) {
2635 if (runner & This->state_block.render_state[D3DRENDERSTATE_CLIPPLANEENABLE - 1]) {
2636 GLdouble plane[4];
2638 plane[0] = This->clipping_planes[i].plane[0];
2639 plane[1] = This->clipping_planes[i].plane[1];
2640 plane[2] = This->clipping_planes[i].plane[2];
2641 plane[3] = This->clipping_planes[i].plane[3];
2643 glClipPlane( GL_CLIP_PLANE0 + i, (const GLdouble*) (&plane) );
2647 if (This->state_block.render_state[D3DRENDERSTATE_LIGHTING - 1] != FALSE) {
2648 GLint i;
2649 DWORD runner;
2651 for (i = 0, runner = 0x00000001; i < MAX_LIGHTS; i++, runner <<= 1) {
2652 if (runner & This->active_lights) {
2653 switch (This->light_parameters[i].dltType) {
2654 case D3DLIGHT_DIRECTIONAL: {
2655 float direction[4];
2656 float cut_off = 180.0;
2658 glLightfv(GL_LIGHT0 + i, GL_AMBIENT, (float *) &(This->light_parameters[i].dcvAmbient));
2659 glLightfv(GL_LIGHT0 + i, GL_DIFFUSE, (float *) &(This->light_parameters[i].dcvDiffuse));
2660 glLightfv(GL_LIGHT0 + i, GL_SPECULAR, (float *) &(This->light_parameters[i].dcvSpecular));
2661 glLightfv(GL_LIGHT0 + i, GL_SPOT_CUTOFF, &cut_off);
2663 direction[0] = This->light_parameters[i].dvDirection.u1.x;
2664 direction[1] = This->light_parameters[i].dvDirection.u2.y;
2665 direction[2] = This->light_parameters[i].dvDirection.u3.z;
2666 direction[3] = 0.0;
2667 glLightfv(GL_LIGHT0 + i, GL_POSITION, (float *) direction);
2668 } break;
2670 case D3DLIGHT_POINT: {
2671 float position[4];
2672 float cut_off = 180.0;
2674 glLightfv(GL_LIGHT0 + i, GL_AMBIENT, (float *) &(This->light_parameters[i].dcvAmbient));
2675 glLightfv(GL_LIGHT0 + i, GL_DIFFUSE, (float *) &(This->light_parameters[i].dcvDiffuse));
2676 glLightfv(GL_LIGHT0 + i, GL_SPECULAR, (float *) &(This->light_parameters[i].dcvSpecular));
2677 position[0] = This->light_parameters[i].dvPosition.u1.x;
2678 position[1] = This->light_parameters[i].dvPosition.u2.y;
2679 position[2] = This->light_parameters[i].dvPosition.u3.z;
2680 position[3] = 1.0;
2681 glLightfv(GL_LIGHT0 + i, GL_POSITION, (float *) position);
2682 glLightfv(GL_LIGHT0 + i, GL_CONSTANT_ATTENUATION, &(This->light_parameters[i].dvAttenuation0));
2683 glLightfv(GL_LIGHT0 + i, GL_LINEAR_ATTENUATION, &(This->light_parameters[i].dvAttenuation1));
2684 glLightfv(GL_LIGHT0 + i, GL_QUADRATIC_ATTENUATION, &(This->light_parameters[i].dvAttenuation2));
2685 glLightfv(GL_LIGHT0 + i, GL_SPOT_CUTOFF, &cut_off);
2686 } break;
2688 case D3DLIGHT_SPOT: {
2689 float direction[4];
2690 float position[4];
2691 float cut_off = 90.0 * (This->light_parameters[i].dvPhi / M_PI);
2693 glLightfv(GL_LIGHT0 + i, GL_AMBIENT, (float *) &(This->light_parameters[i].dcvAmbient));
2694 glLightfv(GL_LIGHT0 + i, GL_DIFFUSE, (float *) &(This->light_parameters[i].dcvDiffuse));
2695 glLightfv(GL_LIGHT0 + i, GL_SPECULAR, (float *) &(This->light_parameters[i].dcvSpecular));
2697 direction[0] = This->light_parameters[i].dvDirection.u1.x;
2698 direction[1] = This->light_parameters[i].dvDirection.u2.y;
2699 direction[2] = This->light_parameters[i].dvDirection.u3.z;
2700 direction[3] = 0.0;
2701 glLightfv(GL_LIGHT0 + i, GL_SPOT_DIRECTION, (float *) direction);
2702 position[0] = This->light_parameters[i].dvPosition.u1.x;
2703 position[1] = This->light_parameters[i].dvPosition.u2.y;
2704 position[2] = This->light_parameters[i].dvPosition.u3.z;
2705 position[3] = 1.0;
2706 glLightfv(GL_LIGHT0 + i, GL_POSITION, (float *) position);
2707 glLightfv(GL_LIGHT0 + i, GL_CONSTANT_ATTENUATION, &(This->light_parameters[i].dvAttenuation0));
2708 glLightfv(GL_LIGHT0 + i, GL_LINEAR_ATTENUATION, &(This->light_parameters[i].dvAttenuation1));
2709 glLightfv(GL_LIGHT0 + i, GL_QUADRATIC_ATTENUATION, &(This->light_parameters[i].dvAttenuation2));
2710 glLightfv(GL_LIGHT0 + i, GL_SPOT_CUTOFF, &cut_off);
2711 glLightfv(GL_LIGHT0 + i, GL_SPOT_EXPONENT, &(This->light_parameters[i].dvFalloff));
2712 } break;
2714 default:
2715 /* No warning here as it's already done at light setting */
2716 break;
2722 glMultMatrixf((float *) world_mat);
2724 if ((matrices & PROJMAT_CHANGED) != 0) {
2725 glMatrixMode(GL_PROJECTION);
2726 glLoadMatrixf((float *) proj_mat);
2730 void
2731 d3ddevice_matrices_updated(IDirect3DDeviceImpl *This, DWORD matrices)
2733 IDirect3DDeviceGLImpl *glThis = (IDirect3DDeviceGLImpl *) This;
2734 DWORD tex_mat, tex_stage;
2735 if ((matrices & (VIEWMAT_CHANGED|WORLDMAT_CHANGED|PROJMAT_CHANGED)) != 0) {
2736 if (glThis->transform_state == GL_TRANSFORM_NORMAL) {
2737 /* This will force an update of the transform state at the next drawing. */
2738 glThis->transform_state = GL_TRANSFORM_NONE;
2741 if (matrices & (TEXMAT0_CHANGED|TEXMAT1_CHANGED|TEXMAT2_CHANGED|TEXMAT3_CHANGED|
2742 TEXMAT4_CHANGED|TEXMAT5_CHANGED|TEXMAT6_CHANGED|TEXMAT7_CHANGED))
2744 ENTER_GL();
2745 for (tex_mat = TEXMAT0_CHANGED, tex_stage = 0; tex_mat <= TEXMAT7_CHANGED; tex_mat <<= 1, tex_stage++) {
2746 if (matrices & tex_mat) {
2747 if (This->state_block.texture_stage_state[tex_stage][D3DTSS_TEXTURETRANSFORMFLAGS - 1] != D3DTTFF_DISABLE) {
2748 if (tex_stage == 0) {
2749 /* No multi-texturing support for now ... */
2750 glMatrixMode(GL_TEXTURE);
2751 glLoadMatrixf((float *) This->tex_mat[tex_stage]);
2753 } else {
2754 glMatrixMode(GL_TEXTURE);
2755 glLoadIdentity();
2759 LEAVE_GL();
2763 /* TODO for both these functions :
2764 - change / restore OpenGL parameters for pictures transfers in case they are ever modified
2765 by other OpenGL code in D3D
2766 - handle the case where no 'Begin / EndScene' was done between two locks
2767 - handle the rectangles in the unlock too
2768 - handle pitch correctly...
2770 static void d3ddevice_lock_update(IDirectDrawSurfaceImpl* This, LPCRECT pRect, DWORD dwFlags)
2772 IDirect3DDeviceImpl *d3d_dev = This->d3ddevice;
2773 IDirect3DDeviceGLImpl* gl_d3d_dev = (IDirect3DDeviceGLImpl*) d3d_dev;
2774 BOOLEAN is_front;
2776 if ((This->surface_desc.ddsCaps.dwCaps & (DDSCAPS_FRONTBUFFER|DDSCAPS_PRIMARYSURFACE)) != 0) {
2777 is_front = TRUE;
2778 if ((gl_d3d_dev->front_state != SURFACE_GL) &&
2779 (gl_d3d_dev->front_lock_surf != This)) {
2780 ERR("Change of front buffer.. Expect graphic corruptions !\n");
2782 gl_d3d_dev->front_lock_surf = This;
2783 } else if ((This->surface_desc.ddsCaps.dwCaps & (DDSCAPS_BACKBUFFER)) == (DDSCAPS_BACKBUFFER)) {
2784 is_front = FALSE;
2785 if ((gl_d3d_dev->state != SURFACE_GL) &&
2786 (gl_d3d_dev->lock_surf != This)) {
2787 ERR("Change of back buffer.. Expect graphic corruptions !\n");
2789 gl_d3d_dev->lock_surf = This;
2790 } else {
2791 ERR("Wrong surface type for locking !\n");
2792 return;
2795 /* Try to acquire the device critical section */
2796 EnterCriticalSection(&(d3d_dev->crit));
2798 if (((is_front == TRUE) && (gl_d3d_dev->front_state == SURFACE_GL)) ||
2799 ((is_front == FALSE) && (gl_d3d_dev->state == SURFACE_GL))) {
2800 /* If the surface is already in memory, no need to do anything here... */
2801 GLenum buffer_type;
2802 GLenum buffer_color;
2803 GLenum prev_read;
2804 RECT loc_rect;
2805 int y;
2806 char *dst;
2808 TRACE(" copying frame buffer to main memory.\n");
2810 /* Note that here we cannot do 'optmizations' about the WriteOnly flag... Indeed, a game
2811 may only write to the device... But when we will blit it back to the screen, we need
2812 also to blit correctly the parts the application did not overwrite... */
2814 ENTER_GL();
2816 glGetIntegerv(GL_READ_BUFFER, &prev_read);
2817 glFlush();
2819 if (is_front == TRUE)
2820 /* Application wants to lock the front buffer */
2821 glReadBuffer(GL_FRONT);
2822 else
2823 /* Application wants to lock the back buffer */
2824 glReadBuffer(GL_BACK);
2826 if ((This->surface_desc.u4.ddpfPixelFormat.u1.dwRGBBitCount == 16) &&
2827 (This->surface_desc.u4.ddpfPixelFormat.u2.dwRBitMask == 0xF800) &&
2828 (This->surface_desc.u4.ddpfPixelFormat.u3.dwGBitMask == 0x07E0) &&
2829 (This->surface_desc.u4.ddpfPixelFormat.u4.dwBBitMask == 0x001F) &&
2830 (This->surface_desc.u4.ddpfPixelFormat.u5.dwRGBAlphaBitMask == 0x0000)) {
2831 buffer_type = GL_UNSIGNED_SHORT_5_6_5;
2832 buffer_color = GL_RGB;
2833 } else if ((This->surface_desc.u4.ddpfPixelFormat.u1.dwRGBBitCount == 32) &&
2834 (This->surface_desc.u4.ddpfPixelFormat.u2.dwRBitMask == 0x00FF0000) &&
2835 (This->surface_desc.u4.ddpfPixelFormat.u3.dwGBitMask == 0x0000FF00) &&
2836 (This->surface_desc.u4.ddpfPixelFormat.u4.dwBBitMask == 0x000000FF) &&
2837 (This->surface_desc.u4.ddpfPixelFormat.u5.dwRGBAlphaBitMask == 0x00000000)) {
2838 buffer_type = GL_UNSIGNED_BYTE;
2839 buffer_color = GL_BGRA;
2840 glPixelStorei(GL_PACK_SWAP_BYTES, TRUE);
2841 } else {
2842 ERR(" unsupported pixel format at device locking.\n");
2843 LEAVE_GL();
2844 return;
2847 /* Just a hack while waiting for proper rectangle support */
2848 pRect = NULL;
2849 if (pRect == NULL) {
2850 loc_rect.top = 0;
2851 loc_rect.left = 0;
2852 loc_rect.bottom = This->surface_desc.dwHeight;
2853 loc_rect.right = This->surface_desc.dwWidth;
2854 } else {
2855 loc_rect = *pRect;
2858 dst = ((char *)This->surface_desc.lpSurface) +
2859 (loc_rect.top * This->surface_desc.u1.lPitch) + (loc_rect.left * GET_BPP(This->surface_desc));
2860 for (y = (This->surface_desc.dwHeight - loc_rect.top - 1);
2861 y >= ((int) This->surface_desc.dwHeight - (int) loc_rect.bottom);
2862 y--) {
2863 glReadPixels(loc_rect.left, y,
2864 loc_rect.right - loc_rect.left, 1,
2865 buffer_color, buffer_type, dst);
2866 dst += This->surface_desc.u1.lPitch;
2869 glReadBuffer(prev_read);
2870 glPixelStorei(GL_PACK_SWAP_BYTES, FALSE);
2872 if (is_front)
2873 gl_d3d_dev->front_state = SURFACE_MEMORY;
2874 else
2875 gl_d3d_dev->state = SURFACE_MEMORY;
2877 #if 0
2878 /* I keep this code here as it's very useful to debug :-) */
2880 static int flush_count = 0;
2881 char buf[128];
2882 FILE *f;
2884 if ((++flush_count % 50) == 0) {
2885 sprintf(buf, "lock_%06d.pnm", flush_count);
2886 f = fopen(buf, "wb");
2887 DDRAW_dump_surface_to_disk(This, f);
2890 #endif
2892 LEAVE_GL();
2896 #define UNLOCK_TEX_SIZE 256
2898 static void d3ddevice_flush_to_frame_buffer(IDirect3DDeviceImpl *d3d_dev, LPCRECT pRect, IDirectDrawSurfaceImpl *surf) {
2899 GLenum buffer_type, buffer_color;
2900 RECT loc_rect;
2901 IDirect3DDeviceGLImpl* gl_d3d_dev = (IDirect3DDeviceGLImpl*) d3d_dev;
2902 GLint depth_test, alpha_test, cull_face, lighting, min_tex, max_tex, tex_env, blend, stencil_test, fog;
2903 GLuint initial_texture;
2904 GLint tex_state;
2905 int x, y;
2907 /* This is to prevent another thread to actually lock the buffer while we flush it on screen */
2908 EnterCriticalSection(&(d3d_dev->crit));
2910 loc_rect.top = 0;
2911 loc_rect.left = 0;
2912 loc_rect.bottom = surf->surface_desc.dwHeight;
2913 loc_rect.right = surf->surface_desc.dwWidth;
2915 TRACE(" flushing memory back to the frame-buffer (%ld,%ld) x (%ld,%ld).\n", loc_rect.top, loc_rect.left, loc_rect.right, loc_rect.bottom);
2917 glGetIntegerv(GL_DEPTH_TEST, &depth_test);
2918 glGetIntegerv(GL_ALPHA_TEST, &alpha_test);
2919 glGetIntegerv(GL_STENCIL_TEST, &stencil_test);
2920 glGetIntegerv(GL_CULL_FACE, &cull_face);
2921 glGetIntegerv(GL_LIGHTING, &lighting);
2922 glGetIntegerv(GL_BLEND, &blend);
2923 glGetIntegerv(GL_TEXTURE_BINDING_2D, &initial_texture);
2924 glGetIntegerv(GL_TEXTURE_2D, &tex_state);
2925 glGetIntegerv(GL_FOG, &fog);
2926 glGetTexParameteriv(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, &max_tex);
2927 glGetTexParameteriv(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, &min_tex);
2928 glGetTexEnviv(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, &tex_env);
2929 glMatrixMode(GL_TEXTURE);
2930 glLoadIdentity();
2931 /* TODO: scissor test if ever we use it ! */
2933 if ((surf->surface_desc.u4.ddpfPixelFormat.u1.dwRGBBitCount == 16) &&
2934 (surf->surface_desc.u4.ddpfPixelFormat.u2.dwRBitMask == 0xF800) &&
2935 (surf->surface_desc.u4.ddpfPixelFormat.u3.dwGBitMask == 0x07E0) &&
2936 (surf->surface_desc.u4.ddpfPixelFormat.u4.dwBBitMask == 0x001F) &&
2937 (surf->surface_desc.u4.ddpfPixelFormat.u5.dwRGBAlphaBitMask == 0x0000)) {
2938 buffer_type = GL_UNSIGNED_SHORT_5_6_5;
2939 buffer_color = GL_RGB;
2940 } else if ((surf->surface_desc.u4.ddpfPixelFormat.u1.dwRGBBitCount == 32) &&
2941 (surf->surface_desc.u4.ddpfPixelFormat.u2.dwRBitMask == 0x00FF0000) &&
2942 (surf->surface_desc.u4.ddpfPixelFormat.u3.dwGBitMask == 0x0000FF00) &&
2943 (surf->surface_desc.u4.ddpfPixelFormat.u4.dwBBitMask == 0x000000FF) &&
2944 (surf->surface_desc.u4.ddpfPixelFormat.u5.dwRGBAlphaBitMask == 0x00000000)) {
2945 buffer_type = GL_UNSIGNED_BYTE;
2946 buffer_color = GL_BGRA;
2947 glPixelStorei(GL_UNPACK_SWAP_BYTES, TRUE);
2948 } else {
2949 ERR(" unsupported pixel format at frame buffer flush.\n");
2950 LeaveCriticalSection(&(d3d_dev->crit));
2951 return;
2954 gl_d3d_dev->transform_state = GL_TRANSFORM_ORTHO;
2955 d3ddevice_set_ortho(d3d_dev);
2957 glDisable(GL_DEPTH_TEST);
2958 glEnable(GL_TEXTURE_2D);
2959 glEnable(GL_SCISSOR_TEST);
2960 glScissor(loc_rect.left, surf->surface_desc.dwHeight - loc_rect.bottom,
2961 loc_rect.right - loc_rect.left, loc_rect.bottom - loc_rect.top);
2963 if (gl_d3d_dev->unlock_tex == 0) {
2964 glGenTextures(1, &gl_d3d_dev->unlock_tex);
2965 glBindTexture(GL_TEXTURE_2D, gl_d3d_dev->unlock_tex);
2966 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB,
2967 UNLOCK_TEX_SIZE, UNLOCK_TEX_SIZE, 0,
2968 GL_RGB, buffer_type, NULL);
2969 } else {
2970 glBindTexture(GL_TEXTURE_2D, gl_d3d_dev->unlock_tex);
2972 glPixelStorei(GL_UNPACK_ROW_LENGTH, surf->surface_desc.dwWidth);
2974 glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);
2975 glDisable(GL_LIGHTING);
2976 glDisable(GL_CULL_FACE);
2977 glDisable(GL_ALPHA_TEST);
2978 glDisable(GL_STENCIL_TEST);
2979 glDisable(GL_BLEND);
2980 glDisable(GL_FOG);
2981 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
2982 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
2984 for (x = loc_rect.left; x < loc_rect.right; x += UNLOCK_TEX_SIZE) {
2985 for (y = loc_rect.top; y < loc_rect.bottom; y += UNLOCK_TEX_SIZE) {
2986 /* First, upload the texture... */
2987 int w = (x + UNLOCK_TEX_SIZE > surf->surface_desc.dwWidth) ? (surf->surface_desc.dwWidth - x) : UNLOCK_TEX_SIZE;
2988 int h = (y + UNLOCK_TEX_SIZE > surf->surface_desc.dwHeight) ? (surf->surface_desc.dwHeight - y) : UNLOCK_TEX_SIZE;
2989 glTexSubImage2D(GL_TEXTURE_2D,
2991 0, 0,
2992 w, h,
2993 buffer_color,
2994 buffer_type,
2995 ((char *) surf->surface_desc.lpSurface) + (x * GET_BPP(surf->surface_desc)) + (y * surf->surface_desc.u1.lPitch));
2996 glBegin(GL_QUADS);
2997 glColor3ub(0xFF, 0xFF, 0xFF);
2998 glTexCoord2f(0.0, 0.0);
2999 glVertex3d(x, y, 0.5);
3000 glTexCoord2f(1.0, 0.0);
3001 glVertex3d(x + UNLOCK_TEX_SIZE, y, 0.5);
3002 glTexCoord2f(1.0, 1.0);
3003 glVertex3d(x + UNLOCK_TEX_SIZE, y + UNLOCK_TEX_SIZE, 0.5);
3004 glTexCoord2f(0.0, 1.0);
3005 glVertex3d(x, y + UNLOCK_TEX_SIZE, 0.5);
3006 glEnd();
3011 /* And restore all the various states modified by this code */
3012 if (depth_test != 0) glEnable(GL_DEPTH_TEST);
3013 if (lighting != 0) glEnable(GL_LIGHTING);
3014 if (alpha_test != 0) glEnable(GL_ALPHA_TEST);
3015 if (stencil_test != 0) glEnable(GL_STENCIL_TEST);
3016 if (cull_face != 0) glEnable(GL_CULL_FACE);
3017 if (blend != 0) glEnable(GL_BLEND);
3018 if (fog != 0) glEnable(GL_FOG);
3019 glBindTexture(GL_TEXTURE_2D, initial_texture);
3020 if (tex_state == 0) glDisable(GL_TEXTURE_2D);
3021 glDisable(GL_SCISSOR_TEST);
3022 glPixelStorei(GL_UNPACK_ROW_LENGTH, 0);
3023 glPixelStorei(GL_UNPACK_SWAP_BYTES, FALSE);
3024 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, max_tex);
3025 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, min_tex);
3026 glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, tex_env);
3027 LEAVE_GL();
3028 d3d_dev->matrices_updated(d3d_dev, TEXMAT0_CHANGED);
3029 ENTER_GL();
3030 #if 0
3031 /* I keep this code here as it's very useful to debug :-) */
3033 static int flush_count = 0;
3034 char buf[128];
3035 FILE *f;
3037 if ((++flush_count % 50) == 0) {
3038 sprintf(buf, "flush_%06d.pnm", flush_count);
3039 f = fopen(buf, "wb");
3040 DDRAW_dump_surface_to_disk(surf, f);
3043 #endif
3045 /* And leave the critical section... */
3046 LeaveCriticalSection(&(d3d_dev->crit));
3049 static void d3ddevice_unlock_update(IDirectDrawSurfaceImpl* This, LPCRECT pRect)
3051 BOOLEAN is_front;
3052 IDirect3DDeviceImpl *d3d_dev = This->d3ddevice;
3053 IDirect3DDeviceGLImpl* gl_d3d_dev = (IDirect3DDeviceGLImpl*) d3d_dev;
3055 if ((This->surface_desc.ddsCaps.dwCaps & (DDSCAPS_FRONTBUFFER|DDSCAPS_PRIMARYSURFACE)) != 0) {
3056 is_front = TRUE;
3057 } else if ((This->surface_desc.ddsCaps.dwCaps & (DDSCAPS_BACKBUFFER)) == (DDSCAPS_BACKBUFFER)) {
3058 is_front = FALSE;
3059 } else {
3060 ERR("Wrong surface type for locking !\n");
3061 return;
3063 /* First, check if we need to do anything. For the backbuffer, flushing is done at the next 3D activity. */
3064 if ((This->lastlocktype & DDLOCK_READONLY) == 0) {
3065 if (is_front == TRUE) {
3066 GLenum prev_draw;
3067 ENTER_GL();
3068 glGetIntegerv(GL_DRAW_BUFFER, &prev_draw);
3069 glDrawBuffer(GL_FRONT);
3070 d3d_dev->flush_to_framebuffer(d3d_dev, pRect, gl_d3d_dev->front_lock_surf);
3071 glDrawBuffer(prev_draw);
3072 LEAVE_GL();
3073 } else {
3074 gl_d3d_dev->state = SURFACE_MEMORY_DIRTY;
3078 /* And 'frees' the device critical section */
3079 LeaveCriticalSection(&(d3d_dev->crit));
3082 static void
3083 apply_texture_state(IDirect3DDeviceImpl *This)
3085 int stage, state;
3087 /* Initialize texture stages states */
3088 for (stage = 0; stage < MAX_TEXTURES; stage++) {
3089 for (state = 0; state < HIGHEST_TEXTURE_STAGE_STATE; state += 1) {
3090 if (This->state_block.set_flags.texture_stage_state[stage][state] == TRUE) {
3091 IDirect3DDevice7_SetTextureStageState(ICOM_INTERFACE(This, IDirect3DDevice7),
3092 stage, state + 1, This->state_block.texture_stage_state[stage][state]);
3098 HRESULT
3099 d3ddevice_create(IDirect3DDeviceImpl **obj, IDirect3DImpl *d3d, IDirectDrawSurfaceImpl *surface)
3101 IDirect3DDeviceImpl *object;
3102 IDirect3DDeviceGLImpl *gl_object;
3103 IDirectDrawSurfaceImpl *surf;
3104 HDC device_context;
3105 XVisualInfo *vis;
3106 int num;
3107 int tex_num;
3108 XVisualInfo template;
3109 GLenum buffer = GL_FRONT;
3110 int light;
3111 GLint max_clipping_planes = 0;
3113 object = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(IDirect3DDeviceGLImpl));
3114 if (object == NULL) return DDERR_OUTOFMEMORY;
3116 gl_object = (IDirect3DDeviceGLImpl *) object;
3118 object->ref = 1;
3119 object->d3d = d3d;
3120 object->surface = surface;
3121 object->set_context = set_context;
3122 object->clear = d3ddevice_clear;
3123 object->set_matrices = d3ddevice_set_matrices;
3124 object->matrices_updated = d3ddevice_matrices_updated;
3125 object->flush_to_framebuffer = d3ddevice_flush_to_frame_buffer;
3127 InitializeCriticalSection(&(object->crit));
3129 TRACE(" creating OpenGL device for surface = %p, d3d = %p\n", surface, d3d);
3131 device_context = GetDC(surface->ddraw_owner->window);
3132 gl_object->display = get_display(device_context);
3133 gl_object->drawable = get_drawable(device_context);
3134 ReleaseDC(surface->ddraw_owner->window,device_context);
3136 ENTER_GL();
3137 template.visualid = (VisualID)GetPropA( GetDesktopWindow(), "__wine_x11_visual_id" );
3138 vis = XGetVisualInfo(gl_object->display, VisualIDMask, &template, &num);
3139 if (vis == NULL) {
3140 HeapFree(GetProcessHeap(), 0, object);
3141 ERR("No visual found !\n");
3142 LEAVE_GL();
3143 return DDERR_INVALIDPARAMS;
3144 } else {
3145 TRACE(" visual found\n");
3148 gl_object->gl_context = glXCreateContext(gl_object->display, vis,
3149 NULL, GL_TRUE);
3151 if (gl_object->gl_context == NULL) {
3152 HeapFree(GetProcessHeap(), 0, object);
3153 ERR("Error in context creation !\n");
3154 LEAVE_GL();
3155 return DDERR_INVALIDPARAMS;
3156 } else {
3157 TRACE(" context created (%p)\n", gl_object->gl_context);
3160 /* Look for the front buffer and override its surface's Flip method (if in double buffering) */
3161 for (surf = surface; surf != NULL; surf = surf->surface_owner) {
3162 if ((surf->surface_desc.ddsCaps.dwCaps&(DDSCAPS_FLIP|DDSCAPS_FRONTBUFFER)) == (DDSCAPS_FLIP|DDSCAPS_FRONTBUFFER)) {
3163 surf->aux_ctx = (LPVOID) object;
3164 surf->aux_data = (LPVOID) gl_object->drawable;
3165 surf->aux_flip = opengl_flip;
3166 buffer = GL_BACK;
3167 break;
3170 /* We are not doing any double buffering.. Then force OpenGL to draw on the front buffer */
3171 if (surf == NULL) {
3172 TRACE(" no double buffering : drawing on the front buffer\n");
3173 buffer = GL_FRONT;
3176 for (surf = surface; surf != NULL; surf = surf->surface_owner) {
3177 IDirectDrawSurfaceImpl *surf2;
3178 for (surf2 = surf; surf2->prev_attached != NULL; surf2 = surf2->prev_attached) ;
3179 for (; surf2 != NULL; surf2 = surf2->next_attached) {
3180 TRACE(" checking surface %p :", surf2);
3181 if (((surf2->surface_desc.ddsCaps.dwCaps & (DDSCAPS_3DDEVICE)) == (DDSCAPS_3DDEVICE)) &&
3182 ((surf2->surface_desc.ddsCaps.dwCaps & (DDSCAPS_ZBUFFER)) != (DDSCAPS_ZBUFFER))) {
3183 /* Override the Lock / Unlock function for all these surfaces */
3184 surf2->lock_update_prev = surf2->lock_update;
3185 surf2->lock_update = d3ddevice_lock_update;
3186 surf2->unlock_update_prev = surf2->unlock_update;
3187 surf2->unlock_update = d3ddevice_unlock_update;
3188 /* And install also the blt / bltfast overrides */
3189 surf2->aux_blt = d3ddevice_blt;
3190 surf2->aux_bltfast = d3ddevice_bltfast;
3192 TRACE(" overiding direct surface access.\n");
3193 } else {
3194 TRACE(" no overide.\n");
3196 surf2->d3ddevice = object;
3200 /* Set the various light parameters */
3201 for (light = 0; light < MAX_LIGHTS; light++) {
3202 /* Only set the fields that are not zero-created */
3203 object->light_parameters[light].dltType = D3DLIGHT_DIRECTIONAL;
3204 object->light_parameters[light].dcvDiffuse.u1.r = 1.0;
3205 object->light_parameters[light].dcvDiffuse.u2.g = 1.0;
3206 object->light_parameters[light].dcvDiffuse.u3.b = 1.0;
3207 object->light_parameters[light].dvDirection.u3.z = 1.0;
3210 /* Allocate memory for the matrices */
3211 object->world_mat = (D3DMATRIX *) HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, 16 * sizeof(float));
3212 object->view_mat = (D3DMATRIX *) HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, 16 * sizeof(float));
3213 object->proj_mat = (D3DMATRIX *) HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, 16 * sizeof(float));
3214 memcpy(object->world_mat, id_mat, 16 * sizeof(float));
3215 memcpy(object->view_mat , id_mat, 16 * sizeof(float));
3216 memcpy(object->proj_mat , id_mat, 16 * sizeof(float));
3217 for (tex_num = 0; tex_num < MAX_TEXTURES; tex_num++) {
3218 object->tex_mat[tex_num] = (D3DMATRIX *) HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, 16 * sizeof(float));
3219 memcpy(object->tex_mat[tex_num], id_mat, 16 * sizeof(float));
3222 /* Initialisation */
3223 TRACE(" setting current context\n");
3224 LEAVE_GL();
3225 object->set_context(object);
3226 ENTER_GL();
3227 TRACE(" current context set\n");
3229 /* allocate the clipping planes */
3230 glGetIntegerv(GL_MAX_CLIP_PLANES,&max_clipping_planes);
3231 if (max_clipping_planes>32) {
3232 object->max_clipping_planes=32;
3233 } else {
3234 object->max_clipping_planes = max_clipping_planes;
3236 TRACE(" capable of %d clipping planes\n", (int)object->max_clipping_planes );
3237 object->clipping_planes = (d3d7clippingplane*)HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, object->max_clipping_planes * sizeof(d3d7clippingplane));
3239 glHint(GL_FOG_HINT,GL_NICEST);
3241 glClearColor(0.0, 0.0, 0.0, 0.0);
3242 glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
3243 glDrawBuffer(buffer);
3244 glReadBuffer(buffer);
3245 /* glDisable(GL_DEPTH_TEST); Need here to check for the presence of a ZBuffer and to reenable it when the ZBuffer is attached */
3246 LEAVE_GL();
3248 gl_object->state = SURFACE_GL;
3250 /* fill_device_capabilities(d3d->ddraw); */
3252 ICOM_INIT_INTERFACE(object, IDirect3DDevice, VTABLE_IDirect3DDevice);
3253 ICOM_INIT_INTERFACE(object, IDirect3DDevice2, VTABLE_IDirect3DDevice2);
3254 ICOM_INIT_INTERFACE(object, IDirect3DDevice3, VTABLE_IDirect3DDevice3);
3255 ICOM_INIT_INTERFACE(object, IDirect3DDevice7, VTABLE_IDirect3DDevice7);
3257 *obj = object;
3259 TRACE(" creating implementation at %p.\n", *obj);
3261 /* And finally warn D3D that this device is now present */
3262 object->d3d->added_device(object->d3d, object);
3264 /* FIXME: Should handle other versions than just 7 */
3265 InitDefaultStateBlock(&object->state_block, 7);
3266 /* Apply default render state and texture stage state values */
3267 apply_render_state(object, &object->state_block);
3268 apply_texture_state(object);
3270 /* And fill the fog table with the default fog value */
3271 build_fog_table(gl_object->fog_table, object->state_block.render_state[D3DRENDERSTATE_FOGCOLOR - 1]);
3273 return DD_OK;