2 * Copyright (c) 1998 Lionel ULMER
4 * This file contains the MESA implementation of all the D3D devices that
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
23 #include "wine/port.h"
29 #define NONAMELESSUNION
30 #define NONAMELESSSTRUCT
38 #include "wine/debug.h"
39 #include "wine/library.h"
41 #include "mesa_private.h"
44 WINE_DEFAULT_DEBUG_CHANNEL(ddraw);
45 WINE_DECLARE_DEBUG_CHANNEL(ddraw_geom);
46 WINE_DECLARE_DEBUG_CHANNEL(ddraw_fps);
48 /* x11drv GDI escapes */
49 #define X11DRV_ESCAPE 6789
50 enum x11drv_escape_codes
52 X11DRV_GET_DISPLAY, /* get X11 display for a DC */
53 X11DRV_GET_DRAWABLE, /* get current drawable for a DC */
54 X11DRV_GET_FONT, /* get current X font for a DC */
57 /* They are non-static as they are used by Direct3D in the creation function */
58 const GUID IID_D3DDEVICE_OpenGL = {
62 { 0x82,0x2d,0xa8,0xd5,0x31,0x87,0xca,0xfa }
65 const float id_mat[16] = {
72 /* This is filled at DLL loading time */
73 static D3DDEVICEDESC7 opengl_device_caps;
74 GL_EXTENSIONS_LIST GL_extensions;
76 static void draw_primitive_strided(IDirect3DDeviceImpl *This,
77 D3DPRIMITIVETYPE d3dptPrimitiveType,
78 DWORD d3dvtVertexType,
79 LPD3DDRAWPRIMITIVESTRIDEDDATA lpD3DDrawPrimStrideData,
85 static DWORD draw_primitive_handle_textures(IDirect3DDeviceImpl *This);
87 /* retrieve the X display to use on a given DC */
88 inline static Display *get_display( HDC hdc )
91 enum x11drv_escape_codes escape = X11DRV_GET_DISPLAY;
93 if (!ExtEscape( hdc, X11DRV_ESCAPE, sizeof(escape), (LPCSTR)&escape,
94 sizeof(display), (LPSTR)&display )) display = NULL;
99 #define UNLOCK_TEX_SIZE 256
101 #define DEPTH_RANGE_BIT (0x00000001 << 0)
102 #define VIEWPORT_BIT (0x00000001 << 1)
104 static DWORD d3ddevice_set_state_for_flush(IDirect3DDeviceImpl *d3d_dev, LPCRECT pRect, BOOLEAN use_alpha, BOOLEAN *initial) {
105 IDirect3DDeviceGLImpl* gl_d3d_dev = (IDirect3DDeviceGLImpl*) d3d_dev;
106 DWORD opt_bitmap = 0x00000000;
108 if ((gl_d3d_dev->current_bound_texture[1] != NULL) &&
109 ((d3d_dev->state_block.texture_stage_state[1][D3DTSS_COLOROP - 1] != D3DTOP_DISABLE))) {
110 if (gl_d3d_dev->current_active_tex_unit != GL_TEXTURE1_WINE) {
111 GL_extensions.glActiveTexture(GL_TEXTURE1_WINE);
112 gl_d3d_dev->current_active_tex_unit = GL_TEXTURE1_WINE;
114 /* Disable multi-texturing for level 1 to disable all others */
115 glDisable(GL_TEXTURE_2D);
117 if (gl_d3d_dev->current_active_tex_unit != GL_TEXTURE0_WINE) {
118 GL_extensions.glActiveTexture(GL_TEXTURE0_WINE);
119 gl_d3d_dev->current_active_tex_unit = GL_TEXTURE0_WINE;
121 if ((gl_d3d_dev->current_bound_texture[0] == NULL) ||
122 (d3d_dev->state_block.texture_stage_state[0][D3DTSS_COLOROP - 1] == D3DTOP_DISABLE))
123 glEnable(GL_TEXTURE_2D);
124 if (gl_d3d_dev->unlock_tex == 0) {
125 glGenTextures(1, &gl_d3d_dev->unlock_tex);
126 glBindTexture(GL_TEXTURE_2D, gl_d3d_dev->unlock_tex);
128 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
129 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
130 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP);
131 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP);
133 glBindTexture(GL_TEXTURE_2D, gl_d3d_dev->unlock_tex);
136 if (d3d_dev->tex_mat_is_identity[0] == FALSE) {
137 glMatrixMode(GL_TEXTURE);
141 if (gl_d3d_dev->transform_state != GL_TRANSFORM_ORTHO) {
142 gl_d3d_dev->transform_state = GL_TRANSFORM_ORTHO;
143 d3ddevice_set_ortho(d3d_dev);
146 if (gl_d3d_dev->depth_test != FALSE) glDisable(GL_DEPTH_TEST);
147 glEnable(GL_SCISSOR_TEST);
148 if ((d3d_dev->active_viewport.dvMinZ != 0.0) ||
149 (d3d_dev->active_viewport.dvMaxZ != 1.0)) {
150 glDepthRange(0.0, 1.0);
151 opt_bitmap |= DEPTH_RANGE_BIT;
153 if ((d3d_dev->active_viewport.dwX != 0) ||
154 (d3d_dev->active_viewport.dwY != 0) ||
155 (d3d_dev->active_viewport.dwWidth != d3d_dev->surface->surface_desc.dwWidth) ||
156 (d3d_dev->active_viewport.dwHeight != d3d_dev->surface->surface_desc.dwHeight)) {
157 glViewport(0, 0, d3d_dev->surface->surface_desc.dwWidth, d3d_dev->surface->surface_desc.dwHeight);
158 opt_bitmap |= VIEWPORT_BIT;
160 glScissor(pRect->left, d3d_dev->surface->surface_desc.dwHeight - pRect->bottom,
161 pRect->right - pRect->left, pRect->bottom - pRect->top);
162 if (gl_d3d_dev->lighting != FALSE) glDisable(GL_LIGHTING);
163 if (gl_d3d_dev->cull_face != FALSE) glDisable(GL_CULL_FACE);
165 if (gl_d3d_dev->alpha_test == FALSE) glEnable(GL_ALPHA_TEST);
166 if ((gl_d3d_dev->current_alpha_test_func != GL_NOTEQUAL) || (gl_d3d_dev->current_alpha_test_ref != 0.0))
167 glAlphaFunc(GL_NOTEQUAL, 0.0);
169 if (gl_d3d_dev->alpha_test != FALSE) glDisable(GL_ALPHA_TEST);
171 if (gl_d3d_dev->stencil_test != FALSE) glDisable(GL_STENCIL_TEST);
172 if (gl_d3d_dev->blending != FALSE) glDisable(GL_BLEND);
173 if (gl_d3d_dev->fogging != FALSE) glDisable(GL_FOG);
174 if (gl_d3d_dev->current_tex_env != GL_REPLACE)
175 glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);
180 static void d3ddevice_restore_state_after_flush(IDirect3DDeviceImpl *d3d_dev, DWORD opt_bitmap, BOOLEAN use_alpha) {
181 IDirect3DDeviceGLImpl* gl_d3d_dev = (IDirect3DDeviceGLImpl*) d3d_dev;
183 /* And restore all the various states modified by this code */
184 if (gl_d3d_dev->depth_test != 0) glEnable(GL_DEPTH_TEST);
185 if (gl_d3d_dev->lighting != 0) glEnable(GL_LIGHTING);
186 if ((gl_d3d_dev->alpha_test != 0) && (use_alpha == 0))
187 glEnable(GL_ALPHA_TEST);
188 else if ((gl_d3d_dev->alpha_test == 0) && (use_alpha != 0))
189 glDisable(GL_ALPHA_TEST);
191 if ((gl_d3d_dev->current_alpha_test_func != GL_NOTEQUAL) || (gl_d3d_dev->current_alpha_test_ref != 0.0))
192 glAlphaFunc(gl_d3d_dev->current_alpha_test_func, gl_d3d_dev->current_alpha_test_ref);
194 if (gl_d3d_dev->stencil_test != 0) glEnable(GL_STENCIL_TEST);
195 if (gl_d3d_dev->cull_face != 0) glEnable(GL_CULL_FACE);
196 if (gl_d3d_dev->blending != 0) glEnable(GL_BLEND);
197 if (gl_d3d_dev->fogging != 0) glEnable(GL_FOG);
198 glDisable(GL_SCISSOR_TEST);
199 if (opt_bitmap & DEPTH_RANGE_BIT) {
200 glDepthRange(d3d_dev->active_viewport.dvMinZ, d3d_dev->active_viewport.dvMaxZ);
202 if (opt_bitmap & VIEWPORT_BIT) {
203 glViewport(d3d_dev->active_viewport.dwX,
204 d3d_dev->surface->surface_desc.dwHeight - (d3d_dev->active_viewport.dwHeight + d3d_dev->active_viewport.dwY),
205 d3d_dev->active_viewport.dwWidth, d3d_dev->active_viewport.dwHeight);
207 if (d3d_dev->tex_mat_is_identity[0] == FALSE) {
208 d3d_dev->matrices_updated(d3d_dev, TEXMAT0_CHANGED);
211 if (gl_d3d_dev->current_active_tex_unit != GL_TEXTURE0_WINE) {
212 GL_extensions.glActiveTexture(GL_TEXTURE0_WINE);
213 gl_d3d_dev->current_active_tex_unit = GL_TEXTURE0_WINE;
215 glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, gl_d3d_dev->current_tex_env);
216 /* Note that here we could directly re-bind the previous texture... But it would in some case be a spurious
217 bind if ever the game changes the texture just after.
219 So choose 0x00000001 to postpone the binding to the next time we draw something on screen. */
220 gl_d3d_dev->current_bound_texture[0] = (IDirectDrawSurfaceImpl *) 0x00000001;
221 if (d3d_dev->state_block.texture_stage_state[0][D3DTSS_COLOROP - 1] == D3DTOP_DISABLE) glDisable(GL_TEXTURE_2D);
223 /* And re-enabled if needed texture level 1 */
224 if ((gl_d3d_dev->current_bound_texture[1] != NULL) &&
225 (d3d_dev->state_block.texture_stage_state[1][D3DTSS_COLOROP - 1] != D3DTOP_DISABLE)) {
226 if (gl_d3d_dev->current_active_tex_unit != GL_TEXTURE1_WINE) {
227 GL_extensions.glActiveTexture(GL_TEXTURE1_WINE);
228 gl_d3d_dev->current_active_tex_unit = GL_TEXTURE1_WINE;
230 glEnable(GL_TEXTURE_2D);
234 /* retrieve the X drawable to use on a given DC */
235 inline static Drawable get_drawable( HDC hdc )
238 enum x11drv_escape_codes escape = X11DRV_GET_DRAWABLE;
240 if (!ExtEscape( hdc, X11DRV_ESCAPE, sizeof(escape), (LPCSTR)&escape,
241 sizeof(drawable), (LPSTR)&drawable )) drawable = 0;
246 /* This is unnecessarely complicated :-) */
247 #define MEASUREMENT_WINDOW 5
248 #define NUMBER_OF_WINDOWS 10
250 static LONGLONG perf_freq;
251 static LONGLONG perf_storage[NUMBER_OF_WINDOWS];
252 static LONGLONG prev_time = 0;
253 static unsigned int current_window;
254 static unsigned int measurements_in_window;
255 static unsigned int valid_windows;
257 static BOOL opengl_flip( LPVOID dev, LPVOID drawable)
259 IDirect3DDeviceImpl *d3d_dev = (IDirect3DDeviceImpl *) dev;
260 IDirect3DDeviceGLImpl *gl_d3d_dev = (IDirect3DDeviceGLImpl *) dev;
262 TRACE("(%p, %ld)\n", gl_d3d_dev->display,(Drawable)drawable);
264 if (gl_d3d_dev->state[WINE_GL_BUFFER_BACK] == SURFACE_MEMORY_DIRTY) {
265 d3d_dev->flush_to_framebuffer(d3d_dev, &(gl_d3d_dev->lock_rect[WINE_GL_BUFFER_BACK]), gl_d3d_dev->lock_surf[WINE_GL_BUFFER_BACK]);
267 gl_d3d_dev->state[WINE_GL_BUFFER_BACK] = SURFACE_GL;
268 gl_d3d_dev->state[WINE_GL_BUFFER_FRONT] = SURFACE_GL;
269 glXSwapBuffers(gl_d3d_dev->display, (Drawable)drawable);
272 if (TRACE_ON(ddraw_fps)) {
273 LONGLONG current_time;
274 LONGLONG frame_duration;
275 QueryPerformanceCounter((LARGE_INTEGER *) ¤t_time);
277 if (prev_time != 0) {
278 LONGLONG total_time = 0;
281 frame_duration = current_time - prev_time;
282 prev_time = current_time;
284 perf_storage[current_window] += frame_duration;
285 measurements_in_window++;
287 if (measurements_in_window >= MEASUREMENT_WINDOW) {
291 if (valid_windows < NUMBER_OF_WINDOWS) {
293 tot_meas = valid_windows * MEASUREMENT_WINDOW;
294 for (i = 0; i < valid_windows; i++) {
295 total_time += perf_storage[i];
299 tot_meas = NUMBER_OF_WINDOWS * MEASUREMENT_WINDOW;
300 for (i = 0; i < NUMBER_OF_WINDOWS; i++) {
301 total_time += perf_storage[i];
305 TRACE_(ddraw_fps)(" %9.5f\n", (double) (perf_freq * tot_meas) / (double) total_time);
307 if (current_window >= NUMBER_OF_WINDOWS) {
310 perf_storage[current_window] = 0;
311 measurements_in_window = 0;
314 prev_time = current_time;
315 memset(perf_storage, 0, sizeof(perf_storage));
318 measurements_in_window = 0;
319 QueryPerformanceFrequency((LARGE_INTEGER *) &perf_freq);
327 /*******************************************************************************
328 * OpenGL static functions
330 static void set_context(IDirect3DDeviceImpl* This)
332 IDirect3DDeviceGLImpl* glThis = (IDirect3DDeviceGLImpl*) This;
334 TRACE("glxMakeCurrent %p, %ld, %p\n",glThis->display,glThis->drawable, glThis->gl_context);
336 if (glXMakeCurrent(glThis->display, glThis->drawable, glThis->gl_context) == False) {
337 ERR("Error in setting current context (context %p drawable %ld)!\n",
338 glThis->gl_context, glThis->drawable);
343 static void fill_opengl_caps(D3DDEVICEDESC *d1)
345 d1->dwSize = sizeof(*d1);
346 d1->dwFlags = D3DDD_COLORMODEL | D3DDD_DEVCAPS | D3DDD_TRANSFORMCAPS | D3DDD_BCLIPPING | D3DDD_LIGHTINGCAPS |
347 D3DDD_LINECAPS | D3DDD_TRICAPS | D3DDD_DEVICERENDERBITDEPTH | D3DDD_DEVICEZBUFFERBITDEPTH |
348 D3DDD_MAXBUFFERSIZE | D3DDD_MAXVERTEXCOUNT;
349 d1->dcmColorModel = D3DCOLOR_RGB;
350 d1->dwDevCaps = opengl_device_caps.dwDevCaps;
351 d1->dtcTransformCaps.dwSize = sizeof(D3DTRANSFORMCAPS);
352 d1->dtcTransformCaps.dwCaps = D3DTRANSFORMCAPS_CLIP;
353 d1->bClipping = TRUE;
354 d1->dlcLightingCaps.dwSize = sizeof(D3DLIGHTINGCAPS);
355 d1->dlcLightingCaps.dwCaps = D3DLIGHTCAPS_DIRECTIONAL | D3DLIGHTCAPS_PARALLELPOINT | D3DLIGHTCAPS_POINT | D3DLIGHTCAPS_SPOT;
356 d1->dlcLightingCaps.dwLightingModel = D3DLIGHTINGMODEL_RGB;
357 d1->dlcLightingCaps.dwNumLights = opengl_device_caps.dwMaxActiveLights;
358 d1->dpcLineCaps = opengl_device_caps.dpcLineCaps;
359 d1->dpcTriCaps = opengl_device_caps.dpcTriCaps;
360 d1->dwDeviceRenderBitDepth = opengl_device_caps.dwDeviceRenderBitDepth;
361 d1->dwDeviceZBufferBitDepth = opengl_device_caps.dwDeviceZBufferBitDepth;
362 d1->dwMaxBufferSize = 0;
363 d1->dwMaxVertexCount = 65536;
364 d1->dwMinTextureWidth = opengl_device_caps.dwMinTextureWidth;
365 d1->dwMinTextureHeight = opengl_device_caps.dwMinTextureHeight;
366 d1->dwMaxTextureWidth = opengl_device_caps.dwMaxTextureWidth;
367 d1->dwMaxTextureHeight = opengl_device_caps.dwMaxTextureHeight;
368 d1->dwMinStippleWidth = 1;
369 d1->dwMinStippleHeight = 1;
370 d1->dwMaxStippleWidth = 32;
371 d1->dwMaxStippleHeight = 32;
372 d1->dwMaxTextureRepeat = opengl_device_caps.dwMaxTextureRepeat;
373 d1->dwMaxTextureAspectRatio = opengl_device_caps.dwMaxTextureAspectRatio;
374 d1->dwMaxAnisotropy = opengl_device_caps.dwMaxAnisotropy;
375 d1->dvGuardBandLeft = opengl_device_caps.dvGuardBandLeft;
376 d1->dvGuardBandRight = opengl_device_caps.dvGuardBandRight;
377 d1->dvGuardBandTop = opengl_device_caps.dvGuardBandTop;
378 d1->dvGuardBandBottom = opengl_device_caps.dvGuardBandBottom;
379 d1->dvExtentsAdjust = opengl_device_caps.dvExtentsAdjust;
380 d1->dwStencilCaps = opengl_device_caps.dwStencilCaps;
381 d1->dwFVFCaps = opengl_device_caps.dwFVFCaps;
382 d1->dwTextureOpCaps = opengl_device_caps.dwTextureOpCaps;
383 d1->wMaxTextureBlendStages = opengl_device_caps.wMaxTextureBlendStages;
384 d1->wMaxSimultaneousTextures = opengl_device_caps.wMaxSimultaneousTextures;
387 static void fill_opengl_caps_7(D3DDEVICEDESC7 *d)
389 *d = opengl_device_caps;
392 HRESULT d3ddevice_enumerate(LPD3DENUMDEVICESCALLBACK cb, LPVOID context, DWORD version)
394 D3DDEVICEDESC dref, d1, d2;
397 /* Some games (Motoracer 2 demo) have the bad idea to modify the device name string.
398 Let's put the string in a sufficiently sized array in writable memory. */
399 char device_name[50];
400 strcpy(device_name,"direct3d");
402 fill_opengl_caps(&dref);
405 /* It seems that enumerating the reference IID on Direct3D 1 games (AvP / Motoracer2) breaks them */
406 char interface_name[] = "WINE Reference Direct3DX using OpenGL";
407 TRACE(" enumerating OpenGL D3DDevice interface using reference IID (IID %s).\n", debugstr_guid(&IID_IDirect3DRefDevice));
410 ret_value = cb((LPIID) &IID_IDirect3DRefDevice, interface_name, device_name, &d1, &d2, context);
411 if (ret_value != D3DENUMRET_OK)
416 char interface_name[] = "WINE Direct3DX using OpenGL";
417 TRACE(" enumerating OpenGL D3DDevice interface (IID %s).\n", debugstr_guid(&IID_D3DDEVICE_OpenGL));
420 ret_value = cb((LPIID) &IID_D3DDEVICE_OpenGL, interface_name, device_name, &d1, &d2, context);
421 if (ret_value != D3DENUMRET_OK)
425 return D3DENUMRET_OK;
428 HRESULT d3ddevice_enumerate7(LPD3DENUMDEVICESCALLBACK7 cb, LPVOID context)
430 D3DDEVICEDESC7 ddesc;
431 char interface_name[] = "WINE Direct3D7 using OpenGL";
432 char device_name[] = "Wine D3D7 device";
434 fill_opengl_caps_7(&ddesc);
436 TRACE(" enumerating OpenGL D3DDevice7 interface.\n");
438 return cb(interface_name, device_name, &ddesc, context);
442 GL_IDirect3DDeviceImpl_7_3T_2T_1T_Release(LPDIRECT3DDEVICE7 iface)
444 ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice7, iface);
445 IDirect3DDeviceGLImpl *glThis = (IDirect3DDeviceGLImpl *) This;
447 TRACE("(%p/%p)->() decrementing from %lu.\n", This, iface, This->ref);
448 if (!--(This->ref)) {
450 IDirectDrawSurfaceImpl *surface = This->surface, *surf;
452 /* Release texture associated with the device */
453 for (i = 0; i < MAX_TEXTURES; i++) {
454 if (This->current_texture[i] != NULL)
455 IDirectDrawSurface7_Release(ICOM_INTERFACE(This->current_texture[i], IDirectDrawSurface7));
456 HeapFree(GetProcessHeap(), 0, This->tex_mat[i]);
459 /* Look for the front buffer and override its surface's Flip method (if in double buffering) */
460 for (surf = surface; surf != NULL; surf = surf->surface_owner) {
461 if ((surf->surface_desc.ddsCaps.dwCaps&(DDSCAPS_FLIP|DDSCAPS_FRONTBUFFER)) == (DDSCAPS_FLIP|DDSCAPS_FRONTBUFFER)) {
462 surf->aux_ctx = NULL;
463 surf->aux_data = NULL;
464 surf->aux_flip = NULL;
468 for (surf = surface; surf != NULL; surf = surf->surface_owner) {
469 IDirectDrawSurfaceImpl *surf2;
470 for (surf2 = surf; surf2->prev_attached != NULL; surf2 = surf2->prev_attached) ;
471 for (; surf2 != NULL; surf2 = surf2->next_attached) {
472 if (((surf2->surface_desc.ddsCaps.dwCaps & (DDSCAPS_3DDEVICE)) == (DDSCAPS_3DDEVICE)) &&
473 ((surf2->surface_desc.ddsCaps.dwCaps & (DDSCAPS_ZBUFFER)) != (DDSCAPS_ZBUFFER))) {
474 /* Override the Lock / Unlock function for all these surfaces */
475 surf2->lock_update = surf2->lock_update_prev;
476 surf2->unlock_update = surf2->unlock_update_prev;
477 /* And install also the blt / bltfast overrides */
478 surf2->aux_blt = NULL;
479 surf2->aux_bltfast = NULL;
481 surf2->d3ddevice = NULL;
485 /* And warn the D3D object that this device is no longer active... */
486 This->d3d->d3d_removed_device(This->d3d, This);
488 HeapFree(GetProcessHeap(), 0, This->world_mat);
489 HeapFree(GetProcessHeap(), 0, This->view_mat);
490 HeapFree(GetProcessHeap(), 0, This->proj_mat);
492 if (glThis->surface_ptr)
493 HeapFree(GetProcessHeap(), 0, glThis->surface_ptr);
495 DeleteCriticalSection(&(This->crit));
498 if (glThis->unlock_tex)
499 glDeleteTextures(1, &(glThis->unlock_tex));
500 glXDestroyContext(glThis->display, glThis->gl_context);
502 HeapFree(GetProcessHeap(), 0, This->clipping_planes);
504 HeapFree(GetProcessHeap(), 0, This);
511 GL_IDirect3DDeviceImpl_3_2T_1T_GetCaps(LPDIRECT3DDEVICE3 iface,
512 LPD3DDEVICEDESC lpD3DHWDevDesc,
513 LPD3DDEVICEDESC lpD3DHELDevDesc)
515 ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice3, iface);
519 TRACE("(%p/%p)->(%p,%p)\n", This, iface, lpD3DHWDevDesc, lpD3DHELDevDesc);
521 fill_opengl_caps(&desc);
522 dwSize = lpD3DHWDevDesc->dwSize;
523 memset(lpD3DHWDevDesc, 0, dwSize);
524 memcpy(lpD3DHWDevDesc, &desc, (dwSize <= desc.dwSize ? dwSize : desc.dwSize));
526 dwSize = lpD3DHELDevDesc->dwSize;
527 memset(lpD3DHELDevDesc, 0, dwSize);
528 memcpy(lpD3DHELDevDesc, &desc, (dwSize <= desc.dwSize ? dwSize : desc.dwSize));
530 TRACE(" returning caps : (no dump function yet)\n");
535 static HRESULT enum_texture_format_OpenGL(LPD3DENUMTEXTUREFORMATSCALLBACK cb_1,
536 LPD3DENUMPIXELFORMATSCALLBACK cb_2,
540 LPDDPIXELFORMAT pformat;
542 /* Do the texture enumeration */
543 sdesc.dwSize = sizeof(DDSURFACEDESC);
544 sdesc.dwFlags = DDSD_PIXELFORMAT | DDSD_CAPS;
545 sdesc.ddsCaps.dwCaps = DDSCAPS_TEXTURE;
546 pformat = &(sdesc.ddpfPixelFormat);
547 pformat->dwSize = sizeof(DDPIXELFORMAT);
548 pformat->dwFourCC = 0;
550 TRACE("Enumerating GL_RGBA unpacked (32)\n");
551 pformat->dwFlags = DDPF_RGB | DDPF_ALPHAPIXELS;
552 pformat->u1.dwRGBBitCount = 32;
553 pformat->u2.dwRBitMask = 0x00FF0000;
554 pformat->u3.dwGBitMask = 0x0000FF00;
555 pformat->u4.dwBBitMask = 0x000000FF;
556 pformat->u5.dwRGBAlphaBitMask = 0xFF000000;
557 if (cb_1) if (cb_1(&sdesc , context) == 0) return DD_OK;
558 if (cb_2) if (cb_2(pformat, context) == 0) return DD_OK;
560 TRACE("Enumerating GL_RGB unpacked (32)\n");
561 pformat->dwFlags = DDPF_RGB;
562 pformat->u1.dwRGBBitCount = 32;
563 pformat->u2.dwRBitMask = 0x00FF0000;
564 pformat->u3.dwGBitMask = 0x0000FF00;
565 pformat->u4.dwBBitMask = 0x000000FF;
566 pformat->u5.dwRGBAlphaBitMask = 0x00000000;
567 if (cb_1) if (cb_1(&sdesc , context) == 0) return DD_OK;
568 if (cb_2) if (cb_2(pformat, context) == 0) return DD_OK;
570 TRACE("Enumerating GL_RGB unpacked (24)\n");
571 pformat->dwFlags = DDPF_RGB;
572 pformat->u1.dwRGBBitCount = 24;
573 pformat->u2.dwRBitMask = 0x00FF0000;
574 pformat->u3.dwGBitMask = 0x0000FF00;
575 pformat->u4.dwBBitMask = 0x000000FF;
576 pformat->u5.dwRGBAlphaBitMask = 0x00000000;
577 if (cb_1) if (cb_1(&sdesc , context) == 0) return DD_OK;
578 if (cb_2) if (cb_2(pformat, context) == 0) return DD_OK;
580 /* Note : even if this is an 'emulated' texture format, it needs to be first
581 as some dumb applications seem to rely on that. */
582 TRACE("Enumerating GL_RGBA packed GL_UNSIGNED_SHORT_1_5_5_5 (ARGB) (16)\n");
583 pformat->dwFlags = DDPF_RGB | DDPF_ALPHAPIXELS;
584 pformat->u1.dwRGBBitCount = 16;
585 pformat->u2.dwRBitMask = 0x00007C00;
586 pformat->u3.dwGBitMask = 0x000003E0;
587 pformat->u4.dwBBitMask = 0x0000001F;
588 pformat->u5.dwRGBAlphaBitMask = 0x00008000;
589 if (cb_1) if (cb_1(&sdesc , context) == 0) return DD_OK;
590 if (cb_2) if (cb_2(pformat, context) == 0) return DD_OK;
592 TRACE("Enumerating GL_RGBA packed GL_UNSIGNED_SHORT_4_4_4_4 (ARGB) (16)\n");
593 pformat->dwFlags = DDPF_RGB | DDPF_ALPHAPIXELS;
594 pformat->u1.dwRGBBitCount = 16;
595 pformat->u2.dwRBitMask = 0x00000F00;
596 pformat->u3.dwGBitMask = 0x000000F0;
597 pformat->u4.dwBBitMask = 0x0000000F;
598 pformat->u5.dwRGBAlphaBitMask = 0x0000F000;
599 if (cb_1) if (cb_1(&sdesc , context) == 0) return DD_OK;
600 if (cb_2) if (cb_2(pformat, context) == 0) return DD_OK;
602 TRACE("Enumerating GL_RGB packed GL_UNSIGNED_SHORT_5_6_5 (16)\n");
603 pformat->dwFlags = DDPF_RGB;
604 pformat->u1.dwRGBBitCount = 16;
605 pformat->u2.dwRBitMask = 0x0000F800;
606 pformat->u3.dwGBitMask = 0x000007E0;
607 pformat->u4.dwBBitMask = 0x0000001F;
608 pformat->u5.dwRGBAlphaBitMask = 0x00000000;
609 if (cb_1) if (cb_1(&sdesc , context) == 0) return DD_OK;
610 if (cb_2) if (cb_2(pformat, context) == 0) return DD_OK;
612 TRACE("Enumerating GL_RGB packed GL_UNSIGNED_SHORT_5_5_5 (16)\n");
613 pformat->dwFlags = DDPF_RGB;
614 pformat->u1.dwRGBBitCount = 16;
615 pformat->u2.dwRBitMask = 0x00007C00;
616 pformat->u3.dwGBitMask = 0x000003E0;
617 pformat->u4.dwBBitMask = 0x0000001F;
618 pformat->u5.dwRGBAlphaBitMask = 0x00000000;
619 if (cb_1) if (cb_1(&sdesc , context) == 0) return DD_OK;
620 if (cb_2) if (cb_2(pformat, context) == 0) return DD_OK;
623 /* This is a compromise : some games choose the first 16 bit texture format with alpha they
624 find enumerated, others the last one. And both want to have the ARGB one.
626 So basically, forget our OpenGL roots and do not even enumerate our RGBA ones.
628 /* See argument about the RGBA format for 'packed' texture formats */
629 TRACE("Enumerating GL_RGBA unpacked (32)\n");
630 pformat->dwFlags = DDPF_RGB | DDPF_ALPHAPIXELS;
631 pformat->u1.dwRGBBitCount = 32;
632 pformat->u2.dwRBitMask = 0xFF000000;
633 pformat->u3.dwGBitMask = 0x00FF0000;
634 pformat->u4.dwBBitMask = 0x0000FF00;
635 pformat->u5.dwRGBAlphaBitMask = 0x000000FF;
636 if (cb_1) if (cb_1(&sdesc , context) == 0) return DD_OK;
637 if (cb_2) if (cb_2(pformat, context) == 0) return DD_OK;
639 TRACE("Enumerating GL_RGBA packed GL_UNSIGNED_SHORT_4_4_4_4 (16)\n");
640 pformat->dwFlags = DDPF_RGB | DDPF_ALPHAPIXELS;
641 pformat->u1.dwRGBBitCount = 16;
642 pformat->u2.dwRBitMask = 0x0000F000;
643 pformat->u3.dwGBitMask = 0x00000F00;
644 pformat->u4.dwBBitMask = 0x000000F0;
645 pformat->u5.dwRGBAlphaBitMask = 0x0000000F;
646 if (cb_1) if (cb_1(&sdesc , context) == 0) return DD_OK;
647 if (cb_2) if (cb_2(pformat, context) == 0) return DD_OK;
649 TRACE("Enumerating GL_RGBA packed GL_UNSIGNED_SHORT_5_5_5_1 (16)\n");
650 pformat->dwFlags = DDPF_RGB | DDPF_ALPHAPIXELS;
651 pformat->u1.dwRGBBitCount = 16;
652 pformat->u2.dwRBitMask = 0x0000F800;
653 pformat->u3.dwGBitMask = 0x000007C0;
654 pformat->u4.dwBBitMask = 0x0000003E;
655 pformat->u5.dwRGBAlphaBitMask = 0x00000001;
656 if (cb_1) if (cb_1(&sdesc , context) == 0) return DD_OK;
657 if (cb_2) if (cb_2(pformat, context) == 0) return DD_OK;
660 TRACE("Enumerating GL_RGB packed GL_UNSIGNED_BYTE_3_3_2 (8)\n");
661 pformat->dwFlags = DDPF_RGB;
662 pformat->u1.dwRGBBitCount = 8;
663 pformat->u2.dwRBitMask = 0x000000E0;
664 pformat->u3.dwGBitMask = 0x0000001C;
665 pformat->u4.dwBBitMask = 0x00000003;
666 pformat->u5.dwRGBAlphaBitMask = 0x00000000;
667 if (cb_1) if (cb_1(&sdesc , context) == 0) return DD_OK;
668 if (cb_2) if (cb_2(pformat, context) == 0) return DD_OK;
670 TRACE("Enumerating Paletted (8)\n");
671 pformat->dwFlags = DDPF_PALETTEINDEXED8;
672 pformat->u1.dwRGBBitCount = 8;
673 pformat->u2.dwRBitMask = 0x00000000;
674 pformat->u3.dwGBitMask = 0x00000000;
675 pformat->u4.dwBBitMask = 0x00000000;
676 pformat->u5.dwRGBAlphaBitMask = 0x00000000;
677 if (cb_1) if (cb_1(&sdesc , context) == 0) return DD_OK;
678 if (cb_2) if (cb_2(pformat, context) == 0) return DD_OK;
680 TRACE("End of enumeration\n");
686 d3ddevice_find(IDirectDrawImpl *d3d,
687 LPD3DFINDDEVICESEARCH lpD3DDFS,
688 LPD3DFINDDEVICERESULT lplpD3DDevice)
692 if ((lpD3DDFS->dwFlags & D3DFDS_COLORMODEL) &&
693 (lpD3DDFS->dcmColorModel != D3DCOLOR_RGB)) {
694 TRACE(" trying to request a non-RGB D3D color model. Not supported.\n");
695 return DDERR_INVALIDPARAMS; /* No real idea what to return here :-) */
697 if (lpD3DDFS->dwFlags & D3DFDS_GUID) {
698 TRACE(" trying to match guid %s.\n", debugstr_guid(&(lpD3DDFS->guid)));
699 if ((IsEqualGUID(&IID_D3DDEVICE_OpenGL, &(lpD3DDFS->guid)) == 0) &&
700 (IsEqualGUID(&IID_IDirect3DHALDevice, &(lpD3DDFS->guid)) == 0) &&
701 (IsEqualGUID(&IID_IDirect3DRefDevice, &(lpD3DDFS->guid)) == 0)) {
702 TRACE(" no match for this GUID.\n");
703 return DDERR_INVALIDPARAMS;
707 /* Now return our own GUID */
708 lplpD3DDevice->guid = IID_D3DDEVICE_OpenGL;
709 fill_opengl_caps(&desc);
710 lplpD3DDevice->ddHwDesc = desc;
711 lplpD3DDevice->ddSwDesc = desc;
713 TRACE(" returning Wine's OpenGL device with (undumped) capabilities\n");
719 GL_IDirect3DDeviceImpl_2_1T_EnumTextureFormats(LPDIRECT3DDEVICE2 iface,
720 LPD3DENUMTEXTUREFORMATSCALLBACK lpD3DEnumTextureProc,
723 ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice2, iface);
724 TRACE("(%p/%p)->(%p,%p)\n", This, iface, lpD3DEnumTextureProc, lpArg);
725 return enum_texture_format_OpenGL(lpD3DEnumTextureProc, NULL, lpArg);
729 GL_IDirect3DDeviceImpl_7_3T_EnumTextureFormats(LPDIRECT3DDEVICE7 iface,
730 LPD3DENUMPIXELFORMATSCALLBACK lpD3DEnumPixelProc,
733 ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice7, iface);
734 TRACE("(%p/%p)->(%p,%p)\n", This, iface, lpD3DEnumPixelProc, lpArg);
735 return enum_texture_format_OpenGL(NULL, lpD3DEnumPixelProc, lpArg);
739 GL_IDirect3DDeviceImpl_7_3T_2T_SetRenderState(LPDIRECT3DDEVICE7 iface,
740 D3DRENDERSTATETYPE dwRenderStateType,
743 ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice7, iface);
744 TRACE("(%p/%p)->(%08x,%08lx)\n", This, iface, dwRenderStateType, dwRenderState);
746 /* Call the render state functions */
747 store_render_state(This, dwRenderStateType, dwRenderState, &This->state_block);
748 set_render_state(This, dwRenderStateType, &This->state_block);
754 GL_IDirect3DDeviceImpl_7_3T_2T_GetRenderState(LPDIRECT3DDEVICE7 iface,
755 D3DRENDERSTATETYPE dwRenderStateType,
756 LPDWORD lpdwRenderState)
758 ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice7, iface);
759 TRACE("(%p/%p)->(%08x,%p)\n", This, iface, dwRenderStateType, lpdwRenderState);
761 /* Call the render state functions */
762 get_render_state(This, dwRenderStateType, lpdwRenderState, &This->state_block);
764 TRACE(" - asked for rendering state : %s, returning value %08lx.\n", _get_renderstate(dwRenderStateType), *lpdwRenderState);
770 GL_IDirect3DDeviceImpl_3_2T_SetLightState(LPDIRECT3DDEVICE3 iface,
771 D3DLIGHTSTATETYPE dwLightStateType,
774 ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice3, iface);
776 TRACE("(%p/%p)->(%08x,%08lx)\n", This, iface, dwLightStateType, dwLightState);
778 if (!dwLightStateType && (dwLightStateType > D3DLIGHTSTATE_COLORVERTEX)) {
779 TRACE("Unexpected Light State Type\n");
780 return DDERR_INVALIDPARAMS;
783 if (dwLightStateType == D3DLIGHTSTATE_MATERIAL /* 1 */) {
784 IDirect3DMaterialImpl *mat = (IDirect3DMaterialImpl *) dwLightState;
787 TRACE(" activating material %p.\n", mat);
790 ERR(" D3DLIGHTSTATE_MATERIAL called with NULL material !!!\n");
791 return DDERR_INVALIDPARAMS;
793 } else if (dwLightStateType == D3DLIGHTSTATE_COLORMODEL /* 3 */) {
794 switch (dwLightState) {
796 ERR("DDCOLOR_MONO should not happen!\n");
799 /* We are already in this mode */
800 TRACE("Setting color model to RGB (no-op).\n");
803 ERR("Unknown color model!\n");
804 return DDERR_INVALIDPARAMS;
807 D3DRENDERSTATETYPE rs;
808 switch (dwLightStateType) {
809 case D3DLIGHTSTATE_AMBIENT: /* 2 */
810 rs = D3DRENDERSTATE_AMBIENT;
812 case D3DLIGHTSTATE_FOGMODE: /* 4 */
813 rs = D3DRENDERSTATE_FOGVERTEXMODE;
815 case D3DLIGHTSTATE_FOGSTART: /* 5 */
816 rs = D3DRENDERSTATE_FOGSTART;
818 case D3DLIGHTSTATE_FOGEND: /* 6 */
819 rs = D3DRENDERSTATE_FOGEND;
821 case D3DLIGHTSTATE_FOGDENSITY: /* 7 */
822 rs = D3DRENDERSTATE_FOGDENSITY;
824 case D3DLIGHTSTATE_COLORVERTEX: /* 8 */
825 rs = D3DRENDERSTATE_COLORVERTEX;
828 ERR("Unknown D3DLIGHTSTATETYPE %d.\n", dwLightStateType);
829 return DDERR_INVALIDPARAMS;
832 IDirect3DDevice7_SetRenderState(ICOM_INTERFACE(This, IDirect3DDevice7),
839 static GLenum convert_D3D_ptype_to_GL(D3DPRIMITIVETYPE d3dpt)
842 case D3DPT_POINTLIST:
843 TRACE(" primitive type is POINTS\n");
847 TRACE(" primitive type is LINES\n");
850 case D3DPT_LINESTRIP:
851 TRACE(" primitive type is LINE_STRIP\n");
852 return GL_LINE_STRIP;
854 case D3DPT_TRIANGLELIST:
855 TRACE(" primitive type is TRIANGLES\n");
858 case D3DPT_TRIANGLESTRIP:
859 TRACE(" primitive type is TRIANGLE_STRIP\n");
860 return GL_TRIANGLE_STRIP;
862 case D3DPT_TRIANGLEFAN:
863 TRACE(" primitive type is TRIANGLE_FAN\n");
864 return GL_TRIANGLE_FAN;
867 FIXME("Unhandled primitive %08x\n", d3dpt);
872 /* This function calculate the Z coordinate from Zproj */
873 static float ZfromZproj(IDirect3DDeviceImpl *This, D3DVALUE Zproj)
876 /* Assume that X = Y = 0 and W = 1 */
877 a = This->proj_mat->_33;
878 b = This->proj_mat->_34;
879 c = This->proj_mat->_43;
880 d = This->proj_mat->_44;
881 /* We have in homogenous coordinates Z' = a * Z + c and W' = b * Z + d
882 * So in non homogenous coordinates we have Zproj = (a * Z + c) / (b * Z + d)
883 * And finally Z = (d * Zproj - c) / (a - b * Zproj)
885 return (d*Zproj - c) / (a - b*Zproj);
888 static void build_fog_table(BYTE *fog_table, DWORD fog_color) {
891 TRACE(" rebuilding fog table (%06lx)...\n", fog_color & 0x00FFFFFF);
893 for (i = 0; i < 3; i++) {
894 BYTE fog_color_component = (fog_color >> (8 * i)) & 0xFF;
896 for (elt = 0; elt < 0x10000; elt++) {
897 /* We apply the fog transformation and cache the result */
898 DWORD fog_intensity = elt & 0xFF;
899 DWORD vertex_color = (elt >> 8) & 0xFF;
900 fog_table[(i * 0x10000) + elt] = ((fog_intensity * vertex_color) + ((0xFF - fog_intensity) * fog_color_component)) / 0xFF;
905 static void draw_primitive_handle_GL_state(IDirect3DDeviceImpl *This,
906 BOOLEAN vertex_transformed,
907 BOOLEAN vertex_lit) {
908 IDirect3DDeviceGLImpl* glThis = (IDirect3DDeviceGLImpl*) This;
910 /* Puts GL in the correct lighting / transformation mode */
911 if ((vertex_transformed == FALSE) &&
912 (glThis->transform_state != GL_TRANSFORM_NORMAL)) {
913 /* Need to put the correct transformation again if we go from Transformed
914 vertices to non-transformed ones.
916 This->set_matrices(This, VIEWMAT_CHANGED|WORLDMAT_CHANGED|PROJMAT_CHANGED,
917 This->world_mat, This->view_mat, This->proj_mat);
918 glThis->transform_state = GL_TRANSFORM_NORMAL;
920 } else if ((vertex_transformed == TRUE) &&
921 (glThis->transform_state != GL_TRANSFORM_ORTHO)) {
922 /* Set our orthographic projection */
923 if (glThis->transform_state != GL_TRANSFORM_ORTHO) {
924 glThis->transform_state = GL_TRANSFORM_ORTHO;
925 d3ddevice_set_ortho(This);
929 /* TODO: optimize this to not always reset all the fog stuff on all DrawPrimitive call
930 if no fogging state change occurred */
931 if (This->state_block.render_state[D3DRENDERSTATE_FOGENABLE - 1] == TRUE) {
932 if (vertex_transformed == TRUE) {
933 if (glThis->fogging != 0) {
937 /* Now check if our fog_table still corresponds to the current vertex color.
938 Element '0x..00' is always the fog color as it corresponds to maximum fog intensity */
939 if ((glThis->fog_table[0 * 0x10000 + 0x0000] != ((This->state_block.render_state[D3DRENDERSTATE_FOGCOLOR - 1] >> 0) & 0xFF)) ||
940 (glThis->fog_table[1 * 0x10000 + 0x0000] != ((This->state_block.render_state[D3DRENDERSTATE_FOGCOLOR - 1] >> 8) & 0xFF)) ||
941 (glThis->fog_table[2 * 0x10000 + 0x0000] != ((This->state_block.render_state[D3DRENDERSTATE_FOGCOLOR - 1] >> 16) & 0xFF))) {
942 /* We need to rebuild our fog table.... */
943 build_fog_table(glThis->fog_table, This->state_block.render_state[D3DRENDERSTATE_FOGCOLOR - 1]);
946 if (This->state_block.render_state[D3DRENDERSTATE_FOGTABLEMODE - 1] != D3DFOG_NONE) {
947 switch (This->state_block.render_state[D3DRENDERSTATE_FOGTABLEMODE - 1]) {
948 case D3DFOG_LINEAR: glFogi(GL_FOG_MODE, GL_LINEAR); break;
949 case D3DFOG_EXP: glFogi(GL_FOG_MODE, GL_EXP); break;
950 case D3DFOG_EXP2: glFogi(GL_FOG_MODE, GL_EXP2); break;
952 if (vertex_lit == FALSE) {
953 glFogf(GL_FOG_START, *(float*)&This->state_block.render_state[D3DRENDERSTATE_FOGSTART - 1]);
954 glFogf(GL_FOG_END, *(float*)&This->state_block.render_state[D3DRENDERSTATE_FOGEND - 1]);
956 /* Special case of 'pixel fog' */
957 glFogf(GL_FOG_START, ZfromZproj(This, *(float*)&This->state_block.render_state[D3DRENDERSTATE_FOGSTART - 1]));
958 glFogf(GL_FOG_END, ZfromZproj(This, *(float*)&This->state_block.render_state[D3DRENDERSTATE_FOGEND - 1]));
960 if (glThis->fogging == 0) {
965 if (glThis->fogging != 0) {
972 if (glThis->fogging != 0) {
978 /* Handle the 'no-normal' case */
979 if ((vertex_lit == FALSE) && (This->state_block.render_state[D3DRENDERSTATE_LIGHTING - 1] == TRUE)) {
980 if (glThis->lighting == 0) {
981 glEnable(GL_LIGHTING);
982 glThis->lighting = 1;
985 if (glThis->lighting != 0) {
986 glDisable(GL_LIGHTING);
987 glThis->lighting = 0;
991 /* Handle the code for pre-vertex material properties */
992 if (vertex_transformed == FALSE) {
993 if ((This->state_block.render_state[D3DRENDERSTATE_LIGHTING - 1] == TRUE) &&
994 (This->state_block.render_state[D3DRENDERSTATE_COLORVERTEX - 1] == TRUE)) {
995 if ((This->state_block.render_state[D3DRENDERSTATE_DIFFUSEMATERIALSOURCE - 1] != D3DMCS_MATERIAL) ||
996 (This->state_block.render_state[D3DRENDERSTATE_AMBIENTMATERIALSOURCE - 1] != D3DMCS_MATERIAL) ||
997 (This->state_block.render_state[D3DRENDERSTATE_EMISSIVEMATERIALSOURCE - 1] != D3DMCS_MATERIAL) ||
998 (This->state_block.render_state[D3DRENDERSTATE_SPECULARMATERIALSOURCE - 1] != D3DMCS_MATERIAL)) {
999 glEnable(GL_COLOR_MATERIAL);
1006 inline static void draw_primitive(IDirect3DDeviceImpl *This, DWORD maxvert, WORD *index,
1007 D3DVERTEXTYPE d3dvt, D3DPRIMITIVETYPE d3dpt, void *lpvertex)
1009 D3DDRAWPRIMITIVESTRIDEDDATA strided;
1012 case D3DVT_VERTEX: {
1013 strided.position.lpvData = &((D3DVERTEX *) lpvertex)->u1.x;
1014 strided.position.dwStride = sizeof(D3DVERTEX);
1015 strided.normal.lpvData = &((D3DVERTEX *) lpvertex)->u4.nx;
1016 strided.normal.dwStride = sizeof(D3DVERTEX);
1017 strided.textureCoords[0].lpvData = &((D3DVERTEX *) lpvertex)->u7.tu;
1018 strided.textureCoords[0].dwStride = sizeof(D3DVERTEX);
1019 draw_primitive_strided(This, d3dpt, D3DFVF_VERTEX, &strided, 0 /* Unused */, index, maxvert, 0 /* Unused */);
1022 case D3DVT_LVERTEX: {
1023 strided.position.lpvData = &((D3DLVERTEX *) lpvertex)->u1.x;
1024 strided.position.dwStride = sizeof(D3DLVERTEX);
1025 strided.diffuse.lpvData = &((D3DLVERTEX *) lpvertex)->u4.color;
1026 strided.diffuse.dwStride = sizeof(D3DLVERTEX);
1027 strided.specular.lpvData = &((D3DLVERTEX *) lpvertex)->u5.specular;
1028 strided.specular.dwStride = sizeof(D3DLVERTEX);
1029 strided.textureCoords[0].lpvData = &((D3DLVERTEX *) lpvertex)->u6.tu;
1030 strided.textureCoords[0].dwStride = sizeof(D3DLVERTEX);
1031 draw_primitive_strided(This, d3dpt, D3DFVF_LVERTEX, &strided, 0 /* Unused */, index, maxvert, 0 /* Unused */);
1034 case D3DVT_TLVERTEX: {
1035 strided.position.lpvData = &((D3DTLVERTEX *) lpvertex)->u1.sx;
1036 strided.position.dwStride = sizeof(D3DTLVERTEX);
1037 strided.diffuse.lpvData = &((D3DTLVERTEX *) lpvertex)->u5.color;
1038 strided.diffuse.dwStride = sizeof(D3DTLVERTEX);
1039 strided.specular.lpvData = &((D3DTLVERTEX *) lpvertex)->u6.specular;
1040 strided.specular.dwStride = sizeof(D3DTLVERTEX);
1041 strided.textureCoords[0].lpvData = &((D3DTLVERTEX *) lpvertex)->u7.tu;
1042 strided.textureCoords[0].dwStride = sizeof(D3DTLVERTEX);
1043 draw_primitive_strided(This, d3dpt, D3DFVF_TLVERTEX, &strided, 0 /* Unused */, index, maxvert, 0 /* Unused */);
1047 FIXME("Unhandled vertex type %08x\n", d3dvt);
1053 GL_IDirect3DDeviceImpl_2_DrawPrimitive(LPDIRECT3DDEVICE2 iface,
1054 D3DPRIMITIVETYPE d3dptPrimitiveType,
1055 D3DVERTEXTYPE d3dvtVertexType,
1057 DWORD dwVertexCount,
1060 ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice2, iface);
1062 TRACE("(%p/%p)->(%08x,%08x,%p,%08lx,%08lx)\n", This, iface, d3dptPrimitiveType, d3dvtVertexType, lpvVertices, dwVertexCount, dwFlags);
1063 if (TRACE_ON(ddraw)) {
1064 TRACE(" - flags : "); dump_DPFLAGS(dwFlags);
1067 draw_primitive(This, dwVertexCount, NULL, d3dvtVertexType, d3dptPrimitiveType, lpvVertices);
1073 GL_IDirect3DDeviceImpl_2_DrawIndexedPrimitive(LPDIRECT3DDEVICE2 iface,
1074 D3DPRIMITIVETYPE d3dptPrimitiveType,
1075 D3DVERTEXTYPE d3dvtVertexType,
1077 DWORD dwVertexCount,
1082 ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice2, iface);
1083 TRACE("(%p/%p)->(%08x,%08x,%p,%08lx,%p,%08lx,%08lx)\n", This, iface, d3dptPrimitiveType, d3dvtVertexType, lpvVertices, dwVertexCount, dwIndices, dwIndexCount, dwFlags);
1084 if (TRACE_ON(ddraw)) {
1085 TRACE(" - flags : "); dump_DPFLAGS(dwFlags);
1088 draw_primitive(This, dwIndexCount, dwIndices, d3dvtVertexType, d3dptPrimitiveType, lpvVertices);
1094 GL_IDirect3DDeviceImpl_1_CreateExecuteBuffer(LPDIRECT3DDEVICE iface,
1095 LPD3DEXECUTEBUFFERDESC lpDesc,
1096 LPDIRECT3DEXECUTEBUFFER* lplpDirect3DExecuteBuffer,
1097 IUnknown* pUnkOuter)
1099 ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice, iface);
1100 IDirect3DExecuteBufferImpl *ret;
1103 TRACE("(%p/%p)->(%p,%p,%p)\n", This, iface, lpDesc, lplpDirect3DExecuteBuffer, pUnkOuter);
1105 ret_value = d3dexecutebuffer_create(&ret, This->d3d, This, lpDesc);
1106 *lplpDirect3DExecuteBuffer = ICOM_INTERFACE(ret, IDirect3DExecuteBuffer);
1108 TRACE(" returning %p.\n", *lplpDirect3DExecuteBuffer);
1113 static void flush_zbuffer_to_GL(IDirect3DDeviceImpl *d3d_dev, LPCRECT pRect, IDirectDrawSurfaceImpl *surf) {
1114 static BOOLEAN first = TRUE;
1115 IDirect3DDeviceGLImpl* gl_d3d_dev = (IDirect3DDeviceGLImpl*) d3d_dev;
1119 if (first == TRUE) {
1120 MESSAGE("Warning : application does direct locking of ZBuffer - expect slowdowns on many GL implementations :-)\n");
1124 TRACE("flushing ZBuffer back to GL\n");
1126 if (gl_d3d_dev->transform_state != GL_TRANSFORM_ORTHO) {
1127 gl_d3d_dev->transform_state = GL_TRANSFORM_ORTHO;
1128 d3ddevice_set_ortho(d3d_dev);
1131 glMatrixMode(GL_MODELVIEW);
1134 if (gl_d3d_dev->depth_test == 0) glEnable(GL_DEPTH_TEST);
1135 if (d3d_dev->state_block.render_state[D3DRENDERSTATE_ZFUNC - 1] != D3DCMP_ALWAYS) glDepthFunc(GL_ALWAYS);
1136 glColorMask(GL_FALSE, GL_FALSE, GL_FALSE, GL_FALSE);
1138 /* This loop here is to prevent using PixelZoom that may be unoptimized for the 1.0 / -1.0 case
1141 switch (surf->surface_desc.u4.ddpfPixelFormat.u1.dwZBufferBitDepth) {
1142 case 16: type = GL_UNSIGNED_SHORT; break;
1143 case 32: type = GL_UNSIGNED_INT; break;
1144 default: FIXME("Unhandled ZBuffer format !\n"); goto restore_state;
1147 for (row = 0; row < surf->surface_desc.dwHeight; row++) {
1148 /* glRasterPos3d(0.0, row + 1.0, 0.5); */
1149 glRasterPos2i(0, row + 1);
1150 glDrawPixels(surf->surface_desc.dwWidth, 1, GL_DEPTH_COMPONENT, type,
1151 ((unsigned char *) surf->surface_desc.lpSurface) + (row * surf->surface_desc.u1.lPitch));
1155 glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
1156 if (d3d_dev->state_block.render_state[D3DRENDERSTATE_ZFUNC - 1] != D3DCMP_ALWAYS)
1157 glDepthFunc(convert_D3D_compare_to_GL(d3d_dev->state_block.render_state[D3DRENDERSTATE_ZFUNC - 1]));
1158 if (gl_d3d_dev->depth_test == 0) glDisable(GL_DEPTH_TEST);
1161 /* These are the various handler used in the generic path */
1162 inline static void handle_xyz(D3DVALUE *coords) {
1163 glVertex3fv(coords);
1165 inline static void handle_xyzrhw(D3DVALUE *coords) {
1166 if (coords[3] < 1e-8)
1167 glVertex3fv(coords);
1169 GLfloat w = 1.0 / coords[3];
1171 glVertex4f(coords[0] * w,
1177 inline static void handle_normal(D3DVALUE *coords) {
1178 glNormal3fv(coords);
1181 inline static void handle_diffuse_base(STATEBLOCK *sb, DWORD *color) {
1182 if ((sb->render_state[D3DRENDERSTATE_ALPHATESTENABLE - 1] == TRUE) ||
1183 (sb->render_state[D3DRENDERSTATE_ALPHABLENDENABLE - 1] == TRUE)) {
1184 glColor4ub((*color >> 16) & 0xFF,
1185 (*color >> 8) & 0xFF,
1186 (*color >> 0) & 0xFF,
1187 (*color >> 24) & 0xFF);
1189 glColor3ub((*color >> 16) & 0xFF,
1190 (*color >> 8) & 0xFF,
1191 (*color >> 0) & 0xFF);
1195 inline static void handle_specular_base(STATEBLOCK *sb, DWORD *color) {
1196 glColor4ub((*color >> 16) & 0xFF,
1197 (*color >> 8) & 0xFF,
1198 (*color >> 0) & 0xFF,
1199 (*color >> 24) & 0xFF); /* No idea if the alpha field is really used.. */
1202 inline static void handle_diffuse(STATEBLOCK *sb, DWORD *color, BOOLEAN lighted) {
1203 if ((lighted == FALSE) &&
1204 (sb->render_state[D3DRENDERSTATE_LIGHTING - 1] == TRUE) &&
1205 (sb->render_state[D3DRENDERSTATE_COLORVERTEX - 1] == TRUE)) {
1206 if (sb->render_state[D3DRENDERSTATE_DIFFUSEMATERIALSOURCE - 1] == D3DMCS_COLOR1) {
1207 glColorMaterial(GL_FRONT_AND_BACK, GL_DIFFUSE);
1208 handle_diffuse_base(sb, color);
1210 if (sb->render_state[D3DRENDERSTATE_AMBIENTMATERIALSOURCE - 1] == D3DMCS_COLOR1) {
1211 glColorMaterial(GL_FRONT_AND_BACK, GL_AMBIENT);
1212 handle_diffuse_base(sb, color);
1214 if ((sb->render_state[D3DRENDERSTATE_SPECULARMATERIALSOURCE - 1] == D3DMCS_COLOR1) &&
1215 (sb->render_state[D3DRENDERSTATE_SPECULARENABLE - 1] == TRUE)) {
1216 glColorMaterial(GL_FRONT_AND_BACK, GL_SPECULAR);
1217 handle_diffuse_base(sb, color);
1219 if (sb->render_state[D3DRENDERSTATE_EMISSIVEMATERIALSOURCE - 1] == D3DMCS_COLOR1) {
1220 glColorMaterial(GL_FRONT_AND_BACK, GL_EMISSION);
1221 handle_diffuse_base(sb, color);
1224 handle_diffuse_base(sb, color);
1228 inline static void handle_specular(STATEBLOCK *sb, DWORD *color, BOOLEAN lighted) {
1229 if ((lighted == FALSE) &&
1230 (sb->render_state[D3DRENDERSTATE_LIGHTING - 1] == TRUE) &&
1231 (sb->render_state[D3DRENDERSTATE_COLORVERTEX - 1] == TRUE)) {
1232 if (sb->render_state[D3DRENDERSTATE_DIFFUSEMATERIALSOURCE - 1] == D3DMCS_COLOR2) {
1233 glColorMaterial(GL_FRONT_AND_BACK, GL_DIFFUSE);
1234 handle_specular_base(sb, color);
1236 if (sb->render_state[D3DRENDERSTATE_AMBIENTMATERIALSOURCE - 1] == D3DMCS_COLOR2) {
1237 glColorMaterial(GL_FRONT_AND_BACK, GL_AMBIENT);
1238 handle_specular_base(sb, color);
1240 if ((sb->render_state[D3DRENDERSTATE_SPECULARMATERIALSOURCE - 1] == D3DMCS_COLOR2) &&
1241 (sb->render_state[D3DRENDERSTATE_SPECULARENABLE - 1] == TRUE)) {
1242 glColorMaterial(GL_FRONT_AND_BACK, GL_SPECULAR);
1243 handle_specular_base(sb, color);
1245 if (sb->render_state[D3DRENDERSTATE_EMISSIVEMATERIALSOURCE - 1] == D3DMCS_COLOR2) {
1246 glColorMaterial(GL_FRONT_AND_BACK, GL_EMISSION);
1247 handle_specular_base(sb, color);
1250 /* No else here as we do not know how to handle 'specular' on its own in any case.. */
1253 inline static void handle_diffuse_and_specular(STATEBLOCK *sb, BYTE *fog_table, DWORD *color_d, DWORD *color_s, BOOLEAN lighted) {
1254 if (lighted == TRUE) {
1255 DWORD color = *color_d;
1256 if (sb->render_state[D3DRENDERSTATE_FOGENABLE - 1] == TRUE) {
1257 /* Special case where the specular value is used to do fogging */
1258 BYTE fog_intensity = *color_s >> 24; /* The alpha value of the specular component is the fog 'intensity' for this vertex */
1259 color &= 0xFF000000; /* Only keep the alpha component */
1260 color |= fog_table[((*color_d >> 0) & 0xFF) << 8 | fog_intensity] << 0;
1261 color |= fog_table[((*color_d >> 8) & 0xFF) << 8 | fog_intensity] << 8;
1262 color |= fog_table[((*color_d >> 16) & 0xFF) << 8 | fog_intensity] << 16;
1264 if (sb->render_state[D3DRENDERSTATE_SPECULARENABLE - 1] == TRUE) {
1265 /* Standard specular value in transformed mode. TODO */
1267 handle_diffuse_base(sb, &color);
1269 if (sb->render_state[D3DRENDERSTATE_LIGHTING - 1] == TRUE) {
1270 handle_diffuse(sb, color_d, FALSE);
1271 handle_specular(sb, color_s, FALSE);
1273 /* In that case, only put the diffuse color... */
1274 handle_diffuse_base(sb, color_d);
1279 inline static void handle_texture(D3DVALUE *coords) {
1280 glTexCoord2fv(coords);
1282 inline static void handle_textures(D3DVALUE *coords, int tex_stage) {
1283 if (GL_extensions.glMultiTexCoord2fv) {
1284 GL_extensions.glMultiTexCoord2fv(GL_TEXTURE0_WINE + tex_stage, coords);
1286 if (tex_stage == 0) glTexCoord2fv(coords);
1290 static void draw_primitive_strided(IDirect3DDeviceImpl *This,
1291 D3DPRIMITIVETYPE d3dptPrimitiveType,
1292 DWORD d3dvtVertexType,
1293 LPD3DDRAWPRIMITIVESTRIDEDDATA lpD3DDrawPrimStrideData,
1294 DWORD dwVertexCount,
1299 BOOLEAN vertex_lighted = FALSE;
1300 IDirect3DDeviceGLImpl* glThis = (IDirect3DDeviceGLImpl*) This;
1301 int num_active_stages = 0;
1302 int num_tex_index = ((d3dvtVertexType & D3DFVF_TEXCOUNT_MASK) >> D3DFVF_TEXCOUNT_SHIFT);
1304 /* I put the trace before the various locks... So as to better understand where locks occur :-) */
1305 if (TRACE_ON(ddraw)) {
1306 TRACE(" Vertex format : "); dump_flexible_vertex(d3dvtVertexType);
1309 /* This is to prevent 'thread contention' between a thread locking the device and another
1310 doing 3D display on it... */
1311 EnterCriticalSection(&(This->crit));
1314 if (glThis->state[WINE_GL_BUFFER_BACK] == SURFACE_MEMORY_DIRTY) {
1315 This->flush_to_framebuffer(This, &(glThis->lock_rect[WINE_GL_BUFFER_BACK]), glThis->lock_surf[WINE_GL_BUFFER_BACK]);
1317 glThis->state[WINE_GL_BUFFER_BACK] = SURFACE_GL;
1319 if (This->current_zbuffer == NULL) {
1320 /* Search for an attached ZBuffer */
1321 static const DDSCAPS2 zbuf_caps = { DDSCAPS_ZBUFFER, 0, 0, 0 };
1322 LPDIRECTDRAWSURFACE7 zbuf;
1325 hr = IDirectDrawSurface7_GetAttachedSurface(ICOM_INTERFACE(This->surface, IDirectDrawSurface7),
1326 (DDSCAPS2 *) &zbuf_caps, &zbuf);
1328 This->current_zbuffer = ICOM_OBJECT(IDirectDrawSurfaceImpl, IDirectDrawSurface7, zbuf);
1329 IDirectDrawSurface7_Release(zbuf);
1332 if (This->current_zbuffer != NULL) {
1333 if (This->current_zbuffer->get_dirty_status(This->current_zbuffer, NULL)) {
1334 flush_zbuffer_to_GL(This, NULL, This->current_zbuffer);
1338 if ( ((d3dvtVertexType & D3DFVF_POSITION_MASK) != D3DFVF_XYZ) ||
1339 ((d3dvtVertexType & D3DFVF_NORMAL) == 0) )
1340 vertex_lighted = TRUE;
1342 /* Compute the number of active texture stages and set the various texture parameters */
1343 num_active_stages = draw_primitive_handle_textures(This);
1345 /* And restore to handle '0' in the case we use glTexCoord calls */
1346 if (glThis->current_active_tex_unit != GL_TEXTURE0_WINE) {
1347 GL_extensions.glActiveTexture(GL_TEXTURE0_WINE);
1348 glThis->current_active_tex_unit = GL_TEXTURE0_WINE;
1351 draw_primitive_handle_GL_state(This,
1352 (d3dvtVertexType & D3DFVF_POSITION_MASK) != D3DFVF_XYZ,
1355 /* First, see if we can use the OpenGL vertex arrays... This is very limited
1356 for now to some 'special' cases where we can do a direct mapping between D3D
1359 Note: in the future all calls will go through vertex arrays but the arrays
1360 will be generated by this function.
1362 Note2: colours cannot be mapped directly because they are stored as BGRA in memory
1363 (ie not as an array of R, G, B, A as OpenGL does it but as a LWORD 0xAARRGGBB
1364 which, as we are little indian, gives a B, G, R, A storage in memory.
1366 if (((d3dvtVertexType & D3DFVF_POSITION_MASK) == D3DFVF_XYZ) && /* Standard XYZ vertices */
1367 ((d3dvtVertexType & (D3DFVF_DIFFUSE|D3DFVF_SPECULAR)) == 0)) {
1369 TRACE(" using GL vertex arrays for performance !\n");
1370 /* First, the vertices (we are sure we have some :-) */
1371 glEnableClientState(GL_VERTEX_ARRAY);
1372 glVertexPointer(3, GL_FLOAT, lpD3DDrawPrimStrideData->position.dwStride, lpD3DDrawPrimStrideData->position.lpvData);
1373 /* Then the normals */
1374 if (d3dvtVertexType & D3DFVF_NORMAL) {
1375 glEnableClientState(GL_NORMAL_ARRAY);
1376 glNormalPointer(GL_FLOAT, lpD3DDrawPrimStrideData->normal.dwStride, lpD3DDrawPrimStrideData->normal.lpvData);
1378 /* Then the diffuse colour */
1379 if (d3dvtVertexType & D3DFVF_DIFFUSE) {
1380 glEnableClientState(GL_COLOR_ARRAY);
1381 glColorPointer(3, GL_UNSIGNED_BYTE, lpD3DDrawPrimStrideData->normal.dwStride,
1382 ((char *) lpD3DDrawPrimStrideData->diffuse.lpvData));
1384 /* Then the various textures */
1385 for (tex_stage = 0; tex_stage < num_active_stages; tex_stage++) {
1386 int tex_index = This->state_block.texture_stage_state[tex_stage][D3DTSS_TEXCOORDINDEX - 1] & 0x0000FFFF;
1387 if (tex_index >= num_tex_index) {
1388 WARN("Default texture coordinate not handled in the vertex array path !!!\n");
1389 tex_index = num_tex_index - 1;
1391 if (GL_extensions.glClientActiveTexture) {
1392 GL_extensions.glClientActiveTexture(GL_TEXTURE0_WINE + tex_stage);
1394 glEnableClientState(GL_TEXTURE_COORD_ARRAY);
1395 glTexCoordPointer(2, GL_FLOAT, lpD3DDrawPrimStrideData->textureCoords[tex_index].dwStride,
1396 lpD3DDrawPrimStrideData->textureCoords[tex_index].lpvData);
1398 if (dwIndices != NULL) {
1399 glDrawElements(convert_D3D_ptype_to_GL(d3dptPrimitiveType), dwIndexCount, GL_UNSIGNED_SHORT, dwIndices);
1401 glDrawArrays(convert_D3D_ptype_to_GL(d3dptPrimitiveType), 0, dwIndexCount);
1403 glDisableClientState(GL_VERTEX_ARRAY);
1404 if (d3dvtVertexType & D3DFVF_NORMAL) {
1405 glDisableClientState(GL_NORMAL_ARRAY);
1407 if (d3dvtVertexType & D3DFVF_DIFFUSE) {
1408 glDisableClientState(GL_COLOR_ARRAY);
1410 for (tex_stage = 0; tex_stage < num_active_stages; tex_stage++) {
1411 if (GL_extensions.glClientActiveTexture) {
1412 GL_extensions.glClientActiveTexture(GL_TEXTURE0_WINE + tex_stage);
1414 glDisableClientState(GL_TEXTURE_COORD_ARRAY);
1417 glBegin(convert_D3D_ptype_to_GL(d3dptPrimitiveType));
1419 /* Some fast paths first before the generic case.... */
1420 if ((d3dvtVertexType == D3DFVF_VERTEX) && (num_active_stages <= 1)) {
1423 for (index = 0; index < dwIndexCount; index++) {
1424 int i = (dwIndices == NULL) ? index : dwIndices[index];
1426 (D3DVALUE *) (((char *) lpD3DDrawPrimStrideData->normal.lpvData) + i * lpD3DDrawPrimStrideData->normal.dwStride);
1427 D3DVALUE *tex_coord =
1428 (D3DVALUE *) (((char *) lpD3DDrawPrimStrideData->textureCoords[0].lpvData) + i * lpD3DDrawPrimStrideData->textureCoords[0].dwStride);
1429 D3DVALUE *position =
1430 (D3DVALUE *) (((char *) lpD3DDrawPrimStrideData->position.lpvData) + i * lpD3DDrawPrimStrideData->position.dwStride);
1432 handle_normal(normal);
1433 handle_texture(tex_coord);
1434 handle_xyz(position);
1436 TRACE_(ddraw_geom)(" %f %f %f / %f %f %f (%f %f)\n",
1437 position[0], position[1], position[2],
1438 normal[0], normal[1], normal[2],
1439 tex_coord[0], tex_coord[1]);
1441 } else if ((d3dvtVertexType == D3DFVF_TLVERTEX) && (num_active_stages <= 1)) {
1444 for (index = 0; index < dwIndexCount; index++) {
1445 int i = (dwIndices == NULL) ? index : dwIndices[index];
1447 (DWORD *) (((char *) lpD3DDrawPrimStrideData->diffuse.lpvData) + i * lpD3DDrawPrimStrideData->diffuse.dwStride);
1449 (DWORD *) (((char *) lpD3DDrawPrimStrideData->specular.lpvData) + i * lpD3DDrawPrimStrideData->specular.dwStride);
1450 D3DVALUE *tex_coord =
1451 (D3DVALUE *) (((char *) lpD3DDrawPrimStrideData->textureCoords[0].lpvData) + i * lpD3DDrawPrimStrideData->textureCoords[0].dwStride);
1452 D3DVALUE *position =
1453 (D3DVALUE *) (((char *) lpD3DDrawPrimStrideData->position.lpvData) + i * lpD3DDrawPrimStrideData->position.dwStride);
1455 handle_diffuse_and_specular(&(This->state_block), glThis->fog_table, color_d, color_s, TRUE);
1456 handle_texture(tex_coord);
1457 handle_xyzrhw(position);
1459 TRACE_(ddraw_geom)(" %f %f %f %f / %02lx %02lx %02lx %02lx - %02lx %02lx %02lx %02lx (%f %f)\n",
1460 position[0], position[1], position[2], position[3],
1461 (*color_d >> 16) & 0xFF,
1462 (*color_d >> 8) & 0xFF,
1463 (*color_d >> 0) & 0xFF,
1464 (*color_d >> 24) & 0xFF,
1465 (*color_s >> 16) & 0xFF,
1466 (*color_s >> 8) & 0xFF,
1467 (*color_s >> 0) & 0xFF,
1468 (*color_s >> 24) & 0xFF,
1469 tex_coord[0], tex_coord[1]);
1471 } else if (((d3dvtVertexType & D3DFVF_POSITION_MASK) == D3DFVF_XYZ) ||
1472 ((d3dvtVertexType & D3DFVF_POSITION_MASK) == D3DFVF_XYZRHW)) {
1473 /* This is the 'slow path' but that should support all possible vertex formats out there...
1474 Note that people should write a fast path for all vertex formats out there...
1477 static const D3DVALUE no_index[] = { 0.0, 0.0, 0.0, 0.0 };
1479 for (index = 0; index < dwIndexCount; index++) {
1480 int i = (dwIndices == NULL) ? index : dwIndices[index];
1483 if (d3dvtVertexType & D3DFVF_NORMAL) {
1485 (D3DVALUE *) (((char *) lpD3DDrawPrimStrideData->normal.lpvData) + i * lpD3DDrawPrimStrideData->normal.dwStride);
1486 handle_normal(normal);
1488 if ((d3dvtVertexType & (D3DFVF_DIFFUSE|D3DFVF_SPECULAR)) == (D3DFVF_DIFFUSE|D3DFVF_SPECULAR)) {
1490 (DWORD *) (((char *) lpD3DDrawPrimStrideData->diffuse.lpvData) + i * lpD3DDrawPrimStrideData->diffuse.dwStride);
1492 (DWORD *) (((char *) lpD3DDrawPrimStrideData->specular.lpvData) + i * lpD3DDrawPrimStrideData->specular.dwStride);
1493 handle_diffuse_and_specular(&(This->state_block), glThis->fog_table, color_d, color_s, vertex_lighted);
1495 if (d3dvtVertexType & D3DFVF_SPECULAR) {
1497 (DWORD *) (((char *) lpD3DDrawPrimStrideData->specular.lpvData) + i * lpD3DDrawPrimStrideData->specular.dwStride);
1498 handle_specular(&(This->state_block), color_s, vertex_lighted);
1499 } else if (d3dvtVertexType & D3DFVF_DIFFUSE) {
1501 (DWORD *) (((char *) lpD3DDrawPrimStrideData->diffuse.lpvData) + i * lpD3DDrawPrimStrideData->diffuse.dwStride);
1502 handle_diffuse(&(This->state_block), color_d, vertex_lighted);
1506 for (tex_stage = 0; tex_stage < num_active_stages; tex_stage++) {
1507 int tex_index = This->state_block.texture_stage_state[tex_stage][D3DTSS_TEXCOORDINDEX - 1] & 0x0000FFFF;
1508 if (tex_index >= num_tex_index) {
1509 handle_textures((D3DVALUE *) no_index, tex_stage);
1511 D3DVALUE *tex_coord =
1512 (D3DVALUE *) (((char *) lpD3DDrawPrimStrideData->textureCoords[tex_index].lpvData) +
1513 i * lpD3DDrawPrimStrideData->textureCoords[tex_index].dwStride);
1514 handle_textures(tex_coord, tex_stage);
1518 if ((d3dvtVertexType & D3DFVF_POSITION_MASK) == D3DFVF_XYZ) {
1519 D3DVALUE *position =
1520 (D3DVALUE *) (((char *) lpD3DDrawPrimStrideData->position.lpvData) + i * lpD3DDrawPrimStrideData->position.dwStride);
1521 handle_xyz(position);
1522 } else if ((d3dvtVertexType & D3DFVF_POSITION_MASK) == D3DFVF_XYZRHW) {
1523 D3DVALUE *position =
1524 (D3DVALUE *) (((char *) lpD3DDrawPrimStrideData->position.lpvData) + i * lpD3DDrawPrimStrideData->position.dwStride);
1525 handle_xyzrhw(position);
1528 if (TRACE_ON(ddraw_geom)) {
1531 if ((d3dvtVertexType & D3DFVF_POSITION_MASK) == D3DFVF_XYZ) {
1532 D3DVALUE *position =
1533 (D3DVALUE *) (((char *) lpD3DDrawPrimStrideData->position.lpvData) + i * lpD3DDrawPrimStrideData->position.dwStride);
1534 TRACE_(ddraw_geom)(" %f %f %f", position[0], position[1], position[2]);
1535 } else if ((d3dvtVertexType & D3DFVF_POSITION_MASK) == D3DFVF_XYZRHW) {
1536 D3DVALUE *position =
1537 (D3DVALUE *) (((char *) lpD3DDrawPrimStrideData->position.lpvData) + i * lpD3DDrawPrimStrideData->position.dwStride);
1538 TRACE_(ddraw_geom)(" %f %f %f %f", position[0], position[1], position[2], position[3]);
1540 if (d3dvtVertexType & D3DFVF_NORMAL) {
1542 (D3DVALUE *) (((char *) lpD3DDrawPrimStrideData->normal.lpvData) + i * lpD3DDrawPrimStrideData->normal.dwStride);
1543 TRACE_(ddraw_geom)(" / %f %f %f", normal[0], normal[1], normal[2]);
1545 if (d3dvtVertexType & D3DFVF_DIFFUSE) {
1547 (DWORD *) (((char *) lpD3DDrawPrimStrideData->diffuse.lpvData) + i * lpD3DDrawPrimStrideData->diffuse.dwStride);
1548 TRACE_(ddraw_geom)(" / %02lx %02lx %02lx %02lx",
1549 (*color_d >> 16) & 0xFF,
1550 (*color_d >> 8) & 0xFF,
1551 (*color_d >> 0) & 0xFF,
1552 (*color_d >> 24) & 0xFF);
1554 if (d3dvtVertexType & D3DFVF_SPECULAR) {
1556 (DWORD *) (((char *) lpD3DDrawPrimStrideData->specular.lpvData) + i * lpD3DDrawPrimStrideData->specular.dwStride);
1557 TRACE_(ddraw_geom)(" / %02lx %02lx %02lx %02lx",
1558 (*color_s >> 16) & 0xFF,
1559 (*color_s >> 8) & 0xFF,
1560 (*color_s >> 0) & 0xFF,
1561 (*color_s >> 24) & 0xFF);
1563 for (tex_index = 0; tex_index < ((d3dvtVertexType & D3DFVF_TEXCOUNT_MASK) >> D3DFVF_TEXCOUNT_SHIFT); tex_index++) {
1564 D3DVALUE *tex_coord =
1565 (D3DVALUE *) (((char *) lpD3DDrawPrimStrideData->textureCoords[tex_index].lpvData) +
1566 i * lpD3DDrawPrimStrideData->textureCoords[tex_index].dwStride);
1567 TRACE_(ddraw_geom)(" / %f %f", tex_coord[0], tex_coord[1]);
1569 TRACE_(ddraw_geom)("\n");
1573 ERR(" matrix weighting not handled yet....\n");
1579 /* Whatever the case, disable the color material stuff */
1580 glDisable(GL_COLOR_MATERIAL);
1585 LeaveCriticalSection(&(This->crit));
1589 GL_IDirect3DDeviceImpl_7_3T_DrawPrimitive(LPDIRECT3DDEVICE7 iface,
1590 D3DPRIMITIVETYPE d3dptPrimitiveType,
1591 DWORD d3dvtVertexType,
1593 DWORD dwVertexCount,
1596 ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice7, iface);
1597 D3DDRAWPRIMITIVESTRIDEDDATA strided;
1599 TRACE("(%p/%p)->(%08x,%08lx,%p,%08lx,%08lx)\n", This, iface, d3dptPrimitiveType, d3dvtVertexType, lpvVertices, dwVertexCount, dwFlags);
1600 if (TRACE_ON(ddraw)) {
1601 TRACE(" - flags : "); dump_DPFLAGS(dwFlags);
1604 convert_FVF_to_strided_data(d3dvtVertexType, lpvVertices, &strided, 0);
1605 draw_primitive_strided(This, d3dptPrimitiveType, d3dvtVertexType, &strided, dwVertexCount, NULL, dwVertexCount, dwFlags);
1611 GL_IDirect3DDeviceImpl_7_3T_DrawIndexedPrimitive(LPDIRECT3DDEVICE7 iface,
1612 D3DPRIMITIVETYPE d3dptPrimitiveType,
1613 DWORD d3dvtVertexType,
1615 DWORD dwVertexCount,
1620 ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice7, iface);
1621 D3DDRAWPRIMITIVESTRIDEDDATA strided;
1623 TRACE("(%p/%p)->(%08x,%08lx,%p,%08lx,%p,%08lx,%08lx)\n", This, iface, d3dptPrimitiveType, d3dvtVertexType, lpvVertices, dwVertexCount, dwIndices, dwIndexCount, dwFlags);
1624 if (TRACE_ON(ddraw)) {
1625 TRACE(" - flags : "); dump_DPFLAGS(dwFlags);
1628 convert_FVF_to_strided_data(d3dvtVertexType, lpvVertices, &strided, 0);
1629 draw_primitive_strided(This, d3dptPrimitiveType, d3dvtVertexType, &strided, dwVertexCount, dwIndices, dwIndexCount, dwFlags);
1635 GL_IDirect3DDeviceImpl_7_3T_DrawPrimitiveStrided(LPDIRECT3DDEVICE7 iface,
1636 D3DPRIMITIVETYPE d3dptPrimitiveType,
1638 LPD3DDRAWPRIMITIVESTRIDEDDATA lpD3DDrawPrimStrideData,
1639 DWORD dwVertexCount,
1642 ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice7, iface);
1644 TRACE("(%p/%p)->(%08x,%08lx,%p,%08lx,%08lx)\n", This, iface, d3dptPrimitiveType, dwVertexType, lpD3DDrawPrimStrideData, dwVertexCount, dwFlags);
1645 if (TRACE_ON(ddraw)) {
1646 TRACE(" - flags : "); dump_DPFLAGS(dwFlags);
1648 draw_primitive_strided(This, d3dptPrimitiveType, dwVertexType, lpD3DDrawPrimStrideData, dwVertexCount, NULL, dwVertexCount, dwFlags);
1654 GL_IDirect3DDeviceImpl_7_3T_DrawIndexedPrimitiveStrided(LPDIRECT3DDEVICE7 iface,
1655 D3DPRIMITIVETYPE d3dptPrimitiveType,
1657 LPD3DDRAWPRIMITIVESTRIDEDDATA lpD3DDrawPrimStrideData,
1658 DWORD dwVertexCount,
1663 ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice7, iface);
1665 TRACE("(%p/%p)->(%08x,%08lx,%p,%08lx,%p,%08lx,%08lx)\n", This, iface, d3dptPrimitiveType, dwVertexType, lpD3DDrawPrimStrideData, dwVertexCount, lpIndex, dwIndexCount, dwFlags);
1666 if (TRACE_ON(ddraw)) {
1667 TRACE(" - flags : "); dump_DPFLAGS(dwFlags);
1670 draw_primitive_strided(This, d3dptPrimitiveType, dwVertexType, lpD3DDrawPrimStrideData, dwVertexCount, lpIndex, dwIndexCount, dwFlags);
1676 GL_IDirect3DDeviceImpl_7_3T_DrawPrimitiveVB(LPDIRECT3DDEVICE7 iface,
1677 D3DPRIMITIVETYPE d3dptPrimitiveType,
1678 LPDIRECT3DVERTEXBUFFER7 lpD3DVertexBuf,
1679 DWORD dwStartVertex,
1680 DWORD dwNumVertices,
1683 ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice7, iface);
1684 IDirect3DVertexBufferImpl *vb_impl = ICOM_OBJECT(IDirect3DVertexBufferImpl, IDirect3DVertexBuffer7, lpD3DVertexBuf);
1685 D3DDRAWPRIMITIVESTRIDEDDATA strided;
1687 TRACE("(%p/%p)->(%08x,%p,%08lx,%08lx,%08lx)\n", This, iface, d3dptPrimitiveType, lpD3DVertexBuf, dwStartVertex, dwNumVertices, dwFlags);
1688 if (TRACE_ON(ddraw)) {
1689 TRACE(" - flags : "); dump_DPFLAGS(dwFlags);
1692 if (vb_impl->processed == TRUE) {
1693 IDirect3DVertexBufferGLImpl *vb_glimp = (IDirect3DVertexBufferGLImpl *) vb_impl;
1694 IDirect3DDeviceGLImpl *glThis = (IDirect3DDeviceGLImpl *) This;
1696 glThis->transform_state = GL_TRANSFORM_VERTEXBUFFER;
1697 This->set_matrices(This, VIEWMAT_CHANGED|WORLDMAT_CHANGED|PROJMAT_CHANGED,
1698 &(vb_glimp->world_mat), &(vb_glimp->view_mat), &(vb_glimp->proj_mat));
1700 convert_FVF_to_strided_data(vb_glimp->dwVertexTypeDesc, vb_glimp->vertices, &strided, dwStartVertex);
1701 draw_primitive_strided(This, d3dptPrimitiveType, vb_glimp->dwVertexTypeDesc, &strided, dwNumVertices, NULL, dwNumVertices, dwFlags);
1704 convert_FVF_to_strided_data(vb_impl->desc.dwFVF, vb_impl->vertices, &strided, dwStartVertex);
1705 draw_primitive_strided(This, d3dptPrimitiveType, vb_impl->desc.dwFVF, &strided, dwNumVertices, NULL, dwNumVertices, dwFlags);
1712 GL_IDirect3DDeviceImpl_7_3T_DrawIndexedPrimitiveVB(LPDIRECT3DDEVICE7 iface,
1713 D3DPRIMITIVETYPE d3dptPrimitiveType,
1714 LPDIRECT3DVERTEXBUFFER7 lpD3DVertexBuf,
1715 DWORD dwStartVertex,
1716 DWORD dwNumVertices,
1721 ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice7, iface);
1722 IDirect3DVertexBufferImpl *vb_impl = ICOM_OBJECT(IDirect3DVertexBufferImpl, IDirect3DVertexBuffer7, lpD3DVertexBuf);
1723 D3DDRAWPRIMITIVESTRIDEDDATA strided;
1725 TRACE("(%p/%p)->(%08x,%p,%08lx,%08lx,%p,%08lx,%08lx)\n", This, iface, d3dptPrimitiveType, lpD3DVertexBuf, dwStartVertex, dwNumVertices, lpwIndices, dwIndexCount, dwFlags);
1726 if (TRACE_ON(ddraw)) {
1727 TRACE(" - flags : "); dump_DPFLAGS(dwFlags);
1730 if (vb_impl->processed == TRUE) {
1731 IDirect3DVertexBufferGLImpl *vb_glimp = (IDirect3DVertexBufferGLImpl *) vb_impl;
1732 IDirect3DDeviceGLImpl *glThis = (IDirect3DDeviceGLImpl *) This;
1734 glThis->transform_state = GL_TRANSFORM_VERTEXBUFFER;
1735 This->set_matrices(This, VIEWMAT_CHANGED|WORLDMAT_CHANGED|PROJMAT_CHANGED,
1736 &(vb_glimp->world_mat), &(vb_glimp->view_mat), &(vb_glimp->proj_mat));
1738 convert_FVF_to_strided_data(vb_glimp->dwVertexTypeDesc, vb_glimp->vertices, &strided, dwStartVertex);
1739 draw_primitive_strided(This, d3dptPrimitiveType, vb_glimp->dwVertexTypeDesc, &strided, dwNumVertices, lpwIndices, dwIndexCount, dwFlags);
1742 convert_FVF_to_strided_data(vb_impl->desc.dwFVF, vb_impl->vertices, &strided, dwStartVertex);
1743 draw_primitive_strided(This, d3dptPrimitiveType, vb_impl->desc.dwFVF, &strided, dwNumVertices, lpwIndices, dwIndexCount, dwFlags);
1749 /* We need a static function for that to handle the 'special' case of 'SELECT_ARG2' */
1751 handle_color_alpha_args(IDirect3DDeviceImpl *This, DWORD dwStage, D3DTEXTURESTAGESTATETYPE d3dTexStageStateType, DWORD dwState, D3DTEXTUREOP tex_op)
1753 BOOLEAN is_complement = FALSE;
1754 BOOLEAN is_alpha_replicate = FALSE;
1755 BOOLEAN handled = TRUE;
1757 BOOLEAN is_color = ((d3dTexStageStateType == D3DTSS_COLORARG1) || (d3dTexStageStateType == D3DTSS_COLORARG2));
1761 if (d3dTexStageStateType == D3DTSS_COLORARG1) num = 0;
1762 else if (d3dTexStageStateType == D3DTSS_COLORARG2) num = 1;
1767 if (tex_op == D3DTOP_SELECTARG2) {
1771 if (d3dTexStageStateType == D3DTSS_ALPHAARG1) num = 0;
1772 else if (d3dTexStageStateType == D3DTSS_ALPHAARG2) num = 1;
1777 if (tex_op == D3DTOP_SELECTARG2) {
1782 if (dwState & D3DTA_COMPLEMENT) {
1783 is_complement = TRUE;
1785 if (dwState & D3DTA_ALPHAREPLICATE) {
1786 is_alpha_replicate = TRUE;
1788 dwState &= D3DTA_SELECTMASK;
1789 if ((dwStage == 0) && (dwState == D3DTA_CURRENT)) {
1790 dwState = D3DTA_DIFFUSE;
1794 case D3DTA_CURRENT: src = GL_PREVIOUS_EXT; break;
1795 case D3DTA_DIFFUSE: src = GL_PRIMARY_COLOR_EXT; break;
1796 case D3DTA_TEXTURE: src = GL_TEXTURE; break;
1797 case D3DTA_TFACTOR: {
1798 /* Get the constant value from the current rendering state */
1800 DWORD col = This->state_block.render_state[D3DRENDERSTATE_TEXTUREFACTOR - 1];
1802 color[0] = ((col >> 16) & 0xFF) / 255.0f;
1803 color[1] = ((col >> 8) & 0xFF) / 255.0f;
1804 color[2] = ((col >> 0) & 0xFF) / 255.0f;
1805 color[3] = ((col >> 24) & 0xFF) / 255.0f;
1806 glTexEnvfv(GL_TEXTURE_ENV, GL_TEXTURE_ENV_COLOR, color);
1808 src = GL_CONSTANT_EXT;
1810 default: src = GL_TEXTURE; handled = FALSE; break;
1814 glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_RGB_EXT + num, src);
1815 if (is_alpha_replicate) {
1816 glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND0_RGB_EXT + num, is_complement ? GL_ONE_MINUS_SRC_ALPHA : GL_SRC_ALPHA);
1818 glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND0_RGB_EXT + num, is_complement ? GL_ONE_MINUS_SRC_COLOR : GL_SRC_COLOR);
1821 glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_ALPHA_EXT + num, src);
1822 glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND0_ALPHA_EXT + num, is_complement ? GL_ONE_MINUS_SRC_ALPHA : GL_SRC_ALPHA);
1829 GL_IDirect3DDeviceImpl_7_3T_SetTextureStageState(LPDIRECT3DDEVICE7 iface,
1831 D3DTEXTURESTAGESTATETYPE d3dTexStageStateType,
1834 ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice7, iface);
1835 IDirect3DDeviceGLImpl *glThis = (IDirect3DDeviceGLImpl *) This;
1840 TRACE("(%p/%p)->(%08lx,%08x,%08lx)\n", This, iface, dwStage, d3dTexStageStateType, dwState);
1842 if (((GL_extensions.max_texture_units == 0) && (dwStage > 0)) ||
1843 ((GL_extensions.max_texture_units != 0) && (dwStage >= GL_extensions.max_texture_units))) {
1847 unit = GL_TEXTURE0_WINE + dwStage;
1848 if (unit != glThis->current_active_tex_unit) {
1849 GL_extensions.glActiveTexture(unit);
1850 glThis->current_active_tex_unit = unit;
1853 switch (d3dTexStageStateType) {
1854 #define GEN_CASE(a) case a: type = #a; break
1855 GEN_CASE(D3DTSS_COLOROP);
1856 GEN_CASE(D3DTSS_COLORARG1);
1857 GEN_CASE(D3DTSS_COLORARG2);
1858 GEN_CASE(D3DTSS_ALPHAOP);
1859 GEN_CASE(D3DTSS_ALPHAARG1);
1860 GEN_CASE(D3DTSS_ALPHAARG2);
1861 GEN_CASE(D3DTSS_BUMPENVMAT00);
1862 GEN_CASE(D3DTSS_BUMPENVMAT01);
1863 GEN_CASE(D3DTSS_BUMPENVMAT10);
1864 GEN_CASE(D3DTSS_BUMPENVMAT11);
1865 GEN_CASE(D3DTSS_TEXCOORDINDEX);
1866 GEN_CASE(D3DTSS_ADDRESS);
1867 GEN_CASE(D3DTSS_ADDRESSU);
1868 GEN_CASE(D3DTSS_ADDRESSV);
1869 GEN_CASE(D3DTSS_BORDERCOLOR);
1870 GEN_CASE(D3DTSS_MAGFILTER);
1871 GEN_CASE(D3DTSS_MINFILTER);
1872 GEN_CASE(D3DTSS_MIPFILTER);
1873 GEN_CASE(D3DTSS_MIPMAPLODBIAS);
1874 GEN_CASE(D3DTSS_MAXMIPLEVEL);
1875 GEN_CASE(D3DTSS_MAXANISOTROPY);
1876 GEN_CASE(D3DTSS_BUMPENVLSCALE);
1877 GEN_CASE(D3DTSS_BUMPENVLOFFSET);
1878 GEN_CASE(D3DTSS_TEXTURETRANSFORMFLAGS);
1880 default: type = "UNKNOWN";
1883 /* Store the values in the state array */
1884 prev_state = This->state_block.texture_stage_state[dwStage][d3dTexStageStateType - 1];
1885 This->state_block.texture_stage_state[dwStage][d3dTexStageStateType - 1] = dwState;
1886 /* Some special cases when one state modifies more than one... */
1887 if (d3dTexStageStateType == D3DTSS_ADDRESS) {
1888 This->state_block.texture_stage_state[dwStage][D3DTSS_ADDRESSU - 1] = dwState;
1889 This->state_block.texture_stage_state[dwStage][D3DTSS_ADDRESSV - 1] = dwState;
1894 switch (d3dTexStageStateType) {
1895 case D3DTSS_MINFILTER:
1896 case D3DTSS_MIPFILTER:
1897 if (TRACE_ON(ddraw)) {
1898 if (d3dTexStageStateType == D3DTSS_MINFILTER) {
1899 switch ((D3DTEXTUREMINFILTER) dwState) {
1900 case D3DTFN_POINT: TRACE(" Stage type is : D3DTSS_MINFILTER => D3DTFN_POINT\n"); break;
1901 case D3DTFN_LINEAR: TRACE(" Stage type is : D3DTSS_MINFILTER => D3DTFN_LINEAR\n"); break;
1902 default: FIXME(" Unhandled stage type : D3DTSS_MINFILTER => %08lx\n", dwState); break;
1905 switch ((D3DTEXTUREMIPFILTER) dwState) {
1906 case D3DTFP_NONE: TRACE(" Stage type is : D3DTSS_MIPFILTER => D3DTFP_NONE\n"); break;
1907 case D3DTFP_POINT: TRACE(" Stage type is : D3DTSS_MIPFILTER => D3DTFP_POINT\n"); break;
1908 case D3DTFP_LINEAR: TRACE(" Stage type is : D3DTSS_MIPFILTER => D3DTFP_LINEAR\n"); break;
1909 default: FIXME(" Unhandled stage type : D3DTSS_MIPFILTER => %08lx\n", dwState); break;
1915 case D3DTSS_MAGFILTER:
1916 if (TRACE_ON(ddraw)) {
1917 switch ((D3DTEXTUREMAGFILTER) dwState) {
1918 case D3DTFG_POINT: TRACE(" Stage type is : D3DTSS_MAGFILTER => D3DTFG_POINT\n"); break;
1919 case D3DTFG_LINEAR: TRACE(" Stage type is : D3DTSS_MAGFILTER => D3DTFG_LINEAR\n"); break;
1920 default: FIXME(" Unhandled stage type : D3DTSS_MAGFILTER => %08lx\n", dwState); break;
1925 case D3DTSS_ADDRESS:
1926 case D3DTSS_ADDRESSU:
1927 case D3DTSS_ADDRESSV: {
1928 switch ((D3DTEXTUREADDRESS) dwState) {
1929 case D3DTADDRESS_WRAP: TRACE(" Stage type is : %s => D3DTADDRESS_WRAP\n", type); break;
1930 case D3DTADDRESS_CLAMP: TRACE(" Stage type is : %s => D3DTADDRESS_CLAMP\n", type); break;
1931 case D3DTADDRESS_BORDER: TRACE(" Stage type is : %s => D3DTADDRESS_BORDER\n", type); break;
1932 case D3DTADDRESS_MIRROR:
1933 if (GL_extensions.mirrored_repeat == TRUE) {
1934 TRACE(" Stage type is : %s => D3DTADDRESS_MIRROR\n", type);
1936 FIXME(" Stage type is : %s => D3DTADDRESS_MIRROR - not supported by GL !\n", type);
1939 default: FIXME(" Unhandled stage type : %s => %08lx\n", type, dwState); break;
1943 case D3DTSS_ALPHAOP:
1944 case D3DTSS_COLOROP: {
1946 GLenum parm = (d3dTexStageStateType == D3DTSS_ALPHAOP) ? GL_COMBINE_ALPHA_EXT : GL_COMBINE_RGB_EXT;
1951 #define GEN_CASE(a) case a: value = #a; break
1952 GEN_CASE(D3DTOP_DISABLE);
1953 GEN_CASE(D3DTOP_SELECTARG1);
1954 GEN_CASE(D3DTOP_SELECTARG2);
1955 GEN_CASE(D3DTOP_MODULATE);
1956 GEN_CASE(D3DTOP_MODULATE2X);
1957 GEN_CASE(D3DTOP_MODULATE4X);
1958 GEN_CASE(D3DTOP_ADD);
1959 GEN_CASE(D3DTOP_ADDSIGNED);
1960 GEN_CASE(D3DTOP_ADDSIGNED2X);
1961 GEN_CASE(D3DTOP_SUBTRACT);
1962 GEN_CASE(D3DTOP_ADDSMOOTH);
1963 GEN_CASE(D3DTOP_BLENDDIFFUSEALPHA);
1964 GEN_CASE(D3DTOP_BLENDTEXTUREALPHA);
1965 GEN_CASE(D3DTOP_BLENDFACTORALPHA);
1966 GEN_CASE(D3DTOP_BLENDTEXTUREALPHAPM);
1967 GEN_CASE(D3DTOP_BLENDCURRENTALPHA);
1968 GEN_CASE(D3DTOP_PREMODULATE);
1969 GEN_CASE(D3DTOP_MODULATEALPHA_ADDCOLOR);
1970 GEN_CASE(D3DTOP_MODULATECOLOR_ADDALPHA);
1971 GEN_CASE(D3DTOP_MODULATEINVALPHA_ADDCOLOR);
1972 GEN_CASE(D3DTOP_MODULATEINVCOLOR_ADDALPHA);
1973 GEN_CASE(D3DTOP_BUMPENVMAP);
1974 GEN_CASE(D3DTOP_BUMPENVMAPLUMINANCE);
1975 GEN_CASE(D3DTOP_DOTPRODUCT3);
1976 GEN_CASE(D3DTOP_FORCE_DWORD);
1978 default: value = "UNKNOWN";
1981 if ((d3dTexStageStateType == D3DTSS_COLOROP) && (dwState == D3DTOP_DISABLE)) {
1982 glDisable(GL_TEXTURE_2D);
1983 TRACE(" disabling 2D texturing.\n");
1985 /* Re-enable texturing only if COLOROP was not already disabled... */
1986 if ((glThis->current_bound_texture[dwStage] != NULL) &&
1987 (This->state_block.texture_stage_state[dwStage][D3DTSS_COLOROP - 1] != D3DTOP_DISABLE)) {
1988 glEnable(GL_TEXTURE_2D);
1989 TRACE(" enabling 2D texturing.\n");
1992 /* Re-Enable GL_TEXTURE_ENV_MODE, GL_COMBINE_EXT */
1993 if ((dwState != D3DTOP_DISABLE) &&
1994 (This->state_block.texture_stage_state[dwStage][D3DTSS_COLOROP - 1] != D3DTOP_DISABLE)) {
1995 if (glThis->current_tex_env != GL_COMBINE_EXT) {
1996 glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE_EXT);
1997 glThis->current_tex_env = GL_COMBINE_EXT;
2001 /* Now set up the operand correctly */
2003 case D3DTOP_DISABLE:
2004 /* Contrary to the docs, alpha can be disabled when colorop is enabled
2005 and it works, so ignore this op */
2006 TRACE(" Note : disable ALPHAOP but COLOROP enabled!\n");
2009 case D3DTOP_SELECTARG1:
2010 case D3DTOP_SELECTARG2:
2011 glTexEnvi(GL_TEXTURE_ENV, parm, GL_REPLACE);
2014 case D3DTOP_MODULATE4X:
2015 scale = scale * 2; /* Drop through */
2016 case D3DTOP_MODULATE2X:
2017 scale = scale * 2; /* Drop through */
2018 case D3DTOP_MODULATE:
2019 glTexEnvi(GL_TEXTURE_ENV, parm, GL_MODULATE);
2023 glTexEnvi(GL_TEXTURE_ENV, parm, GL_ADD);
2026 case D3DTOP_ADDSIGNED2X:
2027 scale = scale * 2; /* Drop through */
2028 case D3DTOP_ADDSIGNED:
2029 glTexEnvi(GL_TEXTURE_ENV, parm, GL_ADD_SIGNED_EXT);
2032 /* For the four blending modes, use the Arg2 parameter */
2033 case D3DTOP_BLENDDIFFUSEALPHA:
2034 case D3DTOP_BLENDTEXTUREALPHA:
2035 case D3DTOP_BLENDFACTORALPHA:
2036 case D3DTOP_BLENDCURRENTALPHA: {
2037 GLenum src = GL_PRIMARY_COLOR_EXT; /* Just to prevent a compiler warning.. */
2040 case D3DTOP_BLENDDIFFUSEALPHA: src = GL_PRIMARY_COLOR_EXT;
2041 case D3DTOP_BLENDTEXTUREALPHA: src = GL_TEXTURE;
2042 case D3DTOP_BLENDFACTORALPHA: src = GL_CONSTANT_EXT;
2043 case D3DTOP_BLENDCURRENTALPHA: src = GL_PREVIOUS_EXT;
2046 glTexEnvi(GL_TEXTURE_ENV, parm, GL_INTERPOLATE_EXT);
2047 glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE2_RGB_EXT, src);
2048 glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND2_RGB_EXT, GL_SRC_ALPHA);
2049 glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE2_ALPHA_EXT, src);
2050 glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND2_ALPHA_EXT, GL_SRC_ALPHA);
2059 if (((prev_state == D3DTOP_SELECTARG2) && (dwState != D3DTOP_SELECTARG2)) ||
2060 ((dwState == D3DTOP_SELECTARG2) && (prev_state != D3DTOP_SELECTARG2))) {
2061 /* Switch the arguments if needed... */
2062 if (d3dTexStageStateType == D3DTSS_COLOROP) {
2063 handle_color_alpha_args(This, dwStage, D3DTSS_COLORARG1,
2064 This->state_block.texture_stage_state[dwStage][D3DTSS_COLORARG1 - 1],
2066 handle_color_alpha_args(This, dwStage, D3DTSS_COLORARG2,
2067 This->state_block.texture_stage_state[dwStage][D3DTSS_COLORARG2 - 1],
2070 handle_color_alpha_args(This, dwStage, D3DTSS_ALPHAARG1,
2071 This->state_block.texture_stage_state[dwStage][D3DTSS_ALPHAARG1 - 1],
2073 handle_color_alpha_args(This, dwStage, D3DTSS_ALPHAARG2,
2074 This->state_block.texture_stage_state[dwStage][D3DTSS_ALPHAARG2 - 1],
2080 if (d3dTexStageStateType == D3DTSS_ALPHAOP) {
2081 glTexEnvi(GL_TEXTURE_ENV, GL_ALPHA_SCALE, scale);
2083 glTexEnvi(GL_TEXTURE_ENV, GL_RGB_SCALE_EXT, scale);
2085 TRACE(" Stage type is : %s => %s\n", type, value);
2087 FIXME(" Unhandled stage type is : %s => %s\n", type, value);
2091 case D3DTSS_COLORARG1:
2092 case D3DTSS_COLORARG2:
2093 case D3DTSS_ALPHAARG1:
2094 case D3DTSS_ALPHAARG2: {
2095 const char *value, *value_comp = "", *value_alpha = "";
2097 D3DTEXTUREOP tex_op;
2099 switch (dwState & D3DTA_SELECTMASK) {
2100 #define GEN_CASE(a) case a: value = #a; break
2101 GEN_CASE(D3DTA_DIFFUSE);
2102 GEN_CASE(D3DTA_CURRENT);
2103 GEN_CASE(D3DTA_TEXTURE);
2104 GEN_CASE(D3DTA_TFACTOR);
2105 GEN_CASE(D3DTA_SPECULAR);
2107 default: value = "UNKNOWN";
2109 if (dwState & D3DTA_COMPLEMENT) {
2110 value_comp = " | D3DTA_COMPLEMENT";
2112 if (dwState & D3DTA_ALPHAREPLICATE) {
2113 value_alpha = " | D3DTA_ALPHAREPLICATE";
2116 if ((d3dTexStageStateType == D3DTSS_COLORARG1) || (d3dTexStageStateType == D3DTSS_COLORARG2)) {
2117 tex_op = This->state_block.texture_stage_state[dwStage][D3DTSS_COLOROP - 1];
2119 tex_op = This->state_block.texture_stage_state[dwStage][D3DTSS_ALPHAOP - 1];
2122 handled = handle_color_alpha_args(This, dwStage, d3dTexStageStateType, dwState, tex_op);
2125 TRACE(" Stage type : %s => %s%s%s\n", type, value, value_comp, value_alpha);
2127 FIXME(" Unhandled stage type : %s => %s%s%s\n", type, value, value_comp, value_alpha);
2131 case D3DTSS_MIPMAPLODBIAS: {
2132 D3DVALUE value = *((D3DVALUE *) &dwState);
2133 BOOLEAN handled = TRUE;
2135 if ((value != 0.0) && (GL_extensions.mipmap_lodbias == FALSE))
2139 TRACE(" Stage type : D3DTSS_MIPMAPLODBIAS => %f\n", value);
2140 glTexEnvf(GL_TEXTURE_FILTER_CONTROL_WINE, GL_TEXTURE_LOD_BIAS_WINE, value);
2142 FIXME(" Unhandled stage type : D3DTSS_MIPMAPLODBIAS => %f\n", value);
2146 case D3DTSS_MAXMIPLEVEL:
2147 TRACE(" Stage type : D3DTSS_MAXMIPLEVEL => %ld\n", dwState);
2150 case D3DTSS_BORDERCOLOR:
2151 TRACE(" Stage type : D3DTSS_BORDERCOLOR => %02lx %02lx %02lx %02lx (RGBA)\n",
2152 ((dwState >> 16) & 0xFF),
2153 ((dwState >> 8) & 0xFF),
2154 ((dwState >> 0) & 0xFF),
2155 ((dwState >> 24) & 0xFF));
2158 case D3DTSS_TEXCOORDINDEX: {
2159 BOOLEAN handled = TRUE;
2162 switch (dwState & 0xFFFF0000) {
2163 #define GEN_CASE(a) case a: value = #a; break
2164 GEN_CASE(D3DTSS_TCI_PASSTHRU);
2165 GEN_CASE(D3DTSS_TCI_CAMERASPACENORMAL);
2166 GEN_CASE(D3DTSS_TCI_CAMERASPACEPOSITION);
2167 GEN_CASE(D3DTSS_TCI_CAMERASPACEREFLECTIONVECTOR);
2169 default: value = "UNKNOWN";
2171 if ((dwState & 0xFFFF0000) != D3DTSS_TCI_PASSTHRU)
2175 TRACE(" Stage type : D3DTSS_TEXCOORDINDEX => %ld | %s\n", dwState & 0x0000FFFF, value);
2177 FIXME(" Unhandled stage type : D3DTSS_TEXCOORDINDEX => %ld | %s\n", dwState & 0x0000FFFF, value);
2181 case D3DTSS_TEXTURETRANSFORMFLAGS: {
2182 const char *projected = "", *value;
2183 BOOLEAN handled = TRUE;
2184 switch (dwState & 0xFF) {
2185 #define GEN_CASE(a) case a: value = #a; break
2186 GEN_CASE(D3DTTFF_DISABLE);
2187 GEN_CASE(D3DTTFF_COUNT1);
2188 GEN_CASE(D3DTTFF_COUNT2);
2189 GEN_CASE(D3DTTFF_COUNT3);
2190 GEN_CASE(D3DTTFF_COUNT4);
2192 default: value = "UNKNOWN";
2194 if (dwState & D3DTTFF_PROJECTED) {
2195 projected = " | D3DTTFF_PROJECTED";
2199 if ((dwState & 0xFF) != D3DTTFF_DISABLE) {
2200 This->matrices_updated(This, TEXMAT0_CHANGED << dwStage);
2203 if (handled == TRUE) {
2204 TRACE(" Stage type : D3DTSS_TEXTURETRANSFORMFLAGS => %s%s\n", value, projected);
2206 FIXME(" Unhandled stage type : D3DTSS_TEXTURETRANSFORMFLAGS => %s%s\n", value, projected);
2211 FIXME(" Unhandled stage type : %s => %08lx\n", type, dwState);
2221 draw_primitive_handle_textures(IDirect3DDeviceImpl *This)
2223 IDirect3DDeviceGLImpl *glThis = (IDirect3DDeviceGLImpl *) This;
2225 BOOLEAN enable_colorkey = FALSE;
2227 for (stage = 0; stage < MAX_TEXTURES; stage++) {
2228 IDirectDrawSurfaceImpl *surf_ptr = This->current_texture[stage];
2231 /* If this stage is disabled, no need to go further... */
2232 if (This->state_block.texture_stage_state[stage][D3DTSS_COLOROP - 1] == D3DTOP_DISABLE)
2235 /* First check if we need to bind any other texture for this stage */
2236 if (This->current_texture[stage] != glThis->current_bound_texture[stage]) {
2237 if (This->current_texture[stage] == NULL) {
2238 TRACE(" disabling 2D texturing for stage %ld.\n", stage);
2240 unit = GL_TEXTURE0_WINE + stage;
2241 if (unit != glThis->current_active_tex_unit) {
2242 GL_extensions.glActiveTexture(unit);
2243 glThis->current_active_tex_unit = unit;
2245 glBindTexture(GL_TEXTURE_2D, 0);
2246 glDisable(GL_TEXTURE_2D);
2248 GLenum tex_name = ((IDirect3DTextureGLImpl *) surf_ptr->tex_private)->tex_name;
2250 unit = GL_TEXTURE0_WINE + stage;
2251 if (unit != glThis->current_active_tex_unit) {
2252 GL_extensions.glActiveTexture(unit);
2253 glThis->current_active_tex_unit = unit;
2256 if (glThis->current_bound_texture[stage] == NULL) {
2257 if (This->state_block.texture_stage_state[stage][D3DTSS_COLOROP - 1] != D3DTOP_DISABLE) {
2258 TRACE(" enabling 2D texturing and");
2259 glEnable(GL_TEXTURE_2D);
2262 TRACE(" activating OpenGL texture id %d for stage %ld.\n", tex_name, stage);
2263 glBindTexture(GL_TEXTURE_2D, tex_name);
2266 glThis->current_bound_texture[stage] = This->current_texture[stage];
2268 if (glThis->current_bound_texture[stage] == NULL) {
2269 TRACE(" displaying without texturing activated for stage %ld.\n", stage);
2271 TRACE(" using already bound texture id %d for stage %ld.\n",
2272 ((IDirect3DTextureGLImpl *) (glThis->current_bound_texture[stage])->tex_private)->tex_name, stage);
2276 /* If no texure valid for this stage, go out of the loop */
2277 if (This->current_texture[stage] == NULL) break;
2279 /* Then check if we need to flush this texture to GL or not (ie did it change) ?.
2280 This will also update the various texture parameters if needed.
2282 gltex_upload_texture(surf_ptr, This, stage);
2284 /* And finally check for color-keying (only on first stage) */
2285 if (This->current_texture[stage]->surface_desc.dwFlags & DDSD_CKSRCBLT) {
2287 enable_colorkey = TRUE;
2289 static BOOL warn = FALSE;
2290 if (warn == FALSE) {
2292 WARN(" Surface has color keying on stage different from 0 (%ld) !", stage);
2297 enable_colorkey = FALSE;
2302 /* Apparently, whatever the state of BLEND, color keying is always activated for 'old' D3D versions */
2303 if (((This->state_block.render_state[D3DRENDERSTATE_COLORKEYENABLE - 1]) ||
2304 (glThis->version == 1)) &&
2305 (enable_colorkey)) {
2306 TRACE(" colorkey activated.\n");
2308 if (glThis->alpha_test == FALSE) {
2309 glEnable(GL_ALPHA_TEST);
2310 glThis->alpha_test = TRUE;
2312 if ((glThis->current_alpha_test_func != GL_NOTEQUAL) || (glThis->current_alpha_test_ref != 0.0)) {
2313 if (This->state_block.render_state[D3DRENDERSTATE_ALPHATESTENABLE - 1] == TRUE) {
2314 static BOOL warn = FALSE;
2315 if (warn == FALSE) {
2317 WARN(" Overriding application-given alpha test values - some graphical glitches may appear !\n");
2320 glThis->current_alpha_test_func = GL_NOTEQUAL;
2321 glThis->current_alpha_test_ref = 0.0;
2322 glAlphaFunc(GL_NOTEQUAL, 0.0);
2324 /* Some sanity checks should be added here if a game mixes alphatest + color keying...
2325 Only one has been found for now, and the ALPHAFUNC is 'Always' so it works :-) */
2327 if (This->state_block.render_state[D3DRENDERSTATE_ALPHATESTENABLE - 1] == FALSE) {
2328 glDisable(GL_ALPHA_TEST);
2329 glThis->alpha_test = FALSE;
2331 /* Maybe we should restore here the application-given alpha test states ? */
2338 GL_IDirect3DDeviceImpl_7_3T_SetTexture(LPDIRECT3DDEVICE7 iface,
2340 LPDIRECTDRAWSURFACE7 lpTexture2)
2342 ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice7, iface);
2344 TRACE("(%p/%p)->(%08lx,%p)\n", This, iface, dwStage, lpTexture2);
2346 if (((GL_extensions.max_texture_units == 0) && (dwStage > 0)) ||
2347 ((GL_extensions.max_texture_units != 0) && (dwStage >= GL_extensions.max_texture_units))) {
2348 if (lpTexture2 != NULL) {
2349 WARN(" setting a texture to a non-supported texture stage !\n");
2354 if (This->current_texture[dwStage] != NULL) {
2355 IDirectDrawSurface7_Release(ICOM_INTERFACE(This->current_texture[dwStage], IDirectDrawSurface7));
2358 if (lpTexture2 == NULL) {
2359 This->current_texture[dwStage] = NULL;
2361 IDirectDrawSurfaceImpl *tex_impl = ICOM_OBJECT(IDirectDrawSurfaceImpl, IDirectDrawSurface7, lpTexture2);
2362 IDirectDrawSurface7_AddRef(ICOM_INTERFACE(tex_impl, IDirectDrawSurface7));
2363 This->current_texture[dwStage] = tex_impl;
2370 GL_IDirect3DDeviceImpl_7_GetCaps(LPDIRECT3DDEVICE7 iface,
2371 LPD3DDEVICEDESC7 lpD3DHELDevDesc)
2373 ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice7, iface);
2374 TRACE("(%p/%p)->(%p)\n", This, iface, lpD3DHELDevDesc);
2376 fill_opengl_caps_7(lpD3DHELDevDesc);
2378 TRACE(" returning caps : no dump function yet.\n");
2384 GL_IDirect3DDeviceImpl_7_SetMaterial(LPDIRECT3DDEVICE7 iface,
2385 LPD3DMATERIAL7 lpMat)
2387 ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice7, iface);
2388 TRACE("(%p/%p)->(%p)\n", This, iface, lpMat);
2390 if (TRACE_ON(ddraw)) {
2391 TRACE(" material is : \n");
2392 dump_D3DMATERIAL7(lpMat);
2395 This->current_material = *lpMat;
2398 glMaterialfv(GL_FRONT_AND_BACK,
2400 (float *) &(This->current_material.u.diffuse));
2401 glMaterialfv(GL_FRONT_AND_BACK,
2403 (float *) &(This->current_material.u1.ambient));
2404 glMaterialfv(GL_FRONT_AND_BACK,
2406 (float *) &(This->current_material.u2.specular));
2407 glMaterialfv(GL_FRONT_AND_BACK,
2409 (float *) &(This->current_material.u3.emissive));
2410 glMaterialf(GL_FRONT_AND_BACK,
2412 This->current_material.u4.power); /* Not sure about this... */
2420 GL_IDirect3DDeviceImpl_7_SetLight(LPDIRECT3DDEVICE7 iface,
2422 LPD3DLIGHT7 lpLight)
2424 ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice7, iface);
2425 IDirect3DDeviceGLImpl *glThis = (IDirect3DDeviceGLImpl *) This;
2426 TRACE("(%p/%p)->(%08lx,%p)\n", This, iface, dwLightIndex, lpLight);
2428 if (TRACE_ON(ddraw)) {
2429 TRACE(" setting light : \n");
2430 dump_D3DLIGHT7(lpLight);
2433 if (dwLightIndex >= MAX_LIGHTS) return DDERR_INVALIDPARAMS;
2434 This->set_lights |= 0x00000001 << dwLightIndex;
2435 This->light_parameters[dwLightIndex] = *lpLight;
2437 /* Some checks to print out nice warnings :-) */
2438 switch (lpLight->dltType) {
2439 case D3DLIGHT_DIRECTIONAL:
2440 case D3DLIGHT_POINT:
2441 /* These are handled properly... */
2445 if ((lpLight->dvTheta != 0.0) ||
2446 (lpLight->dvTheta != lpLight->dvPhi)) {
2447 ERR("dvTheta not fully supported yet !\n");
2452 ERR("Light type not handled yet : %08x !\n", lpLight->dltType);
2455 /* This will force the Light setting on next drawing of primitives */
2456 glThis->transform_state = GL_TRANSFORM_NONE;
2462 GL_IDirect3DDeviceImpl_7_LightEnable(LPDIRECT3DDEVICE7 iface,
2466 ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice7, iface);
2467 TRACE("(%p/%p)->(%08lx,%d)\n", This, iface, dwLightIndex, bEnable);
2469 if (dwLightIndex >= MAX_LIGHTS) return DDERR_INVALIDPARAMS;
2473 if (((0x00000001 << dwLightIndex) & This->set_lights) == 0) {
2474 /* Set the default parameters.. */
2475 TRACE(" setting default light parameters...\n");
2476 GL_IDirect3DDeviceImpl_7_SetLight(iface, dwLightIndex, &(This->light_parameters[dwLightIndex]));
2478 glEnable(GL_LIGHT0 + dwLightIndex);
2479 if ((This->active_lights & (0x00000001 << dwLightIndex)) == 0) {
2480 /* This light gets active... Need to update its parameters to GL before the next drawing */
2481 IDirect3DDeviceGLImpl *glThis = (IDirect3DDeviceGLImpl *) This;
2483 This->active_lights |= 0x00000001 << dwLightIndex;
2484 glThis->transform_state = GL_TRANSFORM_NONE;
2487 glDisable(GL_LIGHT0 + dwLightIndex);
2488 This->active_lights &= ~(0x00000001 << dwLightIndex);
2496 GL_IDirect3DDeviceImpl_7_SetClipPlane(LPDIRECT3DDEVICE7 iface, DWORD dwIndex, CONST D3DVALUE* pPlaneEquation)
2498 ICOM_THIS(IDirect3DDeviceImpl,iface);
2499 IDirect3DDeviceGLImpl* glThis = (IDirect3DDeviceGLImpl*) This;
2501 TRACE("(%p)->(%ld,%p)\n", This, dwIndex, pPlaneEquation);
2503 if (dwIndex >= This->max_clipping_planes) {
2504 return DDERR_INVALIDPARAMS;
2507 TRACE(" clip plane %ld : %f %f %f %f\n", dwIndex, pPlaneEquation[0], pPlaneEquation[1], pPlaneEquation[2], pPlaneEquation[3] );
2509 memcpy(This->clipping_planes[dwIndex].plane, pPlaneEquation, sizeof(D3DVALUE[4]));
2511 /* This is to force the reset of the transformation matrices on the next drawing.
2512 * This is needed to use the correct matrices for the various clipping planes.
2514 glThis->transform_state = GL_TRANSFORM_NONE;
2520 GL_IDirect3DDeviceImpl_7_SetViewport(LPDIRECT3DDEVICE7 iface,
2521 LPD3DVIEWPORT7 lpData)
2523 ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice7, iface);
2524 TRACE("(%p/%p)->(%p)\n", This, iface, lpData);
2526 if (TRACE_ON(ddraw)) {
2527 TRACE(" viewport is : \n");
2528 TRACE(" - dwX = %ld dwY = %ld\n",
2529 lpData->dwX, lpData->dwY);
2530 TRACE(" - dwWidth = %ld dwHeight = %ld\n",
2531 lpData->dwWidth, lpData->dwHeight);
2532 TRACE(" - dvMinZ = %f dvMaxZ = %f\n",
2533 lpData->dvMinZ, lpData->dvMaxZ);
2537 /* Set the viewport */
2538 if ((lpData->dvMinZ != This->active_viewport.dvMinZ) ||
2539 (lpData->dvMaxZ != This->active_viewport.dvMaxZ)) {
2540 glDepthRange(lpData->dvMinZ, lpData->dvMaxZ);
2542 if ((lpData->dwX != This->active_viewport.dwX) ||
2543 (lpData->dwY != This->active_viewport.dwY) ||
2544 (lpData->dwWidth != This->active_viewport.dwWidth) ||
2545 (lpData->dwHeight != This->active_viewport.dwHeight)) {
2546 glViewport(lpData->dwX,
2547 This->surface->surface_desc.dwHeight - (lpData->dwHeight + lpData->dwY),
2548 lpData->dwWidth, lpData->dwHeight);
2553 This->active_viewport = *lpData;
2558 #if !defined(__STRICT_ANSI__) && defined(__GNUC__)
2559 # define XCAST(fun) (typeof(VTABLE_IDirect3DDevice7.fun))
2561 # define XCAST(fun) (void*)
2564 ICOM_VTABLE(IDirect3DDevice7) VTABLE_IDirect3DDevice7 =
2566 ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
2567 XCAST(QueryInterface) Main_IDirect3DDeviceImpl_7_3T_2T_1T_QueryInterface,
2568 XCAST(AddRef) Main_IDirect3DDeviceImpl_7_3T_2T_1T_AddRef,
2569 XCAST(Release) GL_IDirect3DDeviceImpl_7_3T_2T_1T_Release,
2570 XCAST(GetCaps) GL_IDirect3DDeviceImpl_7_GetCaps,
2571 XCAST(EnumTextureFormats) GL_IDirect3DDeviceImpl_7_3T_EnumTextureFormats,
2572 XCAST(BeginScene) Main_IDirect3DDeviceImpl_7_3T_2T_1T_BeginScene,
2573 XCAST(EndScene) Main_IDirect3DDeviceImpl_7_3T_2T_1T_EndScene,
2574 XCAST(GetDirect3D) Main_IDirect3DDeviceImpl_7_3T_2T_1T_GetDirect3D,
2575 XCAST(SetRenderTarget) Main_IDirect3DDeviceImpl_7_3T_2T_SetRenderTarget,
2576 XCAST(GetRenderTarget) Main_IDirect3DDeviceImpl_7_3T_2T_GetRenderTarget,
2577 XCAST(Clear) Main_IDirect3DDeviceImpl_7_Clear,
2578 XCAST(SetTransform) Main_IDirect3DDeviceImpl_7_3T_2T_SetTransform,
2579 XCAST(GetTransform) Main_IDirect3DDeviceImpl_7_3T_2T_GetTransform,
2580 XCAST(SetViewport) GL_IDirect3DDeviceImpl_7_SetViewport,
2581 XCAST(MultiplyTransform) Main_IDirect3DDeviceImpl_7_3T_2T_MultiplyTransform,
2582 XCAST(GetViewport) Main_IDirect3DDeviceImpl_7_GetViewport,
2583 XCAST(SetMaterial) GL_IDirect3DDeviceImpl_7_SetMaterial,
2584 XCAST(GetMaterial) Main_IDirect3DDeviceImpl_7_GetMaterial,
2585 XCAST(SetLight) GL_IDirect3DDeviceImpl_7_SetLight,
2586 XCAST(GetLight) Main_IDirect3DDeviceImpl_7_GetLight,
2587 XCAST(SetRenderState) GL_IDirect3DDeviceImpl_7_3T_2T_SetRenderState,
2588 XCAST(GetRenderState) GL_IDirect3DDeviceImpl_7_3T_2T_GetRenderState,
2589 XCAST(BeginStateBlock) Main_IDirect3DDeviceImpl_7_BeginStateBlock,
2590 XCAST(EndStateBlock) Main_IDirect3DDeviceImpl_7_EndStateBlock,
2591 XCAST(PreLoad) Main_IDirect3DDeviceImpl_7_PreLoad,
2592 XCAST(DrawPrimitive) GL_IDirect3DDeviceImpl_7_3T_DrawPrimitive,
2593 XCAST(DrawIndexedPrimitive) GL_IDirect3DDeviceImpl_7_3T_DrawIndexedPrimitive,
2594 XCAST(SetClipStatus) Main_IDirect3DDeviceImpl_7_3T_2T_SetClipStatus,
2595 XCAST(GetClipStatus) Main_IDirect3DDeviceImpl_7_3T_2T_GetClipStatus,
2596 XCAST(DrawPrimitiveStrided) GL_IDirect3DDeviceImpl_7_3T_DrawPrimitiveStrided,
2597 XCAST(DrawIndexedPrimitiveStrided) GL_IDirect3DDeviceImpl_7_3T_DrawIndexedPrimitiveStrided,
2598 XCAST(DrawPrimitiveVB) GL_IDirect3DDeviceImpl_7_3T_DrawPrimitiveVB,
2599 XCAST(DrawIndexedPrimitiveVB) GL_IDirect3DDeviceImpl_7_3T_DrawIndexedPrimitiveVB,
2600 XCAST(ComputeSphereVisibility) Main_IDirect3DDeviceImpl_7_3T_ComputeSphereVisibility,
2601 XCAST(GetTexture) Main_IDirect3DDeviceImpl_7_3T_GetTexture,
2602 XCAST(SetTexture) GL_IDirect3DDeviceImpl_7_3T_SetTexture,
2603 XCAST(GetTextureStageState) Main_IDirect3DDeviceImpl_7_3T_GetTextureStageState,
2604 XCAST(SetTextureStageState) GL_IDirect3DDeviceImpl_7_3T_SetTextureStageState,
2605 XCAST(ValidateDevice) Main_IDirect3DDeviceImpl_7_3T_ValidateDevice,
2606 XCAST(ApplyStateBlock) Main_IDirect3DDeviceImpl_7_ApplyStateBlock,
2607 XCAST(CaptureStateBlock) Main_IDirect3DDeviceImpl_7_CaptureStateBlock,
2608 XCAST(DeleteStateBlock) Main_IDirect3DDeviceImpl_7_DeleteStateBlock,
2609 XCAST(CreateStateBlock) Main_IDirect3DDeviceImpl_7_CreateStateBlock,
2610 XCAST(Load) Main_IDirect3DDeviceImpl_7_Load,
2611 XCAST(LightEnable) GL_IDirect3DDeviceImpl_7_LightEnable,
2612 XCAST(GetLightEnable) Main_IDirect3DDeviceImpl_7_GetLightEnable,
2613 XCAST(SetClipPlane) GL_IDirect3DDeviceImpl_7_SetClipPlane,
2614 XCAST(GetClipPlane) Main_IDirect3DDeviceImpl_7_GetClipPlane,
2615 XCAST(GetInfo) Main_IDirect3DDeviceImpl_7_GetInfo,
2618 #if !defined(__STRICT_ANSI__) && defined(__GNUC__)
2623 #if !defined(__STRICT_ANSI__) && defined(__GNUC__)
2624 # define XCAST(fun) (typeof(VTABLE_IDirect3DDevice3.fun))
2626 # define XCAST(fun) (void*)
2629 ICOM_VTABLE(IDirect3DDevice3) VTABLE_IDirect3DDevice3 =
2631 ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
2632 XCAST(QueryInterface) Thunk_IDirect3DDeviceImpl_3_QueryInterface,
2633 XCAST(AddRef) Thunk_IDirect3DDeviceImpl_3_AddRef,
2634 XCAST(Release) Thunk_IDirect3DDeviceImpl_3_Release,
2635 XCAST(GetCaps) GL_IDirect3DDeviceImpl_3_2T_1T_GetCaps,
2636 XCAST(GetStats) Main_IDirect3DDeviceImpl_3_2T_1T_GetStats,
2637 XCAST(AddViewport) Main_IDirect3DDeviceImpl_3_2T_1T_AddViewport,
2638 XCAST(DeleteViewport) Main_IDirect3DDeviceImpl_3_2T_1T_DeleteViewport,
2639 XCAST(NextViewport) Main_IDirect3DDeviceImpl_3_2T_1T_NextViewport,
2640 XCAST(EnumTextureFormats) Thunk_IDirect3DDeviceImpl_3_EnumTextureFormats,
2641 XCAST(BeginScene) Thunk_IDirect3DDeviceImpl_3_BeginScene,
2642 XCAST(EndScene) Thunk_IDirect3DDeviceImpl_3_EndScene,
2643 XCAST(GetDirect3D) Thunk_IDirect3DDeviceImpl_3_GetDirect3D,
2644 XCAST(SetCurrentViewport) Main_IDirect3DDeviceImpl_3_2T_SetCurrentViewport,
2645 XCAST(GetCurrentViewport) Main_IDirect3DDeviceImpl_3_2T_GetCurrentViewport,
2646 XCAST(SetRenderTarget) Thunk_IDirect3DDeviceImpl_3_SetRenderTarget,
2647 XCAST(GetRenderTarget) Thunk_IDirect3DDeviceImpl_3_GetRenderTarget,
2648 XCAST(Begin) Main_IDirect3DDeviceImpl_3_Begin,
2649 XCAST(BeginIndexed) Main_IDirect3DDeviceImpl_3_BeginIndexed,
2650 XCAST(Vertex) Main_IDirect3DDeviceImpl_3_2T_Vertex,
2651 XCAST(Index) Main_IDirect3DDeviceImpl_3_2T_Index,
2652 XCAST(End) Main_IDirect3DDeviceImpl_3_2T_End,
2653 XCAST(GetRenderState) Thunk_IDirect3DDeviceImpl_3_GetRenderState,
2654 XCAST(SetRenderState) Thunk_IDirect3DDeviceImpl_3_SetRenderState,
2655 XCAST(GetLightState) Main_IDirect3DDeviceImpl_3_2T_GetLightState,
2656 XCAST(SetLightState) GL_IDirect3DDeviceImpl_3_2T_SetLightState,
2657 XCAST(SetTransform) Thunk_IDirect3DDeviceImpl_3_SetTransform,
2658 XCAST(GetTransform) Thunk_IDirect3DDeviceImpl_3_GetTransform,
2659 XCAST(MultiplyTransform) Thunk_IDirect3DDeviceImpl_3_MultiplyTransform,
2660 XCAST(DrawPrimitive) Thunk_IDirect3DDeviceImpl_3_DrawPrimitive,
2661 XCAST(DrawIndexedPrimitive) Thunk_IDirect3DDeviceImpl_3_DrawIndexedPrimitive,
2662 XCAST(SetClipStatus) Thunk_IDirect3DDeviceImpl_3_SetClipStatus,
2663 XCAST(GetClipStatus) Thunk_IDirect3DDeviceImpl_3_GetClipStatus,
2664 XCAST(DrawPrimitiveStrided) Thunk_IDirect3DDeviceImpl_3_DrawPrimitiveStrided,
2665 XCAST(DrawIndexedPrimitiveStrided) Thunk_IDirect3DDeviceImpl_3_DrawIndexedPrimitiveStrided,
2666 XCAST(DrawPrimitiveVB) Thunk_IDirect3DDeviceImpl_3_DrawPrimitiveVB,
2667 XCAST(DrawIndexedPrimitiveVB) Thunk_IDirect3DDeviceImpl_3_DrawIndexedPrimitiveVB,
2668 XCAST(ComputeSphereVisibility) Thunk_IDirect3DDeviceImpl_3_ComputeSphereVisibility,
2669 XCAST(GetTexture) Thunk_IDirect3DDeviceImpl_3_GetTexture,
2670 XCAST(SetTexture) Thunk_IDirect3DDeviceImpl_3_SetTexture,
2671 XCAST(GetTextureStageState) Thunk_IDirect3DDeviceImpl_3_GetTextureStageState,
2672 XCAST(SetTextureStageState) Thunk_IDirect3DDeviceImpl_3_SetTextureStageState,
2673 XCAST(ValidateDevice) Thunk_IDirect3DDeviceImpl_3_ValidateDevice,
2676 #if !defined(__STRICT_ANSI__) && defined(__GNUC__)
2681 #if !defined(__STRICT_ANSI__) && defined(__GNUC__)
2682 # define XCAST(fun) (typeof(VTABLE_IDirect3DDevice2.fun))
2684 # define XCAST(fun) (void*)
2687 ICOM_VTABLE(IDirect3DDevice2) VTABLE_IDirect3DDevice2 =
2689 ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
2690 XCAST(QueryInterface) Thunk_IDirect3DDeviceImpl_2_QueryInterface,
2691 XCAST(AddRef) Thunk_IDirect3DDeviceImpl_2_AddRef,
2692 XCAST(Release) Thunk_IDirect3DDeviceImpl_2_Release,
2693 XCAST(GetCaps) Thunk_IDirect3DDeviceImpl_2_GetCaps,
2694 XCAST(SwapTextureHandles) Main_IDirect3DDeviceImpl_2_1T_SwapTextureHandles,
2695 XCAST(GetStats) Thunk_IDirect3DDeviceImpl_2_GetStats,
2696 XCAST(AddViewport) Thunk_IDirect3DDeviceImpl_2_AddViewport,
2697 XCAST(DeleteViewport) Thunk_IDirect3DDeviceImpl_2_DeleteViewport,
2698 XCAST(NextViewport) Thunk_IDirect3DDeviceImpl_2_NextViewport,
2699 XCAST(EnumTextureFormats) GL_IDirect3DDeviceImpl_2_1T_EnumTextureFormats,
2700 XCAST(BeginScene) Thunk_IDirect3DDeviceImpl_2_BeginScene,
2701 XCAST(EndScene) Thunk_IDirect3DDeviceImpl_2_EndScene,
2702 XCAST(GetDirect3D) Thunk_IDirect3DDeviceImpl_2_GetDirect3D,
2703 XCAST(SetCurrentViewport) Thunk_IDirect3DDeviceImpl_2_SetCurrentViewport,
2704 XCAST(GetCurrentViewport) Thunk_IDirect3DDeviceImpl_2_GetCurrentViewport,
2705 XCAST(SetRenderTarget) Thunk_IDirect3DDeviceImpl_2_SetRenderTarget,
2706 XCAST(GetRenderTarget) Thunk_IDirect3DDeviceImpl_2_GetRenderTarget,
2707 XCAST(Begin) Main_IDirect3DDeviceImpl_2_Begin,
2708 XCAST(BeginIndexed) Main_IDirect3DDeviceImpl_2_BeginIndexed,
2709 XCAST(Vertex) Thunk_IDirect3DDeviceImpl_2_Vertex,
2710 XCAST(Index) Thunk_IDirect3DDeviceImpl_2_Index,
2711 XCAST(End) Thunk_IDirect3DDeviceImpl_2_End,
2712 XCAST(GetRenderState) Thunk_IDirect3DDeviceImpl_2_GetRenderState,
2713 XCAST(SetRenderState) Thunk_IDirect3DDeviceImpl_2_SetRenderState,
2714 XCAST(GetLightState) Thunk_IDirect3DDeviceImpl_2_GetLightState,
2715 XCAST(SetLightState) Thunk_IDirect3DDeviceImpl_2_SetLightState,
2716 XCAST(SetTransform) Thunk_IDirect3DDeviceImpl_2_SetTransform,
2717 XCAST(GetTransform) Thunk_IDirect3DDeviceImpl_2_GetTransform,
2718 XCAST(MultiplyTransform) Thunk_IDirect3DDeviceImpl_2_MultiplyTransform,
2719 XCAST(DrawPrimitive) GL_IDirect3DDeviceImpl_2_DrawPrimitive,
2720 XCAST(DrawIndexedPrimitive) GL_IDirect3DDeviceImpl_2_DrawIndexedPrimitive,
2721 XCAST(SetClipStatus) Thunk_IDirect3DDeviceImpl_2_SetClipStatus,
2722 XCAST(GetClipStatus) Thunk_IDirect3DDeviceImpl_2_GetClipStatus,
2725 #if !defined(__STRICT_ANSI__) && defined(__GNUC__)
2730 #if !defined(__STRICT_ANSI__) && defined(__GNUC__)
2731 # define XCAST(fun) (typeof(VTABLE_IDirect3DDevice.fun))
2733 # define XCAST(fun) (void*)
2736 ICOM_VTABLE(IDirect3DDevice) VTABLE_IDirect3DDevice =
2738 ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
2739 XCAST(QueryInterface) Thunk_IDirect3DDeviceImpl_1_QueryInterface,
2740 XCAST(AddRef) Thunk_IDirect3DDeviceImpl_1_AddRef,
2741 XCAST(Release) Thunk_IDirect3DDeviceImpl_1_Release,
2742 XCAST(Initialize) Main_IDirect3DDeviceImpl_1_Initialize,
2743 XCAST(GetCaps) Thunk_IDirect3DDeviceImpl_1_GetCaps,
2744 XCAST(SwapTextureHandles) Thunk_IDirect3DDeviceImpl_1_SwapTextureHandles,
2745 XCAST(CreateExecuteBuffer) GL_IDirect3DDeviceImpl_1_CreateExecuteBuffer,
2746 XCAST(GetStats) Thunk_IDirect3DDeviceImpl_1_GetStats,
2747 XCAST(Execute) Main_IDirect3DDeviceImpl_1_Execute,
2748 XCAST(AddViewport) Thunk_IDirect3DDeviceImpl_1_AddViewport,
2749 XCAST(DeleteViewport) Thunk_IDirect3DDeviceImpl_1_DeleteViewport,
2750 XCAST(NextViewport) Thunk_IDirect3DDeviceImpl_1_NextViewport,
2751 XCAST(Pick) Main_IDirect3DDeviceImpl_1_Pick,
2752 XCAST(GetPickRecords) Main_IDirect3DDeviceImpl_1_GetPickRecords,
2753 XCAST(EnumTextureFormats) Thunk_IDirect3DDeviceImpl_1_EnumTextureFormats,
2754 XCAST(CreateMatrix) Main_IDirect3DDeviceImpl_1_CreateMatrix,
2755 XCAST(SetMatrix) Main_IDirect3DDeviceImpl_1_SetMatrix,
2756 XCAST(GetMatrix) Main_IDirect3DDeviceImpl_1_GetMatrix,
2757 XCAST(DeleteMatrix) Main_IDirect3DDeviceImpl_1_DeleteMatrix,
2758 XCAST(BeginScene) Thunk_IDirect3DDeviceImpl_1_BeginScene,
2759 XCAST(EndScene) Thunk_IDirect3DDeviceImpl_1_EndScene,
2760 XCAST(GetDirect3D) Thunk_IDirect3DDeviceImpl_1_GetDirect3D,
2763 #if !defined(__STRICT_ANSI__) && defined(__GNUC__)
2767 static HRESULT d3ddevice_clear(IDirect3DDeviceImpl *This,
2768 WINE_GL_BUFFER_TYPE buffer_type,
2776 IDirect3DDeviceGLImpl *glThis = (IDirect3DDeviceGLImpl *) This;
2777 GLbitfield bitfield = 0;
2781 TRACE("(%p)->(%08lx,%p,%08lx,%08lx,%f,%08lx)\n", This, dwCount, lpRects, dwFlags, dwColor, dvZ, dwStencil);
2782 if (TRACE_ON(ddraw)) {
2785 TRACE(" rectangles : \n");
2786 for (i = 0; i < dwCount; i++) {
2787 TRACE(" - %ld x %ld %ld x %ld\n", lpRects[i].u1.x1, lpRects[i].u2.y1, lpRects[i].u3.x2, lpRects[i].u4.y2);
2796 rect.u3.x2 = This->surface->surface_desc.dwWidth;
2797 rect.u4.y2 = This->surface->surface_desc.dwHeight;
2801 /* Clears the screen */
2804 if (dwFlags & D3DCLEAR_TARGET) {
2805 if (glThis->state[buffer_type] == SURFACE_MEMORY_DIRTY) {
2806 /* TODO: optimize here the case where Clear changes all the screen... */
2807 This->flush_to_framebuffer(This, &(glThis->lock_rect[buffer_type]), glThis->lock_surf[buffer_type]);
2809 glThis->state[buffer_type] = SURFACE_GL;
2812 if (dwFlags & D3DCLEAR_ZBUFFER) {
2813 bitfield |= GL_DEPTH_BUFFER_BIT;
2814 if (glThis->depth_mask == FALSE) {
2815 glDepthMask(GL_TRUE); /* Enables Z writing to be sure to delete also the Z buffer */
2817 if (dvZ != glThis->prev_clear_Z) {
2819 glThis->prev_clear_Z = dvZ;
2821 TRACE(" depth value : %f\n", dvZ);
2823 if (dwFlags & D3DCLEAR_STENCIL) {
2824 bitfield |= GL_STENCIL_BUFFER_BIT;
2825 if (dwStencil != glThis->prev_clear_stencil) {
2826 glClearStencil(dwStencil);
2827 glThis->prev_clear_stencil = dwStencil;
2829 TRACE(" stencil value : %ld\n", dwStencil);
2831 if (dwFlags & D3DCLEAR_TARGET) {
2832 bitfield |= GL_COLOR_BUFFER_BIT;
2833 if (dwColor != glThis->prev_clear_color) {
2834 glClearColor(((dwColor >> 16) & 0xFF) / 255.0,
2835 ((dwColor >> 8) & 0xFF) / 255.0,
2836 ((dwColor >> 0) & 0xFF) / 255.0,
2837 ((dwColor >> 24) & 0xFF) / 255.0);
2838 glThis->prev_clear_color = dwColor;
2840 TRACE(" color value (ARGB) : %08lx\n", dwColor);
2843 glEnable(GL_SCISSOR_TEST);
2844 for (i = 0; i < dwCount; i++) {
2845 glScissor(lpRects[i].u1.x1, This->surface->surface_desc.dwHeight - lpRects[i].u4.y2,
2846 lpRects[i].u3.x2 - lpRects[i].u1.x1, lpRects[i].u4.y2 - lpRects[i].u2.y1);
2849 glDisable(GL_SCISSOR_TEST);
2851 if (dwFlags & D3DCLEAR_ZBUFFER) {
2852 if (glThis->depth_mask == FALSE) glDepthMask(GL_FALSE);
2860 static HRESULT d3ddevice_clear_back(IDirect3DDeviceImpl *This,
2868 return d3ddevice_clear(This, WINE_GL_BUFFER_BACK, dwCount, lpRects, dwFlags, dwColor, dvZ, dwStencil);
2872 setup_rect_and_surface_for_blt(IDirectDrawSurfaceImpl *This,
2873 WINE_GL_BUFFER_TYPE *buffer_type_p, D3DRECT *rect)
2875 IDirect3DDeviceGLImpl *gl_d3d_dev = (IDirect3DDeviceGLImpl *) This->d3ddevice;
2876 WINE_GL_BUFFER_TYPE buffer_type;
2878 /* First check if we BLT to the backbuffer... */
2879 if ((This->surface_desc.ddsCaps.dwCaps & (DDSCAPS_BACKBUFFER)) != 0) {
2880 buffer_type = WINE_GL_BUFFER_BACK;
2881 } else if ((This->surface_desc.ddsCaps.dwCaps & (DDSCAPS_FRONTBUFFER|DDSCAPS_PRIMARYSURFACE)) != 0) {
2882 buffer_type = WINE_GL_BUFFER_FRONT;
2884 ERR("Only BLT override to front or back-buffer is supported for now !\n");
2885 return DDERR_INVALIDPARAMS;
2888 if ((gl_d3d_dev->state[buffer_type] == SURFACE_MEMORY_DIRTY) &&
2889 (rect->u1.x1 >= gl_d3d_dev->lock_rect[buffer_type].left) &&
2890 (rect->u2.y1 >= gl_d3d_dev->lock_rect[buffer_type].top) &&
2891 (rect->u3.x2 <= gl_d3d_dev->lock_rect[buffer_type].right) &&
2892 (rect->u4.y2 <= gl_d3d_dev->lock_rect[buffer_type].bottom)) {
2893 /* If the memory zone is already dirty, use the standard 'in memory' blit operations and not
2896 return DDERR_INVALIDPARAMS;
2898 *buffer_type_p = buffer_type;
2904 d3ddevice_blt(IDirectDrawSurfaceImpl *This, LPRECT rdst,
2905 LPDIRECTDRAWSURFACE7 src, LPRECT rsrc,
2906 DWORD dwFlags, LPDDBLTFX lpbltfx)
2908 WINE_GL_BUFFER_TYPE buffer_type;
2912 rect.u1.x1 = rdst->left;
2913 rect.u2.y1 = rdst->top;
2914 rect.u3.x2 = rdst->right;
2915 rect.u4.y2 = rdst->bottom;
2919 rect.u3.x2 = This->surface_desc.dwWidth;
2920 rect.u4.y2 = This->surface_desc.dwHeight;
2923 if (setup_rect_and_surface_for_blt(This, &buffer_type, &rect) != DD_OK) return DDERR_INVALIDPARAMS;
2925 if (dwFlags & DDBLT_COLORFILL) {
2926 /* This is easy to handle for the D3D Device... */
2930 /* The color as given in the Blt function is in the format of the frame-buffer...
2931 * 'clear' expect it in ARGB format => we need to do some conversion :-)
2933 if (This->surface_desc.u4.ddpfPixelFormat.dwFlags & DDPF_PALETTEINDEXED8) {
2934 if (This->palette) {
2935 color = ((0xFF000000) |
2936 (This->palette->palents[lpbltfx->u5.dwFillColor].peRed << 16) |
2937 (This->palette->palents[lpbltfx->u5.dwFillColor].peGreen << 8) |
2938 (This->palette->palents[lpbltfx->u5.dwFillColor].peBlue));
2942 } else if ((This->surface_desc.u4.ddpfPixelFormat.dwFlags & DDPF_RGB) &&
2943 (((This->surface_desc.u4.ddpfPixelFormat.dwFlags & DDPF_ALPHAPIXELS) == 0) ||
2944 (This->surface_desc.u4.ddpfPixelFormat.u5.dwRGBAlphaBitMask == 0x00000000))) {
2945 if ((This->surface_desc.u4.ddpfPixelFormat.u1.dwRGBBitCount == 16) &&
2946 (This->surface_desc.u4.ddpfPixelFormat.u2.dwRBitMask == 0xF800) &&
2947 (This->surface_desc.u4.ddpfPixelFormat.u3.dwGBitMask == 0x07E0) &&
2948 (This->surface_desc.u4.ddpfPixelFormat.u4.dwBBitMask == 0x001F)) {
2949 if (lpbltfx->u5.dwFillColor == 0xFFFF) {
2952 color = ((0xFF000000) |
2953 ((lpbltfx->u5.dwFillColor & 0xF800) << 8) |
2954 ((lpbltfx->u5.dwFillColor & 0x07E0) << 5) |
2955 ((lpbltfx->u5.dwFillColor & 0x001F) << 3));
2957 } else if (((This->surface_desc.u4.ddpfPixelFormat.u1.dwRGBBitCount == 32) ||
2958 (This->surface_desc.u4.ddpfPixelFormat.u1.dwRGBBitCount == 24)) &&
2959 (This->surface_desc.u4.ddpfPixelFormat.u2.dwRBitMask == 0x00FF0000) &&
2960 (This->surface_desc.u4.ddpfPixelFormat.u3.dwGBitMask == 0x0000FF00) &&
2961 (This->surface_desc.u4.ddpfPixelFormat.u4.dwBBitMask == 0x000000FF)) {
2962 color = 0xFF000000 | lpbltfx->u5.dwFillColor;
2964 ERR("Wrong surface type for BLT override (unknown RGB format) !\n");
2965 return DDERR_INVALIDPARAMS;
2968 ERR("Wrong surface type for BLT override !\n");
2969 return DDERR_INVALIDPARAMS;
2972 TRACE(" executing D3D Device override.\n");
2976 glGetIntegerv(GL_DRAW_BUFFER, &prev_draw);
2977 if (buffer_type == WINE_GL_BUFFER_FRONT)
2978 glDrawBuffer(GL_FRONT);
2980 glDrawBuffer(GL_BACK);
2982 d3ddevice_clear(This->d3ddevice, buffer_type, 1, &rect, D3DCLEAR_TARGET, color, 0.0, 0x00000000);
2984 if (((buffer_type == WINE_GL_BUFFER_FRONT) && (prev_draw == GL_BACK)) ||
2985 ((buffer_type == WINE_GL_BUFFER_BACK) && (prev_draw == GL_FRONT)))
2986 glDrawBuffer(prev_draw);
2991 } else if ((dwFlags & (~(DDBLT_KEYSRC|DDBLT_WAIT|DDBLT_ASYNC))) == 0) {
2992 /* Normal blit without any special case... */
2994 /* And which has a SRC surface */
2995 IDirectDrawSurfaceImpl *src_impl = ICOM_OBJECT(IDirectDrawSurfaceImpl, IDirectDrawSurface7, src);
2997 if ((src_impl->surface_desc.ddsCaps.dwCaps & DDSCAPS_3DDEVICE) &&
2998 (src_impl->d3ddevice == This->d3ddevice) &&
2999 ((dwFlags & DDBLT_KEYSRC) == 0)) {
3000 /* Both are 3D devices and using the same GL device and the Blt is without color-keying */
3004 WINE_GL_BUFFER_TYPE src_buffer_type;
3005 IDirect3DDeviceGLImpl *gl_d3d_dev = (IDirect3DDeviceGLImpl *) This->d3ddevice;
3011 src_rect.u1.x1 = rsrc->left;
3012 src_rect.u2.y1 = rsrc->top;
3013 src_rect.u3.x2 = rsrc->right;
3014 src_rect.u4.y2 = rsrc->bottom;
3018 src_rect.u3.x2 = src_impl->surface_desc.dwWidth;
3019 src_rect.u4.y2 = src_impl->surface_desc.dwHeight;
3022 width = src_rect.u3.x2 - src_rect.u1.x1;
3023 height = src_rect.u4.y2 - src_rect.u2.y1;
3025 if ((width != (rect.u3.x2 - rect.u1.x1)) ||
3026 (height != (rect.u4.y2 - rect.u2.y1))) {
3027 FIXME(" buffer to buffer copy not supported with stretching yet !\n");
3028 return DDERR_INVALIDPARAMS;
3031 /* First check if we BLT from the backbuffer... */
3032 if ((src_impl->surface_desc.ddsCaps.dwCaps & (DDSCAPS_BACKBUFFER)) != 0) {
3033 src_buffer_type = WINE_GL_BUFFER_BACK;
3034 } else if ((src_impl->surface_desc.ddsCaps.dwCaps & (DDSCAPS_FRONTBUFFER|DDSCAPS_PRIMARYSURFACE)) != 0) {
3035 src_buffer_type = WINE_GL_BUFFER_FRONT;
3037 ERR("Unexpected case in direct buffer to buffer copy !\n");
3038 return DDERR_INVALIDPARAMS;
3041 TRACE(" using direct buffer to buffer copy.\n");
3045 opt_bitmap = d3ddevice_set_state_for_flush(This->d3ddevice, (LPCRECT) &rect, FALSE, &initial);
3047 if (upload_surface_to_tex_memory_init(This, 0, &gl_d3d_dev->current_internal_format,
3048 initial, FALSE, UNLOCK_TEX_SIZE, UNLOCK_TEX_SIZE) != DD_OK) {
3049 ERR(" unsupported pixel format at direct buffer to buffer copy.\n");
3051 return DDERR_INVALIDPARAMS;
3054 glGetIntegerv(GL_DRAW_BUFFER, &prev_draw);
3055 if (buffer_type == WINE_GL_BUFFER_FRONT)
3056 glDrawBuffer(GL_FRONT);
3058 glDrawBuffer(GL_BACK);
3060 if (src_buffer_type == WINE_GL_BUFFER_FRONT)
3061 glReadBuffer(GL_FRONT);
3063 glReadBuffer(GL_BACK);
3065 /* Now the serious stuff happens. Basically, we copy from the source buffer to the texture memory.
3066 And directly re-draws this on the destination buffer. */
3067 for (y = 0; y < height; y += UNLOCK_TEX_SIZE) {
3070 if ((src_rect.u2.y1 + y + UNLOCK_TEX_SIZE) > src_impl->surface_desc.dwHeight)
3071 get_height = src_impl->surface_desc.dwHeight - (src_rect.u2.y1 + y);
3073 get_height = UNLOCK_TEX_SIZE;
3075 for (x = 0; x < width; x += UNLOCK_TEX_SIZE) {
3078 if ((src_rect.u1.x1 + x + UNLOCK_TEX_SIZE) > src_impl->surface_desc.dwWidth)
3079 get_width = src_impl->surface_desc.dwWidth - (src_rect.u1.x1 + x);
3081 get_width = UNLOCK_TEX_SIZE;
3083 glCopyTexSubImage2D(GL_TEXTURE_2D, 0,
3084 0, UNLOCK_TEX_SIZE - get_height,
3085 src_rect.u1.x1 + x, src_impl->surface_desc.dwHeight - (src_rect.u2.y1 + y + get_height),
3086 get_width, get_height);
3089 glTexCoord2f(0.0, 0.0);
3090 glVertex3d(rect.u1.x1 + x,
3091 rect.u2.y1 + y + UNLOCK_TEX_SIZE,
3093 glTexCoord2f(1.0, 0.0);
3094 glVertex3d(rect.u1.x1 + x + UNLOCK_TEX_SIZE,
3095 rect.u2.y1 + y + UNLOCK_TEX_SIZE,
3097 glTexCoord2f(1.0, 1.0);
3098 glVertex3d(rect.u1.x1 + x + UNLOCK_TEX_SIZE,
3101 glTexCoord2f(0.0, 1.0);
3102 glVertex3d(rect.u1.x1 + x,
3109 upload_surface_to_tex_memory_release();
3110 d3ddevice_restore_state_after_flush(This->d3ddevice, opt_bitmap, FALSE);
3112 if (((buffer_type == WINE_GL_BUFFER_FRONT) && (prev_draw == GL_BACK)) ||
3113 ((buffer_type == WINE_GL_BUFFER_BACK) && (prev_draw == GL_FRONT)))
3114 glDrawBuffer(prev_draw);
3120 /* This is the normal 'with source' Blit. Use the texture engine to do the Blt for us
3121 (this prevents calling glReadPixels) */
3125 IDirect3DDeviceGLImpl *gl_d3d_dev = (IDirect3DDeviceGLImpl *) This->d3ddevice;
3129 double x_stretch, y_stretch;
3132 src_rect.u1.x1 = rsrc->left;
3133 src_rect.u2.y1 = rsrc->top;
3134 src_rect.u3.x2 = rsrc->right;
3135 src_rect.u4.y2 = rsrc->bottom;
3139 src_rect.u3.x2 = src_impl->surface_desc.dwWidth;
3140 src_rect.u4.y2 = src_impl->surface_desc.dwHeight;
3143 width = src_rect.u3.x2 - src_rect.u1.x1;
3144 height = src_rect.u4.y2 - src_rect.u2.y1;
3146 x_stretch = (double) (rect.u3.x2 - rect.u1.x1) / (double) width;
3147 y_stretch = (double) (rect.u4.y2 - rect.u2.y1) / (double) height;
3149 TRACE(" using memory to buffer Blt overide.\n");
3153 opt_bitmap = d3ddevice_set_state_for_flush(This->d3ddevice, (LPCRECT) &rect, ((dwFlags & DDBLT_KEYSRC) != 0), &initial);
3155 if (upload_surface_to_tex_memory_init(src_impl, 0, &gl_d3d_dev->current_internal_format,
3156 initial, ((dwFlags & DDBLT_KEYSRC) != 0), UNLOCK_TEX_SIZE, UNLOCK_TEX_SIZE) != DD_OK) {
3157 ERR(" unsupported pixel format at memory to buffer Blt overide.\n");
3159 return DDERR_INVALIDPARAMS;
3162 glGetIntegerv(GL_DRAW_BUFFER, &prev_draw);
3163 if (buffer_type == WINE_GL_BUFFER_FRONT)
3164 glDrawBuffer(GL_FRONT);
3166 glDrawBuffer(GL_BACK);
3168 /* Now the serious stuff happens. This is basically the same code that for the memory
3169 flush to frame buffer ... with stretching and different rectangles added :-) */
3170 for (y = 0; y < height; y += UNLOCK_TEX_SIZE) {
3173 flush_rect.top = src_rect.u2.y1 + y;
3174 flush_rect.bottom = ((src_rect.u2.y1 + y + UNLOCK_TEX_SIZE > src_rect.u4.y2) ?
3176 (src_rect.u2.y1 + y + UNLOCK_TEX_SIZE));
3178 for (x = 0; x < width; x += UNLOCK_TEX_SIZE) {
3179 flush_rect.left = src_rect.u1.x1 + x;
3180 flush_rect.right = ((src_rect.u1.x1 + x + UNLOCK_TEX_SIZE > src_rect.u3.x2) ?
3182 (src_rect.u1.x1 + x + UNLOCK_TEX_SIZE));
3184 upload_surface_to_tex_memory(&flush_rect, 0, 0, &(gl_d3d_dev->surface_ptr));
3187 glTexCoord2f(0.0, 0.0);
3188 glVertex3d(rect.u1.x1 + (x * x_stretch),
3189 rect.u2.y1 + (y * y_stretch),
3191 glTexCoord2f(1.0, 0.0);
3192 glVertex3d(rect.u1.x1 + ((x + UNLOCK_TEX_SIZE) * x_stretch),
3193 rect.u2.y1 + (y * y_stretch),
3195 glTexCoord2f(1.0, 1.0);
3196 glVertex3d(rect.u1.x1 + ((x + UNLOCK_TEX_SIZE) * x_stretch),
3197 rect.u2.y1 + ((y + UNLOCK_TEX_SIZE) * y_stretch),
3199 glTexCoord2f(0.0, 1.0);
3200 glVertex3d(rect.u1.x1 + (x * x_stretch),
3201 rect.u2.y1 + ((y + UNLOCK_TEX_SIZE) * y_stretch),
3207 upload_surface_to_tex_memory_release();
3208 d3ddevice_restore_state_after_flush(This->d3ddevice, opt_bitmap, ((dwFlags & DDBLT_KEYSRC) != 0));
3210 if (((buffer_type == WINE_GL_BUFFER_FRONT) && (prev_draw == GL_BACK)) ||
3211 ((buffer_type == WINE_GL_BUFFER_BACK) && (prev_draw == GL_FRONT)))
3212 glDrawBuffer(prev_draw);
3220 return DDERR_INVALIDPARAMS;
3224 d3ddevice_bltfast(IDirectDrawSurfaceImpl *This, DWORD dstx,
3225 DWORD dsty, LPDIRECTDRAWSURFACE7 src,
3226 LPRECT rsrc, DWORD trans)
3230 IDirectDrawSurfaceImpl *src_impl = ICOM_OBJECT(IDirectDrawSurfaceImpl, IDirectDrawSurface7, src);
3231 IDirect3DDeviceGLImpl *gl_d3d_dev = (IDirect3DDeviceGLImpl *) This->d3ddevice;
3232 WINE_GL_BUFFER_TYPE buffer_type;
3236 int width, height, x, y;
3238 /* Cannot support DSTCOLORKEY blitting... */
3239 if ((trans & DDBLTFAST_DESTCOLORKEY) != 0) return DDERR_INVALIDPARAMS;
3242 WARN("rsrc is NULL - getting the whole surface !!\n");
3244 rsrc->left = rsrc->top = 0;
3245 rsrc->right = src_impl->surface_desc.dwWidth;
3246 rsrc->bottom = src_impl->surface_desc.dwHeight;
3254 rdst.right = dstx + (rsrc->right - rsrc->left);
3255 if (rdst.right > This->surface_desc.dwWidth) {
3256 rsrc->right -= (This->surface_desc.dwWidth - rdst.right);
3257 rdst.right = This->surface_desc.dwWidth;
3259 rdst.bottom = dsty + (rsrc->bottom - rsrc->top);
3260 if (rdst.bottom > This->surface_desc.dwHeight) {
3261 rsrc->bottom -= (This->surface_desc.dwHeight - rdst.bottom);
3262 rdst.bottom = This->surface_desc.dwHeight;
3265 width = rsrc->right - rsrc->left;
3266 height = rsrc->bottom - rsrc->top;
3268 if (setup_rect_and_surface_for_blt(This, &buffer_type, (D3DRECT *) &rdst) != DD_OK) return DDERR_INVALIDPARAMS;
3270 TRACE(" using BltFast memory to frame buffer overide.\n");
3274 opt_bitmap = d3ddevice_set_state_for_flush(This->d3ddevice, &rdst, (trans & DDBLTFAST_SRCCOLORKEY) != 0, &initial);
3276 if (upload_surface_to_tex_memory_init(src_impl, 0, &gl_d3d_dev->current_internal_format,
3277 initial, (trans & DDBLTFAST_SRCCOLORKEY) != 0,
3278 UNLOCK_TEX_SIZE, UNLOCK_TEX_SIZE) != DD_OK) {
3279 ERR(" unsupported pixel format at memory to buffer Blt overide.\n");
3281 return DDERR_INVALIDPARAMS;
3284 glGetIntegerv(GL_DRAW_BUFFER, &prev_draw);
3285 if (buffer_type == WINE_GL_BUFFER_FRONT)
3286 glDrawBuffer(GL_FRONT);
3288 glDrawBuffer(GL_BACK);
3290 /* Now the serious stuff happens. This is basically the same code that for the memory
3291 flush to frame buffer but with different rectangles for source and destination :-) */
3292 for (y = 0; y < height; y += UNLOCK_TEX_SIZE) {
3295 flush_rect.top = rsrc->top + y;
3296 flush_rect.bottom = ((rsrc->top + y + UNLOCK_TEX_SIZE > rsrc->bottom) ?
3298 (rsrc->top + y + UNLOCK_TEX_SIZE));
3300 for (x = 0; x < width; x += UNLOCK_TEX_SIZE) {
3301 flush_rect.left = rsrc->left + x;
3302 flush_rect.right = ((rsrc->left + x + UNLOCK_TEX_SIZE > rsrc->right) ?
3304 (rsrc->left + x + UNLOCK_TEX_SIZE));
3306 upload_surface_to_tex_memory(&flush_rect, 0, 0, &(gl_d3d_dev->surface_ptr));
3309 glTexCoord2f(0.0, 0.0);
3310 glVertex3d(rdst.left + x,
3313 glTexCoord2f(1.0, 0.0);
3314 glVertex3d(rdst.left + (x + UNLOCK_TEX_SIZE),
3317 glTexCoord2f(1.0, 1.0);
3318 glVertex3d(rdst.left + (x + UNLOCK_TEX_SIZE),
3319 rdst.top + (y + UNLOCK_TEX_SIZE),
3321 glTexCoord2f(0.0, 1.0);
3322 glVertex3d(rdst.left + x,
3323 rdst.top + (y + UNLOCK_TEX_SIZE),
3329 upload_surface_to_tex_memory_release();
3330 d3ddevice_restore_state_after_flush(This->d3ddevice, opt_bitmap, (trans & DDBLTFAST_SRCCOLORKEY) != 0);
3332 if (((buffer_type == WINE_GL_BUFFER_FRONT) && (prev_draw == GL_BACK)) ||
3333 ((buffer_type == WINE_GL_BUFFER_BACK) && (prev_draw == GL_FRONT)))
3334 glDrawBuffer(prev_draw);
3342 d3ddevice_set_ortho(IDirect3DDeviceImpl *This)
3344 GLfloat height, width;
3345 GLfloat trans_mat[16];
3347 TRACE("(%p)\n", This);
3349 width = This->surface->surface_desc.dwWidth;
3350 height = This->surface->surface_desc.dwHeight;
3352 /* The X axis is straighforward.. For the Y axis, we need to convert 'D3D' screen coordinates
3353 to OpenGL screen coordinates (ie the upper left corner is not the same).
3354 For Z, the mystery is what should it be mapped to ? Ie should the resulting range be between
3355 -1.0 and 1.0 (as the X and Y coordinates) or between 0.0 and 1.0 ? */
3356 trans_mat[ 0] = 2.0 / width; trans_mat[ 4] = 0.0; trans_mat[ 8] = 0.0; trans_mat[12] = -1.0;
3357 trans_mat[ 1] = 0.0; trans_mat[ 5] = -2.0 / height; trans_mat[ 9] = 0.0; trans_mat[13] = 1.0;
3358 trans_mat[ 2] = 0.0; trans_mat[ 6] = 0.0; trans_mat[10] = 2.0; trans_mat[14] = -1.0;
3359 trans_mat[ 3] = 0.0; trans_mat[ 7] = 0.0; trans_mat[11] = 0.0; trans_mat[15] = 1.0;
3362 glMatrixMode(GL_MODELVIEW);
3364 /* See the OpenGL Red Book for an explanation of the following translation (in the OpenGL
3365 Correctness Tips section).
3367 Basically, from what I understood, if the game does not filter the font texture,
3368 as the 'real' pixel will lie at the middle of the two texels, OpenGL may choose the wrong
3369 one and we will have strange artifacts (as the rounding and stuff may give different results
3370 for different pixels, ie sometimes take the left pixel, sometimes the right).
3372 glTranslatef(0.375, 0.375, 0);
3373 glMatrixMode(GL_PROJECTION);
3374 glLoadMatrixf(trans_mat);
3379 d3ddevice_set_matrices(IDirect3DDeviceImpl *This, DWORD matrices,
3380 D3DMATRIX *world_mat, D3DMATRIX *view_mat, D3DMATRIX *proj_mat)
3382 TRACE("(%p,%08lx,%p,%p,%p)\n", This, matrices, world_mat, view_mat, proj_mat);
3385 if ((matrices & (VIEWMAT_CHANGED|WORLDMAT_CHANGED)) != 0) {
3386 glMatrixMode(GL_MODELVIEW);
3387 glLoadMatrixf((float *) view_mat);
3389 /* Now also re-loads all the Lights and Clipping Planes using the new matrices */
3390 if (This->state_block.render_state[D3DRENDERSTATE_CLIPPING - 1] != FALSE) {
3393 for (i = 0, runner = 0x00000001; i < This->max_clipping_planes; i++, runner <<= 1) {
3394 if (runner & This->state_block.render_state[D3DRENDERSTATE_CLIPPLANEENABLE - 1]) {
3397 plane[0] = This->clipping_planes[i].plane[0];
3398 plane[1] = This->clipping_planes[i].plane[1];
3399 plane[2] = This->clipping_planes[i].plane[2];
3400 plane[3] = This->clipping_planes[i].plane[3];
3402 glClipPlane( GL_CLIP_PLANE0 + i, (const GLdouble*) (&plane) );
3406 if (This->state_block.render_state[D3DRENDERSTATE_LIGHTING - 1] != FALSE) {
3410 for (i = 0, runner = 0x00000001; i < MAX_LIGHTS; i++, runner <<= 1) {
3411 if (runner & This->active_lights) {
3412 switch (This->light_parameters[i].dltType) {
3413 case D3DLIGHT_DIRECTIONAL: {
3415 float cut_off = 180.0;
3417 glLightfv(GL_LIGHT0 + i, GL_AMBIENT, (float *) &(This->light_parameters[i].dcvAmbient));
3418 glLightfv(GL_LIGHT0 + i, GL_DIFFUSE, (float *) &(This->light_parameters[i].dcvDiffuse));
3419 glLightfv(GL_LIGHT0 + i, GL_SPECULAR, (float *) &(This->light_parameters[i].dcvSpecular));
3420 glLightfv(GL_LIGHT0 + i, GL_SPOT_CUTOFF, &cut_off);
3422 direction[0] = This->light_parameters[i].dvDirection.u1.x;
3423 direction[1] = This->light_parameters[i].dvDirection.u2.y;
3424 direction[2] = This->light_parameters[i].dvDirection.u3.z;
3426 glLightfv(GL_LIGHT0 + i, GL_POSITION, (float *) direction);
3429 case D3DLIGHT_POINT: {
3431 float cut_off = 180.0;
3433 glLightfv(GL_LIGHT0 + i, GL_AMBIENT, (float *) &(This->light_parameters[i].dcvAmbient));
3434 glLightfv(GL_LIGHT0 + i, GL_DIFFUSE, (float *) &(This->light_parameters[i].dcvDiffuse));
3435 glLightfv(GL_LIGHT0 + i, GL_SPECULAR, (float *) &(This->light_parameters[i].dcvSpecular));
3436 position[0] = This->light_parameters[i].dvPosition.u1.x;
3437 position[1] = This->light_parameters[i].dvPosition.u2.y;
3438 position[2] = This->light_parameters[i].dvPosition.u3.z;
3440 glLightfv(GL_LIGHT0 + i, GL_POSITION, (float *) position);
3441 glLightfv(GL_LIGHT0 + i, GL_CONSTANT_ATTENUATION, &(This->light_parameters[i].dvAttenuation0));
3442 glLightfv(GL_LIGHT0 + i, GL_LINEAR_ATTENUATION, &(This->light_parameters[i].dvAttenuation1));
3443 glLightfv(GL_LIGHT0 + i, GL_QUADRATIC_ATTENUATION, &(This->light_parameters[i].dvAttenuation2));
3444 glLightfv(GL_LIGHT0 + i, GL_SPOT_CUTOFF, &cut_off);
3447 case D3DLIGHT_SPOT: {
3450 float cut_off = 90.0 * (This->light_parameters[i].dvPhi / M_PI);
3452 glLightfv(GL_LIGHT0 + i, GL_AMBIENT, (float *) &(This->light_parameters[i].dcvAmbient));
3453 glLightfv(GL_LIGHT0 + i, GL_DIFFUSE, (float *) &(This->light_parameters[i].dcvDiffuse));
3454 glLightfv(GL_LIGHT0 + i, GL_SPECULAR, (float *) &(This->light_parameters[i].dcvSpecular));
3456 direction[0] = This->light_parameters[i].dvDirection.u1.x;
3457 direction[1] = This->light_parameters[i].dvDirection.u2.y;
3458 direction[2] = This->light_parameters[i].dvDirection.u3.z;
3460 glLightfv(GL_LIGHT0 + i, GL_SPOT_DIRECTION, (float *) direction);
3461 position[0] = This->light_parameters[i].dvPosition.u1.x;
3462 position[1] = This->light_parameters[i].dvPosition.u2.y;
3463 position[2] = This->light_parameters[i].dvPosition.u3.z;
3465 glLightfv(GL_LIGHT0 + i, GL_POSITION, (float *) position);
3466 glLightfv(GL_LIGHT0 + i, GL_CONSTANT_ATTENUATION, &(This->light_parameters[i].dvAttenuation0));
3467 glLightfv(GL_LIGHT0 + i, GL_LINEAR_ATTENUATION, &(This->light_parameters[i].dvAttenuation1));
3468 glLightfv(GL_LIGHT0 + i, GL_QUADRATIC_ATTENUATION, &(This->light_parameters[i].dvAttenuation2));
3469 glLightfv(GL_LIGHT0 + i, GL_SPOT_CUTOFF, &cut_off);
3470 glLightfv(GL_LIGHT0 + i, GL_SPOT_EXPONENT, &(This->light_parameters[i].dvFalloff));
3474 /* No warning here as it's already done at light setting */
3481 glMultMatrixf((float *) world_mat);
3483 if ((matrices & PROJMAT_CHANGED) != 0) {
3484 glMatrixMode(GL_PROJECTION);
3485 glLoadMatrixf((float *) proj_mat);
3491 d3ddevice_matrices_updated(IDirect3DDeviceImpl *This, DWORD matrices)
3493 IDirect3DDeviceGLImpl *glThis = (IDirect3DDeviceGLImpl *) This;
3494 DWORD tex_mat, tex_stage;
3496 TRACE("(%p,%08lx)\n", This, matrices);
3498 if (matrices & (VIEWMAT_CHANGED|WORLDMAT_CHANGED|PROJMAT_CHANGED)) {
3499 if (glThis->transform_state == GL_TRANSFORM_NORMAL) {
3500 /* This will force an update of the transform state at the next drawing. */
3501 glThis->transform_state = GL_TRANSFORM_NONE;
3504 if (matrices & (TEXMAT0_CHANGED|TEXMAT1_CHANGED|TEXMAT2_CHANGED|TEXMAT3_CHANGED|
3505 TEXMAT4_CHANGED|TEXMAT5_CHANGED|TEXMAT6_CHANGED|TEXMAT7_CHANGED))
3508 for (tex_mat = TEXMAT0_CHANGED, tex_stage = 0; tex_mat <= TEXMAT7_CHANGED; tex_mat <<= 1, tex_stage++) {
3509 GLenum unit = GL_TEXTURE0_WINE + tex_stage;
3510 if (matrices & tex_mat) {
3511 if (This->state_block.texture_stage_state[tex_stage][D3DTSS_TEXTURETRANSFORMFLAGS - 1] != D3DTTFF_DISABLE) {
3512 int is_identity = (memcmp(This->tex_mat[tex_stage], id_mat, 16 * sizeof(D3DVALUE)) != 0);
3514 if (This->tex_mat_is_identity[tex_stage] != is_identity) {
3515 if (glThis->current_active_tex_unit != unit) {
3516 GL_extensions.glActiveTexture(unit);
3517 glThis->current_active_tex_unit = unit;
3519 glMatrixMode(GL_TEXTURE);
3520 glLoadMatrixf((float *) This->tex_mat[tex_stage]);
3522 This->tex_mat_is_identity[tex_stage] = is_identity;
3524 if (This->tex_mat_is_identity[tex_stage] == FALSE) {
3525 if (glThis->current_active_tex_unit != unit) {
3526 GL_extensions.glActiveTexture(unit);
3527 glThis->current_active_tex_unit = unit;
3529 glMatrixMode(GL_TEXTURE);
3531 This->tex_mat_is_identity[tex_stage] = TRUE;
3540 /* TODO for both these functions :
3541 - change / restore OpenGL parameters for pictures transfers in case they are ever modified
3542 by other OpenGL code in D3D
3543 - handle the case where no 'Begin / EndScene' was done between two locks
3544 - handle the rectangles in the unlock too
3545 - handle pitch correctly...
3547 static void d3ddevice_lock_update(IDirectDrawSurfaceImpl* This, LPCRECT pRect, DWORD dwFlags)
3549 IDirect3DDeviceImpl *d3d_dev = This->d3ddevice;
3550 IDirect3DDeviceGLImpl* gl_d3d_dev = (IDirect3DDeviceGLImpl*) d3d_dev;
3551 WINE_GL_BUFFER_TYPE buffer_type;
3554 if ((This->surface_desc.ddsCaps.dwCaps & (DDSCAPS_FRONTBUFFER|DDSCAPS_PRIMARYSURFACE)) != 0) {
3555 buffer_type = WINE_GL_BUFFER_FRONT;
3556 if ((gl_d3d_dev->state[WINE_GL_BUFFER_FRONT] != SURFACE_GL) &&
3557 (gl_d3d_dev->lock_surf[WINE_GL_BUFFER_FRONT] != This)) {
3558 ERR("Change of front buffer.. Expect graphic corruptions !\n");
3560 gl_d3d_dev->lock_surf[WINE_GL_BUFFER_FRONT] = This;
3561 } else if ((This->surface_desc.ddsCaps.dwCaps & (DDSCAPS_BACKBUFFER)) == (DDSCAPS_BACKBUFFER)) {
3562 buffer_type = WINE_GL_BUFFER_BACK;
3563 if ((gl_d3d_dev->state[WINE_GL_BUFFER_BACK] != SURFACE_GL) &&
3564 (gl_d3d_dev->lock_surf[WINE_GL_BUFFER_BACK] != This)) {
3565 ERR("Change of back buffer.. Expect graphic corruptions !\n");
3567 gl_d3d_dev->lock_surf[WINE_GL_BUFFER_BACK] = This;
3569 ERR("Wrong surface type for locking !\n");
3573 if (pRect == NULL) {
3576 loc_rect.bottom = This->surface_desc.dwHeight;
3577 loc_rect.right = This->surface_desc.dwWidth;
3581 /* Try to acquire the device critical section */
3582 EnterCriticalSection(&(d3d_dev->crit));
3584 if (gl_d3d_dev->lock_rect_valid[buffer_type] == TRUE) {
3585 ERR("Two consecutive locks on %s buffer... Expect problems !\n",
3586 (buffer_type == WINE_GL_BUFFER_BACK ? "back" : "front"));
3588 gl_d3d_dev->lock_rect_valid[buffer_type] = TRUE;
3590 if (gl_d3d_dev->state[buffer_type] != SURFACE_GL) {
3591 /* Check if the new rectangle is in the previous one or not.
3592 If it is not, flush first the previous locks on screen.
3594 if ((pRect->top < gl_d3d_dev->lock_rect[buffer_type].top) ||
3595 (pRect->left < gl_d3d_dev->lock_rect[buffer_type].left) ||
3596 (pRect->right > gl_d3d_dev->lock_rect[buffer_type].right) ||
3597 (pRect->bottom > gl_d3d_dev->lock_rect[buffer_type].bottom)) {
3598 if (gl_d3d_dev->state[buffer_type] == SURFACE_MEMORY_DIRTY) {
3599 TRACE(" flushing back to %s buffer as new rect : (%ldx%ld) - (%ldx%ld) not included in old rect : (%ldx%ld) - (%ldx%ld)\n",
3600 (buffer_type == WINE_GL_BUFFER_BACK ? "back" : "front"),
3601 pRect->left, pRect->top, pRect->right, pRect->bottom,
3602 gl_d3d_dev->lock_rect[buffer_type].left, gl_d3d_dev->lock_rect[buffer_type].top,
3603 gl_d3d_dev->lock_rect[buffer_type].right, gl_d3d_dev->lock_rect[buffer_type].bottom);
3604 d3d_dev->flush_to_framebuffer(d3d_dev, &(gl_d3d_dev->lock_rect[buffer_type]), gl_d3d_dev->lock_surf[buffer_type]);
3606 gl_d3d_dev->state[buffer_type] = SURFACE_GL;
3607 gl_d3d_dev->lock_rect[buffer_type] = *pRect;
3609 /* In the other case, do not upgrade the locking rectangle as it's no need... */
3611 gl_d3d_dev->lock_rect[buffer_type] = *pRect;
3614 if (gl_d3d_dev->state[buffer_type] == SURFACE_GL) {
3615 /* If the surface is already in memory, no need to do anything here... */
3616 GLenum buffer_format;
3617 GLenum buffer_color;
3621 TRACE(" copying %s buffer to main memory with rectangle (%ldx%ld) - (%ldx%ld).\n", (buffer_type == WINE_GL_BUFFER_BACK ? "back" : "front"),
3622 pRect->left, pRect->top, pRect->right, pRect->bottom);
3624 /* Note that here we cannot do 'optmizations' about the WriteOnly flag... Indeed, a game
3625 may only write to the device... But when we will blit it back to the screen, we need
3626 also to blit correctly the parts the application did not overwrite... */
3628 if (((This->surface_desc.u4.ddpfPixelFormat.dwFlags & DDPF_RGB) != 0) &&
3629 (((This->surface_desc.u4.ddpfPixelFormat.dwFlags & DDPF_ALPHAPIXELS) == 0) ||
3630 (This->surface_desc.u4.ddpfPixelFormat.u5.dwRGBAlphaBitMask == 0x00000000))) {
3631 if ((This->surface_desc.u4.ddpfPixelFormat.u1.dwRGBBitCount == 16) &&
3632 (This->surface_desc.u4.ddpfPixelFormat.u2.dwRBitMask == 0xF800) &&
3633 (This->surface_desc.u4.ddpfPixelFormat.u3.dwGBitMask == 0x07E0) &&
3634 (This->surface_desc.u4.ddpfPixelFormat.u4.dwBBitMask == 0x001F)) {
3635 buffer_format = GL_UNSIGNED_SHORT_5_6_5;
3636 buffer_color = GL_RGB;
3637 } else if ((This->surface_desc.u4.ddpfPixelFormat.u1.dwRGBBitCount == 24) &&
3638 (This->surface_desc.u4.ddpfPixelFormat.u2.dwRBitMask == 0xFF0000) &&
3639 (This->surface_desc.u4.ddpfPixelFormat.u3.dwGBitMask == 0x00FF00) &&
3640 (This->surface_desc.u4.ddpfPixelFormat.u4.dwBBitMask == 0x0000FF)) {
3641 buffer_format = GL_UNSIGNED_BYTE;
3642 buffer_color = GL_RGB;
3643 } else if ((This->surface_desc.u4.ddpfPixelFormat.u1.dwRGBBitCount == 32) &&
3644 (This->surface_desc.u4.ddpfPixelFormat.u2.dwRBitMask == 0x00FF0000) &&
3645 (This->surface_desc.u4.ddpfPixelFormat.u3.dwGBitMask == 0x0000FF00) &&
3646 (This->surface_desc.u4.ddpfPixelFormat.u4.dwBBitMask == 0x000000FF)) {
3647 buffer_format = GL_UNSIGNED_INT_8_8_8_8_REV;
3648 buffer_color = GL_BGRA;
3650 ERR(" unsupported pixel format at device locking.\n");
3654 ERR(" unsupported pixel format at device locking - alpha on frame buffer.\n");
3660 if (buffer_type == WINE_GL_BUFFER_FRONT)
3661 /* Application wants to lock the front buffer */
3662 glReadBuffer(GL_FRONT);
3664 /* Application wants to lock the back buffer */
3665 glReadBuffer(GL_BACK);
3667 dst = ((char *)This->surface_desc.lpSurface) +
3668 (pRect->top * This->surface_desc.u1.lPitch) + (pRect->left * GET_BPP(This->surface_desc));
3669 for (y = (This->surface_desc.dwHeight - pRect->top - 1);
3670 y >= ((int) This->surface_desc.dwHeight - (int) pRect->bottom);
3672 glReadPixels(pRect->left, y,
3673 pRect->right - pRect->left, 1,
3674 buffer_color, buffer_format, dst);
3675 dst += This->surface_desc.u1.lPitch;
3678 gl_d3d_dev->state[buffer_type] = SURFACE_MEMORY;
3681 /* I keep this code here as it's very useful to debug :-) */
3683 static int flush_count = 0;
3687 if ((++flush_count % 50) == 0) {
3688 sprintf(buf, "lock_%06d.pnm", flush_count);
3689 f = fopen(buf, "wb");
3690 DDRAW_dump_surface_to_disk(This, f);
3699 static void d3ddevice_flush_to_frame_buffer(IDirect3DDeviceImpl *d3d_dev, LPCRECT pRect, IDirectDrawSurfaceImpl *surf) {
3701 IDirect3DDeviceGLImpl* gl_d3d_dev = (IDirect3DDeviceGLImpl*) d3d_dev;
3706 /* Note : no need here to lock the 'device critical section' as we are already protected by
3707 the GL critical section. */
3709 if (pRect == NULL) {
3712 loc_rect.bottom = d3d_dev->surface->surface_desc.dwHeight;
3713 loc_rect.right = d3d_dev->surface->surface_desc.dwWidth;
3717 TRACE(" flushing memory back to screen memory (%ld,%ld) x (%ld,%ld).\n", pRect->top, pRect->left, pRect->right, pRect->bottom);
3719 opt_bitmap = d3ddevice_set_state_for_flush(d3d_dev, pRect, FALSE, &initial);
3721 if (upload_surface_to_tex_memory_init(surf, 0, &gl_d3d_dev->current_internal_format,
3722 initial, FALSE, UNLOCK_TEX_SIZE, UNLOCK_TEX_SIZE) != DD_OK) {
3723 ERR(" unsupported pixel format at frame buffer flush.\n");
3727 for (y = pRect->top; y < pRect->bottom; y += UNLOCK_TEX_SIZE) {
3731 flush_rect.bottom = (y + UNLOCK_TEX_SIZE > pRect->bottom) ? pRect->bottom : (y + UNLOCK_TEX_SIZE);
3733 for (x = pRect->left; x < pRect->right; x += UNLOCK_TEX_SIZE) {
3734 /* First, upload the texture... */
3735 flush_rect.left = x;
3736 flush_rect.right = (x + UNLOCK_TEX_SIZE > pRect->right) ? pRect->right : (x + UNLOCK_TEX_SIZE);
3738 upload_surface_to_tex_memory(&flush_rect, 0, 0, &(gl_d3d_dev->surface_ptr));
3741 glTexCoord2f(0.0, 0.0);
3742 glVertex3d(x, y, 0.5);
3743 glTexCoord2f(1.0, 0.0);
3744 glVertex3d(x + UNLOCK_TEX_SIZE, y, 0.5);
3745 glTexCoord2f(1.0, 1.0);
3746 glVertex3d(x + UNLOCK_TEX_SIZE, y + UNLOCK_TEX_SIZE, 0.5);
3747 glTexCoord2f(0.0, 1.0);
3748 glVertex3d(x, y + UNLOCK_TEX_SIZE, 0.5);
3753 upload_surface_to_tex_memory_release();
3754 d3ddevice_restore_state_after_flush(d3d_dev, opt_bitmap, FALSE);
3757 /* I keep this code here as it's very useful to debug :-) */
3759 static int flush_count = 0;
3763 if ((++flush_count % 50) == 0) {
3764 sprintf(buf, "flush_%06d.pnm", flush_count);
3765 f = fopen(buf, "wb");
3766 DDRAW_dump_surface_to_disk(surf, f);
3772 static void d3ddevice_unlock_update(IDirectDrawSurfaceImpl* This, LPCRECT pRect)
3774 WINE_GL_BUFFER_TYPE buffer_type;
3775 IDirect3DDeviceImpl *d3d_dev = This->d3ddevice;
3776 IDirect3DDeviceGLImpl* gl_d3d_dev = (IDirect3DDeviceGLImpl*) d3d_dev;
3778 if ((This->surface_desc.ddsCaps.dwCaps & (DDSCAPS_FRONTBUFFER|DDSCAPS_PRIMARYSURFACE)) != 0) {
3779 buffer_type = WINE_GL_BUFFER_FRONT;
3780 } else if ((This->surface_desc.ddsCaps.dwCaps & (DDSCAPS_BACKBUFFER)) == (DDSCAPS_BACKBUFFER)) {
3781 buffer_type = WINE_GL_BUFFER_BACK;
3783 ERR("Wrong surface type for locking !\n");
3787 if (gl_d3d_dev->lock_rect_valid[buffer_type] == FALSE) {
3788 ERR("Unlock without prior lock on %s buffer... Expect problems !\n",
3789 (buffer_type == WINE_GL_BUFFER_BACK ? "back" : "front"));
3791 gl_d3d_dev->lock_rect_valid[buffer_type] = FALSE;
3793 /* First, check if we need to do anything. For the backbuffer, flushing is done at the next 3D activity. */
3794 if ((This->lastlocktype & DDLOCK_READONLY) == 0) {
3795 if (buffer_type == WINE_GL_BUFFER_FRONT) {
3798 TRACE(" flushing front buffer immediatly on screen.\n");
3801 glGetIntegerv(GL_DRAW_BUFFER, &prev_draw);
3802 glDrawBuffer(GL_FRONT);
3803 /* Note: we do not use the application provided lock rectangle but our own stored at
3804 lock time. This is because in old D3D versions, the 'lock' parameter did not
3807 d3d_dev->flush_to_framebuffer(d3d_dev, &(gl_d3d_dev->lock_rect[WINE_GL_BUFFER_FRONT]), gl_d3d_dev->lock_surf[WINE_GL_BUFFER_FRONT]);
3808 glDrawBuffer(prev_draw);
3811 gl_d3d_dev->state[WINE_GL_BUFFER_BACK] = SURFACE_MEMORY_DIRTY;
3815 /* And 'frees' the device critical section */
3816 LeaveCriticalSection(&(d3d_dev->crit));
3820 apply_texture_state(IDirect3DDeviceImpl *This)
3824 /* Initialize texture stages states */
3825 for (stage = 0; stage < MAX_TEXTURES; stage++) {
3826 for (state = 0; state < HIGHEST_TEXTURE_STAGE_STATE; state += 1) {
3827 if (This->state_block.set_flags.texture_stage_state[stage][state] == TRUE) {
3828 IDirect3DDevice7_SetTextureStageState(ICOM_INTERFACE(This, IDirect3DDevice7),
3829 stage, state + 1, This->state_block.texture_stage_state[stage][state]);
3836 d3ddevice_create(IDirect3DDeviceImpl **obj, IDirectDrawImpl *d3d, IDirectDrawSurfaceImpl *surface, BOOLEAN from_surface)
3838 IDirect3DDeviceImpl *object;
3839 IDirect3DDeviceGLImpl *gl_object;
3840 IDirectDrawSurfaceImpl *surf;
3845 XVisualInfo template;
3846 GLenum buffer = GL_FRONT;
3849 object = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(IDirect3DDeviceGLImpl));
3850 if (object == NULL) return DDERR_OUTOFMEMORY;
3852 gl_object = (IDirect3DDeviceGLImpl *) object;
3856 object->surface = surface;
3857 object->set_context = set_context;
3858 object->clear = d3ddevice_clear_back;
3859 object->set_matrices = d3ddevice_set_matrices;
3860 object->matrices_updated = d3ddevice_matrices_updated;
3861 object->flush_to_framebuffer = d3ddevice_flush_to_frame_buffer;
3863 TRACE(" creating OpenGL device for surface = %p, d3d = %p\n", surface, d3d);
3865 InitializeCriticalSection(&(object->crit));
3867 TRACE(" device critical section : %p\n", &(object->crit));
3869 /* This is just a hack for some badly done games :-/ */
3871 gl_object->version = 1;
3872 TRACE(" using D3D1 special hacks.\n");
3874 gl_object->version = 7;
3876 device_context = GetDC(surface->ddraw_owner->window);
3877 gl_object->display = get_display(device_context);
3878 gl_object->drawable = get_drawable(device_context);
3879 ReleaseDC(surface->ddraw_owner->window,device_context);
3882 template.visualid = (VisualID)GetPropA( GetDesktopWindow(), "__wine_x11_visual_id" );
3883 vis = XGetVisualInfo(gl_object->display, VisualIDMask, &template, &num);
3885 HeapFree(GetProcessHeap(), 0, object);
3886 ERR("No visual found !\n");
3888 return DDERR_INVALIDPARAMS;
3890 TRACE(" visual found\n");
3893 gl_object->gl_context = glXCreateContext(gl_object->display, vis,
3896 if (gl_object->gl_context == NULL) {
3897 HeapFree(GetProcessHeap(), 0, object);
3898 ERR("Error in context creation !\n");
3900 return DDERR_INVALIDPARAMS;
3902 TRACE(" context created (%p)\n", gl_object->gl_context);
3905 /* Look for the front buffer and override its surface's Flip method (if in double buffering) */
3906 for (surf = surface; surf != NULL; surf = surf->surface_owner) {
3907 if ((surf->surface_desc.ddsCaps.dwCaps&(DDSCAPS_FLIP|DDSCAPS_FRONTBUFFER)) == (DDSCAPS_FLIP|DDSCAPS_FRONTBUFFER)) {
3908 surf->aux_ctx = (LPVOID) object;
3909 surf->aux_data = (LPVOID) gl_object->drawable;
3910 surf->aux_flip = opengl_flip;
3915 /* We are not doing any double buffering.. Then force OpenGL to draw on the front buffer */
3917 TRACE(" no double buffering : drawing on the front buffer\n");
3921 for (surf = surface; surf != NULL; surf = surf->surface_owner) {
3922 IDirectDrawSurfaceImpl *surf2;
3923 for (surf2 = surf; surf2->prev_attached != NULL; surf2 = surf2->prev_attached) ;
3924 for (; surf2 != NULL; surf2 = surf2->next_attached) {
3925 TRACE(" checking surface %p :", surf2);
3926 if (((surf2->surface_desc.ddsCaps.dwCaps & (DDSCAPS_3DDEVICE)) == (DDSCAPS_3DDEVICE)) &&
3927 ((surf2->surface_desc.ddsCaps.dwCaps & (DDSCAPS_ZBUFFER)) != (DDSCAPS_ZBUFFER))) {
3928 /* Override the Lock / Unlock function for all these surfaces */
3929 surf2->lock_update_prev = surf2->lock_update;
3930 surf2->lock_update = d3ddevice_lock_update;
3931 surf2->unlock_update_prev = surf2->unlock_update;
3932 surf2->unlock_update = d3ddevice_unlock_update;
3933 /* And install also the blt / bltfast overrides */
3934 surf2->aux_blt = d3ddevice_blt;
3935 surf2->aux_bltfast = d3ddevice_bltfast;
3937 TRACE(" overiding direct surface access.\n");
3939 TRACE(" no overide.\n");
3941 surf2->d3ddevice = object;
3945 /* Set the various light parameters */
3946 for (light = 0; light < MAX_LIGHTS; light++) {
3947 /* Only set the fields that are not zero-created */
3948 object->light_parameters[light].dltType = D3DLIGHT_DIRECTIONAL;
3949 object->light_parameters[light].dcvDiffuse.u1.r = 1.0;
3950 object->light_parameters[light].dcvDiffuse.u2.g = 1.0;
3951 object->light_parameters[light].dcvDiffuse.u3.b = 1.0;
3952 object->light_parameters[light].dvDirection.u3.z = 1.0;
3955 /* Allocate memory for the matrices */
3956 object->world_mat = (D3DMATRIX *) HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, 16 * sizeof(float));
3957 object->view_mat = (D3DMATRIX *) HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, 16 * sizeof(float));
3958 object->proj_mat = (D3DMATRIX *) HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, 16 * sizeof(float));
3959 memcpy(object->world_mat, id_mat, 16 * sizeof(float));
3960 memcpy(object->view_mat , id_mat, 16 * sizeof(float));
3961 memcpy(object->proj_mat , id_mat, 16 * sizeof(float));
3962 for (tex_num = 0; tex_num < MAX_TEXTURES; tex_num++) {
3963 object->tex_mat[tex_num] = (D3DMATRIX *) HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, 16 * sizeof(float));
3964 memcpy(object->tex_mat[tex_num], id_mat, 16 * sizeof(float));
3965 object->tex_mat_is_identity[tex_num] = TRUE;
3968 /* Initialisation */
3969 TRACE(" setting current context\n");
3970 object->set_context(object);
3971 TRACE(" current context set\n");
3973 /* allocate the clipping planes */
3974 object->max_clipping_planes = opengl_device_caps.wMaxUserClipPlanes;
3975 object->clipping_planes = (d3d7clippingplane*)HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, object->max_clipping_planes * sizeof(d3d7clippingplane));
3977 glHint(GL_FOG_HINT,GL_NICEST);
3979 /* Initialize the various GL contexts to be in sync with what we store locally */
3982 glClearColor(0.0, 0.0, 0.0, 0.0);
3983 glDepthMask(GL_TRUE);
3984 gl_object->depth_mask = TRUE;
3985 glEnable(GL_DEPTH_TEST);
3986 gl_object->depth_test = TRUE;
3987 glDisable(GL_ALPHA_TEST);
3988 glDisable(GL_STENCIL_TEST);
3989 glDisable(GL_CULL_FACE);
3990 glDisable(GL_LIGHTING);
3991 glDisable(GL_BLEND);
3993 glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);
3994 gl_object->current_tex_env = GL_REPLACE;
3995 gl_object->current_active_tex_unit = GL_TEXTURE0_WINE;
3996 if (GL_extensions.glActiveTexture != NULL) {
3997 GL_extensions.glActiveTexture(GL_TEXTURE0_WINE);
3999 gl_object->current_alpha_test_ref = 0.0;
4000 gl_object->current_alpha_test_func = GL_ALWAYS;
4001 glAlphaFunc(GL_ALWAYS, 0.0);
4003 glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
4004 glDrawBuffer(buffer);
4005 glReadBuffer(buffer);
4006 /* glDisable(GL_DEPTH_TEST); Need here to check for the presence of a ZBuffer and to reenable it when the ZBuffer is attached */
4009 gl_object->state[WINE_GL_BUFFER_BACK] = SURFACE_GL;
4010 gl_object->state[WINE_GL_BUFFER_FRONT] = SURFACE_GL;
4012 /* fill_device_capabilities(d3d->ddraw); */
4014 ICOM_INIT_INTERFACE(object, IDirect3DDevice, VTABLE_IDirect3DDevice);
4015 ICOM_INIT_INTERFACE(object, IDirect3DDevice2, VTABLE_IDirect3DDevice2);
4016 ICOM_INIT_INTERFACE(object, IDirect3DDevice3, VTABLE_IDirect3DDevice3);
4017 ICOM_INIT_INTERFACE(object, IDirect3DDevice7, VTABLE_IDirect3DDevice7);
4021 TRACE(" creating implementation at %p.\n", *obj);
4023 /* And finally warn D3D that this device is now present */
4024 object->d3d->d3d_added_device(object->d3d, object);
4026 /* FIXME: Should handle other versions than just 7 */
4027 InitDefaultStateBlock(&object->state_block, 7);
4028 /* Apply default render state and texture stage state values */
4029 apply_render_state(object, &object->state_block);
4030 apply_texture_state(object);
4032 /* And fill the fog table with the default fog value */
4033 build_fog_table(gl_object->fog_table, object->state_block.render_state[D3DRENDERSTATE_FOGCOLOR - 1]);
4038 static void fill_opengl_primcaps(D3DPRIMCAPS *pc)
4040 pc->dwSize = sizeof(*pc);
4041 pc->dwMiscCaps = D3DPMISCCAPS_CONFORMANT | D3DPMISCCAPS_CULLCCW | D3DPMISCCAPS_CULLCW |
4042 D3DPMISCCAPS_LINEPATTERNREP | D3DPMISCCAPS_MASKPLANES | D3DPMISCCAPS_MASKZ;
4043 pc->dwRasterCaps = D3DPRASTERCAPS_DITHER | D3DPRASTERCAPS_FOGRANGE | D3DPRASTERCAPS_FOGTABLE |
4044 D3DPRASTERCAPS_FOGVERTEX | D3DPRASTERCAPS_STIPPLE | D3DPRASTERCAPS_ZBIAS | D3DPRASTERCAPS_ZTEST | D3DPRASTERCAPS_SUBPIXEL |
4045 D3DPRASTERCAPS_ZFOG;
4046 if (GL_extensions.mipmap_lodbias == TRUE) {
4047 pc->dwRasterCaps |= D3DPRASTERCAPS_MIPMAPLODBIAS;
4049 pc->dwZCmpCaps = D3DPCMPCAPS_ALWAYS | D3DPCMPCAPS_EQUAL | D3DPCMPCAPS_GREATER | D3DPCMPCAPS_GREATEREQUAL |
4050 D3DPCMPCAPS_LESS | D3DPCMPCAPS_LESSEQUAL | D3DPCMPCAPS_NEVER | D3DPCMPCAPS_NOTEQUAL;
4051 pc->dwSrcBlendCaps = D3DPBLENDCAPS_ZERO | D3DPBLENDCAPS_ONE | D3DPBLENDCAPS_DESTCOLOR | D3DPBLENDCAPS_INVDESTCOLOR |
4052 D3DPBLENDCAPS_SRCALPHA | D3DPBLENDCAPS_INVSRCALPHA | D3DPBLENDCAPS_DESTALPHA | D3DPBLENDCAPS_INVDESTALPHA | D3DPBLENDCAPS_SRCALPHASAT |
4053 D3DPBLENDCAPS_BOTHSRCALPHA | D3DPBLENDCAPS_BOTHINVSRCALPHA;
4054 pc->dwDestBlendCaps = D3DPBLENDCAPS_ZERO | D3DPBLENDCAPS_ONE | D3DPBLENDCAPS_SRCCOLOR | D3DPBLENDCAPS_INVSRCCOLOR |
4055 D3DPBLENDCAPS_SRCALPHA | D3DPBLENDCAPS_INVSRCALPHA | D3DPBLENDCAPS_DESTALPHA | D3DPBLENDCAPS_INVDESTALPHA | D3DPBLENDCAPS_SRCALPHASAT |
4056 D3DPBLENDCAPS_BOTHSRCALPHA | D3DPBLENDCAPS_BOTHINVSRCALPHA;
4057 pc->dwAlphaCmpCaps = D3DPCMPCAPS_ALWAYS | D3DPCMPCAPS_EQUAL | D3DPCMPCAPS_GREATER | D3DPCMPCAPS_GREATEREQUAL |
4058 D3DPCMPCAPS_LESS | D3DPCMPCAPS_LESSEQUAL | D3DPCMPCAPS_NEVER | D3DPCMPCAPS_NOTEQUAL;
4059 pc->dwShadeCaps = D3DPSHADECAPS_ALPHAFLATBLEND | D3DPSHADECAPS_ALPHAGOURAUDBLEND | D3DPSHADECAPS_COLORFLATRGB | D3DPSHADECAPS_COLORGOURAUDRGB |
4060 D3DPSHADECAPS_FOGFLAT | D3DPSHADECAPS_FOGGOURAUD | D3DPSHADECAPS_SPECULARFLATRGB | D3DPSHADECAPS_SPECULARGOURAUDRGB;
4061 pc->dwTextureCaps = D3DPTEXTURECAPS_ALPHA | D3DPTEXTURECAPS_ALPHAPALETTE | D3DPTEXTURECAPS_BORDER | D3DPTEXTURECAPS_PERSPECTIVE |
4062 D3DPTEXTURECAPS_POW2 | D3DPTEXTURECAPS_TRANSPARENCY;
4063 pc->dwTextureFilterCaps = D3DPTFILTERCAPS_LINEAR | D3DPTFILTERCAPS_LINEARMIPLINEAR | D3DPTFILTERCAPS_LINEARMIPNEAREST |
4064 D3DPTFILTERCAPS_MIPLINEAR | D3DPTFILTERCAPS_MIPNEAREST | D3DPTFILTERCAPS_NEAREST | D3DPTFILTERCAPS_MAGFLINEAR |
4065 D3DPTFILTERCAPS_MAGFPOINT | D3DPTFILTERCAPS_MINFLINEAR | D3DPTFILTERCAPS_MINFPOINT | D3DPTFILTERCAPS_MIPFLINEAR |
4066 D3DPTFILTERCAPS_MIPFPOINT;
4067 pc->dwTextureBlendCaps = D3DPTBLENDCAPS_ADD | D3DPTBLENDCAPS_COPY | D3DPTBLENDCAPS_DECAL | D3DPTBLENDCAPS_DECALALPHA | D3DPTBLENDCAPS_DECALMASK |
4068 D3DPTBLENDCAPS_MODULATE | D3DPTBLENDCAPS_MODULATEALPHA | D3DPTBLENDCAPS_MODULATEMASK;
4069 pc->dwTextureAddressCaps = D3DPTADDRESSCAPS_BORDER | D3DPTADDRESSCAPS_CLAMP | D3DPTADDRESSCAPS_WRAP | D3DPTADDRESSCAPS_INDEPENDENTUV;
4070 if (GL_extensions.mirrored_repeat == TRUE) {
4071 pc->dwTextureAddressCaps |= D3DPTADDRESSCAPS_MIRROR;
4073 pc->dwStippleWidth = 32;
4074 pc->dwStippleHeight = 32;
4077 static void fill_caps(void)
4079 GLint max_clip_planes;
4082 /* Fill first all the fields with default values which will be overriden later on with
4083 correct ones from the GL code
4085 opengl_device_caps.dwDevCaps = D3DDEVCAPS_CANRENDERAFTERFLIP | D3DDEVCAPS_DRAWPRIMTLVERTEX | D3DDEVCAPS_EXECUTESYSTEMMEMORY |
4086 D3DDEVCAPS_EXECUTEVIDEOMEMORY | D3DDEVCAPS_FLOATTLVERTEX | D3DDEVCAPS_TEXTURENONLOCALVIDMEM | D3DDEVCAPS_TEXTURESYSTEMMEMORY |
4087 D3DDEVCAPS_TEXTUREVIDEOMEMORY | D3DDEVCAPS_TLVERTEXSYSTEMMEMORY | D3DDEVCAPS_TLVERTEXVIDEOMEMORY |
4088 /* D3D 7 capabilities */
4089 D3DDEVCAPS_DRAWPRIMITIVES2 | D3DDEVCAPS_HWTRANSFORMANDLIGHT | D3DDEVCAPS_HWRASTERIZATION;
4090 fill_opengl_primcaps(&(opengl_device_caps.dpcLineCaps));
4091 fill_opengl_primcaps(&(opengl_device_caps.dpcTriCaps));
4092 opengl_device_caps.dwDeviceRenderBitDepth = DDBD_16|DDBD_24|DDBD_32;
4093 opengl_device_caps.dwMinTextureWidth = 1;
4094 opengl_device_caps.dwMinTextureHeight = 1;
4095 opengl_device_caps.dwMaxTextureWidth = 1024;
4096 opengl_device_caps.dwMaxTextureHeight = 1024;
4097 opengl_device_caps.dwMaxTextureRepeat = 16;
4098 opengl_device_caps.dwMaxTextureAspectRatio = 1024;
4099 opengl_device_caps.dwMaxAnisotropy = 0;
4100 opengl_device_caps.dvGuardBandLeft = 0.0;
4101 opengl_device_caps.dvGuardBandRight = 0.0;
4102 opengl_device_caps.dvGuardBandTop = 0.0;
4103 opengl_device_caps.dvGuardBandBottom = 0.0;
4104 opengl_device_caps.dvExtentsAdjust = 0.0;
4105 opengl_device_caps.dwStencilCaps = D3DSTENCILCAPS_DECRSAT | D3DSTENCILCAPS_INCRSAT | D3DSTENCILCAPS_INVERT | D3DSTENCILCAPS_KEEP |
4106 D3DSTENCILCAPS_REPLACE | D3DSTENCILCAPS_ZERO;
4107 opengl_device_caps.dwTextureOpCaps = D3DTEXOPCAPS_DISABLE | D3DTEXOPCAPS_SELECTARG1 | D3DTEXOPCAPS_SELECTARG2 | D3DTEXOPCAPS_MODULATE4X |
4108 D3DTEXOPCAPS_MODULATE2X | D3DTEXOPCAPS_MODULATE | D3DTEXOPCAPS_ADD | D3DTEXOPCAPS_ADDSIGNED2X | D3DTEXOPCAPS_ADDSIGNED |
4109 D3DTEXOPCAPS_BLENDDIFFUSEALPHA | D3DTEXOPCAPS_BLENDTEXTUREALPHA | D3DTEXOPCAPS_BLENDFACTORALPHA | D3DTEXOPCAPS_BLENDCURRENTALPHA;
4110 if (GL_extensions.max_texture_units != 0) {
4111 opengl_device_caps.wMaxTextureBlendStages = GL_extensions.max_texture_units;
4112 opengl_device_caps.wMaxSimultaneousTextures = GL_extensions.max_texture_units;
4113 opengl_device_caps.dwFVFCaps = D3DFVFCAPS_DONOTSTRIPELEMENTS | GL_extensions.max_texture_units;
4115 opengl_device_caps.wMaxTextureBlendStages = 1;
4116 opengl_device_caps.wMaxSimultaneousTextures = 1;
4117 opengl_device_caps.dwFVFCaps = D3DFVFCAPS_DONOTSTRIPELEMENTS | 1;
4119 opengl_device_caps.dwMaxActiveLights = 16;
4120 opengl_device_caps.dvMaxVertexW = 100000000.0; /* No idea exactly what to put here... */
4121 opengl_device_caps.deviceGUID = IID_IDirect3DTnLHalDevice;
4122 opengl_device_caps.wMaxUserClipPlanes = 1;
4123 opengl_device_caps.wMaxVertexBlendMatrices = 0;
4124 opengl_device_caps.dwVertexProcessingCaps = D3DVTXPCAPS_TEXGEN | D3DVTXPCAPS_MATERIALSOURCE7 | D3DVTXPCAPS_VERTEXFOG |
4125 D3DVTXPCAPS_DIRECTIONALLIGHTS | D3DVTXPCAPS_POSITIONALLIGHTS | D3DVTXPCAPS_LOCALVIEWER;
4126 opengl_device_caps.dwReserved1 = 0;
4127 opengl_device_caps.dwReserved2 = 0;
4128 opengl_device_caps.dwReserved3 = 0;
4129 opengl_device_caps.dwReserved4 = 0;
4131 /* And now some GL overides :-) */
4132 glGetIntegerv(GL_MAX_TEXTURE_SIZE, (GLint *) &opengl_device_caps.dwMaxTextureWidth);
4133 opengl_device_caps.dwMaxTextureHeight = opengl_device_caps.dwMaxTextureWidth;
4134 opengl_device_caps.dwMaxTextureAspectRatio = opengl_device_caps.dwMaxTextureWidth;
4135 TRACE(": max texture size = %ld\n", opengl_device_caps.dwMaxTextureWidth);
4137 glGetIntegerv(GL_MAX_LIGHTS, (GLint *) &opengl_device_caps.dwMaxActiveLights);
4138 TRACE(": max active lights = %ld\n", opengl_device_caps.dwMaxActiveLights);
4140 glGetIntegerv(GL_MAX_CLIP_PLANES, &max_clip_planes);
4141 opengl_device_caps.wMaxUserClipPlanes = max_clip_planes;
4142 TRACE(": max clipping planes = %d\n", opengl_device_caps.wMaxUserClipPlanes);
4144 glGetIntegerv(GL_DEPTH_BITS, &depth_bits);
4145 TRACE(": Z bits = %d\n", depth_bits);
4146 switch (depth_bits) {
4147 case 16: opengl_device_caps.dwDeviceZBufferBitDepth = DDBD_16; break;
4148 case 24: opengl_device_caps.dwDeviceZBufferBitDepth = DDBD_16|DDBD_24; break;
4150 default: opengl_device_caps.dwDeviceZBufferBitDepth = DDBD_16|DDBD_24|DDBD_32; break;
4155 d3ddevice_init_at_startup(void *gl_handle)
4157 XVisualInfo template;
4162 Drawable drawable = (Drawable) GetPropA(GetDesktopWindow(), "__wine_x11_whole_window");
4163 XWindowAttributes win_attr;
4164 GLXContext gl_context;
4166 const char *glExtensions;
4167 const char *glVersion;
4168 const char *glXExtensions = NULL;
4169 const void *(*pglXGetProcAddressARB)(const GLubyte *) = NULL;
4170 int major, minor, patch, num_parsed;
4172 TRACE("Initializing GL...\n");
4174 /* Get a default rendering context to have the 'caps' function query some info from GL */
4175 device_context = GetDC(0);
4176 display = get_display(device_context);
4177 ReleaseDC(0, device_context);
4180 if (XGetWindowAttributes(display, drawable, &win_attr)) {
4181 visual = win_attr.visual;
4183 visual = DefaultVisual(display, DefaultScreen(display));
4185 template.visualid = XVisualIDFromVisual(visual);
4186 vis = XGetVisualInfo(display, VisualIDMask, &template, &num);
4189 WARN("Error creating visual info for capabilities initialization - D3D support disabled !\n");
4192 gl_context = glXCreateContext(display, vis, NULL, GL_TRUE);
4194 if (gl_context == NULL) {
4196 WARN("Error creating default context for capabilities initialization - D3D support disabled !\n");
4199 if (glXMakeCurrent(display, drawable, gl_context) == False) {
4200 glXDestroyContext(display, gl_context);
4202 WARN("Error setting default context as current for capabilities initialization - D3D support disabled !\n");
4206 /* Then, query all extensions */
4207 glXExtensions = glXQueryExtensionsString(display, DefaultScreen(display));
4208 glExtensions = (const char *) glGetString(GL_EXTENSIONS);
4209 glVersion = (const char *) glGetString(GL_VERSION);
4210 if ((glXExtensions != NULL) && (gl_handle != NULL) && (strstr(glXExtensions, "GLX_ARB_get_proc_address"))) {
4211 pglXGetProcAddressARB = wine_dlsym(gl_handle, "glXGetProcAddressARB", NULL, 0);
4214 /* Parse the GL version string */
4215 num_parsed = sscanf(glVersion, "%d.%d.%d", &major, &minor, &patch);
4216 if (num_parsed == 1) {
4219 } else if (num_parsed == 2) {
4222 TRACE("GL version %d.%d.%d\n", major, minor, patch);
4224 /* And starts to fill the extension context properly */
4225 memset(&GL_extensions, 0, sizeof(GL_extensions));
4226 TRACE("GL supports following extensions used by Wine :\n");
4228 /* Mirrored Repeat extension :
4229 - GL_ARB_texture_mirrored_repeat
4230 - GL_IBM_texture_mirrored_repeat
4233 if ((strstr(glExtensions, "GL_ARB_texture_mirrored_repeat")) ||
4234 (strstr(glExtensions, "GL_IBM_texture_mirrored_repeat")) ||
4236 ((major == 1) && (minor >= 4))) {
4237 TRACE(" - mirrored repeat\n");
4238 GL_extensions.mirrored_repeat = TRUE;
4241 /* Texture LOD Bias :
4242 - GL_EXT_texture_lod_bias
4244 if (strstr(glExtensions, "GL_EXT_texture_lod_bias")) {
4245 TRACE(" - texture lod bias\n");
4246 GL_extensions.mipmap_lodbias = TRUE;
4249 /* For all subsequent extensions, we need glXGetProcAddress */
4250 if (pglXGetProcAddressARB != NULL) {
4251 /* Multi-texturing :
4252 - GL_ARB_multitexture
4255 if ((strstr(glExtensions, "GL_ARB_multitexture")) ||
4257 ((major == 1) && (minor > 2)) ||
4258 ((major == 1) && (minor == 2) && (patch >= 1))) {
4259 glGetIntegerv(GL_MAX_TEXTURE_UNITS_WINE, &(GL_extensions.max_texture_units));
4260 TRACE(" - multi-texturing (%d stages)\n", GL_extensions.max_texture_units);
4261 /* We query the ARB version to be the most portable we can... */
4262 GL_extensions.glActiveTexture = pglXGetProcAddressARB("glActiveTextureARB");
4263 GL_extensions.glMultiTexCoord2fv = pglXGetProcAddressARB("glMultiTexCoord2fv");
4264 GL_extensions.glClientActiveTexture = pglXGetProcAddressARB("glClientActiveTextureARB");
4268 /* Fill the D3D capabilities according to what GL tells us... */
4271 /* And frees this now-useless context */
4272 glXMakeCurrent(display, None, NULL);
4273 glXDestroyContext(display, gl_context);