- remove some extraneous saving of the read buffer settings
[wine/multimedia.git] / dlls / ddraw / d3ddevice / mesa.c
blob3e8500bf7cb39146229a7e1c4c2c0d6f78368858
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 /* This is to prevent 'thread contention' between a thread locking the device and another
1130 doing 3D display on it... */
1131 EnterCriticalSection(&(This->crit));
1133 ENTER_GL();
1134 if (glThis->state == SURFACE_MEMORY_DIRTY) {
1135 This->flush_to_framebuffer(This, NULL, glThis->lock_surf);
1138 glThis->state = SURFACE_GL;
1140 /* Compute the number of active texture stages */
1141 while (This->current_texture[num_active_stages] != NULL) num_active_stages++;
1143 if (TRACE_ON(ddraw)) {
1144 TRACE(" Vertex format : "); dump_flexible_vertex(d3dvtVertexType);
1147 /* Just a hack for now.. Will have to find better algorithm :-/ */
1148 if ((d3dvtVertexType & D3DFVF_POSITION_MASK) != D3DFVF_XYZ) {
1149 vertex_lighted = TRUE;
1150 } else {
1151 if ((d3dvtVertexType & D3DFVF_NORMAL) == 0) glNormal3f(0.0, 0.0, 0.0);
1154 draw_primitive_handle_GL_state(This,
1155 (d3dvtVertexType & D3DFVF_POSITION_MASK) != D3DFVF_XYZ,
1156 vertex_lighted);
1157 draw_primitive_start_GL(d3dptPrimitiveType);
1159 /* Some fast paths first before the generic case.... */
1160 if ((d3dvtVertexType == D3DFVF_VERTEX) && (num_active_stages <= 1)) {
1161 int index;
1163 for (index = 0; index < dwIndexCount; index++) {
1164 int i = (dwIndices == NULL) ? index : dwIndices[index];
1165 D3DVALUE *normal =
1166 (D3DVALUE *) (((char *) lpD3DDrawPrimStrideData->normal.lpvData) + i * lpD3DDrawPrimStrideData->normal.dwStride);
1167 D3DVALUE *tex_coord =
1168 (D3DVALUE *) (((char *) lpD3DDrawPrimStrideData->textureCoords[0].lpvData) + i * lpD3DDrawPrimStrideData->textureCoords[0].dwStride);
1169 D3DVALUE *position =
1170 (D3DVALUE *) (((char *) lpD3DDrawPrimStrideData->position.lpvData) + i * lpD3DDrawPrimStrideData->position.dwStride);
1172 handle_normal(normal);
1173 handle_texture(tex_coord);
1174 handle_xyz(position);
1176 TRACE_(ddraw_geom)(" %f %f %f / %f %f %f (%f %f)\n",
1177 position[0], position[1], position[2],
1178 normal[0], normal[1], normal[2],
1179 tex_coord[0], tex_coord[1]);
1181 } else if ((d3dvtVertexType == D3DFVF_TLVERTEX) && (num_active_stages <= 1)) {
1182 int index;
1184 for (index = 0; index < dwIndexCount; index++) {
1185 int i = (dwIndices == NULL) ? index : dwIndices[index];
1186 DWORD *color_d =
1187 (DWORD *) (((char *) lpD3DDrawPrimStrideData->diffuse.lpvData) + i * lpD3DDrawPrimStrideData->diffuse.dwStride);
1188 DWORD *color_s =
1189 (DWORD *) (((char *) lpD3DDrawPrimStrideData->specular.lpvData) + i * lpD3DDrawPrimStrideData->specular.dwStride);
1190 D3DVALUE *tex_coord =
1191 (D3DVALUE *) (((char *) lpD3DDrawPrimStrideData->textureCoords[0].lpvData) + i * lpD3DDrawPrimStrideData->textureCoords[0].dwStride);
1192 D3DVALUE *position =
1193 (D3DVALUE *) (((char *) lpD3DDrawPrimStrideData->position.lpvData) + i * lpD3DDrawPrimStrideData->position.dwStride);
1195 handle_diffuse_and_specular(&(This->state_block), glThis->fog_table, color_d, color_s, TRUE);
1196 handle_texture(tex_coord);
1197 handle_xyzrhw(position);
1199 TRACE_(ddraw_geom)(" %f %f %f %f / %02lx %02lx %02lx %02lx - %02lx %02lx %02lx %02lx (%f %f)\n",
1200 position[0], position[1], position[2], position[3],
1201 (*color_d >> 16) & 0xFF,
1202 (*color_d >> 8) & 0xFF,
1203 (*color_d >> 0) & 0xFF,
1204 (*color_d >> 24) & 0xFF,
1205 (*color_s >> 16) & 0xFF,
1206 (*color_s >> 8) & 0xFF,
1207 (*color_s >> 0) & 0xFF,
1208 (*color_s >> 24) & 0xFF,
1209 tex_coord[0], tex_coord[1]);
1211 } else if (((d3dvtVertexType & D3DFVF_POSITION_MASK) == D3DFVF_XYZ) ||
1212 ((d3dvtVertexType & D3DFVF_POSITION_MASK) == D3DFVF_XYZRHW)) {
1213 /* This is the 'slow path' but that should support all possible vertex formats out there...
1214 Note that people should write a fast path for all vertex formats out there...
1216 int index;
1217 int num_tex_index = ((d3dvtVertexType & D3DFVF_TEXCOUNT_MASK) >> D3DFVF_TEXCOUNT_SHIFT);
1218 static const D3DVALUE no_index[] = { 0.0, 0.0, 0.0, 0.0 };
1220 for (index = 0; index < dwIndexCount; index++) {
1221 int i = (dwIndices == NULL) ? index : dwIndices[index];
1222 int tex_stage;
1224 if (d3dvtVertexType & D3DFVF_NORMAL) {
1225 D3DVALUE *normal =
1226 (D3DVALUE *) (((char *) lpD3DDrawPrimStrideData->normal.lpvData) + i * lpD3DDrawPrimStrideData->normal.dwStride);
1227 handle_normal(normal);
1229 if ((d3dvtVertexType & (D3DFVF_DIFFUSE|D3DFVF_SPECULAR)) == (D3DFVF_DIFFUSE|D3DFVF_SPECULAR)) {
1230 DWORD *color_d =
1231 (DWORD *) (((char *) lpD3DDrawPrimStrideData->diffuse.lpvData) + i * lpD3DDrawPrimStrideData->diffuse.dwStride);
1232 DWORD *color_s =
1233 (DWORD *) (((char *) lpD3DDrawPrimStrideData->specular.lpvData) + i * lpD3DDrawPrimStrideData->specular.dwStride);
1234 handle_diffuse_and_specular(&(This->state_block), glThis->fog_table, color_d, color_s, vertex_lighted);
1235 } else {
1236 if (d3dvtVertexType & D3DFVF_SPECULAR) {
1237 DWORD *color_s =
1238 (DWORD *) (((char *) lpD3DDrawPrimStrideData->specular.lpvData) + i * lpD3DDrawPrimStrideData->specular.dwStride);
1239 handle_specular(&(This->state_block), color_s, vertex_lighted);
1240 } else if (d3dvtVertexType & D3DFVF_DIFFUSE) {
1241 DWORD *color_d =
1242 (DWORD *) (((char *) lpD3DDrawPrimStrideData->diffuse.lpvData) + i * lpD3DDrawPrimStrideData->diffuse.dwStride);
1243 handle_diffuse(&(This->state_block), color_d, vertex_lighted);
1247 for (tex_stage = 0; tex_stage < num_active_stages; tex_stage++) {
1248 int tex_index = This->state_block.texture_stage_state[tex_stage][D3DTSS_TEXCOORDINDEX - 1] & 0xFFFF000;
1249 if (tex_index >= num_tex_index) {
1250 handle_textures((D3DVALUE *) no_index, tex_stage);
1251 } else {
1252 D3DVALUE *tex_coord =
1253 (D3DVALUE *) (((char *) lpD3DDrawPrimStrideData->textureCoords[tex_index].lpvData) +
1254 i * lpD3DDrawPrimStrideData->textureCoords[tex_index].dwStride);
1255 handle_textures(tex_coord, tex_stage);
1259 if ((d3dvtVertexType & D3DFVF_POSITION_MASK) == D3DFVF_XYZ) {
1260 D3DVALUE *position =
1261 (D3DVALUE *) (((char *) lpD3DDrawPrimStrideData->position.lpvData) + i * lpD3DDrawPrimStrideData->position.dwStride);
1262 handle_xyz(position);
1263 } else if ((d3dvtVertexType & D3DFVF_POSITION_MASK) == D3DFVF_XYZRHW) {
1264 D3DVALUE *position =
1265 (D3DVALUE *) (((char *) lpD3DDrawPrimStrideData->position.lpvData) + i * lpD3DDrawPrimStrideData->position.dwStride);
1266 handle_xyzrhw(position);
1269 if (TRACE_ON(ddraw_geom)) {
1270 int tex_index;
1272 if ((d3dvtVertexType & D3DFVF_POSITION_MASK) == D3DFVF_XYZ) {
1273 D3DVALUE *position =
1274 (D3DVALUE *) (((char *) lpD3DDrawPrimStrideData->position.lpvData) + i * lpD3DDrawPrimStrideData->position.dwStride);
1275 TRACE_(ddraw_geom)(" %f %f %f", position[0], position[1], position[2]);
1276 } else if ((d3dvtVertexType & D3DFVF_POSITION_MASK) == D3DFVF_XYZRHW) {
1277 D3DVALUE *position =
1278 (D3DVALUE *) (((char *) lpD3DDrawPrimStrideData->position.lpvData) + i * lpD3DDrawPrimStrideData->position.dwStride);
1279 TRACE_(ddraw_geom)(" %f %f %f %f", position[0], position[1], position[2], position[3]);
1281 if (d3dvtVertexType & D3DFVF_NORMAL) {
1282 D3DVALUE *normal =
1283 (D3DVALUE *) (((char *) lpD3DDrawPrimStrideData->normal.lpvData) + i * lpD3DDrawPrimStrideData->normal.dwStride);
1284 TRACE_(ddraw_geom)(" / %f %f %f", normal[0], normal[1], normal[2]);
1286 if (d3dvtVertexType & D3DFVF_DIFFUSE) {
1287 DWORD *color_d =
1288 (DWORD *) (((char *) lpD3DDrawPrimStrideData->diffuse.lpvData) + i * lpD3DDrawPrimStrideData->diffuse.dwStride);
1289 TRACE_(ddraw_geom)(" / %02lx %02lx %02lx %02lx",
1290 (*color_d >> 16) & 0xFF,
1291 (*color_d >> 8) & 0xFF,
1292 (*color_d >> 0) & 0xFF,
1293 (*color_d >> 24) & 0xFF);
1295 if (d3dvtVertexType & D3DFVF_SPECULAR) {
1296 DWORD *color_s =
1297 (DWORD *) (((char *) lpD3DDrawPrimStrideData->specular.lpvData) + i * lpD3DDrawPrimStrideData->specular.dwStride);
1298 TRACE_(ddraw_geom)(" / %02lx %02lx %02lx %02lx",
1299 (*color_s >> 16) & 0xFF,
1300 (*color_s >> 8) & 0xFF,
1301 (*color_s >> 0) & 0xFF,
1302 (*color_s >> 24) & 0xFF);
1304 for (tex_index = 0; tex_index < ((d3dvtVertexType & D3DFVF_TEXCOUNT_MASK) >> D3DFVF_TEXCOUNT_SHIFT); tex_index++) {
1305 D3DVALUE *tex_coord =
1306 (D3DVALUE *) (((char *) lpD3DDrawPrimStrideData->textureCoords[tex_index].lpvData) +
1307 i * lpD3DDrawPrimStrideData->textureCoords[tex_index].dwStride);
1308 TRACE_(ddraw_geom)(" / %f %f", tex_coord[0], tex_coord[1]);
1310 TRACE_(ddraw_geom)("\n");
1313 } else {
1314 ERR(" matrix weighting not handled yet....\n");
1317 glEnd();
1319 /* Whatever the case, disable the color material stuff */
1320 glDisable(GL_COLOR_MATERIAL);
1322 LEAVE_GL();
1323 TRACE("End\n");
1325 LeaveCriticalSection(&(This->crit));
1328 HRESULT WINAPI
1329 GL_IDirect3DDeviceImpl_7_3T_DrawPrimitive(LPDIRECT3DDEVICE7 iface,
1330 D3DPRIMITIVETYPE d3dptPrimitiveType,
1331 DWORD d3dvtVertexType,
1332 LPVOID lpvVertices,
1333 DWORD dwVertexCount,
1334 DWORD dwFlags)
1336 ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice7, iface);
1337 D3DDRAWPRIMITIVESTRIDEDDATA strided;
1339 TRACE("(%p/%p)->(%08x,%08lx,%p,%08lx,%08lx)\n", This, iface, d3dptPrimitiveType, d3dvtVertexType, lpvVertices, dwVertexCount, dwFlags);
1340 if (TRACE_ON(ddraw)) {
1341 TRACE(" - flags : "); dump_DPFLAGS(dwFlags);
1344 convert_FVF_to_strided_data(d3dvtVertexType, lpvVertices, &strided, 0);
1345 draw_primitive_strided(This, d3dptPrimitiveType, d3dvtVertexType, &strided, dwVertexCount, NULL, dwVertexCount, dwFlags);
1347 return DD_OK;
1350 HRESULT WINAPI
1351 GL_IDirect3DDeviceImpl_7_3T_DrawIndexedPrimitive(LPDIRECT3DDEVICE7 iface,
1352 D3DPRIMITIVETYPE d3dptPrimitiveType,
1353 DWORD d3dvtVertexType,
1354 LPVOID lpvVertices,
1355 DWORD dwVertexCount,
1356 LPWORD dwIndices,
1357 DWORD dwIndexCount,
1358 DWORD dwFlags)
1360 ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice7, iface);
1361 D3DDRAWPRIMITIVESTRIDEDDATA strided;
1363 TRACE("(%p/%p)->(%08x,%08lx,%p,%08lx,%p,%08lx,%08lx)\n", This, iface, d3dptPrimitiveType, d3dvtVertexType, lpvVertices, dwVertexCount, dwIndices, dwIndexCount, dwFlags);
1364 if (TRACE_ON(ddraw)) {
1365 TRACE(" - flags : "); dump_DPFLAGS(dwFlags);
1368 convert_FVF_to_strided_data(d3dvtVertexType, lpvVertices, &strided, 0);
1369 draw_primitive_strided(This, d3dptPrimitiveType, d3dvtVertexType, &strided, dwVertexCount, dwIndices, dwIndexCount, dwFlags);
1371 return DD_OK;
1374 HRESULT WINAPI
1375 GL_IDirect3DDeviceImpl_7_3T_DrawPrimitiveStrided(LPDIRECT3DDEVICE7 iface,
1376 D3DPRIMITIVETYPE d3dptPrimitiveType,
1377 DWORD dwVertexType,
1378 LPD3DDRAWPRIMITIVESTRIDEDDATA lpD3DDrawPrimStrideData,
1379 DWORD dwVertexCount,
1380 DWORD dwFlags)
1382 ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice7, iface);
1384 TRACE("(%p/%p)->(%08x,%08lx,%p,%08lx,%08lx)\n", This, iface, d3dptPrimitiveType, dwVertexType, lpD3DDrawPrimStrideData, dwVertexCount, dwFlags);
1385 if (TRACE_ON(ddraw)) {
1386 TRACE(" - flags : "); dump_DPFLAGS(dwFlags);
1388 draw_primitive_strided(This, d3dptPrimitiveType, dwVertexType, lpD3DDrawPrimStrideData, dwVertexCount, NULL, dwVertexCount, dwFlags);
1390 return DD_OK;
1393 HRESULT WINAPI
1394 GL_IDirect3DDeviceImpl_7_3T_DrawIndexedPrimitiveStrided(LPDIRECT3DDEVICE7 iface,
1395 D3DPRIMITIVETYPE d3dptPrimitiveType,
1396 DWORD dwVertexType,
1397 LPD3DDRAWPRIMITIVESTRIDEDDATA lpD3DDrawPrimStrideData,
1398 DWORD dwVertexCount,
1399 LPWORD lpIndex,
1400 DWORD dwIndexCount,
1401 DWORD dwFlags)
1403 ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice7, iface);
1405 TRACE("(%p/%p)->(%08x,%08lx,%p,%08lx,%p,%08lx,%08lx)\n", This, iface, d3dptPrimitiveType, dwVertexType, lpD3DDrawPrimStrideData, dwVertexCount, lpIndex, dwIndexCount, dwFlags);
1406 if (TRACE_ON(ddraw)) {
1407 TRACE(" - flags : "); dump_DPFLAGS(dwFlags);
1410 draw_primitive_strided(This, d3dptPrimitiveType, dwVertexType, lpD3DDrawPrimStrideData, dwVertexCount, lpIndex, dwIndexCount, dwFlags);
1412 return DD_OK;
1415 HRESULT WINAPI
1416 GL_IDirect3DDeviceImpl_7_3T_DrawPrimitiveVB(LPDIRECT3DDEVICE7 iface,
1417 D3DPRIMITIVETYPE d3dptPrimitiveType,
1418 LPDIRECT3DVERTEXBUFFER7 lpD3DVertexBuf,
1419 DWORD dwStartVertex,
1420 DWORD dwNumVertices,
1421 DWORD dwFlags)
1423 ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice7, iface);
1424 IDirect3DVertexBufferImpl *vb_impl = ICOM_OBJECT(IDirect3DVertexBufferImpl, IDirect3DVertexBuffer7, lpD3DVertexBuf);
1425 D3DDRAWPRIMITIVESTRIDEDDATA strided;
1427 TRACE("(%p/%p)->(%08x,%p,%08lx,%08lx,%08lx)\n", This, iface, d3dptPrimitiveType, lpD3DVertexBuf, dwStartVertex, dwNumVertices, dwFlags);
1428 if (TRACE_ON(ddraw)) {
1429 TRACE(" - flags : "); dump_DPFLAGS(dwFlags);
1432 if (vb_impl->processed == TRUE) {
1433 IDirect3DVertexBufferGLImpl *vb_glimp = (IDirect3DVertexBufferGLImpl *) vb_impl;
1434 IDirect3DDeviceGLImpl *glThis = (IDirect3DDeviceGLImpl *) This;
1436 glThis->transform_state = GL_TRANSFORM_VERTEXBUFFER;
1437 This->set_matrices(This, VIEWMAT_CHANGED|WORLDMAT_CHANGED|PROJMAT_CHANGED,
1438 &(vb_glimp->world_mat), &(vb_glimp->view_mat), &(vb_glimp->proj_mat));
1440 convert_FVF_to_strided_data(vb_glimp->dwVertexTypeDesc, vb_glimp->vertices, &strided, dwStartVertex);
1441 draw_primitive_strided(This, d3dptPrimitiveType, vb_glimp->dwVertexTypeDesc, &strided, dwNumVertices, NULL, dwNumVertices, dwFlags);
1443 } else {
1444 convert_FVF_to_strided_data(vb_impl->desc.dwFVF, vb_impl->vertices, &strided, dwStartVertex);
1445 draw_primitive_strided(This, d3dptPrimitiveType, vb_impl->desc.dwFVF, &strided, dwNumVertices, NULL, dwNumVertices, dwFlags);
1448 return DD_OK;
1451 HRESULT WINAPI
1452 GL_IDirect3DDeviceImpl_7_3T_DrawIndexedPrimitiveVB(LPDIRECT3DDEVICE7 iface,
1453 D3DPRIMITIVETYPE d3dptPrimitiveType,
1454 LPDIRECT3DVERTEXBUFFER7 lpD3DVertexBuf,
1455 DWORD dwStartVertex,
1456 DWORD dwNumVertices,
1457 LPWORD lpwIndices,
1458 DWORD dwIndexCount,
1459 DWORD dwFlags)
1461 ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice7, iface);
1462 IDirect3DVertexBufferImpl *vb_impl = ICOM_OBJECT(IDirect3DVertexBufferImpl, IDirect3DVertexBuffer7, lpD3DVertexBuf);
1463 D3DDRAWPRIMITIVESTRIDEDDATA strided;
1465 TRACE("(%p/%p)->(%08x,%p,%08lx,%08lx,%p,%08lx,%08lx)\n", This, iface, d3dptPrimitiveType, lpD3DVertexBuf, dwStartVertex, dwNumVertices, lpwIndices, dwIndexCount, dwFlags);
1466 if (TRACE_ON(ddraw)) {
1467 TRACE(" - flags : "); dump_DPFLAGS(dwFlags);
1470 if (vb_impl->processed == TRUE) {
1471 IDirect3DVertexBufferGLImpl *vb_glimp = (IDirect3DVertexBufferGLImpl *) vb_impl;
1472 IDirect3DDeviceGLImpl *glThis = (IDirect3DDeviceGLImpl *) This;
1474 glThis->transform_state = GL_TRANSFORM_VERTEXBUFFER;
1475 This->set_matrices(This, VIEWMAT_CHANGED|WORLDMAT_CHANGED|PROJMAT_CHANGED,
1476 &(vb_glimp->world_mat), &(vb_glimp->view_mat), &(vb_glimp->proj_mat));
1478 convert_FVF_to_strided_data(vb_glimp->dwVertexTypeDesc, vb_glimp->vertices, &strided, dwStartVertex);
1479 draw_primitive_strided(This, d3dptPrimitiveType, vb_glimp->dwVertexTypeDesc, &strided, dwNumVertices, lpwIndices, dwIndexCount, dwFlags);
1481 } else {
1482 convert_FVF_to_strided_data(vb_impl->desc.dwFVF, vb_impl->vertices, &strided, dwStartVertex);
1483 draw_primitive_strided(This, d3dptPrimitiveType, vb_impl->desc.dwFVF, &strided, dwNumVertices, lpwIndices, dwIndexCount, dwFlags);
1486 return DD_OK;
1489 static GLenum
1490 convert_min_filter_to_GL(D3DTEXTUREMINFILTER dwMinState, D3DTEXTUREMIPFILTER dwMipState)
1492 GLenum gl_state;
1494 if (dwMipState == D3DTFP_NONE) {
1495 switch (dwMinState) {
1496 case D3DTFN_POINT: gl_state = GL_NEAREST; break;
1497 case D3DTFN_LINEAR: gl_state = GL_LINEAR; break;
1498 default: gl_state = GL_LINEAR; break;
1500 } else if (dwMipState == D3DTFP_POINT) {
1501 switch (dwMinState) {
1502 case D3DTFN_POINT: gl_state = GL_NEAREST_MIPMAP_NEAREST; break;
1503 case D3DTFN_LINEAR: gl_state = GL_LINEAR_MIPMAP_NEAREST; break;
1504 default: gl_state = GL_LINEAR_MIPMAP_NEAREST; break;
1506 } else {
1507 switch (dwMinState) {
1508 case D3DTFN_POINT: gl_state = GL_NEAREST_MIPMAP_LINEAR; break;
1509 case D3DTFN_LINEAR: gl_state = GL_LINEAR_MIPMAP_LINEAR; break;
1510 default: gl_state = GL_LINEAR_MIPMAP_LINEAR; break;
1513 return gl_state;
1516 static GLenum
1517 convert_mag_filter_to_GL(D3DTEXTUREMAGFILTER dwState)
1519 GLenum gl_state;
1521 switch (dwState) {
1522 case D3DTFG_POINT:
1523 gl_state = GL_NEAREST;
1524 break;
1525 case D3DTFG_LINEAR:
1526 gl_state = GL_LINEAR;
1527 break;
1528 default:
1529 gl_state = GL_LINEAR;
1530 break;
1532 return gl_state;
1535 /* We need a static function for that to handle the 'special' case of 'SELECT_ARG2' */
1536 static BOOLEAN
1537 handle_color_alpha_args(IDirect3DDeviceImpl *This, DWORD dwStage, D3DTEXTURESTAGESTATETYPE d3dTexStageStateType, DWORD dwState, D3DTEXTUREOP tex_op)
1539 BOOLEAN is_complement = FALSE;
1540 BOOLEAN is_alpha_replicate = FALSE;
1541 BOOLEAN handled = TRUE;
1542 GLenum src;
1543 BOOLEAN is_color = ((d3dTexStageStateType == D3DTSS_COLORARG1) || (d3dTexStageStateType == D3DTSS_COLORARG2));
1544 int num;
1546 if (is_color) {
1547 if (d3dTexStageStateType == D3DTSS_COLORARG1) num = 0;
1548 else if (d3dTexStageStateType == D3DTSS_COLORARG2) num = 1;
1549 else {
1550 handled = FALSE;
1551 num = 0;
1553 if (tex_op == D3DTOP_SELECTARG2) {
1554 num = 1 - num;
1556 } else {
1557 if (d3dTexStageStateType == D3DTSS_ALPHAARG1) num = 0;
1558 else if (d3dTexStageStateType == D3DTSS_ALPHAARG2) num = 1;
1559 else {
1560 handled = FALSE;
1561 num = 0;
1563 if (tex_op == D3DTOP_SELECTARG2) {
1564 num = 1 - num;
1568 if (dwState & D3DTA_COMPLEMENT) {
1569 is_complement = TRUE;
1571 if (dwState & D3DTA_ALPHAREPLICATE) {
1572 is_alpha_replicate = TRUE;
1574 dwState &= D3DTA_SELECTMASK;
1575 if ((dwStage == 0) && (dwState == D3DTA_CURRENT)) {
1576 dwState = D3DTA_DIFFUSE;
1579 switch (dwState) {
1580 case D3DTA_CURRENT: src = GL_PREVIOUS_EXT; break;
1581 case D3DTA_DIFFUSE: src = GL_PRIMARY_COLOR_EXT; break;
1582 case D3DTA_TEXTURE: src = GL_TEXTURE; break;
1583 case D3DTA_TFACTOR: {
1584 /* Get the constant value from the current rendering state */
1585 GLfloat color[4];
1586 DWORD col = This->state_block.render_state[D3DRENDERSTATE_TEXTUREFACTOR - 1];
1588 color[0] = ((col >> 16) & 0xFF) / 255.0f;
1589 color[1] = ((col >> 8) & 0xFF) / 255.0f;
1590 color[2] = ((col >> 0) & 0xFF) / 255.0f;
1591 color[3] = ((col >> 24) & 0xFF) / 255.0f;
1592 glTexEnvfv(GL_TEXTURE_ENV, GL_TEXTURE_ENV_COLOR, color);
1594 src = GL_CONSTANT_EXT;
1595 } break;
1596 default: src = GL_TEXTURE; handled = FALSE; break;
1599 if (is_color) {
1600 glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_RGB_EXT + num, src);
1601 if (is_alpha_replicate) {
1602 glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND0_RGB_EXT + num, is_complement ? GL_ONE_MINUS_SRC_ALPHA : GL_SRC_ALPHA);
1603 } else {
1604 glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND0_RGB_EXT + num, is_complement ? GL_ONE_MINUS_SRC_COLOR : GL_SRC_COLOR);
1606 } else {
1607 glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_ALPHA_EXT + num, src);
1608 glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND0_ALPHA_EXT + num, is_complement ? GL_ONE_MINUS_SRC_ALPHA : GL_SRC_ALPHA);
1611 return handled;
1614 HRESULT WINAPI
1615 GL_IDirect3DDeviceImpl_7_3T_SetTextureStageState(LPDIRECT3DDEVICE7 iface,
1616 DWORD dwStage,
1617 D3DTEXTURESTAGESTATETYPE d3dTexStageStateType,
1618 DWORD dwState)
1620 ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice7, iface);
1621 const char *type;
1622 DWORD prev_state;
1624 TRACE("(%p/%p)->(%08lx,%08x,%08lx)\n", This, iface, dwStage, d3dTexStageStateType, dwState);
1626 if (dwStage > 0) return DD_OK; /* We nothing in this case for now */
1628 switch (d3dTexStageStateType) {
1629 #define GEN_CASE(a) case a: type = #a; break
1630 GEN_CASE(D3DTSS_COLOROP);
1631 GEN_CASE(D3DTSS_COLORARG1);
1632 GEN_CASE(D3DTSS_COLORARG2);
1633 GEN_CASE(D3DTSS_ALPHAOP);
1634 GEN_CASE(D3DTSS_ALPHAARG1);
1635 GEN_CASE(D3DTSS_ALPHAARG2);
1636 GEN_CASE(D3DTSS_BUMPENVMAT00);
1637 GEN_CASE(D3DTSS_BUMPENVMAT01);
1638 GEN_CASE(D3DTSS_BUMPENVMAT10);
1639 GEN_CASE(D3DTSS_BUMPENVMAT11);
1640 GEN_CASE(D3DTSS_TEXCOORDINDEX);
1641 GEN_CASE(D3DTSS_ADDRESS);
1642 GEN_CASE(D3DTSS_ADDRESSU);
1643 GEN_CASE(D3DTSS_ADDRESSV);
1644 GEN_CASE(D3DTSS_BORDERCOLOR);
1645 GEN_CASE(D3DTSS_MAGFILTER);
1646 GEN_CASE(D3DTSS_MINFILTER);
1647 GEN_CASE(D3DTSS_MIPFILTER);
1648 GEN_CASE(D3DTSS_MIPMAPLODBIAS);
1649 GEN_CASE(D3DTSS_MAXMIPLEVEL);
1650 GEN_CASE(D3DTSS_MAXANISOTROPY);
1651 GEN_CASE(D3DTSS_BUMPENVLSCALE);
1652 GEN_CASE(D3DTSS_BUMPENVLOFFSET);
1653 GEN_CASE(D3DTSS_TEXTURETRANSFORMFLAGS);
1654 #undef GEN_CASE
1655 default: type = "UNKNOWN";
1658 /* Store the values in the state array */
1659 prev_state = This->state_block.texture_stage_state[dwStage][d3dTexStageStateType - 1];
1660 This->state_block.texture_stage_state[dwStage][d3dTexStageStateType - 1] = dwState;
1661 /* Some special cases when one state modifies more than one... */
1662 if (d3dTexStageStateType == D3DTSS_ADDRESS) {
1663 This->state_block.texture_stage_state[dwStage][D3DTSS_ADDRESSU - 1] = dwState;
1664 This->state_block.texture_stage_state[dwStage][D3DTSS_ADDRESSV - 1] = dwState;
1667 ENTER_GL();
1669 switch (d3dTexStageStateType) {
1670 case D3DTSS_MINFILTER:
1671 case D3DTSS_MIPFILTER:
1672 if (TRACE_ON(ddraw)) {
1673 if (d3dTexStageStateType == D3DTSS_MINFILTER) {
1674 switch ((D3DTEXTUREMINFILTER) dwState) {
1675 case D3DTFN_POINT: TRACE(" Stage type is : D3DTSS_MINFILTER => D3DTFN_POINT\n"); break;
1676 case D3DTFN_LINEAR: TRACE(" Stage type is : D3DTSS_MINFILTER => D3DTFN_LINEAR\n"); break;
1677 default: FIXME(" Unhandled stage type : D3DTSS_MINFILTER => %08lx\n", dwState); break;
1679 } else {
1680 switch ((D3DTEXTUREMIPFILTER) dwState) {
1681 case D3DTFP_NONE: TRACE(" Stage type is : D3DTSS_MIPFILTER => D3DTFP_NONE\n"); break;
1682 case D3DTFP_POINT: TRACE(" Stage type is : D3DTSS_MIPFILTER => D3DTFP_POINT\n"); break;
1683 case D3DTFP_LINEAR: TRACE(" Stage type is : D3DTSS_MIPFILTER => D3DTFP_LINEAR\n"); break;
1684 default: FIXME(" Unhandled stage type : D3DTSS_MIPFILTER => %08lx\n", dwState); break;
1689 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER,
1690 convert_min_filter_to_GL(This->state_block.texture_stage_state[dwStage][D3DTSS_MINFILTER - 1],
1691 This->state_block.texture_stage_state[dwStage][D3DTSS_MIPFILTER - 1]));
1692 break;
1694 case D3DTSS_MAGFILTER:
1695 if (TRACE_ON(ddraw)) {
1696 switch ((D3DTEXTUREMAGFILTER) dwState) {
1697 case D3DTFG_POINT: TRACE(" Stage type is : D3DTSS_MAGFILTER => D3DTFN_POINT\n"); break;
1698 case D3DTFG_LINEAR: TRACE(" Stage type is : D3DTSS_MAGFILTER => D3DTFN_LINEAR\n"); break;
1699 default: FIXME(" Unhandled stage type : D3DTSS_MAGFILTER => %08lx\n", dwState); break;
1702 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, convert_mag_filter_to_GL(dwState));
1703 break;
1705 case D3DTSS_ADDRESS:
1706 case D3DTSS_ADDRESSU:
1707 case D3DTSS_ADDRESSV: {
1708 GLenum arg = GL_REPEAT; /* Default value */
1709 switch ((D3DTEXTUREADDRESS) dwState) {
1710 case D3DTADDRESS_WRAP: TRACE(" Stage type is : %s => D3DTADDRESS_WRAP\n", type); arg = GL_REPEAT; break;
1711 case D3DTADDRESS_CLAMP: TRACE(" Stage type is : %s => D3DTADDRESS_CLAMP\n", type); arg = GL_CLAMP; break;
1712 case D3DTADDRESS_BORDER: TRACE(" Stage type is : %s => D3DTADDRESS_BORDER\n", type); arg = GL_CLAMP_TO_EDGE; break;
1713 #if defined(GL_VERSION_1_4)
1714 case D3DTADDRESS_MIRROR: TRACE(" Stage type is : %s => D3DTADDRESS_MIRROR\n", type); arg = GL_MIRRORED_REPEAT; break;
1715 #elif defined(GL_ARB_texture_mirrored_repeat)
1716 case D3DTADDRESS_MIRROR: TRACE(" Stage type is : %s => D3DTADDRESS_MIRROR\n", type); arg = GL_MIRRORED_REPEAT_ARB; break;
1717 #endif
1718 default: FIXME(" Unhandled stage type : %s => %08lx\n", type, dwState); break;
1720 if ((d3dTexStageStateType == D3DTSS_ADDRESS) ||
1721 (d3dTexStageStateType == D3DTSS_ADDRESSU))
1722 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, arg);
1723 if ((d3dTexStageStateType == D3DTSS_ADDRESS) ||
1724 (d3dTexStageStateType == D3DTSS_ADDRESSV))
1725 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, arg);
1726 } break;
1728 case D3DTSS_ALPHAOP:
1729 case D3DTSS_COLOROP: {
1730 int scale = 1;
1731 GLenum parm = (d3dTexStageStateType == D3DTSS_ALPHAOP) ? GL_COMBINE_ALPHA_EXT : GL_COMBINE_RGB_EXT;
1732 const char *value;
1733 int handled = 1;
1735 switch (dwState) {
1736 #define GEN_CASE(a) case a: value = #a; break
1737 GEN_CASE(D3DTOP_DISABLE);
1738 GEN_CASE(D3DTOP_SELECTARG1);
1739 GEN_CASE(D3DTOP_SELECTARG2);
1740 GEN_CASE(D3DTOP_MODULATE);
1741 GEN_CASE(D3DTOP_MODULATE2X);
1742 GEN_CASE(D3DTOP_MODULATE4X);
1743 GEN_CASE(D3DTOP_ADD);
1744 GEN_CASE(D3DTOP_ADDSIGNED);
1745 GEN_CASE(D3DTOP_ADDSIGNED2X);
1746 GEN_CASE(D3DTOP_SUBTRACT);
1747 GEN_CASE(D3DTOP_ADDSMOOTH);
1748 GEN_CASE(D3DTOP_BLENDDIFFUSEALPHA);
1749 GEN_CASE(D3DTOP_BLENDTEXTUREALPHA);
1750 GEN_CASE(D3DTOP_BLENDFACTORALPHA);
1751 GEN_CASE(D3DTOP_BLENDTEXTUREALPHAPM);
1752 GEN_CASE(D3DTOP_BLENDCURRENTALPHA);
1753 GEN_CASE(D3DTOP_PREMODULATE);
1754 GEN_CASE(D3DTOP_MODULATEALPHA_ADDCOLOR);
1755 GEN_CASE(D3DTOP_MODULATECOLOR_ADDALPHA);
1756 GEN_CASE(D3DTOP_MODULATEINVALPHA_ADDCOLOR);
1757 GEN_CASE(D3DTOP_MODULATEINVCOLOR_ADDALPHA);
1758 GEN_CASE(D3DTOP_BUMPENVMAP);
1759 GEN_CASE(D3DTOP_BUMPENVMAPLUMINANCE);
1760 GEN_CASE(D3DTOP_DOTPRODUCT3);
1761 GEN_CASE(D3DTOP_FORCE_DWORD);
1762 #undef GEN_CASE
1763 default: value = "UNKNOWN";
1766 if ((d3dTexStageStateType == D3DTSS_COLOROP) && (dwState == D3DTOP_DISABLE) && (dwStage == 0)) {
1767 glDisable(GL_TEXTURE_2D);
1768 TRACE(" disabling 2D texturing.\n");
1769 } else {
1770 /* Re-enable texturing */
1771 if ((dwStage == 0) && (This->current_texture[0] != NULL)) {
1772 glEnable(GL_TEXTURE_2D);
1773 TRACE(" enabling 2D texturing.\n");
1776 /* Re-Enable GL_TEXTURE_ENV_MODE, GL_COMBINE_EXT */
1777 if (dwState != D3DTOP_DISABLE) {
1778 glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE_EXT);
1781 /* Now set up the operand correctly */
1782 switch (dwState) {
1783 case D3DTOP_DISABLE:
1784 /* Contrary to the docs, alpha can be disabled when colorop is enabled
1785 and it works, so ignore this op */
1786 TRACE(" Note : disable ALPHAOP but COLOROP enabled!\n");
1787 break;
1789 case D3DTOP_SELECTARG1:
1790 case D3DTOP_SELECTARG2:
1791 glTexEnvi(GL_TEXTURE_ENV, parm, GL_REPLACE);
1792 break;
1794 case D3DTOP_MODULATE4X:
1795 scale = scale * 2; /* Drop through */
1796 case D3DTOP_MODULATE2X:
1797 scale = scale * 2; /* Drop through */
1798 case D3DTOP_MODULATE:
1799 glTexEnvi(GL_TEXTURE_ENV, parm, GL_MODULATE);
1800 break;
1802 case D3DTOP_ADD:
1803 glTexEnvi(GL_TEXTURE_ENV, parm, GL_ADD);
1804 break;
1806 case D3DTOP_ADDSIGNED2X:
1807 scale = scale * 2; /* Drop through */
1808 case D3DTOP_ADDSIGNED:
1809 glTexEnvi(GL_TEXTURE_ENV, parm, GL_ADD_SIGNED_EXT);
1810 break;
1812 /* For the four blending modes, use the Arg2 parameter */
1813 case D3DTOP_BLENDDIFFUSEALPHA:
1814 case D3DTOP_BLENDTEXTUREALPHA:
1815 case D3DTOP_BLENDFACTORALPHA:
1816 case D3DTOP_BLENDCURRENTALPHA: {
1817 GLenum src = GL_PRIMARY_COLOR_EXT; /* Just to prevent a compiler warning.. */
1819 switch (dwState) {
1820 case D3DTOP_BLENDDIFFUSEALPHA: src = GL_PRIMARY_COLOR_EXT;
1821 case D3DTOP_BLENDTEXTUREALPHA: src = GL_TEXTURE;
1822 case D3DTOP_BLENDFACTORALPHA: src = GL_CONSTANT_EXT;
1823 case D3DTOP_BLENDCURRENTALPHA: src = GL_PREVIOUS_EXT;
1826 glTexEnvi(GL_TEXTURE_ENV, parm, GL_INTERPOLATE_EXT);
1827 glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE2_RGB_EXT, src);
1828 glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND2_RGB_EXT, GL_SRC_ALPHA);
1829 glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE2_ALPHA_EXT, src);
1830 glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND2_ALPHA_EXT, GL_SRC_ALPHA);
1831 } break;
1833 default:
1834 handled = FALSE;
1835 break;
1839 if (((prev_state == D3DTOP_SELECTARG2) && (dwState != D3DTOP_SELECTARG2)) ||
1840 ((dwState == D3DTOP_SELECTARG2) && (prev_state != D3DTOP_SELECTARG2))) {
1841 /* Switch the arguments if needed... */
1842 if (d3dTexStageStateType == D3DTSS_COLOROP) {
1843 handle_color_alpha_args(This, dwStage, D3DTSS_COLORARG1,
1844 This->state_block.texture_stage_state[dwStage][D3DTSS_COLORARG1 - 1],
1845 dwState);
1846 handle_color_alpha_args(This, dwStage, D3DTSS_COLORARG2,
1847 This->state_block.texture_stage_state[dwStage][D3DTSS_COLORARG2 - 1],
1848 dwState);
1849 } else {
1850 handle_color_alpha_args(This, dwStage, D3DTSS_ALPHAARG1,
1851 This->state_block.texture_stage_state[dwStage][D3DTSS_ALPHAARG1 - 1],
1852 dwState);
1853 handle_color_alpha_args(This, dwStage, D3DTSS_ALPHAARG2,
1854 This->state_block.texture_stage_state[dwStage][D3DTSS_ALPHAARG2 - 1],
1855 dwState);
1859 if (handled) {
1860 if (d3dTexStageStateType == D3DTSS_ALPHAOP) {
1861 glTexEnvi(GL_TEXTURE_ENV, GL_ALPHA_SCALE, scale);
1862 } else {
1863 glTexEnvi(GL_TEXTURE_ENV, GL_RGB_SCALE_EXT, scale);
1865 TRACE(" Stage type is : %s => %s\n", type, value);
1866 } else {
1867 FIXME(" Unhandled stage type is : %s => %s\n", type, value);
1869 } break;
1871 case D3DTSS_COLORARG1:
1872 case D3DTSS_COLORARG2:
1873 case D3DTSS_ALPHAARG1:
1874 case D3DTSS_ALPHAARG2: {
1875 const char *value, *value_comp = "", *value_alpha = "";
1876 BOOLEAN handled;
1877 D3DTEXTUREOP tex_op;
1879 switch (dwState & D3DTA_SELECTMASK) {
1880 #define GEN_CASE(a) case a: value = #a; break
1881 GEN_CASE(D3DTA_DIFFUSE);
1882 GEN_CASE(D3DTA_CURRENT);
1883 GEN_CASE(D3DTA_TEXTURE);
1884 GEN_CASE(D3DTA_TFACTOR);
1885 GEN_CASE(D3DTA_SPECULAR);
1886 #undef GEN_CASE
1887 default: value = "UNKNOWN";
1889 if (dwState & D3DTA_COMPLEMENT) {
1890 value_comp = " | D3DTA_COMPLEMENT";
1892 if (dwState & D3DTA_ALPHAREPLICATE) {
1893 value_alpha = " | D3DTA_ALPHAREPLICATE";
1896 if ((d3dTexStageStateType == D3DTSS_COLORARG1) || (d3dTexStageStateType == D3DTSS_COLORARG2)) {
1897 tex_op = This->state_block.texture_stage_state[dwStage][D3DTSS_COLOROP - 1];
1898 } else {
1899 tex_op = This->state_block.texture_stage_state[dwStage][D3DTSS_ALPHAOP - 1];
1902 handled = handle_color_alpha_args(This, dwStage, d3dTexStageStateType, dwState, tex_op);
1904 if (handled) {
1905 TRACE(" Stage type : %s => %s%s%s\n", type, value, value_comp, value_alpha);
1906 } else {
1907 FIXME(" Unhandled stage type : %s => %s%s%s\n", type, value, value_comp, value_alpha);
1909 } break;
1911 case D3DTSS_MIPMAPLODBIAS: {
1912 D3DVALUE value = *((D3DVALUE *) &dwState);
1913 BOOLEAN handled = TRUE;
1915 if (value != 0.0)
1916 handled = FALSE;
1918 if (handled) {
1919 TRACE(" Stage type : D3DTSS_MIPMAPLODBIAS => %f\n", value);
1920 } else {
1921 FIXME(" Unhandled stage type : D3DTSS_MIPMAPLODBIAS => %f\n", value);
1923 } break;
1925 case D3DTSS_MAXMIPLEVEL:
1926 if (dwState == 0) {
1927 TRACE(" Stage type : D3DTSS_MAXMIPLEVEL => 0 (disabled) \n");
1928 } else {
1929 FIXME(" Unhandled stage type : D3DTSS_MAXMIPLEVEL => %ld\n", dwState);
1931 break;
1933 case D3DTSS_BORDERCOLOR: {
1934 GLfloat color[4];
1936 color[0] = ((dwState >> 16) & 0xFF) / 255.0;
1937 color[1] = ((dwState >> 8) & 0xFF) / 255.0;
1938 color[2] = ((dwState >> 0) & 0xFF) / 255.0;
1939 color[3] = ((dwState >> 24) & 0xFF) / 255.0;
1941 glTexParameterfv(GL_TEXTURE_2D, GL_TEXTURE_BORDER_COLOR, color);
1943 TRACE(" Stage type : D3DTSS_BORDERCOLOR => %02lx %02lx %02lx %02lx (RGBA)\n",
1944 ((dwState >> 16) & 0xFF),
1945 ((dwState >> 8) & 0xFF),
1946 ((dwState >> 0) & 0xFF),
1947 ((dwState >> 24) & 0xFF));
1948 } break;
1950 case D3DTSS_TEXCOORDINDEX: {
1951 BOOLEAN handled = TRUE;
1952 const char *value;
1954 switch (dwState & 0xFFFF0000) {
1955 #define GEN_CASE(a) case a: value = #a; break
1956 GEN_CASE(D3DTSS_TCI_PASSTHRU);
1957 GEN_CASE(D3DTSS_TCI_CAMERASPACENORMAL);
1958 GEN_CASE(D3DTSS_TCI_CAMERASPACEPOSITION);
1959 GEN_CASE(D3DTSS_TCI_CAMERASPACEREFLECTIONVECTOR);
1960 #undef GEN_CASE
1961 default: value = "UNKNOWN";
1963 if ((dwState & 0xFFFF0000) != D3DTSS_TCI_PASSTHRU)
1964 handled = FALSE;
1966 if (handled) {
1967 TRACE(" Stage type : D3DTSS_TEXCOORDINDEX => %ld | %s\n", dwState & 0x0000FFFF, value);
1968 } else {
1969 FIXME(" Unhandled stage type : D3DTSS_TEXCOORDINDEX => %ld | %s\n", dwState & 0x0000FFFF, value);
1971 } break;
1973 case D3DTSS_TEXTURETRANSFORMFLAGS: {
1974 const char *projected = "", *value;
1975 BOOLEAN handled = TRUE;
1976 switch (dwState & 0xFF) {
1977 #define GEN_CASE(a) case a: value = #a; break
1978 GEN_CASE(D3DTTFF_DISABLE);
1979 GEN_CASE(D3DTTFF_COUNT1);
1980 GEN_CASE(D3DTTFF_COUNT2);
1981 GEN_CASE(D3DTTFF_COUNT3);
1982 GEN_CASE(D3DTTFF_COUNT4);
1983 #undef GEN_CASE
1984 default: value = "UNKNOWN";
1986 if (dwState & D3DTTFF_PROJECTED) {
1987 projected = " | D3DTTFF_PROJECTED";
1988 handled = FALSE;
1991 if ((dwState & 0xFF) != D3DTTFF_DISABLE) {
1992 This->matrices_updated(This, TEXMAT0_CHANGED << dwStage);
1995 if (handled == TRUE) {
1996 TRACE(" Stage type : D3DTSS_TEXTURETRANSFORMFLAGS => %s%s\n", value, projected);
1997 } else {
1998 FIXME(" Unhandled stage type : D3DTSS_TEXTURETRANSFORMFLAGS => %s%s\n", value, projected);
2000 } break;
2002 default:
2003 FIXME(" Unhandled stage type : %s => %08lx\n", type, dwState);
2004 break;
2007 LEAVE_GL();
2009 return DD_OK;
2012 HRESULT WINAPI
2013 GL_IDirect3DDeviceImpl_7_3T_SetTexture(LPDIRECT3DDEVICE7 iface,
2014 DWORD dwStage,
2015 LPDIRECTDRAWSURFACE7 lpTexture2)
2017 ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice7, iface);
2019 TRACE("(%p/%p)->(%08lx,%p)\n", This, iface, dwStage, lpTexture2);
2021 if (dwStage > 0) return DD_OK;
2023 if (This->current_texture[dwStage] != NULL) {
2024 IDirectDrawSurface7_Release(ICOM_INTERFACE(This->current_texture[dwStage], IDirectDrawSurface7));
2027 ENTER_GL();
2028 if (lpTexture2 == NULL) {
2029 This->current_texture[dwStage] = NULL;
2031 TRACE(" disabling 2D texturing.\n");
2032 glBindTexture(GL_TEXTURE_2D, 0);
2033 glDisable(GL_TEXTURE_2D);
2034 } else {
2035 IDirectDrawSurfaceImpl *tex_impl = ICOM_OBJECT(IDirectDrawSurfaceImpl, IDirectDrawSurface7, lpTexture2);
2036 GLint max_mip_level;
2038 This->current_texture[dwStage] = tex_impl;
2039 IDirectDrawSurface7_AddRef(ICOM_INTERFACE(tex_impl, IDirectDrawSurface7)); /* Not sure about this either */
2041 if (This->state_block.texture_stage_state[dwStage][D3DTSS_COLOROP - 1] != D3DTOP_DISABLE) {
2042 /* Do not re-enable texturing if it was disabled due to the COLOROP code */
2043 glEnable(GL_TEXTURE_2D);
2044 TRACE(" enabling 2D texturing.\n");
2046 gltex_upload_texture(tex_impl);
2048 if ((tex_impl->surface_desc.ddsCaps.dwCaps & DDSCAPS_MIPMAP) == 0) {
2049 max_mip_level = 0;
2050 } else {
2051 max_mip_level = tex_impl->surface_desc.u2.dwMipMapCount - 1;
2054 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER,
2055 convert_mag_filter_to_GL(This->state_block.texture_stage_state[dwStage][D3DTSS_MAGFILTER - 1]));
2056 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER,
2057 convert_min_filter_to_GL(This->state_block.texture_stage_state[dwStage][D3DTSS_MINFILTER - 1],
2058 This->state_block.texture_stage_state[dwStage][D3DTSS_MIPFILTER - 1]));
2059 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LEVEL, max_mip_level);
2061 LEAVE_GL();
2063 return DD_OK;
2066 HRESULT WINAPI
2067 GL_IDirect3DDeviceImpl_7_GetCaps(LPDIRECT3DDEVICE7 iface,
2068 LPD3DDEVICEDESC7 lpD3DHELDevDesc)
2070 ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice7, iface);
2071 TRACE("(%p/%p)->(%p)\n", This, iface, lpD3DHELDevDesc);
2073 fill_opengl_caps_7(lpD3DHELDevDesc);
2075 TRACE(" returning caps : no dump function yet.\n");
2077 return DD_OK;
2080 HRESULT WINAPI
2081 GL_IDirect3DDeviceImpl_7_SetMaterial(LPDIRECT3DDEVICE7 iface,
2082 LPD3DMATERIAL7 lpMat)
2084 ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice7, iface);
2085 TRACE("(%p/%p)->(%p)\n", This, iface, lpMat);
2087 if (TRACE_ON(ddraw)) {
2088 TRACE(" material is : \n");
2089 dump_D3DMATERIAL7(lpMat);
2092 This->current_material = *lpMat;
2094 glMaterialfv(GL_FRONT_AND_BACK,
2095 GL_DIFFUSE,
2096 (float *) &(This->current_material.u.diffuse));
2097 glMaterialfv(GL_FRONT_AND_BACK,
2098 GL_AMBIENT,
2099 (float *) &(This->current_material.u1.ambient));
2100 glMaterialfv(GL_FRONT_AND_BACK,
2101 GL_SPECULAR,
2102 (float *) &(This->current_material.u2.specular));
2103 glMaterialfv(GL_FRONT_AND_BACK,
2104 GL_EMISSION,
2105 (float *) &(This->current_material.u3.emissive));
2106 glMaterialf(GL_FRONT_AND_BACK,
2107 GL_SHININESS,
2108 This->current_material.u4.power); /* Not sure about this... */
2110 return DD_OK;
2114 HRESULT WINAPI
2115 GL_IDirect3DDeviceImpl_7_SetLight(LPDIRECT3DDEVICE7 iface,
2116 DWORD dwLightIndex,
2117 LPD3DLIGHT7 lpLight)
2119 ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice7, iface);
2120 IDirect3DDeviceGLImpl *glThis = (IDirect3DDeviceGLImpl *) This;
2121 TRACE("(%p/%p)->(%08lx,%p)\n", This, iface, dwLightIndex, lpLight);
2123 if (TRACE_ON(ddraw)) {
2124 TRACE(" setting light : \n");
2125 dump_D3DLIGHT7(lpLight);
2128 if (dwLightIndex >= MAX_LIGHTS) return DDERR_INVALIDPARAMS;
2129 This->set_lights |= 0x00000001 << dwLightIndex;
2130 This->light_parameters[dwLightIndex] = *lpLight;
2132 /* Some checks to print out nice warnings :-) */
2133 switch (lpLight->dltType) {
2134 case D3DLIGHT_DIRECTIONAL:
2135 case D3DLIGHT_POINT:
2136 /* These are handled properly... */
2137 break;
2139 case D3DLIGHT_SPOT:
2140 if ((lpLight->dvTheta != 0.0) ||
2141 (lpLight->dvTheta != lpLight->dvPhi)) {
2142 ERR("dvTheta not fully supported yet !\n");
2144 break;
2146 default:
2147 ERR("Light type not handled yet : %08x !\n", lpLight->dltType);
2150 /* This will force the Light setting on next drawing of primitives */
2151 glThis->transform_state = GL_TRANSFORM_NONE;
2153 return DD_OK;
2156 HRESULT WINAPI
2157 GL_IDirect3DDeviceImpl_7_LightEnable(LPDIRECT3DDEVICE7 iface,
2158 DWORD dwLightIndex,
2159 BOOL bEnable)
2161 ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice7, iface);
2162 TRACE("(%p/%p)->(%08lx,%d)\n", This, iface, dwLightIndex, bEnable);
2164 if (dwLightIndex >= MAX_LIGHTS) return DDERR_INVALIDPARAMS;
2166 if (bEnable) {
2167 if (((0x00000001 << dwLightIndex) & This->set_lights) == 0) {
2168 /* Set the default parameters.. */
2169 TRACE(" setting default light parameters...\n");
2170 GL_IDirect3DDeviceImpl_7_SetLight(iface, dwLightIndex, &(This->light_parameters[dwLightIndex]));
2172 glEnable(GL_LIGHT0 + dwLightIndex);
2173 if ((This->active_lights & (0x00000001 << dwLightIndex)) == 0) {
2174 /* This light gets active... Need to update its parameters to GL before the next drawing */
2175 IDirect3DDeviceGLImpl *glThis = (IDirect3DDeviceGLImpl *) This;
2177 This->active_lights |= 0x00000001 << dwLightIndex;
2178 glThis->transform_state = GL_TRANSFORM_NONE;
2180 } else {
2181 glDisable(GL_LIGHT0 + dwLightIndex);
2182 This->active_lights &= ~(0x00000001 << dwLightIndex);
2185 return DD_OK;
2188 HRESULT WINAPI
2189 GL_IDirect3DDeviceImpl_7_SetClipPlane(LPDIRECT3DDEVICE7 iface, DWORD dwIndex, CONST D3DVALUE* pPlaneEquation)
2191 ICOM_THIS(IDirect3DDeviceImpl,iface);
2192 IDirect3DDeviceGLImpl* glThis = (IDirect3DDeviceGLImpl*) This;
2194 TRACE("(%p)->(%ld,%p)\n", This, dwIndex, pPlaneEquation);
2196 if (dwIndex >= This->max_clipping_planes) {
2197 return DDERR_INVALIDPARAMS;
2200 TRACE(" clip plane %ld : %f %f %f %f\n", dwIndex, pPlaneEquation[0], pPlaneEquation[1], pPlaneEquation[2], pPlaneEquation[3] );
2202 memcpy(This->clipping_planes[dwIndex].plane, pPlaneEquation, sizeof(D3DVALUE[4]));
2204 /* This is to force the reset of the transformation matrices on the next drawing.
2205 * This is needed to use the correct matrices for the various clipping planes.
2207 glThis->transform_state = GL_TRANSFORM_NONE;
2209 return D3D_OK;
2212 HRESULT WINAPI
2213 GL_IDirect3DDeviceImpl_7_SetViewport(LPDIRECT3DDEVICE7 iface,
2214 LPD3DVIEWPORT7 lpData)
2216 ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice7, iface);
2217 TRACE("(%p/%p)->(%p)\n", This, iface, lpData);
2219 if (TRACE_ON(ddraw)) {
2220 TRACE(" viewport is : \n");
2221 TRACE(" - dwX = %ld dwY = %ld\n",
2222 lpData->dwX, lpData->dwY);
2223 TRACE(" - dwWidth = %ld dwHeight = %ld\n",
2224 lpData->dwWidth, lpData->dwHeight);
2225 TRACE(" - dvMinZ = %f dvMaxZ = %f\n",
2226 lpData->dvMinZ, lpData->dvMaxZ);
2228 This->active_viewport = *lpData;
2230 ENTER_GL();
2232 /* Set the viewport */
2233 glDepthRange(lpData->dvMinZ, lpData->dvMaxZ);
2234 glViewport(lpData->dwX,
2235 This->surface->surface_desc.dwHeight - (lpData->dwHeight + lpData->dwY),
2236 lpData->dwWidth, lpData->dwHeight);
2238 LEAVE_GL();
2240 return DD_OK;
2243 #if !defined(__STRICT_ANSI__) && defined(__GNUC__)
2244 # define XCAST(fun) (typeof(VTABLE_IDirect3DDevice7.fun))
2245 #else
2246 # define XCAST(fun) (void*)
2247 #endif
2249 ICOM_VTABLE(IDirect3DDevice7) VTABLE_IDirect3DDevice7 =
2251 ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
2252 XCAST(QueryInterface) Main_IDirect3DDeviceImpl_7_3T_2T_1T_QueryInterface,
2253 XCAST(AddRef) Main_IDirect3DDeviceImpl_7_3T_2T_1T_AddRef,
2254 XCAST(Release) GL_IDirect3DDeviceImpl_7_3T_2T_1T_Release,
2255 XCAST(GetCaps) GL_IDirect3DDeviceImpl_7_GetCaps,
2256 XCAST(EnumTextureFormats) GL_IDirect3DDeviceImpl_7_3T_EnumTextureFormats,
2257 XCAST(BeginScene) Main_IDirect3DDeviceImpl_7_3T_2T_1T_BeginScene,
2258 XCAST(EndScene) Main_IDirect3DDeviceImpl_7_3T_2T_1T_EndScene,
2259 XCAST(GetDirect3D) Main_IDirect3DDeviceImpl_7_3T_2T_1T_GetDirect3D,
2260 XCAST(SetRenderTarget) Main_IDirect3DDeviceImpl_7_3T_2T_SetRenderTarget,
2261 XCAST(GetRenderTarget) Main_IDirect3DDeviceImpl_7_3T_2T_GetRenderTarget,
2262 XCAST(Clear) Main_IDirect3DDeviceImpl_7_Clear,
2263 XCAST(SetTransform) Main_IDirect3DDeviceImpl_7_3T_2T_SetTransform,
2264 XCAST(GetTransform) Main_IDirect3DDeviceImpl_7_3T_2T_GetTransform,
2265 XCAST(SetViewport) GL_IDirect3DDeviceImpl_7_SetViewport,
2266 XCAST(MultiplyTransform) Main_IDirect3DDeviceImpl_7_3T_2T_MultiplyTransform,
2267 XCAST(GetViewport) Main_IDirect3DDeviceImpl_7_GetViewport,
2268 XCAST(SetMaterial) GL_IDirect3DDeviceImpl_7_SetMaterial,
2269 XCAST(GetMaterial) Main_IDirect3DDeviceImpl_7_GetMaterial,
2270 XCAST(SetLight) GL_IDirect3DDeviceImpl_7_SetLight,
2271 XCAST(GetLight) Main_IDirect3DDeviceImpl_7_GetLight,
2272 XCAST(SetRenderState) GL_IDirect3DDeviceImpl_7_3T_2T_SetRenderState,
2273 XCAST(GetRenderState) GL_IDirect3DDeviceImpl_7_3T_2T_GetRenderState,
2274 XCAST(BeginStateBlock) Main_IDirect3DDeviceImpl_7_BeginStateBlock,
2275 XCAST(EndStateBlock) Main_IDirect3DDeviceImpl_7_EndStateBlock,
2276 XCAST(PreLoad) Main_IDirect3DDeviceImpl_7_PreLoad,
2277 XCAST(DrawPrimitive) GL_IDirect3DDeviceImpl_7_3T_DrawPrimitive,
2278 XCAST(DrawIndexedPrimitive) GL_IDirect3DDeviceImpl_7_3T_DrawIndexedPrimitive,
2279 XCAST(SetClipStatus) Main_IDirect3DDeviceImpl_7_3T_2T_SetClipStatus,
2280 XCAST(GetClipStatus) Main_IDirect3DDeviceImpl_7_3T_2T_GetClipStatus,
2281 XCAST(DrawPrimitiveStrided) GL_IDirect3DDeviceImpl_7_3T_DrawPrimitiveStrided,
2282 XCAST(DrawIndexedPrimitiveStrided) GL_IDirect3DDeviceImpl_7_3T_DrawIndexedPrimitiveStrided,
2283 XCAST(DrawPrimitiveVB) GL_IDirect3DDeviceImpl_7_3T_DrawPrimitiveVB,
2284 XCAST(DrawIndexedPrimitiveVB) GL_IDirect3DDeviceImpl_7_3T_DrawIndexedPrimitiveVB,
2285 XCAST(ComputeSphereVisibility) Main_IDirect3DDeviceImpl_7_3T_ComputeSphereVisibility,
2286 XCAST(GetTexture) Main_IDirect3DDeviceImpl_7_3T_GetTexture,
2287 XCAST(SetTexture) GL_IDirect3DDeviceImpl_7_3T_SetTexture,
2288 XCAST(GetTextureStageState) Main_IDirect3DDeviceImpl_7_3T_GetTextureStageState,
2289 XCAST(SetTextureStageState) GL_IDirect3DDeviceImpl_7_3T_SetTextureStageState,
2290 XCAST(ValidateDevice) Main_IDirect3DDeviceImpl_7_3T_ValidateDevice,
2291 XCAST(ApplyStateBlock) Main_IDirect3DDeviceImpl_7_ApplyStateBlock,
2292 XCAST(CaptureStateBlock) Main_IDirect3DDeviceImpl_7_CaptureStateBlock,
2293 XCAST(DeleteStateBlock) Main_IDirect3DDeviceImpl_7_DeleteStateBlock,
2294 XCAST(CreateStateBlock) Main_IDirect3DDeviceImpl_7_CreateStateBlock,
2295 XCAST(Load) Main_IDirect3DDeviceImpl_7_Load,
2296 XCAST(LightEnable) GL_IDirect3DDeviceImpl_7_LightEnable,
2297 XCAST(GetLightEnable) Main_IDirect3DDeviceImpl_7_GetLightEnable,
2298 XCAST(SetClipPlane) GL_IDirect3DDeviceImpl_7_SetClipPlane,
2299 XCAST(GetClipPlane) Main_IDirect3DDeviceImpl_7_GetClipPlane,
2300 XCAST(GetInfo) Main_IDirect3DDeviceImpl_7_GetInfo,
2303 #if !defined(__STRICT_ANSI__) && defined(__GNUC__)
2304 #undef XCAST
2305 #endif
2308 #if !defined(__STRICT_ANSI__) && defined(__GNUC__)
2309 # define XCAST(fun) (typeof(VTABLE_IDirect3DDevice3.fun))
2310 #else
2311 # define XCAST(fun) (void*)
2312 #endif
2314 ICOM_VTABLE(IDirect3DDevice3) VTABLE_IDirect3DDevice3 =
2316 ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
2317 XCAST(QueryInterface) Thunk_IDirect3DDeviceImpl_3_QueryInterface,
2318 XCAST(AddRef) Thunk_IDirect3DDeviceImpl_3_AddRef,
2319 XCAST(Release) Thunk_IDirect3DDeviceImpl_3_Release,
2320 XCAST(GetCaps) GL_IDirect3DDeviceImpl_3_2T_1T_GetCaps,
2321 XCAST(GetStats) Main_IDirect3DDeviceImpl_3_2T_1T_GetStats,
2322 XCAST(AddViewport) Main_IDirect3DDeviceImpl_3_2T_1T_AddViewport,
2323 XCAST(DeleteViewport) Main_IDirect3DDeviceImpl_3_2T_1T_DeleteViewport,
2324 XCAST(NextViewport) Main_IDirect3DDeviceImpl_3_2T_1T_NextViewport,
2325 XCAST(EnumTextureFormats) Thunk_IDirect3DDeviceImpl_3_EnumTextureFormats,
2326 XCAST(BeginScene) Thunk_IDirect3DDeviceImpl_3_BeginScene,
2327 XCAST(EndScene) Thunk_IDirect3DDeviceImpl_3_EndScene,
2328 XCAST(GetDirect3D) Thunk_IDirect3DDeviceImpl_3_GetDirect3D,
2329 XCAST(SetCurrentViewport) Main_IDirect3DDeviceImpl_3_2T_SetCurrentViewport,
2330 XCAST(GetCurrentViewport) Main_IDirect3DDeviceImpl_3_2T_GetCurrentViewport,
2331 XCAST(SetRenderTarget) Thunk_IDirect3DDeviceImpl_3_SetRenderTarget,
2332 XCAST(GetRenderTarget) Thunk_IDirect3DDeviceImpl_3_GetRenderTarget,
2333 XCAST(Begin) Main_IDirect3DDeviceImpl_3_Begin,
2334 XCAST(BeginIndexed) Main_IDirect3DDeviceImpl_3_BeginIndexed,
2335 XCAST(Vertex) Main_IDirect3DDeviceImpl_3_2T_Vertex,
2336 XCAST(Index) Main_IDirect3DDeviceImpl_3_2T_Index,
2337 XCAST(End) Main_IDirect3DDeviceImpl_3_2T_End,
2338 XCAST(GetRenderState) Thunk_IDirect3DDeviceImpl_3_GetRenderState,
2339 XCAST(SetRenderState) Thunk_IDirect3DDeviceImpl_3_SetRenderState,
2340 XCAST(GetLightState) Main_IDirect3DDeviceImpl_3_2T_GetLightState,
2341 XCAST(SetLightState) GL_IDirect3DDeviceImpl_3_2T_SetLightState,
2342 XCAST(SetTransform) Thunk_IDirect3DDeviceImpl_3_SetTransform,
2343 XCAST(GetTransform) Thunk_IDirect3DDeviceImpl_3_GetTransform,
2344 XCAST(MultiplyTransform) Thunk_IDirect3DDeviceImpl_3_MultiplyTransform,
2345 XCAST(DrawPrimitive) Thunk_IDirect3DDeviceImpl_3_DrawPrimitive,
2346 XCAST(DrawIndexedPrimitive) Thunk_IDirect3DDeviceImpl_3_DrawIndexedPrimitive,
2347 XCAST(SetClipStatus) Thunk_IDirect3DDeviceImpl_3_SetClipStatus,
2348 XCAST(GetClipStatus) Thunk_IDirect3DDeviceImpl_3_GetClipStatus,
2349 XCAST(DrawPrimitiveStrided) Thunk_IDirect3DDeviceImpl_3_DrawPrimitiveStrided,
2350 XCAST(DrawIndexedPrimitiveStrided) Thunk_IDirect3DDeviceImpl_3_DrawIndexedPrimitiveStrided,
2351 XCAST(DrawPrimitiveVB) Thunk_IDirect3DDeviceImpl_3_DrawPrimitiveVB,
2352 XCAST(DrawIndexedPrimitiveVB) Thunk_IDirect3DDeviceImpl_3_DrawIndexedPrimitiveVB,
2353 XCAST(ComputeSphereVisibility) Thunk_IDirect3DDeviceImpl_3_ComputeSphereVisibility,
2354 XCAST(GetTexture) Thunk_IDirect3DDeviceImpl_3_GetTexture,
2355 XCAST(SetTexture) Thunk_IDirect3DDeviceImpl_3_SetTexture,
2356 XCAST(GetTextureStageState) Thunk_IDirect3DDeviceImpl_3_GetTextureStageState,
2357 XCAST(SetTextureStageState) Thunk_IDirect3DDeviceImpl_3_SetTextureStageState,
2358 XCAST(ValidateDevice) Thunk_IDirect3DDeviceImpl_3_ValidateDevice,
2361 #if !defined(__STRICT_ANSI__) && defined(__GNUC__)
2362 #undef XCAST
2363 #endif
2366 #if !defined(__STRICT_ANSI__) && defined(__GNUC__)
2367 # define XCAST(fun) (typeof(VTABLE_IDirect3DDevice2.fun))
2368 #else
2369 # define XCAST(fun) (void*)
2370 #endif
2372 ICOM_VTABLE(IDirect3DDevice2) VTABLE_IDirect3DDevice2 =
2374 ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
2375 XCAST(QueryInterface) Thunk_IDirect3DDeviceImpl_2_QueryInterface,
2376 XCAST(AddRef) Thunk_IDirect3DDeviceImpl_2_AddRef,
2377 XCAST(Release) Thunk_IDirect3DDeviceImpl_2_Release,
2378 XCAST(GetCaps) Thunk_IDirect3DDeviceImpl_2_GetCaps,
2379 XCAST(SwapTextureHandles) Main_IDirect3DDeviceImpl_2_1T_SwapTextureHandles,
2380 XCAST(GetStats) Thunk_IDirect3DDeviceImpl_2_GetStats,
2381 XCAST(AddViewport) Thunk_IDirect3DDeviceImpl_2_AddViewport,
2382 XCAST(DeleteViewport) Thunk_IDirect3DDeviceImpl_2_DeleteViewport,
2383 XCAST(NextViewport) Thunk_IDirect3DDeviceImpl_2_NextViewport,
2384 XCAST(EnumTextureFormats) GL_IDirect3DDeviceImpl_2_1T_EnumTextureFormats,
2385 XCAST(BeginScene) Thunk_IDirect3DDeviceImpl_2_BeginScene,
2386 XCAST(EndScene) Thunk_IDirect3DDeviceImpl_2_EndScene,
2387 XCAST(GetDirect3D) Thunk_IDirect3DDeviceImpl_2_GetDirect3D,
2388 XCAST(SetCurrentViewport) Thunk_IDirect3DDeviceImpl_2_SetCurrentViewport,
2389 XCAST(GetCurrentViewport) Thunk_IDirect3DDeviceImpl_2_GetCurrentViewport,
2390 XCAST(SetRenderTarget) Thunk_IDirect3DDeviceImpl_2_SetRenderTarget,
2391 XCAST(GetRenderTarget) Thunk_IDirect3DDeviceImpl_2_GetRenderTarget,
2392 XCAST(Begin) Main_IDirect3DDeviceImpl_2_Begin,
2393 XCAST(BeginIndexed) Main_IDirect3DDeviceImpl_2_BeginIndexed,
2394 XCAST(Vertex) Thunk_IDirect3DDeviceImpl_2_Vertex,
2395 XCAST(Index) Thunk_IDirect3DDeviceImpl_2_Index,
2396 XCAST(End) Thunk_IDirect3DDeviceImpl_2_End,
2397 XCAST(GetRenderState) Thunk_IDirect3DDeviceImpl_2_GetRenderState,
2398 XCAST(SetRenderState) Thunk_IDirect3DDeviceImpl_2_SetRenderState,
2399 XCAST(GetLightState) Thunk_IDirect3DDeviceImpl_2_GetLightState,
2400 XCAST(SetLightState) Thunk_IDirect3DDeviceImpl_2_SetLightState,
2401 XCAST(SetTransform) Thunk_IDirect3DDeviceImpl_2_SetTransform,
2402 XCAST(GetTransform) Thunk_IDirect3DDeviceImpl_2_GetTransform,
2403 XCAST(MultiplyTransform) Thunk_IDirect3DDeviceImpl_2_MultiplyTransform,
2404 XCAST(DrawPrimitive) GL_IDirect3DDeviceImpl_2_DrawPrimitive,
2405 XCAST(DrawIndexedPrimitive) GL_IDirect3DDeviceImpl_2_DrawIndexedPrimitive,
2406 XCAST(SetClipStatus) Thunk_IDirect3DDeviceImpl_2_SetClipStatus,
2407 XCAST(GetClipStatus) Thunk_IDirect3DDeviceImpl_2_GetClipStatus,
2410 #if !defined(__STRICT_ANSI__) && defined(__GNUC__)
2411 #undef XCAST
2412 #endif
2415 #if !defined(__STRICT_ANSI__) && defined(__GNUC__)
2416 # define XCAST(fun) (typeof(VTABLE_IDirect3DDevice.fun))
2417 #else
2418 # define XCAST(fun) (void*)
2419 #endif
2421 ICOM_VTABLE(IDirect3DDevice) VTABLE_IDirect3DDevice =
2423 ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
2424 XCAST(QueryInterface) Thunk_IDirect3DDeviceImpl_1_QueryInterface,
2425 XCAST(AddRef) Thunk_IDirect3DDeviceImpl_1_AddRef,
2426 XCAST(Release) Thunk_IDirect3DDeviceImpl_1_Release,
2427 XCAST(Initialize) Main_IDirect3DDeviceImpl_1_Initialize,
2428 XCAST(GetCaps) Thunk_IDirect3DDeviceImpl_1_GetCaps,
2429 XCAST(SwapTextureHandles) Thunk_IDirect3DDeviceImpl_1_SwapTextureHandles,
2430 XCAST(CreateExecuteBuffer) GL_IDirect3DDeviceImpl_1_CreateExecuteBuffer,
2431 XCAST(GetStats) Thunk_IDirect3DDeviceImpl_1_GetStats,
2432 XCAST(Execute) Main_IDirect3DDeviceImpl_1_Execute,
2433 XCAST(AddViewport) Thunk_IDirect3DDeviceImpl_1_AddViewport,
2434 XCAST(DeleteViewport) Thunk_IDirect3DDeviceImpl_1_DeleteViewport,
2435 XCAST(NextViewport) Thunk_IDirect3DDeviceImpl_1_NextViewport,
2436 XCAST(Pick) Main_IDirect3DDeviceImpl_1_Pick,
2437 XCAST(GetPickRecords) Main_IDirect3DDeviceImpl_1_GetPickRecords,
2438 XCAST(EnumTextureFormats) Thunk_IDirect3DDeviceImpl_1_EnumTextureFormats,
2439 XCAST(CreateMatrix) Main_IDirect3DDeviceImpl_1_CreateMatrix,
2440 XCAST(SetMatrix) Main_IDirect3DDeviceImpl_1_SetMatrix,
2441 XCAST(GetMatrix) Main_IDirect3DDeviceImpl_1_GetMatrix,
2442 XCAST(DeleteMatrix) Main_IDirect3DDeviceImpl_1_DeleteMatrix,
2443 XCAST(BeginScene) Thunk_IDirect3DDeviceImpl_1_BeginScene,
2444 XCAST(EndScene) Thunk_IDirect3DDeviceImpl_1_EndScene,
2445 XCAST(GetDirect3D) Thunk_IDirect3DDeviceImpl_1_GetDirect3D,
2448 #if !defined(__STRICT_ANSI__) && defined(__GNUC__)
2449 #undef XCAST
2450 #endif
2452 static HRESULT d3ddevice_clear(IDirect3DDeviceImpl *This,
2453 DWORD dwCount,
2454 LPD3DRECT lpRects,
2455 DWORD dwFlags,
2456 DWORD dwColor,
2457 D3DVALUE dvZ,
2458 DWORD dwStencil)
2460 IDirect3DDeviceGLImpl *glThis = (IDirect3DDeviceGLImpl *) This;
2461 GLboolean ztest;
2462 GLfloat old_z_clear_value;
2463 GLbitfield bitfield = 0;
2464 GLint old_stencil_clear_value;
2465 GLfloat old_color_clear_value[4];
2466 D3DRECT rect;
2467 int i;
2469 TRACE("(%p)->(%08lx,%p,%08lx,%08lx,%f,%08lx)\n", This, dwCount, lpRects, dwFlags, dwColor, dvZ, dwStencil);
2470 if (TRACE_ON(ddraw)) {
2471 if (dwCount > 0) {
2472 int i;
2473 TRACE(" rectangles : \n");
2474 for (i = 0; i < dwCount; i++) {
2475 TRACE(" - %ld x %ld %ld x %ld\n", lpRects[i].u1.x1, lpRects[i].u2.y1, lpRects[i].u3.x2, lpRects[i].u4.y2);
2480 if (dwCount == 0) {
2481 /* Not sure if this is really needed... */
2482 dwCount = 1;
2483 rect.u1.x1 = 0;
2484 rect.u2.y1 = 0;
2485 rect.u3.x2 = This->surface->surface_desc.dwWidth;
2486 rect.u4.y2 = This->surface->surface_desc.dwHeight;
2487 lpRects = &rect;
2490 /* Clears the screen */
2491 ENTER_GL();
2493 if (glThis->state == SURFACE_MEMORY_DIRTY) {
2494 /* TODO: optimize here the case where Clear changes all the screen... */
2495 This->flush_to_framebuffer(This, NULL, glThis->lock_surf);
2497 glThis->state = SURFACE_GL;
2499 if (dwFlags & D3DCLEAR_ZBUFFER) {
2500 bitfield |= GL_DEPTH_BUFFER_BIT;
2501 glGetBooleanv(GL_DEPTH_WRITEMASK, &ztest);
2502 glDepthMask(GL_TRUE); /* Enables Z writing to be sure to delete also the Z buffer */
2503 glGetFloatv(GL_DEPTH_CLEAR_VALUE, &old_z_clear_value);
2504 glClearDepth(dvZ);
2505 TRACE(" depth value : %f\n", dvZ);
2507 if (dwFlags & D3DCLEAR_STENCIL) {
2508 bitfield |= GL_STENCIL_BUFFER_BIT;
2509 glGetIntegerv(GL_STENCIL_CLEAR_VALUE, &old_stencil_clear_value);
2510 glClearStencil(dwStencil);
2511 TRACE(" stencil value : %ld\n", dwStencil);
2513 if (dwFlags & D3DCLEAR_TARGET) {
2514 bitfield |= GL_COLOR_BUFFER_BIT;
2515 glGetFloatv(GL_COLOR_CLEAR_VALUE, old_color_clear_value);
2516 glClearColor(((dwColor >> 16) & 0xFF) / 255.0,
2517 ((dwColor >> 8) & 0xFF) / 255.0,
2518 ((dwColor >> 0) & 0xFF) / 255.0,
2519 ((dwColor >> 24) & 0xFF) / 255.0);
2520 TRACE(" color value (ARGB) : %08lx\n", dwColor);
2523 glEnable(GL_SCISSOR_TEST);
2524 for (i = 0; i < dwCount; i++) {
2525 glScissor(lpRects[i].u1.x1, This->surface->surface_desc.dwHeight - lpRects[i].u4.y2,
2526 lpRects[i].u3.x2 - lpRects[i].u1.x1, lpRects[i].u4.y2 - lpRects[i].u2.y1);
2527 glClear(bitfield);
2529 glDisable(GL_SCISSOR_TEST);
2531 if (dwFlags & D3DCLEAR_ZBUFFER) {
2532 glDepthMask(ztest);
2533 glClearDepth(old_z_clear_value);
2535 if (dwFlags & D3DCLEAR_STENCIL) {
2536 bitfield |= GL_STENCIL_BUFFER_BIT;
2537 glClearStencil(old_stencil_clear_value);
2539 if (dwFlags & D3DCLEAR_TARGET) {
2540 bitfield |= GL_COLOR_BUFFER_BIT;
2541 glClearColor(old_color_clear_value[0],
2542 old_color_clear_value[1],
2543 old_color_clear_value[2],
2544 old_color_clear_value[3]);
2547 LEAVE_GL();
2549 return DD_OK;
2552 HRESULT
2553 d3ddevice_blt(IDirectDrawSurfaceImpl *This, LPRECT rdst,
2554 LPDIRECTDRAWSURFACE7 src, LPRECT rsrc,
2555 DWORD dwFlags, LPDDBLTFX lpbltfx)
2557 if (dwFlags & DDBLT_COLORFILL) {
2558 /* This is easy to handle for the D3D Device... */
2559 DWORD color = lpbltfx->u5.dwFillColor;
2560 D3DRECT rect;
2562 TRACE(" executing D3D Device override.\n");
2564 if (rdst) {
2565 rect.u1.x1 = rdst->left;
2566 rect.u2.y1 = rdst->top;
2567 rect.u3.x2 = rdst->right;
2568 rect.u4.y2 = rdst->bottom;
2570 d3ddevice_clear(This->d3ddevice, rdst != NULL ? 1 : 0, &rect, D3DCLEAR_TARGET, color, 0.0, 0x00000000);
2571 return DD_OK;
2573 return DDERR_INVALIDPARAMS;
2576 HRESULT
2577 d3ddevice_bltfast(IDirectDrawSurfaceImpl *This, DWORD dstx,
2578 DWORD dsty, LPDIRECTDRAWSURFACE7 src,
2579 LPRECT rsrc, DWORD trans)
2581 return DDERR_INVALIDPARAMS;
2584 void
2585 d3ddevice_set_ortho(IDirect3DDeviceImpl *This)
2587 GLfloat height, width;
2588 GLfloat trans_mat[16];
2590 width = This->surface->surface_desc.dwWidth;
2591 height = This->surface->surface_desc.dwHeight;
2593 /* The X axis is straighforward.. For the Y axis, we need to convert 'D3D' screen coordinates
2594 to OpenGL screen coordinates (ie the upper left corner is not the same).
2595 For Z, the mystery is what should it be mapped to ? Ie should the resulting range be between
2596 -1.0 and 1.0 (as the X and Y coordinates) or between 0.0 and 1.0 ? */
2597 trans_mat[ 0] = 2.0 / width; trans_mat[ 4] = 0.0; trans_mat[ 8] = 0.0; trans_mat[12] = -1.0;
2598 trans_mat[ 1] = 0.0; trans_mat[ 5] = -2.0 / height; trans_mat[ 9] = 0.0; trans_mat[13] = 1.0;
2599 trans_mat[ 2] = 0.0; trans_mat[ 6] = 0.0; trans_mat[10] = 1.0; trans_mat[14] = -1.0;
2600 trans_mat[ 3] = 0.0; trans_mat[ 7] = 0.0; trans_mat[11] = 0.0; trans_mat[15] = 1.0;
2602 glMatrixMode(GL_MODELVIEW);
2603 glLoadIdentity();
2604 /* See the OpenGL Red Book for an explanation of the following translation (in the OpenGL
2605 Correctness Tips section).
2607 Basically, from what I understood, if the game does not filter the font texture,
2608 as the 'real' pixel will lie at the middle of the two texels, OpenGL may choose the wrong
2609 one and we will have strange artifacts (as the rounding and stuff may give different results
2610 for different pixels, ie sometimes take the left pixel, sometimes the right).
2612 glTranslatef(0.375, 0.375, 0);
2613 glMatrixMode(GL_PROJECTION);
2614 glLoadMatrixf(trans_mat);
2617 void
2618 d3ddevice_set_matrices(IDirect3DDeviceImpl *This, DWORD matrices,
2619 D3DMATRIX *world_mat, D3DMATRIX *view_mat, D3DMATRIX *proj_mat)
2621 if ((matrices & (VIEWMAT_CHANGED|WORLDMAT_CHANGED)) != 0) {
2622 glMatrixMode(GL_MODELVIEW);
2623 glLoadMatrixf((float *) view_mat);
2625 /* Now also re-loads all the Lights and Clipping Planes using the new matrices */
2626 if (This->state_block.render_state[D3DRENDERSTATE_CLIPPING - 1] != FALSE) {
2627 GLint i;
2628 DWORD runner;
2629 for (i = 0, runner = 0x00000001; i < This->max_clipping_planes; i++, runner <<= 1) {
2630 if (runner & This->state_block.render_state[D3DRENDERSTATE_CLIPPLANEENABLE - 1]) {
2631 GLdouble plane[4];
2633 plane[0] = This->clipping_planes[i].plane[0];
2634 plane[1] = This->clipping_planes[i].plane[1];
2635 plane[2] = This->clipping_planes[i].plane[2];
2636 plane[3] = This->clipping_planes[i].plane[3];
2638 glClipPlane( GL_CLIP_PLANE0 + i, (const GLdouble*) (&plane) );
2642 if (This->state_block.render_state[D3DRENDERSTATE_LIGHTING - 1] != FALSE) {
2643 GLint i;
2644 DWORD runner;
2646 for (i = 0, runner = 0x00000001; i < MAX_LIGHTS; i++, runner <<= 1) {
2647 if (runner & This->active_lights) {
2648 switch (This->light_parameters[i].dltType) {
2649 case D3DLIGHT_DIRECTIONAL: {
2650 float direction[4];
2651 float cut_off = 180.0;
2653 glLightfv(GL_LIGHT0 + i, GL_AMBIENT, (float *) &(This->light_parameters[i].dcvAmbient));
2654 glLightfv(GL_LIGHT0 + i, GL_DIFFUSE, (float *) &(This->light_parameters[i].dcvDiffuse));
2655 glLightfv(GL_LIGHT0 + i, GL_SPECULAR, (float *) &(This->light_parameters[i].dcvSpecular));
2656 glLightfv(GL_LIGHT0 + i, GL_SPOT_CUTOFF, &cut_off);
2658 direction[0] = This->light_parameters[i].dvDirection.u1.x;
2659 direction[1] = This->light_parameters[i].dvDirection.u2.y;
2660 direction[2] = This->light_parameters[i].dvDirection.u3.z;
2661 direction[3] = 0.0;
2662 glLightfv(GL_LIGHT0 + i, GL_POSITION, (float *) direction);
2663 } break;
2665 case D3DLIGHT_POINT: {
2666 float position[4];
2667 float cut_off = 180.0;
2669 glLightfv(GL_LIGHT0 + i, GL_AMBIENT, (float *) &(This->light_parameters[i].dcvAmbient));
2670 glLightfv(GL_LIGHT0 + i, GL_DIFFUSE, (float *) &(This->light_parameters[i].dcvDiffuse));
2671 glLightfv(GL_LIGHT0 + i, GL_SPECULAR, (float *) &(This->light_parameters[i].dcvSpecular));
2672 position[0] = This->light_parameters[i].dvPosition.u1.x;
2673 position[1] = This->light_parameters[i].dvPosition.u2.y;
2674 position[2] = This->light_parameters[i].dvPosition.u3.z;
2675 position[3] = 1.0;
2676 glLightfv(GL_LIGHT0 + i, GL_POSITION, (float *) position);
2677 glLightfv(GL_LIGHT0 + i, GL_CONSTANT_ATTENUATION, &(This->light_parameters[i].dvAttenuation0));
2678 glLightfv(GL_LIGHT0 + i, GL_LINEAR_ATTENUATION, &(This->light_parameters[i].dvAttenuation1));
2679 glLightfv(GL_LIGHT0 + i, GL_QUADRATIC_ATTENUATION, &(This->light_parameters[i].dvAttenuation2));
2680 glLightfv(GL_LIGHT0 + i, GL_SPOT_CUTOFF, &cut_off);
2681 } break;
2683 case D3DLIGHT_SPOT: {
2684 float direction[4];
2685 float position[4];
2686 float cut_off = 90.0 * (This->light_parameters[i].dvPhi / M_PI);
2688 glLightfv(GL_LIGHT0 + i, GL_AMBIENT, (float *) &(This->light_parameters[i].dcvAmbient));
2689 glLightfv(GL_LIGHT0 + i, GL_DIFFUSE, (float *) &(This->light_parameters[i].dcvDiffuse));
2690 glLightfv(GL_LIGHT0 + i, GL_SPECULAR, (float *) &(This->light_parameters[i].dcvSpecular));
2692 direction[0] = This->light_parameters[i].dvDirection.u1.x;
2693 direction[1] = This->light_parameters[i].dvDirection.u2.y;
2694 direction[2] = This->light_parameters[i].dvDirection.u3.z;
2695 direction[3] = 0.0;
2696 glLightfv(GL_LIGHT0 + i, GL_SPOT_DIRECTION, (float *) direction);
2697 position[0] = This->light_parameters[i].dvPosition.u1.x;
2698 position[1] = This->light_parameters[i].dvPosition.u2.y;
2699 position[2] = This->light_parameters[i].dvPosition.u3.z;
2700 position[3] = 1.0;
2701 glLightfv(GL_LIGHT0 + i, GL_POSITION, (float *) position);
2702 glLightfv(GL_LIGHT0 + i, GL_CONSTANT_ATTENUATION, &(This->light_parameters[i].dvAttenuation0));
2703 glLightfv(GL_LIGHT0 + i, GL_LINEAR_ATTENUATION, &(This->light_parameters[i].dvAttenuation1));
2704 glLightfv(GL_LIGHT0 + i, GL_QUADRATIC_ATTENUATION, &(This->light_parameters[i].dvAttenuation2));
2705 glLightfv(GL_LIGHT0 + i, GL_SPOT_CUTOFF, &cut_off);
2706 glLightfv(GL_LIGHT0 + i, GL_SPOT_EXPONENT, &(This->light_parameters[i].dvFalloff));
2707 } break;
2709 default:
2710 /* No warning here as it's already done at light setting */
2711 break;
2717 glMultMatrixf((float *) world_mat);
2719 if ((matrices & PROJMAT_CHANGED) != 0) {
2720 glMatrixMode(GL_PROJECTION);
2721 glLoadMatrixf((float *) proj_mat);
2725 void
2726 d3ddevice_matrices_updated(IDirect3DDeviceImpl *This, DWORD matrices)
2728 IDirect3DDeviceGLImpl *glThis = (IDirect3DDeviceGLImpl *) This;
2729 DWORD tex_mat, tex_stage;
2730 if ((matrices & (VIEWMAT_CHANGED|WORLDMAT_CHANGED|PROJMAT_CHANGED)) != 0) {
2731 if (glThis->transform_state == GL_TRANSFORM_NORMAL) {
2732 /* This will force an update of the transform state at the next drawing. */
2733 glThis->transform_state = GL_TRANSFORM_NONE;
2736 if (matrices & (TEXMAT0_CHANGED|TEXMAT1_CHANGED|TEXMAT2_CHANGED|TEXMAT3_CHANGED|
2737 TEXMAT4_CHANGED|TEXMAT5_CHANGED|TEXMAT6_CHANGED|TEXMAT7_CHANGED))
2739 ENTER_GL();
2740 for (tex_mat = TEXMAT0_CHANGED, tex_stage = 0; tex_mat <= TEXMAT7_CHANGED; tex_mat <<= 1, tex_stage++) {
2741 if (matrices & tex_mat) {
2742 if (This->state_block.texture_stage_state[tex_stage][D3DTSS_TEXTURETRANSFORMFLAGS - 1] != D3DTTFF_DISABLE) {
2743 if (tex_stage == 0) {
2744 /* No multi-texturing support for now ... */
2745 glMatrixMode(GL_TEXTURE);
2746 glLoadMatrixf((float *) This->tex_mat[tex_stage]);
2748 } else {
2749 glMatrixMode(GL_TEXTURE);
2750 glLoadIdentity();
2754 LEAVE_GL();
2758 /* TODO for both these functions :
2759 - change / restore OpenGL parameters for pictures transfers in case they are ever modified
2760 by other OpenGL code in D3D
2761 - handle the case where no 'Begin / EndScene' was done between two locks
2762 - handle the rectangles in the unlock too
2763 - handle pitch correctly...
2765 static void d3ddevice_lock_update(IDirectDrawSurfaceImpl* This, LPCRECT pRect, DWORD dwFlags)
2767 IDirect3DDeviceImpl *d3d_dev = This->d3ddevice;
2768 IDirect3DDeviceGLImpl* gl_d3d_dev = (IDirect3DDeviceGLImpl*) d3d_dev;
2769 BOOLEAN is_front;
2771 if ((This->surface_desc.ddsCaps.dwCaps & (DDSCAPS_FRONTBUFFER|DDSCAPS_PRIMARYSURFACE)) != 0) {
2772 is_front = TRUE;
2773 if ((gl_d3d_dev->front_state != SURFACE_GL) &&
2774 (gl_d3d_dev->front_lock_surf != This)) {
2775 ERR("Change of front buffer.. Expect graphic corruptions !\n");
2777 gl_d3d_dev->front_lock_surf = This;
2778 } else if ((This->surface_desc.ddsCaps.dwCaps & (DDSCAPS_BACKBUFFER)) == (DDSCAPS_BACKBUFFER)) {
2779 is_front = FALSE;
2780 if ((gl_d3d_dev->state != SURFACE_GL) &&
2781 (gl_d3d_dev->lock_surf != This)) {
2782 ERR("Change of back buffer.. Expect graphic corruptions !\n");
2784 gl_d3d_dev->lock_surf = This;
2785 } else {
2786 ERR("Wrong surface type for locking !\n");
2787 return;
2790 /* Try to acquire the device critical section */
2791 EnterCriticalSection(&(d3d_dev->crit));
2793 if (((is_front == TRUE) && (gl_d3d_dev->front_state == SURFACE_GL)) ||
2794 ((is_front == FALSE) && (gl_d3d_dev->state == SURFACE_GL))) {
2795 /* If the surface is already in memory, no need to do anything here... */
2796 GLenum buffer_type;
2797 GLenum buffer_color;
2798 RECT loc_rect;
2799 int y;
2800 char *dst;
2802 TRACE(" copying frame buffer to main memory.\n");
2804 /* Note that here we cannot do 'optmizations' about the WriteOnly flag... Indeed, a game
2805 may only write to the device... But when we will blit it back to the screen, we need
2806 also to blit correctly the parts the application did not overwrite... */
2808 if ((This->surface_desc.u4.ddpfPixelFormat.u1.dwRGBBitCount == 16) &&
2809 (This->surface_desc.u4.ddpfPixelFormat.u2.dwRBitMask == 0xF800) &&
2810 (This->surface_desc.u4.ddpfPixelFormat.u3.dwGBitMask == 0x07E0) &&
2811 (This->surface_desc.u4.ddpfPixelFormat.u4.dwBBitMask == 0x001F) &&
2812 (This->surface_desc.u4.ddpfPixelFormat.u5.dwRGBAlphaBitMask == 0x0000)) {
2813 buffer_type = GL_UNSIGNED_SHORT_5_6_5;
2814 buffer_color = GL_RGB;
2815 } else if ((This->surface_desc.u4.ddpfPixelFormat.u1.dwRGBBitCount == 32) &&
2816 (This->surface_desc.u4.ddpfPixelFormat.u2.dwRBitMask == 0x00FF0000) &&
2817 (This->surface_desc.u4.ddpfPixelFormat.u3.dwGBitMask == 0x0000FF00) &&
2818 (This->surface_desc.u4.ddpfPixelFormat.u4.dwBBitMask == 0x000000FF) &&
2819 (This->surface_desc.u4.ddpfPixelFormat.u5.dwRGBAlphaBitMask == 0x00000000)) {
2820 buffer_type = GL_UNSIGNED_BYTE;
2821 buffer_color = GL_BGRA;
2822 glPixelStorei(GL_PACK_SWAP_BYTES, TRUE);
2823 } else {
2824 ERR(" unsupported pixel format at device locking.\n");
2825 return;
2828 ENTER_GL();
2830 if (is_front == TRUE)
2831 /* Application wants to lock the front buffer */
2832 glReadBuffer(GL_FRONT);
2833 else
2834 /* Application wants to lock the back buffer */
2835 glReadBuffer(GL_BACK);
2837 /* Just a hack while waiting for proper rectangle support */
2838 pRect = NULL;
2839 if (pRect == NULL) {
2840 loc_rect.top = 0;
2841 loc_rect.left = 0;
2842 loc_rect.bottom = This->surface_desc.dwHeight;
2843 loc_rect.right = This->surface_desc.dwWidth;
2844 } else {
2845 loc_rect = *pRect;
2848 dst = ((char *)This->surface_desc.lpSurface) +
2849 (loc_rect.top * This->surface_desc.u1.lPitch) + (loc_rect.left * GET_BPP(This->surface_desc));
2850 for (y = (This->surface_desc.dwHeight - loc_rect.top - 1);
2851 y >= ((int) This->surface_desc.dwHeight - (int) loc_rect.bottom);
2852 y--) {
2853 glReadPixels(loc_rect.left, y,
2854 loc_rect.right - loc_rect.left, 1,
2855 buffer_color, buffer_type, dst);
2856 dst += This->surface_desc.u1.lPitch;
2859 glPixelStorei(GL_PACK_SWAP_BYTES, FALSE);
2861 if (is_front)
2862 gl_d3d_dev->front_state = SURFACE_MEMORY;
2863 else
2864 gl_d3d_dev->state = SURFACE_MEMORY;
2866 #if 0
2867 /* I keep this code here as it's very useful to debug :-) */
2869 static int flush_count = 0;
2870 char buf[128];
2871 FILE *f;
2873 if ((++flush_count % 50) == 0) {
2874 sprintf(buf, "lock_%06d.pnm", flush_count);
2875 f = fopen(buf, "wb");
2876 DDRAW_dump_surface_to_disk(This, f);
2879 #endif
2881 LEAVE_GL();
2885 #define UNLOCK_TEX_SIZE 256
2887 static void d3ddevice_flush_to_frame_buffer(IDirect3DDeviceImpl *d3d_dev, LPCRECT pRect, IDirectDrawSurfaceImpl *surf) {
2888 GLenum buffer_type, buffer_color;
2889 RECT loc_rect;
2890 IDirect3DDeviceGLImpl* gl_d3d_dev = (IDirect3DDeviceGLImpl*) d3d_dev;
2891 GLint depth_test, alpha_test, cull_face, lighting, min_tex, max_tex, tex_env, blend, stencil_test, fog;
2892 GLuint initial_texture;
2893 GLint tex_state;
2894 int x, y;
2896 /* Note : no need here to lock the 'device critical section' as we are already protected by
2897 the GL critical section. */
2899 loc_rect.top = 0;
2900 loc_rect.left = 0;
2901 loc_rect.bottom = surf->surface_desc.dwHeight;
2902 loc_rect.right = surf->surface_desc.dwWidth;
2904 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);
2906 glGetIntegerv(GL_DEPTH_TEST, &depth_test);
2907 glGetIntegerv(GL_ALPHA_TEST, &alpha_test);
2908 glGetIntegerv(GL_STENCIL_TEST, &stencil_test);
2909 glGetIntegerv(GL_CULL_FACE, &cull_face);
2910 glGetIntegerv(GL_LIGHTING, &lighting);
2911 glGetIntegerv(GL_BLEND, &blend);
2912 glGetIntegerv(GL_TEXTURE_BINDING_2D, &initial_texture);
2913 glGetIntegerv(GL_TEXTURE_2D, &tex_state);
2914 glGetIntegerv(GL_FOG, &fog);
2915 glGetTexParameteriv(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, &max_tex);
2916 glGetTexParameteriv(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, &min_tex);
2917 glGetTexEnviv(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, &tex_env);
2918 glMatrixMode(GL_TEXTURE);
2919 glLoadIdentity();
2920 /* TODO: scissor test if ever we use it ! */
2922 if ((surf->surface_desc.u4.ddpfPixelFormat.u1.dwRGBBitCount == 16) &&
2923 (surf->surface_desc.u4.ddpfPixelFormat.u2.dwRBitMask == 0xF800) &&
2924 (surf->surface_desc.u4.ddpfPixelFormat.u3.dwGBitMask == 0x07E0) &&
2925 (surf->surface_desc.u4.ddpfPixelFormat.u4.dwBBitMask == 0x001F) &&
2926 (surf->surface_desc.u4.ddpfPixelFormat.u5.dwRGBAlphaBitMask == 0x0000)) {
2927 buffer_type = GL_UNSIGNED_SHORT_5_6_5;
2928 buffer_color = GL_RGB;
2929 } else if ((surf->surface_desc.u4.ddpfPixelFormat.u1.dwRGBBitCount == 32) &&
2930 (surf->surface_desc.u4.ddpfPixelFormat.u2.dwRBitMask == 0x00FF0000) &&
2931 (surf->surface_desc.u4.ddpfPixelFormat.u3.dwGBitMask == 0x0000FF00) &&
2932 (surf->surface_desc.u4.ddpfPixelFormat.u4.dwBBitMask == 0x000000FF) &&
2933 (surf->surface_desc.u4.ddpfPixelFormat.u5.dwRGBAlphaBitMask == 0x00000000)) {
2934 buffer_type = GL_UNSIGNED_BYTE;
2935 buffer_color = GL_BGRA;
2936 glPixelStorei(GL_UNPACK_SWAP_BYTES, TRUE);
2937 } else {
2938 ERR(" unsupported pixel format at frame buffer flush.\n");
2939 return;
2942 gl_d3d_dev->transform_state = GL_TRANSFORM_ORTHO;
2943 d3ddevice_set_ortho(d3d_dev);
2945 glDisable(GL_DEPTH_TEST);
2946 glEnable(GL_TEXTURE_2D);
2947 glEnable(GL_SCISSOR_TEST);
2948 glDepthRange(0.0, 1.0);
2949 glViewport(0, 0, d3d_dev->surface->surface_desc.dwWidth, d3d_dev->surface->surface_desc.dwHeight);
2950 glScissor(loc_rect.left, surf->surface_desc.dwHeight - loc_rect.bottom,
2951 loc_rect.right - loc_rect.left, loc_rect.bottom - loc_rect.top);
2953 if (gl_d3d_dev->unlock_tex == 0) {
2954 glGenTextures(1, &gl_d3d_dev->unlock_tex);
2955 glBindTexture(GL_TEXTURE_2D, gl_d3d_dev->unlock_tex);
2956 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB,
2957 UNLOCK_TEX_SIZE, UNLOCK_TEX_SIZE, 0,
2958 GL_RGB, buffer_type, NULL);
2959 } else {
2960 glBindTexture(GL_TEXTURE_2D, gl_d3d_dev->unlock_tex);
2962 glPixelStorei(GL_UNPACK_ROW_LENGTH, surf->surface_desc.dwWidth);
2964 glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);
2965 glDisable(GL_LIGHTING);
2966 glDisable(GL_CULL_FACE);
2967 glDisable(GL_ALPHA_TEST);
2968 glDisable(GL_STENCIL_TEST);
2969 glDisable(GL_BLEND);
2970 glDisable(GL_FOG);
2971 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
2972 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
2974 for (x = loc_rect.left; x < loc_rect.right; x += UNLOCK_TEX_SIZE) {
2975 for (y = loc_rect.top; y < loc_rect.bottom; y += UNLOCK_TEX_SIZE) {
2976 /* First, upload the texture... */
2977 int w = (x + UNLOCK_TEX_SIZE > surf->surface_desc.dwWidth) ? (surf->surface_desc.dwWidth - x) : UNLOCK_TEX_SIZE;
2978 int h = (y + UNLOCK_TEX_SIZE > surf->surface_desc.dwHeight) ? (surf->surface_desc.dwHeight - y) : UNLOCK_TEX_SIZE;
2979 glTexSubImage2D(GL_TEXTURE_2D,
2981 0, 0,
2982 w, h,
2983 buffer_color,
2984 buffer_type,
2985 ((char *) surf->surface_desc.lpSurface) + (x * GET_BPP(surf->surface_desc)) + (y * surf->surface_desc.u1.lPitch));
2986 glBegin(GL_QUADS);
2987 glColor3ub(0xFF, 0xFF, 0xFF);
2988 glTexCoord2f(0.0, 0.0);
2989 glVertex3d(x, y, 0.5);
2990 glTexCoord2f(1.0, 0.0);
2991 glVertex3d(x + UNLOCK_TEX_SIZE, y, 0.5);
2992 glTexCoord2f(1.0, 1.0);
2993 glVertex3d(x + UNLOCK_TEX_SIZE, y + UNLOCK_TEX_SIZE, 0.5);
2994 glTexCoord2f(0.0, 1.0);
2995 glVertex3d(x, y + UNLOCK_TEX_SIZE, 0.5);
2996 glEnd();
3001 /* And restore all the various states modified by this code */
3002 if (depth_test != 0) glEnable(GL_DEPTH_TEST);
3003 if (lighting != 0) glEnable(GL_LIGHTING);
3004 if (alpha_test != 0) glEnable(GL_ALPHA_TEST);
3005 if (stencil_test != 0) glEnable(GL_STENCIL_TEST);
3006 if (cull_face != 0) glEnable(GL_CULL_FACE);
3007 if (blend != 0) glEnable(GL_BLEND);
3008 if (fog != 0) glEnable(GL_FOG);
3009 glBindTexture(GL_TEXTURE_2D, initial_texture);
3010 if (tex_state == 0) glDisable(GL_TEXTURE_2D);
3011 glDisable(GL_SCISSOR_TEST);
3012 glPixelStorei(GL_UNPACK_ROW_LENGTH, 0);
3013 glPixelStorei(GL_UNPACK_SWAP_BYTES, FALSE);
3014 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, max_tex);
3015 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, min_tex);
3016 glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, tex_env);
3017 glDepthRange(d3d_dev->active_viewport.dvMinZ, d3d_dev->active_viewport.dvMaxZ);
3018 glViewport(d3d_dev->active_viewport.dwX,
3019 d3d_dev->surface->surface_desc.dwHeight - (d3d_dev->active_viewport.dwHeight + d3d_dev->active_viewport.dwY),
3020 d3d_dev->active_viewport.dwWidth, d3d_dev->active_viewport.dwHeight);
3021 d3d_dev->matrices_updated(d3d_dev, TEXMAT0_CHANGED);
3022 #if 0
3023 /* I keep this code here as it's very useful to debug :-) */
3025 static int flush_count = 0;
3026 char buf[128];
3027 FILE *f;
3029 if ((++flush_count % 50) == 0) {
3030 sprintf(buf, "flush_%06d.pnm", flush_count);
3031 f = fopen(buf, "wb");
3032 DDRAW_dump_surface_to_disk(surf, f);
3035 #endif
3038 static void d3ddevice_unlock_update(IDirectDrawSurfaceImpl* This, LPCRECT pRect)
3040 BOOLEAN is_front;
3041 IDirect3DDeviceImpl *d3d_dev = This->d3ddevice;
3042 IDirect3DDeviceGLImpl* gl_d3d_dev = (IDirect3DDeviceGLImpl*) d3d_dev;
3044 if ((This->surface_desc.ddsCaps.dwCaps & (DDSCAPS_FRONTBUFFER|DDSCAPS_PRIMARYSURFACE)) != 0) {
3045 is_front = TRUE;
3046 } else if ((This->surface_desc.ddsCaps.dwCaps & (DDSCAPS_BACKBUFFER)) == (DDSCAPS_BACKBUFFER)) {
3047 is_front = FALSE;
3048 } else {
3049 ERR("Wrong surface type for locking !\n");
3050 return;
3052 /* First, check if we need to do anything. For the backbuffer, flushing is done at the next 3D activity. */
3053 if ((This->lastlocktype & DDLOCK_READONLY) == 0) {
3054 if (is_front == TRUE) {
3055 GLenum prev_draw;
3056 ENTER_GL();
3057 glGetIntegerv(GL_DRAW_BUFFER, &prev_draw);
3058 glDrawBuffer(GL_FRONT);
3059 d3d_dev->flush_to_framebuffer(d3d_dev, pRect, gl_d3d_dev->front_lock_surf);
3060 glDrawBuffer(prev_draw);
3061 LEAVE_GL();
3062 } else {
3063 gl_d3d_dev->state = SURFACE_MEMORY_DIRTY;
3067 /* And 'frees' the device critical section */
3068 LeaveCriticalSection(&(d3d_dev->crit));
3071 static void
3072 apply_texture_state(IDirect3DDeviceImpl *This)
3074 int stage, state;
3076 /* Initialize texture stages states */
3077 for (stage = 0; stage < MAX_TEXTURES; stage++) {
3078 for (state = 0; state < HIGHEST_TEXTURE_STAGE_STATE; state += 1) {
3079 if (This->state_block.set_flags.texture_stage_state[stage][state] == TRUE) {
3080 IDirect3DDevice7_SetTextureStageState(ICOM_INTERFACE(This, IDirect3DDevice7),
3081 stage, state + 1, This->state_block.texture_stage_state[stage][state]);
3087 HRESULT
3088 d3ddevice_create(IDirect3DDeviceImpl **obj, IDirect3DImpl *d3d, IDirectDrawSurfaceImpl *surface)
3090 IDirect3DDeviceImpl *object;
3091 IDirect3DDeviceGLImpl *gl_object;
3092 IDirectDrawSurfaceImpl *surf;
3093 HDC device_context;
3094 XVisualInfo *vis;
3095 int num;
3096 int tex_num;
3097 XVisualInfo template;
3098 GLenum buffer = GL_FRONT;
3099 int light;
3100 GLint max_clipping_planes = 0;
3102 object = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(IDirect3DDeviceGLImpl));
3103 if (object == NULL) return DDERR_OUTOFMEMORY;
3105 gl_object = (IDirect3DDeviceGLImpl *) object;
3107 object->ref = 1;
3108 object->d3d = d3d;
3109 object->surface = surface;
3110 object->set_context = set_context;
3111 object->clear = d3ddevice_clear;
3112 object->set_matrices = d3ddevice_set_matrices;
3113 object->matrices_updated = d3ddevice_matrices_updated;
3114 object->flush_to_framebuffer = d3ddevice_flush_to_frame_buffer;
3116 InitializeCriticalSection(&(object->crit));
3118 TRACE(" creating OpenGL device for surface = %p, d3d = %p\n", surface, d3d);
3120 device_context = GetDC(surface->ddraw_owner->window);
3121 gl_object->display = get_display(device_context);
3122 gl_object->drawable = get_drawable(device_context);
3123 ReleaseDC(surface->ddraw_owner->window,device_context);
3125 ENTER_GL();
3126 template.visualid = (VisualID)GetPropA( GetDesktopWindow(), "__wine_x11_visual_id" );
3127 vis = XGetVisualInfo(gl_object->display, VisualIDMask, &template, &num);
3128 if (vis == NULL) {
3129 HeapFree(GetProcessHeap(), 0, object);
3130 ERR("No visual found !\n");
3131 LEAVE_GL();
3132 return DDERR_INVALIDPARAMS;
3133 } else {
3134 TRACE(" visual found\n");
3137 gl_object->gl_context = glXCreateContext(gl_object->display, vis,
3138 NULL, GL_TRUE);
3140 if (gl_object->gl_context == NULL) {
3141 HeapFree(GetProcessHeap(), 0, object);
3142 ERR("Error in context creation !\n");
3143 LEAVE_GL();
3144 return DDERR_INVALIDPARAMS;
3145 } else {
3146 TRACE(" context created (%p)\n", gl_object->gl_context);
3149 /* Look for the front buffer and override its surface's Flip method (if in double buffering) */
3150 for (surf = surface; surf != NULL; surf = surf->surface_owner) {
3151 if ((surf->surface_desc.ddsCaps.dwCaps&(DDSCAPS_FLIP|DDSCAPS_FRONTBUFFER)) == (DDSCAPS_FLIP|DDSCAPS_FRONTBUFFER)) {
3152 surf->aux_ctx = (LPVOID) object;
3153 surf->aux_data = (LPVOID) gl_object->drawable;
3154 surf->aux_flip = opengl_flip;
3155 buffer = GL_BACK;
3156 break;
3159 /* We are not doing any double buffering.. Then force OpenGL to draw on the front buffer */
3160 if (surf == NULL) {
3161 TRACE(" no double buffering : drawing on the front buffer\n");
3162 buffer = GL_FRONT;
3165 for (surf = surface; surf != NULL; surf = surf->surface_owner) {
3166 IDirectDrawSurfaceImpl *surf2;
3167 for (surf2 = surf; surf2->prev_attached != NULL; surf2 = surf2->prev_attached) ;
3168 for (; surf2 != NULL; surf2 = surf2->next_attached) {
3169 TRACE(" checking surface %p :", surf2);
3170 if (((surf2->surface_desc.ddsCaps.dwCaps & (DDSCAPS_3DDEVICE)) == (DDSCAPS_3DDEVICE)) &&
3171 ((surf2->surface_desc.ddsCaps.dwCaps & (DDSCAPS_ZBUFFER)) != (DDSCAPS_ZBUFFER))) {
3172 /* Override the Lock / Unlock function for all these surfaces */
3173 surf2->lock_update_prev = surf2->lock_update;
3174 surf2->lock_update = d3ddevice_lock_update;
3175 surf2->unlock_update_prev = surf2->unlock_update;
3176 surf2->unlock_update = d3ddevice_unlock_update;
3177 /* And install also the blt / bltfast overrides */
3178 surf2->aux_blt = d3ddevice_blt;
3179 surf2->aux_bltfast = d3ddevice_bltfast;
3181 TRACE(" overiding direct surface access.\n");
3182 } else {
3183 TRACE(" no overide.\n");
3185 surf2->d3ddevice = object;
3189 /* Set the various light parameters */
3190 for (light = 0; light < MAX_LIGHTS; light++) {
3191 /* Only set the fields that are not zero-created */
3192 object->light_parameters[light].dltType = D3DLIGHT_DIRECTIONAL;
3193 object->light_parameters[light].dcvDiffuse.u1.r = 1.0;
3194 object->light_parameters[light].dcvDiffuse.u2.g = 1.0;
3195 object->light_parameters[light].dcvDiffuse.u3.b = 1.0;
3196 object->light_parameters[light].dvDirection.u3.z = 1.0;
3199 /* Allocate memory for the matrices */
3200 object->world_mat = (D3DMATRIX *) HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, 16 * sizeof(float));
3201 object->view_mat = (D3DMATRIX *) HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, 16 * sizeof(float));
3202 object->proj_mat = (D3DMATRIX *) HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, 16 * sizeof(float));
3203 memcpy(object->world_mat, id_mat, 16 * sizeof(float));
3204 memcpy(object->view_mat , id_mat, 16 * sizeof(float));
3205 memcpy(object->proj_mat , id_mat, 16 * sizeof(float));
3206 for (tex_num = 0; tex_num < MAX_TEXTURES; tex_num++) {
3207 object->tex_mat[tex_num] = (D3DMATRIX *) HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, 16 * sizeof(float));
3208 memcpy(object->tex_mat[tex_num], id_mat, 16 * sizeof(float));
3211 /* Initialisation */
3212 TRACE(" setting current context\n");
3213 object->set_context(object);
3214 TRACE(" current context set\n");
3216 /* allocate the clipping planes */
3217 glGetIntegerv(GL_MAX_CLIP_PLANES,&max_clipping_planes);
3218 if (max_clipping_planes>32) {
3219 object->max_clipping_planes=32;
3220 } else {
3221 object->max_clipping_planes = max_clipping_planes;
3223 TRACE(" capable of %d clipping planes\n", (int)object->max_clipping_planes );
3224 object->clipping_planes = (d3d7clippingplane*)HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, object->max_clipping_planes * sizeof(d3d7clippingplane));
3226 glHint(GL_FOG_HINT,GL_NICEST);
3228 glClearColor(0.0, 0.0, 0.0, 0.0);
3229 glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
3230 glDrawBuffer(buffer);
3231 glReadBuffer(buffer);
3232 /* glDisable(GL_DEPTH_TEST); Need here to check for the presence of a ZBuffer and to reenable it when the ZBuffer is attached */
3233 LEAVE_GL();
3235 gl_object->state = SURFACE_GL;
3237 /* fill_device_capabilities(d3d->ddraw); */
3239 ICOM_INIT_INTERFACE(object, IDirect3DDevice, VTABLE_IDirect3DDevice);
3240 ICOM_INIT_INTERFACE(object, IDirect3DDevice2, VTABLE_IDirect3DDevice2);
3241 ICOM_INIT_INTERFACE(object, IDirect3DDevice3, VTABLE_IDirect3DDevice3);
3242 ICOM_INIT_INTERFACE(object, IDirect3DDevice7, VTABLE_IDirect3DDevice7);
3244 *obj = object;
3246 TRACE(" creating implementation at %p.\n", *obj);
3248 /* And finally warn D3D that this device is now present */
3249 object->d3d->added_device(object->d3d, object);
3251 /* FIXME: Should handle other versions than just 7 */
3252 InitDefaultStateBlock(&object->state_block, 7);
3253 /* Apply default render state and texture stage state values */
3254 apply_render_state(object, &object->state_block);
3255 apply_texture_state(object);
3257 /* And fill the fog table with the default fog value */
3258 build_fog_table(gl_object->fog_table, object->state_block.render_state[D3DRENDERSTATE_FOGCOLOR - 1]);
3260 return DD_OK;