Support for device surface locking.
[wine/multimedia.git] / dlls / ddraw / d3ddevice / mesa.c
blobd3a14048025c8620198eb98a1585522293df6c0b
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));
349 /* Look for the front buffer and override its surface's Flip method (if in double buffering) */
350 for (surf = surface; surf != NULL; surf = surf->surface_owner) {
351 if ((surf->surface_desc.ddsCaps.dwCaps&(DDSCAPS_FLIP|DDSCAPS_FRONTBUFFER)) == (DDSCAPS_FLIP|DDSCAPS_FRONTBUFFER)) {
352 surf->aux_ctx = NULL;
353 surf->aux_data = NULL;
354 surf->aux_flip = NULL;
355 break;
358 for (surf = surface; surf != NULL; surf = surf->surface_owner) {
359 IDirectDrawSurfaceImpl *surf2;
360 for (surf2 = surf; surf2->prev_attached != NULL; surf2 = surf2->prev_attached) ;
361 for (; surf2 != NULL; surf2 = surf2->next_attached) {
362 if (((surf2->surface_desc.ddsCaps.dwCaps & (DDSCAPS_3DDEVICE)) == (DDSCAPS_3DDEVICE)) &&
363 ((surf2->surface_desc.ddsCaps.dwCaps & (DDSCAPS_ZBUFFER)) != (DDSCAPS_ZBUFFER))) {
364 /* Override the Lock / Unlock function for all these surfaces */
365 surf2->lock_update = surf2->lock_update_prev;
366 surf2->unlock_update = surf2->unlock_update_prev;;
367 /* And install also the blt / bltfast overrides */
368 surf2->aux_blt = NULL;
369 surf2->aux_bltfast = NULL;
371 surf2->d3ddevice = NULL;
375 /* And warn the D3D object that this device is no longer active... */
376 This->d3d->removed_device(This->d3d, This);
378 HeapFree(GetProcessHeap(), 0, This->world_mat);
379 HeapFree(GetProcessHeap(), 0, This->view_mat);
380 HeapFree(GetProcessHeap(), 0, This->proj_mat);
382 DeleteCriticalSection(&(This->crit));
384 ENTER_GL();
385 if (glThis->unlock_tex)
386 glDeleteTextures(1, &(glThis->unlock_tex));
387 glXDestroyContext(glThis->display, glThis->gl_context);
388 LEAVE_GL();
389 HeapFree(GetProcessHeap(), 0, This->clipping_planes);
391 HeapFree(GetProcessHeap(), 0, This);
392 return 0;
394 return This->ref;
397 HRESULT WINAPI
398 GL_IDirect3DDeviceImpl_3_2T_1T_GetCaps(LPDIRECT3DDEVICE3 iface,
399 LPD3DDEVICEDESC lpD3DHWDevDesc,
400 LPD3DDEVICEDESC lpD3DHELDevDesc)
402 ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice3, iface);
403 D3DDEVICEDESC desc;
404 DWORD dwSize;
406 TRACE("(%p/%p)->(%p,%p)\n", This, iface, lpD3DHWDevDesc, lpD3DHELDevDesc);
408 fill_opengl_caps(&desc);
409 dwSize = lpD3DHWDevDesc->dwSize;
410 memset(lpD3DHWDevDesc, 0, dwSize);
411 memcpy(lpD3DHWDevDesc, &desc, (dwSize <= desc.dwSize ? dwSize : desc.dwSize));
413 dwSize = lpD3DHELDevDesc->dwSize;
414 memset(lpD3DHELDevDesc, 0, dwSize);
415 memcpy(lpD3DHELDevDesc, &desc, (dwSize <= desc.dwSize ? dwSize : desc.dwSize));
417 TRACE(" returning caps : (no dump function yet)\n");
419 return DD_OK;
422 static HRESULT enum_texture_format_OpenGL(LPD3DENUMTEXTUREFORMATSCALLBACK cb_1,
423 LPD3DENUMPIXELFORMATSCALLBACK cb_2,
424 LPVOID context)
426 DDSURFACEDESC sdesc;
427 LPDDPIXELFORMAT pformat;
429 /* Do the texture enumeration */
430 sdesc.dwSize = sizeof(DDSURFACEDESC);
431 sdesc.dwFlags = DDSD_PIXELFORMAT | DDSD_CAPS;
432 sdesc.ddsCaps.dwCaps = DDSCAPS_TEXTURE;
433 pformat = &(sdesc.ddpfPixelFormat);
434 pformat->dwSize = sizeof(DDPIXELFORMAT);
435 pformat->dwFourCC = 0;
437 #if 0
438 /* See argument about the RGBA format for 'packed' texture formats */
439 TRACE("Enumerating GL_RGBA unpacked (32)\n");
440 pformat->dwFlags = DDPF_RGB | DDPF_ALPHAPIXELS;
441 pformat->u1.dwRGBBitCount = 32;
442 pformat->u2.dwRBitMask = 0xFF000000;
443 pformat->u3.dwGBitMask = 0x00FF0000;
444 pformat->u4.dwBBitMask = 0x0000FF00;
445 pformat->u5.dwRGBAlphaBitMask = 0x000000FF;
446 if (cb_1) if (cb_1(&sdesc , context) == 0) return DD_OK;
447 if (cb_2) if (cb_2(pformat, context) == 0) return DD_OK;
448 #endif
450 TRACE("Enumerating GL_RGBA unpacked (32)\n");
451 pformat->dwFlags = DDPF_RGB | DDPF_ALPHAPIXELS;
452 pformat->u1.dwRGBBitCount = 32;
453 pformat->u2.dwRBitMask = 0x00FF0000;
454 pformat->u3.dwGBitMask = 0x0000FF00;
455 pformat->u4.dwBBitMask = 0x000000FF;
456 pformat->u5.dwRGBAlphaBitMask = 0xFF000000;
457 if (cb_1) if (cb_1(&sdesc , context) == 0) return DD_OK;
458 if (cb_2) if (cb_2(pformat, context) == 0) return DD_OK;
460 #if 0 /* Enabling this breaks Tomb Raider 3, need to investigate... */
461 TRACE("Enumerating GL_RGB unpacked (32)\n");
462 pformat->dwFlags = DDPF_RGB;
463 pformat->u1.dwRGBBitCount = 32;
464 pformat->u2.dwRBitMask = 0x00FF0000;
465 pformat->u3.dwGBitMask = 0x0000FF00;
466 pformat->u4.dwBBitMask = 0x000000FF;
467 pformat->u5.dwRGBAlphaBitMask = 0x00000000;
468 if (cb_1) if (cb_1(&sdesc , context) == 0) return DD_OK;
469 if (cb_2) if (cb_2(pformat, context) == 0) return DD_OK;
470 #endif
472 TRACE("Enumerating GL_RGB unpacked (24)\n");
473 pformat->dwFlags = DDPF_RGB;
474 pformat->u1.dwRGBBitCount = 24;
475 pformat->u2.dwRBitMask = 0x00FF0000;
476 pformat->u3.dwGBitMask = 0x0000FF00;
477 pformat->u4.dwBBitMask = 0x000000FF;
478 pformat->u5.dwRGBAlphaBitMask = 0x00000000;
479 if (cb_1) if (cb_1(&sdesc , context) == 0) return DD_OK;
480 if (cb_2) if (cb_2(pformat, context) == 0) return DD_OK;
482 /* Note : even if this is an 'emulated' texture format, it needs to be first
483 as some dumb applications seem to rely on that. */
484 TRACE("Enumerating GL_RGBA packed GL_UNSIGNED_SHORT_1_5_5_5 (ARGB) (16)\n");
485 pformat->dwFlags = DDPF_RGB | DDPF_ALPHAPIXELS;
486 pformat->u1.dwRGBBitCount = 16;
487 pformat->u2.dwRBitMask = 0x00007C00;
488 pformat->u3.dwGBitMask = 0x000003E0;
489 pformat->u4.dwBBitMask = 0x0000001F;
490 pformat->u5.dwRGBAlphaBitMask = 0x00008000;
491 if (cb_1) if (cb_1(&sdesc , context) == 0) return DD_OK;
492 if (cb_2) if (cb_2(pformat, context) == 0) return DD_OK;
494 TRACE("Enumerating GL_RGBA packed GL_UNSIGNED_SHORT_4_4_4_4 (ARGB) (16)\n");
495 pformat->dwFlags = DDPF_RGB | DDPF_ALPHAPIXELS;
496 pformat->u1.dwRGBBitCount = 16;
497 pformat->u2.dwRBitMask = 0x00000F00;
498 pformat->u3.dwGBitMask = 0x000000F0;
499 pformat->u4.dwBBitMask = 0x0000000F;
500 pformat->u5.dwRGBAlphaBitMask = 0x0000F000;
501 if (cb_1) if (cb_1(&sdesc , context) == 0) return DD_OK;
502 if (cb_2) if (cb_2(pformat, context) == 0) return DD_OK;
504 TRACE("Enumerating GL_RGB packed GL_UNSIGNED_SHORT_5_6_5 (16)\n");
505 pformat->dwFlags = DDPF_RGB;
506 pformat->u1.dwRGBBitCount = 16;
507 pformat->u2.dwRBitMask = 0x0000F800;
508 pformat->u3.dwGBitMask = 0x000007E0;
509 pformat->u4.dwBBitMask = 0x0000001F;
510 pformat->u5.dwRGBAlphaBitMask = 0x00000000;
511 if (cb_1) if (cb_1(&sdesc , context) == 0) return DD_OK;
512 if (cb_2) if (cb_2(pformat, context) == 0) return DD_OK;
514 TRACE("Enumerating GL_RGB packed GL_UNSIGNED_SHORT_5_5_5 (16)\n");
515 pformat->dwFlags = DDPF_RGB;
516 pformat->u1.dwRGBBitCount = 16;
517 pformat->u2.dwRBitMask = 0x00007C00;
518 pformat->u3.dwGBitMask = 0x000003E0;
519 pformat->u4.dwBBitMask = 0x0000001F;
520 pformat->u5.dwRGBAlphaBitMask = 0x00000000;
521 if (cb_1) if (cb_1(&sdesc , context) == 0) return DD_OK;
522 if (cb_2) if (cb_2(pformat, context) == 0) return DD_OK;
524 #if 0
525 /* This is a compromise : some games choose the first 16 bit texture format with alpha they
526 find enumerated, others the last one. And both want to have the ARGB one.
528 So basically, forget our OpenGL roots and do not even enumerate our RGBA ones.
530 TRACE("Enumerating GL_RGBA packed GL_UNSIGNED_SHORT_4_4_4_4 (16)\n");
531 pformat->dwFlags = DDPF_RGB | DDPF_ALPHAPIXELS;
532 pformat->u1.dwRGBBitCount = 16;
533 pformat->u2.dwRBitMask = 0x0000F000;
534 pformat->u3.dwGBitMask = 0x00000F00;
535 pformat->u4.dwBBitMask = 0x000000F0;
536 pformat->u5.dwRGBAlphaBitMask = 0x0000000F;
537 if (cb_1) if (cb_1(&sdesc , context) == 0) return DD_OK;
538 if (cb_2) if (cb_2(pformat, context) == 0) return DD_OK;
540 TRACE("Enumerating GL_RGBA packed GL_UNSIGNED_SHORT_5_5_5_1 (16)\n");
541 pformat->dwFlags = DDPF_RGB | DDPF_ALPHAPIXELS;
542 pformat->u1.dwRGBBitCount = 16;
543 pformat->u2.dwRBitMask = 0x0000F800;
544 pformat->u3.dwGBitMask = 0x000007C0;
545 pformat->u4.dwBBitMask = 0x0000003E;
546 pformat->u5.dwRGBAlphaBitMask = 0x00000001;
547 if (cb_1) if (cb_1(&sdesc , context) == 0) return DD_OK;
548 if (cb_2) if (cb_2(pformat, context) == 0) return DD_OK;
549 #endif
551 TRACE("Enumerating GL_RGB packed GL_UNSIGNED_BYTE_3_3_2 (8)\n");
552 pformat->dwFlags = DDPF_RGB;
553 pformat->u1.dwRGBBitCount = 8;
554 pformat->u2.dwRBitMask = 0x000000E0;
555 pformat->u3.dwGBitMask = 0x0000001C;
556 pformat->u4.dwBBitMask = 0x00000003;
557 pformat->u5.dwRGBAlphaBitMask = 0x00000000;
558 if (cb_1) if (cb_1(&sdesc , context) == 0) return DD_OK;
559 if (cb_2) if (cb_2(pformat, context) == 0) return DD_OK;
561 TRACE("Enumerating Paletted (8)\n");
562 pformat->dwFlags = DDPF_PALETTEINDEXED8;
563 pformat->u1.dwRGBBitCount = 8;
564 pformat->u2.dwRBitMask = 0x00000000;
565 pformat->u3.dwGBitMask = 0x00000000;
566 pformat->u4.dwBBitMask = 0x00000000;
567 pformat->u5.dwRGBAlphaBitMask = 0x00000000;
568 if (cb_1) if (cb_1(&sdesc , context) == 0) return DD_OK;
569 if (cb_2) if (cb_2(pformat, context) == 0) return DD_OK;
571 TRACE("End of enumeration\n");
572 return DD_OK;
576 HRESULT
577 d3ddevice_find(IDirect3DImpl *d3d,
578 LPD3DFINDDEVICESEARCH lpD3DDFS,
579 LPD3DFINDDEVICERESULT lplpD3DDevice)
581 D3DDEVICEDESC desc;
583 if ((lpD3DDFS->dwFlags & D3DFDS_COLORMODEL) &&
584 (lpD3DDFS->dcmColorModel != D3DCOLOR_RGB)) {
585 TRACE(" trying to request a non-RGB D3D color model. Not supported.\n");
586 return DDERR_INVALIDPARAMS; /* No real idea what to return here :-) */
588 if (lpD3DDFS->dwFlags & D3DFDS_GUID) {
589 TRACE(" trying to match guid %s.\n", debugstr_guid(&(lpD3DDFS->guid)));
590 if ((IsEqualGUID(&IID_D3DDEVICE_OpenGL, &(lpD3DDFS->guid)) == 0) &&
591 (IsEqualGUID(&IID_IDirect3DHALDevice, &(lpD3DDFS->guid)) == 0) &&
592 (IsEqualGUID(&IID_IDirect3DRefDevice, &(lpD3DDFS->guid)) == 0)) {
593 TRACE(" no match for this GUID.\n");
594 return DDERR_INVALIDPARAMS;
598 /* Now return our own GUID */
599 lplpD3DDevice->guid = IID_D3DDEVICE_OpenGL;
600 fill_opengl_caps(&desc);
601 lplpD3DDevice->ddHwDesc = desc;
602 lplpD3DDevice->ddSwDesc = desc;
604 TRACE(" returning Wine's OpenGL device with (undumped) capabilities\n");
606 return D3D_OK;
609 HRESULT WINAPI
610 GL_IDirect3DDeviceImpl_2_1T_EnumTextureFormats(LPDIRECT3DDEVICE2 iface,
611 LPD3DENUMTEXTUREFORMATSCALLBACK lpD3DEnumTextureProc,
612 LPVOID lpArg)
614 ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice2, iface);
615 TRACE("(%p/%p)->(%p,%p)\n", This, iface, lpD3DEnumTextureProc, lpArg);
616 return enum_texture_format_OpenGL(lpD3DEnumTextureProc, NULL, lpArg);
619 HRESULT WINAPI
620 GL_IDirect3DDeviceImpl_7_3T_EnumTextureFormats(LPDIRECT3DDEVICE7 iface,
621 LPD3DENUMPIXELFORMATSCALLBACK lpD3DEnumPixelProc,
622 LPVOID lpArg)
624 ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice7, iface);
625 TRACE("(%p/%p)->(%p,%p)\n", This, iface, lpD3DEnumPixelProc, lpArg);
626 return enum_texture_format_OpenGL(NULL, lpD3DEnumPixelProc, lpArg);
629 HRESULT WINAPI
630 GL_IDirect3DDeviceImpl_7_3T_2T_SetRenderState(LPDIRECT3DDEVICE7 iface,
631 D3DRENDERSTATETYPE dwRenderStateType,
632 DWORD dwRenderState)
634 ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice7, iface);
635 TRACE("(%p/%p)->(%08x,%08lx)\n", This, iface, dwRenderStateType, dwRenderState);
637 /* Call the render state functions */
638 store_render_state(This, dwRenderStateType, dwRenderState, &This->state_block);
639 set_render_state(This, dwRenderStateType, &This->state_block);
641 return DD_OK;
644 HRESULT WINAPI
645 GL_IDirect3DDeviceImpl_7_3T_2T_GetRenderState(LPDIRECT3DDEVICE7 iface,
646 D3DRENDERSTATETYPE dwRenderStateType,
647 LPDWORD lpdwRenderState)
649 ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice7, iface);
650 TRACE("(%p/%p)->(%08x,%p)\n", This, iface, dwRenderStateType, lpdwRenderState);
652 /* Call the render state functions */
653 get_render_state(This, dwRenderStateType, lpdwRenderState, &This->state_block);
655 TRACE(" - asked for rendering state : %s, returning value %08lx.\n", _get_renderstate(dwRenderStateType), *lpdwRenderState);
657 return DD_OK;
660 HRESULT WINAPI
661 GL_IDirect3DDeviceImpl_3_2T_SetLightState(LPDIRECT3DDEVICE3 iface,
662 D3DLIGHTSTATETYPE dwLightStateType,
663 DWORD dwLightState)
665 ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice3, iface);
667 TRACE("(%p/%p)->(%08x,%08lx)\n", This, iface, dwLightStateType, dwLightState);
669 if (!dwLightStateType && (dwLightStateType > D3DLIGHTSTATE_COLORVERTEX))
670 TRACE("Unexpected Light State Type\n");
671 return DDERR_INVALIDPARAMS;
673 if (dwLightStateType == D3DLIGHTSTATE_MATERIAL /* 1 */) {
674 IDirect3DMaterialImpl *mat = (IDirect3DMaterialImpl *) dwLightState;
676 if (mat != NULL) {
677 ENTER_GL();
678 mat->activate(mat);
679 LEAVE_GL();
680 } else {
681 ERR(" D3DLIGHTSTATE_MATERIAL called with NULL material !!!\n");
683 } else if (dwLightStateType == D3DLIGHTSTATE_COLORMODEL /* 3 */) {
684 switch (dwLightState) {
685 case D3DCOLOR_MONO:
686 ERR("DDCOLOR_MONO should not happen!\n");
687 break;
688 case D3DCOLOR_RGB:
689 /* We are already in this mode */
690 break;
691 default:
692 ERR("Unknown color model!\n");
693 break;
695 } else {
696 D3DRENDERSTATETYPE rs;
697 switch (dwLightStateType) {
699 case D3DLIGHTSTATE_AMBIENT: /* 2 */
700 rs = D3DRENDERSTATE_AMBIENT;
701 break;
702 case D3DLIGHTSTATE_FOGMODE: /* 4 */
703 rs = D3DRENDERSTATE_FOGVERTEXMODE;
704 break;
705 case D3DLIGHTSTATE_FOGSTART: /* 5 */
706 rs = D3DRENDERSTATE_FOGSTART;
707 break;
708 case D3DLIGHTSTATE_FOGEND: /* 6 */
709 rs = D3DRENDERSTATE_FOGEND;
710 break;
711 case D3DLIGHTSTATE_FOGDENSITY: /* 7 */
712 rs = D3DRENDERSTATE_FOGDENSITY;
713 break;
714 case D3DLIGHTSTATE_COLORVERTEX: /* 8 */
715 rs = D3DRENDERSTATE_COLORVERTEX;
716 break;
717 default:
718 break;
721 IDirect3DDevice7_SetRenderState(ICOM_INTERFACE(This, IDirect3DDevice7),
722 rs,dwLightState);
725 return DD_OK;
728 static void draw_primitive_start_GL(D3DPRIMITIVETYPE d3dpt)
730 switch (d3dpt) {
731 case D3DPT_POINTLIST:
732 TRACE("Start POINTS\n");
733 glBegin(GL_POINTS);
734 break;
736 case D3DPT_LINELIST:
737 TRACE("Start LINES\n");
738 glBegin(GL_LINES);
739 break;
741 case D3DPT_LINESTRIP:
742 TRACE("Start LINE_STRIP\n");
743 glBegin(GL_LINE_STRIP);
744 break;
746 case D3DPT_TRIANGLELIST:
747 TRACE("Start TRIANGLES\n");
748 glBegin(GL_TRIANGLES);
749 break;
751 case D3DPT_TRIANGLESTRIP:
752 TRACE("Start TRIANGLE_STRIP\n");
753 glBegin(GL_TRIANGLE_STRIP);
754 break;
756 case D3DPT_TRIANGLEFAN:
757 TRACE("Start TRIANGLE_FAN\n");
758 glBegin(GL_TRIANGLE_FAN);
759 break;
761 default:
762 FIXME("Unhandled primitive %08x\n", d3dpt);
763 break;
767 /* This function calculate the Z coordinate from Zproj */
768 static float ZfromZproj(IDirect3DDeviceImpl *This, D3DVALUE Zproj)
770 float a,b,c,d;
771 /* Assume that X = Y = 0 and W = 1 */
772 a = This->proj_mat->_33;
773 b = This->proj_mat->_34;
774 c = This->proj_mat->_43;
775 d = This->proj_mat->_44;
776 /* We have in homogenous coordinates Z' = a * Z + c and W' = b * Z + d
777 * So in non homogenous coordinates we have Zproj = (a * Z + c) / (b * Z + d)
778 * And finally Z = (d * Zproj - c) / (a - b * Zproj)
780 return (d*Zproj - c) / (a - b*Zproj);
783 static void build_fog_table(BYTE *fog_table, DWORD fog_color) {
784 int i;
786 TRACE(" rebuilding fog table (%06lx)...\n", fog_color & 0x00FFFFFF);
788 for (i = 0; i < 3; i++) {
789 BYTE fog_color_component = (fog_color >> (8 * i)) & 0xFF;
790 DWORD elt;
791 for (elt = 0; elt < 0x10000; elt++) {
792 /* We apply the fog transformation and cache the result */
793 DWORD fog_intensity = elt & 0xFF;
794 DWORD vertex_color = (elt >> 8) & 0xFF;
795 fog_table[(i * 0x10000) + elt] = ((fog_intensity * vertex_color) + ((0xFF - fog_intensity) * fog_color_component)) / 0xFF;
800 static void draw_primitive_handle_GL_state(IDirect3DDeviceImpl *This,
801 BOOLEAN vertex_transformed,
802 BOOLEAN vertex_lit) {
803 IDirect3DDeviceGLImpl* glThis = (IDirect3DDeviceGLImpl*) This;
805 /* Puts GL in the correct lighting / transformation mode */
806 if ((vertex_transformed == FALSE) &&
807 (glThis->transform_state != GL_TRANSFORM_NORMAL)) {
808 /* Need to put the correct transformation again if we go from Transformed
809 vertices to non-transformed ones.
811 This->set_matrices(This, VIEWMAT_CHANGED|WORLDMAT_CHANGED|PROJMAT_CHANGED,
812 This->world_mat, This->view_mat, This->proj_mat);
813 glThis->transform_state = GL_TRANSFORM_NORMAL;
815 } else if ((vertex_transformed == TRUE) &&
816 (glThis->transform_state != GL_TRANSFORM_ORTHO)) {
817 /* Set our orthographic projection */
818 glThis->transform_state = GL_TRANSFORM_ORTHO;
819 d3ddevice_set_ortho(This);
822 /* TODO: optimize this to not always reset all the fog stuff on all DrawPrimitive call
823 if no fogging state change occured */
824 if (This->state_block.render_state[D3DRENDERSTATE_FOGENABLE - 1] == TRUE) {
825 if (vertex_transformed == TRUE) {
826 glDisable(GL_FOG);
827 /* Now check if our fog_table still corresponds to the current vertex color.
828 Element '0x..00' is always the fog color as it corresponds to maximum fog intensity */
829 if ((glThis->fog_table[0 * 0x10000 + 0x0000] != ((This->state_block.render_state[D3DRENDERSTATE_FOGCOLOR - 1] >> 0) & 0xFF)) ||
830 (glThis->fog_table[1 * 0x10000 + 0x0000] != ((This->state_block.render_state[D3DRENDERSTATE_FOGCOLOR - 1] >> 8) & 0xFF)) ||
831 (glThis->fog_table[2 * 0x10000 + 0x0000] != ((This->state_block.render_state[D3DRENDERSTATE_FOGCOLOR - 1] >> 16) & 0xFF))) {
832 /* We need to rebuild our fog table.... */
833 build_fog_table(glThis->fog_table, This->state_block.render_state[D3DRENDERSTATE_FOGCOLOR - 1]);
835 } else {
836 if (This->state_block.render_state[D3DRENDERSTATE_FOGTABLEMODE - 1] != D3DFOG_NONE) {
837 switch (This->state_block.render_state[D3DRENDERSTATE_FOGTABLEMODE - 1]) {
838 case D3DFOG_LINEAR: glFogi(GL_FOG_MODE, GL_LINEAR); break;
839 case D3DFOG_EXP: glFogi(GL_FOG_MODE, GL_EXP); break;
840 case D3DFOG_EXP2: glFogi(GL_FOG_MODE, GL_EXP2); break;
842 if (vertex_lit == FALSE) {
843 glFogf(GL_FOG_START, *(float*)&This->state_block.render_state[D3DRENDERSTATE_FOGSTART - 1]);
844 glFogf(GL_FOG_END, *(float*)&This->state_block.render_state[D3DRENDERSTATE_FOGEND - 1]);
845 } else {
846 /* Special case of 'pixel fog' */
847 glFogf(GL_FOG_START, ZfromZproj(This, *(float*)&This->state_block.render_state[D3DRENDERSTATE_FOGSTART - 1]));
848 glFogf(GL_FOG_END, ZfromZproj(This, *(float*)&This->state_block.render_state[D3DRENDERSTATE_FOGEND - 1]));
850 glEnable(GL_FOG);
851 } else {
852 glDisable(GL_FOG);
855 } else {
856 glDisable(GL_FOG);
859 /* Handle the 'no-normal' case */
860 if ((vertex_lit == FALSE) && (This->state_block.render_state[D3DRENDERSTATE_LIGHTING - 1] == TRUE))
861 glEnable(GL_LIGHTING);
862 else
863 glDisable(GL_LIGHTING);
865 /* Handle the code for pre-vertex material properties */
866 if (vertex_transformed == FALSE) {
867 if ((This->state_block.render_state[D3DRENDERSTATE_LIGHTING - 1] == TRUE) &&
868 (This->state_block.render_state[D3DRENDERSTATE_COLORVERTEX - 1] == TRUE)) {
869 if ((This->state_block.render_state[D3DRENDERSTATE_DIFFUSEMATERIALSOURCE - 1] != D3DMCS_MATERIAL) ||
870 (This->state_block.render_state[D3DRENDERSTATE_AMBIENTMATERIALSOURCE - 1] != D3DMCS_MATERIAL) ||
871 (This->state_block.render_state[D3DRENDERSTATE_EMISSIVEMATERIALSOURCE - 1] != D3DMCS_MATERIAL) ||
872 (This->state_block.render_state[D3DRENDERSTATE_SPECULARMATERIALSOURCE - 1] != D3DMCS_MATERIAL)) {
873 glEnable(GL_COLOR_MATERIAL);
880 inline static void draw_primitive(IDirect3DDeviceImpl *This, DWORD maxvert, WORD *index,
881 D3DVERTEXTYPE d3dvt, D3DPRIMITIVETYPE d3dpt, void *lpvertex)
883 D3DDRAWPRIMITIVESTRIDEDDATA strided;
885 switch (d3dvt) {
886 case D3DVT_VERTEX: {
887 strided.position.lpvData = &((D3DVERTEX *) lpvertex)->u1.x;
888 strided.position.dwStride = sizeof(D3DVERTEX);
889 strided.normal.lpvData = &((D3DVERTEX *) lpvertex)->u4.nx;
890 strided.normal.dwStride = sizeof(D3DVERTEX);
891 strided.textureCoords[0].lpvData = &((D3DVERTEX *) lpvertex)->u7.tu;
892 strided.textureCoords[0].dwStride = sizeof(D3DVERTEX);
893 draw_primitive_strided(This, d3dpt, D3DFVF_VERTEX, &strided, 0 /* Unused */, index, maxvert, 0 /* Unused */);
894 } break;
896 case D3DVT_LVERTEX: {
897 strided.position.lpvData = &((D3DLVERTEX *) lpvertex)->u1.x;
898 strided.position.dwStride = sizeof(D3DLVERTEX);
899 strided.diffuse.lpvData = &((D3DLVERTEX *) lpvertex)->u4.color;
900 strided.diffuse.dwStride = sizeof(D3DLVERTEX);
901 strided.specular.lpvData = &((D3DLVERTEX *) lpvertex)->u5.specular;
902 strided.specular.dwStride = sizeof(D3DLVERTEX);
903 strided.textureCoords[0].lpvData = &((D3DLVERTEX *) lpvertex)->u6.tu;
904 strided.textureCoords[0].dwStride = sizeof(D3DLVERTEX);
905 draw_primitive_strided(This, d3dpt, D3DFVF_LVERTEX, &strided, 0 /* Unused */, index, maxvert, 0 /* Unused */);
906 } break;
908 case D3DVT_TLVERTEX: {
909 strided.position.lpvData = &((D3DTLVERTEX *) lpvertex)->u1.sx;
910 strided.position.dwStride = sizeof(D3DTLVERTEX);
911 strided.diffuse.lpvData = &((D3DTLVERTEX *) lpvertex)->u5.color;
912 strided.diffuse.dwStride = sizeof(D3DTLVERTEX);
913 strided.specular.lpvData = &((D3DTLVERTEX *) lpvertex)->u6.specular;
914 strided.specular.dwStride = sizeof(D3DTLVERTEX);
915 strided.textureCoords[0].lpvData = &((D3DTLVERTEX *) lpvertex)->u7.tu;
916 strided.textureCoords[0].dwStride = sizeof(D3DTLVERTEX);
917 draw_primitive_strided(This, d3dpt, D3DFVF_TLVERTEX, &strided, 0 /* Unused */, index, maxvert, 0 /* Unused */);
918 } break;
920 default:
921 FIXME("Unhandled vertex type %08x\n", d3dvt);
922 break;
926 HRESULT WINAPI
927 GL_IDirect3DDeviceImpl_2_DrawPrimitive(LPDIRECT3DDEVICE2 iface,
928 D3DPRIMITIVETYPE d3dptPrimitiveType,
929 D3DVERTEXTYPE d3dvtVertexType,
930 LPVOID lpvVertices,
931 DWORD dwVertexCount,
932 DWORD dwFlags)
934 ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice2, iface);
936 TRACE("(%p/%p)->(%08x,%08x,%p,%08lx,%08lx)\n", This, iface, d3dptPrimitiveType, d3dvtVertexType, lpvVertices, dwVertexCount, dwFlags);
937 if (TRACE_ON(ddraw)) {
938 TRACE(" - flags : "); dump_DPFLAGS(dwFlags);
941 draw_primitive(This, dwVertexCount, NULL, d3dvtVertexType, d3dptPrimitiveType, lpvVertices);
943 return DD_OK;
946 HRESULT WINAPI
947 GL_IDirect3DDeviceImpl_2_DrawIndexedPrimitive(LPDIRECT3DDEVICE2 iface,
948 D3DPRIMITIVETYPE d3dptPrimitiveType,
949 D3DVERTEXTYPE d3dvtVertexType,
950 LPVOID lpvVertices,
951 DWORD dwVertexCount,
952 LPWORD dwIndices,
953 DWORD dwIndexCount,
954 DWORD dwFlags)
956 ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice2, iface);
957 TRACE("(%p/%p)->(%08x,%08x,%p,%08lx,%p,%08lx,%08lx)\n", This, iface, d3dptPrimitiveType, d3dvtVertexType, lpvVertices, dwVertexCount, dwIndices, dwIndexCount, dwFlags);
958 if (TRACE_ON(ddraw)) {
959 TRACE(" - flags : "); dump_DPFLAGS(dwFlags);
962 draw_primitive(This, dwIndexCount, dwIndices, d3dvtVertexType, d3dptPrimitiveType, lpvVertices);
964 return DD_OK;
967 HRESULT WINAPI
968 GL_IDirect3DDeviceImpl_1_CreateExecuteBuffer(LPDIRECT3DDEVICE iface,
969 LPD3DEXECUTEBUFFERDESC lpDesc,
970 LPDIRECT3DEXECUTEBUFFER* lplpDirect3DExecuteBuffer,
971 IUnknown* pUnkOuter)
973 ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice, iface);
974 IDirect3DExecuteBufferImpl *ret;
975 HRESULT ret_value;
977 TRACE("(%p/%p)->(%p,%p,%p)\n", This, iface, lpDesc, lplpDirect3DExecuteBuffer, pUnkOuter);
979 ret_value = d3dexecutebuffer_create(&ret, This->d3d, This, lpDesc);
980 *lplpDirect3DExecuteBuffer = ICOM_INTERFACE(ret, IDirect3DExecuteBuffer);
982 TRACE(" returning %p.\n", *lplpDirect3DExecuteBuffer);
984 return ret_value;
987 /* These are the various handler used in the generic path */
988 inline static void handle_xyz(D3DVALUE *coords) {
989 glVertex3fv(coords);
991 inline static void handle_xyzrhw(D3DVALUE *coords) {
992 if (coords[3] < 1e-8)
993 glVertex3fv(coords);
994 else {
995 GLfloat w = 1.0 / coords[3];
997 glVertex4f(coords[0] * w,
998 coords[1] * w,
999 coords[2] * w,
1003 inline static void handle_normal(D3DVALUE *coords) {
1004 glNormal3fv(coords);
1007 inline static void handle_diffuse_base(STATEBLOCK *sb, DWORD *color) {
1008 if ((sb->render_state[D3DRENDERSTATE_ALPHATESTENABLE - 1] == TRUE) ||
1009 (sb->render_state[D3DRENDERSTATE_ALPHABLENDENABLE - 1] == TRUE)) {
1010 glColor4ub((*color >> 16) & 0xFF,
1011 (*color >> 8) & 0xFF,
1012 (*color >> 0) & 0xFF,
1013 (*color >> 24) & 0xFF);
1014 } else {
1015 glColor3ub((*color >> 16) & 0xFF,
1016 (*color >> 8) & 0xFF,
1017 (*color >> 0) & 0xFF);
1021 inline static void handle_specular_base(STATEBLOCK *sb, DWORD *color) {
1022 glColor4ub((*color >> 16) & 0xFF,
1023 (*color >> 8) & 0xFF,
1024 (*color >> 0) & 0xFF,
1025 (*color >> 24) & 0xFF); /* No idea if the alpha field is really used.. */
1028 inline static void handle_diffuse(STATEBLOCK *sb, DWORD *color, BOOLEAN lighted) {
1029 if ((lighted == FALSE) &&
1030 (sb->render_state[D3DRENDERSTATE_LIGHTING - 1] == TRUE) &&
1031 (sb->render_state[D3DRENDERSTATE_COLORVERTEX - 1] == TRUE)) {
1032 if (sb->render_state[D3DRENDERSTATE_DIFFUSEMATERIALSOURCE - 1] == D3DMCS_COLOR1) {
1033 glColorMaterial(GL_FRONT_AND_BACK, GL_DIFFUSE);
1034 handle_diffuse_base(sb, color);
1036 if (sb->render_state[D3DRENDERSTATE_AMBIENTMATERIALSOURCE - 1] == D3DMCS_COLOR1) {
1037 glColorMaterial(GL_FRONT_AND_BACK, GL_AMBIENT);
1038 handle_diffuse_base(sb, color);
1040 if ((sb->render_state[D3DRENDERSTATE_SPECULARMATERIALSOURCE - 1] == D3DMCS_COLOR1) &&
1041 (sb->render_state[D3DRENDERSTATE_SPECULARENABLE - 1] == TRUE)) {
1042 glColorMaterial(GL_FRONT_AND_BACK, GL_SPECULAR);
1043 handle_diffuse_base(sb, color);
1045 if (sb->render_state[D3DRENDERSTATE_EMISSIVEMATERIALSOURCE - 1] == D3DMCS_COLOR1) {
1046 glColorMaterial(GL_FRONT_AND_BACK, GL_EMISSION);
1047 handle_diffuse_base(sb, color);
1049 } else {
1050 handle_diffuse_base(sb, color);
1054 inline static void handle_specular(STATEBLOCK *sb, DWORD *color, BOOLEAN lighted) {
1055 if ((lighted == FALSE) &&
1056 (sb->render_state[D3DRENDERSTATE_LIGHTING - 1] == TRUE) &&
1057 (sb->render_state[D3DRENDERSTATE_COLORVERTEX - 1] == TRUE)) {
1058 if (sb->render_state[D3DRENDERSTATE_DIFFUSEMATERIALSOURCE - 1] == D3DMCS_COLOR2) {
1059 glColorMaterial(GL_FRONT_AND_BACK, GL_DIFFUSE);
1060 handle_specular_base(sb, color);
1062 if (sb->render_state[D3DRENDERSTATE_AMBIENTMATERIALSOURCE - 1] == D3DMCS_COLOR2) {
1063 glColorMaterial(GL_FRONT_AND_BACK, GL_AMBIENT);
1064 handle_specular_base(sb, color);
1066 if ((sb->render_state[D3DRENDERSTATE_SPECULARMATERIALSOURCE - 1] == D3DMCS_COLOR2) &&
1067 (sb->render_state[D3DRENDERSTATE_SPECULARENABLE - 1] == TRUE)) {
1068 glColorMaterial(GL_FRONT_AND_BACK, GL_SPECULAR);
1069 handle_specular_base(sb, color);
1071 if (sb->render_state[D3DRENDERSTATE_EMISSIVEMATERIALSOURCE - 1] == D3DMCS_COLOR2) {
1072 glColorMaterial(GL_FRONT_AND_BACK, GL_EMISSION);
1073 handle_specular_base(sb, color);
1076 /* No else here as we do not know how to handle 'specular' on its own in any case.. */
1079 inline static void handle_diffuse_and_specular(STATEBLOCK *sb, BYTE *fog_table, DWORD *color_d, DWORD *color_s, BOOLEAN lighted) {
1080 if (lighted == TRUE) {
1081 DWORD color = *color_d;
1082 if (sb->render_state[D3DRENDERSTATE_FOGENABLE - 1] == TRUE) {
1083 /* Special case where the specular value is used to do fogging */
1084 BYTE fog_intensity = *color_s >> 24; /* The alpha value of the specular component is the fog 'intensity' for this vertex */
1085 color &= 0xFF000000; /* Only keep the alpha component */
1086 color |= fog_table[((*color_d >> 0) & 0xFF) << 8 | fog_intensity] << 0;
1087 color |= fog_table[((*color_d >> 8) & 0xFF) << 8 | fog_intensity] << 8;
1088 color |= fog_table[((*color_d >> 16) & 0xFF) << 8 | fog_intensity] << 16;
1090 if (sb->render_state[D3DRENDERSTATE_SPECULARENABLE - 1] == TRUE) {
1091 /* Standard specular value in transformed mode. TODO */
1093 handle_diffuse_base(sb, &color);
1094 } else {
1095 if (sb->render_state[D3DRENDERSTATE_LIGHTING - 1] == TRUE) {
1096 handle_diffuse(sb, color_d, FALSE);
1097 handle_specular(sb, color_s, FALSE);
1098 } else {
1099 /* In that case, only put the diffuse color... */
1100 handle_diffuse_base(sb, color_d);
1105 inline static void handle_texture(D3DVALUE *coords) {
1106 glTexCoord2fv(coords);
1108 inline static void handle_textures(D3DVALUE *coords, int tex_index) {
1109 /* For the moment, draw only the first texture.. */
1110 if (tex_index == 0) glTexCoord2fv(coords);
1113 static void draw_primitive_strided(IDirect3DDeviceImpl *This,
1114 D3DPRIMITIVETYPE d3dptPrimitiveType,
1115 DWORD d3dvtVertexType,
1116 LPD3DDRAWPRIMITIVESTRIDEDDATA lpD3DDrawPrimStrideData,
1117 DWORD dwVertexCount,
1118 LPWORD dwIndices,
1119 DWORD dwIndexCount,
1120 DWORD dwFlags)
1122 BOOLEAN vertex_lighted = FALSE;
1123 IDirect3DDeviceGLImpl* glThis = (IDirect3DDeviceGLImpl*) This;
1124 int num_active_stages = 0;
1126 ENTER_GL();
1127 if (glThis->state == SURFACE_MEMORY) {
1128 This->flush_to_framebuffer(This, NULL);
1130 LEAVE_GL();
1132 glThis->state = SURFACE_GL;
1134 /* Compute the number of active texture stages */
1135 while (This->current_texture[num_active_stages] != NULL) num_active_stages++;
1137 /* This is to prevent 'thread contention' between a thread locking the device and another
1138 doing 3D display on it... */
1139 EnterCriticalSection(&(This->crit));
1141 if (TRACE_ON(ddraw)) {
1142 TRACE(" Vertex format : "); dump_flexible_vertex(d3dvtVertexType);
1145 ENTER_GL();
1147 /* Just a hack for now.. Will have to find better algorithm :-/ */
1148 if ((d3dvtVertexType & D3DFVF_POSITION_MASK) != D3DFVF_XYZ) {
1149 vertex_lighted = TRUE;
1150 } else {
1151 if ((d3dvtVertexType & D3DFVF_NORMAL) == 0) glNormal3f(0.0, 0.0, 0.0);
1154 draw_primitive_handle_GL_state(This,
1155 (d3dvtVertexType & D3DFVF_POSITION_MASK) != D3DFVF_XYZ,
1156 vertex_lighted);
1157 draw_primitive_start_GL(d3dptPrimitiveType);
1159 /* Some fast paths first before the generic case.... */
1160 if ((d3dvtVertexType == D3DFVF_VERTEX) && (num_active_stages <= 1)) {
1161 int index;
1163 for (index = 0; index < dwIndexCount; index++) {
1164 int i = (dwIndices == NULL) ? index : dwIndices[index];
1165 D3DVALUE *normal =
1166 (D3DVALUE *) (((char *) lpD3DDrawPrimStrideData->normal.lpvData) + i * lpD3DDrawPrimStrideData->normal.dwStride);
1167 D3DVALUE *tex_coord =
1168 (D3DVALUE *) (((char *) lpD3DDrawPrimStrideData->textureCoords[0].lpvData) + i * lpD3DDrawPrimStrideData->textureCoords[0].dwStride);
1169 D3DVALUE *position =
1170 (D3DVALUE *) (((char *) lpD3DDrawPrimStrideData->position.lpvData) + i * lpD3DDrawPrimStrideData->position.dwStride);
1172 handle_normal(normal);
1173 handle_texture(tex_coord);
1174 handle_xyz(position);
1176 TRACE_(ddraw_geom)(" %f %f %f / %f %f %f (%f %f)\n",
1177 position[0], position[1], position[2],
1178 normal[0], normal[1], normal[2],
1179 tex_coord[0], tex_coord[1]);
1181 } else if ((d3dvtVertexType == D3DFVF_TLVERTEX) && (num_active_stages <= 1)) {
1182 int index;
1184 for (index = 0; index < dwIndexCount; index++) {
1185 int i = (dwIndices == NULL) ? index : dwIndices[index];
1186 DWORD *color_d =
1187 (DWORD *) (((char *) lpD3DDrawPrimStrideData->diffuse.lpvData) + i * lpD3DDrawPrimStrideData->diffuse.dwStride);
1188 DWORD *color_s =
1189 (DWORD *) (((char *) lpD3DDrawPrimStrideData->specular.lpvData) + i * lpD3DDrawPrimStrideData->specular.dwStride);
1190 D3DVALUE *tex_coord =
1191 (D3DVALUE *) (((char *) lpD3DDrawPrimStrideData->textureCoords[0].lpvData) + i * lpD3DDrawPrimStrideData->textureCoords[0].dwStride);
1192 D3DVALUE *position =
1193 (D3DVALUE *) (((char *) lpD3DDrawPrimStrideData->position.lpvData) + i * lpD3DDrawPrimStrideData->position.dwStride);
1195 handle_diffuse_and_specular(&(This->state_block), glThis->fog_table, color_d, color_s, TRUE);
1196 handle_texture(tex_coord);
1197 handle_xyzrhw(position);
1199 TRACE_(ddraw_geom)(" %f %f %f %f / %02lx %02lx %02lx %02lx - %02lx %02lx %02lx %02lx (%f %f)\n",
1200 position[0], position[1], position[2], position[3],
1201 (*color_d >> 16) & 0xFF,
1202 (*color_d >> 8) & 0xFF,
1203 (*color_d >> 0) & 0xFF,
1204 (*color_d >> 24) & 0xFF,
1205 (*color_s >> 16) & 0xFF,
1206 (*color_s >> 8) & 0xFF,
1207 (*color_s >> 0) & 0xFF,
1208 (*color_s >> 24) & 0xFF,
1209 tex_coord[0], tex_coord[1]);
1211 } else if (((d3dvtVertexType & D3DFVF_POSITION_MASK) == D3DFVF_XYZ) ||
1212 ((d3dvtVertexType & D3DFVF_POSITION_MASK) == D3DFVF_XYZRHW)) {
1213 /* This is the 'slow path' but that should support all possible vertex formats out there...
1214 Note that people should write a fast path for all vertex formats out there...
1216 int index;
1217 int num_tex_index = ((d3dvtVertexType & D3DFVF_TEXCOUNT_MASK) >> D3DFVF_TEXCOUNT_SHIFT);
1218 static const D3DVALUE no_index[] = { 0.0, 0.0, 0.0, 0.0 };
1220 for (index = 0; index < dwIndexCount; index++) {
1221 int i = (dwIndices == NULL) ? index : dwIndices[index];
1222 int tex_stage;
1224 if (d3dvtVertexType & D3DFVF_NORMAL) {
1225 D3DVALUE *normal =
1226 (D3DVALUE *) (((char *) lpD3DDrawPrimStrideData->normal.lpvData) + i * lpD3DDrawPrimStrideData->normal.dwStride);
1227 handle_normal(normal);
1229 if ((d3dvtVertexType & (D3DFVF_DIFFUSE|D3DFVF_SPECULAR)) == (D3DFVF_DIFFUSE|D3DFVF_SPECULAR)) {
1230 DWORD *color_d =
1231 (DWORD *) (((char *) lpD3DDrawPrimStrideData->diffuse.lpvData) + i * lpD3DDrawPrimStrideData->diffuse.dwStride);
1232 DWORD *color_s =
1233 (DWORD *) (((char *) lpD3DDrawPrimStrideData->specular.lpvData) + i * lpD3DDrawPrimStrideData->specular.dwStride);
1234 handle_diffuse_and_specular(&(This->state_block), glThis->fog_table, color_d, color_s, vertex_lighted);
1235 } else {
1236 if (d3dvtVertexType & D3DFVF_SPECULAR) {
1237 DWORD *color_s =
1238 (DWORD *) (((char *) lpD3DDrawPrimStrideData->specular.lpvData) + i * lpD3DDrawPrimStrideData->specular.dwStride);
1239 handle_specular(&(This->state_block), color_s, vertex_lighted);
1240 } else if (d3dvtVertexType & D3DFVF_DIFFUSE) {
1241 DWORD *color_d =
1242 (DWORD *) (((char *) lpD3DDrawPrimStrideData->diffuse.lpvData) + i * lpD3DDrawPrimStrideData->diffuse.dwStride);
1243 handle_diffuse(&(This->state_block), color_d, vertex_lighted);
1247 for (tex_stage = 0; tex_stage < num_active_stages; tex_stage++) {
1248 int tex_index = This->state_block.texture_stage_state[tex_stage][D3DTSS_TEXCOORDINDEX - 1] & 0xFFFF000;
1249 if (tex_index >= num_tex_index) {
1250 handle_textures((D3DVALUE *) no_index, tex_stage);
1251 } else {
1252 D3DVALUE *tex_coord =
1253 (D3DVALUE *) (((char *) lpD3DDrawPrimStrideData->textureCoords[tex_index].lpvData) +
1254 i * lpD3DDrawPrimStrideData->textureCoords[tex_index].dwStride);
1255 handle_textures(tex_coord, tex_stage);
1259 if ((d3dvtVertexType & D3DFVF_POSITION_MASK) == D3DFVF_XYZ) {
1260 D3DVALUE *position =
1261 (D3DVALUE *) (((char *) lpD3DDrawPrimStrideData->position.lpvData) + i * lpD3DDrawPrimStrideData->position.dwStride);
1262 handle_xyz(position);
1263 } else if ((d3dvtVertexType & D3DFVF_POSITION_MASK) == D3DFVF_XYZRHW) {
1264 D3DVALUE *position =
1265 (D3DVALUE *) (((char *) lpD3DDrawPrimStrideData->position.lpvData) + i * lpD3DDrawPrimStrideData->position.dwStride);
1266 handle_xyzrhw(position);
1269 if (TRACE_ON(ddraw_geom)) {
1270 int tex_index;
1272 if ((d3dvtVertexType & D3DFVF_POSITION_MASK) == D3DFVF_XYZ) {
1273 D3DVALUE *position =
1274 (D3DVALUE *) (((char *) lpD3DDrawPrimStrideData->position.lpvData) + i * lpD3DDrawPrimStrideData->position.dwStride);
1275 TRACE_(ddraw_geom)(" %f %f %f", position[0], position[1], position[2]);
1276 } else if ((d3dvtVertexType & D3DFVF_POSITION_MASK) == D3DFVF_XYZRHW) {
1277 D3DVALUE *position =
1278 (D3DVALUE *) (((char *) lpD3DDrawPrimStrideData->position.lpvData) + i * lpD3DDrawPrimStrideData->position.dwStride);
1279 TRACE_(ddraw_geom)(" %f %f %f %f", position[0], position[1], position[2], position[3]);
1281 if (d3dvtVertexType & D3DFVF_NORMAL) {
1282 D3DVALUE *normal =
1283 (D3DVALUE *) (((char *) lpD3DDrawPrimStrideData->normal.lpvData) + i * lpD3DDrawPrimStrideData->normal.dwStride);
1284 TRACE_(ddraw_geom)(" / %f %f %f", normal[0], normal[1], normal[2]);
1286 if (d3dvtVertexType & D3DFVF_DIFFUSE) {
1287 DWORD *color_d =
1288 (DWORD *) (((char *) lpD3DDrawPrimStrideData->diffuse.lpvData) + i * lpD3DDrawPrimStrideData->diffuse.dwStride);
1289 TRACE_(ddraw_geom)(" / %02lx %02lx %02lx %02lx",
1290 (*color_d >> 16) & 0xFF,
1291 (*color_d >> 8) & 0xFF,
1292 (*color_d >> 0) & 0xFF,
1293 (*color_d >> 24) & 0xFF);
1295 if (d3dvtVertexType & D3DFVF_SPECULAR) {
1296 DWORD *color_s =
1297 (DWORD *) (((char *) lpD3DDrawPrimStrideData->specular.lpvData) + i * lpD3DDrawPrimStrideData->specular.dwStride);
1298 TRACE_(ddraw_geom)(" / %02lx %02lx %02lx %02lx",
1299 (*color_s >> 16) & 0xFF,
1300 (*color_s >> 8) & 0xFF,
1301 (*color_s >> 0) & 0xFF,
1302 (*color_s >> 24) & 0xFF);
1304 for (tex_index = 0; tex_index < ((d3dvtVertexType & D3DFVF_TEXCOUNT_MASK) >> D3DFVF_TEXCOUNT_SHIFT); tex_index++) {
1305 D3DVALUE *tex_coord =
1306 (D3DVALUE *) (((char *) lpD3DDrawPrimStrideData->textureCoords[tex_index].lpvData) +
1307 i * lpD3DDrawPrimStrideData->textureCoords[tex_index].dwStride);
1308 TRACE_(ddraw_geom)(" / %f %f", tex_coord[0], tex_coord[1]);
1310 TRACE_(ddraw_geom)("\n");
1313 } else {
1314 ERR(" matrix weighting not handled yet....\n");
1317 glEnd();
1319 /* Whatever the case, disable the color material stuff */
1320 glDisable(GL_COLOR_MATERIAL);
1322 LEAVE_GL();
1323 TRACE("End\n");
1325 LeaveCriticalSection(&(This->crit));
1328 HRESULT WINAPI
1329 GL_IDirect3DDeviceImpl_7_3T_DrawPrimitive(LPDIRECT3DDEVICE7 iface,
1330 D3DPRIMITIVETYPE d3dptPrimitiveType,
1331 DWORD d3dvtVertexType,
1332 LPVOID lpvVertices,
1333 DWORD dwVertexCount,
1334 DWORD dwFlags)
1336 ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice7, iface);
1337 D3DDRAWPRIMITIVESTRIDEDDATA strided;
1339 TRACE("(%p/%p)->(%08x,%08lx,%p,%08lx,%08lx)\n", This, iface, d3dptPrimitiveType, d3dvtVertexType, lpvVertices, dwVertexCount, dwFlags);
1340 if (TRACE_ON(ddraw)) {
1341 TRACE(" - flags : "); dump_DPFLAGS(dwFlags);
1344 convert_FVF_to_strided_data(d3dvtVertexType, lpvVertices, &strided, 0);
1345 draw_primitive_strided(This, d3dptPrimitiveType, d3dvtVertexType, &strided, dwVertexCount, NULL, dwVertexCount, dwFlags);
1347 return DD_OK;
1350 HRESULT WINAPI
1351 GL_IDirect3DDeviceImpl_7_3T_DrawIndexedPrimitive(LPDIRECT3DDEVICE7 iface,
1352 D3DPRIMITIVETYPE d3dptPrimitiveType,
1353 DWORD d3dvtVertexType,
1354 LPVOID lpvVertices,
1355 DWORD dwVertexCount,
1356 LPWORD dwIndices,
1357 DWORD dwIndexCount,
1358 DWORD dwFlags)
1360 ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice7, iface);
1361 D3DDRAWPRIMITIVESTRIDEDDATA strided;
1363 TRACE("(%p/%p)->(%08x,%08lx,%p,%08lx,%p,%08lx,%08lx)\n", This, iface, d3dptPrimitiveType, d3dvtVertexType, lpvVertices, dwVertexCount, dwIndices, dwIndexCount, dwFlags);
1364 if (TRACE_ON(ddraw)) {
1365 TRACE(" - flags : "); dump_DPFLAGS(dwFlags);
1368 convert_FVF_to_strided_data(d3dvtVertexType, lpvVertices, &strided, 0);
1369 draw_primitive_strided(This, d3dptPrimitiveType, d3dvtVertexType, &strided, dwVertexCount, dwIndices, dwIndexCount, dwFlags);
1371 return DD_OK;
1374 HRESULT WINAPI
1375 GL_IDirect3DDeviceImpl_7_3T_DrawPrimitiveStrided(LPDIRECT3DDEVICE7 iface,
1376 D3DPRIMITIVETYPE d3dptPrimitiveType,
1377 DWORD dwVertexType,
1378 LPD3DDRAWPRIMITIVESTRIDEDDATA lpD3DDrawPrimStrideData,
1379 DWORD dwVertexCount,
1380 DWORD dwFlags)
1382 ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice7, iface);
1384 TRACE("(%p/%p)->(%08x,%08lx,%p,%08lx,%08lx)\n", This, iface, d3dptPrimitiveType, dwVertexType, lpD3DDrawPrimStrideData, dwVertexCount, dwFlags);
1385 if (TRACE_ON(ddraw)) {
1386 TRACE(" - flags : "); dump_DPFLAGS(dwFlags);
1388 draw_primitive_strided(This, d3dptPrimitiveType, dwVertexType, lpD3DDrawPrimStrideData, dwVertexCount, NULL, dwVertexCount, dwFlags);
1390 return DD_OK;
1393 HRESULT WINAPI
1394 GL_IDirect3DDeviceImpl_7_3T_DrawIndexedPrimitiveStrided(LPDIRECT3DDEVICE7 iface,
1395 D3DPRIMITIVETYPE d3dptPrimitiveType,
1396 DWORD dwVertexType,
1397 LPD3DDRAWPRIMITIVESTRIDEDDATA lpD3DDrawPrimStrideData,
1398 DWORD dwVertexCount,
1399 LPWORD lpIndex,
1400 DWORD dwIndexCount,
1401 DWORD dwFlags)
1403 ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice7, iface);
1405 TRACE("(%p/%p)->(%08x,%08lx,%p,%08lx,%p,%08lx,%08lx)\n", This, iface, d3dptPrimitiveType, dwVertexType, lpD3DDrawPrimStrideData, dwVertexCount, lpIndex, dwIndexCount, dwFlags);
1406 if (TRACE_ON(ddraw)) {
1407 TRACE(" - flags : "); dump_DPFLAGS(dwFlags);
1410 draw_primitive_strided(This, d3dptPrimitiveType, dwVertexType, lpD3DDrawPrimStrideData, dwVertexCount, lpIndex, dwIndexCount, dwFlags);
1412 return DD_OK;
1415 HRESULT WINAPI
1416 GL_IDirect3DDeviceImpl_7_3T_DrawPrimitiveVB(LPDIRECT3DDEVICE7 iface,
1417 D3DPRIMITIVETYPE d3dptPrimitiveType,
1418 LPDIRECT3DVERTEXBUFFER7 lpD3DVertexBuf,
1419 DWORD dwStartVertex,
1420 DWORD dwNumVertices,
1421 DWORD dwFlags)
1423 ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice7, iface);
1424 IDirect3DVertexBufferImpl *vb_impl = ICOM_OBJECT(IDirect3DVertexBufferImpl, IDirect3DVertexBuffer7, lpD3DVertexBuf);
1425 D3DDRAWPRIMITIVESTRIDEDDATA strided;
1427 TRACE("(%p/%p)->(%08x,%p,%08lx,%08lx,%08lx)\n", This, iface, d3dptPrimitiveType, lpD3DVertexBuf, dwStartVertex, dwNumVertices, dwFlags);
1428 if (TRACE_ON(ddraw)) {
1429 TRACE(" - flags : "); dump_DPFLAGS(dwFlags);
1432 if (vb_impl->processed == TRUE) {
1433 IDirect3DVertexBufferGLImpl *vb_glimp = (IDirect3DVertexBufferGLImpl *) vb_impl;
1434 IDirect3DDeviceGLImpl *glThis = (IDirect3DDeviceGLImpl *) This;
1436 glThis->transform_state = GL_TRANSFORM_VERTEXBUFFER;
1437 This->set_matrices(This, VIEWMAT_CHANGED|WORLDMAT_CHANGED|PROJMAT_CHANGED,
1438 &(vb_glimp->world_mat), &(vb_glimp->view_mat), &(vb_glimp->proj_mat));
1440 convert_FVF_to_strided_data(vb_glimp->dwVertexTypeDesc, vb_glimp->vertices, &strided, dwStartVertex);
1441 draw_primitive_strided(This, d3dptPrimitiveType, vb_glimp->dwVertexTypeDesc, &strided, dwNumVertices, NULL, dwNumVertices, dwFlags);
1443 } else {
1444 convert_FVF_to_strided_data(vb_impl->desc.dwFVF, vb_impl->vertices, &strided, dwStartVertex);
1445 draw_primitive_strided(This, d3dptPrimitiveType, vb_impl->desc.dwFVF, &strided, dwNumVertices, NULL, dwNumVertices, dwFlags);
1448 return DD_OK;
1451 HRESULT WINAPI
1452 GL_IDirect3DDeviceImpl_7_3T_DrawIndexedPrimitiveVB(LPDIRECT3DDEVICE7 iface,
1453 D3DPRIMITIVETYPE d3dptPrimitiveType,
1454 LPDIRECT3DVERTEXBUFFER7 lpD3DVertexBuf,
1455 DWORD dwStartVertex,
1456 DWORD dwNumVertices,
1457 LPWORD lpwIndices,
1458 DWORD dwIndexCount,
1459 DWORD dwFlags)
1461 ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice7, iface);
1462 IDirect3DVertexBufferImpl *vb_impl = ICOM_OBJECT(IDirect3DVertexBufferImpl, IDirect3DVertexBuffer7, lpD3DVertexBuf);
1463 D3DDRAWPRIMITIVESTRIDEDDATA strided;
1465 TRACE("(%p/%p)->(%08x,%p,%08lx,%08lx,%p,%08lx,%08lx)\n", This, iface, d3dptPrimitiveType, lpD3DVertexBuf, dwStartVertex, dwNumVertices, lpwIndices, dwIndexCount, dwFlags);
1466 if (TRACE_ON(ddraw)) {
1467 TRACE(" - flags : "); dump_DPFLAGS(dwFlags);
1470 if (vb_impl->processed == TRUE) {
1471 IDirect3DVertexBufferGLImpl *vb_glimp = (IDirect3DVertexBufferGLImpl *) vb_impl;
1472 IDirect3DDeviceGLImpl *glThis = (IDirect3DDeviceGLImpl *) This;
1474 glThis->transform_state = GL_TRANSFORM_VERTEXBUFFER;
1475 This->set_matrices(This, VIEWMAT_CHANGED|WORLDMAT_CHANGED|PROJMAT_CHANGED,
1476 &(vb_glimp->world_mat), &(vb_glimp->view_mat), &(vb_glimp->proj_mat));
1478 convert_FVF_to_strided_data(vb_glimp->dwVertexTypeDesc, vb_glimp->vertices, &strided, dwStartVertex);
1479 draw_primitive_strided(This, d3dptPrimitiveType, vb_glimp->dwVertexTypeDesc, &strided, dwNumVertices, lpwIndices, dwIndexCount, dwFlags);
1481 } else {
1482 convert_FVF_to_strided_data(vb_impl->desc.dwFVF, vb_impl->vertices, &strided, dwStartVertex);
1483 draw_primitive_strided(This, d3dptPrimitiveType, vb_impl->desc.dwFVF, &strided, dwNumVertices, lpwIndices, dwIndexCount, dwFlags);
1486 return DD_OK;
1489 static GLenum
1490 convert_min_filter_to_GL(D3DTEXTUREMINFILTER dwMinState, D3DTEXTUREMIPFILTER dwMipState)
1492 GLenum gl_state;
1494 if (dwMipState == D3DTFP_NONE) {
1495 switch (dwMinState) {
1496 case D3DTFN_POINT: gl_state = GL_NEAREST; break;
1497 case D3DTFN_LINEAR: gl_state = GL_LINEAR; break;
1498 default: gl_state = GL_LINEAR; break;
1500 } else if (dwMipState == D3DTFP_POINT) {
1501 switch (dwMinState) {
1502 case D3DTFN_POINT: gl_state = GL_NEAREST_MIPMAP_NEAREST; break;
1503 case D3DTFN_LINEAR: gl_state = GL_LINEAR_MIPMAP_NEAREST; break;
1504 default: gl_state = GL_LINEAR_MIPMAP_NEAREST; break;
1506 } else {
1507 switch (dwMinState) {
1508 case D3DTFN_POINT: gl_state = GL_NEAREST_MIPMAP_LINEAR; break;
1509 case D3DTFN_LINEAR: gl_state = GL_LINEAR_MIPMAP_LINEAR; break;
1510 default: gl_state = GL_LINEAR_MIPMAP_LINEAR; break;
1513 return gl_state;
1516 static GLenum
1517 convert_mag_filter_to_GL(D3DTEXTUREMAGFILTER dwState)
1519 GLenum gl_state;
1521 switch (dwState) {
1522 case D3DTFG_POINT:
1523 gl_state = GL_NEAREST;
1524 break;
1525 case D3DTFG_LINEAR:
1526 gl_state = GL_LINEAR;
1527 break;
1528 default:
1529 gl_state = GL_LINEAR;
1530 break;
1532 return gl_state;
1535 /* We need a static function for that to handle the 'special' case of 'SELECT_ARG2' */
1536 static BOOLEAN
1537 handle_color_alpha_args(DWORD dwStage, D3DTEXTURESTAGESTATETYPE d3dTexStageStateType, DWORD dwState, D3DTEXTUREOP tex_op)
1539 BOOLEAN is_complement = FALSE;
1540 BOOLEAN is_alpha_replicate = FALSE;
1541 BOOLEAN handled = TRUE;
1542 GLenum src;
1543 BOOLEAN is_color = ((d3dTexStageStateType == D3DTSS_COLORARG1) || (d3dTexStageStateType == D3DTSS_COLORARG2));
1544 int num;
1546 if (is_color) {
1547 if (d3dTexStageStateType == D3DTSS_COLORARG1) num = 0;
1548 else if (d3dTexStageStateType == D3DTSS_COLORARG2) num = 1;
1549 else {
1550 handled = FALSE;
1551 num = 0;
1553 if (tex_op == D3DTOP_SELECTARG2) {
1554 num = 1 - num;
1556 } else {
1557 if (d3dTexStageStateType == D3DTSS_ALPHAARG1) num = 0;
1558 else if (d3dTexStageStateType == D3DTSS_ALPHAARG2) num = 1;
1559 else {
1560 handled = FALSE;
1561 num = 0;
1563 if (tex_op == D3DTOP_SELECTARG2) {
1564 num = 1 - num;
1568 if (dwState & D3DTA_COMPLEMENT) {
1569 is_complement = TRUE;
1571 if (dwState & D3DTA_ALPHAREPLICATE) {
1572 is_alpha_replicate = TRUE;
1574 dwState &= D3DTA_SELECTMASK;
1575 if ((dwStage == 0) && (dwState == D3DTA_CURRENT)) {
1576 dwState = D3DTA_DIFFUSE;
1579 switch (dwState) {
1580 case D3DTA_CURRENT: src = GL_PREVIOUS_EXT; break;
1581 case D3DTA_DIFFUSE: src = GL_PRIMARY_COLOR_EXT; break;
1582 case D3DTA_TEXTURE: src = GL_TEXTURE; break;
1583 case D3DTA_TFACTOR: src = GL_CONSTANT_EXT; FIXME(" no handling yet of setting of constant value !\n"); break;
1584 default: src = GL_TEXTURE; handled = FALSE; break;
1587 if (is_color) {
1588 glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_RGB_EXT + num, src);
1589 if (is_alpha_replicate) {
1590 glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND0_RGB_EXT + num, is_complement ? GL_ONE_MINUS_SRC_ALPHA : GL_SRC_ALPHA);
1591 } else {
1592 glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND0_RGB_EXT + num, is_complement ? GL_ONE_MINUS_SRC_COLOR : GL_SRC_COLOR);
1594 } else {
1595 glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_ALPHA_EXT + num, src);
1596 glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND0_ALPHA_EXT + num, is_complement ? GL_ONE_MINUS_SRC_ALPHA : GL_SRC_ALPHA);
1599 return handled;
1602 HRESULT WINAPI
1603 GL_IDirect3DDeviceImpl_7_3T_SetTextureStageState(LPDIRECT3DDEVICE7 iface,
1604 DWORD dwStage,
1605 D3DTEXTURESTAGESTATETYPE d3dTexStageStateType,
1606 DWORD dwState)
1608 ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice7, iface);
1609 const char *type;
1610 DWORD prev_state;
1612 TRACE("(%p/%p)->(%08lx,%08x,%08lx)\n", This, iface, dwStage, d3dTexStageStateType, dwState);
1614 if (dwStage > 0) return DD_OK; /* We nothing in this case for now */
1616 switch (d3dTexStageStateType) {
1617 #define GEN_CASE(a) case a: type = #a; break
1618 GEN_CASE(D3DTSS_COLOROP);
1619 GEN_CASE(D3DTSS_COLORARG1);
1620 GEN_CASE(D3DTSS_COLORARG2);
1621 GEN_CASE(D3DTSS_ALPHAOP);
1622 GEN_CASE(D3DTSS_ALPHAARG1);
1623 GEN_CASE(D3DTSS_ALPHAARG2);
1624 GEN_CASE(D3DTSS_BUMPENVMAT00);
1625 GEN_CASE(D3DTSS_BUMPENVMAT01);
1626 GEN_CASE(D3DTSS_BUMPENVMAT10);
1627 GEN_CASE(D3DTSS_BUMPENVMAT11);
1628 GEN_CASE(D3DTSS_TEXCOORDINDEX);
1629 GEN_CASE(D3DTSS_ADDRESS);
1630 GEN_CASE(D3DTSS_ADDRESSU);
1631 GEN_CASE(D3DTSS_ADDRESSV);
1632 GEN_CASE(D3DTSS_BORDERCOLOR);
1633 GEN_CASE(D3DTSS_MAGFILTER);
1634 GEN_CASE(D3DTSS_MINFILTER);
1635 GEN_CASE(D3DTSS_MIPFILTER);
1636 GEN_CASE(D3DTSS_MIPMAPLODBIAS);
1637 GEN_CASE(D3DTSS_MAXMIPLEVEL);
1638 GEN_CASE(D3DTSS_MAXANISOTROPY);
1639 GEN_CASE(D3DTSS_BUMPENVLSCALE);
1640 GEN_CASE(D3DTSS_BUMPENVLOFFSET);
1641 GEN_CASE(D3DTSS_TEXTURETRANSFORMFLAGS);
1642 #undef GEN_CASE
1643 default: type = "UNKNOWN";
1646 /* Store the values in the state array */
1647 prev_state = This->state_block.texture_stage_state[dwStage][d3dTexStageStateType - 1];
1648 This->state_block.texture_stage_state[dwStage][d3dTexStageStateType - 1] = dwState;
1649 /* Some special cases when one state modifies more than one... */
1650 if (d3dTexStageStateType == D3DTSS_ADDRESS) {
1651 This->state_block.texture_stage_state[dwStage][D3DTSS_ADDRESSU - 1] = dwState;
1652 This->state_block.texture_stage_state[dwStage][D3DTSS_ADDRESSV - 1] = dwState;
1655 switch (d3dTexStageStateType) {
1656 case D3DTSS_MINFILTER:
1657 case D3DTSS_MIPFILTER:
1658 if (TRACE_ON(ddraw)) {
1659 if (d3dTexStageStateType == D3DTSS_MINFILTER) {
1660 switch ((D3DTEXTUREMINFILTER) dwState) {
1661 case D3DTFN_POINT: TRACE(" Stage type is : D3DTSS_MINFILTER => D3DTFN_POINT\n"); break;
1662 case D3DTFN_LINEAR: TRACE(" Stage type is : D3DTSS_MINFILTER => D3DTFN_LINEAR\n"); break;
1663 default: FIXME(" Unhandled stage type : D3DTSS_MINFILTER => %08lx\n", dwState); break;
1665 } else {
1666 switch ((D3DTEXTUREMIPFILTER) dwState) {
1667 case D3DTFP_NONE: TRACE(" Stage type is : D3DTSS_MIPFILTER => D3DTFP_NONE\n"); break;
1668 case D3DTFP_POINT: TRACE(" Stage type is : D3DTSS_MIPFILTER => D3DTFP_POINT\n"); break;
1669 case D3DTFP_LINEAR: TRACE(" Stage type is : D3DTSS_MIPFILTER => D3DTFP_LINEAR\n"); break;
1670 default: FIXME(" Unhandled stage type : D3DTSS_MIPFILTER => %08lx\n", dwState); break;
1675 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER,
1676 convert_min_filter_to_GL(This->state_block.texture_stage_state[dwStage][D3DTSS_MINFILTER - 1],
1677 This->state_block.texture_stage_state[dwStage][D3DTSS_MIPFILTER - 1]));
1678 break;
1680 case D3DTSS_MAGFILTER:
1681 if (TRACE_ON(ddraw)) {
1682 switch ((D3DTEXTUREMAGFILTER) dwState) {
1683 case D3DTFG_POINT: TRACE(" Stage type is : D3DTSS_MAGFILTER => D3DTFN_POINT\n"); break;
1684 case D3DTFG_LINEAR: TRACE(" Stage type is : D3DTSS_MAGFILTER => D3DTFN_LINEAR\n"); break;
1685 default: FIXME(" Unhandled stage type : D3DTSS_MAGFILTER => %08lx\n", dwState); break;
1688 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, convert_mag_filter_to_GL(dwState));
1689 break;
1691 case D3DTSS_ADDRESS:
1692 case D3DTSS_ADDRESSU:
1693 case D3DTSS_ADDRESSV: {
1694 GLenum arg = GL_REPEAT; /* Default value */
1695 switch ((D3DTEXTUREADDRESS) dwState) {
1696 case D3DTADDRESS_WRAP: TRACE(" Stage type is : %s => D3DTADDRESS_WRAP\n", type); arg = GL_REPEAT; break;
1697 case D3DTADDRESS_CLAMP: TRACE(" Stage type is : %s => D3DTADDRESS_CLAMP\n", type); arg = GL_CLAMP; break;
1698 case D3DTADDRESS_BORDER: TRACE(" Stage type is : %s => D3DTADDRESS_BORDER\n", type); arg = GL_CLAMP_TO_EDGE; break;
1699 #if defined(GL_VERSION_1_4)
1700 case D3DTADDRESS_MIRROR: TRACE(" Stage type is : %s => D3DTADDRESS_MIRROR\n", type); arg = GL_MIRRORED_REPEAT; break;
1701 #elif defined(GL_ARB_texture_mirrored_repeat)
1702 case D3DTADDRESS_MIRROR: TRACE(" Stage type is : %s => D3DTADDRESS_MIRROR\n", type); arg = GL_MIRRORED_REPEAT_ARB; break;
1703 #endif
1704 default: FIXME(" Unhandled stage type : %s => %08lx\n", type, dwState); break;
1706 if ((d3dTexStageStateType == D3DTSS_ADDRESS) ||
1707 (d3dTexStageStateType == D3DTSS_ADDRESSU))
1708 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, arg);
1709 if ((d3dTexStageStateType == D3DTSS_ADDRESS) ||
1710 (d3dTexStageStateType == D3DTSS_ADDRESSV))
1711 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, arg);
1712 } break;
1714 case D3DTSS_ALPHAOP:
1715 case D3DTSS_COLOROP: {
1716 int scale = 1;
1717 GLenum parm = (d3dTexStageStateType == D3DTSS_ALPHAOP) ? GL_COMBINE_ALPHA_EXT : GL_COMBINE_RGB_EXT;
1718 const char *value;
1719 int handled = 1;
1721 switch (dwState) {
1722 #define GEN_CASE(a) case a: value = #a; break
1723 GEN_CASE(D3DTOP_DISABLE);
1724 GEN_CASE(D3DTOP_SELECTARG1);
1725 GEN_CASE(D3DTOP_SELECTARG2);
1726 GEN_CASE(D3DTOP_MODULATE);
1727 GEN_CASE(D3DTOP_MODULATE2X);
1728 GEN_CASE(D3DTOP_MODULATE4X);
1729 GEN_CASE(D3DTOP_ADD);
1730 GEN_CASE(D3DTOP_ADDSIGNED);
1731 GEN_CASE(D3DTOP_ADDSIGNED2X);
1732 GEN_CASE(D3DTOP_SUBTRACT);
1733 GEN_CASE(D3DTOP_ADDSMOOTH);
1734 GEN_CASE(D3DTOP_BLENDDIFFUSEALPHA);
1735 GEN_CASE(D3DTOP_BLENDTEXTUREALPHA);
1736 GEN_CASE(D3DTOP_BLENDFACTORALPHA);
1737 GEN_CASE(D3DTOP_BLENDTEXTUREALPHAPM);
1738 GEN_CASE(D3DTOP_BLENDCURRENTALPHA);
1739 GEN_CASE(D3DTOP_PREMODULATE);
1740 GEN_CASE(D3DTOP_MODULATEALPHA_ADDCOLOR);
1741 GEN_CASE(D3DTOP_MODULATECOLOR_ADDALPHA);
1742 GEN_CASE(D3DTOP_MODULATEINVALPHA_ADDCOLOR);
1743 GEN_CASE(D3DTOP_MODULATEINVCOLOR_ADDALPHA);
1744 GEN_CASE(D3DTOP_BUMPENVMAP);
1745 GEN_CASE(D3DTOP_BUMPENVMAPLUMINANCE);
1746 GEN_CASE(D3DTOP_DOTPRODUCT3);
1747 GEN_CASE(D3DTOP_FORCE_DWORD);
1748 #undef GEN_CASE
1749 default: value = "UNKNOWN";
1752 if ((d3dTexStageStateType == D3DTSS_COLOROP) && (dwState == D3DTOP_DISABLE) && (dwStage == 0)) {
1753 glDisable(GL_TEXTURE_2D);
1754 TRACE(" disabling 2D texturing.\n");
1755 } else {
1756 /* Re-enable texturing */
1757 if ((dwStage == 0) && (This->current_texture[0] != NULL)) {
1758 glEnable(GL_TEXTURE_2D);
1759 TRACE(" enabling 2D texturing.\n");
1762 /* Re-Enable GL_TEXTURE_ENV_MODE, GL_COMBINE_EXT */
1763 if (dwState != D3DTOP_DISABLE) {
1764 glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE_EXT);
1767 /* Now set up the operand correctly */
1768 switch (dwState) {
1769 case D3DTOP_DISABLE:
1770 /* Contrary to the docs, alpha can be disabled when colorop is enabled
1771 and it works, so ignore this op */
1772 TRACE(" Note : disable ALPHAOP but COLOROP enabled!\n");
1773 break;
1775 case D3DTOP_SELECTARG1:
1776 case D3DTOP_SELECTARG2:
1777 glTexEnvi(GL_TEXTURE_ENV, parm, GL_REPLACE);
1778 break;
1780 case D3DTOP_MODULATE4X:
1781 scale = scale * 2; /* Drop through */
1782 case D3DTOP_MODULATE2X:
1783 scale = scale * 2; /* Drop through */
1784 case D3DTOP_MODULATE:
1785 glTexEnvi(GL_TEXTURE_ENV, parm, GL_MODULATE);
1786 break;
1788 case D3DTOP_ADD:
1789 glTexEnvi(GL_TEXTURE_ENV, parm, GL_ADD);
1790 break;
1792 case D3DTOP_ADDSIGNED2X:
1793 scale = scale * 2; /* Drop through */
1794 case D3DTOP_ADDSIGNED:
1795 glTexEnvi(GL_TEXTURE_ENV, parm, GL_ADD_SIGNED_EXT);
1796 break;
1798 default:
1799 handled = FALSE;
1800 break;
1804 if (((prev_state == D3DTOP_SELECTARG2) && (dwState != D3DTOP_SELECTARG2)) ||
1805 ((dwState == D3DTOP_SELECTARG2) && (prev_state != D3DTOP_SELECTARG2))) {
1806 /* Switch the arguments if needed... */
1807 if (d3dTexStageStateType == D3DTSS_COLOROP) {
1808 handle_color_alpha_args(dwStage, D3DTSS_COLORARG1,
1809 This->state_block.texture_stage_state[dwStage][D3DTSS_COLORARG1 - 1],
1810 dwState);
1811 handle_color_alpha_args(dwStage, D3DTSS_COLORARG2,
1812 This->state_block.texture_stage_state[dwStage][D3DTSS_COLORARG2 - 1],
1813 dwState);
1814 } else {
1815 handle_color_alpha_args(dwStage, D3DTSS_ALPHAARG1,
1816 This->state_block.texture_stage_state[dwStage][D3DTSS_ALPHAARG1 - 1],
1817 dwState);
1818 handle_color_alpha_args(dwStage, D3DTSS_ALPHAARG2,
1819 This->state_block.texture_stage_state[dwStage][D3DTSS_ALPHAARG2 - 1],
1820 dwState);
1824 if (handled) {
1825 if (d3dTexStageStateType == D3DTSS_ALPHAOP) {
1826 glTexEnvi(GL_TEXTURE_ENV, GL_ALPHA_SCALE, scale);
1827 } else {
1828 glTexEnvi(GL_TEXTURE_ENV, GL_RGB_SCALE_EXT, scale);
1830 TRACE(" Stage type is : %s => %s\n", type, value);
1831 } else {
1832 FIXME(" Unhandled stage type is : %s => %s\n", type, value);
1834 } break;
1836 case D3DTSS_COLORARG1:
1837 case D3DTSS_COLORARG2:
1838 case D3DTSS_ALPHAARG1:
1839 case D3DTSS_ALPHAARG2: {
1840 const char *value, *value_comp = "", *value_alpha = "";
1841 BOOLEAN handled;
1842 D3DTEXTUREOP tex_op;
1844 switch (dwState & D3DTA_SELECTMASK) {
1845 #define GEN_CASE(a) case a: value = #a; break
1846 GEN_CASE(D3DTA_DIFFUSE);
1847 GEN_CASE(D3DTA_CURRENT);
1848 GEN_CASE(D3DTA_TEXTURE);
1849 GEN_CASE(D3DTA_TFACTOR);
1850 GEN_CASE(D3DTA_SPECULAR);
1851 #undef GEN_CASE
1852 default: value = "UNKNOWN";
1854 if (dwState & D3DTA_COMPLEMENT) {
1855 value_comp = " | D3DTA_COMPLEMENT";
1857 if (dwState & D3DTA_ALPHAREPLICATE) {
1858 value_alpha = " | D3DTA_ALPHAREPLICATE";
1861 if ((d3dTexStageStateType == D3DTSS_COLORARG1) || (d3dTexStageStateType == D3DTSS_COLORARG2)) {
1862 tex_op = This->state_block.texture_stage_state[dwStage][D3DTSS_COLOROP - 1];
1863 } else {
1864 tex_op = This->state_block.texture_stage_state[dwStage][D3DTSS_ALPHAOP - 1];
1867 handled = handle_color_alpha_args(dwStage, d3dTexStageStateType, dwState, tex_op);
1869 if (handled) {
1870 TRACE(" Stage type : %s => %s%s%s\n", type, value, value_comp, value_alpha);
1871 } else {
1872 FIXME(" Unhandled stage type : %s => %s%s%s\n", type, value, value_comp, value_alpha);
1874 } break;
1876 case D3DTSS_MIPMAPLODBIAS: {
1877 D3DVALUE value = *((D3DVALUE *) &dwState);
1878 BOOLEAN handled = TRUE;
1880 if (value != 0.0)
1881 handled = FALSE;
1883 if (handled) {
1884 TRACE(" Stage type : D3DTSS_MIPMAPLODBIAS => %f\n", value);
1885 } else {
1886 FIXME(" Unhandled stage type : D3DTSS_MIPMAPLODBIAS => %f\n", value);
1888 } break;
1890 case D3DTSS_MAXMIPLEVEL:
1891 if (dwState == 0) {
1892 TRACE(" Stage type : D3DTSS_MAXMIPLEVEL => 0 (disabled) \n");
1893 } else {
1894 FIXME(" Unhandled stage type : D3DTSS_MAXMIPLEVEL => %ld\n", dwState);
1896 break;
1898 case D3DTSS_BORDERCOLOR: {
1899 GLfloat color[4];
1901 color[0] = ((dwState >> 16) & 0xFF) / 255.0;
1902 color[1] = ((dwState >> 8) & 0xFF) / 255.0;
1903 color[2] = ((dwState >> 0) & 0xFF) / 255.0;
1904 color[3] = ((dwState >> 24) & 0xFF) / 255.0;
1906 glTexParameterfv(GL_TEXTURE_2D, GL_TEXTURE_BORDER_COLOR, color);
1908 TRACE(" Stage type : D3DTSS_BORDERCOLOR => %02lx %02lx %02lx %02lx (RGBA)\n",
1909 ((dwState >> 16) & 0xFF),
1910 ((dwState >> 8) & 0xFF),
1911 ((dwState >> 0) & 0xFF),
1912 ((dwState >> 24) & 0xFF));
1913 } break;
1915 case D3DTSS_TEXCOORDINDEX: {
1916 BOOLEAN handled = TRUE;
1917 const char *value;
1919 switch (dwState & 0xFFFF0000) {
1920 #define GEN_CASE(a) case a: value = #a; break
1921 GEN_CASE(D3DTSS_TCI_PASSTHRU);
1922 GEN_CASE(D3DTSS_TCI_CAMERASPACENORMAL);
1923 GEN_CASE(D3DTSS_TCI_CAMERASPACEPOSITION);
1924 GEN_CASE(D3DTSS_TCI_CAMERASPACEREFLECTIONVECTOR);
1925 #undef GEN_CASE
1926 default: value = "UNKNOWN";
1928 if ((dwState & 0xFFFF0000) != D3DTSS_TCI_PASSTHRU)
1929 handled = FALSE;
1931 if (handled) {
1932 TRACE(" Stage type : D3DTSS_TEXCOORDINDEX => %ld | %s\n", dwState & 0x0000FFFF, value);
1933 } else {
1934 FIXME(" Unhandled stage type : D3DTSS_TEXCOORDINDEX => %ld | %s\n", dwState & 0x0000FFFF, value);
1936 } break;
1938 case D3DTSS_TEXTURETRANSFORMFLAGS: {
1939 const char *projected = "", *value;
1940 BOOLEAN handled = TRUE;
1941 switch (dwState & 0xFF) {
1942 #define GEN_CASE(a) case a: value = #a; break
1943 GEN_CASE(D3DTTFF_DISABLE);
1944 GEN_CASE(D3DTTFF_COUNT1);
1945 GEN_CASE(D3DTTFF_COUNT2);
1946 GEN_CASE(D3DTTFF_COUNT3);
1947 GEN_CASE(D3DTTFF_COUNT4);
1948 #undef GEN_CASE
1949 default: value = "UNKNOWN";
1951 if (dwState & D3DTTFF_PROJECTED)
1952 projected = " | D3DTTFF_PROJECTED";
1954 if (dwState != D3DTTFF_DISABLE)
1955 handled = FALSE;
1957 if (handled == TRUE) {
1958 TRACE(" Stage type : D3DTSS_TEXTURETRANSFORMFLAGS => %s%s\n", value, projected);
1959 } else {
1960 FIXME(" Unhandled stage type : D3DTSS_TEXTURETRANSFORMFLAGS => %s%s\n", value, projected);
1962 } break;
1964 default:
1965 FIXME(" Unhandled stage type : %s => %08lx\n", type, dwState);
1966 break;
1969 return DD_OK;
1972 HRESULT WINAPI
1973 GL_IDirect3DDeviceImpl_7_3T_SetTexture(LPDIRECT3DDEVICE7 iface,
1974 DWORD dwStage,
1975 LPDIRECTDRAWSURFACE7 lpTexture2)
1977 ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice7, iface);
1979 TRACE("(%p/%p)->(%08lx,%p)\n", This, iface, dwStage, lpTexture2);
1981 if (dwStage > 0) return DD_OK;
1983 if (This->current_texture[dwStage] != NULL) {
1984 IDirectDrawSurface7_Release(ICOM_INTERFACE(This->current_texture[dwStage], IDirectDrawSurface7));
1987 ENTER_GL();
1988 if (lpTexture2 == NULL) {
1989 This->current_texture[dwStage] = NULL;
1991 TRACE(" disabling 2D texturing.\n");
1992 glBindTexture(GL_TEXTURE_2D, 0);
1993 glDisable(GL_TEXTURE_2D);
1994 } else {
1995 IDirectDrawSurfaceImpl *tex_impl = ICOM_OBJECT(IDirectDrawSurfaceImpl, IDirectDrawSurface7, lpTexture2);
1996 GLint max_mip_level;
1998 This->current_texture[dwStage] = tex_impl;
1999 IDirectDrawSurface7_AddRef(ICOM_INTERFACE(tex_impl, IDirectDrawSurface7)); /* Not sure about this either */
2001 if (This->state_block.texture_stage_state[dwStage][D3DTSS_COLOROP - 1] != D3DTOP_DISABLE) {
2002 /* Do not re-enable texturing if it was disabled due to the COLOROP code */
2003 glEnable(GL_TEXTURE_2D);
2004 TRACE(" enabling 2D texturing.\n");
2006 gltex_upload_texture(tex_impl);
2008 if ((tex_impl->surface_desc.ddsCaps.dwCaps & DDSCAPS_MIPMAP) == 0) {
2009 max_mip_level = 0;
2010 } else {
2011 max_mip_level = tex_impl->surface_desc.u2.dwMipMapCount - 1;
2014 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER,
2015 convert_mag_filter_to_GL(This->state_block.texture_stage_state[dwStage][D3DTSS_MAGFILTER - 1]));
2016 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER,
2017 convert_min_filter_to_GL(This->state_block.texture_stage_state[dwStage][D3DTSS_MINFILTER - 1],
2018 This->state_block.texture_stage_state[dwStage][D3DTSS_MIPFILTER - 1]));
2019 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LEVEL, max_mip_level);
2021 LEAVE_GL();
2023 return DD_OK;
2026 HRESULT WINAPI
2027 GL_IDirect3DDeviceImpl_7_GetCaps(LPDIRECT3DDEVICE7 iface,
2028 LPD3DDEVICEDESC7 lpD3DHELDevDesc)
2030 ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice7, iface);
2031 TRACE("(%p/%p)->(%p)\n", This, iface, lpD3DHELDevDesc);
2033 fill_opengl_caps_7(lpD3DHELDevDesc);
2035 TRACE(" returning caps : no dump function yet.\n");
2037 return DD_OK;
2040 HRESULT WINAPI
2041 GL_IDirect3DDeviceImpl_7_SetMaterial(LPDIRECT3DDEVICE7 iface,
2042 LPD3DMATERIAL7 lpMat)
2044 ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice7, iface);
2045 TRACE("(%p/%p)->(%p)\n", This, iface, lpMat);
2047 if (TRACE_ON(ddraw)) {
2048 TRACE(" material is : \n");
2049 dump_D3DMATERIAL7(lpMat);
2052 This->current_material = *lpMat;
2054 glMaterialfv(GL_FRONT_AND_BACK,
2055 GL_DIFFUSE,
2056 (float *) &(This->current_material.u.diffuse));
2057 glMaterialfv(GL_FRONT_AND_BACK,
2058 GL_AMBIENT,
2059 (float *) &(This->current_material.u1.ambient));
2060 glMaterialfv(GL_FRONT_AND_BACK,
2061 GL_SPECULAR,
2062 (float *) &(This->current_material.u2.specular));
2063 glMaterialfv(GL_FRONT_AND_BACK,
2064 GL_EMISSION,
2065 (float *) &(This->current_material.u3.emissive));
2066 glMaterialf(GL_FRONT_AND_BACK,
2067 GL_SHININESS,
2068 This->current_material.u4.power); /* Not sure about this... */
2070 return DD_OK;
2074 HRESULT WINAPI
2075 GL_IDirect3DDeviceImpl_7_SetLight(LPDIRECT3DDEVICE7 iface,
2076 DWORD dwLightIndex,
2077 LPD3DLIGHT7 lpLight)
2079 ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice7, iface);
2080 TRACE("(%p/%p)->(%08lx,%p)\n", This, iface, dwLightIndex, lpLight);
2082 if (TRACE_ON(ddraw)) {
2083 TRACE(" setting light : \n");
2084 dump_D3DLIGHT7(lpLight);
2087 if (dwLightIndex > MAX_LIGHTS) return DDERR_INVALIDPARAMS;
2088 This->set_lights |= 0x00000001 << dwLightIndex;
2089 This->light_parameters[dwLightIndex] = *lpLight;
2091 switch (lpLight->dltType) {
2092 case D3DLIGHT_DIRECTIONAL: {
2093 float direction[4];
2094 float cut_off = 180.0;
2096 glLightfv(GL_LIGHT0 + dwLightIndex, GL_AMBIENT, (float *) &(lpLight->dcvAmbient));
2097 glLightfv(GL_LIGHT0 + dwLightIndex, GL_DIFFUSE, (float *) &(lpLight->dcvDiffuse));
2098 glLightfv(GL_LIGHT0 + dwLightIndex, GL_SPECULAR, (float *) &(lpLight->dcvSpecular));
2099 glLightfv(GL_LIGHT0 + dwLightIndex, GL_SPOT_CUTOFF, &cut_off);
2101 direction[0] = lpLight->dvDirection.u1.x;
2102 direction[1] = lpLight->dvDirection.u2.y;
2103 direction[2] = lpLight->dvDirection.u3.z;
2104 direction[3] = 0.0;
2105 glLightfv(GL_LIGHT0 + dwLightIndex, GL_POSITION, (float *) direction);
2106 } break;
2108 case D3DLIGHT_POINT: {
2109 float position[4];
2110 float cut_off = 180.0;
2112 glLightfv(GL_LIGHT0 + dwLightIndex, GL_AMBIENT, (float *) &(lpLight->dcvAmbient));
2113 glLightfv(GL_LIGHT0 + dwLightIndex, GL_DIFFUSE, (float *) &(lpLight->dcvDiffuse));
2114 glLightfv(GL_LIGHT0 + dwLightIndex, GL_SPECULAR, (float *) &(lpLight->dcvSpecular));
2115 position[0] = lpLight->dvPosition.u1.x;
2116 position[1] = lpLight->dvPosition.u2.y;
2117 position[2] = lpLight->dvPosition.u3.z;
2118 position[3] = 1.0;
2119 glLightfv(GL_LIGHT0 + dwLightIndex, GL_POSITION, (float *) position);
2120 glLightfv(GL_LIGHT0 + dwLightIndex, GL_CONSTANT_ATTENUATION, &(lpLight->dvAttenuation0));
2121 glLightfv(GL_LIGHT0 + dwLightIndex, GL_LINEAR_ATTENUATION, &(lpLight->dvAttenuation1));
2122 glLightfv(GL_LIGHT0 + dwLightIndex, GL_QUADRATIC_ATTENUATION, &(lpLight->dvAttenuation2));
2123 glLightfv(GL_LIGHT0 + dwLightIndex, GL_SPOT_CUTOFF, &cut_off);
2124 } break;
2126 case D3DLIGHT_SPOT: {
2127 float direction[4];
2128 float position[4];
2129 float cut_off = 90.0 * (lpLight->dvPhi / M_PI);
2131 glLightfv(GL_LIGHT0 + dwLightIndex, GL_AMBIENT, (float *) &(lpLight->dcvAmbient));
2132 glLightfv(GL_LIGHT0 + dwLightIndex, GL_DIFFUSE, (float *) &(lpLight->dcvDiffuse));
2133 glLightfv(GL_LIGHT0 + dwLightIndex, GL_SPECULAR, (float *) &(lpLight->dcvSpecular));
2135 direction[0] = lpLight->dvDirection.u1.x;
2136 direction[1] = lpLight->dvDirection.u2.y;
2137 direction[2] = lpLight->dvDirection.u3.z;
2138 direction[3] = 0.0;
2139 glLightfv(GL_LIGHT0 + dwLightIndex, GL_SPOT_DIRECTION, (float *) direction);
2140 position[0] = lpLight->dvPosition.u1.x;
2141 position[1] = lpLight->dvPosition.u2.y;
2142 position[2] = lpLight->dvPosition.u3.z;
2143 position[3] = 1.0;
2144 glLightfv(GL_LIGHT0 + dwLightIndex, GL_POSITION, (float *) position);
2145 glLightfv(GL_LIGHT0 + dwLightIndex, GL_CONSTANT_ATTENUATION, &(lpLight->dvAttenuation0));
2146 glLightfv(GL_LIGHT0 + dwLightIndex, GL_LINEAR_ATTENUATION, &(lpLight->dvAttenuation1));
2147 glLightfv(GL_LIGHT0 + dwLightIndex, GL_QUADRATIC_ATTENUATION, &(lpLight->dvAttenuation2));
2148 glLightfv(GL_LIGHT0 + dwLightIndex, GL_SPOT_CUTOFF, &cut_off);
2149 glLightfv(GL_LIGHT0 + dwLightIndex, GL_SPOT_EXPONENT, &(lpLight->dvFalloff));
2150 if ((lpLight->dvTheta != 0.0) || (lpLight->dvTheta != lpLight->dvPhi)) {
2151 WARN("dvTheta not fully supported yet !\n");
2153 } break;
2155 default: WARN(" light type not handled yet...\n");
2158 return DD_OK;
2161 HRESULT WINAPI
2162 GL_IDirect3DDeviceImpl_7_LightEnable(LPDIRECT3DDEVICE7 iface,
2163 DWORD dwLightIndex,
2164 BOOL bEnable)
2166 ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice7, iface);
2167 TRACE("(%p/%p)->(%08lx,%d)\n", This, iface, dwLightIndex, bEnable);
2169 if (dwLightIndex > MAX_LIGHTS) return DDERR_INVALIDPARAMS;
2171 if (bEnable) {
2172 if (((0x00000001 << dwLightIndex) & This->set_lights) == 0) {
2173 /* Set the default parameters.. */
2174 TRACE(" setting default light parameters...\n");
2175 GL_IDirect3DDeviceImpl_7_SetLight(iface, dwLightIndex, &(This->light_parameters[dwLightIndex]));
2177 glEnable(GL_LIGHT0 + dwLightIndex);
2178 } else {
2179 glDisable(GL_LIGHT0 + dwLightIndex);
2182 return DD_OK;
2185 HRESULT WINAPI
2186 GL_IDirect3DDeviceImpl_7_SetClipPlane(LPDIRECT3DDEVICE7 iface, DWORD dwIndex, CONST D3DVALUE* pPlaneEquation)
2188 ICOM_THIS(IDirect3DDeviceImpl,iface);
2189 GLdouble plane[4];
2191 TRACE("(%p)->(%ld,%p)\n", This, dwIndex, pPlaneEquation);
2193 if (dwIndex>=This->max_clipping_planes) {
2194 return DDERR_INVALIDPARAMS;
2197 TRACE(" clip plane %ld : %f %f %f %f\n", dwIndex, pPlaneEquation[0], pPlaneEquation[1], pPlaneEquation[2], pPlaneEquation[3] );
2199 memcpy( This->clipping_planes[dwIndex].plane, pPlaneEquation, sizeof(D3DVALUE[4]));
2200 plane[0] = pPlaneEquation[0];
2201 plane[1] = pPlaneEquation[1];
2202 plane[2] = pPlaneEquation[2];
2203 plane[3] = pPlaneEquation[3];
2205 /* XXX: is here also code needed to handle the transformation of the world? */
2206 glClipPlane( GL_CLIP_PLANE0+dwIndex, (const GLdouble*)(&plane) );
2208 return D3D_OK;
2211 #if !defined(__STRICT_ANSI__) && defined(__GNUC__)
2212 # define XCAST(fun) (typeof(VTABLE_IDirect3DDevice7.fun))
2213 #else
2214 # define XCAST(fun) (void*)
2215 #endif
2217 ICOM_VTABLE(IDirect3DDevice7) VTABLE_IDirect3DDevice7 =
2219 ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
2220 XCAST(QueryInterface) Main_IDirect3DDeviceImpl_7_3T_2T_1T_QueryInterface,
2221 XCAST(AddRef) Main_IDirect3DDeviceImpl_7_3T_2T_1T_AddRef,
2222 XCAST(Release) GL_IDirect3DDeviceImpl_7_3T_2T_1T_Release,
2223 XCAST(GetCaps) GL_IDirect3DDeviceImpl_7_GetCaps,
2224 XCAST(EnumTextureFormats) GL_IDirect3DDeviceImpl_7_3T_EnumTextureFormats,
2225 XCAST(BeginScene) Main_IDirect3DDeviceImpl_7_3T_2T_1T_BeginScene,
2226 XCAST(EndScene) Main_IDirect3DDeviceImpl_7_3T_2T_1T_EndScene,
2227 XCAST(GetDirect3D) Main_IDirect3DDeviceImpl_7_3T_2T_1T_GetDirect3D,
2228 XCAST(SetRenderTarget) Main_IDirect3DDeviceImpl_7_3T_2T_SetRenderTarget,
2229 XCAST(GetRenderTarget) Main_IDirect3DDeviceImpl_7_3T_2T_GetRenderTarget,
2230 XCAST(Clear) Main_IDirect3DDeviceImpl_7_Clear,
2231 XCAST(SetTransform) Main_IDirect3DDeviceImpl_7_3T_2T_SetTransform,
2232 XCAST(GetTransform) Main_IDirect3DDeviceImpl_7_3T_2T_GetTransform,
2233 XCAST(SetViewport) Main_IDirect3DDeviceImpl_7_SetViewport,
2234 XCAST(MultiplyTransform) Main_IDirect3DDeviceImpl_7_3T_2T_MultiplyTransform,
2235 XCAST(GetViewport) Main_IDirect3DDeviceImpl_7_GetViewport,
2236 XCAST(SetMaterial) GL_IDirect3DDeviceImpl_7_SetMaterial,
2237 XCAST(GetMaterial) Main_IDirect3DDeviceImpl_7_GetMaterial,
2238 XCAST(SetLight) GL_IDirect3DDeviceImpl_7_SetLight,
2239 XCAST(GetLight) Main_IDirect3DDeviceImpl_7_GetLight,
2240 XCAST(SetRenderState) GL_IDirect3DDeviceImpl_7_3T_2T_SetRenderState,
2241 XCAST(GetRenderState) GL_IDirect3DDeviceImpl_7_3T_2T_GetRenderState,
2242 XCAST(BeginStateBlock) Main_IDirect3DDeviceImpl_7_BeginStateBlock,
2243 XCAST(EndStateBlock) Main_IDirect3DDeviceImpl_7_EndStateBlock,
2244 XCAST(PreLoad) Main_IDirect3DDeviceImpl_7_PreLoad,
2245 XCAST(DrawPrimitive) GL_IDirect3DDeviceImpl_7_3T_DrawPrimitive,
2246 XCAST(DrawIndexedPrimitive) GL_IDirect3DDeviceImpl_7_3T_DrawIndexedPrimitive,
2247 XCAST(SetClipStatus) Main_IDirect3DDeviceImpl_7_3T_2T_SetClipStatus,
2248 XCAST(GetClipStatus) Main_IDirect3DDeviceImpl_7_3T_2T_GetClipStatus,
2249 XCAST(DrawPrimitiveStrided) GL_IDirect3DDeviceImpl_7_3T_DrawPrimitiveStrided,
2250 XCAST(DrawIndexedPrimitiveStrided) GL_IDirect3DDeviceImpl_7_3T_DrawIndexedPrimitiveStrided,
2251 XCAST(DrawPrimitiveVB) GL_IDirect3DDeviceImpl_7_3T_DrawPrimitiveVB,
2252 XCAST(DrawIndexedPrimitiveVB) GL_IDirect3DDeviceImpl_7_3T_DrawIndexedPrimitiveVB,
2253 XCAST(ComputeSphereVisibility) Main_IDirect3DDeviceImpl_7_3T_ComputeSphereVisibility,
2254 XCAST(GetTexture) Main_IDirect3DDeviceImpl_7_3T_GetTexture,
2255 XCAST(SetTexture) GL_IDirect3DDeviceImpl_7_3T_SetTexture,
2256 XCAST(GetTextureStageState) Main_IDirect3DDeviceImpl_7_3T_GetTextureStageState,
2257 XCAST(SetTextureStageState) GL_IDirect3DDeviceImpl_7_3T_SetTextureStageState,
2258 XCAST(ValidateDevice) Main_IDirect3DDeviceImpl_7_3T_ValidateDevice,
2259 XCAST(ApplyStateBlock) Main_IDirect3DDeviceImpl_7_ApplyStateBlock,
2260 XCAST(CaptureStateBlock) Main_IDirect3DDeviceImpl_7_CaptureStateBlock,
2261 XCAST(DeleteStateBlock) Main_IDirect3DDeviceImpl_7_DeleteStateBlock,
2262 XCAST(CreateStateBlock) Main_IDirect3DDeviceImpl_7_CreateStateBlock,
2263 XCAST(Load) Main_IDirect3DDeviceImpl_7_Load,
2264 XCAST(LightEnable) GL_IDirect3DDeviceImpl_7_LightEnable,
2265 XCAST(GetLightEnable) Main_IDirect3DDeviceImpl_7_GetLightEnable,
2266 XCAST(SetClipPlane) GL_IDirect3DDeviceImpl_7_SetClipPlane,
2267 XCAST(GetClipPlane) Main_IDirect3DDeviceImpl_7_GetClipPlane,
2268 XCAST(GetInfo) Main_IDirect3DDeviceImpl_7_GetInfo,
2271 #if !defined(__STRICT_ANSI__) && defined(__GNUC__)
2272 #undef XCAST
2273 #endif
2276 #if !defined(__STRICT_ANSI__) && defined(__GNUC__)
2277 # define XCAST(fun) (typeof(VTABLE_IDirect3DDevice3.fun))
2278 #else
2279 # define XCAST(fun) (void*)
2280 #endif
2282 ICOM_VTABLE(IDirect3DDevice3) VTABLE_IDirect3DDevice3 =
2284 ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
2285 XCAST(QueryInterface) Thunk_IDirect3DDeviceImpl_3_QueryInterface,
2286 XCAST(AddRef) Thunk_IDirect3DDeviceImpl_3_AddRef,
2287 XCAST(Release) Thunk_IDirect3DDeviceImpl_3_Release,
2288 XCAST(GetCaps) GL_IDirect3DDeviceImpl_3_2T_1T_GetCaps,
2289 XCAST(GetStats) Main_IDirect3DDeviceImpl_3_2T_1T_GetStats,
2290 XCAST(AddViewport) Main_IDirect3DDeviceImpl_3_2T_1T_AddViewport,
2291 XCAST(DeleteViewport) Main_IDirect3DDeviceImpl_3_2T_1T_DeleteViewport,
2292 XCAST(NextViewport) Main_IDirect3DDeviceImpl_3_2T_1T_NextViewport,
2293 XCAST(EnumTextureFormats) Thunk_IDirect3DDeviceImpl_3_EnumTextureFormats,
2294 XCAST(BeginScene) Thunk_IDirect3DDeviceImpl_3_BeginScene,
2295 XCAST(EndScene) Thunk_IDirect3DDeviceImpl_3_EndScene,
2296 XCAST(GetDirect3D) Thunk_IDirect3DDeviceImpl_3_GetDirect3D,
2297 XCAST(SetCurrentViewport) Main_IDirect3DDeviceImpl_3_2T_SetCurrentViewport,
2298 XCAST(GetCurrentViewport) Main_IDirect3DDeviceImpl_3_2T_GetCurrentViewport,
2299 XCAST(SetRenderTarget) Thunk_IDirect3DDeviceImpl_3_SetRenderTarget,
2300 XCAST(GetRenderTarget) Thunk_IDirect3DDeviceImpl_3_GetRenderTarget,
2301 XCAST(Begin) Main_IDirect3DDeviceImpl_3_Begin,
2302 XCAST(BeginIndexed) Main_IDirect3DDeviceImpl_3_BeginIndexed,
2303 XCAST(Vertex) Main_IDirect3DDeviceImpl_3_2T_Vertex,
2304 XCAST(Index) Main_IDirect3DDeviceImpl_3_2T_Index,
2305 XCAST(End) Main_IDirect3DDeviceImpl_3_2T_End,
2306 XCAST(GetRenderState) Thunk_IDirect3DDeviceImpl_3_GetRenderState,
2307 XCAST(SetRenderState) Thunk_IDirect3DDeviceImpl_3_SetRenderState,
2308 XCAST(GetLightState) Main_IDirect3DDeviceImpl_3_2T_GetLightState,
2309 XCAST(SetLightState) GL_IDirect3DDeviceImpl_3_2T_SetLightState,
2310 XCAST(SetTransform) Thunk_IDirect3DDeviceImpl_3_SetTransform,
2311 XCAST(GetTransform) Thunk_IDirect3DDeviceImpl_3_GetTransform,
2312 XCAST(MultiplyTransform) Thunk_IDirect3DDeviceImpl_3_MultiplyTransform,
2313 XCAST(DrawPrimitive) Thunk_IDirect3DDeviceImpl_3_DrawPrimitive,
2314 XCAST(DrawIndexedPrimitive) Thunk_IDirect3DDeviceImpl_3_DrawIndexedPrimitive,
2315 XCAST(SetClipStatus) Thunk_IDirect3DDeviceImpl_3_SetClipStatus,
2316 XCAST(GetClipStatus) Thunk_IDirect3DDeviceImpl_3_GetClipStatus,
2317 XCAST(DrawPrimitiveStrided) Thunk_IDirect3DDeviceImpl_3_DrawPrimitiveStrided,
2318 XCAST(DrawIndexedPrimitiveStrided) Thunk_IDirect3DDeviceImpl_3_DrawIndexedPrimitiveStrided,
2319 XCAST(DrawPrimitiveVB) Thunk_IDirect3DDeviceImpl_3_DrawPrimitiveVB,
2320 XCAST(DrawIndexedPrimitiveVB) Thunk_IDirect3DDeviceImpl_3_DrawIndexedPrimitiveVB,
2321 XCAST(ComputeSphereVisibility) Thunk_IDirect3DDeviceImpl_3_ComputeSphereVisibility,
2322 XCAST(GetTexture) Thunk_IDirect3DDeviceImpl_3_GetTexture,
2323 XCAST(SetTexture) Thunk_IDirect3DDeviceImpl_3_SetTexture,
2324 XCAST(GetTextureStageState) Thunk_IDirect3DDeviceImpl_3_GetTextureStageState,
2325 XCAST(SetTextureStageState) Thunk_IDirect3DDeviceImpl_3_SetTextureStageState,
2326 XCAST(ValidateDevice) Thunk_IDirect3DDeviceImpl_3_ValidateDevice,
2329 #if !defined(__STRICT_ANSI__) && defined(__GNUC__)
2330 #undef XCAST
2331 #endif
2334 #if !defined(__STRICT_ANSI__) && defined(__GNUC__)
2335 # define XCAST(fun) (typeof(VTABLE_IDirect3DDevice2.fun))
2336 #else
2337 # define XCAST(fun) (void*)
2338 #endif
2340 ICOM_VTABLE(IDirect3DDevice2) VTABLE_IDirect3DDevice2 =
2342 ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
2343 XCAST(QueryInterface) Thunk_IDirect3DDeviceImpl_2_QueryInterface,
2344 XCAST(AddRef) Thunk_IDirect3DDeviceImpl_2_AddRef,
2345 XCAST(Release) Thunk_IDirect3DDeviceImpl_2_Release,
2346 XCAST(GetCaps) Thunk_IDirect3DDeviceImpl_2_GetCaps,
2347 XCAST(SwapTextureHandles) Main_IDirect3DDeviceImpl_2_1T_SwapTextureHandles,
2348 XCAST(GetStats) Thunk_IDirect3DDeviceImpl_2_GetStats,
2349 XCAST(AddViewport) Thunk_IDirect3DDeviceImpl_2_AddViewport,
2350 XCAST(DeleteViewport) Thunk_IDirect3DDeviceImpl_2_DeleteViewport,
2351 XCAST(NextViewport) Thunk_IDirect3DDeviceImpl_2_NextViewport,
2352 XCAST(EnumTextureFormats) GL_IDirect3DDeviceImpl_2_1T_EnumTextureFormats,
2353 XCAST(BeginScene) Thunk_IDirect3DDeviceImpl_2_BeginScene,
2354 XCAST(EndScene) Thunk_IDirect3DDeviceImpl_2_EndScene,
2355 XCAST(GetDirect3D) Thunk_IDirect3DDeviceImpl_2_GetDirect3D,
2356 XCAST(SetCurrentViewport) Thunk_IDirect3DDeviceImpl_2_SetCurrentViewport,
2357 XCAST(GetCurrentViewport) Thunk_IDirect3DDeviceImpl_2_GetCurrentViewport,
2358 XCAST(SetRenderTarget) Thunk_IDirect3DDeviceImpl_2_SetRenderTarget,
2359 XCAST(GetRenderTarget) Thunk_IDirect3DDeviceImpl_2_GetRenderTarget,
2360 XCAST(Begin) Main_IDirect3DDeviceImpl_2_Begin,
2361 XCAST(BeginIndexed) Main_IDirect3DDeviceImpl_2_BeginIndexed,
2362 XCAST(Vertex) Thunk_IDirect3DDeviceImpl_2_Vertex,
2363 XCAST(Index) Thunk_IDirect3DDeviceImpl_2_Index,
2364 XCAST(End) Thunk_IDirect3DDeviceImpl_2_End,
2365 XCAST(GetRenderState) Thunk_IDirect3DDeviceImpl_2_GetRenderState,
2366 XCAST(SetRenderState) Thunk_IDirect3DDeviceImpl_2_SetRenderState,
2367 XCAST(GetLightState) Thunk_IDirect3DDeviceImpl_2_GetLightState,
2368 XCAST(SetLightState) Thunk_IDirect3DDeviceImpl_2_SetLightState,
2369 XCAST(SetTransform) Thunk_IDirect3DDeviceImpl_2_SetTransform,
2370 XCAST(GetTransform) Thunk_IDirect3DDeviceImpl_2_GetTransform,
2371 XCAST(MultiplyTransform) Thunk_IDirect3DDeviceImpl_2_MultiplyTransform,
2372 XCAST(DrawPrimitive) GL_IDirect3DDeviceImpl_2_DrawPrimitive,
2373 XCAST(DrawIndexedPrimitive) GL_IDirect3DDeviceImpl_2_DrawIndexedPrimitive,
2374 XCAST(SetClipStatus) Thunk_IDirect3DDeviceImpl_2_SetClipStatus,
2375 XCAST(GetClipStatus) Thunk_IDirect3DDeviceImpl_2_GetClipStatus,
2378 #if !defined(__STRICT_ANSI__) && defined(__GNUC__)
2379 #undef XCAST
2380 #endif
2383 #if !defined(__STRICT_ANSI__) && defined(__GNUC__)
2384 # define XCAST(fun) (typeof(VTABLE_IDirect3DDevice.fun))
2385 #else
2386 # define XCAST(fun) (void*)
2387 #endif
2389 ICOM_VTABLE(IDirect3DDevice) VTABLE_IDirect3DDevice =
2391 ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
2392 XCAST(QueryInterface) Thunk_IDirect3DDeviceImpl_1_QueryInterface,
2393 XCAST(AddRef) Thunk_IDirect3DDeviceImpl_1_AddRef,
2394 XCAST(Release) Thunk_IDirect3DDeviceImpl_1_Release,
2395 XCAST(Initialize) Main_IDirect3DDeviceImpl_1_Initialize,
2396 XCAST(GetCaps) Thunk_IDirect3DDeviceImpl_1_GetCaps,
2397 XCAST(SwapTextureHandles) Thunk_IDirect3DDeviceImpl_1_SwapTextureHandles,
2398 XCAST(CreateExecuteBuffer) GL_IDirect3DDeviceImpl_1_CreateExecuteBuffer,
2399 XCAST(GetStats) Thunk_IDirect3DDeviceImpl_1_GetStats,
2400 XCAST(Execute) Main_IDirect3DDeviceImpl_1_Execute,
2401 XCAST(AddViewport) Thunk_IDirect3DDeviceImpl_1_AddViewport,
2402 XCAST(DeleteViewport) Thunk_IDirect3DDeviceImpl_1_DeleteViewport,
2403 XCAST(NextViewport) Thunk_IDirect3DDeviceImpl_1_NextViewport,
2404 XCAST(Pick) Main_IDirect3DDeviceImpl_1_Pick,
2405 XCAST(GetPickRecords) Main_IDirect3DDeviceImpl_1_GetPickRecords,
2406 XCAST(EnumTextureFormats) Thunk_IDirect3DDeviceImpl_1_EnumTextureFormats,
2407 XCAST(CreateMatrix) Main_IDirect3DDeviceImpl_1_CreateMatrix,
2408 XCAST(SetMatrix) Main_IDirect3DDeviceImpl_1_SetMatrix,
2409 XCAST(GetMatrix) Main_IDirect3DDeviceImpl_1_GetMatrix,
2410 XCAST(DeleteMatrix) Main_IDirect3DDeviceImpl_1_DeleteMatrix,
2411 XCAST(BeginScene) Thunk_IDirect3DDeviceImpl_1_BeginScene,
2412 XCAST(EndScene) Thunk_IDirect3DDeviceImpl_1_EndScene,
2413 XCAST(GetDirect3D) Thunk_IDirect3DDeviceImpl_1_GetDirect3D,
2416 #if !defined(__STRICT_ANSI__) && defined(__GNUC__)
2417 #undef XCAST
2418 #endif
2420 static HRESULT d3ddevice_clear(IDirect3DDeviceImpl *This,
2421 DWORD dwCount,
2422 LPD3DRECT lpRects,
2423 DWORD dwFlags,
2424 DWORD dwColor,
2425 D3DVALUE dvZ,
2426 DWORD dwStencil)
2428 GLboolean ztest;
2429 GLfloat old_z_clear_value;
2430 GLbitfield bitfield = 0;
2431 GLint old_stencil_clear_value;
2432 GLfloat old_color_clear_value[4];
2434 TRACE("(%p)->(%08lx,%p,%08lx,%08lx,%f,%08lx)\n", This, dwCount, lpRects, dwFlags, dwColor, dvZ, dwStencil);
2435 if (TRACE_ON(ddraw)) {
2436 if (dwCount > 0) {
2437 int i;
2438 TRACE(" rectangles : \n");
2439 for (i = 0; i < dwCount; i++) {
2440 TRACE(" - %ld x %ld %ld x %ld\n", lpRects[i].u1.x1, lpRects[i].u2.y1, lpRects[i].u3.x2, lpRects[i].u4.y2);
2445 if (dwCount > 1) {
2446 WARN(" Warning, this function only for now clears the whole screen...\n");
2449 /* Clears the screen */
2450 ENTER_GL();
2451 if (dwFlags & D3DCLEAR_ZBUFFER) {
2452 bitfield |= GL_DEPTH_BUFFER_BIT;
2453 glGetBooleanv(GL_DEPTH_WRITEMASK, &ztest);
2454 glDepthMask(GL_TRUE); /* Enables Z writing to be sure to delete also the Z buffer */
2455 glGetFloatv(GL_DEPTH_CLEAR_VALUE, &old_z_clear_value);
2456 glClearDepth(dvZ);
2457 TRACE(" depth value : %f\n", dvZ);
2459 if (dwFlags & D3DCLEAR_STENCIL) {
2460 bitfield |= GL_STENCIL_BUFFER_BIT;
2461 glGetIntegerv(GL_STENCIL_CLEAR_VALUE, &old_stencil_clear_value);
2462 glClearStencil(dwStencil);
2463 TRACE(" stencil value : %ld\n", dwStencil);
2465 if (dwFlags & D3DCLEAR_TARGET) {
2466 bitfield |= GL_COLOR_BUFFER_BIT;
2467 glGetFloatv(GL_COLOR_CLEAR_VALUE, old_color_clear_value);
2468 glClearColor(((dwColor >> 16) & 0xFF) / 255.0,
2469 ((dwColor >> 8) & 0xFF) / 255.0,
2470 ((dwColor >> 0) & 0xFF) / 255.0,
2471 ((dwColor >> 24) & 0xFF) / 255.0);
2472 TRACE(" color value (ARGB) : %08lx\n", dwColor);
2475 glClear(bitfield);
2477 if (dwFlags & D3DCLEAR_ZBUFFER) {
2478 glDepthMask(ztest);
2479 glClearDepth(old_z_clear_value);
2481 if (dwFlags & D3DCLEAR_STENCIL) {
2482 bitfield |= GL_STENCIL_BUFFER_BIT;
2483 glClearStencil(old_stencil_clear_value);
2485 if (dwFlags & D3DCLEAR_TARGET) {
2486 bitfield |= GL_COLOR_BUFFER_BIT;
2487 glClearColor(old_color_clear_value[0],
2488 old_color_clear_value[1],
2489 old_color_clear_value[2],
2490 old_color_clear_value[3]);
2493 LEAVE_GL();
2495 return DD_OK;
2498 HRESULT
2499 d3ddevice_blt(IDirectDrawSurfaceImpl *This, LPRECT rdst,
2500 LPDIRECTDRAWSURFACE7 src, LPRECT rsrc,
2501 DWORD dwFlags, LPDDBLTFX lpbltfx)
2503 if (dwFlags & DDBLT_COLORFILL) {
2504 /* This is easy to handle for the D3D Device... */
2505 DWORD color = lpbltfx->u5.dwFillColor;
2506 TRACE(" executing D3D Device override.\n");
2507 d3ddevice_clear(This->d3ddevice, 0, NULL, D3DCLEAR_TARGET, color, 0.0, 0x00000000);
2508 return DD_OK;
2510 return DDERR_INVALIDPARAMS;
2513 HRESULT
2514 d3ddevice_bltfast(IDirectDrawSurfaceImpl *This, DWORD dstx,
2515 DWORD dsty, LPDIRECTDRAWSURFACE7 src,
2516 LPRECT rsrc, DWORD trans)
2518 return DDERR_INVALIDPARAMS;
2521 void
2522 d3ddevice_set_ortho(IDirect3DDeviceImpl *This)
2524 GLfloat height, width;
2525 GLfloat trans_mat[16];
2527 width = This->surface->surface_desc.dwWidth;
2528 height = This->surface->surface_desc.dwHeight;
2530 /* The X axis is straighforward.. For the Y axis, we need to convert 'D3D' screen coordinates
2531 to OpenGL screen coordinates (ie the upper left corner is not the same).
2532 For Z, the mystery is what should it be mapped to ? Ie should the resulting range be between
2533 -1.0 and 1.0 (as the X and Y coordinates) or between 0.0 and 1.0 ? */
2534 trans_mat[ 0] = 2.0 / width; trans_mat[ 4] = 0.0; trans_mat[ 8] = 0.0; trans_mat[12] = -1.0;
2535 trans_mat[ 1] = 0.0; trans_mat[ 5] = -2.0 / height; trans_mat[ 9] = 0.0; trans_mat[13] = 1.0;
2536 trans_mat[ 2] = 0.0; trans_mat[ 6] = 0.0; trans_mat[10] = 1.0; trans_mat[14] = -1.0;
2537 trans_mat[ 3] = 0.0; trans_mat[ 7] = 0.0; trans_mat[11] = 0.0; trans_mat[15] = 1.0;
2539 glMatrixMode(GL_MODELVIEW);
2540 glLoadIdentity();
2541 /* See the OpenGL Red Book for an explanation of the following translation (in the OpenGL
2542 Correctness Tips section).
2544 Basically, from what I understood, if the game does not filter the font texture,
2545 as the 'real' pixel will lie at the middle of the two texels, OpenGL may choose the wrong
2546 one and we will have strange artifacts (as the rounding and stuff may give different results
2547 for different pixels, ie sometimes take the left pixel, sometimes the right).
2549 glTranslatef(0.375, 0.375, 0);
2550 glMatrixMode(GL_PROJECTION);
2551 glLoadMatrixf(trans_mat);
2554 void
2555 d3ddevice_set_matrices(IDirect3DDeviceImpl *This, DWORD matrices,
2556 D3DMATRIX *world_mat, D3DMATRIX *view_mat, D3DMATRIX *proj_mat)
2558 if ((matrices & (VIEWMAT_CHANGED|WORLDMAT_CHANGED)) != 0) {
2559 glMatrixMode(GL_MODELVIEW);
2560 glLoadMatrixf((float *) view_mat);
2561 glMultMatrixf((float *) world_mat);
2563 if ((matrices & PROJMAT_CHANGED) != 0) {
2564 glMatrixMode(GL_PROJECTION);
2565 glLoadMatrixf((float *) proj_mat);
2569 void
2570 d3ddevice_matrices_updated(IDirect3DDeviceImpl *This, DWORD matrices)
2572 IDirect3DDeviceGLImpl *glThis = (IDirect3DDeviceGLImpl *) This;
2573 if (glThis->transform_state == GL_TRANSFORM_NORMAL) {
2574 /* This will force an update of the transform state at the next drawing. */
2575 glThis->transform_state = GL_TRANSFORM_NONE;
2579 /* TODO for both these functions :
2580 - change / restore OpenGL parameters for pictures transfers in case they are ever modified
2581 by other OpenGL code in D3D
2582 - handle the case where no 'Begin / EndScene' was done between two locks
2583 - handle the rectangles in the unlock too
2584 - handle pitch correctly...
2586 static void d3ddevice_lock_update(IDirectDrawSurfaceImpl* This, LPCRECT pRect, DWORD dwFlags)
2588 IDirect3DDeviceImpl *d3d_dev = This->d3ddevice;
2589 IDirect3DDeviceGLImpl* gl_d3d_dev = (IDirect3DDeviceGLImpl*) d3d_dev;
2590 BOOLEAN is_front;
2592 if ((This->surface_desc.ddsCaps.dwCaps & (DDSCAPS_FRONTBUFFER|DDSCAPS_PRIMARYSURFACE)) != 0) {
2593 is_front = TRUE;
2594 } else if ((This->surface_desc.ddsCaps.dwCaps & (DDSCAPS_BACKBUFFER)) == (DDSCAPS_BACKBUFFER)) {
2595 is_front = FALSE;
2596 } else {
2597 ERR("Wrong surface type for locking !\n");
2598 return;
2601 /* Try to acquire the device critical section */
2602 EnterCriticalSection(&(d3d_dev->crit));
2604 if (((is_front == TRUE) && (gl_d3d_dev->front_state != SURFACE_MEMORY)) ||
2605 ((is_front == FALSE) && (gl_d3d_dev->state != SURFACE_MEMORY))) {
2606 /* If the surface is already in memory, no need to do anything here... */
2607 GLenum buffer_type;
2608 GLenum prev_read;
2609 RECT loc_rect;
2610 int y;
2611 char *dst;
2613 TRACE(" copying frame buffer to main memory.\n");
2615 /* Note that here we cannot do 'optmizations' about the WriteOnly flag... Indeed, a game
2616 may only write to the device... But when we will blit it back to the screen, we need
2617 also to blit correctly the parts the application did not overwrite... */
2619 ENTER_GL();
2621 glGetIntegerv(GL_READ_BUFFER, &prev_read);
2622 glFlush();
2624 if (is_front == TRUE)
2625 /* Application wants to lock the front buffer */
2626 glReadBuffer(GL_FRONT);
2627 else
2628 /* Application wants to lock the back buffer */
2629 glReadBuffer(GL_BACK);
2631 if (This->surface_desc.u4.ddpfPixelFormat.u1.dwRGBBitCount == 16) {
2632 buffer_type = GL_UNSIGNED_SHORT_5_6_5;
2633 } else {
2634 ERR(" unsupported pixel format at device locking.\n");
2635 LEAVE_GL();
2636 return;
2639 /* Just a hack while waiting for proper rectangle support */
2640 pRect = NULL;
2641 if (pRect == NULL) {
2642 loc_rect.top = 0;
2643 loc_rect.left = 0;
2644 loc_rect.bottom = This->surface_desc.dwHeight;
2645 loc_rect.right = This->surface_desc.dwWidth;
2646 } else {
2647 loc_rect = *pRect;
2650 dst = ((char *)This->surface_desc.lpSurface) +
2651 (loc_rect.top * This->surface_desc.u1.lPitch) + (loc_rect.left * GET_BPP(This->surface_desc));
2652 for (y = (This->surface_desc.dwHeight - loc_rect.top - 1);
2653 y >= ((int) This->surface_desc.dwHeight - (int) loc_rect.bottom);
2654 y--) {
2655 glReadPixels(loc_rect.left, y,
2656 loc_rect.right - loc_rect.left, 1,
2657 GL_RGB, buffer_type, dst);
2658 dst += This->surface_desc.u1.lPitch;
2661 glReadBuffer(prev_read);
2663 if (is_front)
2664 gl_d3d_dev->front_state = SURFACE_MEMORY;
2665 else
2666 gl_d3d_dev->state = SURFACE_MEMORY;
2668 LEAVE_GL();
2672 #define UNLOCK_TEX_SIZE 256
2674 static void d3ddevice_flush_to_frame_buffer(IDirect3DDeviceImpl *d3d_dev, LPCRECT pRect) {
2675 GLenum buffer_type;
2676 RECT loc_rect;
2677 IDirectDrawSurfaceImpl *surf = d3d_dev->surface;
2678 IDirect3DDeviceGLImpl* gl_d3d_dev = (IDirect3DDeviceGLImpl*) d3d_dev;
2679 GLint depth_test, alpha_test, cull_face, lighting, min_tex, max_tex, tex_env;
2680 GLuint initial_texture;
2681 GLint tex_state;
2682 int x, y;
2684 loc_rect.top = 0;
2685 loc_rect.left = 0;
2686 loc_rect.bottom = surf->surface_desc.dwHeight;
2687 loc_rect.right = surf->surface_desc.dwWidth;
2689 TRACE(" flushing memory back to the frame-buffer.\n");
2691 glGetIntegerv(GL_DEPTH_TEST, &depth_test);
2692 glGetIntegerv(GL_ALPHA_TEST, &alpha_test);
2693 glGetIntegerv(GL_CULL_FACE, &cull_face);
2694 glGetIntegerv(GL_LIGHTING, &lighting);
2695 glGetIntegerv(GL_TEXTURE_BINDING_2D, &initial_texture);
2696 glGetIntegerv(GL_TEXTURE_2D, &tex_state);
2697 glGetTexParameteriv(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, &max_tex);
2698 glGetTexParameteriv(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, &min_tex);
2699 glGetTexEnviv(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, &tex_env);
2700 /* TODO: scissor test if ever we use it ! */
2702 if (surf->surface_desc.u4.ddpfPixelFormat.u1.dwRGBBitCount == 16) {
2703 buffer_type = GL_UNSIGNED_SHORT_5_6_5;
2704 } else {
2705 WARN(" unsupported pixel format.\n");
2706 return;
2709 gl_d3d_dev->transform_state = GL_TRANSFORM_ORTHO;
2710 d3ddevice_set_ortho(d3d_dev);
2712 glDisable(GL_DEPTH_TEST);
2713 glEnable(GL_TEXTURE_2D);
2714 glEnable(GL_SCISSOR_TEST);
2715 glScissor(loc_rect.left, surf->surface_desc.dwHeight - loc_rect.bottom,
2716 loc_rect.right - loc_rect.left, loc_rect.bottom - loc_rect.top);
2718 if (gl_d3d_dev->unlock_tex == 0) {
2719 glGenTextures(1, &gl_d3d_dev->unlock_tex);
2720 glBindTexture(GL_TEXTURE_2D, gl_d3d_dev->unlock_tex);
2721 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB,
2722 UNLOCK_TEX_SIZE, UNLOCK_TEX_SIZE, 0,
2723 GL_RGB, buffer_type, NULL);
2724 } else {
2725 glBindTexture(GL_TEXTURE_2D, gl_d3d_dev->unlock_tex);
2727 glPixelStorei(GL_UNPACK_ROW_LENGTH, surf->surface_desc.dwWidth);
2729 glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);
2730 glDisable(GL_LIGHTING);
2731 glDisable(GL_CULL_FACE);
2732 glDisable(GL_ALPHA_TEST);
2733 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
2734 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
2736 for (x = loc_rect.left; x < loc_rect.right; x += UNLOCK_TEX_SIZE) {
2737 for (y = loc_rect.top; y < loc_rect.bottom; y += UNLOCK_TEX_SIZE) {
2738 /* First, upload the texture... */
2739 int w = (x + UNLOCK_TEX_SIZE > surf->surface_desc.dwWidth) ? (surf->surface_desc.dwWidth - x) : UNLOCK_TEX_SIZE;
2740 int h = (y + UNLOCK_TEX_SIZE > surf->surface_desc.dwHeight) ? (surf->surface_desc.dwHeight - y) : UNLOCK_TEX_SIZE;
2741 glTexSubImage2D(GL_TEXTURE_2D,
2743 0, 0,
2744 w, h,
2745 GL_RGB,
2746 buffer_type,
2747 ((char *) surf->surface_desc.lpSurface) + (x * GET_BPP(surf->surface_desc)) + (y * surf->surface_desc.u1.lPitch));
2748 glBegin(GL_QUADS);
2749 glColor3ub(0xFF, 0xFF, 0xFF);
2750 glTexCoord2f(0.0, 0.0);
2751 glVertex3d(x, y, 0.5);
2752 glTexCoord2f(1.0, 0.0);
2753 glVertex3d(x + UNLOCK_TEX_SIZE, y, 0.5);
2754 glTexCoord2f(1.0, 1.0);
2755 glVertex3d(x + UNLOCK_TEX_SIZE, y + UNLOCK_TEX_SIZE, 0.5);
2756 glTexCoord2f(0.0, 1.0);
2757 glVertex3d(x, y + UNLOCK_TEX_SIZE, 0.5);
2758 glEnd();
2763 /* And restore all the various states modified by this code */
2764 if (depth_test != 0) glEnable(GL_DEPTH_TEST);
2765 if (lighting != 0) glEnable(GL_LIGHTING);
2766 if (alpha_test != 0) glEnable(GL_ALPHA_TEST);
2767 if (cull_face != 0) glEnable(GL_CULL_FACE);
2768 glBindTexture(GL_TEXTURE_2D, initial_texture);
2769 if (tex_state == 0) glDisable(GL_TEXTURE_2D);
2770 glDisable(GL_SCISSOR_TEST);
2771 glPixelStorei(GL_UNPACK_ROW_LENGTH, 0);
2772 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, max_tex);
2773 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, min_tex);
2774 glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, tex_env);
2777 static void d3ddevice_unlock_update(IDirectDrawSurfaceImpl* This, LPCRECT pRect)
2779 BOOLEAN is_front;
2780 IDirect3DDeviceImpl *d3d_dev = This->d3ddevice;
2782 if ((This->surface_desc.ddsCaps.dwCaps & (DDSCAPS_FRONTBUFFER|DDSCAPS_PRIMARYSURFACE)) != 0) {
2783 is_front = TRUE;
2784 } else if ((This->surface_desc.ddsCaps.dwCaps & (DDSCAPS_BACKBUFFER)) == (DDSCAPS_BACKBUFFER)) {
2785 is_front = FALSE;
2786 } else {
2787 ERR("Wrong surface type for locking !\n");
2788 return;
2790 /* First, check if we need to do anything. For the backbuffer, flushing is done at the next 3D activity. */
2791 if (((This->lastlocktype & DDLOCK_READONLY) == 0) &&
2792 (is_front == TRUE)) {
2793 GLenum prev_draw;
2794 ENTER_GL();
2795 glGetIntegerv(GL_DRAW_BUFFER, &prev_draw);
2796 glDrawBuffer(GL_FRONT);
2797 d3d_dev->flush_to_framebuffer(d3d_dev, pRect);
2798 glDrawBuffer(prev_draw);
2799 LEAVE_GL();
2802 /* And 'frees' the device critical section */
2803 LeaveCriticalSection(&(d3d_dev->crit));
2806 static void
2807 apply_texture_state(IDirect3DDeviceImpl *This)
2809 int stage, state;
2811 /* Initialize texture stages states */
2812 for (stage = 0; stage < MAX_TEXTURES; stage++) {
2813 for (state = 0; state < HIGHEST_TEXTURE_STAGE_STATE; state += 1) {
2814 if (This->state_block.set_flags.texture_stage_state[stage][state] == TRUE) {
2815 IDirect3DDevice7_SetTextureStageState(ICOM_INTERFACE(This, IDirect3DDevice7),
2816 stage, state + 1, This->state_block.texture_stage_state[stage][state]);
2822 HRESULT
2823 d3ddevice_create(IDirect3DDeviceImpl **obj, IDirect3DImpl *d3d, IDirectDrawSurfaceImpl *surface)
2825 IDirect3DDeviceImpl *object;
2826 IDirect3DDeviceGLImpl *gl_object;
2827 IDirectDrawSurfaceImpl *surf;
2828 HDC device_context;
2829 XVisualInfo *vis;
2830 int num;
2831 XVisualInfo template;
2832 GLenum buffer = GL_FRONT;
2833 int light;
2834 GLint max_clipping_planes = 0;
2836 object = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(IDirect3DDeviceGLImpl));
2837 if (object == NULL) return DDERR_OUTOFMEMORY;
2839 gl_object = (IDirect3DDeviceGLImpl *) object;
2841 object->ref = 1;
2842 object->d3d = d3d;
2843 object->surface = surface;
2844 object->set_context = set_context;
2845 object->clear = d3ddevice_clear;
2846 object->set_matrices = d3ddevice_set_matrices;
2847 object->matrices_updated = d3ddevice_matrices_updated;
2848 object->flush_to_framebuffer = d3ddevice_flush_to_frame_buffer;
2850 InitializeCriticalSection(&(object->crit));
2852 TRACE(" creating OpenGL device for surface = %p, d3d = %p\n", surface, d3d);
2854 device_context = GetDC(surface->ddraw_owner->window);
2855 gl_object->display = get_display(device_context);
2856 gl_object->drawable = get_drawable(device_context);
2857 ReleaseDC(surface->ddraw_owner->window,device_context);
2859 ENTER_GL();
2860 template.visualid = (VisualID)GetPropA( GetDesktopWindow(), "__wine_x11_visual_id" );
2861 vis = XGetVisualInfo(gl_object->display, VisualIDMask, &template, &num);
2862 if (vis == NULL) {
2863 HeapFree(GetProcessHeap(), 0, object);
2864 ERR("No visual found !\n");
2865 LEAVE_GL();
2866 return DDERR_INVALIDPARAMS;
2867 } else {
2868 TRACE(" visual found\n");
2871 gl_object->gl_context = glXCreateContext(gl_object->display, vis,
2872 NULL, GL_TRUE);
2874 if (gl_object->gl_context == NULL) {
2875 HeapFree(GetProcessHeap(), 0, object);
2876 ERR("Error in context creation !\n");
2877 LEAVE_GL();
2878 return DDERR_INVALIDPARAMS;
2879 } else {
2880 TRACE(" context created (%p)\n", gl_object->gl_context);
2883 /* Look for the front buffer and override its surface's Flip method (if in double buffering) */
2884 for (surf = surface; surf != NULL; surf = surf->surface_owner) {
2885 if ((surf->surface_desc.ddsCaps.dwCaps&(DDSCAPS_FLIP|DDSCAPS_FRONTBUFFER)) == (DDSCAPS_FLIP|DDSCAPS_FRONTBUFFER)) {
2886 surf->aux_ctx = (LPVOID) object;
2887 surf->aux_data = (LPVOID) gl_object->drawable;
2888 surf->aux_flip = opengl_flip;
2889 buffer = GL_BACK;
2890 break;
2893 /* We are not doing any double buffering.. Then force OpenGL to draw on the front buffer */
2894 if (surf == NULL) {
2895 TRACE(" no double buffering : drawing on the front buffer\n");
2896 buffer = GL_FRONT;
2899 for (surf = surface; surf != NULL; surf = surf->surface_owner) {
2900 IDirectDrawSurfaceImpl *surf2;
2901 for (surf2 = surf; surf2->prev_attached != NULL; surf2 = surf2->prev_attached) ;
2902 for (; surf2 != NULL; surf2 = surf2->next_attached) {
2903 TRACE(" checking surface %p :", surf2);
2904 if (((surf2->surface_desc.ddsCaps.dwCaps & (DDSCAPS_3DDEVICE)) == (DDSCAPS_3DDEVICE)) &&
2905 ((surf2->surface_desc.ddsCaps.dwCaps & (DDSCAPS_ZBUFFER)) != (DDSCAPS_ZBUFFER))) {
2906 /* Override the Lock / Unlock function for all these surfaces */
2907 surf2->lock_update_prev = surf2->lock_update;
2908 surf2->lock_update = d3ddevice_lock_update;
2909 surf2->unlock_update_prev = surf2->unlock_update;
2910 surf2->unlock_update = d3ddevice_unlock_update;
2911 /* And install also the blt / bltfast overrides */
2912 surf2->aux_blt = d3ddevice_blt;
2913 surf2->aux_bltfast = d3ddevice_bltfast;
2915 TRACE(" overiding direct surface access.\n");
2916 } else {
2917 TRACE(" no overide.\n");
2919 surf2->d3ddevice = object;
2923 /* Set the various light parameters */
2924 for (light = 0; light < MAX_LIGHTS; light++) {
2925 /* Only set the fields that are not zero-created */
2926 object->light_parameters[light].dltType = D3DLIGHT_DIRECTIONAL;
2927 object->light_parameters[light].dcvDiffuse.u1.r = 1.0;
2928 object->light_parameters[light].dcvDiffuse.u2.g = 1.0;
2929 object->light_parameters[light].dcvDiffuse.u3.b = 1.0;
2930 object->light_parameters[light].dvDirection.u3.z = 1.0;
2933 /* Allocate memory for the matrices */
2934 object->world_mat = (D3DMATRIX *) HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, 16 * sizeof(float));
2935 object->view_mat = (D3DMATRIX *) HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, 16 * sizeof(float));
2936 object->proj_mat = (D3DMATRIX *) HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, 16 * sizeof(float));
2937 memcpy(object->world_mat, id_mat, 16 * sizeof(float));
2938 memcpy(object->view_mat , id_mat, 16 * sizeof(float));
2939 memcpy(object->proj_mat , id_mat, 16 * sizeof(float));
2941 /* Initialisation */
2942 TRACE(" setting current context\n");
2943 LEAVE_GL();
2944 object->set_context(object);
2945 ENTER_GL();
2946 TRACE(" current context set\n");
2948 /* allocate the clipping planes */
2949 glGetIntegerv(GL_MAX_CLIP_PLANES,&max_clipping_planes);
2950 if (max_clipping_planes>32) {
2951 object->max_clipping_planes=32;
2952 } else {
2953 object->max_clipping_planes = max_clipping_planes;
2955 TRACE(" capable of %d clipping planes\n", (int)object->max_clipping_planes );
2956 object->clipping_planes = (d3d7clippingplane*)HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, object->max_clipping_planes * sizeof(d3d7clippingplane));
2958 glHint(GL_FOG_HINT,GL_NICEST);
2960 glClearColor(0.0, 0.0, 0.0, 0.0);
2961 glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
2962 glDrawBuffer(buffer);
2963 glReadBuffer(buffer);
2964 /* glDisable(GL_DEPTH_TEST); Need here to check for the presence of a ZBuffer and to reenable it when the ZBuffer is attached */
2965 LEAVE_GL();
2967 gl_object->state = SURFACE_GL;
2969 /* fill_device_capabilities(d3d->ddraw); */
2971 ICOM_INIT_INTERFACE(object, IDirect3DDevice, VTABLE_IDirect3DDevice);
2972 ICOM_INIT_INTERFACE(object, IDirect3DDevice2, VTABLE_IDirect3DDevice2);
2973 ICOM_INIT_INTERFACE(object, IDirect3DDevice3, VTABLE_IDirect3DDevice3);
2974 ICOM_INIT_INTERFACE(object, IDirect3DDevice7, VTABLE_IDirect3DDevice7);
2976 *obj = object;
2978 TRACE(" creating implementation at %p.\n", *obj);
2980 /* And finally warn D3D that this device is now present */
2981 object->d3d->added_device(object->d3d, object);
2983 /* FIXME: Should handle other versions than just 7 */
2984 InitDefaultStateBlock(&object->state_block, 7);
2985 /* Apply default render state and texture stage state values */
2986 apply_render_state(object, &object->state_block);
2987 apply_texture_state(object);
2989 /* And fill the fog table with the default fog value */
2990 build_fog_table(gl_object->fog_table, object->state_block.render_state[D3DRENDERSTATE_FOGCOLOR - 1]);
2992 return DD_OK;