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 that in the future all calls will go through vertex arrays but the arrays
1360 will be generated by this function. */
1361 if (((d3dvtVertexType & D3DFVF_POSITION_MASK) == D3DFVF_XYZ) && /* Standard XYZ vertices */
1362 (((d3dvtVertexType & (D3DFVF_DIFFUSE|D3DFVF_SPECULAR)) == 0) || /* Either no colours */
1363 (((d3dvtVertexType & D3DFVF_DIFFUSE) != 0) && /* Or diffuse only but the Alpha component is not used */
1364 (This->state_block.render_state[D3DRENDERSTATE_ALPHATESTENABLE - 1] == FALSE) &&
1365 (This->state_block.render_state[D3DRENDERSTATE_ALPHABLENDENABLE - 1] == FALSE)))) {
1367 TRACE(" using GL vertex arrays for performance !\n");
1368 /* First, the vertices (we are sure we have some :-) */
1369 glEnableClientState(GL_VERTEX_ARRAY);
1370 glVertexPointer(3, GL_FLOAT, lpD3DDrawPrimStrideData->position.dwStride, lpD3DDrawPrimStrideData->position.lpvData);
1371 /* Then the normals */
1372 if (d3dvtVertexType & D3DFVF_NORMAL) {
1373 glEnableClientState(GL_NORMAL_ARRAY);
1374 glNormalPointer(GL_FLOAT, lpD3DDrawPrimStrideData->normal.dwStride, lpD3DDrawPrimStrideData->normal.lpvData);
1376 /* Then the diffuse colour */
1377 if (d3dvtVertexType & D3DFVF_DIFFUSE) {
1378 glEnableClientState(GL_COLOR_ARRAY);
1379 glColorPointer(3, GL_UNSIGNED_BYTE, lpD3DDrawPrimStrideData->normal.dwStride,
1380 ((char *) lpD3DDrawPrimStrideData->diffuse.lpvData));
1382 /* Then the various textures */
1383 for (tex_stage = 0; tex_stage < num_active_stages; tex_stage++) {
1384 int tex_index = This->state_block.texture_stage_state[tex_stage][D3DTSS_TEXCOORDINDEX - 1] & 0x0000FFFF;
1385 if (tex_index >= num_tex_index) {
1386 WARN("Default texture coordinate not handled in the vertex array path !!!\n");
1387 tex_index = num_tex_index - 1;
1389 if (GL_extensions.glClientActiveTexture) {
1390 GL_extensions.glClientActiveTexture(GL_TEXTURE0_WINE + tex_stage);
1392 glEnableClientState(GL_TEXTURE_COORD_ARRAY);
1393 glTexCoordPointer(2, GL_FLOAT, lpD3DDrawPrimStrideData->textureCoords[tex_index].dwStride,
1394 lpD3DDrawPrimStrideData->textureCoords[tex_index].lpvData);
1396 if (dwIndices != NULL) {
1397 glDrawElements(convert_D3D_ptype_to_GL(d3dptPrimitiveType), dwIndexCount, GL_UNSIGNED_SHORT, dwIndices);
1399 glDrawArrays(convert_D3D_ptype_to_GL(d3dptPrimitiveType), 0, dwIndexCount);
1401 glDisableClientState(GL_VERTEX_ARRAY);
1402 if (d3dvtVertexType & D3DFVF_NORMAL) {
1403 glDisableClientState(GL_NORMAL_ARRAY);
1405 if (d3dvtVertexType & D3DFVF_DIFFUSE) {
1406 glDisableClientState(GL_COLOR_ARRAY);
1408 for (tex_stage = 0; tex_stage < num_active_stages; tex_stage++) {
1409 if (GL_extensions.glClientActiveTexture) {
1410 GL_extensions.glClientActiveTexture(GL_TEXTURE0_WINE + tex_stage);
1412 glDisableClientState(GL_TEXTURE_COORD_ARRAY);
1415 glBegin(convert_D3D_ptype_to_GL(d3dptPrimitiveType));
1417 /* Some fast paths first before the generic case.... */
1418 if ((d3dvtVertexType == D3DFVF_VERTEX) && (num_active_stages <= 1)) {
1421 for (index = 0; index < dwIndexCount; index++) {
1422 int i = (dwIndices == NULL) ? index : dwIndices[index];
1424 (D3DVALUE *) (((char *) lpD3DDrawPrimStrideData->normal.lpvData) + i * lpD3DDrawPrimStrideData->normal.dwStride);
1425 D3DVALUE *tex_coord =
1426 (D3DVALUE *) (((char *) lpD3DDrawPrimStrideData->textureCoords[0].lpvData) + i * lpD3DDrawPrimStrideData->textureCoords[0].dwStride);
1427 D3DVALUE *position =
1428 (D3DVALUE *) (((char *) lpD3DDrawPrimStrideData->position.lpvData) + i * lpD3DDrawPrimStrideData->position.dwStride);
1430 handle_normal(normal);
1431 handle_texture(tex_coord);
1432 handle_xyz(position);
1434 TRACE_(ddraw_geom)(" %f %f %f / %f %f %f (%f %f)\n",
1435 position[0], position[1], position[2],
1436 normal[0], normal[1], normal[2],
1437 tex_coord[0], tex_coord[1]);
1439 } else if ((d3dvtVertexType == D3DFVF_TLVERTEX) && (num_active_stages <= 1)) {
1442 for (index = 0; index < dwIndexCount; index++) {
1443 int i = (dwIndices == NULL) ? index : dwIndices[index];
1445 (DWORD *) (((char *) lpD3DDrawPrimStrideData->diffuse.lpvData) + i * lpD3DDrawPrimStrideData->diffuse.dwStride);
1447 (DWORD *) (((char *) lpD3DDrawPrimStrideData->specular.lpvData) + i * lpD3DDrawPrimStrideData->specular.dwStride);
1448 D3DVALUE *tex_coord =
1449 (D3DVALUE *) (((char *) lpD3DDrawPrimStrideData->textureCoords[0].lpvData) + i * lpD3DDrawPrimStrideData->textureCoords[0].dwStride);
1450 D3DVALUE *position =
1451 (D3DVALUE *) (((char *) lpD3DDrawPrimStrideData->position.lpvData) + i * lpD3DDrawPrimStrideData->position.dwStride);
1453 handle_diffuse_and_specular(&(This->state_block), glThis->fog_table, color_d, color_s, TRUE);
1454 handle_texture(tex_coord);
1455 handle_xyzrhw(position);
1457 TRACE_(ddraw_geom)(" %f %f %f %f / %02lx %02lx %02lx %02lx - %02lx %02lx %02lx %02lx (%f %f)\n",
1458 position[0], position[1], position[2], position[3],
1459 (*color_d >> 16) & 0xFF,
1460 (*color_d >> 8) & 0xFF,
1461 (*color_d >> 0) & 0xFF,
1462 (*color_d >> 24) & 0xFF,
1463 (*color_s >> 16) & 0xFF,
1464 (*color_s >> 8) & 0xFF,
1465 (*color_s >> 0) & 0xFF,
1466 (*color_s >> 24) & 0xFF,
1467 tex_coord[0], tex_coord[1]);
1469 } else if (((d3dvtVertexType & D3DFVF_POSITION_MASK) == D3DFVF_XYZ) ||
1470 ((d3dvtVertexType & D3DFVF_POSITION_MASK) == D3DFVF_XYZRHW)) {
1471 /* This is the 'slow path' but that should support all possible vertex formats out there...
1472 Note that people should write a fast path for all vertex formats out there...
1475 static const D3DVALUE no_index[] = { 0.0, 0.0, 0.0, 0.0 };
1477 for (index = 0; index < dwIndexCount; index++) {
1478 int i = (dwIndices == NULL) ? index : dwIndices[index];
1481 if (d3dvtVertexType & D3DFVF_NORMAL) {
1483 (D3DVALUE *) (((char *) lpD3DDrawPrimStrideData->normal.lpvData) + i * lpD3DDrawPrimStrideData->normal.dwStride);
1484 handle_normal(normal);
1486 if ((d3dvtVertexType & (D3DFVF_DIFFUSE|D3DFVF_SPECULAR)) == (D3DFVF_DIFFUSE|D3DFVF_SPECULAR)) {
1488 (DWORD *) (((char *) lpD3DDrawPrimStrideData->diffuse.lpvData) + i * lpD3DDrawPrimStrideData->diffuse.dwStride);
1490 (DWORD *) (((char *) lpD3DDrawPrimStrideData->specular.lpvData) + i * lpD3DDrawPrimStrideData->specular.dwStride);
1491 handle_diffuse_and_specular(&(This->state_block), glThis->fog_table, color_d, color_s, vertex_lighted);
1493 if (d3dvtVertexType & D3DFVF_SPECULAR) {
1495 (DWORD *) (((char *) lpD3DDrawPrimStrideData->specular.lpvData) + i * lpD3DDrawPrimStrideData->specular.dwStride);
1496 handle_specular(&(This->state_block), color_s, vertex_lighted);
1497 } else if (d3dvtVertexType & D3DFVF_DIFFUSE) {
1499 (DWORD *) (((char *) lpD3DDrawPrimStrideData->diffuse.lpvData) + i * lpD3DDrawPrimStrideData->diffuse.dwStride);
1500 handle_diffuse(&(This->state_block), color_d, vertex_lighted);
1504 for (tex_stage = 0; tex_stage < num_active_stages; tex_stage++) {
1505 int tex_index = This->state_block.texture_stage_state[tex_stage][D3DTSS_TEXCOORDINDEX - 1] & 0x0000FFFF;
1506 if (tex_index >= num_tex_index) {
1507 handle_textures((D3DVALUE *) no_index, tex_stage);
1509 D3DVALUE *tex_coord =
1510 (D3DVALUE *) (((char *) lpD3DDrawPrimStrideData->textureCoords[tex_index].lpvData) +
1511 i * lpD3DDrawPrimStrideData->textureCoords[tex_index].dwStride);
1512 handle_textures(tex_coord, tex_stage);
1516 if ((d3dvtVertexType & D3DFVF_POSITION_MASK) == D3DFVF_XYZ) {
1517 D3DVALUE *position =
1518 (D3DVALUE *) (((char *) lpD3DDrawPrimStrideData->position.lpvData) + i * lpD3DDrawPrimStrideData->position.dwStride);
1519 handle_xyz(position);
1520 } else if ((d3dvtVertexType & D3DFVF_POSITION_MASK) == D3DFVF_XYZRHW) {
1521 D3DVALUE *position =
1522 (D3DVALUE *) (((char *) lpD3DDrawPrimStrideData->position.lpvData) + i * lpD3DDrawPrimStrideData->position.dwStride);
1523 handle_xyzrhw(position);
1526 if (TRACE_ON(ddraw_geom)) {
1529 if ((d3dvtVertexType & D3DFVF_POSITION_MASK) == D3DFVF_XYZ) {
1530 D3DVALUE *position =
1531 (D3DVALUE *) (((char *) lpD3DDrawPrimStrideData->position.lpvData) + i * lpD3DDrawPrimStrideData->position.dwStride);
1532 TRACE_(ddraw_geom)(" %f %f %f", position[0], position[1], position[2]);
1533 } else if ((d3dvtVertexType & D3DFVF_POSITION_MASK) == D3DFVF_XYZRHW) {
1534 D3DVALUE *position =
1535 (D3DVALUE *) (((char *) lpD3DDrawPrimStrideData->position.lpvData) + i * lpD3DDrawPrimStrideData->position.dwStride);
1536 TRACE_(ddraw_geom)(" %f %f %f %f", position[0], position[1], position[2], position[3]);
1538 if (d3dvtVertexType & D3DFVF_NORMAL) {
1540 (D3DVALUE *) (((char *) lpD3DDrawPrimStrideData->normal.lpvData) + i * lpD3DDrawPrimStrideData->normal.dwStride);
1541 TRACE_(ddraw_geom)(" / %f %f %f", normal[0], normal[1], normal[2]);
1543 if (d3dvtVertexType & D3DFVF_DIFFUSE) {
1545 (DWORD *) (((char *) lpD3DDrawPrimStrideData->diffuse.lpvData) + i * lpD3DDrawPrimStrideData->diffuse.dwStride);
1546 TRACE_(ddraw_geom)(" / %02lx %02lx %02lx %02lx",
1547 (*color_d >> 16) & 0xFF,
1548 (*color_d >> 8) & 0xFF,
1549 (*color_d >> 0) & 0xFF,
1550 (*color_d >> 24) & 0xFF);
1552 if (d3dvtVertexType & D3DFVF_SPECULAR) {
1554 (DWORD *) (((char *) lpD3DDrawPrimStrideData->specular.lpvData) + i * lpD3DDrawPrimStrideData->specular.dwStride);
1555 TRACE_(ddraw_geom)(" / %02lx %02lx %02lx %02lx",
1556 (*color_s >> 16) & 0xFF,
1557 (*color_s >> 8) & 0xFF,
1558 (*color_s >> 0) & 0xFF,
1559 (*color_s >> 24) & 0xFF);
1561 for (tex_index = 0; tex_index < ((d3dvtVertexType & D3DFVF_TEXCOUNT_MASK) >> D3DFVF_TEXCOUNT_SHIFT); tex_index++) {
1562 D3DVALUE *tex_coord =
1563 (D3DVALUE *) (((char *) lpD3DDrawPrimStrideData->textureCoords[tex_index].lpvData) +
1564 i * lpD3DDrawPrimStrideData->textureCoords[tex_index].dwStride);
1565 TRACE_(ddraw_geom)(" / %f %f", tex_coord[0], tex_coord[1]);
1567 TRACE_(ddraw_geom)("\n");
1571 ERR(" matrix weighting not handled yet....\n");
1577 /* Whatever the case, disable the color material stuff */
1578 glDisable(GL_COLOR_MATERIAL);
1583 LeaveCriticalSection(&(This->crit));
1587 GL_IDirect3DDeviceImpl_7_3T_DrawPrimitive(LPDIRECT3DDEVICE7 iface,
1588 D3DPRIMITIVETYPE d3dptPrimitiveType,
1589 DWORD d3dvtVertexType,
1591 DWORD dwVertexCount,
1594 ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice7, iface);
1595 D3DDRAWPRIMITIVESTRIDEDDATA strided;
1597 TRACE("(%p/%p)->(%08x,%08lx,%p,%08lx,%08lx)\n", This, iface, d3dptPrimitiveType, d3dvtVertexType, lpvVertices, dwVertexCount, dwFlags);
1598 if (TRACE_ON(ddraw)) {
1599 TRACE(" - flags : "); dump_DPFLAGS(dwFlags);
1602 convert_FVF_to_strided_data(d3dvtVertexType, lpvVertices, &strided, 0);
1603 draw_primitive_strided(This, d3dptPrimitiveType, d3dvtVertexType, &strided, dwVertexCount, NULL, dwVertexCount, dwFlags);
1609 GL_IDirect3DDeviceImpl_7_3T_DrawIndexedPrimitive(LPDIRECT3DDEVICE7 iface,
1610 D3DPRIMITIVETYPE d3dptPrimitiveType,
1611 DWORD d3dvtVertexType,
1613 DWORD dwVertexCount,
1618 ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice7, iface);
1619 D3DDRAWPRIMITIVESTRIDEDDATA strided;
1621 TRACE("(%p/%p)->(%08x,%08lx,%p,%08lx,%p,%08lx,%08lx)\n", This, iface, d3dptPrimitiveType, d3dvtVertexType, lpvVertices, dwVertexCount, dwIndices, dwIndexCount, dwFlags);
1622 if (TRACE_ON(ddraw)) {
1623 TRACE(" - flags : "); dump_DPFLAGS(dwFlags);
1626 convert_FVF_to_strided_data(d3dvtVertexType, lpvVertices, &strided, 0);
1627 draw_primitive_strided(This, d3dptPrimitiveType, d3dvtVertexType, &strided, dwVertexCount, dwIndices, dwIndexCount, dwFlags);
1633 GL_IDirect3DDeviceImpl_7_3T_DrawPrimitiveStrided(LPDIRECT3DDEVICE7 iface,
1634 D3DPRIMITIVETYPE d3dptPrimitiveType,
1636 LPD3DDRAWPRIMITIVESTRIDEDDATA lpD3DDrawPrimStrideData,
1637 DWORD dwVertexCount,
1640 ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice7, iface);
1642 TRACE("(%p/%p)->(%08x,%08lx,%p,%08lx,%08lx)\n", This, iface, d3dptPrimitiveType, dwVertexType, lpD3DDrawPrimStrideData, dwVertexCount, dwFlags);
1643 if (TRACE_ON(ddraw)) {
1644 TRACE(" - flags : "); dump_DPFLAGS(dwFlags);
1646 draw_primitive_strided(This, d3dptPrimitiveType, dwVertexType, lpD3DDrawPrimStrideData, dwVertexCount, NULL, dwVertexCount, dwFlags);
1652 GL_IDirect3DDeviceImpl_7_3T_DrawIndexedPrimitiveStrided(LPDIRECT3DDEVICE7 iface,
1653 D3DPRIMITIVETYPE d3dptPrimitiveType,
1655 LPD3DDRAWPRIMITIVESTRIDEDDATA lpD3DDrawPrimStrideData,
1656 DWORD dwVertexCount,
1661 ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice7, iface);
1663 TRACE("(%p/%p)->(%08x,%08lx,%p,%08lx,%p,%08lx,%08lx)\n", This, iface, d3dptPrimitiveType, dwVertexType, lpD3DDrawPrimStrideData, dwVertexCount, lpIndex, dwIndexCount, dwFlags);
1664 if (TRACE_ON(ddraw)) {
1665 TRACE(" - flags : "); dump_DPFLAGS(dwFlags);
1668 draw_primitive_strided(This, d3dptPrimitiveType, dwVertexType, lpD3DDrawPrimStrideData, dwVertexCount, lpIndex, dwIndexCount, dwFlags);
1674 GL_IDirect3DDeviceImpl_7_3T_DrawPrimitiveVB(LPDIRECT3DDEVICE7 iface,
1675 D3DPRIMITIVETYPE d3dptPrimitiveType,
1676 LPDIRECT3DVERTEXBUFFER7 lpD3DVertexBuf,
1677 DWORD dwStartVertex,
1678 DWORD dwNumVertices,
1681 ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice7, iface);
1682 IDirect3DVertexBufferImpl *vb_impl = ICOM_OBJECT(IDirect3DVertexBufferImpl, IDirect3DVertexBuffer7, lpD3DVertexBuf);
1683 D3DDRAWPRIMITIVESTRIDEDDATA strided;
1685 TRACE("(%p/%p)->(%08x,%p,%08lx,%08lx,%08lx)\n", This, iface, d3dptPrimitiveType, lpD3DVertexBuf, dwStartVertex, dwNumVertices, dwFlags);
1686 if (TRACE_ON(ddraw)) {
1687 TRACE(" - flags : "); dump_DPFLAGS(dwFlags);
1690 if (vb_impl->processed == TRUE) {
1691 IDirect3DVertexBufferGLImpl *vb_glimp = (IDirect3DVertexBufferGLImpl *) vb_impl;
1692 IDirect3DDeviceGLImpl *glThis = (IDirect3DDeviceGLImpl *) This;
1694 glThis->transform_state = GL_TRANSFORM_VERTEXBUFFER;
1695 This->set_matrices(This, VIEWMAT_CHANGED|WORLDMAT_CHANGED|PROJMAT_CHANGED,
1696 &(vb_glimp->world_mat), &(vb_glimp->view_mat), &(vb_glimp->proj_mat));
1698 convert_FVF_to_strided_data(vb_glimp->dwVertexTypeDesc, vb_glimp->vertices, &strided, dwStartVertex);
1699 draw_primitive_strided(This, d3dptPrimitiveType, vb_glimp->dwVertexTypeDesc, &strided, dwNumVertices, NULL, dwNumVertices, dwFlags);
1702 convert_FVF_to_strided_data(vb_impl->desc.dwFVF, vb_impl->vertices, &strided, dwStartVertex);
1703 draw_primitive_strided(This, d3dptPrimitiveType, vb_impl->desc.dwFVF, &strided, dwNumVertices, NULL, dwNumVertices, dwFlags);
1710 GL_IDirect3DDeviceImpl_7_3T_DrawIndexedPrimitiveVB(LPDIRECT3DDEVICE7 iface,
1711 D3DPRIMITIVETYPE d3dptPrimitiveType,
1712 LPDIRECT3DVERTEXBUFFER7 lpD3DVertexBuf,
1713 DWORD dwStartVertex,
1714 DWORD dwNumVertices,
1719 ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice7, iface);
1720 IDirect3DVertexBufferImpl *vb_impl = ICOM_OBJECT(IDirect3DVertexBufferImpl, IDirect3DVertexBuffer7, lpD3DVertexBuf);
1721 D3DDRAWPRIMITIVESTRIDEDDATA strided;
1723 TRACE("(%p/%p)->(%08x,%p,%08lx,%08lx,%p,%08lx,%08lx)\n", This, iface, d3dptPrimitiveType, lpD3DVertexBuf, dwStartVertex, dwNumVertices, lpwIndices, dwIndexCount, dwFlags);
1724 if (TRACE_ON(ddraw)) {
1725 TRACE(" - flags : "); dump_DPFLAGS(dwFlags);
1728 if (vb_impl->processed == TRUE) {
1729 IDirect3DVertexBufferGLImpl *vb_glimp = (IDirect3DVertexBufferGLImpl *) vb_impl;
1730 IDirect3DDeviceGLImpl *glThis = (IDirect3DDeviceGLImpl *) This;
1732 glThis->transform_state = GL_TRANSFORM_VERTEXBUFFER;
1733 This->set_matrices(This, VIEWMAT_CHANGED|WORLDMAT_CHANGED|PROJMAT_CHANGED,
1734 &(vb_glimp->world_mat), &(vb_glimp->view_mat), &(vb_glimp->proj_mat));
1736 convert_FVF_to_strided_data(vb_glimp->dwVertexTypeDesc, vb_glimp->vertices, &strided, dwStartVertex);
1737 draw_primitive_strided(This, d3dptPrimitiveType, vb_glimp->dwVertexTypeDesc, &strided, dwNumVertices, lpwIndices, dwIndexCount, dwFlags);
1740 convert_FVF_to_strided_data(vb_impl->desc.dwFVF, vb_impl->vertices, &strided, dwStartVertex);
1741 draw_primitive_strided(This, d3dptPrimitiveType, vb_impl->desc.dwFVF, &strided, dwNumVertices, lpwIndices, dwIndexCount, dwFlags);
1747 /* We need a static function for that to handle the 'special' case of 'SELECT_ARG2' */
1749 handle_color_alpha_args(IDirect3DDeviceImpl *This, DWORD dwStage, D3DTEXTURESTAGESTATETYPE d3dTexStageStateType, DWORD dwState, D3DTEXTUREOP tex_op)
1751 BOOLEAN is_complement = FALSE;
1752 BOOLEAN is_alpha_replicate = FALSE;
1753 BOOLEAN handled = TRUE;
1755 BOOLEAN is_color = ((d3dTexStageStateType == D3DTSS_COLORARG1) || (d3dTexStageStateType == D3DTSS_COLORARG2));
1759 if (d3dTexStageStateType == D3DTSS_COLORARG1) num = 0;
1760 else if (d3dTexStageStateType == D3DTSS_COLORARG2) num = 1;
1765 if (tex_op == D3DTOP_SELECTARG2) {
1769 if (d3dTexStageStateType == D3DTSS_ALPHAARG1) num = 0;
1770 else if (d3dTexStageStateType == D3DTSS_ALPHAARG2) num = 1;
1775 if (tex_op == D3DTOP_SELECTARG2) {
1780 if (dwState & D3DTA_COMPLEMENT) {
1781 is_complement = TRUE;
1783 if (dwState & D3DTA_ALPHAREPLICATE) {
1784 is_alpha_replicate = TRUE;
1786 dwState &= D3DTA_SELECTMASK;
1787 if ((dwStage == 0) && (dwState == D3DTA_CURRENT)) {
1788 dwState = D3DTA_DIFFUSE;
1792 case D3DTA_CURRENT: src = GL_PREVIOUS_EXT; break;
1793 case D3DTA_DIFFUSE: src = GL_PRIMARY_COLOR_EXT; break;
1794 case D3DTA_TEXTURE: src = GL_TEXTURE; break;
1795 case D3DTA_TFACTOR: {
1796 /* Get the constant value from the current rendering state */
1798 DWORD col = This->state_block.render_state[D3DRENDERSTATE_TEXTUREFACTOR - 1];
1800 color[0] = ((col >> 16) & 0xFF) / 255.0f;
1801 color[1] = ((col >> 8) & 0xFF) / 255.0f;
1802 color[2] = ((col >> 0) & 0xFF) / 255.0f;
1803 color[3] = ((col >> 24) & 0xFF) / 255.0f;
1804 glTexEnvfv(GL_TEXTURE_ENV, GL_TEXTURE_ENV_COLOR, color);
1806 src = GL_CONSTANT_EXT;
1808 default: src = GL_TEXTURE; handled = FALSE; break;
1812 glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_RGB_EXT + num, src);
1813 if (is_alpha_replicate) {
1814 glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND0_RGB_EXT + num, is_complement ? GL_ONE_MINUS_SRC_ALPHA : GL_SRC_ALPHA);
1816 glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND0_RGB_EXT + num, is_complement ? GL_ONE_MINUS_SRC_COLOR : GL_SRC_COLOR);
1819 glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_ALPHA_EXT + num, src);
1820 glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND0_ALPHA_EXT + num, is_complement ? GL_ONE_MINUS_SRC_ALPHA : GL_SRC_ALPHA);
1827 GL_IDirect3DDeviceImpl_7_3T_SetTextureStageState(LPDIRECT3DDEVICE7 iface,
1829 D3DTEXTURESTAGESTATETYPE d3dTexStageStateType,
1832 ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice7, iface);
1833 IDirect3DDeviceGLImpl *glThis = (IDirect3DDeviceGLImpl *) This;
1838 TRACE("(%p/%p)->(%08lx,%08x,%08lx)\n", This, iface, dwStage, d3dTexStageStateType, dwState);
1840 if (((GL_extensions.max_texture_units == 0) && (dwStage > 0)) ||
1841 ((GL_extensions.max_texture_units != 0) && (dwStage >= GL_extensions.max_texture_units))) {
1845 unit = GL_TEXTURE0_WINE + dwStage;
1846 if (unit != glThis->current_active_tex_unit) {
1847 GL_extensions.glActiveTexture(unit);
1848 glThis->current_active_tex_unit = unit;
1851 switch (d3dTexStageStateType) {
1852 #define GEN_CASE(a) case a: type = #a; break
1853 GEN_CASE(D3DTSS_COLOROP);
1854 GEN_CASE(D3DTSS_COLORARG1);
1855 GEN_CASE(D3DTSS_COLORARG2);
1856 GEN_CASE(D3DTSS_ALPHAOP);
1857 GEN_CASE(D3DTSS_ALPHAARG1);
1858 GEN_CASE(D3DTSS_ALPHAARG2);
1859 GEN_CASE(D3DTSS_BUMPENVMAT00);
1860 GEN_CASE(D3DTSS_BUMPENVMAT01);
1861 GEN_CASE(D3DTSS_BUMPENVMAT10);
1862 GEN_CASE(D3DTSS_BUMPENVMAT11);
1863 GEN_CASE(D3DTSS_TEXCOORDINDEX);
1864 GEN_CASE(D3DTSS_ADDRESS);
1865 GEN_CASE(D3DTSS_ADDRESSU);
1866 GEN_CASE(D3DTSS_ADDRESSV);
1867 GEN_CASE(D3DTSS_BORDERCOLOR);
1868 GEN_CASE(D3DTSS_MAGFILTER);
1869 GEN_CASE(D3DTSS_MINFILTER);
1870 GEN_CASE(D3DTSS_MIPFILTER);
1871 GEN_CASE(D3DTSS_MIPMAPLODBIAS);
1872 GEN_CASE(D3DTSS_MAXMIPLEVEL);
1873 GEN_CASE(D3DTSS_MAXANISOTROPY);
1874 GEN_CASE(D3DTSS_BUMPENVLSCALE);
1875 GEN_CASE(D3DTSS_BUMPENVLOFFSET);
1876 GEN_CASE(D3DTSS_TEXTURETRANSFORMFLAGS);
1878 default: type = "UNKNOWN";
1881 /* Store the values in the state array */
1882 prev_state = This->state_block.texture_stage_state[dwStage][d3dTexStageStateType - 1];
1883 This->state_block.texture_stage_state[dwStage][d3dTexStageStateType - 1] = dwState;
1884 /* Some special cases when one state modifies more than one... */
1885 if (d3dTexStageStateType == D3DTSS_ADDRESS) {
1886 This->state_block.texture_stage_state[dwStage][D3DTSS_ADDRESSU - 1] = dwState;
1887 This->state_block.texture_stage_state[dwStage][D3DTSS_ADDRESSV - 1] = dwState;
1892 switch (d3dTexStageStateType) {
1893 case D3DTSS_MINFILTER:
1894 case D3DTSS_MIPFILTER:
1895 if (TRACE_ON(ddraw)) {
1896 if (d3dTexStageStateType == D3DTSS_MINFILTER) {
1897 switch ((D3DTEXTUREMINFILTER) dwState) {
1898 case D3DTFN_POINT: TRACE(" Stage type is : D3DTSS_MINFILTER => D3DTFN_POINT\n"); break;
1899 case D3DTFN_LINEAR: TRACE(" Stage type is : D3DTSS_MINFILTER => D3DTFN_LINEAR\n"); break;
1900 default: FIXME(" Unhandled stage type : D3DTSS_MINFILTER => %08lx\n", dwState); break;
1903 switch ((D3DTEXTUREMIPFILTER) dwState) {
1904 case D3DTFP_NONE: TRACE(" Stage type is : D3DTSS_MIPFILTER => D3DTFP_NONE\n"); break;
1905 case D3DTFP_POINT: TRACE(" Stage type is : D3DTSS_MIPFILTER => D3DTFP_POINT\n"); break;
1906 case D3DTFP_LINEAR: TRACE(" Stage type is : D3DTSS_MIPFILTER => D3DTFP_LINEAR\n"); break;
1907 default: FIXME(" Unhandled stage type : D3DTSS_MIPFILTER => %08lx\n", dwState); break;
1913 case D3DTSS_MAGFILTER:
1914 if (TRACE_ON(ddraw)) {
1915 switch ((D3DTEXTUREMAGFILTER) dwState) {
1916 case D3DTFG_POINT: TRACE(" Stage type is : D3DTSS_MAGFILTER => D3DTFG_POINT\n"); break;
1917 case D3DTFG_LINEAR: TRACE(" Stage type is : D3DTSS_MAGFILTER => D3DTFG_LINEAR\n"); break;
1918 default: FIXME(" Unhandled stage type : D3DTSS_MAGFILTER => %08lx\n", dwState); break;
1923 case D3DTSS_ADDRESS:
1924 case D3DTSS_ADDRESSU:
1925 case D3DTSS_ADDRESSV: {
1926 switch ((D3DTEXTUREADDRESS) dwState) {
1927 case D3DTADDRESS_WRAP: TRACE(" Stage type is : %s => D3DTADDRESS_WRAP\n", type); break;
1928 case D3DTADDRESS_CLAMP: TRACE(" Stage type is : %s => D3DTADDRESS_CLAMP\n", type); break;
1929 case D3DTADDRESS_BORDER: TRACE(" Stage type is : %s => D3DTADDRESS_BORDER\n", type); break;
1930 case D3DTADDRESS_MIRROR:
1931 if (GL_extensions.mirrored_repeat == TRUE) {
1932 TRACE(" Stage type is : %s => D3DTADDRESS_MIRROR\n", type);
1934 FIXME(" Stage type is : %s => D3DTADDRESS_MIRROR - not supported by GL !\n", type);
1937 default: FIXME(" Unhandled stage type : %s => %08lx\n", type, dwState); break;
1941 case D3DTSS_ALPHAOP:
1942 case D3DTSS_COLOROP: {
1944 GLenum parm = (d3dTexStageStateType == D3DTSS_ALPHAOP) ? GL_COMBINE_ALPHA_EXT : GL_COMBINE_RGB_EXT;
1949 #define GEN_CASE(a) case a: value = #a; break
1950 GEN_CASE(D3DTOP_DISABLE);
1951 GEN_CASE(D3DTOP_SELECTARG1);
1952 GEN_CASE(D3DTOP_SELECTARG2);
1953 GEN_CASE(D3DTOP_MODULATE);
1954 GEN_CASE(D3DTOP_MODULATE2X);
1955 GEN_CASE(D3DTOP_MODULATE4X);
1956 GEN_CASE(D3DTOP_ADD);
1957 GEN_CASE(D3DTOP_ADDSIGNED);
1958 GEN_CASE(D3DTOP_ADDSIGNED2X);
1959 GEN_CASE(D3DTOP_SUBTRACT);
1960 GEN_CASE(D3DTOP_ADDSMOOTH);
1961 GEN_CASE(D3DTOP_BLENDDIFFUSEALPHA);
1962 GEN_CASE(D3DTOP_BLENDTEXTUREALPHA);
1963 GEN_CASE(D3DTOP_BLENDFACTORALPHA);
1964 GEN_CASE(D3DTOP_BLENDTEXTUREALPHAPM);
1965 GEN_CASE(D3DTOP_BLENDCURRENTALPHA);
1966 GEN_CASE(D3DTOP_PREMODULATE);
1967 GEN_CASE(D3DTOP_MODULATEALPHA_ADDCOLOR);
1968 GEN_CASE(D3DTOP_MODULATECOLOR_ADDALPHA);
1969 GEN_CASE(D3DTOP_MODULATEINVALPHA_ADDCOLOR);
1970 GEN_CASE(D3DTOP_MODULATEINVCOLOR_ADDALPHA);
1971 GEN_CASE(D3DTOP_BUMPENVMAP);
1972 GEN_CASE(D3DTOP_BUMPENVMAPLUMINANCE);
1973 GEN_CASE(D3DTOP_DOTPRODUCT3);
1974 GEN_CASE(D3DTOP_FORCE_DWORD);
1976 default: value = "UNKNOWN";
1979 if ((d3dTexStageStateType == D3DTSS_COLOROP) && (dwState == D3DTOP_DISABLE)) {
1980 glDisable(GL_TEXTURE_2D);
1981 TRACE(" disabling 2D texturing.\n");
1983 /* Re-enable texturing only if COLOROP was not already disabled... */
1984 if ((glThis->current_bound_texture[dwStage] != NULL) &&
1985 (This->state_block.texture_stage_state[dwStage][D3DTSS_COLOROP - 1] != D3DTOP_DISABLE)) {
1986 glEnable(GL_TEXTURE_2D);
1987 TRACE(" enabling 2D texturing.\n");
1990 /* Re-Enable GL_TEXTURE_ENV_MODE, GL_COMBINE_EXT */
1991 if ((dwState != D3DTOP_DISABLE) &&
1992 (This->state_block.texture_stage_state[dwStage][D3DTSS_COLOROP - 1] != D3DTOP_DISABLE)) {
1993 if (glThis->current_tex_env != GL_COMBINE_EXT) {
1994 glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE_EXT);
1995 glThis->current_tex_env = GL_COMBINE_EXT;
1999 /* Now set up the operand correctly */
2001 case D3DTOP_DISABLE:
2002 /* Contrary to the docs, alpha can be disabled when colorop is enabled
2003 and it works, so ignore this op */
2004 TRACE(" Note : disable ALPHAOP but COLOROP enabled!\n");
2007 case D3DTOP_SELECTARG1:
2008 case D3DTOP_SELECTARG2:
2009 glTexEnvi(GL_TEXTURE_ENV, parm, GL_REPLACE);
2012 case D3DTOP_MODULATE4X:
2013 scale = scale * 2; /* Drop through */
2014 case D3DTOP_MODULATE2X:
2015 scale = scale * 2; /* Drop through */
2016 case D3DTOP_MODULATE:
2017 glTexEnvi(GL_TEXTURE_ENV, parm, GL_MODULATE);
2021 glTexEnvi(GL_TEXTURE_ENV, parm, GL_ADD);
2024 case D3DTOP_ADDSIGNED2X:
2025 scale = scale * 2; /* Drop through */
2026 case D3DTOP_ADDSIGNED:
2027 glTexEnvi(GL_TEXTURE_ENV, parm, GL_ADD_SIGNED_EXT);
2030 /* For the four blending modes, use the Arg2 parameter */
2031 case D3DTOP_BLENDDIFFUSEALPHA:
2032 case D3DTOP_BLENDTEXTUREALPHA:
2033 case D3DTOP_BLENDFACTORALPHA:
2034 case D3DTOP_BLENDCURRENTALPHA: {
2035 GLenum src = GL_PRIMARY_COLOR_EXT; /* Just to prevent a compiler warning.. */
2038 case D3DTOP_BLENDDIFFUSEALPHA: src = GL_PRIMARY_COLOR_EXT;
2039 case D3DTOP_BLENDTEXTUREALPHA: src = GL_TEXTURE;
2040 case D3DTOP_BLENDFACTORALPHA: src = GL_CONSTANT_EXT;
2041 case D3DTOP_BLENDCURRENTALPHA: src = GL_PREVIOUS_EXT;
2044 glTexEnvi(GL_TEXTURE_ENV, parm, GL_INTERPOLATE_EXT);
2045 glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE2_RGB_EXT, src);
2046 glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND2_RGB_EXT, GL_SRC_ALPHA);
2047 glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE2_ALPHA_EXT, src);
2048 glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND2_ALPHA_EXT, GL_SRC_ALPHA);
2057 if (((prev_state == D3DTOP_SELECTARG2) && (dwState != D3DTOP_SELECTARG2)) ||
2058 ((dwState == D3DTOP_SELECTARG2) && (prev_state != D3DTOP_SELECTARG2))) {
2059 /* Switch the arguments if needed... */
2060 if (d3dTexStageStateType == D3DTSS_COLOROP) {
2061 handle_color_alpha_args(This, dwStage, D3DTSS_COLORARG1,
2062 This->state_block.texture_stage_state[dwStage][D3DTSS_COLORARG1 - 1],
2064 handle_color_alpha_args(This, dwStage, D3DTSS_COLORARG2,
2065 This->state_block.texture_stage_state[dwStage][D3DTSS_COLORARG2 - 1],
2068 handle_color_alpha_args(This, dwStage, D3DTSS_ALPHAARG1,
2069 This->state_block.texture_stage_state[dwStage][D3DTSS_ALPHAARG1 - 1],
2071 handle_color_alpha_args(This, dwStage, D3DTSS_ALPHAARG2,
2072 This->state_block.texture_stage_state[dwStage][D3DTSS_ALPHAARG2 - 1],
2078 if (d3dTexStageStateType == D3DTSS_ALPHAOP) {
2079 glTexEnvi(GL_TEXTURE_ENV, GL_ALPHA_SCALE, scale);
2081 glTexEnvi(GL_TEXTURE_ENV, GL_RGB_SCALE_EXT, scale);
2083 TRACE(" Stage type is : %s => %s\n", type, value);
2085 FIXME(" Unhandled stage type is : %s => %s\n", type, value);
2089 case D3DTSS_COLORARG1:
2090 case D3DTSS_COLORARG2:
2091 case D3DTSS_ALPHAARG1:
2092 case D3DTSS_ALPHAARG2: {
2093 const char *value, *value_comp = "", *value_alpha = "";
2095 D3DTEXTUREOP tex_op;
2097 switch (dwState & D3DTA_SELECTMASK) {
2098 #define GEN_CASE(a) case a: value = #a; break
2099 GEN_CASE(D3DTA_DIFFUSE);
2100 GEN_CASE(D3DTA_CURRENT);
2101 GEN_CASE(D3DTA_TEXTURE);
2102 GEN_CASE(D3DTA_TFACTOR);
2103 GEN_CASE(D3DTA_SPECULAR);
2105 default: value = "UNKNOWN";
2107 if (dwState & D3DTA_COMPLEMENT) {
2108 value_comp = " | D3DTA_COMPLEMENT";
2110 if (dwState & D3DTA_ALPHAREPLICATE) {
2111 value_alpha = " | D3DTA_ALPHAREPLICATE";
2114 if ((d3dTexStageStateType == D3DTSS_COLORARG1) || (d3dTexStageStateType == D3DTSS_COLORARG2)) {
2115 tex_op = This->state_block.texture_stage_state[dwStage][D3DTSS_COLOROP - 1];
2117 tex_op = This->state_block.texture_stage_state[dwStage][D3DTSS_ALPHAOP - 1];
2120 handled = handle_color_alpha_args(This, dwStage, d3dTexStageStateType, dwState, tex_op);
2123 TRACE(" Stage type : %s => %s%s%s\n", type, value, value_comp, value_alpha);
2125 FIXME(" Unhandled stage type : %s => %s%s%s\n", type, value, value_comp, value_alpha);
2129 case D3DTSS_MIPMAPLODBIAS: {
2130 D3DVALUE value = *((D3DVALUE *) &dwState);
2131 BOOLEAN handled = TRUE;
2133 if ((value != 0.0) && (GL_extensions.mipmap_lodbias == FALSE))
2137 TRACE(" Stage type : D3DTSS_MIPMAPLODBIAS => %f\n", value);
2138 glTexEnvf(GL_TEXTURE_FILTER_CONTROL_WINE, GL_TEXTURE_LOD_BIAS_WINE, value);
2140 FIXME(" Unhandled stage type : D3DTSS_MIPMAPLODBIAS => %f\n", value);
2144 case D3DTSS_MAXMIPLEVEL:
2145 TRACE(" Stage type : D3DTSS_MAXMIPLEVEL => %ld\n", dwState);
2148 case D3DTSS_BORDERCOLOR:
2149 TRACE(" Stage type : D3DTSS_BORDERCOLOR => %02lx %02lx %02lx %02lx (RGBA)\n",
2150 ((dwState >> 16) & 0xFF),
2151 ((dwState >> 8) & 0xFF),
2152 ((dwState >> 0) & 0xFF),
2153 ((dwState >> 24) & 0xFF));
2156 case D3DTSS_TEXCOORDINDEX: {
2157 BOOLEAN handled = TRUE;
2160 switch (dwState & 0xFFFF0000) {
2161 #define GEN_CASE(a) case a: value = #a; break
2162 GEN_CASE(D3DTSS_TCI_PASSTHRU);
2163 GEN_CASE(D3DTSS_TCI_CAMERASPACENORMAL);
2164 GEN_CASE(D3DTSS_TCI_CAMERASPACEPOSITION);
2165 GEN_CASE(D3DTSS_TCI_CAMERASPACEREFLECTIONVECTOR);
2167 default: value = "UNKNOWN";
2169 if ((dwState & 0xFFFF0000) != D3DTSS_TCI_PASSTHRU)
2173 TRACE(" Stage type : D3DTSS_TEXCOORDINDEX => %ld | %s\n", dwState & 0x0000FFFF, value);
2175 FIXME(" Unhandled stage type : D3DTSS_TEXCOORDINDEX => %ld | %s\n", dwState & 0x0000FFFF, value);
2179 case D3DTSS_TEXTURETRANSFORMFLAGS: {
2180 const char *projected = "", *value;
2181 BOOLEAN handled = TRUE;
2182 switch (dwState & 0xFF) {
2183 #define GEN_CASE(a) case a: value = #a; break
2184 GEN_CASE(D3DTTFF_DISABLE);
2185 GEN_CASE(D3DTTFF_COUNT1);
2186 GEN_CASE(D3DTTFF_COUNT2);
2187 GEN_CASE(D3DTTFF_COUNT3);
2188 GEN_CASE(D3DTTFF_COUNT4);
2190 default: value = "UNKNOWN";
2192 if (dwState & D3DTTFF_PROJECTED) {
2193 projected = " | D3DTTFF_PROJECTED";
2197 if ((dwState & 0xFF) != D3DTTFF_DISABLE) {
2198 This->matrices_updated(This, TEXMAT0_CHANGED << dwStage);
2201 if (handled == TRUE) {
2202 TRACE(" Stage type : D3DTSS_TEXTURETRANSFORMFLAGS => %s%s\n", value, projected);
2204 FIXME(" Unhandled stage type : D3DTSS_TEXTURETRANSFORMFLAGS => %s%s\n", value, projected);
2209 FIXME(" Unhandled stage type : %s => %08lx\n", type, dwState);
2219 draw_primitive_handle_textures(IDirect3DDeviceImpl *This)
2221 IDirect3DDeviceGLImpl *glThis = (IDirect3DDeviceGLImpl *) This;
2223 BOOLEAN enable_colorkey = FALSE;
2225 for (stage = 0; stage < MAX_TEXTURES; stage++) {
2226 IDirectDrawSurfaceImpl *surf_ptr = This->current_texture[stage];
2229 /* If this stage is disabled, no need to go further... */
2230 if (This->state_block.texture_stage_state[stage][D3DTSS_COLOROP - 1] == D3DTOP_DISABLE)
2233 /* First check if we need to bind any other texture for this stage */
2234 if (This->current_texture[stage] != glThis->current_bound_texture[stage]) {
2235 if (This->current_texture[stage] == NULL) {
2236 TRACE(" disabling 2D texturing for stage %ld.\n", stage);
2238 unit = GL_TEXTURE0_WINE + stage;
2239 if (unit != glThis->current_active_tex_unit) {
2240 GL_extensions.glActiveTexture(unit);
2241 glThis->current_active_tex_unit = unit;
2243 glBindTexture(GL_TEXTURE_2D, 0);
2244 glDisable(GL_TEXTURE_2D);
2246 GLenum tex_name = ((IDirect3DTextureGLImpl *) surf_ptr->tex_private)->tex_name;
2248 unit = GL_TEXTURE0_WINE + stage;
2249 if (unit != glThis->current_active_tex_unit) {
2250 GL_extensions.glActiveTexture(unit);
2251 glThis->current_active_tex_unit = unit;
2254 if (glThis->current_bound_texture[stage] == NULL) {
2255 if (This->state_block.texture_stage_state[stage][D3DTSS_COLOROP - 1] != D3DTOP_DISABLE) {
2256 TRACE(" enabling 2D texturing and");
2257 glEnable(GL_TEXTURE_2D);
2260 TRACE(" activating OpenGL texture id %d for stage %ld.\n", tex_name, stage);
2261 glBindTexture(GL_TEXTURE_2D, tex_name);
2264 glThis->current_bound_texture[stage] = This->current_texture[stage];
2266 if (glThis->current_bound_texture[stage] == NULL) {
2267 TRACE(" displaying without texturing activated for stage %ld.\n", stage);
2269 TRACE(" using already bound texture id %d for stage %ld.\n",
2270 ((IDirect3DTextureGLImpl *) (glThis->current_bound_texture[stage])->tex_private)->tex_name, stage);
2274 /* If no texure valid for this stage, go out of the loop */
2275 if (This->current_texture[stage] == NULL) break;
2277 /* Then check if we need to flush this texture to GL or not (ie did it change) ?.
2278 This will also update the various texture parameters if needed.
2280 gltex_upload_texture(surf_ptr, This, stage);
2282 /* And finally check for color-keying (only on first stage) */
2283 if (This->current_texture[stage]->surface_desc.dwFlags & DDSD_CKSRCBLT) {
2285 enable_colorkey = TRUE;
2287 static BOOL warn = FALSE;
2288 if (warn == FALSE) {
2290 WARN(" Surface has color keying on stage different from 0 (%ld) !", stage);
2295 enable_colorkey = FALSE;
2300 /* Apparently, whatever the state of BLEND, color keying is always activated for 'old' D3D versions */
2301 if (((This->state_block.render_state[D3DRENDERSTATE_COLORKEYENABLE - 1]) ||
2302 (glThis->version == 1)) &&
2303 (enable_colorkey)) {
2304 TRACE(" colorkey activated.\n");
2306 if (glThis->alpha_test == FALSE) {
2307 glEnable(GL_ALPHA_TEST);
2308 glThis->alpha_test = TRUE;
2310 if ((glThis->current_alpha_test_func != GL_NOTEQUAL) || (glThis->current_alpha_test_ref != 0.0)) {
2311 if (This->state_block.render_state[D3DRENDERSTATE_ALPHATESTENABLE - 1] == TRUE) {
2312 static BOOL warn = FALSE;
2313 if (warn == FALSE) {
2315 WARN(" Overriding application-given alpha test values - some graphical glitches may appear !\n");
2318 glThis->current_alpha_test_func = GL_NOTEQUAL;
2319 glThis->current_alpha_test_ref = 0.0;
2320 glAlphaFunc(GL_NOTEQUAL, 0.0);
2322 /* Some sanity checks should be added here if a game mixes alphatest + color keying...
2323 Only one has been found for now, and the ALPHAFUNC is 'Always' so it works :-) */
2325 if (This->state_block.render_state[D3DRENDERSTATE_ALPHATESTENABLE - 1] == FALSE) {
2326 glDisable(GL_ALPHA_TEST);
2327 glThis->alpha_test = FALSE;
2329 /* Maybe we should restore here the application-given alpha test states ? */
2336 GL_IDirect3DDeviceImpl_7_3T_SetTexture(LPDIRECT3DDEVICE7 iface,
2338 LPDIRECTDRAWSURFACE7 lpTexture2)
2340 ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice7, iface);
2342 TRACE("(%p/%p)->(%08lx,%p)\n", This, iface, dwStage, lpTexture2);
2344 if (((GL_extensions.max_texture_units == 0) && (dwStage > 0)) ||
2345 ((GL_extensions.max_texture_units != 0) && (dwStage >= GL_extensions.max_texture_units))) {
2346 if (lpTexture2 != NULL) {
2347 WARN(" setting a texture to a non-supported texture stage !\n");
2352 if (This->current_texture[dwStage] != NULL) {
2353 IDirectDrawSurface7_Release(ICOM_INTERFACE(This->current_texture[dwStage], IDirectDrawSurface7));
2356 if (lpTexture2 == NULL) {
2357 This->current_texture[dwStage] = NULL;
2359 IDirectDrawSurfaceImpl *tex_impl = ICOM_OBJECT(IDirectDrawSurfaceImpl, IDirectDrawSurface7, lpTexture2);
2360 IDirectDrawSurface7_AddRef(ICOM_INTERFACE(tex_impl, IDirectDrawSurface7));
2361 This->current_texture[dwStage] = tex_impl;
2368 GL_IDirect3DDeviceImpl_7_GetCaps(LPDIRECT3DDEVICE7 iface,
2369 LPD3DDEVICEDESC7 lpD3DHELDevDesc)
2371 ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice7, iface);
2372 TRACE("(%p/%p)->(%p)\n", This, iface, lpD3DHELDevDesc);
2374 fill_opengl_caps_7(lpD3DHELDevDesc);
2376 TRACE(" returning caps : no dump function yet.\n");
2382 GL_IDirect3DDeviceImpl_7_SetMaterial(LPDIRECT3DDEVICE7 iface,
2383 LPD3DMATERIAL7 lpMat)
2385 ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice7, iface);
2386 TRACE("(%p/%p)->(%p)\n", This, iface, lpMat);
2388 if (TRACE_ON(ddraw)) {
2389 TRACE(" material is : \n");
2390 dump_D3DMATERIAL7(lpMat);
2393 This->current_material = *lpMat;
2396 glMaterialfv(GL_FRONT_AND_BACK,
2398 (float *) &(This->current_material.u.diffuse));
2399 glMaterialfv(GL_FRONT_AND_BACK,
2401 (float *) &(This->current_material.u1.ambient));
2402 glMaterialfv(GL_FRONT_AND_BACK,
2404 (float *) &(This->current_material.u2.specular));
2405 glMaterialfv(GL_FRONT_AND_BACK,
2407 (float *) &(This->current_material.u3.emissive));
2408 glMaterialf(GL_FRONT_AND_BACK,
2410 This->current_material.u4.power); /* Not sure about this... */
2418 GL_IDirect3DDeviceImpl_7_SetLight(LPDIRECT3DDEVICE7 iface,
2420 LPD3DLIGHT7 lpLight)
2422 ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice7, iface);
2423 IDirect3DDeviceGLImpl *glThis = (IDirect3DDeviceGLImpl *) This;
2424 TRACE("(%p/%p)->(%08lx,%p)\n", This, iface, dwLightIndex, lpLight);
2426 if (TRACE_ON(ddraw)) {
2427 TRACE(" setting light : \n");
2428 dump_D3DLIGHT7(lpLight);
2431 if (dwLightIndex >= MAX_LIGHTS) return DDERR_INVALIDPARAMS;
2432 This->set_lights |= 0x00000001 << dwLightIndex;
2433 This->light_parameters[dwLightIndex] = *lpLight;
2435 /* Some checks to print out nice warnings :-) */
2436 switch (lpLight->dltType) {
2437 case D3DLIGHT_DIRECTIONAL:
2438 case D3DLIGHT_POINT:
2439 /* These are handled properly... */
2443 if ((lpLight->dvTheta != 0.0) ||
2444 (lpLight->dvTheta != lpLight->dvPhi)) {
2445 ERR("dvTheta not fully supported yet !\n");
2450 ERR("Light type not handled yet : %08x !\n", lpLight->dltType);
2453 /* This will force the Light setting on next drawing of primitives */
2454 glThis->transform_state = GL_TRANSFORM_NONE;
2460 GL_IDirect3DDeviceImpl_7_LightEnable(LPDIRECT3DDEVICE7 iface,
2464 ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice7, iface);
2465 TRACE("(%p/%p)->(%08lx,%d)\n", This, iface, dwLightIndex, bEnable);
2467 if (dwLightIndex >= MAX_LIGHTS) return DDERR_INVALIDPARAMS;
2471 if (((0x00000001 << dwLightIndex) & This->set_lights) == 0) {
2472 /* Set the default parameters.. */
2473 TRACE(" setting default light parameters...\n");
2474 GL_IDirect3DDeviceImpl_7_SetLight(iface, dwLightIndex, &(This->light_parameters[dwLightIndex]));
2476 glEnable(GL_LIGHT0 + dwLightIndex);
2477 if ((This->active_lights & (0x00000001 << dwLightIndex)) == 0) {
2478 /* This light gets active... Need to update its parameters to GL before the next drawing */
2479 IDirect3DDeviceGLImpl *glThis = (IDirect3DDeviceGLImpl *) This;
2481 This->active_lights |= 0x00000001 << dwLightIndex;
2482 glThis->transform_state = GL_TRANSFORM_NONE;
2485 glDisable(GL_LIGHT0 + dwLightIndex);
2486 This->active_lights &= ~(0x00000001 << dwLightIndex);
2494 GL_IDirect3DDeviceImpl_7_SetClipPlane(LPDIRECT3DDEVICE7 iface, DWORD dwIndex, CONST D3DVALUE* pPlaneEquation)
2496 ICOM_THIS(IDirect3DDeviceImpl,iface);
2497 IDirect3DDeviceGLImpl* glThis = (IDirect3DDeviceGLImpl*) This;
2499 TRACE("(%p)->(%ld,%p)\n", This, dwIndex, pPlaneEquation);
2501 if (dwIndex >= This->max_clipping_planes) {
2502 return DDERR_INVALIDPARAMS;
2505 TRACE(" clip plane %ld : %f %f %f %f\n", dwIndex, pPlaneEquation[0], pPlaneEquation[1], pPlaneEquation[2], pPlaneEquation[3] );
2507 memcpy(This->clipping_planes[dwIndex].plane, pPlaneEquation, sizeof(D3DVALUE[4]));
2509 /* This is to force the reset of the transformation matrices on the next drawing.
2510 * This is needed to use the correct matrices for the various clipping planes.
2512 glThis->transform_state = GL_TRANSFORM_NONE;
2518 GL_IDirect3DDeviceImpl_7_SetViewport(LPDIRECT3DDEVICE7 iface,
2519 LPD3DVIEWPORT7 lpData)
2521 ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice7, iface);
2522 TRACE("(%p/%p)->(%p)\n", This, iface, lpData);
2524 if (TRACE_ON(ddraw)) {
2525 TRACE(" viewport is : \n");
2526 TRACE(" - dwX = %ld dwY = %ld\n",
2527 lpData->dwX, lpData->dwY);
2528 TRACE(" - dwWidth = %ld dwHeight = %ld\n",
2529 lpData->dwWidth, lpData->dwHeight);
2530 TRACE(" - dvMinZ = %f dvMaxZ = %f\n",
2531 lpData->dvMinZ, lpData->dvMaxZ);
2535 /* Set the viewport */
2536 if ((lpData->dvMinZ != This->active_viewport.dvMinZ) ||
2537 (lpData->dvMaxZ != This->active_viewport.dvMaxZ)) {
2538 glDepthRange(lpData->dvMinZ, lpData->dvMaxZ);
2540 if ((lpData->dwX != This->active_viewport.dwX) ||
2541 (lpData->dwY != This->active_viewport.dwY) ||
2542 (lpData->dwWidth != This->active_viewport.dwWidth) ||
2543 (lpData->dwHeight != This->active_viewport.dwHeight)) {
2544 glViewport(lpData->dwX,
2545 This->surface->surface_desc.dwHeight - (lpData->dwHeight + lpData->dwY),
2546 lpData->dwWidth, lpData->dwHeight);
2551 This->active_viewport = *lpData;
2556 #if !defined(__STRICT_ANSI__) && defined(__GNUC__)
2557 # define XCAST(fun) (typeof(VTABLE_IDirect3DDevice7.fun))
2559 # define XCAST(fun) (void*)
2562 ICOM_VTABLE(IDirect3DDevice7) VTABLE_IDirect3DDevice7 =
2564 ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
2565 XCAST(QueryInterface) Main_IDirect3DDeviceImpl_7_3T_2T_1T_QueryInterface,
2566 XCAST(AddRef) Main_IDirect3DDeviceImpl_7_3T_2T_1T_AddRef,
2567 XCAST(Release) GL_IDirect3DDeviceImpl_7_3T_2T_1T_Release,
2568 XCAST(GetCaps) GL_IDirect3DDeviceImpl_7_GetCaps,
2569 XCAST(EnumTextureFormats) GL_IDirect3DDeviceImpl_7_3T_EnumTextureFormats,
2570 XCAST(BeginScene) Main_IDirect3DDeviceImpl_7_3T_2T_1T_BeginScene,
2571 XCAST(EndScene) Main_IDirect3DDeviceImpl_7_3T_2T_1T_EndScene,
2572 XCAST(GetDirect3D) Main_IDirect3DDeviceImpl_7_3T_2T_1T_GetDirect3D,
2573 XCAST(SetRenderTarget) Main_IDirect3DDeviceImpl_7_3T_2T_SetRenderTarget,
2574 XCAST(GetRenderTarget) Main_IDirect3DDeviceImpl_7_3T_2T_GetRenderTarget,
2575 XCAST(Clear) Main_IDirect3DDeviceImpl_7_Clear,
2576 XCAST(SetTransform) Main_IDirect3DDeviceImpl_7_3T_2T_SetTransform,
2577 XCAST(GetTransform) Main_IDirect3DDeviceImpl_7_3T_2T_GetTransform,
2578 XCAST(SetViewport) GL_IDirect3DDeviceImpl_7_SetViewport,
2579 XCAST(MultiplyTransform) Main_IDirect3DDeviceImpl_7_3T_2T_MultiplyTransform,
2580 XCAST(GetViewport) Main_IDirect3DDeviceImpl_7_GetViewport,
2581 XCAST(SetMaterial) GL_IDirect3DDeviceImpl_7_SetMaterial,
2582 XCAST(GetMaterial) Main_IDirect3DDeviceImpl_7_GetMaterial,
2583 XCAST(SetLight) GL_IDirect3DDeviceImpl_7_SetLight,
2584 XCAST(GetLight) Main_IDirect3DDeviceImpl_7_GetLight,
2585 XCAST(SetRenderState) GL_IDirect3DDeviceImpl_7_3T_2T_SetRenderState,
2586 XCAST(GetRenderState) GL_IDirect3DDeviceImpl_7_3T_2T_GetRenderState,
2587 XCAST(BeginStateBlock) Main_IDirect3DDeviceImpl_7_BeginStateBlock,
2588 XCAST(EndStateBlock) Main_IDirect3DDeviceImpl_7_EndStateBlock,
2589 XCAST(PreLoad) Main_IDirect3DDeviceImpl_7_PreLoad,
2590 XCAST(DrawPrimitive) GL_IDirect3DDeviceImpl_7_3T_DrawPrimitive,
2591 XCAST(DrawIndexedPrimitive) GL_IDirect3DDeviceImpl_7_3T_DrawIndexedPrimitive,
2592 XCAST(SetClipStatus) Main_IDirect3DDeviceImpl_7_3T_2T_SetClipStatus,
2593 XCAST(GetClipStatus) Main_IDirect3DDeviceImpl_7_3T_2T_GetClipStatus,
2594 XCAST(DrawPrimitiveStrided) GL_IDirect3DDeviceImpl_7_3T_DrawPrimitiveStrided,
2595 XCAST(DrawIndexedPrimitiveStrided) GL_IDirect3DDeviceImpl_7_3T_DrawIndexedPrimitiveStrided,
2596 XCAST(DrawPrimitiveVB) GL_IDirect3DDeviceImpl_7_3T_DrawPrimitiveVB,
2597 XCAST(DrawIndexedPrimitiveVB) GL_IDirect3DDeviceImpl_7_3T_DrawIndexedPrimitiveVB,
2598 XCAST(ComputeSphereVisibility) Main_IDirect3DDeviceImpl_7_3T_ComputeSphereVisibility,
2599 XCAST(GetTexture) Main_IDirect3DDeviceImpl_7_3T_GetTexture,
2600 XCAST(SetTexture) GL_IDirect3DDeviceImpl_7_3T_SetTexture,
2601 XCAST(GetTextureStageState) Main_IDirect3DDeviceImpl_7_3T_GetTextureStageState,
2602 XCAST(SetTextureStageState) GL_IDirect3DDeviceImpl_7_3T_SetTextureStageState,
2603 XCAST(ValidateDevice) Main_IDirect3DDeviceImpl_7_3T_ValidateDevice,
2604 XCAST(ApplyStateBlock) Main_IDirect3DDeviceImpl_7_ApplyStateBlock,
2605 XCAST(CaptureStateBlock) Main_IDirect3DDeviceImpl_7_CaptureStateBlock,
2606 XCAST(DeleteStateBlock) Main_IDirect3DDeviceImpl_7_DeleteStateBlock,
2607 XCAST(CreateStateBlock) Main_IDirect3DDeviceImpl_7_CreateStateBlock,
2608 XCAST(Load) Main_IDirect3DDeviceImpl_7_Load,
2609 XCAST(LightEnable) GL_IDirect3DDeviceImpl_7_LightEnable,
2610 XCAST(GetLightEnable) Main_IDirect3DDeviceImpl_7_GetLightEnable,
2611 XCAST(SetClipPlane) GL_IDirect3DDeviceImpl_7_SetClipPlane,
2612 XCAST(GetClipPlane) Main_IDirect3DDeviceImpl_7_GetClipPlane,
2613 XCAST(GetInfo) Main_IDirect3DDeviceImpl_7_GetInfo,
2616 #if !defined(__STRICT_ANSI__) && defined(__GNUC__)
2621 #if !defined(__STRICT_ANSI__) && defined(__GNUC__)
2622 # define XCAST(fun) (typeof(VTABLE_IDirect3DDevice3.fun))
2624 # define XCAST(fun) (void*)
2627 ICOM_VTABLE(IDirect3DDevice3) VTABLE_IDirect3DDevice3 =
2629 ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
2630 XCAST(QueryInterface) Thunk_IDirect3DDeviceImpl_3_QueryInterface,
2631 XCAST(AddRef) Thunk_IDirect3DDeviceImpl_3_AddRef,
2632 XCAST(Release) Thunk_IDirect3DDeviceImpl_3_Release,
2633 XCAST(GetCaps) GL_IDirect3DDeviceImpl_3_2T_1T_GetCaps,
2634 XCAST(GetStats) Main_IDirect3DDeviceImpl_3_2T_1T_GetStats,
2635 XCAST(AddViewport) Main_IDirect3DDeviceImpl_3_2T_1T_AddViewport,
2636 XCAST(DeleteViewport) Main_IDirect3DDeviceImpl_3_2T_1T_DeleteViewport,
2637 XCAST(NextViewport) Main_IDirect3DDeviceImpl_3_2T_1T_NextViewport,
2638 XCAST(EnumTextureFormats) Thunk_IDirect3DDeviceImpl_3_EnumTextureFormats,
2639 XCAST(BeginScene) Thunk_IDirect3DDeviceImpl_3_BeginScene,
2640 XCAST(EndScene) Thunk_IDirect3DDeviceImpl_3_EndScene,
2641 XCAST(GetDirect3D) Thunk_IDirect3DDeviceImpl_3_GetDirect3D,
2642 XCAST(SetCurrentViewport) Main_IDirect3DDeviceImpl_3_2T_SetCurrentViewport,
2643 XCAST(GetCurrentViewport) Main_IDirect3DDeviceImpl_3_2T_GetCurrentViewport,
2644 XCAST(SetRenderTarget) Thunk_IDirect3DDeviceImpl_3_SetRenderTarget,
2645 XCAST(GetRenderTarget) Thunk_IDirect3DDeviceImpl_3_GetRenderTarget,
2646 XCAST(Begin) Main_IDirect3DDeviceImpl_3_Begin,
2647 XCAST(BeginIndexed) Main_IDirect3DDeviceImpl_3_BeginIndexed,
2648 XCAST(Vertex) Main_IDirect3DDeviceImpl_3_2T_Vertex,
2649 XCAST(Index) Main_IDirect3DDeviceImpl_3_2T_Index,
2650 XCAST(End) Main_IDirect3DDeviceImpl_3_2T_End,
2651 XCAST(GetRenderState) Thunk_IDirect3DDeviceImpl_3_GetRenderState,
2652 XCAST(SetRenderState) Thunk_IDirect3DDeviceImpl_3_SetRenderState,
2653 XCAST(GetLightState) Main_IDirect3DDeviceImpl_3_2T_GetLightState,
2654 XCAST(SetLightState) GL_IDirect3DDeviceImpl_3_2T_SetLightState,
2655 XCAST(SetTransform) Thunk_IDirect3DDeviceImpl_3_SetTransform,
2656 XCAST(GetTransform) Thunk_IDirect3DDeviceImpl_3_GetTransform,
2657 XCAST(MultiplyTransform) Thunk_IDirect3DDeviceImpl_3_MultiplyTransform,
2658 XCAST(DrawPrimitive) Thunk_IDirect3DDeviceImpl_3_DrawPrimitive,
2659 XCAST(DrawIndexedPrimitive) Thunk_IDirect3DDeviceImpl_3_DrawIndexedPrimitive,
2660 XCAST(SetClipStatus) Thunk_IDirect3DDeviceImpl_3_SetClipStatus,
2661 XCAST(GetClipStatus) Thunk_IDirect3DDeviceImpl_3_GetClipStatus,
2662 XCAST(DrawPrimitiveStrided) Thunk_IDirect3DDeviceImpl_3_DrawPrimitiveStrided,
2663 XCAST(DrawIndexedPrimitiveStrided) Thunk_IDirect3DDeviceImpl_3_DrawIndexedPrimitiveStrided,
2664 XCAST(DrawPrimitiveVB) Thunk_IDirect3DDeviceImpl_3_DrawPrimitiveVB,
2665 XCAST(DrawIndexedPrimitiveVB) Thunk_IDirect3DDeviceImpl_3_DrawIndexedPrimitiveVB,
2666 XCAST(ComputeSphereVisibility) Thunk_IDirect3DDeviceImpl_3_ComputeSphereVisibility,
2667 XCAST(GetTexture) Thunk_IDirect3DDeviceImpl_3_GetTexture,
2668 XCAST(SetTexture) Thunk_IDirect3DDeviceImpl_3_SetTexture,
2669 XCAST(GetTextureStageState) Thunk_IDirect3DDeviceImpl_3_GetTextureStageState,
2670 XCAST(SetTextureStageState) Thunk_IDirect3DDeviceImpl_3_SetTextureStageState,
2671 XCAST(ValidateDevice) Thunk_IDirect3DDeviceImpl_3_ValidateDevice,
2674 #if !defined(__STRICT_ANSI__) && defined(__GNUC__)
2679 #if !defined(__STRICT_ANSI__) && defined(__GNUC__)
2680 # define XCAST(fun) (typeof(VTABLE_IDirect3DDevice2.fun))
2682 # define XCAST(fun) (void*)
2685 ICOM_VTABLE(IDirect3DDevice2) VTABLE_IDirect3DDevice2 =
2687 ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
2688 XCAST(QueryInterface) Thunk_IDirect3DDeviceImpl_2_QueryInterface,
2689 XCAST(AddRef) Thunk_IDirect3DDeviceImpl_2_AddRef,
2690 XCAST(Release) Thunk_IDirect3DDeviceImpl_2_Release,
2691 XCAST(GetCaps) Thunk_IDirect3DDeviceImpl_2_GetCaps,
2692 XCAST(SwapTextureHandles) Main_IDirect3DDeviceImpl_2_1T_SwapTextureHandles,
2693 XCAST(GetStats) Thunk_IDirect3DDeviceImpl_2_GetStats,
2694 XCAST(AddViewport) Thunk_IDirect3DDeviceImpl_2_AddViewport,
2695 XCAST(DeleteViewport) Thunk_IDirect3DDeviceImpl_2_DeleteViewport,
2696 XCAST(NextViewport) Thunk_IDirect3DDeviceImpl_2_NextViewport,
2697 XCAST(EnumTextureFormats) GL_IDirect3DDeviceImpl_2_1T_EnumTextureFormats,
2698 XCAST(BeginScene) Thunk_IDirect3DDeviceImpl_2_BeginScene,
2699 XCAST(EndScene) Thunk_IDirect3DDeviceImpl_2_EndScene,
2700 XCAST(GetDirect3D) Thunk_IDirect3DDeviceImpl_2_GetDirect3D,
2701 XCAST(SetCurrentViewport) Thunk_IDirect3DDeviceImpl_2_SetCurrentViewport,
2702 XCAST(GetCurrentViewport) Thunk_IDirect3DDeviceImpl_2_GetCurrentViewport,
2703 XCAST(SetRenderTarget) Thunk_IDirect3DDeviceImpl_2_SetRenderTarget,
2704 XCAST(GetRenderTarget) Thunk_IDirect3DDeviceImpl_2_GetRenderTarget,
2705 XCAST(Begin) Main_IDirect3DDeviceImpl_2_Begin,
2706 XCAST(BeginIndexed) Main_IDirect3DDeviceImpl_2_BeginIndexed,
2707 XCAST(Vertex) Thunk_IDirect3DDeviceImpl_2_Vertex,
2708 XCAST(Index) Thunk_IDirect3DDeviceImpl_2_Index,
2709 XCAST(End) Thunk_IDirect3DDeviceImpl_2_End,
2710 XCAST(GetRenderState) Thunk_IDirect3DDeviceImpl_2_GetRenderState,
2711 XCAST(SetRenderState) Thunk_IDirect3DDeviceImpl_2_SetRenderState,
2712 XCAST(GetLightState) Thunk_IDirect3DDeviceImpl_2_GetLightState,
2713 XCAST(SetLightState) Thunk_IDirect3DDeviceImpl_2_SetLightState,
2714 XCAST(SetTransform) Thunk_IDirect3DDeviceImpl_2_SetTransform,
2715 XCAST(GetTransform) Thunk_IDirect3DDeviceImpl_2_GetTransform,
2716 XCAST(MultiplyTransform) Thunk_IDirect3DDeviceImpl_2_MultiplyTransform,
2717 XCAST(DrawPrimitive) GL_IDirect3DDeviceImpl_2_DrawPrimitive,
2718 XCAST(DrawIndexedPrimitive) GL_IDirect3DDeviceImpl_2_DrawIndexedPrimitive,
2719 XCAST(SetClipStatus) Thunk_IDirect3DDeviceImpl_2_SetClipStatus,
2720 XCAST(GetClipStatus) Thunk_IDirect3DDeviceImpl_2_GetClipStatus,
2723 #if !defined(__STRICT_ANSI__) && defined(__GNUC__)
2728 #if !defined(__STRICT_ANSI__) && defined(__GNUC__)
2729 # define XCAST(fun) (typeof(VTABLE_IDirect3DDevice.fun))
2731 # define XCAST(fun) (void*)
2734 ICOM_VTABLE(IDirect3DDevice) VTABLE_IDirect3DDevice =
2736 ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
2737 XCAST(QueryInterface) Thunk_IDirect3DDeviceImpl_1_QueryInterface,
2738 XCAST(AddRef) Thunk_IDirect3DDeviceImpl_1_AddRef,
2739 XCAST(Release) Thunk_IDirect3DDeviceImpl_1_Release,
2740 XCAST(Initialize) Main_IDirect3DDeviceImpl_1_Initialize,
2741 XCAST(GetCaps) Thunk_IDirect3DDeviceImpl_1_GetCaps,
2742 XCAST(SwapTextureHandles) Thunk_IDirect3DDeviceImpl_1_SwapTextureHandles,
2743 XCAST(CreateExecuteBuffer) GL_IDirect3DDeviceImpl_1_CreateExecuteBuffer,
2744 XCAST(GetStats) Thunk_IDirect3DDeviceImpl_1_GetStats,
2745 XCAST(Execute) Main_IDirect3DDeviceImpl_1_Execute,
2746 XCAST(AddViewport) Thunk_IDirect3DDeviceImpl_1_AddViewport,
2747 XCAST(DeleteViewport) Thunk_IDirect3DDeviceImpl_1_DeleteViewport,
2748 XCAST(NextViewport) Thunk_IDirect3DDeviceImpl_1_NextViewport,
2749 XCAST(Pick) Main_IDirect3DDeviceImpl_1_Pick,
2750 XCAST(GetPickRecords) Main_IDirect3DDeviceImpl_1_GetPickRecords,
2751 XCAST(EnumTextureFormats) Thunk_IDirect3DDeviceImpl_1_EnumTextureFormats,
2752 XCAST(CreateMatrix) Main_IDirect3DDeviceImpl_1_CreateMatrix,
2753 XCAST(SetMatrix) Main_IDirect3DDeviceImpl_1_SetMatrix,
2754 XCAST(GetMatrix) Main_IDirect3DDeviceImpl_1_GetMatrix,
2755 XCAST(DeleteMatrix) Main_IDirect3DDeviceImpl_1_DeleteMatrix,
2756 XCAST(BeginScene) Thunk_IDirect3DDeviceImpl_1_BeginScene,
2757 XCAST(EndScene) Thunk_IDirect3DDeviceImpl_1_EndScene,
2758 XCAST(GetDirect3D) Thunk_IDirect3DDeviceImpl_1_GetDirect3D,
2761 #if !defined(__STRICT_ANSI__) && defined(__GNUC__)
2765 static HRESULT d3ddevice_clear(IDirect3DDeviceImpl *This,
2766 WINE_GL_BUFFER_TYPE buffer_type,
2774 IDirect3DDeviceGLImpl *glThis = (IDirect3DDeviceGLImpl *) This;
2775 GLbitfield bitfield = 0;
2779 TRACE("(%p)->(%08lx,%p,%08lx,%08lx,%f,%08lx)\n", This, dwCount, lpRects, dwFlags, dwColor, dvZ, dwStencil);
2780 if (TRACE_ON(ddraw)) {
2783 TRACE(" rectangles : \n");
2784 for (i = 0; i < dwCount; i++) {
2785 TRACE(" - %ld x %ld %ld x %ld\n", lpRects[i].u1.x1, lpRects[i].u2.y1, lpRects[i].u3.x2, lpRects[i].u4.y2);
2794 rect.u3.x2 = This->surface->surface_desc.dwWidth;
2795 rect.u4.y2 = This->surface->surface_desc.dwHeight;
2799 /* Clears the screen */
2802 if (dwFlags & D3DCLEAR_TARGET) {
2803 if (glThis->state[buffer_type] == SURFACE_MEMORY_DIRTY) {
2804 /* TODO: optimize here the case where Clear changes all the screen... */
2805 This->flush_to_framebuffer(This, &(glThis->lock_rect[buffer_type]), glThis->lock_surf[buffer_type]);
2807 glThis->state[buffer_type] = SURFACE_GL;
2810 if (dwFlags & D3DCLEAR_ZBUFFER) {
2811 bitfield |= GL_DEPTH_BUFFER_BIT;
2812 if (glThis->depth_mask == FALSE) {
2813 glDepthMask(GL_TRUE); /* Enables Z writing to be sure to delete also the Z buffer */
2815 if (dvZ != glThis->prev_clear_Z) {
2817 glThis->prev_clear_Z = dvZ;
2819 TRACE(" depth value : %f\n", dvZ);
2821 if (dwFlags & D3DCLEAR_STENCIL) {
2822 bitfield |= GL_STENCIL_BUFFER_BIT;
2823 if (dwStencil != glThis->prev_clear_stencil) {
2824 glClearStencil(dwStencil);
2825 glThis->prev_clear_stencil = dwStencil;
2827 TRACE(" stencil value : %ld\n", dwStencil);
2829 if (dwFlags & D3DCLEAR_TARGET) {
2830 bitfield |= GL_COLOR_BUFFER_BIT;
2831 if (dwColor != glThis->prev_clear_color) {
2832 glClearColor(((dwColor >> 16) & 0xFF) / 255.0,
2833 ((dwColor >> 8) & 0xFF) / 255.0,
2834 ((dwColor >> 0) & 0xFF) / 255.0,
2835 ((dwColor >> 24) & 0xFF) / 255.0);
2836 glThis->prev_clear_color = dwColor;
2838 TRACE(" color value (ARGB) : %08lx\n", dwColor);
2841 glEnable(GL_SCISSOR_TEST);
2842 for (i = 0; i < dwCount; i++) {
2843 glScissor(lpRects[i].u1.x1, This->surface->surface_desc.dwHeight - lpRects[i].u4.y2,
2844 lpRects[i].u3.x2 - lpRects[i].u1.x1, lpRects[i].u4.y2 - lpRects[i].u2.y1);
2847 glDisable(GL_SCISSOR_TEST);
2849 if (dwFlags & D3DCLEAR_ZBUFFER) {
2850 if (glThis->depth_mask == FALSE) glDepthMask(GL_FALSE);
2858 static HRESULT d3ddevice_clear_back(IDirect3DDeviceImpl *This,
2866 return d3ddevice_clear(This, WINE_GL_BUFFER_BACK, dwCount, lpRects, dwFlags, dwColor, dvZ, dwStencil);
2870 setup_rect_and_surface_for_blt(IDirectDrawSurfaceImpl *This,
2871 WINE_GL_BUFFER_TYPE *buffer_type_p, D3DRECT *rect)
2873 IDirect3DDeviceGLImpl *gl_d3d_dev = (IDirect3DDeviceGLImpl *) This->d3ddevice;
2874 WINE_GL_BUFFER_TYPE buffer_type;
2876 /* First check if we BLT to the backbuffer... */
2877 if ((This->surface_desc.ddsCaps.dwCaps & (DDSCAPS_BACKBUFFER)) != 0) {
2878 buffer_type = WINE_GL_BUFFER_BACK;
2879 } else if ((This->surface_desc.ddsCaps.dwCaps & (DDSCAPS_FRONTBUFFER|DDSCAPS_PRIMARYSURFACE)) != 0) {
2880 buffer_type = WINE_GL_BUFFER_FRONT;
2882 ERR("Only BLT override to front or back-buffer is supported for now !\n");
2883 return DDERR_INVALIDPARAMS;
2886 if ((gl_d3d_dev->state[buffer_type] == SURFACE_MEMORY_DIRTY) &&
2887 (rect->u1.x1 >= gl_d3d_dev->lock_rect[buffer_type].left) &&
2888 (rect->u2.y1 >= gl_d3d_dev->lock_rect[buffer_type].top) &&
2889 (rect->u3.x2 <= gl_d3d_dev->lock_rect[buffer_type].right) &&
2890 (rect->u4.y2 <= gl_d3d_dev->lock_rect[buffer_type].bottom)) {
2891 /* If the memory zone is already dirty, use the standard 'in memory' blit operations and not
2894 return DDERR_INVALIDPARAMS;
2896 *buffer_type_p = buffer_type;
2902 d3ddevice_blt(IDirectDrawSurfaceImpl *This, LPRECT rdst,
2903 LPDIRECTDRAWSURFACE7 src, LPRECT rsrc,
2904 DWORD dwFlags, LPDDBLTFX lpbltfx)
2906 WINE_GL_BUFFER_TYPE buffer_type;
2910 rect.u1.x1 = rdst->left;
2911 rect.u2.y1 = rdst->top;
2912 rect.u3.x2 = rdst->right;
2913 rect.u4.y2 = rdst->bottom;
2917 rect.u3.x2 = This->surface_desc.dwWidth;
2918 rect.u4.y2 = This->surface_desc.dwHeight;
2921 if (setup_rect_and_surface_for_blt(This, &buffer_type, &rect) != DD_OK) return DDERR_INVALIDPARAMS;
2923 if (dwFlags & DDBLT_COLORFILL) {
2924 /* This is easy to handle for the D3D Device... */
2928 /* The color as given in the Blt function is in the format of the frame-buffer...
2929 * 'clear' expect it in ARGB format => we need to do some conversion :-)
2931 if (This->surface_desc.u4.ddpfPixelFormat.dwFlags & DDPF_PALETTEINDEXED8) {
2932 if (This->palette) {
2933 color = ((0xFF000000) |
2934 (This->palette->palents[lpbltfx->u5.dwFillColor].peRed << 16) |
2935 (This->palette->palents[lpbltfx->u5.dwFillColor].peGreen << 8) |
2936 (This->palette->palents[lpbltfx->u5.dwFillColor].peBlue));
2940 } else if ((This->surface_desc.u4.ddpfPixelFormat.dwFlags & DDPF_RGB) &&
2941 (((This->surface_desc.u4.ddpfPixelFormat.dwFlags & DDPF_ALPHAPIXELS) == 0) ||
2942 (This->surface_desc.u4.ddpfPixelFormat.u5.dwRGBAlphaBitMask == 0x00000000))) {
2943 if ((This->surface_desc.u4.ddpfPixelFormat.u1.dwRGBBitCount == 16) &&
2944 (This->surface_desc.u4.ddpfPixelFormat.u2.dwRBitMask == 0xF800) &&
2945 (This->surface_desc.u4.ddpfPixelFormat.u3.dwGBitMask == 0x07E0) &&
2946 (This->surface_desc.u4.ddpfPixelFormat.u4.dwBBitMask == 0x001F)) {
2947 if (lpbltfx->u5.dwFillColor == 0xFFFF) {
2950 color = ((0xFF000000) |
2951 ((lpbltfx->u5.dwFillColor & 0xF800) << 8) |
2952 ((lpbltfx->u5.dwFillColor & 0x07E0) << 5) |
2953 ((lpbltfx->u5.dwFillColor & 0x001F) << 3));
2955 } else if (((This->surface_desc.u4.ddpfPixelFormat.u1.dwRGBBitCount == 32) ||
2956 (This->surface_desc.u4.ddpfPixelFormat.u1.dwRGBBitCount == 24)) &&
2957 (This->surface_desc.u4.ddpfPixelFormat.u2.dwRBitMask == 0x00FF0000) &&
2958 (This->surface_desc.u4.ddpfPixelFormat.u3.dwGBitMask == 0x0000FF00) &&
2959 (This->surface_desc.u4.ddpfPixelFormat.u4.dwBBitMask == 0x000000FF)) {
2960 color = 0xFF000000 | lpbltfx->u5.dwFillColor;
2962 ERR("Wrong surface type for BLT override (unknown RGB format) !\n");
2963 return DDERR_INVALIDPARAMS;
2966 ERR("Wrong surface type for BLT override !\n");
2967 return DDERR_INVALIDPARAMS;
2970 TRACE(" executing D3D Device override.\n");
2974 glGetIntegerv(GL_DRAW_BUFFER, &prev_draw);
2975 if (buffer_type == WINE_GL_BUFFER_FRONT)
2976 glDrawBuffer(GL_FRONT);
2978 glDrawBuffer(GL_BACK);
2980 d3ddevice_clear(This->d3ddevice, buffer_type, 1, &rect, D3DCLEAR_TARGET, color, 0.0, 0x00000000);
2982 if (((buffer_type == WINE_GL_BUFFER_FRONT) && (prev_draw == GL_BACK)) ||
2983 ((buffer_type == WINE_GL_BUFFER_BACK) && (prev_draw == GL_FRONT)))
2984 glDrawBuffer(prev_draw);
2989 } else if ((dwFlags & (~(DDBLT_KEYSRC|DDBLT_WAIT|DDBLT_ASYNC))) == 0) {
2990 /* Normal blit without any special case... */
2992 /* And which has a SRC surface */
2993 IDirectDrawSurfaceImpl *src_impl = ICOM_OBJECT(IDirectDrawSurfaceImpl, IDirectDrawSurface7, src);
2995 if ((src_impl->surface_desc.ddsCaps.dwCaps & DDSCAPS_3DDEVICE) &&
2996 (src_impl->d3ddevice == This->d3ddevice) &&
2997 ((dwFlags & DDBLT_KEYSRC) == 0)) {
2998 /* Both are 3D devices and using the same GL device and the Blt is without color-keying */
3002 WINE_GL_BUFFER_TYPE src_buffer_type;
3003 IDirect3DDeviceGLImpl *gl_d3d_dev = (IDirect3DDeviceGLImpl *) This->d3ddevice;
3009 src_rect.u1.x1 = rsrc->left;
3010 src_rect.u2.y1 = rsrc->top;
3011 src_rect.u3.x2 = rsrc->right;
3012 src_rect.u4.y2 = rsrc->bottom;
3016 src_rect.u3.x2 = src_impl->surface_desc.dwWidth;
3017 src_rect.u4.y2 = src_impl->surface_desc.dwHeight;
3020 width = src_rect.u3.x2 - src_rect.u1.x1;
3021 height = src_rect.u4.y2 - src_rect.u2.y1;
3023 if ((width != (rect.u3.x2 - rect.u1.x1)) ||
3024 (height != (rect.u4.y2 - rect.u2.y1))) {
3025 FIXME(" buffer to buffer copy not supported with stretching yet !\n");
3026 return DDERR_INVALIDPARAMS;
3029 /* First check if we BLT from the backbuffer... */
3030 if ((src_impl->surface_desc.ddsCaps.dwCaps & (DDSCAPS_BACKBUFFER)) != 0) {
3031 src_buffer_type = WINE_GL_BUFFER_BACK;
3032 } else if ((src_impl->surface_desc.ddsCaps.dwCaps & (DDSCAPS_FRONTBUFFER|DDSCAPS_PRIMARYSURFACE)) != 0) {
3033 src_buffer_type = WINE_GL_BUFFER_FRONT;
3035 ERR("Unexpected case in direct buffer to buffer copy !\n");
3036 return DDERR_INVALIDPARAMS;
3039 TRACE(" using direct buffer to buffer copy.\n");
3043 opt_bitmap = d3ddevice_set_state_for_flush(This->d3ddevice, (LPCRECT) &rect, FALSE, &initial);
3045 if (upload_surface_to_tex_memory_init(This, 0, &gl_d3d_dev->current_internal_format,
3046 initial, FALSE, UNLOCK_TEX_SIZE, UNLOCK_TEX_SIZE) != DD_OK) {
3047 ERR(" unsupported pixel format at direct buffer to buffer copy.\n");
3049 return DDERR_INVALIDPARAMS;
3052 glGetIntegerv(GL_DRAW_BUFFER, &prev_draw);
3053 if (buffer_type == WINE_GL_BUFFER_FRONT)
3054 glDrawBuffer(GL_FRONT);
3056 glDrawBuffer(GL_BACK);
3058 if (src_buffer_type == WINE_GL_BUFFER_FRONT)
3059 glReadBuffer(GL_FRONT);
3061 glReadBuffer(GL_BACK);
3063 /* Now the serious stuff happens. Basically, we copy from the source buffer to the texture memory.
3064 And directly re-draws this on the destination buffer. */
3065 for (y = 0; y < height; y += UNLOCK_TEX_SIZE) {
3068 if ((src_rect.u2.y1 + y + UNLOCK_TEX_SIZE) > src_impl->surface_desc.dwHeight)
3069 get_height = src_impl->surface_desc.dwHeight - (src_rect.u2.y1 + y);
3071 get_height = UNLOCK_TEX_SIZE;
3073 for (x = 0; x < width; x += UNLOCK_TEX_SIZE) {
3076 if ((src_rect.u1.x1 + x + UNLOCK_TEX_SIZE) > src_impl->surface_desc.dwWidth)
3077 get_width = src_impl->surface_desc.dwWidth - (src_rect.u1.x1 + x);
3079 get_width = UNLOCK_TEX_SIZE;
3081 glCopyTexSubImage2D(GL_TEXTURE_2D, 0,
3082 0, UNLOCK_TEX_SIZE - get_height,
3083 src_rect.u1.x1 + x, src_impl->surface_desc.dwHeight - (src_rect.u2.y1 + y + get_height),
3084 get_width, get_height);
3087 glTexCoord2f(0.0, 0.0);
3088 glVertex3d(rect.u1.x1 + x,
3089 rect.u2.y1 + y + UNLOCK_TEX_SIZE,
3091 glTexCoord2f(1.0, 0.0);
3092 glVertex3d(rect.u1.x1 + x + UNLOCK_TEX_SIZE,
3093 rect.u2.y1 + y + UNLOCK_TEX_SIZE,
3095 glTexCoord2f(1.0, 1.0);
3096 glVertex3d(rect.u1.x1 + x + UNLOCK_TEX_SIZE,
3099 glTexCoord2f(0.0, 1.0);
3100 glVertex3d(rect.u1.x1 + x,
3107 upload_surface_to_tex_memory_release();
3108 d3ddevice_restore_state_after_flush(This->d3ddevice, opt_bitmap, FALSE);
3110 if (((buffer_type == WINE_GL_BUFFER_FRONT) && (prev_draw == GL_BACK)) ||
3111 ((buffer_type == WINE_GL_BUFFER_BACK) && (prev_draw == GL_FRONT)))
3112 glDrawBuffer(prev_draw);
3118 /* This is the normal 'with source' Blit. Use the texture engine to do the Blt for us
3119 (this prevents calling glReadPixels) */
3123 IDirect3DDeviceGLImpl *gl_d3d_dev = (IDirect3DDeviceGLImpl *) This->d3ddevice;
3127 double x_stretch, y_stretch;
3130 src_rect.u1.x1 = rsrc->left;
3131 src_rect.u2.y1 = rsrc->top;
3132 src_rect.u3.x2 = rsrc->right;
3133 src_rect.u4.y2 = rsrc->bottom;
3137 src_rect.u3.x2 = src_impl->surface_desc.dwWidth;
3138 src_rect.u4.y2 = src_impl->surface_desc.dwHeight;
3141 width = src_rect.u3.x2 - src_rect.u1.x1;
3142 height = src_rect.u4.y2 - src_rect.u2.y1;
3144 x_stretch = (double) (rect.u3.x2 - rect.u1.x1) / (double) width;
3145 y_stretch = (double) (rect.u4.y2 - rect.u2.y1) / (double) height;
3147 TRACE(" using memory to buffer Blt overide.\n");
3151 opt_bitmap = d3ddevice_set_state_for_flush(This->d3ddevice, (LPCRECT) &rect, ((dwFlags & DDBLT_KEYSRC) != 0), &initial);
3153 if (upload_surface_to_tex_memory_init(src_impl, 0, &gl_d3d_dev->current_internal_format,
3154 initial, ((dwFlags & DDBLT_KEYSRC) != 0), UNLOCK_TEX_SIZE, UNLOCK_TEX_SIZE) != DD_OK) {
3155 ERR(" unsupported pixel format at memory to buffer Blt overide.\n");
3157 return DDERR_INVALIDPARAMS;
3160 glGetIntegerv(GL_DRAW_BUFFER, &prev_draw);
3161 if (buffer_type == WINE_GL_BUFFER_FRONT)
3162 glDrawBuffer(GL_FRONT);
3164 glDrawBuffer(GL_BACK);
3166 /* Now the serious stuff happens. This is basically the same code that for the memory
3167 flush to frame buffer ... with stretching and different rectangles added :-) */
3168 for (y = 0; y < height; y += UNLOCK_TEX_SIZE) {
3171 flush_rect.top = src_rect.u2.y1 + y;
3172 flush_rect.bottom = ((src_rect.u2.y1 + y + UNLOCK_TEX_SIZE > src_rect.u4.y2) ?
3174 (src_rect.u2.y1 + y + UNLOCK_TEX_SIZE));
3176 for (x = 0; x < width; x += UNLOCK_TEX_SIZE) {
3177 flush_rect.left = src_rect.u1.x1 + x;
3178 flush_rect.right = ((src_rect.u1.x1 + x + UNLOCK_TEX_SIZE > src_rect.u3.x2) ?
3180 (src_rect.u1.x1 + x + UNLOCK_TEX_SIZE));
3182 upload_surface_to_tex_memory(&flush_rect, 0, 0, &(gl_d3d_dev->surface_ptr));
3185 glTexCoord2f(0.0, 0.0);
3186 glVertex3d(rect.u1.x1 + (x * x_stretch),
3187 rect.u2.y1 + (y * y_stretch),
3189 glTexCoord2f(1.0, 0.0);
3190 glVertex3d(rect.u1.x1 + ((x + UNLOCK_TEX_SIZE) * x_stretch),
3191 rect.u2.y1 + (y * y_stretch),
3193 glTexCoord2f(1.0, 1.0);
3194 glVertex3d(rect.u1.x1 + ((x + UNLOCK_TEX_SIZE) * x_stretch),
3195 rect.u2.y1 + ((y + UNLOCK_TEX_SIZE) * y_stretch),
3197 glTexCoord2f(0.0, 1.0);
3198 glVertex3d(rect.u1.x1 + (x * x_stretch),
3199 rect.u2.y1 + ((y + UNLOCK_TEX_SIZE) * y_stretch),
3205 upload_surface_to_tex_memory_release();
3206 d3ddevice_restore_state_after_flush(This->d3ddevice, opt_bitmap, ((dwFlags & DDBLT_KEYSRC) != 0));
3208 if (((buffer_type == WINE_GL_BUFFER_FRONT) && (prev_draw == GL_BACK)) ||
3209 ((buffer_type == WINE_GL_BUFFER_BACK) && (prev_draw == GL_FRONT)))
3210 glDrawBuffer(prev_draw);
3218 return DDERR_INVALIDPARAMS;
3222 d3ddevice_bltfast(IDirectDrawSurfaceImpl *This, DWORD dstx,
3223 DWORD dsty, LPDIRECTDRAWSURFACE7 src,
3224 LPRECT rsrc, DWORD trans)
3228 IDirectDrawSurfaceImpl *src_impl = ICOM_OBJECT(IDirectDrawSurfaceImpl, IDirectDrawSurface7, src);
3229 IDirect3DDeviceGLImpl *gl_d3d_dev = (IDirect3DDeviceGLImpl *) This->d3ddevice;
3230 WINE_GL_BUFFER_TYPE buffer_type;
3234 int width, height, x, y;
3236 /* Cannot support DSTCOLORKEY blitting... */
3237 if ((trans & DDBLTFAST_DESTCOLORKEY) != 0) return DDERR_INVALIDPARAMS;
3240 WARN("rsrc is NULL - getting the whole surface !!\n");
3242 rsrc->left = rsrc->top = 0;
3243 rsrc->right = src_impl->surface_desc.dwWidth;
3244 rsrc->bottom = src_impl->surface_desc.dwHeight;
3252 rdst.right = dstx + (rsrc->right - rsrc->left);
3253 if (rdst.right > This->surface_desc.dwWidth) {
3254 rsrc->right -= (This->surface_desc.dwWidth - rdst.right);
3255 rdst.right = This->surface_desc.dwWidth;
3257 rdst.bottom = dsty + (rsrc->bottom - rsrc->top);
3258 if (rdst.bottom > This->surface_desc.dwHeight) {
3259 rsrc->bottom -= (This->surface_desc.dwHeight - rdst.bottom);
3260 rdst.bottom = This->surface_desc.dwHeight;
3263 width = rsrc->right - rsrc->left;
3264 height = rsrc->bottom - rsrc->top;
3266 if (setup_rect_and_surface_for_blt(This, &buffer_type, (D3DRECT *) &rdst) != DD_OK) return DDERR_INVALIDPARAMS;
3268 TRACE(" using BltFast memory to frame buffer overide.\n");
3272 opt_bitmap = d3ddevice_set_state_for_flush(This->d3ddevice, &rdst, (trans & DDBLTFAST_SRCCOLORKEY) != 0, &initial);
3274 if (upload_surface_to_tex_memory_init(src_impl, 0, &gl_d3d_dev->current_internal_format,
3275 initial, (trans & DDBLTFAST_SRCCOLORKEY) != 0,
3276 UNLOCK_TEX_SIZE, UNLOCK_TEX_SIZE) != DD_OK) {
3277 ERR(" unsupported pixel format at memory to buffer Blt overide.\n");
3279 return DDERR_INVALIDPARAMS;
3282 glGetIntegerv(GL_DRAW_BUFFER, &prev_draw);
3283 if (buffer_type == WINE_GL_BUFFER_FRONT)
3284 glDrawBuffer(GL_FRONT);
3286 glDrawBuffer(GL_BACK);
3288 /* Now the serious stuff happens. This is basically the same code that for the memory
3289 flush to frame buffer but with different rectangles for source and destination :-) */
3290 for (y = 0; y < height; y += UNLOCK_TEX_SIZE) {
3293 flush_rect.top = rsrc->top + y;
3294 flush_rect.bottom = ((rsrc->top + y + UNLOCK_TEX_SIZE > rsrc->bottom) ?
3296 (rsrc->top + y + UNLOCK_TEX_SIZE));
3298 for (x = 0; x < width; x += UNLOCK_TEX_SIZE) {
3299 flush_rect.left = rsrc->left + x;
3300 flush_rect.right = ((rsrc->left + x + UNLOCK_TEX_SIZE > rsrc->right) ?
3302 (rsrc->left + x + UNLOCK_TEX_SIZE));
3304 upload_surface_to_tex_memory(&flush_rect, 0, 0, &(gl_d3d_dev->surface_ptr));
3307 glTexCoord2f(0.0, 0.0);
3308 glVertex3d(rdst.left + x,
3311 glTexCoord2f(1.0, 0.0);
3312 glVertex3d(rdst.left + (x + UNLOCK_TEX_SIZE),
3315 glTexCoord2f(1.0, 1.0);
3316 glVertex3d(rdst.left + (x + UNLOCK_TEX_SIZE),
3317 rdst.top + (y + UNLOCK_TEX_SIZE),
3319 glTexCoord2f(0.0, 1.0);
3320 glVertex3d(rdst.left + x,
3321 rdst.top + (y + UNLOCK_TEX_SIZE),
3327 upload_surface_to_tex_memory_release();
3328 d3ddevice_restore_state_after_flush(This->d3ddevice, opt_bitmap, (trans & DDBLTFAST_SRCCOLORKEY) != 0);
3330 if (((buffer_type == WINE_GL_BUFFER_FRONT) && (prev_draw == GL_BACK)) ||
3331 ((buffer_type == WINE_GL_BUFFER_BACK) && (prev_draw == GL_FRONT)))
3332 glDrawBuffer(prev_draw);
3340 d3ddevice_set_ortho(IDirect3DDeviceImpl *This)
3342 GLfloat height, width;
3343 GLfloat trans_mat[16];
3345 TRACE("(%p)\n", This);
3347 width = This->surface->surface_desc.dwWidth;
3348 height = This->surface->surface_desc.dwHeight;
3350 /* The X axis is straighforward.. For the Y axis, we need to convert 'D3D' screen coordinates
3351 to OpenGL screen coordinates (ie the upper left corner is not the same).
3352 For Z, the mystery is what should it be mapped to ? Ie should the resulting range be between
3353 -1.0 and 1.0 (as the X and Y coordinates) or between 0.0 and 1.0 ? */
3354 trans_mat[ 0] = 2.0 / width; trans_mat[ 4] = 0.0; trans_mat[ 8] = 0.0; trans_mat[12] = -1.0;
3355 trans_mat[ 1] = 0.0; trans_mat[ 5] = -2.0 / height; trans_mat[ 9] = 0.0; trans_mat[13] = 1.0;
3356 trans_mat[ 2] = 0.0; trans_mat[ 6] = 0.0; trans_mat[10] = 2.0; trans_mat[14] = -1.0;
3357 trans_mat[ 3] = 0.0; trans_mat[ 7] = 0.0; trans_mat[11] = 0.0; trans_mat[15] = 1.0;
3360 glMatrixMode(GL_MODELVIEW);
3362 /* See the OpenGL Red Book for an explanation of the following translation (in the OpenGL
3363 Correctness Tips section).
3365 Basically, from what I understood, if the game does not filter the font texture,
3366 as the 'real' pixel will lie at the middle of the two texels, OpenGL may choose the wrong
3367 one and we will have strange artifacts (as the rounding and stuff may give different results
3368 for different pixels, ie sometimes take the left pixel, sometimes the right).
3370 glTranslatef(0.375, 0.375, 0);
3371 glMatrixMode(GL_PROJECTION);
3372 glLoadMatrixf(trans_mat);
3377 d3ddevice_set_matrices(IDirect3DDeviceImpl *This, DWORD matrices,
3378 D3DMATRIX *world_mat, D3DMATRIX *view_mat, D3DMATRIX *proj_mat)
3380 TRACE("(%p,%08lx,%p,%p,%p)\n", This, matrices, world_mat, view_mat, proj_mat);
3383 if ((matrices & (VIEWMAT_CHANGED|WORLDMAT_CHANGED)) != 0) {
3384 glMatrixMode(GL_MODELVIEW);
3385 glLoadMatrixf((float *) view_mat);
3387 /* Now also re-loads all the Lights and Clipping Planes using the new matrices */
3388 if (This->state_block.render_state[D3DRENDERSTATE_CLIPPING - 1] != FALSE) {
3391 for (i = 0, runner = 0x00000001; i < This->max_clipping_planes; i++, runner <<= 1) {
3392 if (runner & This->state_block.render_state[D3DRENDERSTATE_CLIPPLANEENABLE - 1]) {
3395 plane[0] = This->clipping_planes[i].plane[0];
3396 plane[1] = This->clipping_planes[i].plane[1];
3397 plane[2] = This->clipping_planes[i].plane[2];
3398 plane[3] = This->clipping_planes[i].plane[3];
3400 glClipPlane( GL_CLIP_PLANE0 + i, (const GLdouble*) (&plane) );
3404 if (This->state_block.render_state[D3DRENDERSTATE_LIGHTING - 1] != FALSE) {
3408 for (i = 0, runner = 0x00000001; i < MAX_LIGHTS; i++, runner <<= 1) {
3409 if (runner & This->active_lights) {
3410 switch (This->light_parameters[i].dltType) {
3411 case D3DLIGHT_DIRECTIONAL: {
3413 float cut_off = 180.0;
3415 glLightfv(GL_LIGHT0 + i, GL_AMBIENT, (float *) &(This->light_parameters[i].dcvAmbient));
3416 glLightfv(GL_LIGHT0 + i, GL_DIFFUSE, (float *) &(This->light_parameters[i].dcvDiffuse));
3417 glLightfv(GL_LIGHT0 + i, GL_SPECULAR, (float *) &(This->light_parameters[i].dcvSpecular));
3418 glLightfv(GL_LIGHT0 + i, GL_SPOT_CUTOFF, &cut_off);
3420 direction[0] = This->light_parameters[i].dvDirection.u1.x;
3421 direction[1] = This->light_parameters[i].dvDirection.u2.y;
3422 direction[2] = This->light_parameters[i].dvDirection.u3.z;
3424 glLightfv(GL_LIGHT0 + i, GL_POSITION, (float *) direction);
3427 case D3DLIGHT_POINT: {
3429 float cut_off = 180.0;
3431 glLightfv(GL_LIGHT0 + i, GL_AMBIENT, (float *) &(This->light_parameters[i].dcvAmbient));
3432 glLightfv(GL_LIGHT0 + i, GL_DIFFUSE, (float *) &(This->light_parameters[i].dcvDiffuse));
3433 glLightfv(GL_LIGHT0 + i, GL_SPECULAR, (float *) &(This->light_parameters[i].dcvSpecular));
3434 position[0] = This->light_parameters[i].dvPosition.u1.x;
3435 position[1] = This->light_parameters[i].dvPosition.u2.y;
3436 position[2] = This->light_parameters[i].dvPosition.u3.z;
3438 glLightfv(GL_LIGHT0 + i, GL_POSITION, (float *) position);
3439 glLightfv(GL_LIGHT0 + i, GL_CONSTANT_ATTENUATION, &(This->light_parameters[i].dvAttenuation0));
3440 glLightfv(GL_LIGHT0 + i, GL_LINEAR_ATTENUATION, &(This->light_parameters[i].dvAttenuation1));
3441 glLightfv(GL_LIGHT0 + i, GL_QUADRATIC_ATTENUATION, &(This->light_parameters[i].dvAttenuation2));
3442 glLightfv(GL_LIGHT0 + i, GL_SPOT_CUTOFF, &cut_off);
3445 case D3DLIGHT_SPOT: {
3448 float cut_off = 90.0 * (This->light_parameters[i].dvPhi / M_PI);
3450 glLightfv(GL_LIGHT0 + i, GL_AMBIENT, (float *) &(This->light_parameters[i].dcvAmbient));
3451 glLightfv(GL_LIGHT0 + i, GL_DIFFUSE, (float *) &(This->light_parameters[i].dcvDiffuse));
3452 glLightfv(GL_LIGHT0 + i, GL_SPECULAR, (float *) &(This->light_parameters[i].dcvSpecular));
3454 direction[0] = This->light_parameters[i].dvDirection.u1.x;
3455 direction[1] = This->light_parameters[i].dvDirection.u2.y;
3456 direction[2] = This->light_parameters[i].dvDirection.u3.z;
3458 glLightfv(GL_LIGHT0 + i, GL_SPOT_DIRECTION, (float *) direction);
3459 position[0] = This->light_parameters[i].dvPosition.u1.x;
3460 position[1] = This->light_parameters[i].dvPosition.u2.y;
3461 position[2] = This->light_parameters[i].dvPosition.u3.z;
3463 glLightfv(GL_LIGHT0 + i, GL_POSITION, (float *) position);
3464 glLightfv(GL_LIGHT0 + i, GL_CONSTANT_ATTENUATION, &(This->light_parameters[i].dvAttenuation0));
3465 glLightfv(GL_LIGHT0 + i, GL_LINEAR_ATTENUATION, &(This->light_parameters[i].dvAttenuation1));
3466 glLightfv(GL_LIGHT0 + i, GL_QUADRATIC_ATTENUATION, &(This->light_parameters[i].dvAttenuation2));
3467 glLightfv(GL_LIGHT0 + i, GL_SPOT_CUTOFF, &cut_off);
3468 glLightfv(GL_LIGHT0 + i, GL_SPOT_EXPONENT, &(This->light_parameters[i].dvFalloff));
3472 /* No warning here as it's already done at light setting */
3479 glMultMatrixf((float *) world_mat);
3481 if ((matrices & PROJMAT_CHANGED) != 0) {
3482 glMatrixMode(GL_PROJECTION);
3483 glLoadMatrixf((float *) proj_mat);
3489 d3ddevice_matrices_updated(IDirect3DDeviceImpl *This, DWORD matrices)
3491 IDirect3DDeviceGLImpl *glThis = (IDirect3DDeviceGLImpl *) This;
3492 DWORD tex_mat, tex_stage;
3494 TRACE("(%p,%08lx)\n", This, matrices);
3496 if (matrices & (VIEWMAT_CHANGED|WORLDMAT_CHANGED|PROJMAT_CHANGED)) {
3497 if (glThis->transform_state == GL_TRANSFORM_NORMAL) {
3498 /* This will force an update of the transform state at the next drawing. */
3499 glThis->transform_state = GL_TRANSFORM_NONE;
3502 if (matrices & (TEXMAT0_CHANGED|TEXMAT1_CHANGED|TEXMAT2_CHANGED|TEXMAT3_CHANGED|
3503 TEXMAT4_CHANGED|TEXMAT5_CHANGED|TEXMAT6_CHANGED|TEXMAT7_CHANGED))
3506 for (tex_mat = TEXMAT0_CHANGED, tex_stage = 0; tex_mat <= TEXMAT7_CHANGED; tex_mat <<= 1, tex_stage++) {
3507 GLenum unit = GL_TEXTURE0_WINE + tex_stage;
3508 if (matrices & tex_mat) {
3509 if (This->state_block.texture_stage_state[tex_stage][D3DTSS_TEXTURETRANSFORMFLAGS - 1] != D3DTTFF_DISABLE) {
3510 int is_identity = (memcmp(This->tex_mat[tex_stage], id_mat, 16 * sizeof(D3DVALUE)) != 0);
3512 if (This->tex_mat_is_identity[tex_stage] != is_identity) {
3513 if (glThis->current_active_tex_unit != unit) {
3514 GL_extensions.glActiveTexture(unit);
3515 glThis->current_active_tex_unit = unit;
3517 glMatrixMode(GL_TEXTURE);
3518 glLoadMatrixf((float *) This->tex_mat[tex_stage]);
3520 This->tex_mat_is_identity[tex_stage] = is_identity;
3522 if (This->tex_mat_is_identity[tex_stage] == FALSE) {
3523 if (glThis->current_active_tex_unit != unit) {
3524 GL_extensions.glActiveTexture(unit);
3525 glThis->current_active_tex_unit = unit;
3527 glMatrixMode(GL_TEXTURE);
3529 This->tex_mat_is_identity[tex_stage] = TRUE;
3538 /* TODO for both these functions :
3539 - change / restore OpenGL parameters for pictures transfers in case they are ever modified
3540 by other OpenGL code in D3D
3541 - handle the case where no 'Begin / EndScene' was done between two locks
3542 - handle the rectangles in the unlock too
3543 - handle pitch correctly...
3545 static void d3ddevice_lock_update(IDirectDrawSurfaceImpl* This, LPCRECT pRect, DWORD dwFlags)
3547 IDirect3DDeviceImpl *d3d_dev = This->d3ddevice;
3548 IDirect3DDeviceGLImpl* gl_d3d_dev = (IDirect3DDeviceGLImpl*) d3d_dev;
3549 WINE_GL_BUFFER_TYPE buffer_type;
3552 if ((This->surface_desc.ddsCaps.dwCaps & (DDSCAPS_FRONTBUFFER|DDSCAPS_PRIMARYSURFACE)) != 0) {
3553 buffer_type = WINE_GL_BUFFER_FRONT;
3554 if ((gl_d3d_dev->state[WINE_GL_BUFFER_FRONT] != SURFACE_GL) &&
3555 (gl_d3d_dev->lock_surf[WINE_GL_BUFFER_FRONT] != This)) {
3556 ERR("Change of front buffer.. Expect graphic corruptions !\n");
3558 gl_d3d_dev->lock_surf[WINE_GL_BUFFER_FRONT] = This;
3559 } else if ((This->surface_desc.ddsCaps.dwCaps & (DDSCAPS_BACKBUFFER)) == (DDSCAPS_BACKBUFFER)) {
3560 buffer_type = WINE_GL_BUFFER_BACK;
3561 if ((gl_d3d_dev->state[WINE_GL_BUFFER_BACK] != SURFACE_GL) &&
3562 (gl_d3d_dev->lock_surf[WINE_GL_BUFFER_BACK] != This)) {
3563 ERR("Change of back buffer.. Expect graphic corruptions !\n");
3565 gl_d3d_dev->lock_surf[WINE_GL_BUFFER_BACK] = This;
3567 ERR("Wrong surface type for locking !\n");
3571 if (pRect == NULL) {
3574 loc_rect.bottom = This->surface_desc.dwHeight;
3575 loc_rect.right = This->surface_desc.dwWidth;
3579 /* Try to acquire the device critical section */
3580 EnterCriticalSection(&(d3d_dev->crit));
3582 if (gl_d3d_dev->lock_rect_valid[buffer_type] == TRUE) {
3583 ERR("Two consecutive locks on %s buffer... Expect problems !\n",
3584 (buffer_type == WINE_GL_BUFFER_BACK ? "back" : "front"));
3586 gl_d3d_dev->lock_rect_valid[buffer_type] = TRUE;
3588 if (gl_d3d_dev->state[buffer_type] != SURFACE_GL) {
3589 /* Check if the new rectangle is in the previous one or not.
3590 If it is not, flush first the previous locks on screen.
3592 if ((pRect->top < gl_d3d_dev->lock_rect[buffer_type].top) ||
3593 (pRect->left < gl_d3d_dev->lock_rect[buffer_type].left) ||
3594 (pRect->right > gl_d3d_dev->lock_rect[buffer_type].right) ||
3595 (pRect->bottom > gl_d3d_dev->lock_rect[buffer_type].bottom)) {
3596 if (gl_d3d_dev->state[buffer_type] == SURFACE_MEMORY_DIRTY) {
3597 TRACE(" flushing back to %s buffer as new rect : (%ldx%ld) - (%ldx%ld) not included in old rect : (%ldx%ld) - (%ldx%ld)\n",
3598 (buffer_type == WINE_GL_BUFFER_BACK ? "back" : "front"),
3599 pRect->left, pRect->top, pRect->right, pRect->bottom,
3600 gl_d3d_dev->lock_rect[buffer_type].left, gl_d3d_dev->lock_rect[buffer_type].top,
3601 gl_d3d_dev->lock_rect[buffer_type].right, gl_d3d_dev->lock_rect[buffer_type].bottom);
3602 d3d_dev->flush_to_framebuffer(d3d_dev, &(gl_d3d_dev->lock_rect[buffer_type]), gl_d3d_dev->lock_surf[buffer_type]);
3604 gl_d3d_dev->state[buffer_type] = SURFACE_GL;
3605 gl_d3d_dev->lock_rect[buffer_type] = *pRect;
3607 /* In the other case, do not upgrade the locking rectangle as it's no need... */
3609 gl_d3d_dev->lock_rect[buffer_type] = *pRect;
3612 if (gl_d3d_dev->state[buffer_type] == SURFACE_GL) {
3613 /* If the surface is already in memory, no need to do anything here... */
3614 GLenum buffer_format;
3615 GLenum buffer_color;
3619 TRACE(" copying %s buffer to main memory with rectangle (%ldx%ld) - (%ldx%ld).\n", (buffer_type == WINE_GL_BUFFER_BACK ? "back" : "front"),
3620 pRect->left, pRect->top, pRect->right, pRect->bottom);
3622 /* Note that here we cannot do 'optmizations' about the WriteOnly flag... Indeed, a game
3623 may only write to the device... But when we will blit it back to the screen, we need
3624 also to blit correctly the parts the application did not overwrite... */
3626 if (((This->surface_desc.u4.ddpfPixelFormat.dwFlags & DDPF_RGB) != 0) &&
3627 (((This->surface_desc.u4.ddpfPixelFormat.dwFlags & DDPF_ALPHAPIXELS) == 0) ||
3628 (This->surface_desc.u4.ddpfPixelFormat.u5.dwRGBAlphaBitMask == 0x00000000))) {
3629 if ((This->surface_desc.u4.ddpfPixelFormat.u1.dwRGBBitCount == 16) &&
3630 (This->surface_desc.u4.ddpfPixelFormat.u2.dwRBitMask == 0xF800) &&
3631 (This->surface_desc.u4.ddpfPixelFormat.u3.dwGBitMask == 0x07E0) &&
3632 (This->surface_desc.u4.ddpfPixelFormat.u4.dwBBitMask == 0x001F)) {
3633 buffer_format = GL_UNSIGNED_SHORT_5_6_5;
3634 buffer_color = GL_RGB;
3635 } else if ((This->surface_desc.u4.ddpfPixelFormat.u1.dwRGBBitCount == 24) &&
3636 (This->surface_desc.u4.ddpfPixelFormat.u2.dwRBitMask == 0xFF0000) &&
3637 (This->surface_desc.u4.ddpfPixelFormat.u3.dwGBitMask == 0x00FF00) &&
3638 (This->surface_desc.u4.ddpfPixelFormat.u4.dwBBitMask == 0x0000FF)) {
3639 buffer_format = GL_UNSIGNED_BYTE;
3640 buffer_color = GL_RGB;
3641 } else if ((This->surface_desc.u4.ddpfPixelFormat.u1.dwRGBBitCount == 32) &&
3642 (This->surface_desc.u4.ddpfPixelFormat.u2.dwRBitMask == 0x00FF0000) &&
3643 (This->surface_desc.u4.ddpfPixelFormat.u3.dwGBitMask == 0x0000FF00) &&
3644 (This->surface_desc.u4.ddpfPixelFormat.u4.dwBBitMask == 0x000000FF)) {
3645 buffer_format = GL_UNSIGNED_INT_8_8_8_8_REV;
3646 buffer_color = GL_BGRA;
3648 ERR(" unsupported pixel format at device locking.\n");
3652 ERR(" unsupported pixel format at device locking - alpha on frame buffer.\n");
3658 if (buffer_type == WINE_GL_BUFFER_FRONT)
3659 /* Application wants to lock the front buffer */
3660 glReadBuffer(GL_FRONT);
3662 /* Application wants to lock the back buffer */
3663 glReadBuffer(GL_BACK);
3665 dst = ((char *)This->surface_desc.lpSurface) +
3666 (pRect->top * This->surface_desc.u1.lPitch) + (pRect->left * GET_BPP(This->surface_desc));
3667 for (y = (This->surface_desc.dwHeight - pRect->top - 1);
3668 y >= ((int) This->surface_desc.dwHeight - (int) pRect->bottom);
3670 glReadPixels(pRect->left, y,
3671 pRect->right - pRect->left, 1,
3672 buffer_color, buffer_format, dst);
3673 dst += This->surface_desc.u1.lPitch;
3676 gl_d3d_dev->state[buffer_type] = SURFACE_MEMORY;
3679 /* I keep this code here as it's very useful to debug :-) */
3681 static int flush_count = 0;
3685 if ((++flush_count % 50) == 0) {
3686 sprintf(buf, "lock_%06d.pnm", flush_count);
3687 f = fopen(buf, "wb");
3688 DDRAW_dump_surface_to_disk(This, f);
3697 static void d3ddevice_flush_to_frame_buffer(IDirect3DDeviceImpl *d3d_dev, LPCRECT pRect, IDirectDrawSurfaceImpl *surf) {
3699 IDirect3DDeviceGLImpl* gl_d3d_dev = (IDirect3DDeviceGLImpl*) d3d_dev;
3704 /* Note : no need here to lock the 'device critical section' as we are already protected by
3705 the GL critical section. */
3707 if (pRect == NULL) {
3710 loc_rect.bottom = d3d_dev->surface->surface_desc.dwHeight;
3711 loc_rect.right = d3d_dev->surface->surface_desc.dwWidth;
3715 TRACE(" flushing memory back to screen memory (%ld,%ld) x (%ld,%ld).\n", pRect->top, pRect->left, pRect->right, pRect->bottom);
3717 opt_bitmap = d3ddevice_set_state_for_flush(d3d_dev, pRect, FALSE, &initial);
3719 if (upload_surface_to_tex_memory_init(surf, 0, &gl_d3d_dev->current_internal_format,
3720 initial, FALSE, UNLOCK_TEX_SIZE, UNLOCK_TEX_SIZE) != DD_OK) {
3721 ERR(" unsupported pixel format at frame buffer flush.\n");
3725 for (y = pRect->top; y < pRect->bottom; y += UNLOCK_TEX_SIZE) {
3729 flush_rect.bottom = (y + UNLOCK_TEX_SIZE > pRect->bottom) ? pRect->bottom : (y + UNLOCK_TEX_SIZE);
3731 for (x = pRect->left; x < pRect->right; x += UNLOCK_TEX_SIZE) {
3732 /* First, upload the texture... */
3733 flush_rect.left = x;
3734 flush_rect.right = (x + UNLOCK_TEX_SIZE > pRect->right) ? pRect->right : (x + UNLOCK_TEX_SIZE);
3736 upload_surface_to_tex_memory(&flush_rect, 0, 0, &(gl_d3d_dev->surface_ptr));
3739 glTexCoord2f(0.0, 0.0);
3740 glVertex3d(x, y, 0.5);
3741 glTexCoord2f(1.0, 0.0);
3742 glVertex3d(x + UNLOCK_TEX_SIZE, y, 0.5);
3743 glTexCoord2f(1.0, 1.0);
3744 glVertex3d(x + UNLOCK_TEX_SIZE, y + UNLOCK_TEX_SIZE, 0.5);
3745 glTexCoord2f(0.0, 1.0);
3746 glVertex3d(x, y + UNLOCK_TEX_SIZE, 0.5);
3751 upload_surface_to_tex_memory_release();
3752 d3ddevice_restore_state_after_flush(d3d_dev, opt_bitmap, FALSE);
3755 /* I keep this code here as it's very useful to debug :-) */
3757 static int flush_count = 0;
3761 if ((++flush_count % 50) == 0) {
3762 sprintf(buf, "flush_%06d.pnm", flush_count);
3763 f = fopen(buf, "wb");
3764 DDRAW_dump_surface_to_disk(surf, f);
3770 static void d3ddevice_unlock_update(IDirectDrawSurfaceImpl* This, LPCRECT pRect)
3772 WINE_GL_BUFFER_TYPE buffer_type;
3773 IDirect3DDeviceImpl *d3d_dev = This->d3ddevice;
3774 IDirect3DDeviceGLImpl* gl_d3d_dev = (IDirect3DDeviceGLImpl*) d3d_dev;
3776 if ((This->surface_desc.ddsCaps.dwCaps & (DDSCAPS_FRONTBUFFER|DDSCAPS_PRIMARYSURFACE)) != 0) {
3777 buffer_type = WINE_GL_BUFFER_FRONT;
3778 } else if ((This->surface_desc.ddsCaps.dwCaps & (DDSCAPS_BACKBUFFER)) == (DDSCAPS_BACKBUFFER)) {
3779 buffer_type = WINE_GL_BUFFER_BACK;
3781 ERR("Wrong surface type for locking !\n");
3785 if (gl_d3d_dev->lock_rect_valid[buffer_type] == FALSE) {
3786 ERR("Unlock without prior lock on %s buffer... Expect problems !\n",
3787 (buffer_type == WINE_GL_BUFFER_BACK ? "back" : "front"));
3789 gl_d3d_dev->lock_rect_valid[buffer_type] = FALSE;
3791 /* First, check if we need to do anything. For the backbuffer, flushing is done at the next 3D activity. */
3792 if ((This->lastlocktype & DDLOCK_READONLY) == 0) {
3793 if (buffer_type == WINE_GL_BUFFER_FRONT) {
3796 TRACE(" flushing front buffer immediatly on screen.\n");
3799 glGetIntegerv(GL_DRAW_BUFFER, &prev_draw);
3800 glDrawBuffer(GL_FRONT);
3801 /* Note: we do not use the application provided lock rectangle but our own stored at
3802 lock time. This is because in old D3D versions, the 'lock' parameter did not
3805 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]);
3806 glDrawBuffer(prev_draw);
3809 gl_d3d_dev->state[WINE_GL_BUFFER_BACK] = SURFACE_MEMORY_DIRTY;
3813 /* And 'frees' the device critical section */
3814 LeaveCriticalSection(&(d3d_dev->crit));
3818 apply_texture_state(IDirect3DDeviceImpl *This)
3822 /* Initialize texture stages states */
3823 for (stage = 0; stage < MAX_TEXTURES; stage++) {
3824 for (state = 0; state < HIGHEST_TEXTURE_STAGE_STATE; state += 1) {
3825 if (This->state_block.set_flags.texture_stage_state[stage][state] == TRUE) {
3826 IDirect3DDevice7_SetTextureStageState(ICOM_INTERFACE(This, IDirect3DDevice7),
3827 stage, state + 1, This->state_block.texture_stage_state[stage][state]);
3834 d3ddevice_create(IDirect3DDeviceImpl **obj, IDirectDrawImpl *d3d, IDirectDrawSurfaceImpl *surface, BOOLEAN from_surface)
3836 IDirect3DDeviceImpl *object;
3837 IDirect3DDeviceGLImpl *gl_object;
3838 IDirectDrawSurfaceImpl *surf;
3843 XVisualInfo template;
3844 GLenum buffer = GL_FRONT;
3847 object = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(IDirect3DDeviceGLImpl));
3848 if (object == NULL) return DDERR_OUTOFMEMORY;
3850 gl_object = (IDirect3DDeviceGLImpl *) object;
3854 object->surface = surface;
3855 object->set_context = set_context;
3856 object->clear = d3ddevice_clear_back;
3857 object->set_matrices = d3ddevice_set_matrices;
3858 object->matrices_updated = d3ddevice_matrices_updated;
3859 object->flush_to_framebuffer = d3ddevice_flush_to_frame_buffer;
3861 TRACE(" creating OpenGL device for surface = %p, d3d = %p\n", surface, d3d);
3863 InitializeCriticalSection(&(object->crit));
3865 TRACE(" device critical section : %p\n", &(object->crit));
3867 /* This is just a hack for some badly done games :-/ */
3869 gl_object->version = 1;
3870 TRACE(" using D3D1 special hacks.\n");
3872 gl_object->version = 7;
3874 device_context = GetDC(surface->ddraw_owner->window);
3875 gl_object->display = get_display(device_context);
3876 gl_object->drawable = get_drawable(device_context);
3877 ReleaseDC(surface->ddraw_owner->window,device_context);
3880 template.visualid = (VisualID)GetPropA( GetDesktopWindow(), "__wine_x11_visual_id" );
3881 vis = XGetVisualInfo(gl_object->display, VisualIDMask, &template, &num);
3883 HeapFree(GetProcessHeap(), 0, object);
3884 ERR("No visual found !\n");
3886 return DDERR_INVALIDPARAMS;
3888 TRACE(" visual found\n");
3891 gl_object->gl_context = glXCreateContext(gl_object->display, vis,
3894 if (gl_object->gl_context == NULL) {
3895 HeapFree(GetProcessHeap(), 0, object);
3896 ERR("Error in context creation !\n");
3898 return DDERR_INVALIDPARAMS;
3900 TRACE(" context created (%p)\n", gl_object->gl_context);
3903 /* Look for the front buffer and override its surface's Flip method (if in double buffering) */
3904 for (surf = surface; surf != NULL; surf = surf->surface_owner) {
3905 if ((surf->surface_desc.ddsCaps.dwCaps&(DDSCAPS_FLIP|DDSCAPS_FRONTBUFFER)) == (DDSCAPS_FLIP|DDSCAPS_FRONTBUFFER)) {
3906 surf->aux_ctx = (LPVOID) object;
3907 surf->aux_data = (LPVOID) gl_object->drawable;
3908 surf->aux_flip = opengl_flip;
3913 /* We are not doing any double buffering.. Then force OpenGL to draw on the front buffer */
3915 TRACE(" no double buffering : drawing on the front buffer\n");
3919 for (surf = surface; surf != NULL; surf = surf->surface_owner) {
3920 IDirectDrawSurfaceImpl *surf2;
3921 for (surf2 = surf; surf2->prev_attached != NULL; surf2 = surf2->prev_attached) ;
3922 for (; surf2 != NULL; surf2 = surf2->next_attached) {
3923 TRACE(" checking surface %p :", surf2);
3924 if (((surf2->surface_desc.ddsCaps.dwCaps & (DDSCAPS_3DDEVICE)) == (DDSCAPS_3DDEVICE)) &&
3925 ((surf2->surface_desc.ddsCaps.dwCaps & (DDSCAPS_ZBUFFER)) != (DDSCAPS_ZBUFFER))) {
3926 /* Override the Lock / Unlock function for all these surfaces */
3927 surf2->lock_update_prev = surf2->lock_update;
3928 surf2->lock_update = d3ddevice_lock_update;
3929 surf2->unlock_update_prev = surf2->unlock_update;
3930 surf2->unlock_update = d3ddevice_unlock_update;
3931 /* And install also the blt / bltfast overrides */
3932 surf2->aux_blt = d3ddevice_blt;
3933 surf2->aux_bltfast = d3ddevice_bltfast;
3935 TRACE(" overiding direct surface access.\n");
3937 TRACE(" no overide.\n");
3939 surf2->d3ddevice = object;
3943 /* Set the various light parameters */
3944 for (light = 0; light < MAX_LIGHTS; light++) {
3945 /* Only set the fields that are not zero-created */
3946 object->light_parameters[light].dltType = D3DLIGHT_DIRECTIONAL;
3947 object->light_parameters[light].dcvDiffuse.u1.r = 1.0;
3948 object->light_parameters[light].dcvDiffuse.u2.g = 1.0;
3949 object->light_parameters[light].dcvDiffuse.u3.b = 1.0;
3950 object->light_parameters[light].dvDirection.u3.z = 1.0;
3953 /* Allocate memory for the matrices */
3954 object->world_mat = (D3DMATRIX *) HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, 16 * sizeof(float));
3955 object->view_mat = (D3DMATRIX *) HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, 16 * sizeof(float));
3956 object->proj_mat = (D3DMATRIX *) HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, 16 * sizeof(float));
3957 memcpy(object->world_mat, id_mat, 16 * sizeof(float));
3958 memcpy(object->view_mat , id_mat, 16 * sizeof(float));
3959 memcpy(object->proj_mat , id_mat, 16 * sizeof(float));
3960 for (tex_num = 0; tex_num < MAX_TEXTURES; tex_num++) {
3961 object->tex_mat[tex_num] = (D3DMATRIX *) HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, 16 * sizeof(float));
3962 memcpy(object->tex_mat[tex_num], id_mat, 16 * sizeof(float));
3963 object->tex_mat_is_identity[tex_num] = TRUE;
3966 /* Initialisation */
3967 TRACE(" setting current context\n");
3968 object->set_context(object);
3969 TRACE(" current context set\n");
3971 /* allocate the clipping planes */
3972 object->max_clipping_planes = opengl_device_caps.wMaxUserClipPlanes;
3973 object->clipping_planes = (d3d7clippingplane*)HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, object->max_clipping_planes * sizeof(d3d7clippingplane));
3975 glHint(GL_FOG_HINT,GL_NICEST);
3977 /* Initialize the various GL contexts to be in sync with what we store locally */
3980 glClearColor(0.0, 0.0, 0.0, 0.0);
3981 glDepthMask(GL_TRUE);
3982 gl_object->depth_mask = TRUE;
3983 glEnable(GL_DEPTH_TEST);
3984 gl_object->depth_test = TRUE;
3985 glDisable(GL_ALPHA_TEST);
3986 glDisable(GL_STENCIL_TEST);
3987 glDisable(GL_CULL_FACE);
3988 glDisable(GL_LIGHTING);
3989 glDisable(GL_BLEND);
3991 glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);
3992 gl_object->current_tex_env = GL_REPLACE;
3993 gl_object->current_active_tex_unit = GL_TEXTURE0_WINE;
3994 if (GL_extensions.glActiveTexture != NULL) {
3995 GL_extensions.glActiveTexture(GL_TEXTURE0_WINE);
3997 gl_object->current_alpha_test_ref = 0.0;
3998 gl_object->current_alpha_test_func = GL_ALWAYS;
3999 glAlphaFunc(GL_ALWAYS, 0.0);
4001 glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
4002 glDrawBuffer(buffer);
4003 glReadBuffer(buffer);
4004 /* glDisable(GL_DEPTH_TEST); Need here to check for the presence of a ZBuffer and to reenable it when the ZBuffer is attached */
4007 gl_object->state[WINE_GL_BUFFER_BACK] = SURFACE_GL;
4008 gl_object->state[WINE_GL_BUFFER_FRONT] = SURFACE_GL;
4010 /* fill_device_capabilities(d3d->ddraw); */
4012 ICOM_INIT_INTERFACE(object, IDirect3DDevice, VTABLE_IDirect3DDevice);
4013 ICOM_INIT_INTERFACE(object, IDirect3DDevice2, VTABLE_IDirect3DDevice2);
4014 ICOM_INIT_INTERFACE(object, IDirect3DDevice3, VTABLE_IDirect3DDevice3);
4015 ICOM_INIT_INTERFACE(object, IDirect3DDevice7, VTABLE_IDirect3DDevice7);
4019 TRACE(" creating implementation at %p.\n", *obj);
4021 /* And finally warn D3D that this device is now present */
4022 object->d3d->d3d_added_device(object->d3d, object);
4024 /* FIXME: Should handle other versions than just 7 */
4025 InitDefaultStateBlock(&object->state_block, 7);
4026 /* Apply default render state and texture stage state values */
4027 apply_render_state(object, &object->state_block);
4028 apply_texture_state(object);
4030 /* And fill the fog table with the default fog value */
4031 build_fog_table(gl_object->fog_table, object->state_block.render_state[D3DRENDERSTATE_FOGCOLOR - 1]);
4036 static void fill_opengl_primcaps(D3DPRIMCAPS *pc)
4038 pc->dwSize = sizeof(*pc);
4039 pc->dwMiscCaps = D3DPMISCCAPS_CONFORMANT | D3DPMISCCAPS_CULLCCW | D3DPMISCCAPS_CULLCW |
4040 D3DPMISCCAPS_LINEPATTERNREP | D3DPMISCCAPS_MASKPLANES | D3DPMISCCAPS_MASKZ;
4041 pc->dwRasterCaps = D3DPRASTERCAPS_DITHER | D3DPRASTERCAPS_FOGRANGE | D3DPRASTERCAPS_FOGTABLE |
4042 D3DPRASTERCAPS_FOGVERTEX | D3DPRASTERCAPS_STIPPLE | D3DPRASTERCAPS_ZBIAS | D3DPRASTERCAPS_ZTEST | D3DPRASTERCAPS_SUBPIXEL |
4043 D3DPRASTERCAPS_ZFOG;
4044 if (GL_extensions.mipmap_lodbias == TRUE) {
4045 pc->dwRasterCaps |= D3DPRASTERCAPS_MIPMAPLODBIAS;
4047 pc->dwZCmpCaps = D3DPCMPCAPS_ALWAYS | D3DPCMPCAPS_EQUAL | D3DPCMPCAPS_GREATER | D3DPCMPCAPS_GREATEREQUAL |
4048 D3DPCMPCAPS_LESS | D3DPCMPCAPS_LESSEQUAL | D3DPCMPCAPS_NEVER | D3DPCMPCAPS_NOTEQUAL;
4049 pc->dwSrcBlendCaps = D3DPBLENDCAPS_ZERO | D3DPBLENDCAPS_ONE | D3DPBLENDCAPS_DESTCOLOR | D3DPBLENDCAPS_INVDESTCOLOR |
4050 D3DPBLENDCAPS_SRCALPHA | D3DPBLENDCAPS_INVSRCALPHA | D3DPBLENDCAPS_DESTALPHA | D3DPBLENDCAPS_INVDESTALPHA | D3DPBLENDCAPS_SRCALPHASAT |
4051 D3DPBLENDCAPS_BOTHSRCALPHA | D3DPBLENDCAPS_BOTHINVSRCALPHA;
4052 pc->dwDestBlendCaps = D3DPBLENDCAPS_ZERO | D3DPBLENDCAPS_ONE | D3DPBLENDCAPS_SRCCOLOR | D3DPBLENDCAPS_INVSRCCOLOR |
4053 D3DPBLENDCAPS_SRCALPHA | D3DPBLENDCAPS_INVSRCALPHA | D3DPBLENDCAPS_DESTALPHA | D3DPBLENDCAPS_INVDESTALPHA | D3DPBLENDCAPS_SRCALPHASAT |
4054 D3DPBLENDCAPS_BOTHSRCALPHA | D3DPBLENDCAPS_BOTHINVSRCALPHA;
4055 pc->dwAlphaCmpCaps = D3DPCMPCAPS_ALWAYS | D3DPCMPCAPS_EQUAL | D3DPCMPCAPS_GREATER | D3DPCMPCAPS_GREATEREQUAL |
4056 D3DPCMPCAPS_LESS | D3DPCMPCAPS_LESSEQUAL | D3DPCMPCAPS_NEVER | D3DPCMPCAPS_NOTEQUAL;
4057 pc->dwShadeCaps = D3DPSHADECAPS_ALPHAFLATBLEND | D3DPSHADECAPS_ALPHAGOURAUDBLEND | D3DPSHADECAPS_COLORFLATRGB | D3DPSHADECAPS_COLORGOURAUDRGB |
4058 D3DPSHADECAPS_FOGFLAT | D3DPSHADECAPS_FOGGOURAUD | D3DPSHADECAPS_SPECULARFLATRGB | D3DPSHADECAPS_SPECULARGOURAUDRGB;
4059 pc->dwTextureCaps = D3DPTEXTURECAPS_ALPHA | D3DPTEXTURECAPS_ALPHAPALETTE | D3DPTEXTURECAPS_BORDER | D3DPTEXTURECAPS_PERSPECTIVE |
4060 D3DPTEXTURECAPS_POW2 | D3DPTEXTURECAPS_TRANSPARENCY;
4061 pc->dwTextureFilterCaps = D3DPTFILTERCAPS_LINEAR | D3DPTFILTERCAPS_LINEARMIPLINEAR | D3DPTFILTERCAPS_LINEARMIPNEAREST |
4062 D3DPTFILTERCAPS_MIPLINEAR | D3DPTFILTERCAPS_MIPNEAREST | D3DPTFILTERCAPS_NEAREST | D3DPTFILTERCAPS_MAGFLINEAR |
4063 D3DPTFILTERCAPS_MAGFPOINT | D3DPTFILTERCAPS_MINFLINEAR | D3DPTFILTERCAPS_MINFPOINT | D3DPTFILTERCAPS_MIPFLINEAR |
4064 D3DPTFILTERCAPS_MIPFPOINT;
4065 pc->dwTextureBlendCaps = D3DPTBLENDCAPS_ADD | D3DPTBLENDCAPS_COPY | D3DPTBLENDCAPS_DECAL | D3DPTBLENDCAPS_DECALALPHA | D3DPTBLENDCAPS_DECALMASK |
4066 D3DPTBLENDCAPS_MODULATE | D3DPTBLENDCAPS_MODULATEALPHA | D3DPTBLENDCAPS_MODULATEMASK;
4067 pc->dwTextureAddressCaps = D3DPTADDRESSCAPS_BORDER | D3DPTADDRESSCAPS_CLAMP | D3DPTADDRESSCAPS_WRAP | D3DPTADDRESSCAPS_INDEPENDENTUV;
4068 if (GL_extensions.mirrored_repeat == TRUE) {
4069 pc->dwTextureAddressCaps |= D3DPTADDRESSCAPS_MIRROR;
4071 pc->dwStippleWidth = 32;
4072 pc->dwStippleHeight = 32;
4075 static void fill_caps(void)
4077 GLint max_clip_planes;
4080 /* Fill first all the fields with default values which will be overriden later on with
4081 correct ones from the GL code
4083 opengl_device_caps.dwDevCaps = D3DDEVCAPS_CANRENDERAFTERFLIP | D3DDEVCAPS_DRAWPRIMTLVERTEX | D3DDEVCAPS_EXECUTESYSTEMMEMORY |
4084 D3DDEVCAPS_EXECUTEVIDEOMEMORY | D3DDEVCAPS_FLOATTLVERTEX | D3DDEVCAPS_TEXTURENONLOCALVIDMEM | D3DDEVCAPS_TEXTURESYSTEMMEMORY |
4085 D3DDEVCAPS_TEXTUREVIDEOMEMORY | D3DDEVCAPS_TLVERTEXSYSTEMMEMORY | D3DDEVCAPS_TLVERTEXVIDEOMEMORY |
4086 /* D3D 7 capabilities */
4087 D3DDEVCAPS_DRAWPRIMITIVES2 | D3DDEVCAPS_HWTRANSFORMANDLIGHT | D3DDEVCAPS_HWRASTERIZATION;
4088 fill_opengl_primcaps(&(opengl_device_caps.dpcLineCaps));
4089 fill_opengl_primcaps(&(opengl_device_caps.dpcTriCaps));
4090 opengl_device_caps.dwDeviceRenderBitDepth = DDBD_16|DDBD_24|DDBD_32;
4091 opengl_device_caps.dwMinTextureWidth = 1;
4092 opengl_device_caps.dwMinTextureHeight = 1;
4093 opengl_device_caps.dwMaxTextureWidth = 1024;
4094 opengl_device_caps.dwMaxTextureHeight = 1024;
4095 opengl_device_caps.dwMaxTextureRepeat = 16;
4096 opengl_device_caps.dwMaxTextureAspectRatio = 1024;
4097 opengl_device_caps.dwMaxAnisotropy = 0;
4098 opengl_device_caps.dvGuardBandLeft = 0.0;
4099 opengl_device_caps.dvGuardBandRight = 0.0;
4100 opengl_device_caps.dvGuardBandTop = 0.0;
4101 opengl_device_caps.dvGuardBandBottom = 0.0;
4102 opengl_device_caps.dvExtentsAdjust = 0.0;
4103 opengl_device_caps.dwStencilCaps = D3DSTENCILCAPS_DECRSAT | D3DSTENCILCAPS_INCRSAT | D3DSTENCILCAPS_INVERT | D3DSTENCILCAPS_KEEP |
4104 D3DSTENCILCAPS_REPLACE | D3DSTENCILCAPS_ZERO;
4105 opengl_device_caps.dwTextureOpCaps = D3DTEXOPCAPS_DISABLE | D3DTEXOPCAPS_SELECTARG1 | D3DTEXOPCAPS_SELECTARG2 | D3DTEXOPCAPS_MODULATE4X |
4106 D3DTEXOPCAPS_MODULATE2X | D3DTEXOPCAPS_MODULATE | D3DTEXOPCAPS_ADD | D3DTEXOPCAPS_ADDSIGNED2X | D3DTEXOPCAPS_ADDSIGNED |
4107 D3DTEXOPCAPS_BLENDDIFFUSEALPHA | D3DTEXOPCAPS_BLENDTEXTUREALPHA | D3DTEXOPCAPS_BLENDFACTORALPHA | D3DTEXOPCAPS_BLENDCURRENTALPHA;
4108 if (GL_extensions.max_texture_units != 0) {
4109 opengl_device_caps.wMaxTextureBlendStages = GL_extensions.max_texture_units;
4110 opengl_device_caps.wMaxSimultaneousTextures = GL_extensions.max_texture_units;
4111 opengl_device_caps.dwFVFCaps = D3DFVFCAPS_DONOTSTRIPELEMENTS | GL_extensions.max_texture_units;
4113 opengl_device_caps.wMaxTextureBlendStages = 1;
4114 opengl_device_caps.wMaxSimultaneousTextures = 1;
4115 opengl_device_caps.dwFVFCaps = D3DFVFCAPS_DONOTSTRIPELEMENTS | 1;
4117 opengl_device_caps.dwMaxActiveLights = 16;
4118 opengl_device_caps.dvMaxVertexW = 100000000.0; /* No idea exactly what to put here... */
4119 opengl_device_caps.deviceGUID = IID_IDirect3DTnLHalDevice;
4120 opengl_device_caps.wMaxUserClipPlanes = 1;
4121 opengl_device_caps.wMaxVertexBlendMatrices = 0;
4122 opengl_device_caps.dwVertexProcessingCaps = D3DVTXPCAPS_TEXGEN | D3DVTXPCAPS_MATERIALSOURCE7 | D3DVTXPCAPS_VERTEXFOG |
4123 D3DVTXPCAPS_DIRECTIONALLIGHTS | D3DVTXPCAPS_POSITIONALLIGHTS | D3DVTXPCAPS_LOCALVIEWER;
4124 opengl_device_caps.dwReserved1 = 0;
4125 opengl_device_caps.dwReserved2 = 0;
4126 opengl_device_caps.dwReserved3 = 0;
4127 opengl_device_caps.dwReserved4 = 0;
4129 /* And now some GL overides :-) */
4130 glGetIntegerv(GL_MAX_TEXTURE_SIZE, (GLint *) &opengl_device_caps.dwMaxTextureWidth);
4131 opengl_device_caps.dwMaxTextureHeight = opengl_device_caps.dwMaxTextureWidth;
4132 opengl_device_caps.dwMaxTextureAspectRatio = opengl_device_caps.dwMaxTextureWidth;
4133 TRACE(": max texture size = %ld\n", opengl_device_caps.dwMaxTextureWidth);
4135 glGetIntegerv(GL_MAX_LIGHTS, (GLint *) &opengl_device_caps.dwMaxActiveLights);
4136 TRACE(": max active lights = %ld\n", opengl_device_caps.dwMaxActiveLights);
4138 glGetIntegerv(GL_MAX_CLIP_PLANES, &max_clip_planes);
4139 opengl_device_caps.wMaxUserClipPlanes = max_clip_planes;
4140 TRACE(": max clipping planes = %d\n", opengl_device_caps.wMaxUserClipPlanes);
4142 glGetIntegerv(GL_DEPTH_BITS, &depth_bits);
4143 TRACE(": Z bits = %d\n", depth_bits);
4144 switch (depth_bits) {
4145 case 16: opengl_device_caps.dwDeviceZBufferBitDepth = DDBD_16; break;
4146 case 24: opengl_device_caps.dwDeviceZBufferBitDepth = DDBD_16|DDBD_24; break;
4148 default: opengl_device_caps.dwDeviceZBufferBitDepth = DDBD_16|DDBD_24|DDBD_32; break;
4153 d3ddevice_init_at_startup(void *gl_handle)
4155 XVisualInfo template;
4160 Drawable drawable = (Drawable) GetPropA(GetDesktopWindow(), "__wine_x11_whole_window");
4161 XWindowAttributes win_attr;
4162 GLXContext gl_context;
4164 const char *glExtensions;
4165 const char *glVersion;
4166 const char *glXExtensions = NULL;
4167 const void *(*pglXGetProcAddressARB)(const GLubyte *) = NULL;
4168 int major, minor, patch, num_parsed;
4170 TRACE("Initializing GL...\n");
4172 /* Get a default rendering context to have the 'caps' function query some info from GL */
4173 device_context = GetDC(0);
4174 display = get_display(device_context);
4175 ReleaseDC(0, device_context);
4178 if (XGetWindowAttributes(display, drawable, &win_attr)) {
4179 visual = win_attr.visual;
4181 visual = DefaultVisual(display, DefaultScreen(display));
4183 template.visualid = XVisualIDFromVisual(visual);
4184 vis = XGetVisualInfo(display, VisualIDMask, &template, &num);
4187 WARN("Error creating visual info for capabilities initialization - D3D support disabled !\n");
4190 gl_context = glXCreateContext(display, vis, NULL, GL_TRUE);
4192 if (gl_context == NULL) {
4194 WARN("Error creating default context for capabilities initialization - D3D support disabled !\n");
4197 if (glXMakeCurrent(display, drawable, gl_context) == False) {
4198 glXDestroyContext(display, gl_context);
4200 WARN("Error setting default context as current for capabilities initialization - D3D support disabled !\n");
4204 /* Then, query all extensions */
4205 glXExtensions = glXQueryExtensionsString(display, DefaultScreen(display));
4206 glExtensions = (const char *) glGetString(GL_EXTENSIONS);
4207 glVersion = (const char *) glGetString(GL_VERSION);
4208 if ((glXExtensions != NULL) && (gl_handle != NULL) && (strstr(glXExtensions, "GLX_ARB_get_proc_address"))) {
4209 pglXGetProcAddressARB = wine_dlsym(gl_handle, "glXGetProcAddressARB", NULL, 0);
4212 /* Parse the GL version string */
4213 num_parsed = sscanf(glVersion, "%d.%d.%d", &major, &minor, &patch);
4214 if (num_parsed == 1) {
4217 } else if (num_parsed == 2) {
4220 TRACE("GL version %d.%d.%d\n", major, minor, patch);
4222 /* And starts to fill the extension context properly */
4223 memset(&GL_extensions, 0, sizeof(GL_extensions));
4224 TRACE("GL supports following extensions used by Wine :\n");
4226 /* Mirrored Repeat extension :
4227 - GL_ARB_texture_mirrored_repeat
4228 - GL_IBM_texture_mirrored_repeat
4231 if ((strstr(glExtensions, "GL_ARB_texture_mirrored_repeat")) ||
4232 (strstr(glExtensions, "GL_IBM_texture_mirrored_repeat")) ||
4234 ((major == 1) && (minor >= 4))) {
4235 TRACE(" - mirrored repeat\n");
4236 GL_extensions.mirrored_repeat = TRUE;
4239 /* Texture LOD Bias :
4240 - GL_EXT_texture_lod_bias
4242 if (strstr(glExtensions, "GL_EXT_texture_lod_bias")) {
4243 TRACE(" - texture lod bias\n");
4244 GL_extensions.mipmap_lodbias = TRUE;
4247 /* For all subsequent extensions, we need glXGetProcAddress */
4248 if (pglXGetProcAddressARB != NULL) {
4249 /* Multi-texturing :
4250 - GL_ARB_multitexture
4253 if ((strstr(glExtensions, "GL_ARB_multitexture")) ||
4255 ((major == 1) && (minor > 2)) ||
4256 ((major == 1) && (minor == 2) && (patch >= 1))) {
4257 glGetIntegerv(GL_MAX_TEXTURE_UNITS_WINE, &(GL_extensions.max_texture_units));
4258 TRACE(" - multi-texturing (%d stages)\n", GL_extensions.max_texture_units);
4259 /* We query the ARB version to be the most portable we can... */
4260 GL_extensions.glActiveTexture = pglXGetProcAddressARB("glActiveTextureARB");
4261 GL_extensions.glMultiTexCoord2fv = pglXGetProcAddressARB("glMultiTexCoord2fv");
4262 GL_extensions.glClientActiveTexture = pglXGetProcAddressARB("glClientActiveTextureARB");
4266 /* Fill the D3D capabilities according to what GL tells us... */
4269 /* And frees this now-useless context */
4270 glXMakeCurrent(display, None, NULL);
4271 glXDestroyContext(display, gl_context);