- implement the TFACTOR texture stage state
[wine.git] / dlls / ddraw / d3ddevice / mesa.c
blob9e43857d48859accfbeb3e5e2d9b043f7b37df60
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) {
116 d3d_dev->flush_to_framebuffer(d3d_dev, NULL);
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();
122 return TRUE;
126 /*******************************************************************************
127 * OpenGL static functions
129 static void set_context(IDirect3DDeviceImpl* This)
131 IDirect3DDeviceGLImpl* glThis = (IDirect3DDeviceGLImpl*) This;
133 ENTER_GL();
134 TRACE("glxMakeCurrent %p, %ld, %p\n",glThis->display,glThis->drawable, glThis->gl_context);
135 if (glXMakeCurrent(glThis->display, glThis->drawable, glThis->gl_context) == False) {
136 ERR("Error in setting current context (context %p drawable %ld)!\n",
137 glThis->gl_context, glThis->drawable);
139 LEAVE_GL();
142 static void fill_opengl_primcaps(D3DPRIMCAPS *pc)
144 pc->dwSize = sizeof(*pc);
145 pc->dwMiscCaps = D3DPMISCCAPS_CONFORMANT | D3DPMISCCAPS_CULLCCW | D3DPMISCCAPS_CULLCW |
146 D3DPMISCCAPS_LINEPATTERNREP | D3DPMISCCAPS_MASKZ;
147 pc->dwRasterCaps = D3DPRASTERCAPS_DITHER | D3DPRASTERCAPS_FOGRANGE | D3DPRASTERCAPS_FOGTABLE |
148 D3DPRASTERCAPS_FOGVERTEX | D3DPRASTERCAPS_STIPPLE | D3DPRASTERCAPS_ZBIAS | D3DPRASTERCAPS_ZTEST | D3DPRASTERCAPS_SUBPIXEL;
149 pc->dwZCmpCaps = D3DPCMPCAPS_ALWAYS | D3DPCMPCAPS_EQUAL | D3DPCMPCAPS_GREATER | D3DPCMPCAPS_GREATEREQUAL |
150 D3DPCMPCAPS_LESS | D3DPCMPCAPS_LESSEQUAL | D3DPCMPCAPS_NEVER | D3DPCMPCAPS_NOTEQUAL;
151 pc->dwSrcBlendCaps = D3DPBLENDCAPS_ZERO | D3DPBLENDCAPS_ONE | D3DPBLENDCAPS_DESTCOLOR | D3DPBLENDCAPS_INVDESTCOLOR |
152 D3DPBLENDCAPS_SRCALPHA | D3DPBLENDCAPS_INVSRCALPHA | D3DPBLENDCAPS_DESTALPHA | D3DPBLENDCAPS_INVDESTALPHA | D3DPBLENDCAPS_SRCALPHASAT |
153 D3DPBLENDCAPS_BOTHSRCALPHA | D3DPBLENDCAPS_BOTHINVSRCALPHA;
154 pc->dwDestBlendCaps = D3DPBLENDCAPS_ZERO | D3DPBLENDCAPS_ONE | D3DPBLENDCAPS_SRCCOLOR | D3DPBLENDCAPS_INVSRCCOLOR |
155 D3DPBLENDCAPS_SRCALPHA | D3DPBLENDCAPS_INVSRCALPHA | D3DPBLENDCAPS_DESTALPHA | D3DPBLENDCAPS_INVDESTALPHA | D3DPBLENDCAPS_SRCALPHASAT |
156 D3DPBLENDCAPS_BOTHSRCALPHA | D3DPBLENDCAPS_BOTHINVSRCALPHA;
157 pc->dwAlphaCmpCaps = D3DPCMPCAPS_ALWAYS | D3DPCMPCAPS_EQUAL | D3DPCMPCAPS_GREATER | D3DPCMPCAPS_GREATEREQUAL |
158 D3DPCMPCAPS_LESS | D3DPCMPCAPS_LESSEQUAL | D3DPCMPCAPS_NEVER | D3DPCMPCAPS_NOTEQUAL;
159 pc->dwShadeCaps = D3DPSHADECAPS_ALPHAFLATBLEND | D3DPSHADECAPS_ALPHAGOURAUDBLEND | D3DPSHADECAPS_COLORFLATRGB | D3DPSHADECAPS_COLORGOURAUDRGB |
160 D3DPSHADECAPS_FOGFLAT | D3DPSHADECAPS_FOGGOURAUD | D3DPSHADECAPS_SPECULARFLATRGB | D3DPSHADECAPS_SPECULARGOURAUDRGB;
161 pc->dwTextureCaps = D3DPTEXTURECAPS_ALPHA | D3DPTEXTURECAPS_ALPHAPALETTE | D3DPTEXTURECAPS_BORDER | D3DPTEXTURECAPS_PERSPECTIVE |
162 D3DPTEXTURECAPS_POW2 | D3DPTEXTURECAPS_TRANSPARENCY;
163 pc->dwTextureFilterCaps = D3DPTFILTERCAPS_LINEAR | D3DPTFILTERCAPS_LINEARMIPLINEAR | D3DPTFILTERCAPS_LINEARMIPNEAREST |
164 D3DPTFILTERCAPS_MIPLINEAR | D3DPTFILTERCAPS_MIPNEAREST | D3DPTFILTERCAPS_NEAREST;
165 pc->dwTextureBlendCaps = D3DPTBLENDCAPS_ADD | D3DPTBLENDCAPS_COPY | D3DPTBLENDCAPS_DECAL | D3DPTBLENDCAPS_DECALALPHA | D3DPTBLENDCAPS_DECALMASK |
166 D3DPTBLENDCAPS_MODULATE | D3DPTBLENDCAPS_MODULATEALPHA | D3DPTBLENDCAPS_MODULATEMASK;
167 pc->dwTextureAddressCaps = D3DPTADDRESSCAPS_BORDER | D3DPTADDRESSCAPS_CLAMP | D3DPTADDRESSCAPS_WRAP | D3DPTADDRESSCAPS_INDEPENDENTUV;
168 pc->dwStippleWidth = 32;
169 pc->dwStippleHeight = 32;
172 static void fill_opengl_caps(D3DDEVICEDESC *d1)
174 /* GLint maxlight; */
176 d1->dwSize = sizeof(*d1);
177 d1->dwFlags = D3DDD_DEVCAPS | D3DDD_BCLIPPING | D3DDD_COLORMODEL | D3DDD_DEVICERENDERBITDEPTH | D3DDD_DEVICEZBUFFERBITDEPTH
178 | D3DDD_LIGHTINGCAPS | D3DDD_LINECAPS | D3DDD_MAXBUFFERSIZE | D3DDD_MAXVERTEXCOUNT | D3DDD_TRANSFORMCAPS | D3DDD_TRICAPS;
179 d1->dcmColorModel = D3DCOLOR_RGB;
180 d1->dwDevCaps = D3DDEVCAPS_CANRENDERAFTERFLIP | D3DDEVCAPS_DRAWPRIMTLVERTEX | D3DDEVCAPS_EXECUTESYSTEMMEMORY |
181 D3DDEVCAPS_EXECUTEVIDEOMEMORY | D3DDEVCAPS_FLOATTLVERTEX | D3DDEVCAPS_TEXTURENONLOCALVIDMEM | D3DDEVCAPS_TEXTURESYSTEMMEMORY |
182 D3DDEVCAPS_TEXTUREVIDEOMEMORY | D3DDEVCAPS_TLVERTEXSYSTEMMEMORY | D3DDEVCAPS_TLVERTEXVIDEOMEMORY |
183 /* D3D 7 capabilities */
184 D3DDEVCAPS_DRAWPRIMITIVES2 | D3DDEVCAPS_HWTRANSFORMANDLIGHT | D3DDEVCAPS_HWRASTERIZATION;
185 d1->dtcTransformCaps.dwSize = sizeof(D3DTRANSFORMCAPS);
186 d1->dtcTransformCaps.dwCaps = D3DTRANSFORMCAPS_CLIP;
187 d1->bClipping = TRUE;
188 d1->dlcLightingCaps.dwSize = sizeof(D3DLIGHTINGCAPS);
189 d1->dlcLightingCaps.dwCaps = D3DLIGHTCAPS_DIRECTIONAL | D3DLIGHTCAPS_PARALLELPOINT | D3DLIGHTCAPS_POINT | D3DLIGHTCAPS_SPOT;
190 d1->dlcLightingCaps.dwLightingModel = D3DLIGHTINGMODEL_RGB;
191 d1->dlcLightingCaps.dwNumLights = 16; /* glGetIntegerv(GL_MAX_LIGHTS, &maxlight); d1->dlcLightingCaps.dwNumLights = maxlight; */
192 fill_opengl_primcaps(&(d1->dpcLineCaps));
193 fill_opengl_primcaps(&(d1->dpcTriCaps));
194 d1->dwDeviceRenderBitDepth = DDBD_16|DDBD_24|DDBD_32;
195 d1->dwDeviceZBufferBitDepth = DDBD_16|DDBD_24|DDBD_32;
196 d1->dwMaxBufferSize = 0;
197 d1->dwMaxVertexCount = 65536;
198 d1->dwMinTextureWidth = 1;
199 d1->dwMinTextureHeight = 1;
200 d1->dwMaxTextureWidth = 1024;
201 d1->dwMaxTextureHeight = 1024;
202 d1->dwMinStippleWidth = 1;
203 d1->dwMinStippleHeight = 1;
204 d1->dwMaxStippleWidth = 32;
205 d1->dwMaxStippleHeight = 32;
206 d1->dwMaxTextureRepeat = 16;
207 d1->dwMaxTextureAspectRatio = 1024;
208 d1->dwMaxAnisotropy = 0;
209 d1->dvGuardBandLeft = 0.0;
210 d1->dvGuardBandRight = 0.0;
211 d1->dvGuardBandTop = 0.0;
212 d1->dvGuardBandBottom = 0.0;
213 d1->dvExtentsAdjust = 0.0;
214 d1->dwStencilCaps = D3DSTENCILCAPS_DECRSAT | D3DSTENCILCAPS_INCRSAT | D3DSTENCILCAPS_INVERT | D3DSTENCILCAPS_KEEP |
215 D3DSTENCILCAPS_REPLACE | D3DSTENCILCAPS_ZERO;
216 d1->dwFVFCaps = D3DFVFCAPS_DONOTSTRIPELEMENTS | 1;
217 d1->dwTextureOpCaps = 0; /* TODO add proper caps according to OpenGL multi-texture stuff */
218 d1->wMaxTextureBlendStages = 1; /* TODO add proper caps according to OpenGL multi-texture stuff */
219 d1->wMaxSimultaneousTextures = 1; /* TODO add proper caps according to OpenGL multi-texture stuff */
222 static void fill_opengl_caps_7(D3DDEVICEDESC7 *d)
224 D3DDEVICEDESC d1;
226 /* Copy first D3D1/2/3 capabilities */
227 fill_opengl_caps(&d1);
229 /* And fill the D3D7 one with it */
230 d->dwDevCaps = d1.dwDevCaps;
231 d->dpcLineCaps = d1.dpcLineCaps;
232 d->dpcTriCaps = d1.dpcTriCaps;
233 d->dwDeviceRenderBitDepth = d1.dwDeviceRenderBitDepth;
234 d->dwDeviceZBufferBitDepth = d1.dwDeviceZBufferBitDepth;
235 d->dwMinTextureWidth = d1.dwMinTextureWidth;
236 d->dwMinTextureHeight = d1.dwMinTextureHeight;
237 d->dwMaxTextureWidth = d1.dwMaxTextureWidth;
238 d->dwMaxTextureHeight = d1.dwMaxTextureHeight;
239 d->dwMaxTextureRepeat = d1.dwMaxTextureRepeat;
240 d->dwMaxTextureAspectRatio = d1.dwMaxTextureAspectRatio;
241 d->dwMaxAnisotropy = d1.dwMaxAnisotropy;
242 d->dvGuardBandLeft = d1.dvGuardBandLeft;
243 d->dvGuardBandTop = d1.dvGuardBandTop;
244 d->dvGuardBandRight = d1.dvGuardBandRight;
245 d->dvGuardBandBottom = d1.dvGuardBandBottom;
246 d->dvExtentsAdjust = d1.dvExtentsAdjust;
247 d->dwStencilCaps = d1.dwStencilCaps;
248 d->dwFVFCaps = d1.dwFVFCaps;
249 d->dwTextureOpCaps = d1.dwTextureOpCaps;
250 d->wMaxTextureBlendStages = d1.wMaxTextureBlendStages;
251 d->wMaxSimultaneousTextures = d1.wMaxSimultaneousTextures;
252 d->dwMaxActiveLights = d1.dlcLightingCaps.dwNumLights;
253 d->dvMaxVertexW = 100000000.0; /* No idea exactly what to put here... */
254 d->deviceGUID = IID_IDirect3DTnLHalDevice;
255 d->wMaxUserClipPlanes = 1;
256 d->wMaxVertexBlendMatrices = 0;
257 d->dwVertexProcessingCaps = D3DVTXPCAPS_TEXGEN | D3DVTXPCAPS_MATERIALSOURCE7 | D3DVTXPCAPS_VERTEXFOG | D3DVTXPCAPS_DIRECTIONALLIGHTS |
258 D3DVTXPCAPS_POSITIONALLIGHTS | D3DVTXPCAPS_LOCALVIEWER;
259 d->dwReserved1 = 0;
260 d->dwReserved2 = 0;
261 d->dwReserved3 = 0;
262 d->dwReserved4 = 0;
265 #if 0 /* TODO : fix this and add multitexturing and other needed stuff */
266 static void fill_device_capabilities(IDirectDrawImpl* ddraw)
268 x11_dd_private *private = (x11_dd_private *) ddraw->d->private;
269 const char *ext_string;
270 Mesa_DeviceCapabilities *devcap;
272 private->device_capabilities = HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,sizeof(Mesa_DeviceCapabilities));
273 devcap = (Mesa_DeviceCapabilities *) private->device_capabilities;
275 ENTER_GL();
276 ext_string = glGetString(GL_EXTENSIONS);
277 /* Query for the ColorTable Extension */
278 if (strstr(ext_string, "GL_EXT_paletted_texture")) {
279 devcap->ptr_ColorTableEXT = (PFNGLCOLORTABLEEXTPROC) glXGetProcAddressARB("glColorTableEXT");
280 TRACE("Color table extension supported (function at %p)\n", devcap->ptr_ColorTableEXT);
281 } else {
282 TRACE("Color table extension not found.\n");
284 LEAVE_GL();
286 #endif
290 HRESULT d3ddevice_enumerate(LPD3DENUMDEVICESCALLBACK cb, LPVOID context, DWORD version)
292 D3DDEVICEDESC dref, d1, d2;
293 HRESULT ret_value;
295 /* Some games (Motoracer 2 demo) have the bad idea to modify the device name string.
296 Let's put the string in a sufficiently sized array in writable memory. */
297 char device_name[50];
298 strcpy(device_name,"direct3d");
300 fill_opengl_caps(&dref);
302 if (version > 1) {
303 /* It seems that enumerating the reference IID on Direct3D 1 games (AvP / Motoracer2) breaks them */
304 TRACE(" enumerating OpenGL D3DDevice interface using reference IID (IID %s).\n", debugstr_guid(&IID_IDirect3DRefDevice));
305 d1 = dref;
306 d2 = dref;
307 ret_value = cb((LPIID) &IID_IDirect3DRefDevice, "WINE Reference Direct3DX using OpenGL", device_name, &d1, &d2, context);
308 if (ret_value != D3DENUMRET_OK)
309 return ret_value;
312 TRACE(" enumerating OpenGL D3DDevice interface (IID %s).\n", debugstr_guid(&IID_D3DDEVICE_OpenGL));
313 d1 = dref;
314 d2 = dref;
315 ret_value = cb((LPIID) &IID_D3DDEVICE_OpenGL, "WINE Direct3DX using OpenGL", device_name, &d1, &d2, context);
316 if (ret_value != D3DENUMRET_OK)
317 return ret_value;
319 return D3DENUMRET_OK;
322 HRESULT d3ddevice_enumerate7(LPD3DENUMDEVICESCALLBACK7 cb, LPVOID context)
324 D3DDEVICEDESC7 ddesc;
326 fill_opengl_caps_7(&ddesc);
328 TRACE(" enumerating OpenGL D3DDevice7 interface.\n");
330 return cb("WINE Direct3D7 using OpenGL", "Wine D3D7 device", &ddesc, context);
333 ULONG WINAPI
334 GL_IDirect3DDeviceImpl_7_3T_2T_1T_Release(LPDIRECT3DDEVICE7 iface)
336 ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice7, iface);
337 IDirect3DDeviceGLImpl *glThis = (IDirect3DDeviceGLImpl *) This;
339 TRACE("(%p/%p)->() decrementing from %lu.\n", This, iface, This->ref);
340 if (!--(This->ref)) {
341 int i;
342 IDirectDrawSurfaceImpl *surface = This->surface, *surf;
344 /* Release texture associated with the device */
345 for (i = 0; i < MAX_TEXTURES; i++) {
346 if (This->current_texture[i] != NULL)
347 IDirectDrawSurface7_Release(ICOM_INTERFACE(This->current_texture[i], IDirectDrawSurface7));
348 HeapFree(GetProcessHeap(), 0, This->tex_mat[i]);
351 /* Look for the front buffer and override its surface's Flip method (if in double buffering) */
352 for (surf = surface; surf != NULL; surf = surf->surface_owner) {
353 if ((surf->surface_desc.ddsCaps.dwCaps&(DDSCAPS_FLIP|DDSCAPS_FRONTBUFFER)) == (DDSCAPS_FLIP|DDSCAPS_FRONTBUFFER)) {
354 surf->aux_ctx = NULL;
355 surf->aux_data = NULL;
356 surf->aux_flip = NULL;
357 break;
360 for (surf = surface; surf != NULL; surf = surf->surface_owner) {
361 IDirectDrawSurfaceImpl *surf2;
362 for (surf2 = surf; surf2->prev_attached != NULL; surf2 = surf2->prev_attached) ;
363 for (; surf2 != NULL; surf2 = surf2->next_attached) {
364 if (((surf2->surface_desc.ddsCaps.dwCaps & (DDSCAPS_3DDEVICE)) == (DDSCAPS_3DDEVICE)) &&
365 ((surf2->surface_desc.ddsCaps.dwCaps & (DDSCAPS_ZBUFFER)) != (DDSCAPS_ZBUFFER))) {
366 /* Override the Lock / Unlock function for all these surfaces */
367 surf2->lock_update = surf2->lock_update_prev;
368 surf2->unlock_update = surf2->unlock_update_prev;
369 /* And install also the blt / bltfast overrides */
370 surf2->aux_blt = NULL;
371 surf2->aux_bltfast = NULL;
373 surf2->d3ddevice = NULL;
377 /* And warn the D3D object that this device is no longer active... */
378 This->d3d->removed_device(This->d3d, This);
380 HeapFree(GetProcessHeap(), 0, This->world_mat);
381 HeapFree(GetProcessHeap(), 0, This->view_mat);
382 HeapFree(GetProcessHeap(), 0, This->proj_mat);
384 DeleteCriticalSection(&(This->crit));
386 ENTER_GL();
387 if (glThis->unlock_tex)
388 glDeleteTextures(1, &(glThis->unlock_tex));
389 glXDestroyContext(glThis->display, glThis->gl_context);
390 LEAVE_GL();
391 HeapFree(GetProcessHeap(), 0, This->clipping_planes);
393 HeapFree(GetProcessHeap(), 0, This);
394 return 0;
396 return This->ref;
399 HRESULT WINAPI
400 GL_IDirect3DDeviceImpl_3_2T_1T_GetCaps(LPDIRECT3DDEVICE3 iface,
401 LPD3DDEVICEDESC lpD3DHWDevDesc,
402 LPD3DDEVICEDESC lpD3DHELDevDesc)
404 ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice3, iface);
405 D3DDEVICEDESC desc;
406 DWORD dwSize;
408 TRACE("(%p/%p)->(%p,%p)\n", This, iface, lpD3DHWDevDesc, lpD3DHELDevDesc);
410 fill_opengl_caps(&desc);
411 dwSize = lpD3DHWDevDesc->dwSize;
412 memset(lpD3DHWDevDesc, 0, dwSize);
413 memcpy(lpD3DHWDevDesc, &desc, (dwSize <= desc.dwSize ? dwSize : desc.dwSize));
415 dwSize = lpD3DHELDevDesc->dwSize;
416 memset(lpD3DHELDevDesc, 0, dwSize);
417 memcpy(lpD3DHELDevDesc, &desc, (dwSize <= desc.dwSize ? dwSize : desc.dwSize));
419 TRACE(" returning caps : (no dump function yet)\n");
421 return DD_OK;
424 static HRESULT enum_texture_format_OpenGL(LPD3DENUMTEXTUREFORMATSCALLBACK cb_1,
425 LPD3DENUMPIXELFORMATSCALLBACK cb_2,
426 LPVOID context)
428 DDSURFACEDESC sdesc;
429 LPDDPIXELFORMAT pformat;
431 /* Do the texture enumeration */
432 sdesc.dwSize = sizeof(DDSURFACEDESC);
433 sdesc.dwFlags = DDSD_PIXELFORMAT | DDSD_CAPS;
434 sdesc.ddsCaps.dwCaps = DDSCAPS_TEXTURE;
435 pformat = &(sdesc.ddpfPixelFormat);
436 pformat->dwSize = sizeof(DDPIXELFORMAT);
437 pformat->dwFourCC = 0;
439 #if 0
440 /* See argument about the RGBA format for 'packed' texture formats */
441 TRACE("Enumerating GL_RGBA unpacked (32)\n");
442 pformat->dwFlags = DDPF_RGB | DDPF_ALPHAPIXELS;
443 pformat->u1.dwRGBBitCount = 32;
444 pformat->u2.dwRBitMask = 0xFF000000;
445 pformat->u3.dwGBitMask = 0x00FF0000;
446 pformat->u4.dwBBitMask = 0x0000FF00;
447 pformat->u5.dwRGBAlphaBitMask = 0x000000FF;
448 if (cb_1) if (cb_1(&sdesc , context) == 0) return DD_OK;
449 if (cb_2) if (cb_2(pformat, context) == 0) return DD_OK;
450 #endif
452 TRACE("Enumerating GL_RGBA unpacked (32)\n");
453 pformat->dwFlags = DDPF_RGB | DDPF_ALPHAPIXELS;
454 pformat->u1.dwRGBBitCount = 32;
455 pformat->u2.dwRBitMask = 0x00FF0000;
456 pformat->u3.dwGBitMask = 0x0000FF00;
457 pformat->u4.dwBBitMask = 0x000000FF;
458 pformat->u5.dwRGBAlphaBitMask = 0xFF000000;
459 if (cb_1) if (cb_1(&sdesc , context) == 0) return DD_OK;
460 if (cb_2) if (cb_2(pformat, context) == 0) return DD_OK;
462 #if 0 /* Enabling this breaks Tomb Raider 3, need to investigate... */
463 TRACE("Enumerating GL_RGB unpacked (32)\n");
464 pformat->dwFlags = DDPF_RGB;
465 pformat->u1.dwRGBBitCount = 32;
466 pformat->u2.dwRBitMask = 0x00FF0000;
467 pformat->u3.dwGBitMask = 0x0000FF00;
468 pformat->u4.dwBBitMask = 0x000000FF;
469 pformat->u5.dwRGBAlphaBitMask = 0x00000000;
470 if (cb_1) if (cb_1(&sdesc , context) == 0) return DD_OK;
471 if (cb_2) if (cb_2(pformat, context) == 0) return DD_OK;
472 #endif
474 TRACE("Enumerating GL_RGB unpacked (24)\n");
475 pformat->dwFlags = DDPF_RGB;
476 pformat->u1.dwRGBBitCount = 24;
477 pformat->u2.dwRBitMask = 0x00FF0000;
478 pformat->u3.dwGBitMask = 0x0000FF00;
479 pformat->u4.dwBBitMask = 0x000000FF;
480 pformat->u5.dwRGBAlphaBitMask = 0x00000000;
481 if (cb_1) if (cb_1(&sdesc , context) == 0) return DD_OK;
482 if (cb_2) if (cb_2(pformat, context) == 0) return DD_OK;
484 /* Note : even if this is an 'emulated' texture format, it needs to be first
485 as some dumb applications seem to rely on that. */
486 TRACE("Enumerating GL_RGBA packed GL_UNSIGNED_SHORT_1_5_5_5 (ARGB) (16)\n");
487 pformat->dwFlags = DDPF_RGB | DDPF_ALPHAPIXELS;
488 pformat->u1.dwRGBBitCount = 16;
489 pformat->u2.dwRBitMask = 0x00007C00;
490 pformat->u3.dwGBitMask = 0x000003E0;
491 pformat->u4.dwBBitMask = 0x0000001F;
492 pformat->u5.dwRGBAlphaBitMask = 0x00008000;
493 if (cb_1) if (cb_1(&sdesc , context) == 0) return DD_OK;
494 if (cb_2) if (cb_2(pformat, context) == 0) return DD_OK;
496 TRACE("Enumerating GL_RGBA packed GL_UNSIGNED_SHORT_4_4_4_4 (ARGB) (16)\n");
497 pformat->dwFlags = DDPF_RGB | DDPF_ALPHAPIXELS;
498 pformat->u1.dwRGBBitCount = 16;
499 pformat->u2.dwRBitMask = 0x00000F00;
500 pformat->u3.dwGBitMask = 0x000000F0;
501 pformat->u4.dwBBitMask = 0x0000000F;
502 pformat->u5.dwRGBAlphaBitMask = 0x0000F000;
503 if (cb_1) if (cb_1(&sdesc , context) == 0) return DD_OK;
504 if (cb_2) if (cb_2(pformat, context) == 0) return DD_OK;
506 TRACE("Enumerating GL_RGB packed GL_UNSIGNED_SHORT_5_6_5 (16)\n");
507 pformat->dwFlags = DDPF_RGB;
508 pformat->u1.dwRGBBitCount = 16;
509 pformat->u2.dwRBitMask = 0x0000F800;
510 pformat->u3.dwGBitMask = 0x000007E0;
511 pformat->u4.dwBBitMask = 0x0000001F;
512 pformat->u5.dwRGBAlphaBitMask = 0x00000000;
513 if (cb_1) if (cb_1(&sdesc , context) == 0) return DD_OK;
514 if (cb_2) if (cb_2(pformat, context) == 0) return DD_OK;
516 TRACE("Enumerating GL_RGB packed GL_UNSIGNED_SHORT_5_5_5 (16)\n");
517 pformat->dwFlags = DDPF_RGB;
518 pformat->u1.dwRGBBitCount = 16;
519 pformat->u2.dwRBitMask = 0x00007C00;
520 pformat->u3.dwGBitMask = 0x000003E0;
521 pformat->u4.dwBBitMask = 0x0000001F;
522 pformat->u5.dwRGBAlphaBitMask = 0x00000000;
523 if (cb_1) if (cb_1(&sdesc , context) == 0) return DD_OK;
524 if (cb_2) if (cb_2(pformat, context) == 0) return DD_OK;
526 #if 0
527 /* This is a compromise : some games choose the first 16 bit texture format with alpha they
528 find enumerated, others the last one. And both want to have the ARGB one.
530 So basically, forget our OpenGL roots and do not even enumerate our RGBA ones.
532 TRACE("Enumerating GL_RGBA packed GL_UNSIGNED_SHORT_4_4_4_4 (16)\n");
533 pformat->dwFlags = DDPF_RGB | DDPF_ALPHAPIXELS;
534 pformat->u1.dwRGBBitCount = 16;
535 pformat->u2.dwRBitMask = 0x0000F000;
536 pformat->u3.dwGBitMask = 0x00000F00;
537 pformat->u4.dwBBitMask = 0x000000F0;
538 pformat->u5.dwRGBAlphaBitMask = 0x0000000F;
539 if (cb_1) if (cb_1(&sdesc , context) == 0) return DD_OK;
540 if (cb_2) if (cb_2(pformat, context) == 0) return DD_OK;
542 TRACE("Enumerating GL_RGBA packed GL_UNSIGNED_SHORT_5_5_5_1 (16)\n");
543 pformat->dwFlags = DDPF_RGB | DDPF_ALPHAPIXELS;
544 pformat->u1.dwRGBBitCount = 16;
545 pformat->u2.dwRBitMask = 0x0000F800;
546 pformat->u3.dwGBitMask = 0x000007C0;
547 pformat->u4.dwBBitMask = 0x0000003E;
548 pformat->u5.dwRGBAlphaBitMask = 0x00000001;
549 if (cb_1) if (cb_1(&sdesc , context) == 0) return DD_OK;
550 if (cb_2) if (cb_2(pformat, context) == 0) return DD_OK;
551 #endif
553 TRACE("Enumerating GL_RGB packed GL_UNSIGNED_BYTE_3_3_2 (8)\n");
554 pformat->dwFlags = DDPF_RGB;
555 pformat->u1.dwRGBBitCount = 8;
556 pformat->u2.dwRBitMask = 0x000000E0;
557 pformat->u3.dwGBitMask = 0x0000001C;
558 pformat->u4.dwBBitMask = 0x00000003;
559 pformat->u5.dwRGBAlphaBitMask = 0x00000000;
560 if (cb_1) if (cb_1(&sdesc , context) == 0) return DD_OK;
561 if (cb_2) if (cb_2(pformat, context) == 0) return DD_OK;
563 TRACE("Enumerating Paletted (8)\n");
564 pformat->dwFlags = DDPF_PALETTEINDEXED8;
565 pformat->u1.dwRGBBitCount = 8;
566 pformat->u2.dwRBitMask = 0x00000000;
567 pformat->u3.dwGBitMask = 0x00000000;
568 pformat->u4.dwBBitMask = 0x00000000;
569 pformat->u5.dwRGBAlphaBitMask = 0x00000000;
570 if (cb_1) if (cb_1(&sdesc , context) == 0) return DD_OK;
571 if (cb_2) if (cb_2(pformat, context) == 0) return DD_OK;
573 TRACE("End of enumeration\n");
574 return DD_OK;
578 HRESULT
579 d3ddevice_find(IDirect3DImpl *d3d,
580 LPD3DFINDDEVICESEARCH lpD3DDFS,
581 LPD3DFINDDEVICERESULT lplpD3DDevice)
583 D3DDEVICEDESC desc;
585 if ((lpD3DDFS->dwFlags & D3DFDS_COLORMODEL) &&
586 (lpD3DDFS->dcmColorModel != D3DCOLOR_RGB)) {
587 TRACE(" trying to request a non-RGB D3D color model. Not supported.\n");
588 return DDERR_INVALIDPARAMS; /* No real idea what to return here :-) */
590 if (lpD3DDFS->dwFlags & D3DFDS_GUID) {
591 TRACE(" trying to match guid %s.\n", debugstr_guid(&(lpD3DDFS->guid)));
592 if ((IsEqualGUID(&IID_D3DDEVICE_OpenGL, &(lpD3DDFS->guid)) == 0) &&
593 (IsEqualGUID(&IID_IDirect3DHALDevice, &(lpD3DDFS->guid)) == 0) &&
594 (IsEqualGUID(&IID_IDirect3DRefDevice, &(lpD3DDFS->guid)) == 0)) {
595 TRACE(" no match for this GUID.\n");
596 return DDERR_INVALIDPARAMS;
600 /* Now return our own GUID */
601 lplpD3DDevice->guid = IID_D3DDEVICE_OpenGL;
602 fill_opengl_caps(&desc);
603 lplpD3DDevice->ddHwDesc = desc;
604 lplpD3DDevice->ddSwDesc = desc;
606 TRACE(" returning Wine's OpenGL device with (undumped) capabilities\n");
608 return D3D_OK;
611 HRESULT WINAPI
612 GL_IDirect3DDeviceImpl_2_1T_EnumTextureFormats(LPDIRECT3DDEVICE2 iface,
613 LPD3DENUMTEXTUREFORMATSCALLBACK lpD3DEnumTextureProc,
614 LPVOID lpArg)
616 ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice2, iface);
617 TRACE("(%p/%p)->(%p,%p)\n", This, iface, lpD3DEnumTextureProc, lpArg);
618 return enum_texture_format_OpenGL(lpD3DEnumTextureProc, NULL, lpArg);
621 HRESULT WINAPI
622 GL_IDirect3DDeviceImpl_7_3T_EnumTextureFormats(LPDIRECT3DDEVICE7 iface,
623 LPD3DENUMPIXELFORMATSCALLBACK lpD3DEnumPixelProc,
624 LPVOID lpArg)
626 ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice7, iface);
627 TRACE("(%p/%p)->(%p,%p)\n", This, iface, lpD3DEnumPixelProc, lpArg);
628 return enum_texture_format_OpenGL(NULL, lpD3DEnumPixelProc, lpArg);
631 HRESULT WINAPI
632 GL_IDirect3DDeviceImpl_7_3T_2T_SetRenderState(LPDIRECT3DDEVICE7 iface,
633 D3DRENDERSTATETYPE dwRenderStateType,
634 DWORD dwRenderState)
636 ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice7, iface);
637 TRACE("(%p/%p)->(%08x,%08lx)\n", This, iface, dwRenderStateType, dwRenderState);
639 /* Call the render state functions */
640 store_render_state(This, dwRenderStateType, dwRenderState, &This->state_block);
641 set_render_state(This, dwRenderStateType, &This->state_block);
643 return DD_OK;
646 HRESULT WINAPI
647 GL_IDirect3DDeviceImpl_7_3T_2T_GetRenderState(LPDIRECT3DDEVICE7 iface,
648 D3DRENDERSTATETYPE dwRenderStateType,
649 LPDWORD lpdwRenderState)
651 ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice7, iface);
652 TRACE("(%p/%p)->(%08x,%p)\n", This, iface, dwRenderStateType, lpdwRenderState);
654 /* Call the render state functions */
655 get_render_state(This, dwRenderStateType, lpdwRenderState, &This->state_block);
657 TRACE(" - asked for rendering state : %s, returning value %08lx.\n", _get_renderstate(dwRenderStateType), *lpdwRenderState);
659 return DD_OK;
662 HRESULT WINAPI
663 GL_IDirect3DDeviceImpl_3_2T_SetLightState(LPDIRECT3DDEVICE3 iface,
664 D3DLIGHTSTATETYPE dwLightStateType,
665 DWORD dwLightState)
667 ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice3, iface);
669 TRACE("(%p/%p)->(%08x,%08lx)\n", This, iface, dwLightStateType, dwLightState);
671 if (!dwLightStateType && (dwLightStateType > D3DLIGHTSTATE_COLORVERTEX))
672 TRACE("Unexpected Light State Type\n");
673 return DDERR_INVALIDPARAMS;
675 if (dwLightStateType == D3DLIGHTSTATE_MATERIAL /* 1 */) {
676 IDirect3DMaterialImpl *mat = (IDirect3DMaterialImpl *) dwLightState;
678 if (mat != NULL) {
679 ENTER_GL();
680 mat->activate(mat);
681 LEAVE_GL();
682 } else {
683 ERR(" D3DLIGHTSTATE_MATERIAL called with NULL material !!!\n");
685 } else if (dwLightStateType == D3DLIGHTSTATE_COLORMODEL /* 3 */) {
686 switch (dwLightState) {
687 case D3DCOLOR_MONO:
688 ERR("DDCOLOR_MONO should not happen!\n");
689 break;
690 case D3DCOLOR_RGB:
691 /* We are already in this mode */
692 break;
693 default:
694 ERR("Unknown color model!\n");
695 break;
697 } else {
698 D3DRENDERSTATETYPE rs;
699 switch (dwLightStateType) {
701 case D3DLIGHTSTATE_AMBIENT: /* 2 */
702 rs = D3DRENDERSTATE_AMBIENT;
703 break;
704 case D3DLIGHTSTATE_FOGMODE: /* 4 */
705 rs = D3DRENDERSTATE_FOGVERTEXMODE;
706 break;
707 case D3DLIGHTSTATE_FOGSTART: /* 5 */
708 rs = D3DRENDERSTATE_FOGSTART;
709 break;
710 case D3DLIGHTSTATE_FOGEND: /* 6 */
711 rs = D3DRENDERSTATE_FOGEND;
712 break;
713 case D3DLIGHTSTATE_FOGDENSITY: /* 7 */
714 rs = D3DRENDERSTATE_FOGDENSITY;
715 break;
716 case D3DLIGHTSTATE_COLORVERTEX: /* 8 */
717 rs = D3DRENDERSTATE_COLORVERTEX;
718 break;
719 default:
720 break;
723 IDirect3DDevice7_SetRenderState(ICOM_INTERFACE(This, IDirect3DDevice7),
724 rs,dwLightState);
727 return DD_OK;
730 static void draw_primitive_start_GL(D3DPRIMITIVETYPE d3dpt)
732 switch (d3dpt) {
733 case D3DPT_POINTLIST:
734 TRACE("Start POINTS\n");
735 glBegin(GL_POINTS);
736 break;
738 case D3DPT_LINELIST:
739 TRACE("Start LINES\n");
740 glBegin(GL_LINES);
741 break;
743 case D3DPT_LINESTRIP:
744 TRACE("Start LINE_STRIP\n");
745 glBegin(GL_LINE_STRIP);
746 break;
748 case D3DPT_TRIANGLELIST:
749 TRACE("Start TRIANGLES\n");
750 glBegin(GL_TRIANGLES);
751 break;
753 case D3DPT_TRIANGLESTRIP:
754 TRACE("Start TRIANGLE_STRIP\n");
755 glBegin(GL_TRIANGLE_STRIP);
756 break;
758 case D3DPT_TRIANGLEFAN:
759 TRACE("Start TRIANGLE_FAN\n");
760 glBegin(GL_TRIANGLE_FAN);
761 break;
763 default:
764 FIXME("Unhandled primitive %08x\n", d3dpt);
765 break;
769 /* This function calculate the Z coordinate from Zproj */
770 static float ZfromZproj(IDirect3DDeviceImpl *This, D3DVALUE Zproj)
772 float a,b,c,d;
773 /* Assume that X = Y = 0 and W = 1 */
774 a = This->proj_mat->_33;
775 b = This->proj_mat->_34;
776 c = This->proj_mat->_43;
777 d = This->proj_mat->_44;
778 /* We have in homogenous coordinates Z' = a * Z + c and W' = b * Z + d
779 * So in non homogenous coordinates we have Zproj = (a * Z + c) / (b * Z + d)
780 * And finally Z = (d * Zproj - c) / (a - b * Zproj)
782 return (d*Zproj - c) / (a - b*Zproj);
785 static void build_fog_table(BYTE *fog_table, DWORD fog_color) {
786 int i;
788 TRACE(" rebuilding fog table (%06lx)...\n", fog_color & 0x00FFFFFF);
790 for (i = 0; i < 3; i++) {
791 BYTE fog_color_component = (fog_color >> (8 * i)) & 0xFF;
792 DWORD elt;
793 for (elt = 0; elt < 0x10000; elt++) {
794 /* We apply the fog transformation and cache the result */
795 DWORD fog_intensity = elt & 0xFF;
796 DWORD vertex_color = (elt >> 8) & 0xFF;
797 fog_table[(i * 0x10000) + elt] = ((fog_intensity * vertex_color) + ((0xFF - fog_intensity) * fog_color_component)) / 0xFF;
802 static void draw_primitive_handle_GL_state(IDirect3DDeviceImpl *This,
803 BOOLEAN vertex_transformed,
804 BOOLEAN vertex_lit) {
805 IDirect3DDeviceGLImpl* glThis = (IDirect3DDeviceGLImpl*) This;
807 /* Puts GL in the correct lighting / transformation mode */
808 if ((vertex_transformed == FALSE) &&
809 (glThis->transform_state != GL_TRANSFORM_NORMAL)) {
810 /* Need to put the correct transformation again if we go from Transformed
811 vertices to non-transformed ones.
813 This->set_matrices(This, VIEWMAT_CHANGED|WORLDMAT_CHANGED|PROJMAT_CHANGED,
814 This->world_mat, This->view_mat, This->proj_mat);
815 glThis->transform_state = GL_TRANSFORM_NORMAL;
817 } else if ((vertex_transformed == TRUE) &&
818 (glThis->transform_state != GL_TRANSFORM_ORTHO)) {
819 /* Set our orthographic projection */
820 glThis->transform_state = GL_TRANSFORM_ORTHO;
821 d3ddevice_set_ortho(This);
824 /* TODO: optimize this to not always reset all the fog stuff on all DrawPrimitive call
825 if no fogging state change occured */
826 if (This->state_block.render_state[D3DRENDERSTATE_FOGENABLE - 1] == TRUE) {
827 if (vertex_transformed == TRUE) {
828 glDisable(GL_FOG);
829 /* Now check if our fog_table still corresponds to the current vertex color.
830 Element '0x..00' is always the fog color as it corresponds to maximum fog intensity */
831 if ((glThis->fog_table[0 * 0x10000 + 0x0000] != ((This->state_block.render_state[D3DRENDERSTATE_FOGCOLOR - 1] >> 0) & 0xFF)) ||
832 (glThis->fog_table[1 * 0x10000 + 0x0000] != ((This->state_block.render_state[D3DRENDERSTATE_FOGCOLOR - 1] >> 8) & 0xFF)) ||
833 (glThis->fog_table[2 * 0x10000 + 0x0000] != ((This->state_block.render_state[D3DRENDERSTATE_FOGCOLOR - 1] >> 16) & 0xFF))) {
834 /* We need to rebuild our fog table.... */
835 build_fog_table(glThis->fog_table, This->state_block.render_state[D3DRENDERSTATE_FOGCOLOR - 1]);
837 } else {
838 if (This->state_block.render_state[D3DRENDERSTATE_FOGTABLEMODE - 1] != D3DFOG_NONE) {
839 switch (This->state_block.render_state[D3DRENDERSTATE_FOGTABLEMODE - 1]) {
840 case D3DFOG_LINEAR: glFogi(GL_FOG_MODE, GL_LINEAR); break;
841 case D3DFOG_EXP: glFogi(GL_FOG_MODE, GL_EXP); break;
842 case D3DFOG_EXP2: glFogi(GL_FOG_MODE, GL_EXP2); break;
844 if (vertex_lit == FALSE) {
845 glFogf(GL_FOG_START, *(float*)&This->state_block.render_state[D3DRENDERSTATE_FOGSTART - 1]);
846 glFogf(GL_FOG_END, *(float*)&This->state_block.render_state[D3DRENDERSTATE_FOGEND - 1]);
847 } else {
848 /* Special case of 'pixel fog' */
849 glFogf(GL_FOG_START, ZfromZproj(This, *(float*)&This->state_block.render_state[D3DRENDERSTATE_FOGSTART - 1]));
850 glFogf(GL_FOG_END, ZfromZproj(This, *(float*)&This->state_block.render_state[D3DRENDERSTATE_FOGEND - 1]));
852 glEnable(GL_FOG);
853 } else {
854 glDisable(GL_FOG);
857 } else {
858 glDisable(GL_FOG);
861 /* Handle the 'no-normal' case */
862 if ((vertex_lit == FALSE) && (This->state_block.render_state[D3DRENDERSTATE_LIGHTING - 1] == TRUE))
863 glEnable(GL_LIGHTING);
864 else
865 glDisable(GL_LIGHTING);
867 /* Handle the code for pre-vertex material properties */
868 if (vertex_transformed == FALSE) {
869 if ((This->state_block.render_state[D3DRENDERSTATE_LIGHTING - 1] == TRUE) &&
870 (This->state_block.render_state[D3DRENDERSTATE_COLORVERTEX - 1] == TRUE)) {
871 if ((This->state_block.render_state[D3DRENDERSTATE_DIFFUSEMATERIALSOURCE - 1] != D3DMCS_MATERIAL) ||
872 (This->state_block.render_state[D3DRENDERSTATE_AMBIENTMATERIALSOURCE - 1] != D3DMCS_MATERIAL) ||
873 (This->state_block.render_state[D3DRENDERSTATE_EMISSIVEMATERIALSOURCE - 1] != D3DMCS_MATERIAL) ||
874 (This->state_block.render_state[D3DRENDERSTATE_SPECULARMATERIALSOURCE - 1] != D3DMCS_MATERIAL)) {
875 glEnable(GL_COLOR_MATERIAL);
882 inline static void draw_primitive(IDirect3DDeviceImpl *This, DWORD maxvert, WORD *index,
883 D3DVERTEXTYPE d3dvt, D3DPRIMITIVETYPE d3dpt, void *lpvertex)
885 D3DDRAWPRIMITIVESTRIDEDDATA strided;
887 switch (d3dvt) {
888 case D3DVT_VERTEX: {
889 strided.position.lpvData = &((D3DVERTEX *) lpvertex)->u1.x;
890 strided.position.dwStride = sizeof(D3DVERTEX);
891 strided.normal.lpvData = &((D3DVERTEX *) lpvertex)->u4.nx;
892 strided.normal.dwStride = sizeof(D3DVERTEX);
893 strided.textureCoords[0].lpvData = &((D3DVERTEX *) lpvertex)->u7.tu;
894 strided.textureCoords[0].dwStride = sizeof(D3DVERTEX);
895 draw_primitive_strided(This, d3dpt, D3DFVF_VERTEX, &strided, 0 /* Unused */, index, maxvert, 0 /* Unused */);
896 } break;
898 case D3DVT_LVERTEX: {
899 strided.position.lpvData = &((D3DLVERTEX *) lpvertex)->u1.x;
900 strided.position.dwStride = sizeof(D3DLVERTEX);
901 strided.diffuse.lpvData = &((D3DLVERTEX *) lpvertex)->u4.color;
902 strided.diffuse.dwStride = sizeof(D3DLVERTEX);
903 strided.specular.lpvData = &((D3DLVERTEX *) lpvertex)->u5.specular;
904 strided.specular.dwStride = sizeof(D3DLVERTEX);
905 strided.textureCoords[0].lpvData = &((D3DLVERTEX *) lpvertex)->u6.tu;
906 strided.textureCoords[0].dwStride = sizeof(D3DLVERTEX);
907 draw_primitive_strided(This, d3dpt, D3DFVF_LVERTEX, &strided, 0 /* Unused */, index, maxvert, 0 /* Unused */);
908 } break;
910 case D3DVT_TLVERTEX: {
911 strided.position.lpvData = &((D3DTLVERTEX *) lpvertex)->u1.sx;
912 strided.position.dwStride = sizeof(D3DTLVERTEX);
913 strided.diffuse.lpvData = &((D3DTLVERTEX *) lpvertex)->u5.color;
914 strided.diffuse.dwStride = sizeof(D3DTLVERTEX);
915 strided.specular.lpvData = &((D3DTLVERTEX *) lpvertex)->u6.specular;
916 strided.specular.dwStride = sizeof(D3DTLVERTEX);
917 strided.textureCoords[0].lpvData = &((D3DTLVERTEX *) lpvertex)->u7.tu;
918 strided.textureCoords[0].dwStride = sizeof(D3DTLVERTEX);
919 draw_primitive_strided(This, d3dpt, D3DFVF_TLVERTEX, &strided, 0 /* Unused */, index, maxvert, 0 /* Unused */);
920 } break;
922 default:
923 FIXME("Unhandled vertex type %08x\n", d3dvt);
924 break;
928 HRESULT WINAPI
929 GL_IDirect3DDeviceImpl_2_DrawPrimitive(LPDIRECT3DDEVICE2 iface,
930 D3DPRIMITIVETYPE d3dptPrimitiveType,
931 D3DVERTEXTYPE d3dvtVertexType,
932 LPVOID lpvVertices,
933 DWORD dwVertexCount,
934 DWORD dwFlags)
936 ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice2, iface);
938 TRACE("(%p/%p)->(%08x,%08x,%p,%08lx,%08lx)\n", This, iface, d3dptPrimitiveType, d3dvtVertexType, lpvVertices, dwVertexCount, dwFlags);
939 if (TRACE_ON(ddraw)) {
940 TRACE(" - flags : "); dump_DPFLAGS(dwFlags);
943 draw_primitive(This, dwVertexCount, NULL, d3dvtVertexType, d3dptPrimitiveType, lpvVertices);
945 return DD_OK;
948 HRESULT WINAPI
949 GL_IDirect3DDeviceImpl_2_DrawIndexedPrimitive(LPDIRECT3DDEVICE2 iface,
950 D3DPRIMITIVETYPE d3dptPrimitiveType,
951 D3DVERTEXTYPE d3dvtVertexType,
952 LPVOID lpvVertices,
953 DWORD dwVertexCount,
954 LPWORD dwIndices,
955 DWORD dwIndexCount,
956 DWORD dwFlags)
958 ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice2, iface);
959 TRACE("(%p/%p)->(%08x,%08x,%p,%08lx,%p,%08lx,%08lx)\n", This, iface, d3dptPrimitiveType, d3dvtVertexType, lpvVertices, dwVertexCount, dwIndices, dwIndexCount, dwFlags);
960 if (TRACE_ON(ddraw)) {
961 TRACE(" - flags : "); dump_DPFLAGS(dwFlags);
964 draw_primitive(This, dwIndexCount, dwIndices, d3dvtVertexType, d3dptPrimitiveType, lpvVertices);
966 return DD_OK;
969 HRESULT WINAPI
970 GL_IDirect3DDeviceImpl_1_CreateExecuteBuffer(LPDIRECT3DDEVICE iface,
971 LPD3DEXECUTEBUFFERDESC lpDesc,
972 LPDIRECT3DEXECUTEBUFFER* lplpDirect3DExecuteBuffer,
973 IUnknown* pUnkOuter)
975 ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice, iface);
976 IDirect3DExecuteBufferImpl *ret;
977 HRESULT ret_value;
979 TRACE("(%p/%p)->(%p,%p,%p)\n", This, iface, lpDesc, lplpDirect3DExecuteBuffer, pUnkOuter);
981 ret_value = d3dexecutebuffer_create(&ret, This->d3d, This, lpDesc);
982 *lplpDirect3DExecuteBuffer = ICOM_INTERFACE(ret, IDirect3DExecuteBuffer);
984 TRACE(" returning %p.\n", *lplpDirect3DExecuteBuffer);
986 return ret_value;
989 /* These are the various handler used in the generic path */
990 inline static void handle_xyz(D3DVALUE *coords) {
991 glVertex3fv(coords);
993 inline static void handle_xyzrhw(D3DVALUE *coords) {
994 if (coords[3] < 1e-8)
995 glVertex3fv(coords);
996 else {
997 GLfloat w = 1.0 / coords[3];
999 glVertex4f(coords[0] * w,
1000 coords[1] * w,
1001 coords[2] * w,
1005 inline static void handle_normal(D3DVALUE *coords) {
1006 glNormal3fv(coords);
1009 inline static void handle_diffuse_base(STATEBLOCK *sb, DWORD *color) {
1010 if ((sb->render_state[D3DRENDERSTATE_ALPHATESTENABLE - 1] == TRUE) ||
1011 (sb->render_state[D3DRENDERSTATE_ALPHABLENDENABLE - 1] == TRUE)) {
1012 glColor4ub((*color >> 16) & 0xFF,
1013 (*color >> 8) & 0xFF,
1014 (*color >> 0) & 0xFF,
1015 (*color >> 24) & 0xFF);
1016 } else {
1017 glColor3ub((*color >> 16) & 0xFF,
1018 (*color >> 8) & 0xFF,
1019 (*color >> 0) & 0xFF);
1023 inline static void handle_specular_base(STATEBLOCK *sb, DWORD *color) {
1024 glColor4ub((*color >> 16) & 0xFF,
1025 (*color >> 8) & 0xFF,
1026 (*color >> 0) & 0xFF,
1027 (*color >> 24) & 0xFF); /* No idea if the alpha field is really used.. */
1030 inline static void handle_diffuse(STATEBLOCK *sb, DWORD *color, BOOLEAN lighted) {
1031 if ((lighted == FALSE) &&
1032 (sb->render_state[D3DRENDERSTATE_LIGHTING - 1] == TRUE) &&
1033 (sb->render_state[D3DRENDERSTATE_COLORVERTEX - 1] == TRUE)) {
1034 if (sb->render_state[D3DRENDERSTATE_DIFFUSEMATERIALSOURCE - 1] == D3DMCS_COLOR1) {
1035 glColorMaterial(GL_FRONT_AND_BACK, GL_DIFFUSE);
1036 handle_diffuse_base(sb, color);
1038 if (sb->render_state[D3DRENDERSTATE_AMBIENTMATERIALSOURCE - 1] == D3DMCS_COLOR1) {
1039 glColorMaterial(GL_FRONT_AND_BACK, GL_AMBIENT);
1040 handle_diffuse_base(sb, color);
1042 if ((sb->render_state[D3DRENDERSTATE_SPECULARMATERIALSOURCE - 1] == D3DMCS_COLOR1) &&
1043 (sb->render_state[D3DRENDERSTATE_SPECULARENABLE - 1] == TRUE)) {
1044 glColorMaterial(GL_FRONT_AND_BACK, GL_SPECULAR);
1045 handle_diffuse_base(sb, color);
1047 if (sb->render_state[D3DRENDERSTATE_EMISSIVEMATERIALSOURCE - 1] == D3DMCS_COLOR1) {
1048 glColorMaterial(GL_FRONT_AND_BACK, GL_EMISSION);
1049 handle_diffuse_base(sb, color);
1051 } else {
1052 handle_diffuse_base(sb, color);
1056 inline static void handle_specular(STATEBLOCK *sb, DWORD *color, BOOLEAN lighted) {
1057 if ((lighted == FALSE) &&
1058 (sb->render_state[D3DRENDERSTATE_LIGHTING - 1] == TRUE) &&
1059 (sb->render_state[D3DRENDERSTATE_COLORVERTEX - 1] == TRUE)) {
1060 if (sb->render_state[D3DRENDERSTATE_DIFFUSEMATERIALSOURCE - 1] == D3DMCS_COLOR2) {
1061 glColorMaterial(GL_FRONT_AND_BACK, GL_DIFFUSE);
1062 handle_specular_base(sb, color);
1064 if (sb->render_state[D3DRENDERSTATE_AMBIENTMATERIALSOURCE - 1] == D3DMCS_COLOR2) {
1065 glColorMaterial(GL_FRONT_AND_BACK, GL_AMBIENT);
1066 handle_specular_base(sb, color);
1068 if ((sb->render_state[D3DRENDERSTATE_SPECULARMATERIALSOURCE - 1] == D3DMCS_COLOR2) &&
1069 (sb->render_state[D3DRENDERSTATE_SPECULARENABLE - 1] == TRUE)) {
1070 glColorMaterial(GL_FRONT_AND_BACK, GL_SPECULAR);
1071 handle_specular_base(sb, color);
1073 if (sb->render_state[D3DRENDERSTATE_EMISSIVEMATERIALSOURCE - 1] == D3DMCS_COLOR2) {
1074 glColorMaterial(GL_FRONT_AND_BACK, GL_EMISSION);
1075 handle_specular_base(sb, color);
1078 /* No else here as we do not know how to handle 'specular' on its own in any case.. */
1081 inline static void handle_diffuse_and_specular(STATEBLOCK *sb, BYTE *fog_table, DWORD *color_d, DWORD *color_s, BOOLEAN lighted) {
1082 if (lighted == TRUE) {
1083 DWORD color = *color_d;
1084 if (sb->render_state[D3DRENDERSTATE_FOGENABLE - 1] == TRUE) {
1085 /* Special case where the specular value is used to do fogging */
1086 BYTE fog_intensity = *color_s >> 24; /* The alpha value of the specular component is the fog 'intensity' for this vertex */
1087 color &= 0xFF000000; /* Only keep the alpha component */
1088 color |= fog_table[((*color_d >> 0) & 0xFF) << 8 | fog_intensity] << 0;
1089 color |= fog_table[((*color_d >> 8) & 0xFF) << 8 | fog_intensity] << 8;
1090 color |= fog_table[((*color_d >> 16) & 0xFF) << 8 | fog_intensity] << 16;
1092 if (sb->render_state[D3DRENDERSTATE_SPECULARENABLE - 1] == TRUE) {
1093 /* Standard specular value in transformed mode. TODO */
1095 handle_diffuse_base(sb, &color);
1096 } else {
1097 if (sb->render_state[D3DRENDERSTATE_LIGHTING - 1] == TRUE) {
1098 handle_diffuse(sb, color_d, FALSE);
1099 handle_specular(sb, color_s, FALSE);
1100 } else {
1101 /* In that case, only put the diffuse color... */
1102 handle_diffuse_base(sb, color_d);
1107 inline static void handle_texture(D3DVALUE *coords) {
1108 glTexCoord2fv(coords);
1110 inline static void handle_textures(D3DVALUE *coords, int tex_index) {
1111 /* For the moment, draw only the first texture.. */
1112 if (tex_index == 0) glTexCoord2fv(coords);
1115 static void draw_primitive_strided(IDirect3DDeviceImpl *This,
1116 D3DPRIMITIVETYPE d3dptPrimitiveType,
1117 DWORD d3dvtVertexType,
1118 LPD3DDRAWPRIMITIVESTRIDEDDATA lpD3DDrawPrimStrideData,
1119 DWORD dwVertexCount,
1120 LPWORD dwIndices,
1121 DWORD dwIndexCount,
1122 DWORD dwFlags)
1124 BOOLEAN vertex_lighted = FALSE;
1125 IDirect3DDeviceGLImpl* glThis = (IDirect3DDeviceGLImpl*) This;
1126 int num_active_stages = 0;
1128 ENTER_GL();
1129 if (glThis->state == SURFACE_MEMORY) {
1130 This->flush_to_framebuffer(This, NULL);
1132 LEAVE_GL();
1134 glThis->state = SURFACE_GL;
1136 /* Compute the number of active texture stages */
1137 while (This->current_texture[num_active_stages] != NULL) num_active_stages++;
1139 /* This is to prevent 'thread contention' between a thread locking the device and another
1140 doing 3D display on it... */
1141 EnterCriticalSection(&(This->crit));
1143 if (TRACE_ON(ddraw)) {
1144 TRACE(" Vertex format : "); dump_flexible_vertex(d3dvtVertexType);
1147 ENTER_GL();
1149 /* Just a hack for now.. Will have to find better algorithm :-/ */
1150 if ((d3dvtVertexType & D3DFVF_POSITION_MASK) != D3DFVF_XYZ) {
1151 vertex_lighted = TRUE;
1152 } else {
1153 if ((d3dvtVertexType & D3DFVF_NORMAL) == 0) glNormal3f(0.0, 0.0, 0.0);
1156 draw_primitive_handle_GL_state(This,
1157 (d3dvtVertexType & D3DFVF_POSITION_MASK) != D3DFVF_XYZ,
1158 vertex_lighted);
1159 draw_primitive_start_GL(d3dptPrimitiveType);
1161 /* Some fast paths first before the generic case.... */
1162 if ((d3dvtVertexType == D3DFVF_VERTEX) && (num_active_stages <= 1)) {
1163 int index;
1165 for (index = 0; index < dwIndexCount; index++) {
1166 int i = (dwIndices == NULL) ? index : dwIndices[index];
1167 D3DVALUE *normal =
1168 (D3DVALUE *) (((char *) lpD3DDrawPrimStrideData->normal.lpvData) + i * lpD3DDrawPrimStrideData->normal.dwStride);
1169 D3DVALUE *tex_coord =
1170 (D3DVALUE *) (((char *) lpD3DDrawPrimStrideData->textureCoords[0].lpvData) + i * lpD3DDrawPrimStrideData->textureCoords[0].dwStride);
1171 D3DVALUE *position =
1172 (D3DVALUE *) (((char *) lpD3DDrawPrimStrideData->position.lpvData) + i * lpD3DDrawPrimStrideData->position.dwStride);
1174 handle_normal(normal);
1175 handle_texture(tex_coord);
1176 handle_xyz(position);
1178 TRACE_(ddraw_geom)(" %f %f %f / %f %f %f (%f %f)\n",
1179 position[0], position[1], position[2],
1180 normal[0], normal[1], normal[2],
1181 tex_coord[0], tex_coord[1]);
1183 } else if ((d3dvtVertexType == D3DFVF_TLVERTEX) && (num_active_stages <= 1)) {
1184 int index;
1186 for (index = 0; index < dwIndexCount; index++) {
1187 int i = (dwIndices == NULL) ? index : dwIndices[index];
1188 DWORD *color_d =
1189 (DWORD *) (((char *) lpD3DDrawPrimStrideData->diffuse.lpvData) + i * lpD3DDrawPrimStrideData->diffuse.dwStride);
1190 DWORD *color_s =
1191 (DWORD *) (((char *) lpD3DDrawPrimStrideData->specular.lpvData) + i * lpD3DDrawPrimStrideData->specular.dwStride);
1192 D3DVALUE *tex_coord =
1193 (D3DVALUE *) (((char *) lpD3DDrawPrimStrideData->textureCoords[0].lpvData) + i * lpD3DDrawPrimStrideData->textureCoords[0].dwStride);
1194 D3DVALUE *position =
1195 (D3DVALUE *) (((char *) lpD3DDrawPrimStrideData->position.lpvData) + i * lpD3DDrawPrimStrideData->position.dwStride);
1197 handle_diffuse_and_specular(&(This->state_block), glThis->fog_table, color_d, color_s, TRUE);
1198 handle_texture(tex_coord);
1199 handle_xyzrhw(position);
1201 TRACE_(ddraw_geom)(" %f %f %f %f / %02lx %02lx %02lx %02lx - %02lx %02lx %02lx %02lx (%f %f)\n",
1202 position[0], position[1], position[2], position[3],
1203 (*color_d >> 16) & 0xFF,
1204 (*color_d >> 8) & 0xFF,
1205 (*color_d >> 0) & 0xFF,
1206 (*color_d >> 24) & 0xFF,
1207 (*color_s >> 16) & 0xFF,
1208 (*color_s >> 8) & 0xFF,
1209 (*color_s >> 0) & 0xFF,
1210 (*color_s >> 24) & 0xFF,
1211 tex_coord[0], tex_coord[1]);
1213 } else if (((d3dvtVertexType & D3DFVF_POSITION_MASK) == D3DFVF_XYZ) ||
1214 ((d3dvtVertexType & D3DFVF_POSITION_MASK) == D3DFVF_XYZRHW)) {
1215 /* This is the 'slow path' but that should support all possible vertex formats out there...
1216 Note that people should write a fast path for all vertex formats out there...
1218 int index;
1219 int num_tex_index = ((d3dvtVertexType & D3DFVF_TEXCOUNT_MASK) >> D3DFVF_TEXCOUNT_SHIFT);
1220 static const D3DVALUE no_index[] = { 0.0, 0.0, 0.0, 0.0 };
1222 for (index = 0; index < dwIndexCount; index++) {
1223 int i = (dwIndices == NULL) ? index : dwIndices[index];
1224 int tex_stage;
1226 if (d3dvtVertexType & D3DFVF_NORMAL) {
1227 D3DVALUE *normal =
1228 (D3DVALUE *) (((char *) lpD3DDrawPrimStrideData->normal.lpvData) + i * lpD3DDrawPrimStrideData->normal.dwStride);
1229 handle_normal(normal);
1231 if ((d3dvtVertexType & (D3DFVF_DIFFUSE|D3DFVF_SPECULAR)) == (D3DFVF_DIFFUSE|D3DFVF_SPECULAR)) {
1232 DWORD *color_d =
1233 (DWORD *) (((char *) lpD3DDrawPrimStrideData->diffuse.lpvData) + i * lpD3DDrawPrimStrideData->diffuse.dwStride);
1234 DWORD *color_s =
1235 (DWORD *) (((char *) lpD3DDrawPrimStrideData->specular.lpvData) + i * lpD3DDrawPrimStrideData->specular.dwStride);
1236 handle_diffuse_and_specular(&(This->state_block), glThis->fog_table, color_d, color_s, vertex_lighted);
1237 } else {
1238 if (d3dvtVertexType & D3DFVF_SPECULAR) {
1239 DWORD *color_s =
1240 (DWORD *) (((char *) lpD3DDrawPrimStrideData->specular.lpvData) + i * lpD3DDrawPrimStrideData->specular.dwStride);
1241 handle_specular(&(This->state_block), color_s, vertex_lighted);
1242 } else if (d3dvtVertexType & D3DFVF_DIFFUSE) {
1243 DWORD *color_d =
1244 (DWORD *) (((char *) lpD3DDrawPrimStrideData->diffuse.lpvData) + i * lpD3DDrawPrimStrideData->diffuse.dwStride);
1245 handle_diffuse(&(This->state_block), color_d, vertex_lighted);
1249 for (tex_stage = 0; tex_stage < num_active_stages; tex_stage++) {
1250 int tex_index = This->state_block.texture_stage_state[tex_stage][D3DTSS_TEXCOORDINDEX - 1] & 0xFFFF000;
1251 if (tex_index >= num_tex_index) {
1252 handle_textures((D3DVALUE *) no_index, tex_stage);
1253 } else {
1254 D3DVALUE *tex_coord =
1255 (D3DVALUE *) (((char *) lpD3DDrawPrimStrideData->textureCoords[tex_index].lpvData) +
1256 i * lpD3DDrawPrimStrideData->textureCoords[tex_index].dwStride);
1257 handle_textures(tex_coord, tex_stage);
1261 if ((d3dvtVertexType & D3DFVF_POSITION_MASK) == D3DFVF_XYZ) {
1262 D3DVALUE *position =
1263 (D3DVALUE *) (((char *) lpD3DDrawPrimStrideData->position.lpvData) + i * lpD3DDrawPrimStrideData->position.dwStride);
1264 handle_xyz(position);
1265 } else if ((d3dvtVertexType & D3DFVF_POSITION_MASK) == D3DFVF_XYZRHW) {
1266 D3DVALUE *position =
1267 (D3DVALUE *) (((char *) lpD3DDrawPrimStrideData->position.lpvData) + i * lpD3DDrawPrimStrideData->position.dwStride);
1268 handle_xyzrhw(position);
1271 if (TRACE_ON(ddraw_geom)) {
1272 int tex_index;
1274 if ((d3dvtVertexType & D3DFVF_POSITION_MASK) == D3DFVF_XYZ) {
1275 D3DVALUE *position =
1276 (D3DVALUE *) (((char *) lpD3DDrawPrimStrideData->position.lpvData) + i * lpD3DDrawPrimStrideData->position.dwStride);
1277 TRACE_(ddraw_geom)(" %f %f %f", position[0], position[1], position[2]);
1278 } else if ((d3dvtVertexType & D3DFVF_POSITION_MASK) == D3DFVF_XYZRHW) {
1279 D3DVALUE *position =
1280 (D3DVALUE *) (((char *) lpD3DDrawPrimStrideData->position.lpvData) + i * lpD3DDrawPrimStrideData->position.dwStride);
1281 TRACE_(ddraw_geom)(" %f %f %f %f", position[0], position[1], position[2], position[3]);
1283 if (d3dvtVertexType & D3DFVF_NORMAL) {
1284 D3DVALUE *normal =
1285 (D3DVALUE *) (((char *) lpD3DDrawPrimStrideData->normal.lpvData) + i * lpD3DDrawPrimStrideData->normal.dwStride);
1286 TRACE_(ddraw_geom)(" / %f %f %f", normal[0], normal[1], normal[2]);
1288 if (d3dvtVertexType & D3DFVF_DIFFUSE) {
1289 DWORD *color_d =
1290 (DWORD *) (((char *) lpD3DDrawPrimStrideData->diffuse.lpvData) + i * lpD3DDrawPrimStrideData->diffuse.dwStride);
1291 TRACE_(ddraw_geom)(" / %02lx %02lx %02lx %02lx",
1292 (*color_d >> 16) & 0xFF,
1293 (*color_d >> 8) & 0xFF,
1294 (*color_d >> 0) & 0xFF,
1295 (*color_d >> 24) & 0xFF);
1297 if (d3dvtVertexType & D3DFVF_SPECULAR) {
1298 DWORD *color_s =
1299 (DWORD *) (((char *) lpD3DDrawPrimStrideData->specular.lpvData) + i * lpD3DDrawPrimStrideData->specular.dwStride);
1300 TRACE_(ddraw_geom)(" / %02lx %02lx %02lx %02lx",
1301 (*color_s >> 16) & 0xFF,
1302 (*color_s >> 8) & 0xFF,
1303 (*color_s >> 0) & 0xFF,
1304 (*color_s >> 24) & 0xFF);
1306 for (tex_index = 0; tex_index < ((d3dvtVertexType & D3DFVF_TEXCOUNT_MASK) >> D3DFVF_TEXCOUNT_SHIFT); tex_index++) {
1307 D3DVALUE *tex_coord =
1308 (D3DVALUE *) (((char *) lpD3DDrawPrimStrideData->textureCoords[tex_index].lpvData) +
1309 i * lpD3DDrawPrimStrideData->textureCoords[tex_index].dwStride);
1310 TRACE_(ddraw_geom)(" / %f %f", tex_coord[0], tex_coord[1]);
1312 TRACE_(ddraw_geom)("\n");
1315 } else {
1316 ERR(" matrix weighting not handled yet....\n");
1319 glEnd();
1321 /* Whatever the case, disable the color material stuff */
1322 glDisable(GL_COLOR_MATERIAL);
1324 LEAVE_GL();
1325 TRACE("End\n");
1327 LeaveCriticalSection(&(This->crit));
1330 HRESULT WINAPI
1331 GL_IDirect3DDeviceImpl_7_3T_DrawPrimitive(LPDIRECT3DDEVICE7 iface,
1332 D3DPRIMITIVETYPE d3dptPrimitiveType,
1333 DWORD d3dvtVertexType,
1334 LPVOID lpvVertices,
1335 DWORD dwVertexCount,
1336 DWORD dwFlags)
1338 ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice7, iface);
1339 D3DDRAWPRIMITIVESTRIDEDDATA strided;
1341 TRACE("(%p/%p)->(%08x,%08lx,%p,%08lx,%08lx)\n", This, iface, d3dptPrimitiveType, d3dvtVertexType, lpvVertices, dwVertexCount, dwFlags);
1342 if (TRACE_ON(ddraw)) {
1343 TRACE(" - flags : "); dump_DPFLAGS(dwFlags);
1346 convert_FVF_to_strided_data(d3dvtVertexType, lpvVertices, &strided, 0);
1347 draw_primitive_strided(This, d3dptPrimitiveType, d3dvtVertexType, &strided, dwVertexCount, NULL, dwVertexCount, dwFlags);
1349 return DD_OK;
1352 HRESULT WINAPI
1353 GL_IDirect3DDeviceImpl_7_3T_DrawIndexedPrimitive(LPDIRECT3DDEVICE7 iface,
1354 D3DPRIMITIVETYPE d3dptPrimitiveType,
1355 DWORD d3dvtVertexType,
1356 LPVOID lpvVertices,
1357 DWORD dwVertexCount,
1358 LPWORD dwIndices,
1359 DWORD dwIndexCount,
1360 DWORD dwFlags)
1362 ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice7, iface);
1363 D3DDRAWPRIMITIVESTRIDEDDATA strided;
1365 TRACE("(%p/%p)->(%08x,%08lx,%p,%08lx,%p,%08lx,%08lx)\n", This, iface, d3dptPrimitiveType, d3dvtVertexType, lpvVertices, dwVertexCount, dwIndices, dwIndexCount, dwFlags);
1366 if (TRACE_ON(ddraw)) {
1367 TRACE(" - flags : "); dump_DPFLAGS(dwFlags);
1370 convert_FVF_to_strided_data(d3dvtVertexType, lpvVertices, &strided, 0);
1371 draw_primitive_strided(This, d3dptPrimitiveType, d3dvtVertexType, &strided, dwVertexCount, dwIndices, dwIndexCount, dwFlags);
1373 return DD_OK;
1376 HRESULT WINAPI
1377 GL_IDirect3DDeviceImpl_7_3T_DrawPrimitiveStrided(LPDIRECT3DDEVICE7 iface,
1378 D3DPRIMITIVETYPE d3dptPrimitiveType,
1379 DWORD dwVertexType,
1380 LPD3DDRAWPRIMITIVESTRIDEDDATA lpD3DDrawPrimStrideData,
1381 DWORD dwVertexCount,
1382 DWORD dwFlags)
1384 ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice7, iface);
1386 TRACE("(%p/%p)->(%08x,%08lx,%p,%08lx,%08lx)\n", This, iface, d3dptPrimitiveType, dwVertexType, lpD3DDrawPrimStrideData, dwVertexCount, dwFlags);
1387 if (TRACE_ON(ddraw)) {
1388 TRACE(" - flags : "); dump_DPFLAGS(dwFlags);
1390 draw_primitive_strided(This, d3dptPrimitiveType, dwVertexType, lpD3DDrawPrimStrideData, dwVertexCount, NULL, dwVertexCount, dwFlags);
1392 return DD_OK;
1395 HRESULT WINAPI
1396 GL_IDirect3DDeviceImpl_7_3T_DrawIndexedPrimitiveStrided(LPDIRECT3DDEVICE7 iface,
1397 D3DPRIMITIVETYPE d3dptPrimitiveType,
1398 DWORD dwVertexType,
1399 LPD3DDRAWPRIMITIVESTRIDEDDATA lpD3DDrawPrimStrideData,
1400 DWORD dwVertexCount,
1401 LPWORD lpIndex,
1402 DWORD dwIndexCount,
1403 DWORD dwFlags)
1405 ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice7, iface);
1407 TRACE("(%p/%p)->(%08x,%08lx,%p,%08lx,%p,%08lx,%08lx)\n", This, iface, d3dptPrimitiveType, dwVertexType, lpD3DDrawPrimStrideData, dwVertexCount, lpIndex, dwIndexCount, dwFlags);
1408 if (TRACE_ON(ddraw)) {
1409 TRACE(" - flags : "); dump_DPFLAGS(dwFlags);
1412 draw_primitive_strided(This, d3dptPrimitiveType, dwVertexType, lpD3DDrawPrimStrideData, dwVertexCount, lpIndex, dwIndexCount, dwFlags);
1414 return DD_OK;
1417 HRESULT WINAPI
1418 GL_IDirect3DDeviceImpl_7_3T_DrawPrimitiveVB(LPDIRECT3DDEVICE7 iface,
1419 D3DPRIMITIVETYPE d3dptPrimitiveType,
1420 LPDIRECT3DVERTEXBUFFER7 lpD3DVertexBuf,
1421 DWORD dwStartVertex,
1422 DWORD dwNumVertices,
1423 DWORD dwFlags)
1425 ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice7, iface);
1426 IDirect3DVertexBufferImpl *vb_impl = ICOM_OBJECT(IDirect3DVertexBufferImpl, IDirect3DVertexBuffer7, lpD3DVertexBuf);
1427 D3DDRAWPRIMITIVESTRIDEDDATA strided;
1429 TRACE("(%p/%p)->(%08x,%p,%08lx,%08lx,%08lx)\n", This, iface, d3dptPrimitiveType, lpD3DVertexBuf, dwStartVertex, dwNumVertices, dwFlags);
1430 if (TRACE_ON(ddraw)) {
1431 TRACE(" - flags : "); dump_DPFLAGS(dwFlags);
1434 if (vb_impl->processed == TRUE) {
1435 IDirect3DVertexBufferGLImpl *vb_glimp = (IDirect3DVertexBufferGLImpl *) vb_impl;
1436 IDirect3DDeviceGLImpl *glThis = (IDirect3DDeviceGLImpl *) This;
1438 glThis->transform_state = GL_TRANSFORM_VERTEXBUFFER;
1439 This->set_matrices(This, VIEWMAT_CHANGED|WORLDMAT_CHANGED|PROJMAT_CHANGED,
1440 &(vb_glimp->world_mat), &(vb_glimp->view_mat), &(vb_glimp->proj_mat));
1442 convert_FVF_to_strided_data(vb_glimp->dwVertexTypeDesc, vb_glimp->vertices, &strided, dwStartVertex);
1443 draw_primitive_strided(This, d3dptPrimitiveType, vb_glimp->dwVertexTypeDesc, &strided, dwNumVertices, NULL, dwNumVertices, dwFlags);
1445 } else {
1446 convert_FVF_to_strided_data(vb_impl->desc.dwFVF, vb_impl->vertices, &strided, dwStartVertex);
1447 draw_primitive_strided(This, d3dptPrimitiveType, vb_impl->desc.dwFVF, &strided, dwNumVertices, NULL, dwNumVertices, dwFlags);
1450 return DD_OK;
1453 HRESULT WINAPI
1454 GL_IDirect3DDeviceImpl_7_3T_DrawIndexedPrimitiveVB(LPDIRECT3DDEVICE7 iface,
1455 D3DPRIMITIVETYPE d3dptPrimitiveType,
1456 LPDIRECT3DVERTEXBUFFER7 lpD3DVertexBuf,
1457 DWORD dwStartVertex,
1458 DWORD dwNumVertices,
1459 LPWORD lpwIndices,
1460 DWORD dwIndexCount,
1461 DWORD dwFlags)
1463 ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice7, iface);
1464 IDirect3DVertexBufferImpl *vb_impl = ICOM_OBJECT(IDirect3DVertexBufferImpl, IDirect3DVertexBuffer7, lpD3DVertexBuf);
1465 D3DDRAWPRIMITIVESTRIDEDDATA strided;
1467 TRACE("(%p/%p)->(%08x,%p,%08lx,%08lx,%p,%08lx,%08lx)\n", This, iface, d3dptPrimitiveType, lpD3DVertexBuf, dwStartVertex, dwNumVertices, lpwIndices, dwIndexCount, dwFlags);
1468 if (TRACE_ON(ddraw)) {
1469 TRACE(" - flags : "); dump_DPFLAGS(dwFlags);
1472 if (vb_impl->processed == TRUE) {
1473 IDirect3DVertexBufferGLImpl *vb_glimp = (IDirect3DVertexBufferGLImpl *) vb_impl;
1474 IDirect3DDeviceGLImpl *glThis = (IDirect3DDeviceGLImpl *) This;
1476 glThis->transform_state = GL_TRANSFORM_VERTEXBUFFER;
1477 This->set_matrices(This, VIEWMAT_CHANGED|WORLDMAT_CHANGED|PROJMAT_CHANGED,
1478 &(vb_glimp->world_mat), &(vb_glimp->view_mat), &(vb_glimp->proj_mat));
1480 convert_FVF_to_strided_data(vb_glimp->dwVertexTypeDesc, vb_glimp->vertices, &strided, dwStartVertex);
1481 draw_primitive_strided(This, d3dptPrimitiveType, vb_glimp->dwVertexTypeDesc, &strided, dwNumVertices, lpwIndices, dwIndexCount, dwFlags);
1483 } else {
1484 convert_FVF_to_strided_data(vb_impl->desc.dwFVF, vb_impl->vertices, &strided, dwStartVertex);
1485 draw_primitive_strided(This, d3dptPrimitiveType, vb_impl->desc.dwFVF, &strided, dwNumVertices, lpwIndices, dwIndexCount, dwFlags);
1488 return DD_OK;
1491 static GLenum
1492 convert_min_filter_to_GL(D3DTEXTUREMINFILTER dwMinState, D3DTEXTUREMIPFILTER dwMipState)
1494 GLenum gl_state;
1496 if (dwMipState == D3DTFP_NONE) {
1497 switch (dwMinState) {
1498 case D3DTFN_POINT: gl_state = GL_NEAREST; break;
1499 case D3DTFN_LINEAR: gl_state = GL_LINEAR; break;
1500 default: gl_state = GL_LINEAR; break;
1502 } else if (dwMipState == D3DTFP_POINT) {
1503 switch (dwMinState) {
1504 case D3DTFN_POINT: gl_state = GL_NEAREST_MIPMAP_NEAREST; break;
1505 case D3DTFN_LINEAR: gl_state = GL_LINEAR_MIPMAP_NEAREST; break;
1506 default: gl_state = GL_LINEAR_MIPMAP_NEAREST; break;
1508 } else {
1509 switch (dwMinState) {
1510 case D3DTFN_POINT: gl_state = GL_NEAREST_MIPMAP_LINEAR; break;
1511 case D3DTFN_LINEAR: gl_state = GL_LINEAR_MIPMAP_LINEAR; break;
1512 default: gl_state = GL_LINEAR_MIPMAP_LINEAR; break;
1515 return gl_state;
1518 static GLenum
1519 convert_mag_filter_to_GL(D3DTEXTUREMAGFILTER dwState)
1521 GLenum gl_state;
1523 switch (dwState) {
1524 case D3DTFG_POINT:
1525 gl_state = GL_NEAREST;
1526 break;
1527 case D3DTFG_LINEAR:
1528 gl_state = GL_LINEAR;
1529 break;
1530 default:
1531 gl_state = GL_LINEAR;
1532 break;
1534 return gl_state;
1537 /* We need a static function for that to handle the 'special' case of 'SELECT_ARG2' */
1538 static BOOLEAN
1539 handle_color_alpha_args(IDirect3DDeviceImpl *This, DWORD dwStage, D3DTEXTURESTAGESTATETYPE d3dTexStageStateType, DWORD dwState, D3DTEXTUREOP tex_op)
1541 BOOLEAN is_complement = FALSE;
1542 BOOLEAN is_alpha_replicate = FALSE;
1543 BOOLEAN handled = TRUE;
1544 GLenum src;
1545 BOOLEAN is_color = ((d3dTexStageStateType == D3DTSS_COLORARG1) || (d3dTexStageStateType == D3DTSS_COLORARG2));
1546 int num;
1548 if (is_color) {
1549 if (d3dTexStageStateType == D3DTSS_COLORARG1) num = 0;
1550 else if (d3dTexStageStateType == D3DTSS_COLORARG2) num = 1;
1551 else {
1552 handled = FALSE;
1553 num = 0;
1555 if (tex_op == D3DTOP_SELECTARG2) {
1556 num = 1 - num;
1558 } else {
1559 if (d3dTexStageStateType == D3DTSS_ALPHAARG1) num = 0;
1560 else if (d3dTexStageStateType == D3DTSS_ALPHAARG2) num = 1;
1561 else {
1562 handled = FALSE;
1563 num = 0;
1565 if (tex_op == D3DTOP_SELECTARG2) {
1566 num = 1 - num;
1570 if (dwState & D3DTA_COMPLEMENT) {
1571 is_complement = TRUE;
1573 if (dwState & D3DTA_ALPHAREPLICATE) {
1574 is_alpha_replicate = TRUE;
1576 dwState &= D3DTA_SELECTMASK;
1577 if ((dwStage == 0) && (dwState == D3DTA_CURRENT)) {
1578 dwState = D3DTA_DIFFUSE;
1581 switch (dwState) {
1582 case D3DTA_CURRENT: src = GL_PREVIOUS_EXT; break;
1583 case D3DTA_DIFFUSE: src = GL_PRIMARY_COLOR_EXT; break;
1584 case D3DTA_TEXTURE: src = GL_TEXTURE; break;
1585 case D3DTA_TFACTOR: {
1586 /* Get the constant value from the current rendering state */
1587 GLfloat color[4];
1588 DWORD col = This->state_block.render_state[D3DRENDERSTATE_TEXTUREFACTOR - 1];
1590 color[0] = ((col >> 16) & 0xFF) / 255.0f;
1591 color[1] = ((col >> 8) & 0xFF) / 255.0f;
1592 color[2] = ((col >> 0) & 0xFF) / 255.0f;
1593 color[3] = ((col >> 24) & 0xFF) / 255.0f;
1594 glTexEnvfv(GL_TEXTURE_ENV, GL_TEXTURE_ENV_COLOR, color);
1596 src = GL_CONSTANT_EXT;
1597 } break;
1598 default: src = GL_TEXTURE; handled = FALSE; break;
1601 if (is_color) {
1602 glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_RGB_EXT + num, src);
1603 if (is_alpha_replicate) {
1604 glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND0_RGB_EXT + num, is_complement ? GL_ONE_MINUS_SRC_ALPHA : GL_SRC_ALPHA);
1605 } else {
1606 glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND0_RGB_EXT + num, is_complement ? GL_ONE_MINUS_SRC_COLOR : GL_SRC_COLOR);
1608 } else {
1609 glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_ALPHA_EXT + num, src);
1610 glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND0_ALPHA_EXT + num, is_complement ? GL_ONE_MINUS_SRC_ALPHA : GL_SRC_ALPHA);
1613 return handled;
1616 HRESULT WINAPI
1617 GL_IDirect3DDeviceImpl_7_3T_SetTextureStageState(LPDIRECT3DDEVICE7 iface,
1618 DWORD dwStage,
1619 D3DTEXTURESTAGESTATETYPE d3dTexStageStateType,
1620 DWORD dwState)
1622 ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice7, iface);
1623 const char *type;
1624 DWORD prev_state;
1626 TRACE("(%p/%p)->(%08lx,%08x,%08lx)\n", This, iface, dwStage, d3dTexStageStateType, dwState);
1628 if (dwStage > 0) return DD_OK; /* We nothing in this case for now */
1630 switch (d3dTexStageStateType) {
1631 #define GEN_CASE(a) case a: type = #a; break
1632 GEN_CASE(D3DTSS_COLOROP);
1633 GEN_CASE(D3DTSS_COLORARG1);
1634 GEN_CASE(D3DTSS_COLORARG2);
1635 GEN_CASE(D3DTSS_ALPHAOP);
1636 GEN_CASE(D3DTSS_ALPHAARG1);
1637 GEN_CASE(D3DTSS_ALPHAARG2);
1638 GEN_CASE(D3DTSS_BUMPENVMAT00);
1639 GEN_CASE(D3DTSS_BUMPENVMAT01);
1640 GEN_CASE(D3DTSS_BUMPENVMAT10);
1641 GEN_CASE(D3DTSS_BUMPENVMAT11);
1642 GEN_CASE(D3DTSS_TEXCOORDINDEX);
1643 GEN_CASE(D3DTSS_ADDRESS);
1644 GEN_CASE(D3DTSS_ADDRESSU);
1645 GEN_CASE(D3DTSS_ADDRESSV);
1646 GEN_CASE(D3DTSS_BORDERCOLOR);
1647 GEN_CASE(D3DTSS_MAGFILTER);
1648 GEN_CASE(D3DTSS_MINFILTER);
1649 GEN_CASE(D3DTSS_MIPFILTER);
1650 GEN_CASE(D3DTSS_MIPMAPLODBIAS);
1651 GEN_CASE(D3DTSS_MAXMIPLEVEL);
1652 GEN_CASE(D3DTSS_MAXANISOTROPY);
1653 GEN_CASE(D3DTSS_BUMPENVLSCALE);
1654 GEN_CASE(D3DTSS_BUMPENVLOFFSET);
1655 GEN_CASE(D3DTSS_TEXTURETRANSFORMFLAGS);
1656 #undef GEN_CASE
1657 default: type = "UNKNOWN";
1660 /* Store the values in the state array */
1661 prev_state = This->state_block.texture_stage_state[dwStage][d3dTexStageStateType - 1];
1662 This->state_block.texture_stage_state[dwStage][d3dTexStageStateType - 1] = dwState;
1663 /* Some special cases when one state modifies more than one... */
1664 if (d3dTexStageStateType == D3DTSS_ADDRESS) {
1665 This->state_block.texture_stage_state[dwStage][D3DTSS_ADDRESSU - 1] = dwState;
1666 This->state_block.texture_stage_state[dwStage][D3DTSS_ADDRESSV - 1] = dwState;
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 default:
1813 handled = FALSE;
1814 break;
1818 if (((prev_state == D3DTOP_SELECTARG2) && (dwState != D3DTOP_SELECTARG2)) ||
1819 ((dwState == D3DTOP_SELECTARG2) && (prev_state != D3DTOP_SELECTARG2))) {
1820 /* Switch the arguments if needed... */
1821 if (d3dTexStageStateType == D3DTSS_COLOROP) {
1822 handle_color_alpha_args(This, dwStage, D3DTSS_COLORARG1,
1823 This->state_block.texture_stage_state[dwStage][D3DTSS_COLORARG1 - 1],
1824 dwState);
1825 handle_color_alpha_args(This, dwStage, D3DTSS_COLORARG2,
1826 This->state_block.texture_stage_state[dwStage][D3DTSS_COLORARG2 - 1],
1827 dwState);
1828 } else {
1829 handle_color_alpha_args(This, dwStage, D3DTSS_ALPHAARG1,
1830 This->state_block.texture_stage_state[dwStage][D3DTSS_ALPHAARG1 - 1],
1831 dwState);
1832 handle_color_alpha_args(This, dwStage, D3DTSS_ALPHAARG2,
1833 This->state_block.texture_stage_state[dwStage][D3DTSS_ALPHAARG2 - 1],
1834 dwState);
1838 if (handled) {
1839 if (d3dTexStageStateType == D3DTSS_ALPHAOP) {
1840 glTexEnvi(GL_TEXTURE_ENV, GL_ALPHA_SCALE, scale);
1841 } else {
1842 glTexEnvi(GL_TEXTURE_ENV, GL_RGB_SCALE_EXT, scale);
1844 TRACE(" Stage type is : %s => %s\n", type, value);
1845 } else {
1846 FIXME(" Unhandled stage type is : %s => %s\n", type, value);
1848 } break;
1850 case D3DTSS_COLORARG1:
1851 case D3DTSS_COLORARG2:
1852 case D3DTSS_ALPHAARG1:
1853 case D3DTSS_ALPHAARG2: {
1854 const char *value, *value_comp = "", *value_alpha = "";
1855 BOOLEAN handled;
1856 D3DTEXTUREOP tex_op;
1858 switch (dwState & D3DTA_SELECTMASK) {
1859 #define GEN_CASE(a) case a: value = #a; break
1860 GEN_CASE(D3DTA_DIFFUSE);
1861 GEN_CASE(D3DTA_CURRENT);
1862 GEN_CASE(D3DTA_TEXTURE);
1863 GEN_CASE(D3DTA_TFACTOR);
1864 GEN_CASE(D3DTA_SPECULAR);
1865 #undef GEN_CASE
1866 default: value = "UNKNOWN";
1868 if (dwState & D3DTA_COMPLEMENT) {
1869 value_comp = " | D3DTA_COMPLEMENT";
1871 if (dwState & D3DTA_ALPHAREPLICATE) {
1872 value_alpha = " | D3DTA_ALPHAREPLICATE";
1875 if ((d3dTexStageStateType == D3DTSS_COLORARG1) || (d3dTexStageStateType == D3DTSS_COLORARG2)) {
1876 tex_op = This->state_block.texture_stage_state[dwStage][D3DTSS_COLOROP - 1];
1877 } else {
1878 tex_op = This->state_block.texture_stage_state[dwStage][D3DTSS_ALPHAOP - 1];
1881 handled = handle_color_alpha_args(This, dwStage, d3dTexStageStateType, dwState, tex_op);
1883 if (handled) {
1884 TRACE(" Stage type : %s => %s%s%s\n", type, value, value_comp, value_alpha);
1885 } else {
1886 FIXME(" Unhandled stage type : %s => %s%s%s\n", type, value, value_comp, value_alpha);
1888 } break;
1890 case D3DTSS_MIPMAPLODBIAS: {
1891 D3DVALUE value = *((D3DVALUE *) &dwState);
1892 BOOLEAN handled = TRUE;
1894 if (value != 0.0)
1895 handled = FALSE;
1897 if (handled) {
1898 TRACE(" Stage type : D3DTSS_MIPMAPLODBIAS => %f\n", value);
1899 } else {
1900 FIXME(" Unhandled stage type : D3DTSS_MIPMAPLODBIAS => %f\n", value);
1902 } break;
1904 case D3DTSS_MAXMIPLEVEL:
1905 if (dwState == 0) {
1906 TRACE(" Stage type : D3DTSS_MAXMIPLEVEL => 0 (disabled) \n");
1907 } else {
1908 FIXME(" Unhandled stage type : D3DTSS_MAXMIPLEVEL => %ld\n", dwState);
1910 break;
1912 case D3DTSS_BORDERCOLOR: {
1913 GLfloat color[4];
1915 color[0] = ((dwState >> 16) & 0xFF) / 255.0;
1916 color[1] = ((dwState >> 8) & 0xFF) / 255.0;
1917 color[2] = ((dwState >> 0) & 0xFF) / 255.0;
1918 color[3] = ((dwState >> 24) & 0xFF) / 255.0;
1920 glTexParameterfv(GL_TEXTURE_2D, GL_TEXTURE_BORDER_COLOR, color);
1922 TRACE(" Stage type : D3DTSS_BORDERCOLOR => %02lx %02lx %02lx %02lx (RGBA)\n",
1923 ((dwState >> 16) & 0xFF),
1924 ((dwState >> 8) & 0xFF),
1925 ((dwState >> 0) & 0xFF),
1926 ((dwState >> 24) & 0xFF));
1927 } break;
1929 case D3DTSS_TEXCOORDINDEX: {
1930 BOOLEAN handled = TRUE;
1931 const char *value;
1933 switch (dwState & 0xFFFF0000) {
1934 #define GEN_CASE(a) case a: value = #a; break
1935 GEN_CASE(D3DTSS_TCI_PASSTHRU);
1936 GEN_CASE(D3DTSS_TCI_CAMERASPACENORMAL);
1937 GEN_CASE(D3DTSS_TCI_CAMERASPACEPOSITION);
1938 GEN_CASE(D3DTSS_TCI_CAMERASPACEREFLECTIONVECTOR);
1939 #undef GEN_CASE
1940 default: value = "UNKNOWN";
1942 if ((dwState & 0xFFFF0000) != D3DTSS_TCI_PASSTHRU)
1943 handled = FALSE;
1945 if (handled) {
1946 TRACE(" Stage type : D3DTSS_TEXCOORDINDEX => %ld | %s\n", dwState & 0x0000FFFF, value);
1947 } else {
1948 FIXME(" Unhandled stage type : D3DTSS_TEXCOORDINDEX => %ld | %s\n", dwState & 0x0000FFFF, value);
1950 } break;
1952 case D3DTSS_TEXTURETRANSFORMFLAGS: {
1953 const char *projected = "", *value;
1954 BOOLEAN handled = TRUE;
1955 switch (dwState & 0xFF) {
1956 #define GEN_CASE(a) case a: value = #a; break
1957 GEN_CASE(D3DTTFF_DISABLE);
1958 GEN_CASE(D3DTTFF_COUNT1);
1959 GEN_CASE(D3DTTFF_COUNT2);
1960 GEN_CASE(D3DTTFF_COUNT3);
1961 GEN_CASE(D3DTTFF_COUNT4);
1962 #undef GEN_CASE
1963 default: value = "UNKNOWN";
1965 if (dwState & D3DTTFF_PROJECTED) {
1966 projected = " | D3DTTFF_PROJECTED";
1967 handled = FALSE;
1970 if ((dwState & 0xFF) != D3DTTFF_DISABLE) {
1971 This->matrices_updated(This, TEXMAT0_CHANGED << dwStage);
1974 if (handled == TRUE) {
1975 TRACE(" Stage type : D3DTSS_TEXTURETRANSFORMFLAGS => %s%s\n", value, projected);
1976 } else {
1977 FIXME(" Unhandled stage type : D3DTSS_TEXTURETRANSFORMFLAGS => %s%s\n", value, projected);
1979 } break;
1981 default:
1982 FIXME(" Unhandled stage type : %s => %08lx\n", type, dwState);
1983 break;
1986 return DD_OK;
1989 HRESULT WINAPI
1990 GL_IDirect3DDeviceImpl_7_3T_SetTexture(LPDIRECT3DDEVICE7 iface,
1991 DWORD dwStage,
1992 LPDIRECTDRAWSURFACE7 lpTexture2)
1994 ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice7, iface);
1996 TRACE("(%p/%p)->(%08lx,%p)\n", This, iface, dwStage, lpTexture2);
1998 if (dwStage > 0) return DD_OK;
2000 if (This->current_texture[dwStage] != NULL) {
2001 IDirectDrawSurface7_Release(ICOM_INTERFACE(This->current_texture[dwStage], IDirectDrawSurface7));
2004 ENTER_GL();
2005 if (lpTexture2 == NULL) {
2006 This->current_texture[dwStage] = NULL;
2008 TRACE(" disabling 2D texturing.\n");
2009 glBindTexture(GL_TEXTURE_2D, 0);
2010 glDisable(GL_TEXTURE_2D);
2011 } else {
2012 IDirectDrawSurfaceImpl *tex_impl = ICOM_OBJECT(IDirectDrawSurfaceImpl, IDirectDrawSurface7, lpTexture2);
2013 GLint max_mip_level;
2015 This->current_texture[dwStage] = tex_impl;
2016 IDirectDrawSurface7_AddRef(ICOM_INTERFACE(tex_impl, IDirectDrawSurface7)); /* Not sure about this either */
2018 if (This->state_block.texture_stage_state[dwStage][D3DTSS_COLOROP - 1] != D3DTOP_DISABLE) {
2019 /* Do not re-enable texturing if it was disabled due to the COLOROP code */
2020 glEnable(GL_TEXTURE_2D);
2021 TRACE(" enabling 2D texturing.\n");
2023 gltex_upload_texture(tex_impl);
2025 if ((tex_impl->surface_desc.ddsCaps.dwCaps & DDSCAPS_MIPMAP) == 0) {
2026 max_mip_level = 0;
2027 } else {
2028 max_mip_level = tex_impl->surface_desc.u2.dwMipMapCount - 1;
2031 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER,
2032 convert_mag_filter_to_GL(This->state_block.texture_stage_state[dwStage][D3DTSS_MAGFILTER - 1]));
2033 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER,
2034 convert_min_filter_to_GL(This->state_block.texture_stage_state[dwStage][D3DTSS_MINFILTER - 1],
2035 This->state_block.texture_stage_state[dwStage][D3DTSS_MIPFILTER - 1]));
2036 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LEVEL, max_mip_level);
2038 LEAVE_GL();
2040 return DD_OK;
2043 HRESULT WINAPI
2044 GL_IDirect3DDeviceImpl_7_GetCaps(LPDIRECT3DDEVICE7 iface,
2045 LPD3DDEVICEDESC7 lpD3DHELDevDesc)
2047 ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice7, iface);
2048 TRACE("(%p/%p)->(%p)\n", This, iface, lpD3DHELDevDesc);
2050 fill_opengl_caps_7(lpD3DHELDevDesc);
2052 TRACE(" returning caps : no dump function yet.\n");
2054 return DD_OK;
2057 HRESULT WINAPI
2058 GL_IDirect3DDeviceImpl_7_SetMaterial(LPDIRECT3DDEVICE7 iface,
2059 LPD3DMATERIAL7 lpMat)
2061 ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice7, iface);
2062 TRACE("(%p/%p)->(%p)\n", This, iface, lpMat);
2064 if (TRACE_ON(ddraw)) {
2065 TRACE(" material is : \n");
2066 dump_D3DMATERIAL7(lpMat);
2069 This->current_material = *lpMat;
2071 glMaterialfv(GL_FRONT_AND_BACK,
2072 GL_DIFFUSE,
2073 (float *) &(This->current_material.u.diffuse));
2074 glMaterialfv(GL_FRONT_AND_BACK,
2075 GL_AMBIENT,
2076 (float *) &(This->current_material.u1.ambient));
2077 glMaterialfv(GL_FRONT_AND_BACK,
2078 GL_SPECULAR,
2079 (float *) &(This->current_material.u2.specular));
2080 glMaterialfv(GL_FRONT_AND_BACK,
2081 GL_EMISSION,
2082 (float *) &(This->current_material.u3.emissive));
2083 glMaterialf(GL_FRONT_AND_BACK,
2084 GL_SHININESS,
2085 This->current_material.u4.power); /* Not sure about this... */
2087 return DD_OK;
2091 HRESULT WINAPI
2092 GL_IDirect3DDeviceImpl_7_SetLight(LPDIRECT3DDEVICE7 iface,
2093 DWORD dwLightIndex,
2094 LPD3DLIGHT7 lpLight)
2096 ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice7, iface);
2097 TRACE("(%p/%p)->(%08lx,%p)\n", This, iface, dwLightIndex, lpLight);
2099 if (TRACE_ON(ddraw)) {
2100 TRACE(" setting light : \n");
2101 dump_D3DLIGHT7(lpLight);
2104 if (dwLightIndex > MAX_LIGHTS) return DDERR_INVALIDPARAMS;
2105 This->set_lights |= 0x00000001 << dwLightIndex;
2106 This->light_parameters[dwLightIndex] = *lpLight;
2108 switch (lpLight->dltType) {
2109 case D3DLIGHT_DIRECTIONAL: {
2110 float direction[4];
2111 float cut_off = 180.0;
2113 glLightfv(GL_LIGHT0 + dwLightIndex, GL_AMBIENT, (float *) &(lpLight->dcvAmbient));
2114 glLightfv(GL_LIGHT0 + dwLightIndex, GL_DIFFUSE, (float *) &(lpLight->dcvDiffuse));
2115 glLightfv(GL_LIGHT0 + dwLightIndex, GL_SPECULAR, (float *) &(lpLight->dcvSpecular));
2116 glLightfv(GL_LIGHT0 + dwLightIndex, GL_SPOT_CUTOFF, &cut_off);
2118 direction[0] = lpLight->dvDirection.u1.x;
2119 direction[1] = lpLight->dvDirection.u2.y;
2120 direction[2] = lpLight->dvDirection.u3.z;
2121 direction[3] = 0.0;
2122 glLightfv(GL_LIGHT0 + dwLightIndex, GL_POSITION, (float *) direction);
2123 } break;
2125 case D3DLIGHT_POINT: {
2126 float position[4];
2127 float cut_off = 180.0;
2129 glLightfv(GL_LIGHT0 + dwLightIndex, GL_AMBIENT, (float *) &(lpLight->dcvAmbient));
2130 glLightfv(GL_LIGHT0 + dwLightIndex, GL_DIFFUSE, (float *) &(lpLight->dcvDiffuse));
2131 glLightfv(GL_LIGHT0 + dwLightIndex, GL_SPECULAR, (float *) &(lpLight->dcvSpecular));
2132 position[0] = lpLight->dvPosition.u1.x;
2133 position[1] = lpLight->dvPosition.u2.y;
2134 position[2] = lpLight->dvPosition.u3.z;
2135 position[3] = 1.0;
2136 glLightfv(GL_LIGHT0 + dwLightIndex, GL_POSITION, (float *) position);
2137 glLightfv(GL_LIGHT0 + dwLightIndex, GL_CONSTANT_ATTENUATION, &(lpLight->dvAttenuation0));
2138 glLightfv(GL_LIGHT0 + dwLightIndex, GL_LINEAR_ATTENUATION, &(lpLight->dvAttenuation1));
2139 glLightfv(GL_LIGHT0 + dwLightIndex, GL_QUADRATIC_ATTENUATION, &(lpLight->dvAttenuation2));
2140 glLightfv(GL_LIGHT0 + dwLightIndex, GL_SPOT_CUTOFF, &cut_off);
2141 } break;
2143 case D3DLIGHT_SPOT: {
2144 float direction[4];
2145 float position[4];
2146 float cut_off = 90.0 * (lpLight->dvPhi / M_PI);
2148 glLightfv(GL_LIGHT0 + dwLightIndex, GL_AMBIENT, (float *) &(lpLight->dcvAmbient));
2149 glLightfv(GL_LIGHT0 + dwLightIndex, GL_DIFFUSE, (float *) &(lpLight->dcvDiffuse));
2150 glLightfv(GL_LIGHT0 + dwLightIndex, GL_SPECULAR, (float *) &(lpLight->dcvSpecular));
2152 direction[0] = lpLight->dvDirection.u1.x;
2153 direction[1] = lpLight->dvDirection.u2.y;
2154 direction[2] = lpLight->dvDirection.u3.z;
2155 direction[3] = 0.0;
2156 glLightfv(GL_LIGHT0 + dwLightIndex, GL_SPOT_DIRECTION, (float *) direction);
2157 position[0] = lpLight->dvPosition.u1.x;
2158 position[1] = lpLight->dvPosition.u2.y;
2159 position[2] = lpLight->dvPosition.u3.z;
2160 position[3] = 1.0;
2161 glLightfv(GL_LIGHT0 + dwLightIndex, GL_POSITION, (float *) position);
2162 glLightfv(GL_LIGHT0 + dwLightIndex, GL_CONSTANT_ATTENUATION, &(lpLight->dvAttenuation0));
2163 glLightfv(GL_LIGHT0 + dwLightIndex, GL_LINEAR_ATTENUATION, &(lpLight->dvAttenuation1));
2164 glLightfv(GL_LIGHT0 + dwLightIndex, GL_QUADRATIC_ATTENUATION, &(lpLight->dvAttenuation2));
2165 glLightfv(GL_LIGHT0 + dwLightIndex, GL_SPOT_CUTOFF, &cut_off);
2166 glLightfv(GL_LIGHT0 + dwLightIndex, GL_SPOT_EXPONENT, &(lpLight->dvFalloff));
2167 if ((lpLight->dvTheta != 0.0) || (lpLight->dvTheta != lpLight->dvPhi)) {
2168 WARN("dvTheta not fully supported yet !\n");
2170 } break;
2172 default: WARN(" light type not handled yet...\n");
2175 return DD_OK;
2178 HRESULT WINAPI
2179 GL_IDirect3DDeviceImpl_7_LightEnable(LPDIRECT3DDEVICE7 iface,
2180 DWORD dwLightIndex,
2181 BOOL bEnable)
2183 ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice7, iface);
2184 TRACE("(%p/%p)->(%08lx,%d)\n", This, iface, dwLightIndex, bEnable);
2186 if (dwLightIndex > MAX_LIGHTS) return DDERR_INVALIDPARAMS;
2188 if (bEnable) {
2189 if (((0x00000001 << dwLightIndex) & This->set_lights) == 0) {
2190 /* Set the default parameters.. */
2191 TRACE(" setting default light parameters...\n");
2192 GL_IDirect3DDeviceImpl_7_SetLight(iface, dwLightIndex, &(This->light_parameters[dwLightIndex]));
2194 glEnable(GL_LIGHT0 + dwLightIndex);
2195 } else {
2196 glDisable(GL_LIGHT0 + dwLightIndex);
2199 return DD_OK;
2202 HRESULT WINAPI
2203 GL_IDirect3DDeviceImpl_7_SetClipPlane(LPDIRECT3DDEVICE7 iface, DWORD dwIndex, CONST D3DVALUE* pPlaneEquation)
2205 ICOM_THIS(IDirect3DDeviceImpl,iface);
2206 GLdouble plane[4];
2208 TRACE("(%p)->(%ld,%p)\n", This, dwIndex, pPlaneEquation);
2210 if (dwIndex >= This->max_clipping_planes) {
2211 return DDERR_INVALIDPARAMS;
2214 TRACE(" clip plane %ld : %f %f %f %f\n", dwIndex, pPlaneEquation[0], pPlaneEquation[1], pPlaneEquation[2], pPlaneEquation[3] );
2216 memcpy(This->clipping_planes[dwIndex].plane, pPlaneEquation, sizeof(D3DVALUE[4]));
2217 plane[0] = pPlaneEquation[0];
2218 plane[1] = pPlaneEquation[1];
2219 plane[2] = pPlaneEquation[2];
2220 plane[3] = pPlaneEquation[3];
2222 /* XXX: is here also code needed to handle the transformation of the world? */
2223 glClipPlane( GL_CLIP_PLANE0 + dwIndex, (const GLdouble*) (&plane) );
2225 return D3D_OK;
2228 HRESULT WINAPI
2229 GL_IDirect3DDeviceImpl_7_SetViewport(LPDIRECT3DDEVICE7 iface,
2230 LPD3DVIEWPORT7 lpData)
2232 ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice7, iface);
2233 TRACE("(%p/%p)->(%p)\n", This, iface, lpData);
2235 if (TRACE_ON(ddraw)) {
2236 TRACE(" viewport is : \n");
2237 TRACE(" - dwX = %ld dwY = %ld\n",
2238 lpData->dwX, lpData->dwY);
2239 TRACE(" - dwWidth = %ld dwHeight = %ld\n",
2240 lpData->dwWidth, lpData->dwHeight);
2241 TRACE(" - dvMinZ = %f dvMaxZ = %f\n",
2242 lpData->dvMinZ, lpData->dvMaxZ);
2244 This->active_viewport = *lpData;
2246 /* Set the viewport */
2247 glDepthRange(lpData->dvMinZ, lpData->dvMaxZ);
2248 glViewport(lpData->dwX,
2249 This->surface->surface_desc.dwHeight - (lpData->dwHeight + lpData->dwY),
2250 lpData->dwWidth, lpData->dwHeight);
2252 return DD_OK;
2255 #if !defined(__STRICT_ANSI__) && defined(__GNUC__)
2256 # define XCAST(fun) (typeof(VTABLE_IDirect3DDevice7.fun))
2257 #else
2258 # define XCAST(fun) (void*)
2259 #endif
2261 ICOM_VTABLE(IDirect3DDevice7) VTABLE_IDirect3DDevice7 =
2263 ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
2264 XCAST(QueryInterface) Main_IDirect3DDeviceImpl_7_3T_2T_1T_QueryInterface,
2265 XCAST(AddRef) Main_IDirect3DDeviceImpl_7_3T_2T_1T_AddRef,
2266 XCAST(Release) GL_IDirect3DDeviceImpl_7_3T_2T_1T_Release,
2267 XCAST(GetCaps) GL_IDirect3DDeviceImpl_7_GetCaps,
2268 XCAST(EnumTextureFormats) GL_IDirect3DDeviceImpl_7_3T_EnumTextureFormats,
2269 XCAST(BeginScene) Main_IDirect3DDeviceImpl_7_3T_2T_1T_BeginScene,
2270 XCAST(EndScene) Main_IDirect3DDeviceImpl_7_3T_2T_1T_EndScene,
2271 XCAST(GetDirect3D) Main_IDirect3DDeviceImpl_7_3T_2T_1T_GetDirect3D,
2272 XCAST(SetRenderTarget) Main_IDirect3DDeviceImpl_7_3T_2T_SetRenderTarget,
2273 XCAST(GetRenderTarget) Main_IDirect3DDeviceImpl_7_3T_2T_GetRenderTarget,
2274 XCAST(Clear) Main_IDirect3DDeviceImpl_7_Clear,
2275 XCAST(SetTransform) Main_IDirect3DDeviceImpl_7_3T_2T_SetTransform,
2276 XCAST(GetTransform) Main_IDirect3DDeviceImpl_7_3T_2T_GetTransform,
2277 XCAST(SetViewport) GL_IDirect3DDeviceImpl_7_SetViewport,
2278 XCAST(MultiplyTransform) Main_IDirect3DDeviceImpl_7_3T_2T_MultiplyTransform,
2279 XCAST(GetViewport) Main_IDirect3DDeviceImpl_7_GetViewport,
2280 XCAST(SetMaterial) GL_IDirect3DDeviceImpl_7_SetMaterial,
2281 XCAST(GetMaterial) Main_IDirect3DDeviceImpl_7_GetMaterial,
2282 XCAST(SetLight) GL_IDirect3DDeviceImpl_7_SetLight,
2283 XCAST(GetLight) Main_IDirect3DDeviceImpl_7_GetLight,
2284 XCAST(SetRenderState) GL_IDirect3DDeviceImpl_7_3T_2T_SetRenderState,
2285 XCAST(GetRenderState) GL_IDirect3DDeviceImpl_7_3T_2T_GetRenderState,
2286 XCAST(BeginStateBlock) Main_IDirect3DDeviceImpl_7_BeginStateBlock,
2287 XCAST(EndStateBlock) Main_IDirect3DDeviceImpl_7_EndStateBlock,
2288 XCAST(PreLoad) Main_IDirect3DDeviceImpl_7_PreLoad,
2289 XCAST(DrawPrimitive) GL_IDirect3DDeviceImpl_7_3T_DrawPrimitive,
2290 XCAST(DrawIndexedPrimitive) GL_IDirect3DDeviceImpl_7_3T_DrawIndexedPrimitive,
2291 XCAST(SetClipStatus) Main_IDirect3DDeviceImpl_7_3T_2T_SetClipStatus,
2292 XCAST(GetClipStatus) Main_IDirect3DDeviceImpl_7_3T_2T_GetClipStatus,
2293 XCAST(DrawPrimitiveStrided) GL_IDirect3DDeviceImpl_7_3T_DrawPrimitiveStrided,
2294 XCAST(DrawIndexedPrimitiveStrided) GL_IDirect3DDeviceImpl_7_3T_DrawIndexedPrimitiveStrided,
2295 XCAST(DrawPrimitiveVB) GL_IDirect3DDeviceImpl_7_3T_DrawPrimitiveVB,
2296 XCAST(DrawIndexedPrimitiveVB) GL_IDirect3DDeviceImpl_7_3T_DrawIndexedPrimitiveVB,
2297 XCAST(ComputeSphereVisibility) Main_IDirect3DDeviceImpl_7_3T_ComputeSphereVisibility,
2298 XCAST(GetTexture) Main_IDirect3DDeviceImpl_7_3T_GetTexture,
2299 XCAST(SetTexture) GL_IDirect3DDeviceImpl_7_3T_SetTexture,
2300 XCAST(GetTextureStageState) Main_IDirect3DDeviceImpl_7_3T_GetTextureStageState,
2301 XCAST(SetTextureStageState) GL_IDirect3DDeviceImpl_7_3T_SetTextureStageState,
2302 XCAST(ValidateDevice) Main_IDirect3DDeviceImpl_7_3T_ValidateDevice,
2303 XCAST(ApplyStateBlock) Main_IDirect3DDeviceImpl_7_ApplyStateBlock,
2304 XCAST(CaptureStateBlock) Main_IDirect3DDeviceImpl_7_CaptureStateBlock,
2305 XCAST(DeleteStateBlock) Main_IDirect3DDeviceImpl_7_DeleteStateBlock,
2306 XCAST(CreateStateBlock) Main_IDirect3DDeviceImpl_7_CreateStateBlock,
2307 XCAST(Load) Main_IDirect3DDeviceImpl_7_Load,
2308 XCAST(LightEnable) GL_IDirect3DDeviceImpl_7_LightEnable,
2309 XCAST(GetLightEnable) Main_IDirect3DDeviceImpl_7_GetLightEnable,
2310 XCAST(SetClipPlane) GL_IDirect3DDeviceImpl_7_SetClipPlane,
2311 XCAST(GetClipPlane) Main_IDirect3DDeviceImpl_7_GetClipPlane,
2312 XCAST(GetInfo) Main_IDirect3DDeviceImpl_7_GetInfo,
2315 #if !defined(__STRICT_ANSI__) && defined(__GNUC__)
2316 #undef XCAST
2317 #endif
2320 #if !defined(__STRICT_ANSI__) && defined(__GNUC__)
2321 # define XCAST(fun) (typeof(VTABLE_IDirect3DDevice3.fun))
2322 #else
2323 # define XCAST(fun) (void*)
2324 #endif
2326 ICOM_VTABLE(IDirect3DDevice3) VTABLE_IDirect3DDevice3 =
2328 ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
2329 XCAST(QueryInterface) Thunk_IDirect3DDeviceImpl_3_QueryInterface,
2330 XCAST(AddRef) Thunk_IDirect3DDeviceImpl_3_AddRef,
2331 XCAST(Release) Thunk_IDirect3DDeviceImpl_3_Release,
2332 XCAST(GetCaps) GL_IDirect3DDeviceImpl_3_2T_1T_GetCaps,
2333 XCAST(GetStats) Main_IDirect3DDeviceImpl_3_2T_1T_GetStats,
2334 XCAST(AddViewport) Main_IDirect3DDeviceImpl_3_2T_1T_AddViewport,
2335 XCAST(DeleteViewport) Main_IDirect3DDeviceImpl_3_2T_1T_DeleteViewport,
2336 XCAST(NextViewport) Main_IDirect3DDeviceImpl_3_2T_1T_NextViewport,
2337 XCAST(EnumTextureFormats) Thunk_IDirect3DDeviceImpl_3_EnumTextureFormats,
2338 XCAST(BeginScene) Thunk_IDirect3DDeviceImpl_3_BeginScene,
2339 XCAST(EndScene) Thunk_IDirect3DDeviceImpl_3_EndScene,
2340 XCAST(GetDirect3D) Thunk_IDirect3DDeviceImpl_3_GetDirect3D,
2341 XCAST(SetCurrentViewport) Main_IDirect3DDeviceImpl_3_2T_SetCurrentViewport,
2342 XCAST(GetCurrentViewport) Main_IDirect3DDeviceImpl_3_2T_GetCurrentViewport,
2343 XCAST(SetRenderTarget) Thunk_IDirect3DDeviceImpl_3_SetRenderTarget,
2344 XCAST(GetRenderTarget) Thunk_IDirect3DDeviceImpl_3_GetRenderTarget,
2345 XCAST(Begin) Main_IDirect3DDeviceImpl_3_Begin,
2346 XCAST(BeginIndexed) Main_IDirect3DDeviceImpl_3_BeginIndexed,
2347 XCAST(Vertex) Main_IDirect3DDeviceImpl_3_2T_Vertex,
2348 XCAST(Index) Main_IDirect3DDeviceImpl_3_2T_Index,
2349 XCAST(End) Main_IDirect3DDeviceImpl_3_2T_End,
2350 XCAST(GetRenderState) Thunk_IDirect3DDeviceImpl_3_GetRenderState,
2351 XCAST(SetRenderState) Thunk_IDirect3DDeviceImpl_3_SetRenderState,
2352 XCAST(GetLightState) Main_IDirect3DDeviceImpl_3_2T_GetLightState,
2353 XCAST(SetLightState) GL_IDirect3DDeviceImpl_3_2T_SetLightState,
2354 XCAST(SetTransform) Thunk_IDirect3DDeviceImpl_3_SetTransform,
2355 XCAST(GetTransform) Thunk_IDirect3DDeviceImpl_3_GetTransform,
2356 XCAST(MultiplyTransform) Thunk_IDirect3DDeviceImpl_3_MultiplyTransform,
2357 XCAST(DrawPrimitive) Thunk_IDirect3DDeviceImpl_3_DrawPrimitive,
2358 XCAST(DrawIndexedPrimitive) Thunk_IDirect3DDeviceImpl_3_DrawIndexedPrimitive,
2359 XCAST(SetClipStatus) Thunk_IDirect3DDeviceImpl_3_SetClipStatus,
2360 XCAST(GetClipStatus) Thunk_IDirect3DDeviceImpl_3_GetClipStatus,
2361 XCAST(DrawPrimitiveStrided) Thunk_IDirect3DDeviceImpl_3_DrawPrimitiveStrided,
2362 XCAST(DrawIndexedPrimitiveStrided) Thunk_IDirect3DDeviceImpl_3_DrawIndexedPrimitiveStrided,
2363 XCAST(DrawPrimitiveVB) Thunk_IDirect3DDeviceImpl_3_DrawPrimitiveVB,
2364 XCAST(DrawIndexedPrimitiveVB) Thunk_IDirect3DDeviceImpl_3_DrawIndexedPrimitiveVB,
2365 XCAST(ComputeSphereVisibility) Thunk_IDirect3DDeviceImpl_3_ComputeSphereVisibility,
2366 XCAST(GetTexture) Thunk_IDirect3DDeviceImpl_3_GetTexture,
2367 XCAST(SetTexture) Thunk_IDirect3DDeviceImpl_3_SetTexture,
2368 XCAST(GetTextureStageState) Thunk_IDirect3DDeviceImpl_3_GetTextureStageState,
2369 XCAST(SetTextureStageState) Thunk_IDirect3DDeviceImpl_3_SetTextureStageState,
2370 XCAST(ValidateDevice) Thunk_IDirect3DDeviceImpl_3_ValidateDevice,
2373 #if !defined(__STRICT_ANSI__) && defined(__GNUC__)
2374 #undef XCAST
2375 #endif
2378 #if !defined(__STRICT_ANSI__) && defined(__GNUC__)
2379 # define XCAST(fun) (typeof(VTABLE_IDirect3DDevice2.fun))
2380 #else
2381 # define XCAST(fun) (void*)
2382 #endif
2384 ICOM_VTABLE(IDirect3DDevice2) VTABLE_IDirect3DDevice2 =
2386 ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
2387 XCAST(QueryInterface) Thunk_IDirect3DDeviceImpl_2_QueryInterface,
2388 XCAST(AddRef) Thunk_IDirect3DDeviceImpl_2_AddRef,
2389 XCAST(Release) Thunk_IDirect3DDeviceImpl_2_Release,
2390 XCAST(GetCaps) Thunk_IDirect3DDeviceImpl_2_GetCaps,
2391 XCAST(SwapTextureHandles) Main_IDirect3DDeviceImpl_2_1T_SwapTextureHandles,
2392 XCAST(GetStats) Thunk_IDirect3DDeviceImpl_2_GetStats,
2393 XCAST(AddViewport) Thunk_IDirect3DDeviceImpl_2_AddViewport,
2394 XCAST(DeleteViewport) Thunk_IDirect3DDeviceImpl_2_DeleteViewport,
2395 XCAST(NextViewport) Thunk_IDirect3DDeviceImpl_2_NextViewport,
2396 XCAST(EnumTextureFormats) GL_IDirect3DDeviceImpl_2_1T_EnumTextureFormats,
2397 XCAST(BeginScene) Thunk_IDirect3DDeviceImpl_2_BeginScene,
2398 XCAST(EndScene) Thunk_IDirect3DDeviceImpl_2_EndScene,
2399 XCAST(GetDirect3D) Thunk_IDirect3DDeviceImpl_2_GetDirect3D,
2400 XCAST(SetCurrentViewport) Thunk_IDirect3DDeviceImpl_2_SetCurrentViewport,
2401 XCAST(GetCurrentViewport) Thunk_IDirect3DDeviceImpl_2_GetCurrentViewport,
2402 XCAST(SetRenderTarget) Thunk_IDirect3DDeviceImpl_2_SetRenderTarget,
2403 XCAST(GetRenderTarget) Thunk_IDirect3DDeviceImpl_2_GetRenderTarget,
2404 XCAST(Begin) Main_IDirect3DDeviceImpl_2_Begin,
2405 XCAST(BeginIndexed) Main_IDirect3DDeviceImpl_2_BeginIndexed,
2406 XCAST(Vertex) Thunk_IDirect3DDeviceImpl_2_Vertex,
2407 XCAST(Index) Thunk_IDirect3DDeviceImpl_2_Index,
2408 XCAST(End) Thunk_IDirect3DDeviceImpl_2_End,
2409 XCAST(GetRenderState) Thunk_IDirect3DDeviceImpl_2_GetRenderState,
2410 XCAST(SetRenderState) Thunk_IDirect3DDeviceImpl_2_SetRenderState,
2411 XCAST(GetLightState) Thunk_IDirect3DDeviceImpl_2_GetLightState,
2412 XCAST(SetLightState) Thunk_IDirect3DDeviceImpl_2_SetLightState,
2413 XCAST(SetTransform) Thunk_IDirect3DDeviceImpl_2_SetTransform,
2414 XCAST(GetTransform) Thunk_IDirect3DDeviceImpl_2_GetTransform,
2415 XCAST(MultiplyTransform) Thunk_IDirect3DDeviceImpl_2_MultiplyTransform,
2416 XCAST(DrawPrimitive) GL_IDirect3DDeviceImpl_2_DrawPrimitive,
2417 XCAST(DrawIndexedPrimitive) GL_IDirect3DDeviceImpl_2_DrawIndexedPrimitive,
2418 XCAST(SetClipStatus) Thunk_IDirect3DDeviceImpl_2_SetClipStatus,
2419 XCAST(GetClipStatus) Thunk_IDirect3DDeviceImpl_2_GetClipStatus,
2422 #if !defined(__STRICT_ANSI__) && defined(__GNUC__)
2423 #undef XCAST
2424 #endif
2427 #if !defined(__STRICT_ANSI__) && defined(__GNUC__)
2428 # define XCAST(fun) (typeof(VTABLE_IDirect3DDevice.fun))
2429 #else
2430 # define XCAST(fun) (void*)
2431 #endif
2433 ICOM_VTABLE(IDirect3DDevice) VTABLE_IDirect3DDevice =
2435 ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
2436 XCAST(QueryInterface) Thunk_IDirect3DDeviceImpl_1_QueryInterface,
2437 XCAST(AddRef) Thunk_IDirect3DDeviceImpl_1_AddRef,
2438 XCAST(Release) Thunk_IDirect3DDeviceImpl_1_Release,
2439 XCAST(Initialize) Main_IDirect3DDeviceImpl_1_Initialize,
2440 XCAST(GetCaps) Thunk_IDirect3DDeviceImpl_1_GetCaps,
2441 XCAST(SwapTextureHandles) Thunk_IDirect3DDeviceImpl_1_SwapTextureHandles,
2442 XCAST(CreateExecuteBuffer) GL_IDirect3DDeviceImpl_1_CreateExecuteBuffer,
2443 XCAST(GetStats) Thunk_IDirect3DDeviceImpl_1_GetStats,
2444 XCAST(Execute) Main_IDirect3DDeviceImpl_1_Execute,
2445 XCAST(AddViewport) Thunk_IDirect3DDeviceImpl_1_AddViewport,
2446 XCAST(DeleteViewport) Thunk_IDirect3DDeviceImpl_1_DeleteViewport,
2447 XCAST(NextViewport) Thunk_IDirect3DDeviceImpl_1_NextViewport,
2448 XCAST(Pick) Main_IDirect3DDeviceImpl_1_Pick,
2449 XCAST(GetPickRecords) Main_IDirect3DDeviceImpl_1_GetPickRecords,
2450 XCAST(EnumTextureFormats) Thunk_IDirect3DDeviceImpl_1_EnumTextureFormats,
2451 XCAST(CreateMatrix) Main_IDirect3DDeviceImpl_1_CreateMatrix,
2452 XCAST(SetMatrix) Main_IDirect3DDeviceImpl_1_SetMatrix,
2453 XCAST(GetMatrix) Main_IDirect3DDeviceImpl_1_GetMatrix,
2454 XCAST(DeleteMatrix) Main_IDirect3DDeviceImpl_1_DeleteMatrix,
2455 XCAST(BeginScene) Thunk_IDirect3DDeviceImpl_1_BeginScene,
2456 XCAST(EndScene) Thunk_IDirect3DDeviceImpl_1_EndScene,
2457 XCAST(GetDirect3D) Thunk_IDirect3DDeviceImpl_1_GetDirect3D,
2460 #if !defined(__STRICT_ANSI__) && defined(__GNUC__)
2461 #undef XCAST
2462 #endif
2464 static HRESULT d3ddevice_clear(IDirect3DDeviceImpl *This,
2465 DWORD dwCount,
2466 LPD3DRECT lpRects,
2467 DWORD dwFlags,
2468 DWORD dwColor,
2469 D3DVALUE dvZ,
2470 DWORD dwStencil)
2472 GLboolean ztest;
2473 GLfloat old_z_clear_value;
2474 GLbitfield bitfield = 0;
2475 GLint old_stencil_clear_value;
2476 GLfloat old_color_clear_value[4];
2477 D3DRECT rect;
2478 int i;
2480 TRACE("(%p)->(%08lx,%p,%08lx,%08lx,%f,%08lx)\n", This, dwCount, lpRects, dwFlags, dwColor, dvZ, dwStencil);
2481 if (TRACE_ON(ddraw)) {
2482 if (dwCount > 0) {
2483 int i;
2484 TRACE(" rectangles : \n");
2485 for (i = 0; i < dwCount; i++) {
2486 TRACE(" - %ld x %ld %ld x %ld\n", lpRects[i].u1.x1, lpRects[i].u2.y1, lpRects[i].u3.x2, lpRects[i].u4.y2);
2491 if (dwCount == 0) {
2492 /* Not sure if this is really needed... */
2493 dwCount = 1;
2494 rect.u1.x1 = 0;
2495 rect.u2.y1 = 0;
2496 rect.u3.x2 = This->surface->surface_desc.dwWidth;
2497 rect.u4.y2 = This->surface->surface_desc.dwHeight;
2498 lpRects = &rect;
2501 /* Clears the screen */
2502 ENTER_GL();
2503 if (dwFlags & D3DCLEAR_ZBUFFER) {
2504 bitfield |= GL_DEPTH_BUFFER_BIT;
2505 glGetBooleanv(GL_DEPTH_WRITEMASK, &ztest);
2506 glDepthMask(GL_TRUE); /* Enables Z writing to be sure to delete also the Z buffer */
2507 glGetFloatv(GL_DEPTH_CLEAR_VALUE, &old_z_clear_value);
2508 glClearDepth(dvZ);
2509 TRACE(" depth value : %f\n", dvZ);
2511 if (dwFlags & D3DCLEAR_STENCIL) {
2512 bitfield |= GL_STENCIL_BUFFER_BIT;
2513 glGetIntegerv(GL_STENCIL_CLEAR_VALUE, &old_stencil_clear_value);
2514 glClearStencil(dwStencil);
2515 TRACE(" stencil value : %ld\n", dwStencil);
2517 if (dwFlags & D3DCLEAR_TARGET) {
2518 bitfield |= GL_COLOR_BUFFER_BIT;
2519 glGetFloatv(GL_COLOR_CLEAR_VALUE, old_color_clear_value);
2520 glClearColor(((dwColor >> 16) & 0xFF) / 255.0,
2521 ((dwColor >> 8) & 0xFF) / 255.0,
2522 ((dwColor >> 0) & 0xFF) / 255.0,
2523 ((dwColor >> 24) & 0xFF) / 255.0);
2524 TRACE(" color value (ARGB) : %08lx\n", dwColor);
2527 glEnable(GL_SCISSOR_TEST);
2528 for (i = 0; i < dwCount; i++) {
2529 glScissor(lpRects[i].u1.x1, This->surface->surface_desc.dwHeight - lpRects[i].u4.y2,
2530 lpRects[i].u3.x2 - lpRects[i].u1.x1, lpRects[i].u4.y2 - lpRects[i].u2.y1);
2531 glClear(bitfield);
2533 glDisable(GL_SCISSOR_TEST);
2535 if (dwFlags & D3DCLEAR_ZBUFFER) {
2536 glDepthMask(ztest);
2537 glClearDepth(old_z_clear_value);
2539 if (dwFlags & D3DCLEAR_STENCIL) {
2540 bitfield |= GL_STENCIL_BUFFER_BIT;
2541 glClearStencil(old_stencil_clear_value);
2543 if (dwFlags & D3DCLEAR_TARGET) {
2544 bitfield |= GL_COLOR_BUFFER_BIT;
2545 glClearColor(old_color_clear_value[0],
2546 old_color_clear_value[1],
2547 old_color_clear_value[2],
2548 old_color_clear_value[3]);
2551 LEAVE_GL();
2553 return DD_OK;
2556 HRESULT
2557 d3ddevice_blt(IDirectDrawSurfaceImpl *This, LPRECT rdst,
2558 LPDIRECTDRAWSURFACE7 src, LPRECT rsrc,
2559 DWORD dwFlags, LPDDBLTFX lpbltfx)
2561 if (dwFlags & DDBLT_COLORFILL) {
2562 /* This is easy to handle for the D3D Device... */
2563 DWORD color = lpbltfx->u5.dwFillColor;
2564 D3DRECT rect;
2565 TRACE(" executing D3D Device override.\n");
2566 rect.u1.x1 = rdst->left;
2567 rect.u2.y1 = rdst->top;
2568 rect.u3.x2 = rdst->right;
2569 rect.u4.y2 = rdst->bottom;
2570 d3ddevice_clear(This->d3ddevice, 1, &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);
2624 glMultMatrixf((float *) world_mat);
2626 if ((matrices & PROJMAT_CHANGED) != 0) {
2627 glMatrixMode(GL_PROJECTION);
2628 glLoadMatrixf((float *) proj_mat);
2632 void
2633 d3ddevice_matrices_updated(IDirect3DDeviceImpl *This, DWORD matrices)
2635 IDirect3DDeviceGLImpl *glThis = (IDirect3DDeviceGLImpl *) This;
2636 DWORD tex_mat, tex_stage;
2637 if ((matrices & (VIEWMAT_CHANGED|WORLDMAT_CHANGED|PROJMAT_CHANGED)) != 0) {
2638 if (glThis->transform_state == GL_TRANSFORM_NORMAL) {
2639 /* This will force an update of the transform state at the next drawing. */
2640 glThis->transform_state = GL_TRANSFORM_NONE;
2643 for (tex_mat = TEXMAT0_CHANGED, tex_stage = 0; tex_mat <= TEXMAT7_CHANGED; tex_mat <<= 1, tex_stage++) {
2644 if (matrices & tex_mat) {
2645 if (This->state_block.texture_stage_state[tex_stage][D3DTSS_TEXTURETRANSFORMFLAGS - 1] != D3DTTFF_DISABLE) {
2646 if (tex_stage == 0) {
2647 /* No multi-texturing support for now ... */
2648 glMatrixMode(GL_TEXTURE);
2649 glLoadMatrixf((float *) This->tex_mat[tex_stage]);
2651 } else {
2652 glMatrixMode(GL_TEXTURE);
2653 glLoadIdentity();
2659 /* TODO for both these functions :
2660 - change / restore OpenGL parameters for pictures transfers in case they are ever modified
2661 by other OpenGL code in D3D
2662 - handle the case where no 'Begin / EndScene' was done between two locks
2663 - handle the rectangles in the unlock too
2664 - handle pitch correctly...
2666 static void d3ddevice_lock_update(IDirectDrawSurfaceImpl* This, LPCRECT pRect, DWORD dwFlags)
2668 IDirect3DDeviceImpl *d3d_dev = This->d3ddevice;
2669 IDirect3DDeviceGLImpl* gl_d3d_dev = (IDirect3DDeviceGLImpl*) d3d_dev;
2670 BOOLEAN is_front;
2672 if ((This->surface_desc.ddsCaps.dwCaps & (DDSCAPS_FRONTBUFFER|DDSCAPS_PRIMARYSURFACE)) != 0) {
2673 is_front = TRUE;
2674 } else if ((This->surface_desc.ddsCaps.dwCaps & (DDSCAPS_BACKBUFFER)) == (DDSCAPS_BACKBUFFER)) {
2675 is_front = FALSE;
2676 } else {
2677 ERR("Wrong surface type for locking !\n");
2678 return;
2681 /* Try to acquire the device critical section */
2682 EnterCriticalSection(&(d3d_dev->crit));
2684 if (((is_front == TRUE) && (gl_d3d_dev->front_state != SURFACE_MEMORY)) ||
2685 ((is_front == FALSE) && (gl_d3d_dev->state != SURFACE_MEMORY))) {
2686 /* If the surface is already in memory, no need to do anything here... */
2687 GLenum buffer_type;
2688 GLenum buffer_color;
2689 GLenum prev_read;
2690 RECT loc_rect;
2691 int y;
2692 char *dst;
2694 TRACE(" copying frame buffer to main memory.\n");
2696 /* Note that here we cannot do 'optmizations' about the WriteOnly flag... Indeed, a game
2697 may only write to the device... But when we will blit it back to the screen, we need
2698 also to blit correctly the parts the application did not overwrite... */
2700 ENTER_GL();
2702 glGetIntegerv(GL_READ_BUFFER, &prev_read);
2703 glFlush();
2705 if (is_front == TRUE)
2706 /* Application wants to lock the front buffer */
2707 glReadBuffer(GL_FRONT);
2708 else
2709 /* Application wants to lock the back buffer */
2710 glReadBuffer(GL_BACK);
2712 if ((This->surface_desc.u4.ddpfPixelFormat.u1.dwRGBBitCount == 16) &&
2713 (This->surface_desc.u4.ddpfPixelFormat.u2.dwRBitMask == 0xF800) &&
2714 (This->surface_desc.u4.ddpfPixelFormat.u3.dwGBitMask == 0x07E0) &&
2715 (This->surface_desc.u4.ddpfPixelFormat.u4.dwBBitMask == 0x001F) &&
2716 (This->surface_desc.u4.ddpfPixelFormat.u5.dwRGBAlphaBitMask == 0x0000)) {
2717 buffer_type = GL_UNSIGNED_SHORT_5_6_5;
2718 buffer_color = GL_RGB;
2719 } else if ((This->surface_desc.u4.ddpfPixelFormat.u1.dwRGBBitCount == 32) &&
2720 (This->surface_desc.u4.ddpfPixelFormat.u2.dwRBitMask == 0x00FF0000) &&
2721 (This->surface_desc.u4.ddpfPixelFormat.u3.dwGBitMask == 0x0000FF00) &&
2722 (This->surface_desc.u4.ddpfPixelFormat.u4.dwBBitMask == 0x000000FF) &&
2723 (This->surface_desc.u4.ddpfPixelFormat.u5.dwRGBAlphaBitMask == 0x00000000)) {
2724 buffer_type = GL_UNSIGNED_BYTE;
2725 buffer_color = GL_BGRA;
2726 glPixelStorei(GL_PACK_SWAP_BYTES, TRUE);
2727 } else {
2728 ERR(" unsupported pixel format at device locking.\n");
2729 LEAVE_GL();
2730 return;
2733 /* Just a hack while waiting for proper rectangle support */
2734 pRect = NULL;
2735 if (pRect == NULL) {
2736 loc_rect.top = 0;
2737 loc_rect.left = 0;
2738 loc_rect.bottom = This->surface_desc.dwHeight;
2739 loc_rect.right = This->surface_desc.dwWidth;
2740 } else {
2741 loc_rect = *pRect;
2744 dst = ((char *)This->surface_desc.lpSurface) +
2745 (loc_rect.top * This->surface_desc.u1.lPitch) + (loc_rect.left * GET_BPP(This->surface_desc));
2746 for (y = (This->surface_desc.dwHeight - loc_rect.top - 1);
2747 y >= ((int) This->surface_desc.dwHeight - (int) loc_rect.bottom);
2748 y--) {
2749 glReadPixels(loc_rect.left, y,
2750 loc_rect.right - loc_rect.left, 1,
2751 buffer_color, buffer_type, dst);
2752 dst += This->surface_desc.u1.lPitch;
2755 glReadBuffer(prev_read);
2756 glPixelStorei(GL_PACK_SWAP_BYTES, FALSE);
2758 if (is_front)
2759 gl_d3d_dev->front_state = SURFACE_MEMORY;
2760 else
2761 gl_d3d_dev->state = SURFACE_MEMORY;
2763 #if 0
2764 /* I keep this code here as it's very useful to debug :-) */
2766 static int flush_count = 0;
2767 char buf[128];
2768 FILE *f;
2770 if ((++flush_count % 50) == 0) {
2771 sprintf(buf, "lock_%06d.pnm", flush_count);
2772 f = fopen(buf, "wb");
2773 DDRAW_dump_surface_to_disk(This, f);
2776 #endif
2778 LEAVE_GL();
2782 #define UNLOCK_TEX_SIZE 256
2784 static void d3ddevice_flush_to_frame_buffer(IDirect3DDeviceImpl *d3d_dev, LPCRECT pRect) {
2785 GLenum buffer_type, buffer_color;
2786 RECT loc_rect;
2787 IDirectDrawSurfaceImpl *surf = d3d_dev->surface;
2788 IDirect3DDeviceGLImpl* gl_d3d_dev = (IDirect3DDeviceGLImpl*) d3d_dev;
2789 GLint depth_test, alpha_test, cull_face, lighting, min_tex, max_tex, tex_env, blend, stencil_test;
2790 GLuint initial_texture;
2791 GLint tex_state;
2792 int x, y;
2794 loc_rect.top = 0;
2795 loc_rect.left = 0;
2796 loc_rect.bottom = surf->surface_desc.dwHeight;
2797 loc_rect.right = surf->surface_desc.dwWidth;
2799 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);
2801 glGetIntegerv(GL_DEPTH_TEST, &depth_test);
2802 glGetIntegerv(GL_ALPHA_TEST, &alpha_test);
2803 glGetIntegerv(GL_STENCIL_TEST, &stencil_test);
2804 glGetIntegerv(GL_CULL_FACE, &cull_face);
2805 glGetIntegerv(GL_LIGHTING, &lighting);
2806 glGetIntegerv(GL_BLEND, &blend);
2807 glGetIntegerv(GL_TEXTURE_BINDING_2D, &initial_texture);
2808 glGetIntegerv(GL_TEXTURE_2D, &tex_state);
2809 glGetTexParameteriv(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, &max_tex);
2810 glGetTexParameteriv(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, &min_tex);
2811 glGetTexEnviv(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, &tex_env);
2812 glMatrixMode(GL_TEXTURE);
2813 glLoadIdentity();
2814 /* TODO: scissor test if ever we use it ! */
2816 if ((surf->surface_desc.u4.ddpfPixelFormat.u1.dwRGBBitCount == 16) &&
2817 (surf->surface_desc.u4.ddpfPixelFormat.u2.dwRBitMask == 0xF800) &&
2818 (surf->surface_desc.u4.ddpfPixelFormat.u3.dwGBitMask == 0x07E0) &&
2819 (surf->surface_desc.u4.ddpfPixelFormat.u4.dwBBitMask == 0x001F) &&
2820 (surf->surface_desc.u4.ddpfPixelFormat.u5.dwRGBAlphaBitMask == 0x0000)) {
2821 buffer_type = GL_UNSIGNED_SHORT_5_6_5;
2822 buffer_color = GL_RGB;
2823 } else if ((surf->surface_desc.u4.ddpfPixelFormat.u1.dwRGBBitCount == 32) &&
2824 (surf->surface_desc.u4.ddpfPixelFormat.u2.dwRBitMask == 0x00FF0000) &&
2825 (surf->surface_desc.u4.ddpfPixelFormat.u3.dwGBitMask == 0x0000FF00) &&
2826 (surf->surface_desc.u4.ddpfPixelFormat.u4.dwBBitMask == 0x000000FF) &&
2827 (surf->surface_desc.u4.ddpfPixelFormat.u5.dwRGBAlphaBitMask == 0x00000000)) {
2828 buffer_type = GL_UNSIGNED_BYTE;
2829 buffer_color = GL_BGRA;
2830 glPixelStorei(GL_UNPACK_SWAP_BYTES, TRUE);
2831 } else {
2832 ERR(" unsupported pixel format at frame buffer flush.\n");
2833 return;
2836 gl_d3d_dev->transform_state = GL_TRANSFORM_ORTHO;
2837 d3ddevice_set_ortho(d3d_dev);
2839 glDisable(GL_DEPTH_TEST);
2840 glEnable(GL_TEXTURE_2D);
2841 glEnable(GL_SCISSOR_TEST);
2842 glScissor(loc_rect.left, surf->surface_desc.dwHeight - loc_rect.bottom,
2843 loc_rect.right - loc_rect.left, loc_rect.bottom - loc_rect.top);
2845 if (gl_d3d_dev->unlock_tex == 0) {
2846 glGenTextures(1, &gl_d3d_dev->unlock_tex);
2847 glBindTexture(GL_TEXTURE_2D, gl_d3d_dev->unlock_tex);
2848 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB,
2849 UNLOCK_TEX_SIZE, UNLOCK_TEX_SIZE, 0,
2850 GL_RGB, buffer_type, NULL);
2851 } else {
2852 glBindTexture(GL_TEXTURE_2D, gl_d3d_dev->unlock_tex);
2854 glPixelStorei(GL_UNPACK_ROW_LENGTH, surf->surface_desc.dwWidth);
2856 glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);
2857 glDisable(GL_LIGHTING);
2858 glDisable(GL_CULL_FACE);
2859 glDisable(GL_ALPHA_TEST);
2860 glDisable(GL_STENCIL_TEST);
2861 glDisable(GL_BLEND);
2862 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
2863 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
2865 for (x = loc_rect.left; x < loc_rect.right; x += UNLOCK_TEX_SIZE) {
2866 for (y = loc_rect.top; y < loc_rect.bottom; y += UNLOCK_TEX_SIZE) {
2867 /* First, upload the texture... */
2868 int w = (x + UNLOCK_TEX_SIZE > surf->surface_desc.dwWidth) ? (surf->surface_desc.dwWidth - x) : UNLOCK_TEX_SIZE;
2869 int h = (y + UNLOCK_TEX_SIZE > surf->surface_desc.dwHeight) ? (surf->surface_desc.dwHeight - y) : UNLOCK_TEX_SIZE;
2870 glTexSubImage2D(GL_TEXTURE_2D,
2872 0, 0,
2873 w, h,
2874 buffer_color,
2875 buffer_type,
2876 ((char *) surf->surface_desc.lpSurface) + (x * GET_BPP(surf->surface_desc)) + (y * surf->surface_desc.u1.lPitch));
2877 glBegin(GL_QUADS);
2878 glColor3ub(0xFF, 0xFF, 0xFF);
2879 glTexCoord2f(0.0, 0.0);
2880 glVertex3d(x, y, 0.5);
2881 glTexCoord2f(1.0, 0.0);
2882 glVertex3d(x + UNLOCK_TEX_SIZE, y, 0.5);
2883 glTexCoord2f(1.0, 1.0);
2884 glVertex3d(x + UNLOCK_TEX_SIZE, y + UNLOCK_TEX_SIZE, 0.5);
2885 glTexCoord2f(0.0, 1.0);
2886 glVertex3d(x, y + UNLOCK_TEX_SIZE, 0.5);
2887 glEnd();
2892 /* And restore all the various states modified by this code */
2893 if (depth_test != 0) glEnable(GL_DEPTH_TEST);
2894 if (lighting != 0) glEnable(GL_LIGHTING);
2895 if (alpha_test != 0) glEnable(GL_ALPHA_TEST);
2896 if (stencil_test != 0) glEnable(GL_STENCIL_TEST);
2897 if (cull_face != 0) glEnable(GL_CULL_FACE);
2898 if (blend != 0) glEnable(GL_BLEND);
2899 glBindTexture(GL_TEXTURE_2D, initial_texture);
2900 if (tex_state == 0) glDisable(GL_TEXTURE_2D);
2901 glDisable(GL_SCISSOR_TEST);
2902 glPixelStorei(GL_UNPACK_ROW_LENGTH, 0);
2903 glPixelStorei(GL_UNPACK_SWAP_BYTES, FALSE);
2904 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, max_tex);
2905 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, min_tex);
2906 glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, tex_env);
2907 d3d_dev->matrices_updated(d3d_dev, TEXMAT0_CHANGED);
2908 #if 0
2909 /* I keep this code here as it's very useful to debug :-) */
2911 static int flush_count = 0;
2912 char buf[128];
2913 FILE *f;
2915 if ((++flush_count % 50) == 0) {
2916 sprintf(buf, "flush_%06d.pnm", flush_count);
2917 f = fopen(buf, "wb");
2918 DDRAW_dump_surface_to_disk(surf, f);
2921 #endif
2924 static void d3ddevice_unlock_update(IDirectDrawSurfaceImpl* This, LPCRECT pRect)
2926 BOOLEAN is_front;
2927 IDirect3DDeviceImpl *d3d_dev = This->d3ddevice;
2929 if ((This->surface_desc.ddsCaps.dwCaps & (DDSCAPS_FRONTBUFFER|DDSCAPS_PRIMARYSURFACE)) != 0) {
2930 is_front = TRUE;
2931 } else if ((This->surface_desc.ddsCaps.dwCaps & (DDSCAPS_BACKBUFFER)) == (DDSCAPS_BACKBUFFER)) {
2932 is_front = FALSE;
2933 } else {
2934 ERR("Wrong surface type for locking !\n");
2935 return;
2937 /* First, check if we need to do anything. For the backbuffer, flushing is done at the next 3D activity. */
2938 if (((This->lastlocktype & DDLOCK_READONLY) == 0) &&
2939 (is_front == TRUE)) {
2940 GLenum prev_draw;
2941 ENTER_GL();
2942 glGetIntegerv(GL_DRAW_BUFFER, &prev_draw);
2943 glDrawBuffer(GL_FRONT);
2944 d3d_dev->flush_to_framebuffer(d3d_dev, pRect);
2945 glDrawBuffer(prev_draw);
2946 LEAVE_GL();
2949 /* And 'frees' the device critical section */
2950 LeaveCriticalSection(&(d3d_dev->crit));
2953 static void
2954 apply_texture_state(IDirect3DDeviceImpl *This)
2956 int stage, state;
2958 /* Initialize texture stages states */
2959 for (stage = 0; stage < MAX_TEXTURES; stage++) {
2960 for (state = 0; state < HIGHEST_TEXTURE_STAGE_STATE; state += 1) {
2961 if (This->state_block.set_flags.texture_stage_state[stage][state] == TRUE) {
2962 IDirect3DDevice7_SetTextureStageState(ICOM_INTERFACE(This, IDirect3DDevice7),
2963 stage, state + 1, This->state_block.texture_stage_state[stage][state]);
2969 HRESULT
2970 d3ddevice_create(IDirect3DDeviceImpl **obj, IDirect3DImpl *d3d, IDirectDrawSurfaceImpl *surface)
2972 IDirect3DDeviceImpl *object;
2973 IDirect3DDeviceGLImpl *gl_object;
2974 IDirectDrawSurfaceImpl *surf;
2975 HDC device_context;
2976 XVisualInfo *vis;
2977 int num;
2978 int tex_num;
2979 XVisualInfo template;
2980 GLenum buffer = GL_FRONT;
2981 int light;
2982 GLint max_clipping_planes = 0;
2984 object = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(IDirect3DDeviceGLImpl));
2985 if (object == NULL) return DDERR_OUTOFMEMORY;
2987 gl_object = (IDirect3DDeviceGLImpl *) object;
2989 object->ref = 1;
2990 object->d3d = d3d;
2991 object->surface = surface;
2992 object->set_context = set_context;
2993 object->clear = d3ddevice_clear;
2994 object->set_matrices = d3ddevice_set_matrices;
2995 object->matrices_updated = d3ddevice_matrices_updated;
2996 object->flush_to_framebuffer = d3ddevice_flush_to_frame_buffer;
2998 InitializeCriticalSection(&(object->crit));
3000 TRACE(" creating OpenGL device for surface = %p, d3d = %p\n", surface, d3d);
3002 device_context = GetDC(surface->ddraw_owner->window);
3003 gl_object->display = get_display(device_context);
3004 gl_object->drawable = get_drawable(device_context);
3005 ReleaseDC(surface->ddraw_owner->window,device_context);
3007 ENTER_GL();
3008 template.visualid = (VisualID)GetPropA( GetDesktopWindow(), "__wine_x11_visual_id" );
3009 vis = XGetVisualInfo(gl_object->display, VisualIDMask, &template, &num);
3010 if (vis == NULL) {
3011 HeapFree(GetProcessHeap(), 0, object);
3012 ERR("No visual found !\n");
3013 LEAVE_GL();
3014 return DDERR_INVALIDPARAMS;
3015 } else {
3016 TRACE(" visual found\n");
3019 gl_object->gl_context = glXCreateContext(gl_object->display, vis,
3020 NULL, GL_TRUE);
3022 if (gl_object->gl_context == NULL) {
3023 HeapFree(GetProcessHeap(), 0, object);
3024 ERR("Error in context creation !\n");
3025 LEAVE_GL();
3026 return DDERR_INVALIDPARAMS;
3027 } else {
3028 TRACE(" context created (%p)\n", gl_object->gl_context);
3031 /* Look for the front buffer and override its surface's Flip method (if in double buffering) */
3032 for (surf = surface; surf != NULL; surf = surf->surface_owner) {
3033 if ((surf->surface_desc.ddsCaps.dwCaps&(DDSCAPS_FLIP|DDSCAPS_FRONTBUFFER)) == (DDSCAPS_FLIP|DDSCAPS_FRONTBUFFER)) {
3034 surf->aux_ctx = (LPVOID) object;
3035 surf->aux_data = (LPVOID) gl_object->drawable;
3036 surf->aux_flip = opengl_flip;
3037 buffer = GL_BACK;
3038 break;
3041 /* We are not doing any double buffering.. Then force OpenGL to draw on the front buffer */
3042 if (surf == NULL) {
3043 TRACE(" no double buffering : drawing on the front buffer\n");
3044 buffer = GL_FRONT;
3047 for (surf = surface; surf != NULL; surf = surf->surface_owner) {
3048 IDirectDrawSurfaceImpl *surf2;
3049 for (surf2 = surf; surf2->prev_attached != NULL; surf2 = surf2->prev_attached) ;
3050 for (; surf2 != NULL; surf2 = surf2->next_attached) {
3051 TRACE(" checking surface %p :", surf2);
3052 if (((surf2->surface_desc.ddsCaps.dwCaps & (DDSCAPS_3DDEVICE)) == (DDSCAPS_3DDEVICE)) &&
3053 ((surf2->surface_desc.ddsCaps.dwCaps & (DDSCAPS_ZBUFFER)) != (DDSCAPS_ZBUFFER))) {
3054 /* Override the Lock / Unlock function for all these surfaces */
3055 surf2->lock_update_prev = surf2->lock_update;
3056 surf2->lock_update = d3ddevice_lock_update;
3057 surf2->unlock_update_prev = surf2->unlock_update;
3058 surf2->unlock_update = d3ddevice_unlock_update;
3059 /* And install also the blt / bltfast overrides */
3060 surf2->aux_blt = d3ddevice_blt;
3061 surf2->aux_bltfast = d3ddevice_bltfast;
3063 TRACE(" overiding direct surface access.\n");
3064 } else {
3065 TRACE(" no overide.\n");
3067 surf2->d3ddevice = object;
3071 /* Set the various light parameters */
3072 for (light = 0; light < MAX_LIGHTS; light++) {
3073 /* Only set the fields that are not zero-created */
3074 object->light_parameters[light].dltType = D3DLIGHT_DIRECTIONAL;
3075 object->light_parameters[light].dcvDiffuse.u1.r = 1.0;
3076 object->light_parameters[light].dcvDiffuse.u2.g = 1.0;
3077 object->light_parameters[light].dcvDiffuse.u3.b = 1.0;
3078 object->light_parameters[light].dvDirection.u3.z = 1.0;
3081 /* Allocate memory for the matrices */
3082 object->world_mat = (D3DMATRIX *) HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, 16 * sizeof(float));
3083 object->view_mat = (D3DMATRIX *) HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, 16 * sizeof(float));
3084 object->proj_mat = (D3DMATRIX *) HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, 16 * sizeof(float));
3085 memcpy(object->world_mat, id_mat, 16 * sizeof(float));
3086 memcpy(object->view_mat , id_mat, 16 * sizeof(float));
3087 memcpy(object->proj_mat , id_mat, 16 * sizeof(float));
3088 for (tex_num = 0; tex_num < MAX_TEXTURES; tex_num++) {
3089 object->tex_mat[tex_num] = (D3DMATRIX *) HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, 16 * sizeof(float));
3090 memcpy(object->tex_mat[tex_num], id_mat, 16 * sizeof(float));
3093 /* Initialisation */
3094 TRACE(" setting current context\n");
3095 LEAVE_GL();
3096 object->set_context(object);
3097 ENTER_GL();
3098 TRACE(" current context set\n");
3100 /* allocate the clipping planes */
3101 glGetIntegerv(GL_MAX_CLIP_PLANES,&max_clipping_planes);
3102 if (max_clipping_planes>32) {
3103 object->max_clipping_planes=32;
3104 } else {
3105 object->max_clipping_planes = max_clipping_planes;
3107 TRACE(" capable of %d clipping planes\n", (int)object->max_clipping_planes );
3108 object->clipping_planes = (d3d7clippingplane*)HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, object->max_clipping_planes * sizeof(d3d7clippingplane));
3110 glHint(GL_FOG_HINT,GL_NICEST);
3112 glClearColor(0.0, 0.0, 0.0, 0.0);
3113 glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
3114 glDrawBuffer(buffer);
3115 glReadBuffer(buffer);
3116 /* glDisable(GL_DEPTH_TEST); Need here to check for the presence of a ZBuffer and to reenable it when the ZBuffer is attached */
3117 LEAVE_GL();
3119 gl_object->state = SURFACE_GL;
3121 /* fill_device_capabilities(d3d->ddraw); */
3123 ICOM_INIT_INTERFACE(object, IDirect3DDevice, VTABLE_IDirect3DDevice);
3124 ICOM_INIT_INTERFACE(object, IDirect3DDevice2, VTABLE_IDirect3DDevice2);
3125 ICOM_INIT_INTERFACE(object, IDirect3DDevice3, VTABLE_IDirect3DDevice3);
3126 ICOM_INIT_INTERFACE(object, IDirect3DDevice7, VTABLE_IDirect3DDevice7);
3128 *obj = object;
3130 TRACE(" creating implementation at %p.\n", *obj);
3132 /* And finally warn D3D that this device is now present */
3133 object->d3d->added_device(object->d3d, object);
3135 /* FIXME: Should handle other versions than just 7 */
3136 InitDefaultStateBlock(&object->state_block, 7);
3137 /* Apply default render state and texture stage state values */
3138 apply_render_state(object, &object->state_block);
3139 apply_texture_state(object);
3141 /* And fill the fog table with the default fog value */
3142 build_fog_table(gl_object->fog_table, object->state_block.render_state[D3DRENDERSTATE_FOGCOLOR - 1]);
3144 return DD_OK;