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_active_tex_unit != GL_TEXTURE0_WINE) {
109 GL_extensions.glActiveTexture(GL_TEXTURE0_WINE);
110 gl_d3d_dev->current_active_tex_unit = GL_TEXTURE0_WINE;
112 if (gl_d3d_dev->unlock_tex == 0) {
113 glGenTextures(1, &gl_d3d_dev->unlock_tex);
114 glBindTexture(GL_TEXTURE_2D, gl_d3d_dev->unlock_tex);
116 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
117 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
118 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP);
119 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP);
121 glBindTexture(GL_TEXTURE_2D, gl_d3d_dev->unlock_tex);
124 if (d3d_dev->tex_mat_is_identity[0] == FALSE) {
125 glMatrixMode(GL_TEXTURE);
129 if (gl_d3d_dev->transform_state != GL_TRANSFORM_ORTHO) {
130 gl_d3d_dev->transform_state = GL_TRANSFORM_ORTHO;
131 d3ddevice_set_ortho(d3d_dev);
134 if (gl_d3d_dev->depth_test != FALSE) glDisable(GL_DEPTH_TEST);
135 if ((gl_d3d_dev->current_bound_texture[0] == NULL) ||
136 (d3d_dev->state_block.texture_stage_state[0][D3DTSS_COLOROP - 1] == D3DTOP_DISABLE))
137 glEnable(GL_TEXTURE_2D);
138 if (gl_d3d_dev->current_bound_texture[1] != NULL) {
139 if (gl_d3d_dev->current_active_tex_unit != GL_TEXTURE1_WINE) {
140 GL_extensions.glActiveTexture(GL_TEXTURE1_WINE);
141 gl_d3d_dev->current_active_tex_unit = GL_TEXTURE1_WINE;
143 /* 'unbound' texture level 1 in that case to disable multi-texturing */
144 glBindTexture(GL_TEXTURE_2D, 0);
145 glDisable(GL_TEXTURE_2D);
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 glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, gl_d3d_dev->current_tex_env);
200 if (opt_bitmap & DEPTH_RANGE_BIT) {
201 glDepthRange(d3d_dev->active_viewport.dvMinZ, d3d_dev->active_viewport.dvMaxZ);
203 if (opt_bitmap & VIEWPORT_BIT) {
204 glViewport(d3d_dev->active_viewport.dwX,
205 d3d_dev->surface->surface_desc.dwHeight - (d3d_dev->active_viewport.dwHeight + d3d_dev->active_viewport.dwY),
206 d3d_dev->active_viewport.dwWidth, d3d_dev->active_viewport.dwHeight);
208 if (d3d_dev->tex_mat_is_identity[0] == FALSE) {
209 d3d_dev->matrices_updated(d3d_dev, TEXMAT0_CHANGED);
212 /* This is a hack to prevent querying the current texture from GL. Basically, at the next
213 DrawPrimitive call, this will bind the correct texture to this stage. */
214 gl_d3d_dev->current_bound_texture[0] = (IDirectDrawSurfaceImpl *) 0x00000001;
215 gl_d3d_dev->current_bound_texture[1] = (IDirectDrawSurfaceImpl *) 0x00000000;
216 if (d3d_dev->state_block.texture_stage_state[0][D3DTSS_COLOROP - 1] == D3DTOP_DISABLE) glDisable(GL_TEXTURE_2D);
219 /* retrieve the X drawable to use on a given DC */
220 inline static Drawable get_drawable( HDC hdc )
223 enum x11drv_escape_codes escape = X11DRV_GET_DRAWABLE;
225 if (!ExtEscape( hdc, X11DRV_ESCAPE, sizeof(escape), (LPCSTR)&escape,
226 sizeof(drawable), (LPSTR)&drawable )) drawable = 0;
231 /* This is unnecessarely complicated :-) */
232 #define MEASUREMENT_WINDOW 5
233 #define NUMBER_OF_WINDOWS 10
235 static LONGLONG perf_freq;
236 static LONGLONG perf_storage[NUMBER_OF_WINDOWS];
237 static LONGLONG prev_time = 0;
238 static unsigned int current_window;
239 static unsigned int measurements_in_window;
240 static unsigned int valid_windows;
242 static BOOL opengl_flip( LPVOID dev, LPVOID drawable)
244 IDirect3DDeviceImpl *d3d_dev = (IDirect3DDeviceImpl *) dev;
245 IDirect3DDeviceGLImpl *gl_d3d_dev = (IDirect3DDeviceGLImpl *) dev;
247 TRACE("(%p, %ld)\n", gl_d3d_dev->display,(Drawable)drawable);
249 if (gl_d3d_dev->state[WINE_GL_BUFFER_BACK] == SURFACE_MEMORY_DIRTY) {
250 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]);
252 gl_d3d_dev->state[WINE_GL_BUFFER_BACK] = SURFACE_GL;
253 gl_d3d_dev->state[WINE_GL_BUFFER_FRONT] = SURFACE_GL;
254 glXSwapBuffers(gl_d3d_dev->display, (Drawable)drawable);
257 if (TRACE_ON(ddraw_fps)) {
258 LONGLONG current_time;
259 LONGLONG frame_duration;
260 QueryPerformanceCounter((LARGE_INTEGER *) ¤t_time);
262 if (prev_time != 0) {
263 LONGLONG total_time = 0;
266 frame_duration = current_time - prev_time;
267 prev_time = current_time;
269 perf_storage[current_window] += frame_duration;
270 measurements_in_window++;
272 if (measurements_in_window >= MEASUREMENT_WINDOW) {
276 if (valid_windows < NUMBER_OF_WINDOWS) {
278 tot_meas = valid_windows * MEASUREMENT_WINDOW;
279 for (i = 0; i < valid_windows; i++) {
280 total_time += perf_storage[i];
284 tot_meas = NUMBER_OF_WINDOWS * MEASUREMENT_WINDOW;
285 for (i = 0; i < NUMBER_OF_WINDOWS; i++) {
286 total_time += perf_storage[i];
290 TRACE_(ddraw_fps)(" %9.5f\n", (double) (perf_freq * tot_meas) / (double) total_time);
292 if (current_window >= NUMBER_OF_WINDOWS) {
295 perf_storage[current_window] = 0;
296 measurements_in_window = 0;
299 prev_time = current_time;
300 memset(perf_storage, 0, sizeof(perf_storage));
303 measurements_in_window = 0;
304 QueryPerformanceFrequency((LARGE_INTEGER *) &perf_freq);
312 /*******************************************************************************
313 * OpenGL static functions
315 static void set_context(IDirect3DDeviceImpl* This)
317 IDirect3DDeviceGLImpl* glThis = (IDirect3DDeviceGLImpl*) This;
319 TRACE("glxMakeCurrent %p, %ld, %p\n",glThis->display,glThis->drawable, glThis->gl_context);
321 if (glXMakeCurrent(glThis->display, glThis->drawable, glThis->gl_context) == False) {
322 ERR("Error in setting current context (context %p drawable %ld)!\n",
323 glThis->gl_context, glThis->drawable);
328 static void fill_opengl_caps(D3DDEVICEDESC *d1)
330 d1->dwSize = sizeof(*d1);
331 d1->dwFlags = D3DDD_COLORMODEL | D3DDD_DEVCAPS | D3DDD_TRANSFORMCAPS | D3DDD_BCLIPPING | D3DDD_LIGHTINGCAPS |
332 D3DDD_LINECAPS | D3DDD_TRICAPS | D3DDD_DEVICERENDERBITDEPTH | D3DDD_DEVICEZBUFFERBITDEPTH |
333 D3DDD_MAXBUFFERSIZE | D3DDD_MAXVERTEXCOUNT;
334 d1->dcmColorModel = D3DCOLOR_RGB;
335 d1->dwDevCaps = opengl_device_caps.dwDevCaps;
336 d1->dtcTransformCaps.dwSize = sizeof(D3DTRANSFORMCAPS);
337 d1->dtcTransformCaps.dwCaps = D3DTRANSFORMCAPS_CLIP;
338 d1->bClipping = TRUE;
339 d1->dlcLightingCaps.dwSize = sizeof(D3DLIGHTINGCAPS);
340 d1->dlcLightingCaps.dwCaps = D3DLIGHTCAPS_DIRECTIONAL | D3DLIGHTCAPS_PARALLELPOINT | D3DLIGHTCAPS_POINT | D3DLIGHTCAPS_SPOT;
341 d1->dlcLightingCaps.dwLightingModel = D3DLIGHTINGMODEL_RGB;
342 d1->dlcLightingCaps.dwNumLights = opengl_device_caps.dwMaxActiveLights;
343 d1->dpcLineCaps = opengl_device_caps.dpcLineCaps;
344 d1->dpcTriCaps = opengl_device_caps.dpcTriCaps;
345 d1->dwDeviceRenderBitDepth = opengl_device_caps.dwDeviceRenderBitDepth;
346 d1->dwDeviceZBufferBitDepth = opengl_device_caps.dwDeviceZBufferBitDepth;
347 d1->dwMaxBufferSize = 0;
348 d1->dwMaxVertexCount = 65536;
349 d1->dwMinTextureWidth = opengl_device_caps.dwMinTextureWidth;
350 d1->dwMinTextureHeight = opengl_device_caps.dwMinTextureHeight;
351 d1->dwMaxTextureWidth = opengl_device_caps.dwMaxTextureWidth;
352 d1->dwMaxTextureHeight = opengl_device_caps.dwMaxTextureHeight;
353 d1->dwMinStippleWidth = 1;
354 d1->dwMinStippleHeight = 1;
355 d1->dwMaxStippleWidth = 32;
356 d1->dwMaxStippleHeight = 32;
357 d1->dwMaxTextureRepeat = opengl_device_caps.dwMaxTextureRepeat;
358 d1->dwMaxTextureAspectRatio = opengl_device_caps.dwMaxTextureAspectRatio;
359 d1->dwMaxAnisotropy = opengl_device_caps.dwMaxAnisotropy;
360 d1->dvGuardBandLeft = opengl_device_caps.dvGuardBandLeft;
361 d1->dvGuardBandRight = opengl_device_caps.dvGuardBandRight;
362 d1->dvGuardBandTop = opengl_device_caps.dvGuardBandTop;
363 d1->dvGuardBandBottom = opengl_device_caps.dvGuardBandBottom;
364 d1->dvExtentsAdjust = opengl_device_caps.dvExtentsAdjust;
365 d1->dwStencilCaps = opengl_device_caps.dwStencilCaps;
366 d1->dwFVFCaps = opengl_device_caps.dwFVFCaps;
367 d1->dwTextureOpCaps = opengl_device_caps.dwTextureOpCaps;
368 d1->wMaxTextureBlendStages = opengl_device_caps.wMaxTextureBlendStages;
369 d1->wMaxSimultaneousTextures = opengl_device_caps.wMaxSimultaneousTextures;
372 static void fill_opengl_caps_7(D3DDEVICEDESC7 *d)
374 *d = opengl_device_caps;
377 HRESULT d3ddevice_enumerate(LPD3DENUMDEVICESCALLBACK cb, LPVOID context, DWORD version)
379 D3DDEVICEDESC dref, d1, d2;
382 /* Some games (Motoracer 2 demo) have the bad idea to modify the device name string.
383 Let's put the string in a sufficiently sized array in writable memory. */
384 char device_name[50];
385 strcpy(device_name,"direct3d");
387 fill_opengl_caps(&dref);
390 /* It seems that enumerating the reference IID on Direct3D 1 games (AvP / Motoracer2) breaks them */
391 char interface_name[] = "WINE Reference Direct3DX using OpenGL";
392 TRACE(" enumerating OpenGL D3DDevice interface using reference IID (IID %s).\n", debugstr_guid(&IID_IDirect3DRefDevice));
395 ret_value = cb((LPIID) &IID_IDirect3DRefDevice, interface_name, device_name, &d1, &d2, context);
396 if (ret_value != D3DENUMRET_OK)
401 char interface_name[] = "WINE Direct3DX using OpenGL";
402 TRACE(" enumerating OpenGL D3DDevice interface (IID %s).\n", debugstr_guid(&IID_D3DDEVICE_OpenGL));
405 ret_value = cb((LPIID) &IID_D3DDEVICE_OpenGL, interface_name, device_name, &d1, &d2, context);
406 if (ret_value != D3DENUMRET_OK)
410 return D3DENUMRET_OK;
413 HRESULT d3ddevice_enumerate7(LPD3DENUMDEVICESCALLBACK7 cb, LPVOID context)
415 D3DDEVICEDESC7 ddesc;
416 char interface_name[] = "WINE Direct3D7 using OpenGL";
417 char device_name[] = "Wine D3D7 device";
419 fill_opengl_caps_7(&ddesc);
421 TRACE(" enumerating OpenGL D3DDevice7 interface.\n");
423 return cb(interface_name, device_name, &ddesc, context);
427 GL_IDirect3DDeviceImpl_7_3T_2T_1T_Release(LPDIRECT3DDEVICE7 iface)
429 ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice7, iface);
430 IDirect3DDeviceGLImpl *glThis = (IDirect3DDeviceGLImpl *) This;
432 TRACE("(%p/%p)->() decrementing from %lu.\n", This, iface, This->ref);
433 if (!--(This->ref)) {
435 IDirectDrawSurfaceImpl *surface = This->surface, *surf;
437 /* Release texture associated with the device */
438 for (i = 0; i < MAX_TEXTURES; i++) {
439 if (This->current_texture[i] != NULL)
440 IDirectDrawSurface7_Release(ICOM_INTERFACE(This->current_texture[i], IDirectDrawSurface7));
441 HeapFree(GetProcessHeap(), 0, This->tex_mat[i]);
444 /* Look for the front buffer and override its surface's Flip method (if in double buffering) */
445 for (surf = surface; surf != NULL; surf = surf->surface_owner) {
446 if ((surf->surface_desc.ddsCaps.dwCaps&(DDSCAPS_FLIP|DDSCAPS_FRONTBUFFER)) == (DDSCAPS_FLIP|DDSCAPS_FRONTBUFFER)) {
447 surf->aux_ctx = NULL;
448 surf->aux_data = NULL;
449 surf->aux_flip = NULL;
453 for (surf = surface; surf != NULL; surf = surf->surface_owner) {
454 IDirectDrawSurfaceImpl *surf2;
455 for (surf2 = surf; surf2->prev_attached != NULL; surf2 = surf2->prev_attached) ;
456 for (; surf2 != NULL; surf2 = surf2->next_attached) {
457 if (((surf2->surface_desc.ddsCaps.dwCaps & (DDSCAPS_3DDEVICE)) == (DDSCAPS_3DDEVICE)) &&
458 ((surf2->surface_desc.ddsCaps.dwCaps & (DDSCAPS_ZBUFFER)) != (DDSCAPS_ZBUFFER))) {
459 /* Override the Lock / Unlock function for all these surfaces */
460 surf2->lock_update = surf2->lock_update_prev;
461 surf2->unlock_update = surf2->unlock_update_prev;
462 /* And install also the blt / bltfast overrides */
463 surf2->aux_blt = NULL;
464 surf2->aux_bltfast = NULL;
466 surf2->d3ddevice = NULL;
470 /* And warn the D3D object that this device is no longer active... */
471 This->d3d->d3d_removed_device(This->d3d, This);
473 HeapFree(GetProcessHeap(), 0, This->world_mat);
474 HeapFree(GetProcessHeap(), 0, This->view_mat);
475 HeapFree(GetProcessHeap(), 0, This->proj_mat);
477 if (glThis->surface_ptr)
478 HeapFree(GetProcessHeap(), 0, glThis->surface_ptr);
480 DeleteCriticalSection(&(This->crit));
483 if (glThis->unlock_tex)
484 glDeleteTextures(1, &(glThis->unlock_tex));
485 glXDestroyContext(glThis->display, glThis->gl_context);
487 HeapFree(GetProcessHeap(), 0, This->clipping_planes);
489 HeapFree(GetProcessHeap(), 0, This);
496 GL_IDirect3DDeviceImpl_3_2T_1T_GetCaps(LPDIRECT3DDEVICE3 iface,
497 LPD3DDEVICEDESC lpD3DHWDevDesc,
498 LPD3DDEVICEDESC lpD3DHELDevDesc)
500 ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice3, iface);
504 TRACE("(%p/%p)->(%p,%p)\n", This, iface, lpD3DHWDevDesc, lpD3DHELDevDesc);
506 fill_opengl_caps(&desc);
507 dwSize = lpD3DHWDevDesc->dwSize;
508 memset(lpD3DHWDevDesc, 0, dwSize);
509 memcpy(lpD3DHWDevDesc, &desc, (dwSize <= desc.dwSize ? dwSize : desc.dwSize));
511 dwSize = lpD3DHELDevDesc->dwSize;
512 memset(lpD3DHELDevDesc, 0, dwSize);
513 memcpy(lpD3DHELDevDesc, &desc, (dwSize <= desc.dwSize ? dwSize : desc.dwSize));
515 TRACE(" returning caps : (no dump function yet)\n");
520 static HRESULT enum_texture_format_OpenGL(LPD3DENUMTEXTUREFORMATSCALLBACK cb_1,
521 LPD3DENUMPIXELFORMATSCALLBACK cb_2,
525 LPDDPIXELFORMAT pformat;
527 /* Do the texture enumeration */
528 sdesc.dwSize = sizeof(DDSURFACEDESC);
529 sdesc.dwFlags = DDSD_PIXELFORMAT | DDSD_CAPS;
530 sdesc.ddsCaps.dwCaps = DDSCAPS_TEXTURE;
531 pformat = &(sdesc.ddpfPixelFormat);
532 pformat->dwSize = sizeof(DDPIXELFORMAT);
533 pformat->dwFourCC = 0;
535 TRACE("Enumerating GL_RGBA unpacked (32)\n");
536 pformat->dwFlags = DDPF_RGB | DDPF_ALPHAPIXELS;
537 pformat->u1.dwRGBBitCount = 32;
538 pformat->u2.dwRBitMask = 0x00FF0000;
539 pformat->u3.dwGBitMask = 0x0000FF00;
540 pformat->u4.dwBBitMask = 0x000000FF;
541 pformat->u5.dwRGBAlphaBitMask = 0xFF000000;
542 if (cb_1) if (cb_1(&sdesc , context) == 0) return DD_OK;
543 if (cb_2) if (cb_2(pformat, context) == 0) return DD_OK;
545 TRACE("Enumerating GL_RGB unpacked (32)\n");
546 pformat->dwFlags = DDPF_RGB;
547 pformat->u1.dwRGBBitCount = 32;
548 pformat->u2.dwRBitMask = 0x00FF0000;
549 pformat->u3.dwGBitMask = 0x0000FF00;
550 pformat->u4.dwBBitMask = 0x000000FF;
551 pformat->u5.dwRGBAlphaBitMask = 0x00000000;
552 if (cb_1) if (cb_1(&sdesc , context) == 0) return DD_OK;
553 if (cb_2) if (cb_2(pformat, context) == 0) return DD_OK;
555 TRACE("Enumerating GL_RGB unpacked (24)\n");
556 pformat->dwFlags = DDPF_RGB;
557 pformat->u1.dwRGBBitCount = 24;
558 pformat->u2.dwRBitMask = 0x00FF0000;
559 pformat->u3.dwGBitMask = 0x0000FF00;
560 pformat->u4.dwBBitMask = 0x000000FF;
561 pformat->u5.dwRGBAlphaBitMask = 0x00000000;
562 if (cb_1) if (cb_1(&sdesc , context) == 0) return DD_OK;
563 if (cb_2) if (cb_2(pformat, context) == 0) return DD_OK;
565 /* Note : even if this is an 'emulated' texture format, it needs to be first
566 as some dumb applications seem to rely on that. */
567 TRACE("Enumerating GL_RGBA packed GL_UNSIGNED_SHORT_1_5_5_5 (ARGB) (16)\n");
568 pformat->dwFlags = DDPF_RGB | DDPF_ALPHAPIXELS;
569 pformat->u1.dwRGBBitCount = 16;
570 pformat->u2.dwRBitMask = 0x00007C00;
571 pformat->u3.dwGBitMask = 0x000003E0;
572 pformat->u4.dwBBitMask = 0x0000001F;
573 pformat->u5.dwRGBAlphaBitMask = 0x00008000;
574 if (cb_1) if (cb_1(&sdesc , context) == 0) return DD_OK;
575 if (cb_2) if (cb_2(pformat, context) == 0) return DD_OK;
577 TRACE("Enumerating GL_RGBA packed GL_UNSIGNED_SHORT_4_4_4_4 (ARGB) (16)\n");
578 pformat->dwFlags = DDPF_RGB | DDPF_ALPHAPIXELS;
579 pformat->u1.dwRGBBitCount = 16;
580 pformat->u2.dwRBitMask = 0x00000F00;
581 pformat->u3.dwGBitMask = 0x000000F0;
582 pformat->u4.dwBBitMask = 0x0000000F;
583 pformat->u5.dwRGBAlphaBitMask = 0x0000F000;
584 if (cb_1) if (cb_1(&sdesc , context) == 0) return DD_OK;
585 if (cb_2) if (cb_2(pformat, context) == 0) return DD_OK;
587 TRACE("Enumerating GL_RGB packed GL_UNSIGNED_SHORT_5_6_5 (16)\n");
588 pformat->dwFlags = DDPF_RGB;
589 pformat->u1.dwRGBBitCount = 16;
590 pformat->u2.dwRBitMask = 0x0000F800;
591 pformat->u3.dwGBitMask = 0x000007E0;
592 pformat->u4.dwBBitMask = 0x0000001F;
593 pformat->u5.dwRGBAlphaBitMask = 0x00000000;
594 if (cb_1) if (cb_1(&sdesc , context) == 0) return DD_OK;
595 if (cb_2) if (cb_2(pformat, context) == 0) return DD_OK;
597 TRACE("Enumerating GL_RGB packed GL_UNSIGNED_SHORT_5_5_5 (16)\n");
598 pformat->dwFlags = DDPF_RGB;
599 pformat->u1.dwRGBBitCount = 16;
600 pformat->u2.dwRBitMask = 0x00007C00;
601 pformat->u3.dwGBitMask = 0x000003E0;
602 pformat->u4.dwBBitMask = 0x0000001F;
603 pformat->u5.dwRGBAlphaBitMask = 0x00000000;
604 if (cb_1) if (cb_1(&sdesc , context) == 0) return DD_OK;
605 if (cb_2) if (cb_2(pformat, context) == 0) return DD_OK;
608 /* This is a compromise : some games choose the first 16 bit texture format with alpha they
609 find enumerated, others the last one. And both want to have the ARGB one.
611 So basically, forget our OpenGL roots and do not even enumerate our RGBA ones.
613 /* See argument about the RGBA format for 'packed' texture formats */
614 TRACE("Enumerating GL_RGBA unpacked (32)\n");
615 pformat->dwFlags = DDPF_RGB | DDPF_ALPHAPIXELS;
616 pformat->u1.dwRGBBitCount = 32;
617 pformat->u2.dwRBitMask = 0xFF000000;
618 pformat->u3.dwGBitMask = 0x00FF0000;
619 pformat->u4.dwBBitMask = 0x0000FF00;
620 pformat->u5.dwRGBAlphaBitMask = 0x000000FF;
621 if (cb_1) if (cb_1(&sdesc , context) == 0) return DD_OK;
622 if (cb_2) if (cb_2(pformat, context) == 0) return DD_OK;
624 TRACE("Enumerating GL_RGBA packed GL_UNSIGNED_SHORT_4_4_4_4 (16)\n");
625 pformat->dwFlags = DDPF_RGB | DDPF_ALPHAPIXELS;
626 pformat->u1.dwRGBBitCount = 16;
627 pformat->u2.dwRBitMask = 0x0000F000;
628 pformat->u3.dwGBitMask = 0x00000F00;
629 pformat->u4.dwBBitMask = 0x000000F0;
630 pformat->u5.dwRGBAlphaBitMask = 0x0000000F;
631 if (cb_1) if (cb_1(&sdesc , context) == 0) return DD_OK;
632 if (cb_2) if (cb_2(pformat, context) == 0) return DD_OK;
634 TRACE("Enumerating GL_RGBA packed GL_UNSIGNED_SHORT_5_5_5_1 (16)\n");
635 pformat->dwFlags = DDPF_RGB | DDPF_ALPHAPIXELS;
636 pformat->u1.dwRGBBitCount = 16;
637 pformat->u2.dwRBitMask = 0x0000F800;
638 pformat->u3.dwGBitMask = 0x000007C0;
639 pformat->u4.dwBBitMask = 0x0000003E;
640 pformat->u5.dwRGBAlphaBitMask = 0x00000001;
641 if (cb_1) if (cb_1(&sdesc , context) == 0) return DD_OK;
642 if (cb_2) if (cb_2(pformat, context) == 0) return DD_OK;
645 TRACE("Enumerating GL_RGB packed GL_UNSIGNED_BYTE_3_3_2 (8)\n");
646 pformat->dwFlags = DDPF_RGB;
647 pformat->u1.dwRGBBitCount = 8;
648 pformat->u2.dwRBitMask = 0x000000E0;
649 pformat->u3.dwGBitMask = 0x0000001C;
650 pformat->u4.dwBBitMask = 0x00000003;
651 pformat->u5.dwRGBAlphaBitMask = 0x00000000;
652 if (cb_1) if (cb_1(&sdesc , context) == 0) return DD_OK;
653 if (cb_2) if (cb_2(pformat, context) == 0) return DD_OK;
655 TRACE("Enumerating Paletted (8)\n");
656 pformat->dwFlags = DDPF_PALETTEINDEXED8;
657 pformat->u1.dwRGBBitCount = 8;
658 pformat->u2.dwRBitMask = 0x00000000;
659 pformat->u3.dwGBitMask = 0x00000000;
660 pformat->u4.dwBBitMask = 0x00000000;
661 pformat->u5.dwRGBAlphaBitMask = 0x00000000;
662 if (cb_1) if (cb_1(&sdesc , context) == 0) return DD_OK;
663 if (cb_2) if (cb_2(pformat, context) == 0) return DD_OK;
665 TRACE("End of enumeration\n");
671 d3ddevice_find(IDirectDrawImpl *d3d,
672 LPD3DFINDDEVICESEARCH lpD3DDFS,
673 LPD3DFINDDEVICERESULT lplpD3DDevice)
677 if ((lpD3DDFS->dwFlags & D3DFDS_COLORMODEL) &&
678 (lpD3DDFS->dcmColorModel != D3DCOLOR_RGB)) {
679 TRACE(" trying to request a non-RGB D3D color model. Not supported.\n");
680 return DDERR_INVALIDPARAMS; /* No real idea what to return here :-) */
682 if (lpD3DDFS->dwFlags & D3DFDS_GUID) {
683 TRACE(" trying to match guid %s.\n", debugstr_guid(&(lpD3DDFS->guid)));
684 if ((IsEqualGUID(&IID_D3DDEVICE_OpenGL, &(lpD3DDFS->guid)) == 0) &&
685 (IsEqualGUID(&IID_IDirect3DHALDevice, &(lpD3DDFS->guid)) == 0) &&
686 (IsEqualGUID(&IID_IDirect3DRefDevice, &(lpD3DDFS->guid)) == 0)) {
687 TRACE(" no match for this GUID.\n");
688 return DDERR_INVALIDPARAMS;
692 /* Now return our own GUID */
693 lplpD3DDevice->guid = IID_D3DDEVICE_OpenGL;
694 fill_opengl_caps(&desc);
695 lplpD3DDevice->ddHwDesc = desc;
696 lplpD3DDevice->ddSwDesc = desc;
698 TRACE(" returning Wine's OpenGL device with (undumped) capabilities\n");
704 GL_IDirect3DDeviceImpl_2_1T_EnumTextureFormats(LPDIRECT3DDEVICE2 iface,
705 LPD3DENUMTEXTUREFORMATSCALLBACK lpD3DEnumTextureProc,
708 ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice2, iface);
709 TRACE("(%p/%p)->(%p,%p)\n", This, iface, lpD3DEnumTextureProc, lpArg);
710 return enum_texture_format_OpenGL(lpD3DEnumTextureProc, NULL, lpArg);
714 GL_IDirect3DDeviceImpl_7_3T_EnumTextureFormats(LPDIRECT3DDEVICE7 iface,
715 LPD3DENUMPIXELFORMATSCALLBACK lpD3DEnumPixelProc,
718 ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice7, iface);
719 TRACE("(%p/%p)->(%p,%p)\n", This, iface, lpD3DEnumPixelProc, lpArg);
720 return enum_texture_format_OpenGL(NULL, lpD3DEnumPixelProc, lpArg);
724 GL_IDirect3DDeviceImpl_7_3T_2T_SetRenderState(LPDIRECT3DDEVICE7 iface,
725 D3DRENDERSTATETYPE dwRenderStateType,
728 ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice7, iface);
729 TRACE("(%p/%p)->(%08x,%08lx)\n", This, iface, dwRenderStateType, dwRenderState);
731 /* Call the render state functions */
732 store_render_state(This, dwRenderStateType, dwRenderState, &This->state_block);
733 set_render_state(This, dwRenderStateType, &This->state_block);
739 GL_IDirect3DDeviceImpl_7_3T_2T_GetRenderState(LPDIRECT3DDEVICE7 iface,
740 D3DRENDERSTATETYPE dwRenderStateType,
741 LPDWORD lpdwRenderState)
743 ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice7, iface);
744 TRACE("(%p/%p)->(%08x,%p)\n", This, iface, dwRenderStateType, lpdwRenderState);
746 /* Call the render state functions */
747 get_render_state(This, dwRenderStateType, lpdwRenderState, &This->state_block);
749 TRACE(" - asked for rendering state : %s, returning value %08lx.\n", _get_renderstate(dwRenderStateType), *lpdwRenderState);
755 GL_IDirect3DDeviceImpl_3_2T_SetLightState(LPDIRECT3DDEVICE3 iface,
756 D3DLIGHTSTATETYPE dwLightStateType,
759 ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice3, iface);
761 TRACE("(%p/%p)->(%08x,%08lx)\n", This, iface, dwLightStateType, dwLightState);
763 if (!dwLightStateType && (dwLightStateType > D3DLIGHTSTATE_COLORVERTEX)) {
764 TRACE("Unexpected Light State Type\n");
765 return DDERR_INVALIDPARAMS;
768 if (dwLightStateType == D3DLIGHTSTATE_MATERIAL /* 1 */) {
769 IDirect3DMaterialImpl *mat = (IDirect3DMaterialImpl *) dwLightState;
772 TRACE(" activating material %p.\n", mat);
775 ERR(" D3DLIGHTSTATE_MATERIAL called with NULL material !!!\n");
776 return DDERR_INVALIDPARAMS;
778 } else if (dwLightStateType == D3DLIGHTSTATE_COLORMODEL /* 3 */) {
779 switch (dwLightState) {
781 ERR("DDCOLOR_MONO should not happen!\n");
784 /* We are already in this mode */
785 TRACE("Setting color model to RGB (no-op).\n");
788 ERR("Unknown color model!\n");
789 return DDERR_INVALIDPARAMS;
792 D3DRENDERSTATETYPE rs;
793 switch (dwLightStateType) {
794 case D3DLIGHTSTATE_AMBIENT: /* 2 */
795 rs = D3DRENDERSTATE_AMBIENT;
797 case D3DLIGHTSTATE_FOGMODE: /* 4 */
798 rs = D3DRENDERSTATE_FOGVERTEXMODE;
800 case D3DLIGHTSTATE_FOGSTART: /* 5 */
801 rs = D3DRENDERSTATE_FOGSTART;
803 case D3DLIGHTSTATE_FOGEND: /* 6 */
804 rs = D3DRENDERSTATE_FOGEND;
806 case D3DLIGHTSTATE_FOGDENSITY: /* 7 */
807 rs = D3DRENDERSTATE_FOGDENSITY;
809 case D3DLIGHTSTATE_COLORVERTEX: /* 8 */
810 rs = D3DRENDERSTATE_COLORVERTEX;
813 ERR("Unknown D3DLIGHTSTATETYPE %d.\n", dwLightStateType);
814 return DDERR_INVALIDPARAMS;
817 IDirect3DDevice7_SetRenderState(ICOM_INTERFACE(This, IDirect3DDevice7),
824 static void draw_primitive_start_GL(D3DPRIMITIVETYPE d3dpt)
827 case D3DPT_POINTLIST:
828 TRACE("Start POINTS\n");
833 TRACE("Start LINES\n");
837 case D3DPT_LINESTRIP:
838 TRACE("Start LINE_STRIP\n");
839 glBegin(GL_LINE_STRIP);
842 case D3DPT_TRIANGLELIST:
843 TRACE("Start TRIANGLES\n");
844 glBegin(GL_TRIANGLES);
847 case D3DPT_TRIANGLESTRIP:
848 TRACE("Start TRIANGLE_STRIP\n");
849 glBegin(GL_TRIANGLE_STRIP);
852 case D3DPT_TRIANGLEFAN:
853 TRACE("Start TRIANGLE_FAN\n");
854 glBegin(GL_TRIANGLE_FAN);
858 FIXME("Unhandled primitive %08x\n", d3dpt);
863 /* This function calculate the Z coordinate from Zproj */
864 static float ZfromZproj(IDirect3DDeviceImpl *This, D3DVALUE Zproj)
867 /* Assume that X = Y = 0 and W = 1 */
868 a = This->proj_mat->_33;
869 b = This->proj_mat->_34;
870 c = This->proj_mat->_43;
871 d = This->proj_mat->_44;
872 /* We have in homogenous coordinates Z' = a * Z + c and W' = b * Z + d
873 * So in non homogenous coordinates we have Zproj = (a * Z + c) / (b * Z + d)
874 * And finally Z = (d * Zproj - c) / (a - b * Zproj)
876 return (d*Zproj - c) / (a - b*Zproj);
879 static void build_fog_table(BYTE *fog_table, DWORD fog_color) {
882 TRACE(" rebuilding fog table (%06lx)...\n", fog_color & 0x00FFFFFF);
884 for (i = 0; i < 3; i++) {
885 BYTE fog_color_component = (fog_color >> (8 * i)) & 0xFF;
887 for (elt = 0; elt < 0x10000; elt++) {
888 /* We apply the fog transformation and cache the result */
889 DWORD fog_intensity = elt & 0xFF;
890 DWORD vertex_color = (elt >> 8) & 0xFF;
891 fog_table[(i * 0x10000) + elt] = ((fog_intensity * vertex_color) + ((0xFF - fog_intensity) * fog_color_component)) / 0xFF;
896 static void draw_primitive_handle_GL_state(IDirect3DDeviceImpl *This,
897 BOOLEAN vertex_transformed,
898 BOOLEAN vertex_lit) {
899 IDirect3DDeviceGLImpl* glThis = (IDirect3DDeviceGLImpl*) This;
901 /* Puts GL in the correct lighting / transformation mode */
902 if ((vertex_transformed == FALSE) &&
903 (glThis->transform_state != GL_TRANSFORM_NORMAL)) {
904 /* Need to put the correct transformation again if we go from Transformed
905 vertices to non-transformed ones.
907 This->set_matrices(This, VIEWMAT_CHANGED|WORLDMAT_CHANGED|PROJMAT_CHANGED,
908 This->world_mat, This->view_mat, This->proj_mat);
909 glThis->transform_state = GL_TRANSFORM_NORMAL;
911 } else if ((vertex_transformed == TRUE) &&
912 (glThis->transform_state != GL_TRANSFORM_ORTHO)) {
913 /* Set our orthographic projection */
914 if (glThis->transform_state != GL_TRANSFORM_ORTHO) {
915 glThis->transform_state = GL_TRANSFORM_ORTHO;
916 d3ddevice_set_ortho(This);
920 /* TODO: optimize this to not always reset all the fog stuff on all DrawPrimitive call
921 if no fogging state change occurred */
922 if (This->state_block.render_state[D3DRENDERSTATE_FOGENABLE - 1] == TRUE) {
923 if (vertex_transformed == TRUE) {
924 if (glThis->fogging != 0) {
928 /* Now check if our fog_table still corresponds to the current vertex color.
929 Element '0x..00' is always the fog color as it corresponds to maximum fog intensity */
930 if ((glThis->fog_table[0 * 0x10000 + 0x0000] != ((This->state_block.render_state[D3DRENDERSTATE_FOGCOLOR - 1] >> 0) & 0xFF)) ||
931 (glThis->fog_table[1 * 0x10000 + 0x0000] != ((This->state_block.render_state[D3DRENDERSTATE_FOGCOLOR - 1] >> 8) & 0xFF)) ||
932 (glThis->fog_table[2 * 0x10000 + 0x0000] != ((This->state_block.render_state[D3DRENDERSTATE_FOGCOLOR - 1] >> 16) & 0xFF))) {
933 /* We need to rebuild our fog table.... */
934 build_fog_table(glThis->fog_table, This->state_block.render_state[D3DRENDERSTATE_FOGCOLOR - 1]);
937 if (This->state_block.render_state[D3DRENDERSTATE_FOGTABLEMODE - 1] != D3DFOG_NONE) {
938 switch (This->state_block.render_state[D3DRENDERSTATE_FOGTABLEMODE - 1]) {
939 case D3DFOG_LINEAR: glFogi(GL_FOG_MODE, GL_LINEAR); break;
940 case D3DFOG_EXP: glFogi(GL_FOG_MODE, GL_EXP); break;
941 case D3DFOG_EXP2: glFogi(GL_FOG_MODE, GL_EXP2); break;
943 if (vertex_lit == FALSE) {
944 glFogf(GL_FOG_START, *(float*)&This->state_block.render_state[D3DRENDERSTATE_FOGSTART - 1]);
945 glFogf(GL_FOG_END, *(float*)&This->state_block.render_state[D3DRENDERSTATE_FOGEND - 1]);
947 /* Special case of 'pixel fog' */
948 glFogf(GL_FOG_START, ZfromZproj(This, *(float*)&This->state_block.render_state[D3DRENDERSTATE_FOGSTART - 1]));
949 glFogf(GL_FOG_END, ZfromZproj(This, *(float*)&This->state_block.render_state[D3DRENDERSTATE_FOGEND - 1]));
951 if (glThis->fogging == 0) {
956 if (glThis->fogging != 0) {
963 if (glThis->fogging != 0) {
969 /* Handle the 'no-normal' case */
970 if ((vertex_lit == FALSE) && (This->state_block.render_state[D3DRENDERSTATE_LIGHTING - 1] == TRUE)) {
971 if (glThis->lighting == 0) {
972 glEnable(GL_LIGHTING);
973 glThis->lighting = 1;
976 if (glThis->lighting != 0) {
977 glDisable(GL_LIGHTING);
978 glThis->lighting = 0;
982 /* Handle the code for pre-vertex material properties */
983 if (vertex_transformed == FALSE) {
984 if ((This->state_block.render_state[D3DRENDERSTATE_LIGHTING - 1] == TRUE) &&
985 (This->state_block.render_state[D3DRENDERSTATE_COLORVERTEX - 1] == TRUE)) {
986 if ((This->state_block.render_state[D3DRENDERSTATE_DIFFUSEMATERIALSOURCE - 1] != D3DMCS_MATERIAL) ||
987 (This->state_block.render_state[D3DRENDERSTATE_AMBIENTMATERIALSOURCE - 1] != D3DMCS_MATERIAL) ||
988 (This->state_block.render_state[D3DRENDERSTATE_EMISSIVEMATERIALSOURCE - 1] != D3DMCS_MATERIAL) ||
989 (This->state_block.render_state[D3DRENDERSTATE_SPECULARMATERIALSOURCE - 1] != D3DMCS_MATERIAL)) {
990 glEnable(GL_COLOR_MATERIAL);
997 inline static void draw_primitive(IDirect3DDeviceImpl *This, DWORD maxvert, WORD *index,
998 D3DVERTEXTYPE d3dvt, D3DPRIMITIVETYPE d3dpt, void *lpvertex)
1000 D3DDRAWPRIMITIVESTRIDEDDATA strided;
1003 case D3DVT_VERTEX: {
1004 strided.position.lpvData = &((D3DVERTEX *) lpvertex)->u1.x;
1005 strided.position.dwStride = sizeof(D3DVERTEX);
1006 strided.normal.lpvData = &((D3DVERTEX *) lpvertex)->u4.nx;
1007 strided.normal.dwStride = sizeof(D3DVERTEX);
1008 strided.textureCoords[0].lpvData = &((D3DVERTEX *) lpvertex)->u7.tu;
1009 strided.textureCoords[0].dwStride = sizeof(D3DVERTEX);
1010 draw_primitive_strided(This, d3dpt, D3DFVF_VERTEX, &strided, 0 /* Unused */, index, maxvert, 0 /* Unused */);
1013 case D3DVT_LVERTEX: {
1014 strided.position.lpvData = &((D3DLVERTEX *) lpvertex)->u1.x;
1015 strided.position.dwStride = sizeof(D3DLVERTEX);
1016 strided.diffuse.lpvData = &((D3DLVERTEX *) lpvertex)->u4.color;
1017 strided.diffuse.dwStride = sizeof(D3DLVERTEX);
1018 strided.specular.lpvData = &((D3DLVERTEX *) lpvertex)->u5.specular;
1019 strided.specular.dwStride = sizeof(D3DLVERTEX);
1020 strided.textureCoords[0].lpvData = &((D3DLVERTEX *) lpvertex)->u6.tu;
1021 strided.textureCoords[0].dwStride = sizeof(D3DLVERTEX);
1022 draw_primitive_strided(This, d3dpt, D3DFVF_LVERTEX, &strided, 0 /* Unused */, index, maxvert, 0 /* Unused */);
1025 case D3DVT_TLVERTEX: {
1026 strided.position.lpvData = &((D3DTLVERTEX *) lpvertex)->u1.sx;
1027 strided.position.dwStride = sizeof(D3DTLVERTEX);
1028 strided.diffuse.lpvData = &((D3DTLVERTEX *) lpvertex)->u5.color;
1029 strided.diffuse.dwStride = sizeof(D3DTLVERTEX);
1030 strided.specular.lpvData = &((D3DTLVERTEX *) lpvertex)->u6.specular;
1031 strided.specular.dwStride = sizeof(D3DTLVERTEX);
1032 strided.textureCoords[0].lpvData = &((D3DTLVERTEX *) lpvertex)->u7.tu;
1033 strided.textureCoords[0].dwStride = sizeof(D3DTLVERTEX);
1034 draw_primitive_strided(This, d3dpt, D3DFVF_TLVERTEX, &strided, 0 /* Unused */, index, maxvert, 0 /* Unused */);
1038 FIXME("Unhandled vertex type %08x\n", d3dvt);
1044 GL_IDirect3DDeviceImpl_2_DrawPrimitive(LPDIRECT3DDEVICE2 iface,
1045 D3DPRIMITIVETYPE d3dptPrimitiveType,
1046 D3DVERTEXTYPE d3dvtVertexType,
1048 DWORD dwVertexCount,
1051 ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice2, iface);
1053 TRACE("(%p/%p)->(%08x,%08x,%p,%08lx,%08lx)\n", This, iface, d3dptPrimitiveType, d3dvtVertexType, lpvVertices, dwVertexCount, dwFlags);
1054 if (TRACE_ON(ddraw)) {
1055 TRACE(" - flags : "); dump_DPFLAGS(dwFlags);
1058 draw_primitive(This, dwVertexCount, NULL, d3dvtVertexType, d3dptPrimitiveType, lpvVertices);
1064 GL_IDirect3DDeviceImpl_2_DrawIndexedPrimitive(LPDIRECT3DDEVICE2 iface,
1065 D3DPRIMITIVETYPE d3dptPrimitiveType,
1066 D3DVERTEXTYPE d3dvtVertexType,
1068 DWORD dwVertexCount,
1073 ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice2, iface);
1074 TRACE("(%p/%p)->(%08x,%08x,%p,%08lx,%p,%08lx,%08lx)\n", This, iface, d3dptPrimitiveType, d3dvtVertexType, lpvVertices, dwVertexCount, dwIndices, dwIndexCount, dwFlags);
1075 if (TRACE_ON(ddraw)) {
1076 TRACE(" - flags : "); dump_DPFLAGS(dwFlags);
1079 draw_primitive(This, dwIndexCount, dwIndices, d3dvtVertexType, d3dptPrimitiveType, lpvVertices);
1085 GL_IDirect3DDeviceImpl_1_CreateExecuteBuffer(LPDIRECT3DDEVICE iface,
1086 LPD3DEXECUTEBUFFERDESC lpDesc,
1087 LPDIRECT3DEXECUTEBUFFER* lplpDirect3DExecuteBuffer,
1088 IUnknown* pUnkOuter)
1090 ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice, iface);
1091 IDirect3DExecuteBufferImpl *ret;
1094 TRACE("(%p/%p)->(%p,%p,%p)\n", This, iface, lpDesc, lplpDirect3DExecuteBuffer, pUnkOuter);
1096 ret_value = d3dexecutebuffer_create(&ret, This->d3d, This, lpDesc);
1097 *lplpDirect3DExecuteBuffer = ICOM_INTERFACE(ret, IDirect3DExecuteBuffer);
1099 TRACE(" returning %p.\n", *lplpDirect3DExecuteBuffer);
1104 static void flush_zbuffer_to_GL(IDirect3DDeviceImpl *d3d_dev, LPCRECT pRect, IDirectDrawSurfaceImpl *surf) {
1105 static BOOLEAN first = TRUE;
1106 IDirect3DDeviceGLImpl* gl_d3d_dev = (IDirect3DDeviceGLImpl*) d3d_dev;
1110 if (first == TRUE) {
1111 MESSAGE("Warning : application does direct locking of ZBuffer - expect slowdowns on many GL implementations :-)\n");
1115 TRACE("flushing ZBuffer back to GL\n");
1117 if (gl_d3d_dev->transform_state != GL_TRANSFORM_ORTHO) {
1118 gl_d3d_dev->transform_state = GL_TRANSFORM_ORTHO;
1119 d3ddevice_set_ortho(d3d_dev);
1122 glMatrixMode(GL_MODELVIEW);
1125 if (gl_d3d_dev->depth_test == 0) glEnable(GL_DEPTH_TEST);
1126 if (d3d_dev->state_block.render_state[D3DRENDERSTATE_ZFUNC - 1] != D3DCMP_ALWAYS) glDepthFunc(GL_ALWAYS);
1127 glColorMask(GL_FALSE, GL_FALSE, GL_FALSE, GL_FALSE);
1129 /* This loop here is to prevent using PixelZoom that may be unoptimized for the 1.0 / -1.0 case
1132 switch (surf->surface_desc.u4.ddpfPixelFormat.u1.dwZBufferBitDepth) {
1133 case 16: type = GL_UNSIGNED_SHORT; break;
1134 case 32: type = GL_UNSIGNED_INT; break;
1135 default: FIXME("Unhandled ZBuffer format !\n"); goto restore_state;
1138 for (row = 0; row < surf->surface_desc.dwHeight; row++) {
1139 /* glRasterPos3d(0.0, row + 1.0, 0.5); */
1140 glRasterPos2i(0, row + 1);
1141 glDrawPixels(surf->surface_desc.dwWidth, 1, GL_DEPTH_COMPONENT, type,
1142 ((unsigned char *) surf->surface_desc.lpSurface) + (row * surf->surface_desc.u1.lPitch));
1146 glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
1147 if (d3d_dev->state_block.render_state[D3DRENDERSTATE_ZFUNC - 1] != D3DCMP_ALWAYS)
1148 glDepthFunc(convert_D3D_compare_to_GL(d3d_dev->state_block.render_state[D3DRENDERSTATE_ZFUNC - 1]));
1149 if (gl_d3d_dev->depth_test == 0) glDisable(GL_DEPTH_TEST);
1152 /* These are the various handler used in the generic path */
1153 inline static void handle_xyz(D3DVALUE *coords) {
1154 glVertex3fv(coords);
1156 inline static void handle_xyzrhw(D3DVALUE *coords) {
1157 if (coords[3] < 1e-8)
1158 glVertex3fv(coords);
1160 GLfloat w = 1.0 / coords[3];
1162 glVertex4f(coords[0] * w,
1168 inline static void handle_normal(D3DVALUE *coords) {
1169 glNormal3fv(coords);
1172 inline static void handle_diffuse_base(STATEBLOCK *sb, DWORD *color) {
1173 if ((sb->render_state[D3DRENDERSTATE_ALPHATESTENABLE - 1] == TRUE) ||
1174 (sb->render_state[D3DRENDERSTATE_ALPHABLENDENABLE - 1] == TRUE)) {
1175 glColor4ub((*color >> 16) & 0xFF,
1176 (*color >> 8) & 0xFF,
1177 (*color >> 0) & 0xFF,
1178 (*color >> 24) & 0xFF);
1180 glColor3ub((*color >> 16) & 0xFF,
1181 (*color >> 8) & 0xFF,
1182 (*color >> 0) & 0xFF);
1186 inline static void handle_specular_base(STATEBLOCK *sb, DWORD *color) {
1187 glColor4ub((*color >> 16) & 0xFF,
1188 (*color >> 8) & 0xFF,
1189 (*color >> 0) & 0xFF,
1190 (*color >> 24) & 0xFF); /* No idea if the alpha field is really used.. */
1193 inline static void handle_diffuse(STATEBLOCK *sb, DWORD *color, BOOLEAN lighted) {
1194 if ((lighted == FALSE) &&
1195 (sb->render_state[D3DRENDERSTATE_LIGHTING - 1] == TRUE) &&
1196 (sb->render_state[D3DRENDERSTATE_COLORVERTEX - 1] == TRUE)) {
1197 if (sb->render_state[D3DRENDERSTATE_DIFFUSEMATERIALSOURCE - 1] == D3DMCS_COLOR1) {
1198 glColorMaterial(GL_FRONT_AND_BACK, GL_DIFFUSE);
1199 handle_diffuse_base(sb, color);
1201 if (sb->render_state[D3DRENDERSTATE_AMBIENTMATERIALSOURCE - 1] == D3DMCS_COLOR1) {
1202 glColorMaterial(GL_FRONT_AND_BACK, GL_AMBIENT);
1203 handle_diffuse_base(sb, color);
1205 if ((sb->render_state[D3DRENDERSTATE_SPECULARMATERIALSOURCE - 1] == D3DMCS_COLOR1) &&
1206 (sb->render_state[D3DRENDERSTATE_SPECULARENABLE - 1] == TRUE)) {
1207 glColorMaterial(GL_FRONT_AND_BACK, GL_SPECULAR);
1208 handle_diffuse_base(sb, color);
1210 if (sb->render_state[D3DRENDERSTATE_EMISSIVEMATERIALSOURCE - 1] == D3DMCS_COLOR1) {
1211 glColorMaterial(GL_FRONT_AND_BACK, GL_EMISSION);
1212 handle_diffuse_base(sb, color);
1215 handle_diffuse_base(sb, color);
1219 inline static void handle_specular(STATEBLOCK *sb, DWORD *color, BOOLEAN lighted) {
1220 if ((lighted == FALSE) &&
1221 (sb->render_state[D3DRENDERSTATE_LIGHTING - 1] == TRUE) &&
1222 (sb->render_state[D3DRENDERSTATE_COLORVERTEX - 1] == TRUE)) {
1223 if (sb->render_state[D3DRENDERSTATE_DIFFUSEMATERIALSOURCE - 1] == D3DMCS_COLOR2) {
1224 glColorMaterial(GL_FRONT_AND_BACK, GL_DIFFUSE);
1225 handle_specular_base(sb, color);
1227 if (sb->render_state[D3DRENDERSTATE_AMBIENTMATERIALSOURCE - 1] == D3DMCS_COLOR2) {
1228 glColorMaterial(GL_FRONT_AND_BACK, GL_AMBIENT);
1229 handle_specular_base(sb, color);
1231 if ((sb->render_state[D3DRENDERSTATE_SPECULARMATERIALSOURCE - 1] == D3DMCS_COLOR2) &&
1232 (sb->render_state[D3DRENDERSTATE_SPECULARENABLE - 1] == TRUE)) {
1233 glColorMaterial(GL_FRONT_AND_BACK, GL_SPECULAR);
1234 handle_specular_base(sb, color);
1236 if (sb->render_state[D3DRENDERSTATE_EMISSIVEMATERIALSOURCE - 1] == D3DMCS_COLOR2) {
1237 glColorMaterial(GL_FRONT_AND_BACK, GL_EMISSION);
1238 handle_specular_base(sb, color);
1241 /* No else here as we do not know how to handle 'specular' on its own in any case.. */
1244 inline static void handle_diffuse_and_specular(STATEBLOCK *sb, BYTE *fog_table, DWORD *color_d, DWORD *color_s, BOOLEAN lighted) {
1245 if (lighted == TRUE) {
1246 DWORD color = *color_d;
1247 if (sb->render_state[D3DRENDERSTATE_FOGENABLE - 1] == TRUE) {
1248 /* Special case where the specular value is used to do fogging */
1249 BYTE fog_intensity = *color_s >> 24; /* The alpha value of the specular component is the fog 'intensity' for this vertex */
1250 color &= 0xFF000000; /* Only keep the alpha component */
1251 color |= fog_table[((*color_d >> 0) & 0xFF) << 8 | fog_intensity] << 0;
1252 color |= fog_table[((*color_d >> 8) & 0xFF) << 8 | fog_intensity] << 8;
1253 color |= fog_table[((*color_d >> 16) & 0xFF) << 8 | fog_intensity] << 16;
1255 if (sb->render_state[D3DRENDERSTATE_SPECULARENABLE - 1] == TRUE) {
1256 /* Standard specular value in transformed mode. TODO */
1258 handle_diffuse_base(sb, &color);
1260 if (sb->render_state[D3DRENDERSTATE_LIGHTING - 1] == TRUE) {
1261 handle_diffuse(sb, color_d, FALSE);
1262 handle_specular(sb, color_s, FALSE);
1264 /* In that case, only put the diffuse color... */
1265 handle_diffuse_base(sb, color_d);
1270 inline static void handle_texture(D3DVALUE *coords) {
1271 glTexCoord2fv(coords);
1273 inline static void handle_textures(D3DVALUE *coords, int tex_stage) {
1274 if (GL_extensions.glMultiTexCoord2fv) {
1275 GL_extensions.glMultiTexCoord2fv(GL_TEXTURE0_WINE + tex_stage, coords);
1277 if (tex_stage == 0) glTexCoord2fv(coords);
1281 static void draw_primitive_strided(IDirect3DDeviceImpl *This,
1282 D3DPRIMITIVETYPE d3dptPrimitiveType,
1283 DWORD d3dvtVertexType,
1284 LPD3DDRAWPRIMITIVESTRIDEDDATA lpD3DDrawPrimStrideData,
1285 DWORD dwVertexCount,
1290 BOOLEAN vertex_lighted = FALSE;
1291 IDirect3DDeviceGLImpl* glThis = (IDirect3DDeviceGLImpl*) This;
1292 int num_active_stages = 0;
1294 /* I put the trace before the various locks... So as to better understand where locks occur :-) */
1295 if (TRACE_ON(ddraw)) {
1296 TRACE(" Vertex format : "); dump_flexible_vertex(d3dvtVertexType);
1299 /* This is to prevent 'thread contention' between a thread locking the device and another
1300 doing 3D display on it... */
1301 EnterCriticalSection(&(This->crit));
1304 if (glThis->state[WINE_GL_BUFFER_BACK] == SURFACE_MEMORY_DIRTY) {
1305 This->flush_to_framebuffer(This, &(glThis->lock_rect[WINE_GL_BUFFER_BACK]), glThis->lock_surf[WINE_GL_BUFFER_BACK]);
1307 glThis->state[WINE_GL_BUFFER_BACK] = SURFACE_GL;
1309 if (This->current_zbuffer == NULL) {
1310 /* Search for an attached ZBuffer */
1311 static const DDSCAPS2 zbuf_caps = { DDSCAPS_ZBUFFER, 0, 0, 0 };
1312 LPDIRECTDRAWSURFACE7 zbuf;
1315 hr = IDirectDrawSurface7_GetAttachedSurface(ICOM_INTERFACE(This->surface, IDirectDrawSurface7),
1316 (DDSCAPS2 *) &zbuf_caps, &zbuf);
1318 This->current_zbuffer = ICOM_OBJECT(IDirectDrawSurfaceImpl, IDirectDrawSurface7, zbuf);
1319 IDirectDrawSurface7_Release(zbuf);
1322 if (This->current_zbuffer != NULL) {
1323 if (This->current_zbuffer->get_dirty_status(This->current_zbuffer, NULL)) {
1324 flush_zbuffer_to_GL(This, NULL, This->current_zbuffer);
1328 if ( ((d3dvtVertexType & D3DFVF_POSITION_MASK) != D3DFVF_XYZ) ||
1329 ((d3dvtVertexType & D3DFVF_NORMAL) == 0) )
1330 vertex_lighted = TRUE;
1332 /* Compute the number of active texture stages and set the various texture parameters */
1333 num_active_stages = draw_primitive_handle_textures(This);
1335 /* And restore to handle '0' in the case we use glTexCorrd calls */
1336 if (glThis->current_active_tex_unit != GL_TEXTURE0_WINE) {
1337 GL_extensions.glActiveTexture(GL_TEXTURE0_WINE);
1338 glThis->current_active_tex_unit = GL_TEXTURE0_WINE;
1341 draw_primitive_handle_GL_state(This,
1342 (d3dvtVertexType & D3DFVF_POSITION_MASK) != D3DFVF_XYZ,
1344 draw_primitive_start_GL(d3dptPrimitiveType);
1346 /* Some fast paths first before the generic case.... */
1347 if ((d3dvtVertexType == D3DFVF_VERTEX) && (num_active_stages <= 1)) {
1350 for (index = 0; index < dwIndexCount; index++) {
1351 int i = (dwIndices == NULL) ? index : dwIndices[index];
1353 (D3DVALUE *) (((char *) lpD3DDrawPrimStrideData->normal.lpvData) + i * lpD3DDrawPrimStrideData->normal.dwStride);
1354 D3DVALUE *tex_coord =
1355 (D3DVALUE *) (((char *) lpD3DDrawPrimStrideData->textureCoords[0].lpvData) + i * lpD3DDrawPrimStrideData->textureCoords[0].dwStride);
1356 D3DVALUE *position =
1357 (D3DVALUE *) (((char *) lpD3DDrawPrimStrideData->position.lpvData) + i * lpD3DDrawPrimStrideData->position.dwStride);
1359 handle_normal(normal);
1360 handle_texture(tex_coord);
1361 handle_xyz(position);
1363 TRACE_(ddraw_geom)(" %f %f %f / %f %f %f (%f %f)\n",
1364 position[0], position[1], position[2],
1365 normal[0], normal[1], normal[2],
1366 tex_coord[0], tex_coord[1]);
1368 } else if ((d3dvtVertexType == D3DFVF_TLVERTEX) && (num_active_stages <= 1)) {
1371 for (index = 0; index < dwIndexCount; index++) {
1372 int i = (dwIndices == NULL) ? index : dwIndices[index];
1374 (DWORD *) (((char *) lpD3DDrawPrimStrideData->diffuse.lpvData) + i * lpD3DDrawPrimStrideData->diffuse.dwStride);
1376 (DWORD *) (((char *) lpD3DDrawPrimStrideData->specular.lpvData) + i * lpD3DDrawPrimStrideData->specular.dwStride);
1377 D3DVALUE *tex_coord =
1378 (D3DVALUE *) (((char *) lpD3DDrawPrimStrideData->textureCoords[0].lpvData) + i * lpD3DDrawPrimStrideData->textureCoords[0].dwStride);
1379 D3DVALUE *position =
1380 (D3DVALUE *) (((char *) lpD3DDrawPrimStrideData->position.lpvData) + i * lpD3DDrawPrimStrideData->position.dwStride);
1382 handle_diffuse_and_specular(&(This->state_block), glThis->fog_table, color_d, color_s, TRUE);
1383 handle_texture(tex_coord);
1384 handle_xyzrhw(position);
1386 TRACE_(ddraw_geom)(" %f %f %f %f / %02lx %02lx %02lx %02lx - %02lx %02lx %02lx %02lx (%f %f)\n",
1387 position[0], position[1], position[2], position[3],
1388 (*color_d >> 16) & 0xFF,
1389 (*color_d >> 8) & 0xFF,
1390 (*color_d >> 0) & 0xFF,
1391 (*color_d >> 24) & 0xFF,
1392 (*color_s >> 16) & 0xFF,
1393 (*color_s >> 8) & 0xFF,
1394 (*color_s >> 0) & 0xFF,
1395 (*color_s >> 24) & 0xFF,
1396 tex_coord[0], tex_coord[1]);
1398 } else if (((d3dvtVertexType & D3DFVF_POSITION_MASK) == D3DFVF_XYZ) ||
1399 ((d3dvtVertexType & D3DFVF_POSITION_MASK) == D3DFVF_XYZRHW)) {
1400 /* This is the 'slow path' but that should support all possible vertex formats out there...
1401 Note that people should write a fast path for all vertex formats out there...
1404 int num_tex_index = ((d3dvtVertexType & D3DFVF_TEXCOUNT_MASK) >> D3DFVF_TEXCOUNT_SHIFT);
1405 static const D3DVALUE no_index[] = { 0.0, 0.0, 0.0, 0.0 };
1407 for (index = 0; index < dwIndexCount; index++) {
1408 int i = (dwIndices == NULL) ? index : dwIndices[index];
1411 if (d3dvtVertexType & D3DFVF_NORMAL) {
1413 (D3DVALUE *) (((char *) lpD3DDrawPrimStrideData->normal.lpvData) + i * lpD3DDrawPrimStrideData->normal.dwStride);
1414 handle_normal(normal);
1416 if ((d3dvtVertexType & (D3DFVF_DIFFUSE|D3DFVF_SPECULAR)) == (D3DFVF_DIFFUSE|D3DFVF_SPECULAR)) {
1418 (DWORD *) (((char *) lpD3DDrawPrimStrideData->diffuse.lpvData) + i * lpD3DDrawPrimStrideData->diffuse.dwStride);
1420 (DWORD *) (((char *) lpD3DDrawPrimStrideData->specular.lpvData) + i * lpD3DDrawPrimStrideData->specular.dwStride);
1421 handle_diffuse_and_specular(&(This->state_block), glThis->fog_table, color_d, color_s, vertex_lighted);
1423 if (d3dvtVertexType & D3DFVF_SPECULAR) {
1425 (DWORD *) (((char *) lpD3DDrawPrimStrideData->specular.lpvData) + i * lpD3DDrawPrimStrideData->specular.dwStride);
1426 handle_specular(&(This->state_block), color_s, vertex_lighted);
1427 } else if (d3dvtVertexType & D3DFVF_DIFFUSE) {
1429 (DWORD *) (((char *) lpD3DDrawPrimStrideData->diffuse.lpvData) + i * lpD3DDrawPrimStrideData->diffuse.dwStride);
1430 handle_diffuse(&(This->state_block), color_d, vertex_lighted);
1434 for (tex_stage = 0; tex_stage < num_active_stages; tex_stage++) {
1435 int tex_index = This->state_block.texture_stage_state[tex_stage][D3DTSS_TEXCOORDINDEX - 1] & 0x0000FFFF;
1436 if (tex_index >= num_tex_index) {
1437 handle_textures((D3DVALUE *) no_index, tex_stage);
1439 D3DVALUE *tex_coord =
1440 (D3DVALUE *) (((char *) lpD3DDrawPrimStrideData->textureCoords[tex_index].lpvData) +
1441 i * lpD3DDrawPrimStrideData->textureCoords[tex_index].dwStride);
1442 handle_textures(tex_coord, tex_stage);
1446 if ((d3dvtVertexType & D3DFVF_POSITION_MASK) == D3DFVF_XYZ) {
1447 D3DVALUE *position =
1448 (D3DVALUE *) (((char *) lpD3DDrawPrimStrideData->position.lpvData) + i * lpD3DDrawPrimStrideData->position.dwStride);
1449 handle_xyz(position);
1450 } else if ((d3dvtVertexType & D3DFVF_POSITION_MASK) == D3DFVF_XYZRHW) {
1451 D3DVALUE *position =
1452 (D3DVALUE *) (((char *) lpD3DDrawPrimStrideData->position.lpvData) + i * lpD3DDrawPrimStrideData->position.dwStride);
1453 handle_xyzrhw(position);
1456 if (TRACE_ON(ddraw_geom)) {
1459 if ((d3dvtVertexType & D3DFVF_POSITION_MASK) == D3DFVF_XYZ) {
1460 D3DVALUE *position =
1461 (D3DVALUE *) (((char *) lpD3DDrawPrimStrideData->position.lpvData) + i * lpD3DDrawPrimStrideData->position.dwStride);
1462 TRACE_(ddraw_geom)(" %f %f %f", position[0], position[1], position[2]);
1463 } else if ((d3dvtVertexType & D3DFVF_POSITION_MASK) == D3DFVF_XYZRHW) {
1464 D3DVALUE *position =
1465 (D3DVALUE *) (((char *) lpD3DDrawPrimStrideData->position.lpvData) + i * lpD3DDrawPrimStrideData->position.dwStride);
1466 TRACE_(ddraw_geom)(" %f %f %f %f", position[0], position[1], position[2], position[3]);
1468 if (d3dvtVertexType & D3DFVF_NORMAL) {
1470 (D3DVALUE *) (((char *) lpD3DDrawPrimStrideData->normal.lpvData) + i * lpD3DDrawPrimStrideData->normal.dwStride);
1471 TRACE_(ddraw_geom)(" / %f %f %f", normal[0], normal[1], normal[2]);
1473 if (d3dvtVertexType & D3DFVF_DIFFUSE) {
1475 (DWORD *) (((char *) lpD3DDrawPrimStrideData->diffuse.lpvData) + i * lpD3DDrawPrimStrideData->diffuse.dwStride);
1476 TRACE_(ddraw_geom)(" / %02lx %02lx %02lx %02lx",
1477 (*color_d >> 16) & 0xFF,
1478 (*color_d >> 8) & 0xFF,
1479 (*color_d >> 0) & 0xFF,
1480 (*color_d >> 24) & 0xFF);
1482 if (d3dvtVertexType & D3DFVF_SPECULAR) {
1484 (DWORD *) (((char *) lpD3DDrawPrimStrideData->specular.lpvData) + i * lpD3DDrawPrimStrideData->specular.dwStride);
1485 TRACE_(ddraw_geom)(" / %02lx %02lx %02lx %02lx",
1486 (*color_s >> 16) & 0xFF,
1487 (*color_s >> 8) & 0xFF,
1488 (*color_s >> 0) & 0xFF,
1489 (*color_s >> 24) & 0xFF);
1491 for (tex_index = 0; tex_index < ((d3dvtVertexType & D3DFVF_TEXCOUNT_MASK) >> D3DFVF_TEXCOUNT_SHIFT); tex_index++) {
1492 D3DVALUE *tex_coord =
1493 (D3DVALUE *) (((char *) lpD3DDrawPrimStrideData->textureCoords[tex_index].lpvData) +
1494 i * lpD3DDrawPrimStrideData->textureCoords[tex_index].dwStride);
1495 TRACE_(ddraw_geom)(" / %f %f", tex_coord[0], tex_coord[1]);
1497 TRACE_(ddraw_geom)("\n");
1501 ERR(" matrix weighting not handled yet....\n");
1506 /* Whatever the case, disable the color material stuff */
1507 glDisable(GL_COLOR_MATERIAL);
1512 LeaveCriticalSection(&(This->crit));
1516 GL_IDirect3DDeviceImpl_7_3T_DrawPrimitive(LPDIRECT3DDEVICE7 iface,
1517 D3DPRIMITIVETYPE d3dptPrimitiveType,
1518 DWORD d3dvtVertexType,
1520 DWORD dwVertexCount,
1523 ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice7, iface);
1524 D3DDRAWPRIMITIVESTRIDEDDATA strided;
1526 TRACE("(%p/%p)->(%08x,%08lx,%p,%08lx,%08lx)\n", This, iface, d3dptPrimitiveType, d3dvtVertexType, lpvVertices, dwVertexCount, dwFlags);
1527 if (TRACE_ON(ddraw)) {
1528 TRACE(" - flags : "); dump_DPFLAGS(dwFlags);
1531 convert_FVF_to_strided_data(d3dvtVertexType, lpvVertices, &strided, 0);
1532 draw_primitive_strided(This, d3dptPrimitiveType, d3dvtVertexType, &strided, dwVertexCount, NULL, dwVertexCount, dwFlags);
1538 GL_IDirect3DDeviceImpl_7_3T_DrawIndexedPrimitive(LPDIRECT3DDEVICE7 iface,
1539 D3DPRIMITIVETYPE d3dptPrimitiveType,
1540 DWORD d3dvtVertexType,
1542 DWORD dwVertexCount,
1547 ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice7, iface);
1548 D3DDRAWPRIMITIVESTRIDEDDATA strided;
1550 TRACE("(%p/%p)->(%08x,%08lx,%p,%08lx,%p,%08lx,%08lx)\n", This, iface, d3dptPrimitiveType, d3dvtVertexType, lpvVertices, dwVertexCount, dwIndices, dwIndexCount, dwFlags);
1551 if (TRACE_ON(ddraw)) {
1552 TRACE(" - flags : "); dump_DPFLAGS(dwFlags);
1555 convert_FVF_to_strided_data(d3dvtVertexType, lpvVertices, &strided, 0);
1556 draw_primitive_strided(This, d3dptPrimitiveType, d3dvtVertexType, &strided, dwVertexCount, dwIndices, dwIndexCount, dwFlags);
1562 GL_IDirect3DDeviceImpl_7_3T_DrawPrimitiveStrided(LPDIRECT3DDEVICE7 iface,
1563 D3DPRIMITIVETYPE d3dptPrimitiveType,
1565 LPD3DDRAWPRIMITIVESTRIDEDDATA lpD3DDrawPrimStrideData,
1566 DWORD dwVertexCount,
1569 ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice7, iface);
1571 TRACE("(%p/%p)->(%08x,%08lx,%p,%08lx,%08lx)\n", This, iface, d3dptPrimitiveType, dwVertexType, lpD3DDrawPrimStrideData, dwVertexCount, dwFlags);
1572 if (TRACE_ON(ddraw)) {
1573 TRACE(" - flags : "); dump_DPFLAGS(dwFlags);
1575 draw_primitive_strided(This, d3dptPrimitiveType, dwVertexType, lpD3DDrawPrimStrideData, dwVertexCount, NULL, dwVertexCount, dwFlags);
1581 GL_IDirect3DDeviceImpl_7_3T_DrawIndexedPrimitiveStrided(LPDIRECT3DDEVICE7 iface,
1582 D3DPRIMITIVETYPE d3dptPrimitiveType,
1584 LPD3DDRAWPRIMITIVESTRIDEDDATA lpD3DDrawPrimStrideData,
1585 DWORD dwVertexCount,
1590 ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice7, iface);
1592 TRACE("(%p/%p)->(%08x,%08lx,%p,%08lx,%p,%08lx,%08lx)\n", This, iface, d3dptPrimitiveType, dwVertexType, lpD3DDrawPrimStrideData, dwVertexCount, lpIndex, dwIndexCount, dwFlags);
1593 if (TRACE_ON(ddraw)) {
1594 TRACE(" - flags : "); dump_DPFLAGS(dwFlags);
1597 draw_primitive_strided(This, d3dptPrimitiveType, dwVertexType, lpD3DDrawPrimStrideData, dwVertexCount, lpIndex, dwIndexCount, dwFlags);
1603 GL_IDirect3DDeviceImpl_7_3T_DrawPrimitiveVB(LPDIRECT3DDEVICE7 iface,
1604 D3DPRIMITIVETYPE d3dptPrimitiveType,
1605 LPDIRECT3DVERTEXBUFFER7 lpD3DVertexBuf,
1606 DWORD dwStartVertex,
1607 DWORD dwNumVertices,
1610 ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice7, iface);
1611 IDirect3DVertexBufferImpl *vb_impl = ICOM_OBJECT(IDirect3DVertexBufferImpl, IDirect3DVertexBuffer7, lpD3DVertexBuf);
1612 D3DDRAWPRIMITIVESTRIDEDDATA strided;
1614 TRACE("(%p/%p)->(%08x,%p,%08lx,%08lx,%08lx)\n", This, iface, d3dptPrimitiveType, lpD3DVertexBuf, dwStartVertex, dwNumVertices, dwFlags);
1615 if (TRACE_ON(ddraw)) {
1616 TRACE(" - flags : "); dump_DPFLAGS(dwFlags);
1619 if (vb_impl->processed == TRUE) {
1620 IDirect3DVertexBufferGLImpl *vb_glimp = (IDirect3DVertexBufferGLImpl *) vb_impl;
1621 IDirect3DDeviceGLImpl *glThis = (IDirect3DDeviceGLImpl *) This;
1623 glThis->transform_state = GL_TRANSFORM_VERTEXBUFFER;
1624 This->set_matrices(This, VIEWMAT_CHANGED|WORLDMAT_CHANGED|PROJMAT_CHANGED,
1625 &(vb_glimp->world_mat), &(vb_glimp->view_mat), &(vb_glimp->proj_mat));
1627 convert_FVF_to_strided_data(vb_glimp->dwVertexTypeDesc, vb_glimp->vertices, &strided, dwStartVertex);
1628 draw_primitive_strided(This, d3dptPrimitiveType, vb_glimp->dwVertexTypeDesc, &strided, dwNumVertices, NULL, dwNumVertices, dwFlags);
1631 convert_FVF_to_strided_data(vb_impl->desc.dwFVF, vb_impl->vertices, &strided, dwStartVertex);
1632 draw_primitive_strided(This, d3dptPrimitiveType, vb_impl->desc.dwFVF, &strided, dwNumVertices, NULL, dwNumVertices, dwFlags);
1639 GL_IDirect3DDeviceImpl_7_3T_DrawIndexedPrimitiveVB(LPDIRECT3DDEVICE7 iface,
1640 D3DPRIMITIVETYPE d3dptPrimitiveType,
1641 LPDIRECT3DVERTEXBUFFER7 lpD3DVertexBuf,
1642 DWORD dwStartVertex,
1643 DWORD dwNumVertices,
1648 ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice7, iface);
1649 IDirect3DVertexBufferImpl *vb_impl = ICOM_OBJECT(IDirect3DVertexBufferImpl, IDirect3DVertexBuffer7, lpD3DVertexBuf);
1650 D3DDRAWPRIMITIVESTRIDEDDATA strided;
1652 TRACE("(%p/%p)->(%08x,%p,%08lx,%08lx,%p,%08lx,%08lx)\n", This, iface, d3dptPrimitiveType, lpD3DVertexBuf, dwStartVertex, dwNumVertices, lpwIndices, dwIndexCount, dwFlags);
1653 if (TRACE_ON(ddraw)) {
1654 TRACE(" - flags : "); dump_DPFLAGS(dwFlags);
1657 if (vb_impl->processed == TRUE) {
1658 IDirect3DVertexBufferGLImpl *vb_glimp = (IDirect3DVertexBufferGLImpl *) vb_impl;
1659 IDirect3DDeviceGLImpl *glThis = (IDirect3DDeviceGLImpl *) This;
1661 glThis->transform_state = GL_TRANSFORM_VERTEXBUFFER;
1662 This->set_matrices(This, VIEWMAT_CHANGED|WORLDMAT_CHANGED|PROJMAT_CHANGED,
1663 &(vb_glimp->world_mat), &(vb_glimp->view_mat), &(vb_glimp->proj_mat));
1665 convert_FVF_to_strided_data(vb_glimp->dwVertexTypeDesc, vb_glimp->vertices, &strided, dwStartVertex);
1666 draw_primitive_strided(This, d3dptPrimitiveType, vb_glimp->dwVertexTypeDesc, &strided, dwNumVertices, lpwIndices, dwIndexCount, dwFlags);
1669 convert_FVF_to_strided_data(vb_impl->desc.dwFVF, vb_impl->vertices, &strided, dwStartVertex);
1670 draw_primitive_strided(This, d3dptPrimitiveType, vb_impl->desc.dwFVF, &strided, dwNumVertices, lpwIndices, dwIndexCount, dwFlags);
1676 /* We need a static function for that to handle the 'special' case of 'SELECT_ARG2' */
1678 handle_color_alpha_args(IDirect3DDeviceImpl *This, DWORD dwStage, D3DTEXTURESTAGESTATETYPE d3dTexStageStateType, DWORD dwState, D3DTEXTUREOP tex_op)
1680 BOOLEAN is_complement = FALSE;
1681 BOOLEAN is_alpha_replicate = FALSE;
1682 BOOLEAN handled = TRUE;
1684 BOOLEAN is_color = ((d3dTexStageStateType == D3DTSS_COLORARG1) || (d3dTexStageStateType == D3DTSS_COLORARG2));
1688 if (d3dTexStageStateType == D3DTSS_COLORARG1) num = 0;
1689 else if (d3dTexStageStateType == D3DTSS_COLORARG2) num = 1;
1694 if (tex_op == D3DTOP_SELECTARG2) {
1698 if (d3dTexStageStateType == D3DTSS_ALPHAARG1) num = 0;
1699 else if (d3dTexStageStateType == D3DTSS_ALPHAARG2) num = 1;
1704 if (tex_op == D3DTOP_SELECTARG2) {
1709 if (dwState & D3DTA_COMPLEMENT) {
1710 is_complement = TRUE;
1712 if (dwState & D3DTA_ALPHAREPLICATE) {
1713 is_alpha_replicate = TRUE;
1715 dwState &= D3DTA_SELECTMASK;
1716 if ((dwStage == 0) && (dwState == D3DTA_CURRENT)) {
1717 dwState = D3DTA_DIFFUSE;
1721 case D3DTA_CURRENT: src = GL_PREVIOUS_EXT; break;
1722 case D3DTA_DIFFUSE: src = GL_PRIMARY_COLOR_EXT; break;
1723 case D3DTA_TEXTURE: src = GL_TEXTURE; break;
1724 case D3DTA_TFACTOR: {
1725 /* Get the constant value from the current rendering state */
1727 DWORD col = This->state_block.render_state[D3DRENDERSTATE_TEXTUREFACTOR - 1];
1729 color[0] = ((col >> 16) & 0xFF) / 255.0f;
1730 color[1] = ((col >> 8) & 0xFF) / 255.0f;
1731 color[2] = ((col >> 0) & 0xFF) / 255.0f;
1732 color[3] = ((col >> 24) & 0xFF) / 255.0f;
1733 glTexEnvfv(GL_TEXTURE_ENV, GL_TEXTURE_ENV_COLOR, color);
1735 src = GL_CONSTANT_EXT;
1737 default: src = GL_TEXTURE; handled = FALSE; break;
1741 glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_RGB_EXT + num, src);
1742 if (is_alpha_replicate) {
1743 glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND0_RGB_EXT + num, is_complement ? GL_ONE_MINUS_SRC_ALPHA : GL_SRC_ALPHA);
1745 glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND0_RGB_EXT + num, is_complement ? GL_ONE_MINUS_SRC_COLOR : GL_SRC_COLOR);
1748 glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_ALPHA_EXT + num, src);
1749 glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND0_ALPHA_EXT + num, is_complement ? GL_ONE_MINUS_SRC_ALPHA : GL_SRC_ALPHA);
1756 GL_IDirect3DDeviceImpl_7_3T_SetTextureStageState(LPDIRECT3DDEVICE7 iface,
1758 D3DTEXTURESTAGESTATETYPE d3dTexStageStateType,
1761 ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice7, iface);
1762 IDirect3DDeviceGLImpl *glThis = (IDirect3DDeviceGLImpl *) This;
1767 TRACE("(%p/%p)->(%08lx,%08x,%08lx)\n", This, iface, dwStage, d3dTexStageStateType, dwState);
1769 if (((GL_extensions.max_texture_units == 0) && (dwStage > 0)) ||
1770 ((GL_extensions.max_texture_units != 0) && (dwStage >= GL_extensions.max_texture_units))) {
1774 unit = GL_TEXTURE0_WINE + dwStage;
1775 if (unit != glThis->current_active_tex_unit) {
1776 GL_extensions.glActiveTexture(unit);
1777 glThis->current_active_tex_unit = unit;
1780 switch (d3dTexStageStateType) {
1781 #define GEN_CASE(a) case a: type = #a; break
1782 GEN_CASE(D3DTSS_COLOROP);
1783 GEN_CASE(D3DTSS_COLORARG1);
1784 GEN_CASE(D3DTSS_COLORARG2);
1785 GEN_CASE(D3DTSS_ALPHAOP);
1786 GEN_CASE(D3DTSS_ALPHAARG1);
1787 GEN_CASE(D3DTSS_ALPHAARG2);
1788 GEN_CASE(D3DTSS_BUMPENVMAT00);
1789 GEN_CASE(D3DTSS_BUMPENVMAT01);
1790 GEN_CASE(D3DTSS_BUMPENVMAT10);
1791 GEN_CASE(D3DTSS_BUMPENVMAT11);
1792 GEN_CASE(D3DTSS_TEXCOORDINDEX);
1793 GEN_CASE(D3DTSS_ADDRESS);
1794 GEN_CASE(D3DTSS_ADDRESSU);
1795 GEN_CASE(D3DTSS_ADDRESSV);
1796 GEN_CASE(D3DTSS_BORDERCOLOR);
1797 GEN_CASE(D3DTSS_MAGFILTER);
1798 GEN_CASE(D3DTSS_MINFILTER);
1799 GEN_CASE(D3DTSS_MIPFILTER);
1800 GEN_CASE(D3DTSS_MIPMAPLODBIAS);
1801 GEN_CASE(D3DTSS_MAXMIPLEVEL);
1802 GEN_CASE(D3DTSS_MAXANISOTROPY);
1803 GEN_CASE(D3DTSS_BUMPENVLSCALE);
1804 GEN_CASE(D3DTSS_BUMPENVLOFFSET);
1805 GEN_CASE(D3DTSS_TEXTURETRANSFORMFLAGS);
1807 default: type = "UNKNOWN";
1810 /* Store the values in the state array */
1811 prev_state = This->state_block.texture_stage_state[dwStage][d3dTexStageStateType - 1];
1812 This->state_block.texture_stage_state[dwStage][d3dTexStageStateType - 1] = dwState;
1813 /* Some special cases when one state modifies more than one... */
1814 if (d3dTexStageStateType == D3DTSS_ADDRESS) {
1815 This->state_block.texture_stage_state[dwStage][D3DTSS_ADDRESSU - 1] = dwState;
1816 This->state_block.texture_stage_state[dwStage][D3DTSS_ADDRESSV - 1] = dwState;
1821 switch (d3dTexStageStateType) {
1822 case D3DTSS_MINFILTER:
1823 case D3DTSS_MIPFILTER:
1824 if (TRACE_ON(ddraw)) {
1825 if (d3dTexStageStateType == D3DTSS_MINFILTER) {
1826 switch ((D3DTEXTUREMINFILTER) dwState) {
1827 case D3DTFN_POINT: TRACE(" Stage type is : D3DTSS_MINFILTER => D3DTFN_POINT\n"); break;
1828 case D3DTFN_LINEAR: TRACE(" Stage type is : D3DTSS_MINFILTER => D3DTFN_LINEAR\n"); break;
1829 default: FIXME(" Unhandled stage type : D3DTSS_MINFILTER => %08lx\n", dwState); break;
1832 switch ((D3DTEXTUREMIPFILTER) dwState) {
1833 case D3DTFP_NONE: TRACE(" Stage type is : D3DTSS_MIPFILTER => D3DTFP_NONE\n"); break;
1834 case D3DTFP_POINT: TRACE(" Stage type is : D3DTSS_MIPFILTER => D3DTFP_POINT\n"); break;
1835 case D3DTFP_LINEAR: TRACE(" Stage type is : D3DTSS_MIPFILTER => D3DTFP_LINEAR\n"); break;
1836 default: FIXME(" Unhandled stage type : D3DTSS_MIPFILTER => %08lx\n", dwState); break;
1842 case D3DTSS_MAGFILTER:
1843 if (TRACE_ON(ddraw)) {
1844 switch ((D3DTEXTUREMAGFILTER) dwState) {
1845 case D3DTFG_POINT: TRACE(" Stage type is : D3DTSS_MAGFILTER => D3DTFG_POINT\n"); break;
1846 case D3DTFG_LINEAR: TRACE(" Stage type is : D3DTSS_MAGFILTER => D3DTFG_LINEAR\n"); break;
1847 default: FIXME(" Unhandled stage type : D3DTSS_MAGFILTER => %08lx\n", dwState); break;
1852 case D3DTSS_ADDRESS:
1853 case D3DTSS_ADDRESSU:
1854 case D3DTSS_ADDRESSV: {
1855 switch ((D3DTEXTUREADDRESS) dwState) {
1856 case D3DTADDRESS_WRAP: TRACE(" Stage type is : %s => D3DTADDRESS_WRAP\n", type); break;
1857 case D3DTADDRESS_CLAMP: TRACE(" Stage type is : %s => D3DTADDRESS_CLAMP\n", type); break;
1858 case D3DTADDRESS_BORDER: TRACE(" Stage type is : %s => D3DTADDRESS_BORDER\n", type); break;
1859 case D3DTADDRESS_MIRROR:
1860 if (GL_extensions.mirrored_repeat == TRUE) {
1861 TRACE(" Stage type is : %s => D3DTADDRESS_MIRROR\n", type);
1863 FIXME(" Stage type is : %s => D3DTADDRESS_MIRROR - not supported by GL !\n", type);
1866 default: FIXME(" Unhandled stage type : %s => %08lx\n", type, dwState); break;
1870 case D3DTSS_ALPHAOP:
1871 case D3DTSS_COLOROP: {
1873 GLenum parm = (d3dTexStageStateType == D3DTSS_ALPHAOP) ? GL_COMBINE_ALPHA_EXT : GL_COMBINE_RGB_EXT;
1878 #define GEN_CASE(a) case a: value = #a; break
1879 GEN_CASE(D3DTOP_DISABLE);
1880 GEN_CASE(D3DTOP_SELECTARG1);
1881 GEN_CASE(D3DTOP_SELECTARG2);
1882 GEN_CASE(D3DTOP_MODULATE);
1883 GEN_CASE(D3DTOP_MODULATE2X);
1884 GEN_CASE(D3DTOP_MODULATE4X);
1885 GEN_CASE(D3DTOP_ADD);
1886 GEN_CASE(D3DTOP_ADDSIGNED);
1887 GEN_CASE(D3DTOP_ADDSIGNED2X);
1888 GEN_CASE(D3DTOP_SUBTRACT);
1889 GEN_CASE(D3DTOP_ADDSMOOTH);
1890 GEN_CASE(D3DTOP_BLENDDIFFUSEALPHA);
1891 GEN_CASE(D3DTOP_BLENDTEXTUREALPHA);
1892 GEN_CASE(D3DTOP_BLENDFACTORALPHA);
1893 GEN_CASE(D3DTOP_BLENDTEXTUREALPHAPM);
1894 GEN_CASE(D3DTOP_BLENDCURRENTALPHA);
1895 GEN_CASE(D3DTOP_PREMODULATE);
1896 GEN_CASE(D3DTOP_MODULATEALPHA_ADDCOLOR);
1897 GEN_CASE(D3DTOP_MODULATECOLOR_ADDALPHA);
1898 GEN_CASE(D3DTOP_MODULATEINVALPHA_ADDCOLOR);
1899 GEN_CASE(D3DTOP_MODULATEINVCOLOR_ADDALPHA);
1900 GEN_CASE(D3DTOP_BUMPENVMAP);
1901 GEN_CASE(D3DTOP_BUMPENVMAPLUMINANCE);
1902 GEN_CASE(D3DTOP_DOTPRODUCT3);
1903 GEN_CASE(D3DTOP_FORCE_DWORD);
1905 default: value = "UNKNOWN";
1908 if ((d3dTexStageStateType == D3DTSS_COLOROP) && (dwState == D3DTOP_DISABLE)) {
1909 glDisable(GL_TEXTURE_2D);
1910 TRACE(" disabling 2D texturing.\n");
1912 /* Re-enable texturing */
1913 if (This->current_texture[0] != NULL) {
1914 glEnable(GL_TEXTURE_2D);
1915 TRACE(" enabling 2D texturing.\n");
1918 /* Re-Enable GL_TEXTURE_ENV_MODE, GL_COMBINE_EXT */
1919 if (dwState != D3DTOP_DISABLE) {
1920 if (glThis->current_tex_env != GL_COMBINE_EXT) {
1921 glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE_EXT);
1922 glThis->current_tex_env = GL_COMBINE_EXT;
1926 /* Now set up the operand correctly */
1928 case D3DTOP_DISABLE:
1929 /* Contrary to the docs, alpha can be disabled when colorop is enabled
1930 and it works, so ignore this op */
1931 TRACE(" Note : disable ALPHAOP but COLOROP enabled!\n");
1934 case D3DTOP_SELECTARG1:
1935 case D3DTOP_SELECTARG2:
1936 glTexEnvi(GL_TEXTURE_ENV, parm, GL_REPLACE);
1939 case D3DTOP_MODULATE4X:
1940 scale = scale * 2; /* Drop through */
1941 case D3DTOP_MODULATE2X:
1942 scale = scale * 2; /* Drop through */
1943 case D3DTOP_MODULATE:
1944 glTexEnvi(GL_TEXTURE_ENV, parm, GL_MODULATE);
1948 glTexEnvi(GL_TEXTURE_ENV, parm, GL_ADD);
1951 case D3DTOP_ADDSIGNED2X:
1952 scale = scale * 2; /* Drop through */
1953 case D3DTOP_ADDSIGNED:
1954 glTexEnvi(GL_TEXTURE_ENV, parm, GL_ADD_SIGNED_EXT);
1957 /* For the four blending modes, use the Arg2 parameter */
1958 case D3DTOP_BLENDDIFFUSEALPHA:
1959 case D3DTOP_BLENDTEXTUREALPHA:
1960 case D3DTOP_BLENDFACTORALPHA:
1961 case D3DTOP_BLENDCURRENTALPHA: {
1962 GLenum src = GL_PRIMARY_COLOR_EXT; /* Just to prevent a compiler warning.. */
1965 case D3DTOP_BLENDDIFFUSEALPHA: src = GL_PRIMARY_COLOR_EXT;
1966 case D3DTOP_BLENDTEXTUREALPHA: src = GL_TEXTURE;
1967 case D3DTOP_BLENDFACTORALPHA: src = GL_CONSTANT_EXT;
1968 case D3DTOP_BLENDCURRENTALPHA: src = GL_PREVIOUS_EXT;
1971 glTexEnvi(GL_TEXTURE_ENV, parm, GL_INTERPOLATE_EXT);
1972 glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE2_RGB_EXT, src);
1973 glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND2_RGB_EXT, GL_SRC_ALPHA);
1974 glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE2_ALPHA_EXT, src);
1975 glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND2_ALPHA_EXT, GL_SRC_ALPHA);
1984 if (((prev_state == D3DTOP_SELECTARG2) && (dwState != D3DTOP_SELECTARG2)) ||
1985 ((dwState == D3DTOP_SELECTARG2) && (prev_state != D3DTOP_SELECTARG2))) {
1986 /* Switch the arguments if needed... */
1987 if (d3dTexStageStateType == D3DTSS_COLOROP) {
1988 handle_color_alpha_args(This, dwStage, D3DTSS_COLORARG1,
1989 This->state_block.texture_stage_state[dwStage][D3DTSS_COLORARG1 - 1],
1991 handle_color_alpha_args(This, dwStage, D3DTSS_COLORARG2,
1992 This->state_block.texture_stage_state[dwStage][D3DTSS_COLORARG2 - 1],
1995 handle_color_alpha_args(This, dwStage, D3DTSS_ALPHAARG1,
1996 This->state_block.texture_stage_state[dwStage][D3DTSS_ALPHAARG1 - 1],
1998 handle_color_alpha_args(This, dwStage, D3DTSS_ALPHAARG2,
1999 This->state_block.texture_stage_state[dwStage][D3DTSS_ALPHAARG2 - 1],
2005 if (d3dTexStageStateType == D3DTSS_ALPHAOP) {
2006 glTexEnvi(GL_TEXTURE_ENV, GL_ALPHA_SCALE, scale);
2008 glTexEnvi(GL_TEXTURE_ENV, GL_RGB_SCALE_EXT, scale);
2010 TRACE(" Stage type is : %s => %s\n", type, value);
2012 FIXME(" Unhandled stage type is : %s => %s\n", type, value);
2016 case D3DTSS_COLORARG1:
2017 case D3DTSS_COLORARG2:
2018 case D3DTSS_ALPHAARG1:
2019 case D3DTSS_ALPHAARG2: {
2020 const char *value, *value_comp = "", *value_alpha = "";
2022 D3DTEXTUREOP tex_op;
2024 switch (dwState & D3DTA_SELECTMASK) {
2025 #define GEN_CASE(a) case a: value = #a; break
2026 GEN_CASE(D3DTA_DIFFUSE);
2027 GEN_CASE(D3DTA_CURRENT);
2028 GEN_CASE(D3DTA_TEXTURE);
2029 GEN_CASE(D3DTA_TFACTOR);
2030 GEN_CASE(D3DTA_SPECULAR);
2032 default: value = "UNKNOWN";
2034 if (dwState & D3DTA_COMPLEMENT) {
2035 value_comp = " | D3DTA_COMPLEMENT";
2037 if (dwState & D3DTA_ALPHAREPLICATE) {
2038 value_alpha = " | D3DTA_ALPHAREPLICATE";
2041 if ((d3dTexStageStateType == D3DTSS_COLORARG1) || (d3dTexStageStateType == D3DTSS_COLORARG2)) {
2042 tex_op = This->state_block.texture_stage_state[dwStage][D3DTSS_COLOROP - 1];
2044 tex_op = This->state_block.texture_stage_state[dwStage][D3DTSS_ALPHAOP - 1];
2047 handled = handle_color_alpha_args(This, dwStage, d3dTexStageStateType, dwState, tex_op);
2050 TRACE(" Stage type : %s => %s%s%s\n", type, value, value_comp, value_alpha);
2052 FIXME(" Unhandled stage type : %s => %s%s%s\n", type, value, value_comp, value_alpha);
2056 case D3DTSS_MIPMAPLODBIAS: {
2057 D3DVALUE value = *((D3DVALUE *) &dwState);
2058 BOOLEAN handled = TRUE;
2060 if ((value != 0.0) && (GL_extensions.mipmap_lodbias == FALSE))
2064 TRACE(" Stage type : D3DTSS_MIPMAPLODBIAS => %f\n", value);
2065 glTexEnvf(GL_TEXTURE_FILTER_CONTROL_WINE, GL_TEXTURE_LOD_BIAS_WINE, value);
2067 FIXME(" Unhandled stage type : D3DTSS_MIPMAPLODBIAS => %f\n", value);
2071 case D3DTSS_MAXMIPLEVEL:
2072 TRACE(" Stage type : D3DTSS_MAXMIPLEVEL => %ld\n", dwState);
2075 case D3DTSS_BORDERCOLOR:
2076 TRACE(" Stage type : D3DTSS_BORDERCOLOR => %02lx %02lx %02lx %02lx (RGBA)\n",
2077 ((dwState >> 16) & 0xFF),
2078 ((dwState >> 8) & 0xFF),
2079 ((dwState >> 0) & 0xFF),
2080 ((dwState >> 24) & 0xFF));
2083 case D3DTSS_TEXCOORDINDEX: {
2084 BOOLEAN handled = TRUE;
2087 switch (dwState & 0xFFFF0000) {
2088 #define GEN_CASE(a) case a: value = #a; break
2089 GEN_CASE(D3DTSS_TCI_PASSTHRU);
2090 GEN_CASE(D3DTSS_TCI_CAMERASPACENORMAL);
2091 GEN_CASE(D3DTSS_TCI_CAMERASPACEPOSITION);
2092 GEN_CASE(D3DTSS_TCI_CAMERASPACEREFLECTIONVECTOR);
2094 default: value = "UNKNOWN";
2096 if ((dwState & 0xFFFF0000) != D3DTSS_TCI_PASSTHRU)
2100 TRACE(" Stage type : D3DTSS_TEXCOORDINDEX => %ld | %s\n", dwState & 0x0000FFFF, value);
2102 FIXME(" Unhandled stage type : D3DTSS_TEXCOORDINDEX => %ld | %s\n", dwState & 0x0000FFFF, value);
2106 case D3DTSS_TEXTURETRANSFORMFLAGS: {
2107 const char *projected = "", *value;
2108 BOOLEAN handled = TRUE;
2109 switch (dwState & 0xFF) {
2110 #define GEN_CASE(a) case a: value = #a; break
2111 GEN_CASE(D3DTTFF_DISABLE);
2112 GEN_CASE(D3DTTFF_COUNT1);
2113 GEN_CASE(D3DTTFF_COUNT2);
2114 GEN_CASE(D3DTTFF_COUNT3);
2115 GEN_CASE(D3DTTFF_COUNT4);
2117 default: value = "UNKNOWN";
2119 if (dwState & D3DTTFF_PROJECTED) {
2120 projected = " | D3DTTFF_PROJECTED";
2124 if ((dwState & 0xFF) != D3DTTFF_DISABLE) {
2125 This->matrices_updated(This, TEXMAT0_CHANGED << dwStage);
2128 if (handled == TRUE) {
2129 TRACE(" Stage type : D3DTSS_TEXTURETRANSFORMFLAGS => %s%s\n", value, projected);
2131 FIXME(" Unhandled stage type : D3DTSS_TEXTURETRANSFORMFLAGS => %s%s\n", value, projected);
2136 FIXME(" Unhandled stage type : %s => %08lx\n", type, dwState);
2146 draw_primitive_handle_textures(IDirect3DDeviceImpl *This)
2148 IDirect3DDeviceGLImpl *glThis = (IDirect3DDeviceGLImpl *) This;
2150 BOOLEAN enable_colorkey = FALSE;
2152 for (stage = 0; stage < MAX_TEXTURES; stage++) {
2153 IDirectDrawSurfaceImpl *surf_ptr = This->current_texture[stage];
2156 /* First check if we need to bind any other texture for this stage */
2157 if (This->current_texture[stage] != glThis->current_bound_texture[stage]) {
2158 if (This->current_texture[stage] == NULL) {
2159 TRACE(" disabling 2D texturing for stage %ld.\n", stage);
2161 unit = GL_TEXTURE0_WINE + stage;
2162 if (unit != glThis->current_active_tex_unit) {
2163 GL_extensions.glActiveTexture(unit);
2164 glThis->current_active_tex_unit = unit;
2166 glBindTexture(GL_TEXTURE_2D, 0);
2169 glDisable(GL_TEXTURE_2D);
2172 GLenum tex_name = ((IDirect3DTextureGLImpl *) surf_ptr->tex_private)->tex_name;
2174 unit = GL_TEXTURE0_WINE + stage;
2175 if (unit != glThis->current_active_tex_unit) {
2176 GL_extensions.glActiveTexture(unit);
2177 glThis->current_active_tex_unit = unit;
2180 if (glThis->current_bound_texture[stage] == NULL) {
2181 if (This->state_block.texture_stage_state[stage][D3DTSS_COLOROP - 1] != D3DTOP_DISABLE) {
2182 TRACE(" enabling 2D texturing and");
2183 glEnable(GL_TEXTURE_2D);
2186 TRACE(" activating OpenGL texture id %d for stage %ld.\n", tex_name, stage);
2187 glBindTexture(GL_TEXTURE_2D, tex_name);
2190 glThis->current_bound_texture[stage] = This->current_texture[stage];
2192 if (glThis->current_bound_texture[stage] == NULL) {
2193 TRACE(" displaying without texturing activated for stage %ld.\n", stage);
2195 TRACE(" using already bound texture id %d for stage %ld.\n",
2196 ((IDirect3DTextureGLImpl *) (glThis->current_bound_texture[stage])->tex_private)->tex_name, stage);
2200 /* If no texure valid for this stage, go out of the loop */
2201 if (This->current_texture[stage] == NULL) break;
2203 /* Then check if we need to flush this texture to GL or not (ie did it change) ?.
2204 This will also update the various texture parameters if needed.
2206 gltex_upload_texture(surf_ptr, This, stage);
2208 /* And finally check for color-keying (only on first stage) */
2209 if (This->current_texture[stage]->surface_desc.dwFlags & DDSD_CKSRCBLT) {
2211 enable_colorkey = TRUE;
2213 static BOOL warn = FALSE;
2214 if (warn == FALSE) {
2216 WARN(" Surface has color keying on stage different from 0 (%ld) !", stage);
2221 enable_colorkey = FALSE;
2226 /* Apparently, whatever the state of BLEND, color keying is always activated for 'old' D3D versions */
2227 if (((This->state_block.render_state[D3DRENDERSTATE_COLORKEYENABLE - 1]) ||
2228 (glThis->version == 1)) &&
2229 (enable_colorkey)) {
2230 TRACE(" colorkey activated.\n");
2232 if (glThis->alpha_test == FALSE) {
2233 glEnable(GL_ALPHA_TEST);
2234 glThis->alpha_test = TRUE;
2236 if ((glThis->current_alpha_test_func != GL_NOTEQUAL) || (glThis->current_alpha_test_ref != 0.0)) {
2237 if (This->state_block.render_state[D3DRENDERSTATE_ALPHATESTENABLE - 1] == TRUE) {
2238 static BOOL warn = FALSE;
2239 if (warn == FALSE) {
2241 WARN(" Overriding application-given alpha test values - some graphical glitches may appear !\n");
2244 glThis->current_alpha_test_func = GL_NOTEQUAL;
2245 glThis->current_alpha_test_ref = 0.0;
2246 glAlphaFunc(GL_NOTEQUAL, 0.0);
2248 /* Some sanity checks should be added here if a game mixes alphatest + color keying...
2249 Only one has been found for now, and the ALPHAFUNC is 'Always' so it works :-) */
2251 if (This->state_block.render_state[D3DRENDERSTATE_ALPHATESTENABLE - 1] == FALSE) {
2252 glDisable(GL_ALPHA_TEST);
2253 glThis->alpha_test = FALSE;
2255 /* Maybe we should restore here the application-given alpha test states ? */
2262 GL_IDirect3DDeviceImpl_7_3T_SetTexture(LPDIRECT3DDEVICE7 iface,
2264 LPDIRECTDRAWSURFACE7 lpTexture2)
2266 ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice7, iface);
2268 TRACE("(%p/%p)->(%08lx,%p)\n", This, iface, dwStage, lpTexture2);
2270 if (((GL_extensions.max_texture_units == 0) && (dwStage > 0)) ||
2271 ((GL_extensions.max_texture_units != 0) && (dwStage >= GL_extensions.max_texture_units))) {
2272 if (lpTexture2 != NULL) {
2273 WARN(" setting a texture to a non-supported texture stage !\n");
2278 if (This->current_texture[dwStage] != NULL) {
2279 IDirectDrawSurface7_Release(ICOM_INTERFACE(This->current_texture[dwStage], IDirectDrawSurface7));
2282 if (lpTexture2 == NULL) {
2283 This->current_texture[dwStage] = NULL;
2285 IDirectDrawSurfaceImpl *tex_impl = ICOM_OBJECT(IDirectDrawSurfaceImpl, IDirectDrawSurface7, lpTexture2);
2286 IDirectDrawSurface7_AddRef(ICOM_INTERFACE(tex_impl, IDirectDrawSurface7));
2287 This->current_texture[dwStage] = tex_impl;
2294 GL_IDirect3DDeviceImpl_7_GetCaps(LPDIRECT3DDEVICE7 iface,
2295 LPD3DDEVICEDESC7 lpD3DHELDevDesc)
2297 ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice7, iface);
2298 TRACE("(%p/%p)->(%p)\n", This, iface, lpD3DHELDevDesc);
2300 fill_opengl_caps_7(lpD3DHELDevDesc);
2302 TRACE(" returning caps : no dump function yet.\n");
2308 GL_IDirect3DDeviceImpl_7_SetMaterial(LPDIRECT3DDEVICE7 iface,
2309 LPD3DMATERIAL7 lpMat)
2311 ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice7, iface);
2312 TRACE("(%p/%p)->(%p)\n", This, iface, lpMat);
2314 if (TRACE_ON(ddraw)) {
2315 TRACE(" material is : \n");
2316 dump_D3DMATERIAL7(lpMat);
2319 This->current_material = *lpMat;
2322 glMaterialfv(GL_FRONT_AND_BACK,
2324 (float *) &(This->current_material.u.diffuse));
2325 glMaterialfv(GL_FRONT_AND_BACK,
2327 (float *) &(This->current_material.u1.ambient));
2328 glMaterialfv(GL_FRONT_AND_BACK,
2330 (float *) &(This->current_material.u2.specular));
2331 glMaterialfv(GL_FRONT_AND_BACK,
2333 (float *) &(This->current_material.u3.emissive));
2334 glMaterialf(GL_FRONT_AND_BACK,
2336 This->current_material.u4.power); /* Not sure about this... */
2344 GL_IDirect3DDeviceImpl_7_SetLight(LPDIRECT3DDEVICE7 iface,
2346 LPD3DLIGHT7 lpLight)
2348 ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice7, iface);
2349 IDirect3DDeviceGLImpl *glThis = (IDirect3DDeviceGLImpl *) This;
2350 TRACE("(%p/%p)->(%08lx,%p)\n", This, iface, dwLightIndex, lpLight);
2352 if (TRACE_ON(ddraw)) {
2353 TRACE(" setting light : \n");
2354 dump_D3DLIGHT7(lpLight);
2357 if (dwLightIndex >= MAX_LIGHTS) return DDERR_INVALIDPARAMS;
2358 This->set_lights |= 0x00000001 << dwLightIndex;
2359 This->light_parameters[dwLightIndex] = *lpLight;
2361 /* Some checks to print out nice warnings :-) */
2362 switch (lpLight->dltType) {
2363 case D3DLIGHT_DIRECTIONAL:
2364 case D3DLIGHT_POINT:
2365 /* These are handled properly... */
2369 if ((lpLight->dvTheta != 0.0) ||
2370 (lpLight->dvTheta != lpLight->dvPhi)) {
2371 ERR("dvTheta not fully supported yet !\n");
2376 ERR("Light type not handled yet : %08x !\n", lpLight->dltType);
2379 /* This will force the Light setting on next drawing of primitives */
2380 glThis->transform_state = GL_TRANSFORM_NONE;
2386 GL_IDirect3DDeviceImpl_7_LightEnable(LPDIRECT3DDEVICE7 iface,
2390 ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice7, iface);
2391 TRACE("(%p/%p)->(%08lx,%d)\n", This, iface, dwLightIndex, bEnable);
2393 if (dwLightIndex >= MAX_LIGHTS) return DDERR_INVALIDPARAMS;
2397 if (((0x00000001 << dwLightIndex) & This->set_lights) == 0) {
2398 /* Set the default parameters.. */
2399 TRACE(" setting default light parameters...\n");
2400 GL_IDirect3DDeviceImpl_7_SetLight(iface, dwLightIndex, &(This->light_parameters[dwLightIndex]));
2402 glEnable(GL_LIGHT0 + dwLightIndex);
2403 if ((This->active_lights & (0x00000001 << dwLightIndex)) == 0) {
2404 /* This light gets active... Need to update its parameters to GL before the next drawing */
2405 IDirect3DDeviceGLImpl *glThis = (IDirect3DDeviceGLImpl *) This;
2407 This->active_lights |= 0x00000001 << dwLightIndex;
2408 glThis->transform_state = GL_TRANSFORM_NONE;
2411 glDisable(GL_LIGHT0 + dwLightIndex);
2412 This->active_lights &= ~(0x00000001 << dwLightIndex);
2420 GL_IDirect3DDeviceImpl_7_SetClipPlane(LPDIRECT3DDEVICE7 iface, DWORD dwIndex, CONST D3DVALUE* pPlaneEquation)
2422 ICOM_THIS(IDirect3DDeviceImpl,iface);
2423 IDirect3DDeviceGLImpl* glThis = (IDirect3DDeviceGLImpl*) This;
2425 TRACE("(%p)->(%ld,%p)\n", This, dwIndex, pPlaneEquation);
2427 if (dwIndex >= This->max_clipping_planes) {
2428 return DDERR_INVALIDPARAMS;
2431 TRACE(" clip plane %ld : %f %f %f %f\n", dwIndex, pPlaneEquation[0], pPlaneEquation[1], pPlaneEquation[2], pPlaneEquation[3] );
2433 memcpy(This->clipping_planes[dwIndex].plane, pPlaneEquation, sizeof(D3DVALUE[4]));
2435 /* This is to force the reset of the transformation matrices on the next drawing.
2436 * This is needed to use the correct matrices for the various clipping planes.
2438 glThis->transform_state = GL_TRANSFORM_NONE;
2444 GL_IDirect3DDeviceImpl_7_SetViewport(LPDIRECT3DDEVICE7 iface,
2445 LPD3DVIEWPORT7 lpData)
2447 ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice7, iface);
2448 TRACE("(%p/%p)->(%p)\n", This, iface, lpData);
2450 if (TRACE_ON(ddraw)) {
2451 TRACE(" viewport is : \n");
2452 TRACE(" - dwX = %ld dwY = %ld\n",
2453 lpData->dwX, lpData->dwY);
2454 TRACE(" - dwWidth = %ld dwHeight = %ld\n",
2455 lpData->dwWidth, lpData->dwHeight);
2456 TRACE(" - dvMinZ = %f dvMaxZ = %f\n",
2457 lpData->dvMinZ, lpData->dvMaxZ);
2461 /* Set the viewport */
2462 if ((lpData->dvMinZ != This->active_viewport.dvMinZ) ||
2463 (lpData->dvMaxZ != This->active_viewport.dvMaxZ)) {
2464 glDepthRange(lpData->dvMinZ, lpData->dvMaxZ);
2466 if ((lpData->dwX != This->active_viewport.dwX) ||
2467 (lpData->dwY != This->active_viewport.dwY) ||
2468 (lpData->dwWidth != This->active_viewport.dwWidth) ||
2469 (lpData->dwHeight != This->active_viewport.dwHeight)) {
2470 glViewport(lpData->dwX,
2471 This->surface->surface_desc.dwHeight - (lpData->dwHeight + lpData->dwY),
2472 lpData->dwWidth, lpData->dwHeight);
2477 This->active_viewport = *lpData;
2482 #if !defined(__STRICT_ANSI__) && defined(__GNUC__)
2483 # define XCAST(fun) (typeof(VTABLE_IDirect3DDevice7.fun))
2485 # define XCAST(fun) (void*)
2488 ICOM_VTABLE(IDirect3DDevice7) VTABLE_IDirect3DDevice7 =
2490 ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
2491 XCAST(QueryInterface) Main_IDirect3DDeviceImpl_7_3T_2T_1T_QueryInterface,
2492 XCAST(AddRef) Main_IDirect3DDeviceImpl_7_3T_2T_1T_AddRef,
2493 XCAST(Release) GL_IDirect3DDeviceImpl_7_3T_2T_1T_Release,
2494 XCAST(GetCaps) GL_IDirect3DDeviceImpl_7_GetCaps,
2495 XCAST(EnumTextureFormats) GL_IDirect3DDeviceImpl_7_3T_EnumTextureFormats,
2496 XCAST(BeginScene) Main_IDirect3DDeviceImpl_7_3T_2T_1T_BeginScene,
2497 XCAST(EndScene) Main_IDirect3DDeviceImpl_7_3T_2T_1T_EndScene,
2498 XCAST(GetDirect3D) Main_IDirect3DDeviceImpl_7_3T_2T_1T_GetDirect3D,
2499 XCAST(SetRenderTarget) Main_IDirect3DDeviceImpl_7_3T_2T_SetRenderTarget,
2500 XCAST(GetRenderTarget) Main_IDirect3DDeviceImpl_7_3T_2T_GetRenderTarget,
2501 XCAST(Clear) Main_IDirect3DDeviceImpl_7_Clear,
2502 XCAST(SetTransform) Main_IDirect3DDeviceImpl_7_3T_2T_SetTransform,
2503 XCAST(GetTransform) Main_IDirect3DDeviceImpl_7_3T_2T_GetTransform,
2504 XCAST(SetViewport) GL_IDirect3DDeviceImpl_7_SetViewport,
2505 XCAST(MultiplyTransform) Main_IDirect3DDeviceImpl_7_3T_2T_MultiplyTransform,
2506 XCAST(GetViewport) Main_IDirect3DDeviceImpl_7_GetViewport,
2507 XCAST(SetMaterial) GL_IDirect3DDeviceImpl_7_SetMaterial,
2508 XCAST(GetMaterial) Main_IDirect3DDeviceImpl_7_GetMaterial,
2509 XCAST(SetLight) GL_IDirect3DDeviceImpl_7_SetLight,
2510 XCAST(GetLight) Main_IDirect3DDeviceImpl_7_GetLight,
2511 XCAST(SetRenderState) GL_IDirect3DDeviceImpl_7_3T_2T_SetRenderState,
2512 XCAST(GetRenderState) GL_IDirect3DDeviceImpl_7_3T_2T_GetRenderState,
2513 XCAST(BeginStateBlock) Main_IDirect3DDeviceImpl_7_BeginStateBlock,
2514 XCAST(EndStateBlock) Main_IDirect3DDeviceImpl_7_EndStateBlock,
2515 XCAST(PreLoad) Main_IDirect3DDeviceImpl_7_PreLoad,
2516 XCAST(DrawPrimitive) GL_IDirect3DDeviceImpl_7_3T_DrawPrimitive,
2517 XCAST(DrawIndexedPrimitive) GL_IDirect3DDeviceImpl_7_3T_DrawIndexedPrimitive,
2518 XCAST(SetClipStatus) Main_IDirect3DDeviceImpl_7_3T_2T_SetClipStatus,
2519 XCAST(GetClipStatus) Main_IDirect3DDeviceImpl_7_3T_2T_GetClipStatus,
2520 XCAST(DrawPrimitiveStrided) GL_IDirect3DDeviceImpl_7_3T_DrawPrimitiveStrided,
2521 XCAST(DrawIndexedPrimitiveStrided) GL_IDirect3DDeviceImpl_7_3T_DrawIndexedPrimitiveStrided,
2522 XCAST(DrawPrimitiveVB) GL_IDirect3DDeviceImpl_7_3T_DrawPrimitiveVB,
2523 XCAST(DrawIndexedPrimitiveVB) GL_IDirect3DDeviceImpl_7_3T_DrawIndexedPrimitiveVB,
2524 XCAST(ComputeSphereVisibility) Main_IDirect3DDeviceImpl_7_3T_ComputeSphereVisibility,
2525 XCAST(GetTexture) Main_IDirect3DDeviceImpl_7_3T_GetTexture,
2526 XCAST(SetTexture) GL_IDirect3DDeviceImpl_7_3T_SetTexture,
2527 XCAST(GetTextureStageState) Main_IDirect3DDeviceImpl_7_3T_GetTextureStageState,
2528 XCAST(SetTextureStageState) GL_IDirect3DDeviceImpl_7_3T_SetTextureStageState,
2529 XCAST(ValidateDevice) Main_IDirect3DDeviceImpl_7_3T_ValidateDevice,
2530 XCAST(ApplyStateBlock) Main_IDirect3DDeviceImpl_7_ApplyStateBlock,
2531 XCAST(CaptureStateBlock) Main_IDirect3DDeviceImpl_7_CaptureStateBlock,
2532 XCAST(DeleteStateBlock) Main_IDirect3DDeviceImpl_7_DeleteStateBlock,
2533 XCAST(CreateStateBlock) Main_IDirect3DDeviceImpl_7_CreateStateBlock,
2534 XCAST(Load) Main_IDirect3DDeviceImpl_7_Load,
2535 XCAST(LightEnable) GL_IDirect3DDeviceImpl_7_LightEnable,
2536 XCAST(GetLightEnable) Main_IDirect3DDeviceImpl_7_GetLightEnable,
2537 XCAST(SetClipPlane) GL_IDirect3DDeviceImpl_7_SetClipPlane,
2538 XCAST(GetClipPlane) Main_IDirect3DDeviceImpl_7_GetClipPlane,
2539 XCAST(GetInfo) Main_IDirect3DDeviceImpl_7_GetInfo,
2542 #if !defined(__STRICT_ANSI__) && defined(__GNUC__)
2547 #if !defined(__STRICT_ANSI__) && defined(__GNUC__)
2548 # define XCAST(fun) (typeof(VTABLE_IDirect3DDevice3.fun))
2550 # define XCAST(fun) (void*)
2553 ICOM_VTABLE(IDirect3DDevice3) VTABLE_IDirect3DDevice3 =
2555 ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
2556 XCAST(QueryInterface) Thunk_IDirect3DDeviceImpl_3_QueryInterface,
2557 XCAST(AddRef) Thunk_IDirect3DDeviceImpl_3_AddRef,
2558 XCAST(Release) Thunk_IDirect3DDeviceImpl_3_Release,
2559 XCAST(GetCaps) GL_IDirect3DDeviceImpl_3_2T_1T_GetCaps,
2560 XCAST(GetStats) Main_IDirect3DDeviceImpl_3_2T_1T_GetStats,
2561 XCAST(AddViewport) Main_IDirect3DDeviceImpl_3_2T_1T_AddViewport,
2562 XCAST(DeleteViewport) Main_IDirect3DDeviceImpl_3_2T_1T_DeleteViewport,
2563 XCAST(NextViewport) Main_IDirect3DDeviceImpl_3_2T_1T_NextViewport,
2564 XCAST(EnumTextureFormats) Thunk_IDirect3DDeviceImpl_3_EnumTextureFormats,
2565 XCAST(BeginScene) Thunk_IDirect3DDeviceImpl_3_BeginScene,
2566 XCAST(EndScene) Thunk_IDirect3DDeviceImpl_3_EndScene,
2567 XCAST(GetDirect3D) Thunk_IDirect3DDeviceImpl_3_GetDirect3D,
2568 XCAST(SetCurrentViewport) Main_IDirect3DDeviceImpl_3_2T_SetCurrentViewport,
2569 XCAST(GetCurrentViewport) Main_IDirect3DDeviceImpl_3_2T_GetCurrentViewport,
2570 XCAST(SetRenderTarget) Thunk_IDirect3DDeviceImpl_3_SetRenderTarget,
2571 XCAST(GetRenderTarget) Thunk_IDirect3DDeviceImpl_3_GetRenderTarget,
2572 XCAST(Begin) Main_IDirect3DDeviceImpl_3_Begin,
2573 XCAST(BeginIndexed) Main_IDirect3DDeviceImpl_3_BeginIndexed,
2574 XCAST(Vertex) Main_IDirect3DDeviceImpl_3_2T_Vertex,
2575 XCAST(Index) Main_IDirect3DDeviceImpl_3_2T_Index,
2576 XCAST(End) Main_IDirect3DDeviceImpl_3_2T_End,
2577 XCAST(GetRenderState) Thunk_IDirect3DDeviceImpl_3_GetRenderState,
2578 XCAST(SetRenderState) Thunk_IDirect3DDeviceImpl_3_SetRenderState,
2579 XCAST(GetLightState) Main_IDirect3DDeviceImpl_3_2T_GetLightState,
2580 XCAST(SetLightState) GL_IDirect3DDeviceImpl_3_2T_SetLightState,
2581 XCAST(SetTransform) Thunk_IDirect3DDeviceImpl_3_SetTransform,
2582 XCAST(GetTransform) Thunk_IDirect3DDeviceImpl_3_GetTransform,
2583 XCAST(MultiplyTransform) Thunk_IDirect3DDeviceImpl_3_MultiplyTransform,
2584 XCAST(DrawPrimitive) Thunk_IDirect3DDeviceImpl_3_DrawPrimitive,
2585 XCAST(DrawIndexedPrimitive) Thunk_IDirect3DDeviceImpl_3_DrawIndexedPrimitive,
2586 XCAST(SetClipStatus) Thunk_IDirect3DDeviceImpl_3_SetClipStatus,
2587 XCAST(GetClipStatus) Thunk_IDirect3DDeviceImpl_3_GetClipStatus,
2588 XCAST(DrawPrimitiveStrided) Thunk_IDirect3DDeviceImpl_3_DrawPrimitiveStrided,
2589 XCAST(DrawIndexedPrimitiveStrided) Thunk_IDirect3DDeviceImpl_3_DrawIndexedPrimitiveStrided,
2590 XCAST(DrawPrimitiveVB) Thunk_IDirect3DDeviceImpl_3_DrawPrimitiveVB,
2591 XCAST(DrawIndexedPrimitiveVB) Thunk_IDirect3DDeviceImpl_3_DrawIndexedPrimitiveVB,
2592 XCAST(ComputeSphereVisibility) Thunk_IDirect3DDeviceImpl_3_ComputeSphereVisibility,
2593 XCAST(GetTexture) Thunk_IDirect3DDeviceImpl_3_GetTexture,
2594 XCAST(SetTexture) Thunk_IDirect3DDeviceImpl_3_SetTexture,
2595 XCAST(GetTextureStageState) Thunk_IDirect3DDeviceImpl_3_GetTextureStageState,
2596 XCAST(SetTextureStageState) Thunk_IDirect3DDeviceImpl_3_SetTextureStageState,
2597 XCAST(ValidateDevice) Thunk_IDirect3DDeviceImpl_3_ValidateDevice,
2600 #if !defined(__STRICT_ANSI__) && defined(__GNUC__)
2605 #if !defined(__STRICT_ANSI__) && defined(__GNUC__)
2606 # define XCAST(fun) (typeof(VTABLE_IDirect3DDevice2.fun))
2608 # define XCAST(fun) (void*)
2611 ICOM_VTABLE(IDirect3DDevice2) VTABLE_IDirect3DDevice2 =
2613 ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
2614 XCAST(QueryInterface) Thunk_IDirect3DDeviceImpl_2_QueryInterface,
2615 XCAST(AddRef) Thunk_IDirect3DDeviceImpl_2_AddRef,
2616 XCAST(Release) Thunk_IDirect3DDeviceImpl_2_Release,
2617 XCAST(GetCaps) Thunk_IDirect3DDeviceImpl_2_GetCaps,
2618 XCAST(SwapTextureHandles) Main_IDirect3DDeviceImpl_2_1T_SwapTextureHandles,
2619 XCAST(GetStats) Thunk_IDirect3DDeviceImpl_2_GetStats,
2620 XCAST(AddViewport) Thunk_IDirect3DDeviceImpl_2_AddViewport,
2621 XCAST(DeleteViewport) Thunk_IDirect3DDeviceImpl_2_DeleteViewport,
2622 XCAST(NextViewport) Thunk_IDirect3DDeviceImpl_2_NextViewport,
2623 XCAST(EnumTextureFormats) GL_IDirect3DDeviceImpl_2_1T_EnumTextureFormats,
2624 XCAST(BeginScene) Thunk_IDirect3DDeviceImpl_2_BeginScene,
2625 XCAST(EndScene) Thunk_IDirect3DDeviceImpl_2_EndScene,
2626 XCAST(GetDirect3D) Thunk_IDirect3DDeviceImpl_2_GetDirect3D,
2627 XCAST(SetCurrentViewport) Thunk_IDirect3DDeviceImpl_2_SetCurrentViewport,
2628 XCAST(GetCurrentViewport) Thunk_IDirect3DDeviceImpl_2_GetCurrentViewport,
2629 XCAST(SetRenderTarget) Thunk_IDirect3DDeviceImpl_2_SetRenderTarget,
2630 XCAST(GetRenderTarget) Thunk_IDirect3DDeviceImpl_2_GetRenderTarget,
2631 XCAST(Begin) Main_IDirect3DDeviceImpl_2_Begin,
2632 XCAST(BeginIndexed) Main_IDirect3DDeviceImpl_2_BeginIndexed,
2633 XCAST(Vertex) Thunk_IDirect3DDeviceImpl_2_Vertex,
2634 XCAST(Index) Thunk_IDirect3DDeviceImpl_2_Index,
2635 XCAST(End) Thunk_IDirect3DDeviceImpl_2_End,
2636 XCAST(GetRenderState) Thunk_IDirect3DDeviceImpl_2_GetRenderState,
2637 XCAST(SetRenderState) Thunk_IDirect3DDeviceImpl_2_SetRenderState,
2638 XCAST(GetLightState) Thunk_IDirect3DDeviceImpl_2_GetLightState,
2639 XCAST(SetLightState) Thunk_IDirect3DDeviceImpl_2_SetLightState,
2640 XCAST(SetTransform) Thunk_IDirect3DDeviceImpl_2_SetTransform,
2641 XCAST(GetTransform) Thunk_IDirect3DDeviceImpl_2_GetTransform,
2642 XCAST(MultiplyTransform) Thunk_IDirect3DDeviceImpl_2_MultiplyTransform,
2643 XCAST(DrawPrimitive) GL_IDirect3DDeviceImpl_2_DrawPrimitive,
2644 XCAST(DrawIndexedPrimitive) GL_IDirect3DDeviceImpl_2_DrawIndexedPrimitive,
2645 XCAST(SetClipStatus) Thunk_IDirect3DDeviceImpl_2_SetClipStatus,
2646 XCAST(GetClipStatus) Thunk_IDirect3DDeviceImpl_2_GetClipStatus,
2649 #if !defined(__STRICT_ANSI__) && defined(__GNUC__)
2654 #if !defined(__STRICT_ANSI__) && defined(__GNUC__)
2655 # define XCAST(fun) (typeof(VTABLE_IDirect3DDevice.fun))
2657 # define XCAST(fun) (void*)
2660 ICOM_VTABLE(IDirect3DDevice) VTABLE_IDirect3DDevice =
2662 ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
2663 XCAST(QueryInterface) Thunk_IDirect3DDeviceImpl_1_QueryInterface,
2664 XCAST(AddRef) Thunk_IDirect3DDeviceImpl_1_AddRef,
2665 XCAST(Release) Thunk_IDirect3DDeviceImpl_1_Release,
2666 XCAST(Initialize) Main_IDirect3DDeviceImpl_1_Initialize,
2667 XCAST(GetCaps) Thunk_IDirect3DDeviceImpl_1_GetCaps,
2668 XCAST(SwapTextureHandles) Thunk_IDirect3DDeviceImpl_1_SwapTextureHandles,
2669 XCAST(CreateExecuteBuffer) GL_IDirect3DDeviceImpl_1_CreateExecuteBuffer,
2670 XCAST(GetStats) Thunk_IDirect3DDeviceImpl_1_GetStats,
2671 XCAST(Execute) Main_IDirect3DDeviceImpl_1_Execute,
2672 XCAST(AddViewport) Thunk_IDirect3DDeviceImpl_1_AddViewport,
2673 XCAST(DeleteViewport) Thunk_IDirect3DDeviceImpl_1_DeleteViewport,
2674 XCAST(NextViewport) Thunk_IDirect3DDeviceImpl_1_NextViewport,
2675 XCAST(Pick) Main_IDirect3DDeviceImpl_1_Pick,
2676 XCAST(GetPickRecords) Main_IDirect3DDeviceImpl_1_GetPickRecords,
2677 XCAST(EnumTextureFormats) Thunk_IDirect3DDeviceImpl_1_EnumTextureFormats,
2678 XCAST(CreateMatrix) Main_IDirect3DDeviceImpl_1_CreateMatrix,
2679 XCAST(SetMatrix) Main_IDirect3DDeviceImpl_1_SetMatrix,
2680 XCAST(GetMatrix) Main_IDirect3DDeviceImpl_1_GetMatrix,
2681 XCAST(DeleteMatrix) Main_IDirect3DDeviceImpl_1_DeleteMatrix,
2682 XCAST(BeginScene) Thunk_IDirect3DDeviceImpl_1_BeginScene,
2683 XCAST(EndScene) Thunk_IDirect3DDeviceImpl_1_EndScene,
2684 XCAST(GetDirect3D) Thunk_IDirect3DDeviceImpl_1_GetDirect3D,
2687 #if !defined(__STRICT_ANSI__) && defined(__GNUC__)
2691 static HRESULT d3ddevice_clear(IDirect3DDeviceImpl *This,
2692 WINE_GL_BUFFER_TYPE buffer_type,
2700 IDirect3DDeviceGLImpl *glThis = (IDirect3DDeviceGLImpl *) This;
2701 GLbitfield bitfield = 0;
2705 TRACE("(%p)->(%08lx,%p,%08lx,%08lx,%f,%08lx)\n", This, dwCount, lpRects, dwFlags, dwColor, dvZ, dwStencil);
2706 if (TRACE_ON(ddraw)) {
2709 TRACE(" rectangles : \n");
2710 for (i = 0; i < dwCount; i++) {
2711 TRACE(" - %ld x %ld %ld x %ld\n", lpRects[i].u1.x1, lpRects[i].u2.y1, lpRects[i].u3.x2, lpRects[i].u4.y2);
2720 rect.u3.x2 = This->surface->surface_desc.dwWidth;
2721 rect.u4.y2 = This->surface->surface_desc.dwHeight;
2725 /* Clears the screen */
2728 if (dwFlags & D3DCLEAR_TARGET) {
2729 if (glThis->state[buffer_type] == SURFACE_MEMORY_DIRTY) {
2730 /* TODO: optimize here the case where Clear changes all the screen... */
2731 This->flush_to_framebuffer(This, &(glThis->lock_rect[buffer_type]), glThis->lock_surf[buffer_type]);
2733 glThis->state[buffer_type] = SURFACE_GL;
2736 if (dwFlags & D3DCLEAR_ZBUFFER) {
2737 bitfield |= GL_DEPTH_BUFFER_BIT;
2738 if (glThis->depth_mask == FALSE) {
2739 glDepthMask(GL_TRUE); /* Enables Z writing to be sure to delete also the Z buffer */
2741 if (dvZ != glThis->prev_clear_Z) {
2743 glThis->prev_clear_Z = dvZ;
2745 TRACE(" depth value : %f\n", dvZ);
2747 if (dwFlags & D3DCLEAR_STENCIL) {
2748 bitfield |= GL_STENCIL_BUFFER_BIT;
2749 if (dwStencil != glThis->prev_clear_stencil) {
2750 glClearStencil(dwStencil);
2751 glThis->prev_clear_stencil = dwStencil;
2753 TRACE(" stencil value : %ld\n", dwStencil);
2755 if (dwFlags & D3DCLEAR_TARGET) {
2756 bitfield |= GL_COLOR_BUFFER_BIT;
2757 if (dwColor != glThis->prev_clear_color) {
2758 glClearColor(((dwColor >> 16) & 0xFF) / 255.0,
2759 ((dwColor >> 8) & 0xFF) / 255.0,
2760 ((dwColor >> 0) & 0xFF) / 255.0,
2761 ((dwColor >> 24) & 0xFF) / 255.0);
2762 glThis->prev_clear_color = dwColor;
2764 TRACE(" color value (ARGB) : %08lx\n", dwColor);
2767 glEnable(GL_SCISSOR_TEST);
2768 for (i = 0; i < dwCount; i++) {
2769 glScissor(lpRects[i].u1.x1, This->surface->surface_desc.dwHeight - lpRects[i].u4.y2,
2770 lpRects[i].u3.x2 - lpRects[i].u1.x1, lpRects[i].u4.y2 - lpRects[i].u2.y1);
2773 glDisable(GL_SCISSOR_TEST);
2775 if (dwFlags & D3DCLEAR_ZBUFFER) {
2776 if (glThis->depth_mask == FALSE) glDepthMask(GL_FALSE);
2784 static HRESULT d3ddevice_clear_back(IDirect3DDeviceImpl *This,
2792 return d3ddevice_clear(This, WINE_GL_BUFFER_BACK, dwCount, lpRects, dwFlags, dwColor, dvZ, dwStencil);
2796 setup_rect_and_surface_for_blt(IDirectDrawSurfaceImpl *This,
2797 WINE_GL_BUFFER_TYPE *buffer_type_p, D3DRECT *rect)
2799 IDirect3DDeviceGLImpl *gl_d3d_dev = (IDirect3DDeviceGLImpl *) This->d3ddevice;
2800 WINE_GL_BUFFER_TYPE buffer_type;
2802 /* First check if we BLT to the backbuffer... */
2803 if ((This->surface_desc.ddsCaps.dwCaps & (DDSCAPS_BACKBUFFER)) != 0) {
2804 buffer_type = WINE_GL_BUFFER_BACK;
2805 } else if ((This->surface_desc.ddsCaps.dwCaps & (DDSCAPS_FRONTBUFFER|DDSCAPS_PRIMARYSURFACE)) != 0) {
2806 buffer_type = WINE_GL_BUFFER_FRONT;
2808 ERR("Only BLT override to front or back-buffer is supported for now !\n");
2809 return DDERR_INVALIDPARAMS;
2812 if ((gl_d3d_dev->state[buffer_type] == SURFACE_MEMORY_DIRTY) &&
2813 (rect->u1.x1 >= gl_d3d_dev->lock_rect[buffer_type].left) &&
2814 (rect->u2.y1 >= gl_d3d_dev->lock_rect[buffer_type].top) &&
2815 (rect->u3.x2 <= gl_d3d_dev->lock_rect[buffer_type].right) &&
2816 (rect->u4.y2 <= gl_d3d_dev->lock_rect[buffer_type].bottom)) {
2817 /* If the memory zone is already dirty, use the standard 'in memory' blit operations and not
2820 return DDERR_INVALIDPARAMS;
2822 *buffer_type_p = buffer_type;
2828 d3ddevice_blt(IDirectDrawSurfaceImpl *This, LPRECT rdst,
2829 LPDIRECTDRAWSURFACE7 src, LPRECT rsrc,
2830 DWORD dwFlags, LPDDBLTFX lpbltfx)
2832 WINE_GL_BUFFER_TYPE buffer_type;
2836 rect.u1.x1 = rdst->left;
2837 rect.u2.y1 = rdst->top;
2838 rect.u3.x2 = rdst->right;
2839 rect.u4.y2 = rdst->bottom;
2843 rect.u3.x2 = This->surface_desc.dwWidth;
2844 rect.u4.y2 = This->surface_desc.dwHeight;
2847 if (setup_rect_and_surface_for_blt(This, &buffer_type, &rect) != DD_OK) return DDERR_INVALIDPARAMS;
2849 if (dwFlags & DDBLT_COLORFILL) {
2850 /* This is easy to handle for the D3D Device... */
2854 /* The color as given in the Blt function is in the format of the frame-buffer...
2855 * 'clear' expect it in ARGB format => we need to do some conversion :-)
2857 if (This->surface_desc.u4.ddpfPixelFormat.dwFlags & DDPF_PALETTEINDEXED8) {
2858 if (This->palette) {
2859 color = ((0xFF000000) |
2860 (This->palette->palents[lpbltfx->u5.dwFillColor].peRed << 16) |
2861 (This->palette->palents[lpbltfx->u5.dwFillColor].peGreen << 8) |
2862 (This->palette->palents[lpbltfx->u5.dwFillColor].peBlue));
2866 } else if ((This->surface_desc.u4.ddpfPixelFormat.dwFlags & DDPF_RGB) &&
2867 (((This->surface_desc.u4.ddpfPixelFormat.dwFlags & DDPF_ALPHAPIXELS) == 0) ||
2868 (This->surface_desc.u4.ddpfPixelFormat.u5.dwRGBAlphaBitMask == 0x00000000))) {
2869 if ((This->surface_desc.u4.ddpfPixelFormat.u1.dwRGBBitCount == 16) &&
2870 (This->surface_desc.u4.ddpfPixelFormat.u2.dwRBitMask == 0xF800) &&
2871 (This->surface_desc.u4.ddpfPixelFormat.u3.dwGBitMask == 0x07E0) &&
2872 (This->surface_desc.u4.ddpfPixelFormat.u4.dwBBitMask == 0x001F)) {
2873 if (lpbltfx->u5.dwFillColor == 0xFFFF) {
2876 color = ((0xFF000000) |
2877 ((lpbltfx->u5.dwFillColor & 0xF800) << 8) |
2878 ((lpbltfx->u5.dwFillColor & 0x07E0) << 5) |
2879 ((lpbltfx->u5.dwFillColor & 0x001F) << 3));
2881 } else if (((This->surface_desc.u4.ddpfPixelFormat.u1.dwRGBBitCount == 32) ||
2882 (This->surface_desc.u4.ddpfPixelFormat.u1.dwRGBBitCount == 24)) &&
2883 (This->surface_desc.u4.ddpfPixelFormat.u2.dwRBitMask == 0x00FF0000) &&
2884 (This->surface_desc.u4.ddpfPixelFormat.u3.dwGBitMask == 0x0000FF00) &&
2885 (This->surface_desc.u4.ddpfPixelFormat.u4.dwBBitMask == 0x000000FF)) {
2886 color = 0xFF000000 | lpbltfx->u5.dwFillColor;
2888 ERR("Wrong surface type for BLT override (unknown RGB format) !\n");
2889 return DDERR_INVALIDPARAMS;
2892 ERR("Wrong surface type for BLT override !\n");
2893 return DDERR_INVALIDPARAMS;
2896 TRACE(" executing D3D Device override.\n");
2900 glGetIntegerv(GL_DRAW_BUFFER, &prev_draw);
2901 if (buffer_type == WINE_GL_BUFFER_FRONT)
2902 glDrawBuffer(GL_FRONT);
2904 glDrawBuffer(GL_BACK);
2906 d3ddevice_clear(This->d3ddevice, buffer_type, 1, &rect, D3DCLEAR_TARGET, color, 0.0, 0x00000000);
2908 if (((buffer_type == WINE_GL_BUFFER_FRONT) && (prev_draw == GL_BACK)) ||
2909 ((buffer_type == WINE_GL_BUFFER_BACK) && (prev_draw == GL_FRONT)))
2910 glDrawBuffer(prev_draw);
2915 } else if ((dwFlags & (~(DDBLT_KEYSRC|DDBLT_WAIT|DDBLT_ASYNC))) == 0) {
2916 /* Normal blit without any special case... */
2918 /* And which has a SRC surface */
2919 IDirectDrawSurfaceImpl *src_impl = ICOM_OBJECT(IDirectDrawSurfaceImpl, IDirectDrawSurface7, src);
2921 if ((src_impl->surface_desc.ddsCaps.dwCaps & DDSCAPS_3DDEVICE) &&
2922 (src_impl->d3ddevice == This->d3ddevice) &&
2923 ((dwFlags & DDBLT_KEYSRC) == 0)) {
2924 /* Both are 3D devices and using the same GL device and the Blt is without color-keying */
2928 WINE_GL_BUFFER_TYPE src_buffer_type;
2929 IDirect3DDeviceGLImpl *gl_d3d_dev = (IDirect3DDeviceGLImpl *) This->d3ddevice;
2935 src_rect.u1.x1 = rsrc->left;
2936 src_rect.u2.y1 = rsrc->top;
2937 src_rect.u3.x2 = rsrc->right;
2938 src_rect.u4.y2 = rsrc->bottom;
2942 src_rect.u3.x2 = src_impl->surface_desc.dwWidth;
2943 src_rect.u4.y2 = src_impl->surface_desc.dwHeight;
2946 width = src_rect.u3.x2 - src_rect.u1.x1;
2947 height = src_rect.u4.y2 - src_rect.u2.y1;
2949 if ((width != (rect.u3.x2 - rect.u1.x1)) ||
2950 (height != (rect.u4.y2 - rect.u2.y1))) {
2951 FIXME(" buffer to buffer copy not supported with stretching yet !\n");
2952 return DDERR_INVALIDPARAMS;
2955 /* First check if we BLT from the backbuffer... */
2956 if ((src_impl->surface_desc.ddsCaps.dwCaps & (DDSCAPS_BACKBUFFER)) != 0) {
2957 src_buffer_type = WINE_GL_BUFFER_BACK;
2958 } else if ((src_impl->surface_desc.ddsCaps.dwCaps & (DDSCAPS_FRONTBUFFER|DDSCAPS_PRIMARYSURFACE)) != 0) {
2959 src_buffer_type = WINE_GL_BUFFER_FRONT;
2961 ERR("Unexpected case in direct buffer to buffer copy !\n");
2962 return DDERR_INVALIDPARAMS;
2965 TRACE(" using direct buffer to buffer copy.\n");
2969 opt_bitmap = d3ddevice_set_state_for_flush(This->d3ddevice, (LPCRECT) &rect, FALSE, &initial);
2971 if (upload_surface_to_tex_memory_init(This, 0, &gl_d3d_dev->current_internal_format,
2972 initial, FALSE, UNLOCK_TEX_SIZE, UNLOCK_TEX_SIZE) != DD_OK) {
2973 ERR(" unsupported pixel format at direct buffer to buffer copy.\n");
2975 return DDERR_INVALIDPARAMS;
2978 glGetIntegerv(GL_DRAW_BUFFER, &prev_draw);
2979 if (buffer_type == WINE_GL_BUFFER_FRONT)
2980 glDrawBuffer(GL_FRONT);
2982 glDrawBuffer(GL_BACK);
2984 if (src_buffer_type == WINE_GL_BUFFER_FRONT)
2985 glReadBuffer(GL_FRONT);
2987 glReadBuffer(GL_BACK);
2989 /* Now the serious stuff happens. Basically, we copy from the source buffer to the texture memory.
2990 And directly re-draws this on the destination buffer. */
2991 for (y = 0; y < height; y += UNLOCK_TEX_SIZE) {
2994 if ((src_rect.u2.y1 + y + UNLOCK_TEX_SIZE) > src_impl->surface_desc.dwHeight)
2995 get_height = src_impl->surface_desc.dwHeight - (src_rect.u2.y1 + y);
2997 get_height = UNLOCK_TEX_SIZE;
2999 for (x = 0; x < width; x += UNLOCK_TEX_SIZE) {
3002 if ((src_rect.u1.x1 + x + UNLOCK_TEX_SIZE) > src_impl->surface_desc.dwWidth)
3003 get_width = src_impl->surface_desc.dwWidth - (src_rect.u1.x1 + x);
3005 get_width = UNLOCK_TEX_SIZE;
3007 glCopyTexSubImage2D(GL_TEXTURE_2D, 0,
3008 0, UNLOCK_TEX_SIZE - get_height,
3009 src_rect.u1.x1 + x, src_impl->surface_desc.dwHeight - (src_rect.u2.y1 + y + get_height),
3010 get_width, get_height);
3013 glTexCoord2f(0.0, 0.0);
3014 glVertex3d(rect.u1.x1 + x,
3015 rect.u2.y1 + y + UNLOCK_TEX_SIZE,
3017 glTexCoord2f(1.0, 0.0);
3018 glVertex3d(rect.u1.x1 + x + UNLOCK_TEX_SIZE,
3019 rect.u2.y1 + y + UNLOCK_TEX_SIZE,
3021 glTexCoord2f(1.0, 1.0);
3022 glVertex3d(rect.u1.x1 + x + UNLOCK_TEX_SIZE,
3025 glTexCoord2f(0.0, 1.0);
3026 glVertex3d(rect.u1.x1 + x,
3033 upload_surface_to_tex_memory_release();
3034 d3ddevice_restore_state_after_flush(This->d3ddevice, opt_bitmap, FALSE);
3036 if (((buffer_type == WINE_GL_BUFFER_FRONT) && (prev_draw == GL_BACK)) ||
3037 ((buffer_type == WINE_GL_BUFFER_BACK) && (prev_draw == GL_FRONT)))
3038 glDrawBuffer(prev_draw);
3044 /* This is the normal 'with source' Blit. Use the texture engine to do the Blt for us
3045 (this prevents calling glReadPixels) */
3049 IDirect3DDeviceGLImpl *gl_d3d_dev = (IDirect3DDeviceGLImpl *) This->d3ddevice;
3053 double x_stretch, y_stretch;
3056 src_rect.u1.x1 = rsrc->left;
3057 src_rect.u2.y1 = rsrc->top;
3058 src_rect.u3.x2 = rsrc->right;
3059 src_rect.u4.y2 = rsrc->bottom;
3063 src_rect.u3.x2 = src_impl->surface_desc.dwWidth;
3064 src_rect.u4.y2 = src_impl->surface_desc.dwHeight;
3067 width = src_rect.u3.x2 - src_rect.u1.x1;
3068 height = src_rect.u4.y2 - src_rect.u2.y1;
3070 x_stretch = (double) (rect.u3.x2 - rect.u1.x1) / (double) width;
3071 y_stretch = (double) (rect.u4.y2 - rect.u2.y1) / (double) height;
3073 TRACE(" using memory to buffer Blt overide.\n");
3077 opt_bitmap = d3ddevice_set_state_for_flush(This->d3ddevice, (LPCRECT) &rect, ((dwFlags & DDBLT_KEYSRC) != 0), &initial);
3079 if (upload_surface_to_tex_memory_init(src_impl, 0, &gl_d3d_dev->current_internal_format,
3080 initial, ((dwFlags & DDBLT_KEYSRC) != 0), UNLOCK_TEX_SIZE, UNLOCK_TEX_SIZE) != DD_OK) {
3081 ERR(" unsupported pixel format at memory to buffer Blt overide.\n");
3083 return DDERR_INVALIDPARAMS;
3086 glGetIntegerv(GL_DRAW_BUFFER, &prev_draw);
3087 if (buffer_type == WINE_GL_BUFFER_FRONT)
3088 glDrawBuffer(GL_FRONT);
3090 glDrawBuffer(GL_BACK);
3092 /* Now the serious stuff happens. This is basically the same code that for the memory
3093 flush to frame buffer ... with stretching and different rectangles added :-) */
3094 for (y = 0; y < height; y += UNLOCK_TEX_SIZE) {
3097 flush_rect.top = src_rect.u2.y1 + y;
3098 flush_rect.bottom = ((src_rect.u2.y1 + y + UNLOCK_TEX_SIZE > src_rect.u4.y2) ?
3100 (src_rect.u2.y1 + y + UNLOCK_TEX_SIZE));
3102 for (x = 0; x < width; x += UNLOCK_TEX_SIZE) {
3103 flush_rect.left = src_rect.u1.x1 + x;
3104 flush_rect.right = ((src_rect.u1.x1 + x + UNLOCK_TEX_SIZE > src_rect.u3.x2) ?
3106 (src_rect.u1.x1 + x + UNLOCK_TEX_SIZE));
3108 upload_surface_to_tex_memory(&flush_rect, 0, 0, &(gl_d3d_dev->surface_ptr));
3111 glTexCoord2f(0.0, 0.0);
3112 glVertex3d(rect.u1.x1 + (x * x_stretch),
3113 rect.u2.y1 + (y * y_stretch),
3115 glTexCoord2f(1.0, 0.0);
3116 glVertex3d(rect.u1.x1 + ((x + UNLOCK_TEX_SIZE) * x_stretch),
3117 rect.u2.y1 + (y * y_stretch),
3119 glTexCoord2f(1.0, 1.0);
3120 glVertex3d(rect.u1.x1 + ((x + UNLOCK_TEX_SIZE) * x_stretch),
3121 rect.u2.y1 + ((y + UNLOCK_TEX_SIZE) * y_stretch),
3123 glTexCoord2f(0.0, 1.0);
3124 glVertex3d(rect.u1.x1 + (x * x_stretch),
3125 rect.u2.y1 + ((y + UNLOCK_TEX_SIZE) * y_stretch),
3131 upload_surface_to_tex_memory_release();
3132 d3ddevice_restore_state_after_flush(This->d3ddevice, opt_bitmap, ((dwFlags & DDBLT_KEYSRC) != 0));
3134 if (((buffer_type == WINE_GL_BUFFER_FRONT) && (prev_draw == GL_BACK)) ||
3135 ((buffer_type == WINE_GL_BUFFER_BACK) && (prev_draw == GL_FRONT)))
3136 glDrawBuffer(prev_draw);
3144 return DDERR_INVALIDPARAMS;
3148 d3ddevice_bltfast(IDirectDrawSurfaceImpl *This, DWORD dstx,
3149 DWORD dsty, LPDIRECTDRAWSURFACE7 src,
3150 LPRECT rsrc, DWORD trans)
3154 IDirectDrawSurfaceImpl *src_impl = ICOM_OBJECT(IDirectDrawSurfaceImpl, IDirectDrawSurface7, src);
3155 IDirect3DDeviceGLImpl *gl_d3d_dev = (IDirect3DDeviceGLImpl *) This->d3ddevice;
3156 WINE_GL_BUFFER_TYPE buffer_type;
3160 int width, height, x, y;
3162 /* Cannot support DSTCOLORKEY blitting... */
3163 if ((trans & DDBLTFAST_DESTCOLORKEY) != 0) return DDERR_INVALIDPARAMS;
3166 WARN("rsrc is NULL - getting the whole surface !!\n");
3168 rsrc->left = rsrc->top = 0;
3169 rsrc->right = src_impl->surface_desc.dwWidth;
3170 rsrc->bottom = src_impl->surface_desc.dwHeight;
3178 rdst.right = dstx + (rsrc->right - rsrc->left);
3179 if (rdst.right > This->surface_desc.dwWidth) {
3180 rsrc->right -= (This->surface_desc.dwWidth - rdst.right);
3181 rdst.right = This->surface_desc.dwWidth;
3183 rdst.bottom = dsty + (rsrc->bottom - rsrc->top);
3184 if (rdst.bottom > This->surface_desc.dwHeight) {
3185 rsrc->bottom -= (This->surface_desc.dwHeight - rdst.bottom);
3186 rdst.bottom = This->surface_desc.dwHeight;
3189 width = rsrc->right - rsrc->left;
3190 height = rsrc->bottom - rsrc->top;
3192 if (setup_rect_and_surface_for_blt(This, &buffer_type, (D3DRECT *) &rdst) != DD_OK) return DDERR_INVALIDPARAMS;
3194 TRACE(" using BltFast memory to frame buffer overide.\n");
3198 opt_bitmap = d3ddevice_set_state_for_flush(This->d3ddevice, &rdst, (trans & DDBLTFAST_SRCCOLORKEY) != 0, &initial);
3200 if (upload_surface_to_tex_memory_init(src_impl, 0, &gl_d3d_dev->current_internal_format,
3201 initial, (trans & DDBLTFAST_SRCCOLORKEY) != 0,
3202 UNLOCK_TEX_SIZE, UNLOCK_TEX_SIZE) != DD_OK) {
3203 ERR(" unsupported pixel format at memory to buffer Blt overide.\n");
3205 return DDERR_INVALIDPARAMS;
3208 glGetIntegerv(GL_DRAW_BUFFER, &prev_draw);
3209 if (buffer_type == WINE_GL_BUFFER_FRONT)
3210 glDrawBuffer(GL_FRONT);
3212 glDrawBuffer(GL_BACK);
3214 /* Now the serious stuff happens. This is basically the same code that for the memory
3215 flush to frame buffer but with different rectangles for source and destination :-) */
3216 for (y = 0; y < height; y += UNLOCK_TEX_SIZE) {
3219 flush_rect.top = rsrc->top + y;
3220 flush_rect.bottom = ((rsrc->top + y + UNLOCK_TEX_SIZE > rsrc->bottom) ?
3222 (rsrc->top + y + UNLOCK_TEX_SIZE));
3224 for (x = 0; x < width; x += UNLOCK_TEX_SIZE) {
3225 flush_rect.left = rsrc->left + x;
3226 flush_rect.right = ((rsrc->left + x + UNLOCK_TEX_SIZE > rsrc->right) ?
3228 (rsrc->left + x + UNLOCK_TEX_SIZE));
3230 upload_surface_to_tex_memory(&flush_rect, 0, 0, &(gl_d3d_dev->surface_ptr));
3233 glTexCoord2f(0.0, 0.0);
3234 glVertex3d(rdst.left + x,
3237 glTexCoord2f(1.0, 0.0);
3238 glVertex3d(rdst.left + (x + UNLOCK_TEX_SIZE),
3241 glTexCoord2f(1.0, 1.0);
3242 glVertex3d(rdst.left + (x + UNLOCK_TEX_SIZE),
3243 rdst.top + (y + UNLOCK_TEX_SIZE),
3245 glTexCoord2f(0.0, 1.0);
3246 glVertex3d(rdst.left + x,
3247 rdst.top + (y + UNLOCK_TEX_SIZE),
3253 upload_surface_to_tex_memory_release();
3254 d3ddevice_restore_state_after_flush(This->d3ddevice, opt_bitmap, (trans & DDBLTFAST_SRCCOLORKEY) != 0);
3256 if (((buffer_type == WINE_GL_BUFFER_FRONT) && (prev_draw == GL_BACK)) ||
3257 ((buffer_type == WINE_GL_BUFFER_BACK) && (prev_draw == GL_FRONT)))
3258 glDrawBuffer(prev_draw);
3266 d3ddevice_set_ortho(IDirect3DDeviceImpl *This)
3268 GLfloat height, width;
3269 GLfloat trans_mat[16];
3271 TRACE("(%p)\n", This);
3273 width = This->surface->surface_desc.dwWidth;
3274 height = This->surface->surface_desc.dwHeight;
3276 /* The X axis is straighforward.. For the Y axis, we need to convert 'D3D' screen coordinates
3277 to OpenGL screen coordinates (ie the upper left corner is not the same).
3278 For Z, the mystery is what should it be mapped to ? Ie should the resulting range be between
3279 -1.0 and 1.0 (as the X and Y coordinates) or between 0.0 and 1.0 ? */
3280 trans_mat[ 0] = 2.0 / width; trans_mat[ 4] = 0.0; trans_mat[ 8] = 0.0; trans_mat[12] = -1.0;
3281 trans_mat[ 1] = 0.0; trans_mat[ 5] = -2.0 / height; trans_mat[ 9] = 0.0; trans_mat[13] = 1.0;
3282 trans_mat[ 2] = 0.0; trans_mat[ 6] = 0.0; trans_mat[10] = 2.0; trans_mat[14] = -1.0;
3283 trans_mat[ 3] = 0.0; trans_mat[ 7] = 0.0; trans_mat[11] = 0.0; trans_mat[15] = 1.0;
3286 glMatrixMode(GL_MODELVIEW);
3288 /* See the OpenGL Red Book for an explanation of the following translation (in the OpenGL
3289 Correctness Tips section).
3291 Basically, from what I understood, if the game does not filter the font texture,
3292 as the 'real' pixel will lie at the middle of the two texels, OpenGL may choose the wrong
3293 one and we will have strange artifacts (as the rounding and stuff may give different results
3294 for different pixels, ie sometimes take the left pixel, sometimes the right).
3296 glTranslatef(0.375, 0.375, 0);
3297 glMatrixMode(GL_PROJECTION);
3298 glLoadMatrixf(trans_mat);
3303 d3ddevice_set_matrices(IDirect3DDeviceImpl *This, DWORD matrices,
3304 D3DMATRIX *world_mat, D3DMATRIX *view_mat, D3DMATRIX *proj_mat)
3306 TRACE("(%p,%08lx,%p,%p,%p)\n", This, matrices, world_mat, view_mat, proj_mat);
3309 if ((matrices & (VIEWMAT_CHANGED|WORLDMAT_CHANGED)) != 0) {
3310 glMatrixMode(GL_MODELVIEW);
3311 glLoadMatrixf((float *) view_mat);
3313 /* Now also re-loads all the Lights and Clipping Planes using the new matrices */
3314 if (This->state_block.render_state[D3DRENDERSTATE_CLIPPING - 1] != FALSE) {
3317 for (i = 0, runner = 0x00000001; i < This->max_clipping_planes; i++, runner <<= 1) {
3318 if (runner & This->state_block.render_state[D3DRENDERSTATE_CLIPPLANEENABLE - 1]) {
3321 plane[0] = This->clipping_planes[i].plane[0];
3322 plane[1] = This->clipping_planes[i].plane[1];
3323 plane[2] = This->clipping_planes[i].plane[2];
3324 plane[3] = This->clipping_planes[i].plane[3];
3326 glClipPlane( GL_CLIP_PLANE0 + i, (const GLdouble*) (&plane) );
3330 if (This->state_block.render_state[D3DRENDERSTATE_LIGHTING - 1] != FALSE) {
3334 for (i = 0, runner = 0x00000001; i < MAX_LIGHTS; i++, runner <<= 1) {
3335 if (runner & This->active_lights) {
3336 switch (This->light_parameters[i].dltType) {
3337 case D3DLIGHT_DIRECTIONAL: {
3339 float cut_off = 180.0;
3341 glLightfv(GL_LIGHT0 + i, GL_AMBIENT, (float *) &(This->light_parameters[i].dcvAmbient));
3342 glLightfv(GL_LIGHT0 + i, GL_DIFFUSE, (float *) &(This->light_parameters[i].dcvDiffuse));
3343 glLightfv(GL_LIGHT0 + i, GL_SPECULAR, (float *) &(This->light_parameters[i].dcvSpecular));
3344 glLightfv(GL_LIGHT0 + i, GL_SPOT_CUTOFF, &cut_off);
3346 direction[0] = This->light_parameters[i].dvDirection.u1.x;
3347 direction[1] = This->light_parameters[i].dvDirection.u2.y;
3348 direction[2] = This->light_parameters[i].dvDirection.u3.z;
3350 glLightfv(GL_LIGHT0 + i, GL_POSITION, (float *) direction);
3353 case D3DLIGHT_POINT: {
3355 float cut_off = 180.0;
3357 glLightfv(GL_LIGHT0 + i, GL_AMBIENT, (float *) &(This->light_parameters[i].dcvAmbient));
3358 glLightfv(GL_LIGHT0 + i, GL_DIFFUSE, (float *) &(This->light_parameters[i].dcvDiffuse));
3359 glLightfv(GL_LIGHT0 + i, GL_SPECULAR, (float *) &(This->light_parameters[i].dcvSpecular));
3360 position[0] = This->light_parameters[i].dvPosition.u1.x;
3361 position[1] = This->light_parameters[i].dvPosition.u2.y;
3362 position[2] = This->light_parameters[i].dvPosition.u3.z;
3364 glLightfv(GL_LIGHT0 + i, GL_POSITION, (float *) position);
3365 glLightfv(GL_LIGHT0 + i, GL_CONSTANT_ATTENUATION, &(This->light_parameters[i].dvAttenuation0));
3366 glLightfv(GL_LIGHT0 + i, GL_LINEAR_ATTENUATION, &(This->light_parameters[i].dvAttenuation1));
3367 glLightfv(GL_LIGHT0 + i, GL_QUADRATIC_ATTENUATION, &(This->light_parameters[i].dvAttenuation2));
3368 glLightfv(GL_LIGHT0 + i, GL_SPOT_CUTOFF, &cut_off);
3371 case D3DLIGHT_SPOT: {
3374 float cut_off = 90.0 * (This->light_parameters[i].dvPhi / M_PI);
3376 glLightfv(GL_LIGHT0 + i, GL_AMBIENT, (float *) &(This->light_parameters[i].dcvAmbient));
3377 glLightfv(GL_LIGHT0 + i, GL_DIFFUSE, (float *) &(This->light_parameters[i].dcvDiffuse));
3378 glLightfv(GL_LIGHT0 + i, GL_SPECULAR, (float *) &(This->light_parameters[i].dcvSpecular));
3380 direction[0] = This->light_parameters[i].dvDirection.u1.x;
3381 direction[1] = This->light_parameters[i].dvDirection.u2.y;
3382 direction[2] = This->light_parameters[i].dvDirection.u3.z;
3384 glLightfv(GL_LIGHT0 + i, GL_SPOT_DIRECTION, (float *) direction);
3385 position[0] = This->light_parameters[i].dvPosition.u1.x;
3386 position[1] = This->light_parameters[i].dvPosition.u2.y;
3387 position[2] = This->light_parameters[i].dvPosition.u3.z;
3389 glLightfv(GL_LIGHT0 + i, GL_POSITION, (float *) position);
3390 glLightfv(GL_LIGHT0 + i, GL_CONSTANT_ATTENUATION, &(This->light_parameters[i].dvAttenuation0));
3391 glLightfv(GL_LIGHT0 + i, GL_LINEAR_ATTENUATION, &(This->light_parameters[i].dvAttenuation1));
3392 glLightfv(GL_LIGHT0 + i, GL_QUADRATIC_ATTENUATION, &(This->light_parameters[i].dvAttenuation2));
3393 glLightfv(GL_LIGHT0 + i, GL_SPOT_CUTOFF, &cut_off);
3394 glLightfv(GL_LIGHT0 + i, GL_SPOT_EXPONENT, &(This->light_parameters[i].dvFalloff));
3398 /* No warning here as it's already done at light setting */
3405 glMultMatrixf((float *) world_mat);
3407 if ((matrices & PROJMAT_CHANGED) != 0) {
3408 glMatrixMode(GL_PROJECTION);
3409 glLoadMatrixf((float *) proj_mat);
3415 d3ddevice_matrices_updated(IDirect3DDeviceImpl *This, DWORD matrices)
3417 IDirect3DDeviceGLImpl *glThis = (IDirect3DDeviceGLImpl *) This;
3418 DWORD tex_mat, tex_stage;
3420 TRACE("(%p,%08lx)\n", This, matrices);
3422 if (matrices & (VIEWMAT_CHANGED|WORLDMAT_CHANGED|PROJMAT_CHANGED)) {
3423 if (glThis->transform_state == GL_TRANSFORM_NORMAL) {
3424 /* This will force an update of the transform state at the next drawing. */
3425 glThis->transform_state = GL_TRANSFORM_NONE;
3428 if (matrices & (TEXMAT0_CHANGED|TEXMAT1_CHANGED|TEXMAT2_CHANGED|TEXMAT3_CHANGED|
3429 TEXMAT4_CHANGED|TEXMAT5_CHANGED|TEXMAT6_CHANGED|TEXMAT7_CHANGED))
3432 for (tex_mat = TEXMAT0_CHANGED, tex_stage = 0; tex_mat <= TEXMAT7_CHANGED; tex_mat <<= 1, tex_stage++) {
3433 GLenum unit = GL_TEXTURE0_WINE + tex_stage;
3434 if (matrices & tex_mat) {
3435 if (This->state_block.texture_stage_state[tex_stage][D3DTSS_TEXTURETRANSFORMFLAGS - 1] != D3DTTFF_DISABLE) {
3436 int is_identity = (memcmp(This->tex_mat[tex_stage], id_mat, 16 * sizeof(D3DVALUE)) != 0);
3438 if (This->tex_mat_is_identity[tex_stage] != is_identity) {
3439 if (glThis->current_active_tex_unit != unit) {
3440 GL_extensions.glActiveTexture(unit);
3441 glThis->current_active_tex_unit = unit;
3443 glMatrixMode(GL_TEXTURE);
3444 glLoadMatrixf((float *) This->tex_mat[tex_stage]);
3446 This->tex_mat_is_identity[tex_stage] = is_identity;
3448 if (This->tex_mat_is_identity[tex_stage] == FALSE) {
3449 if (glThis->current_active_tex_unit != unit) {
3450 GL_extensions.glActiveTexture(unit);
3451 glThis->current_active_tex_unit = unit;
3453 glMatrixMode(GL_TEXTURE);
3455 This->tex_mat_is_identity[tex_stage] = TRUE;
3464 /* TODO for both these functions :
3465 - change / restore OpenGL parameters for pictures transfers in case they are ever modified
3466 by other OpenGL code in D3D
3467 - handle the case where no 'Begin / EndScene' was done between two locks
3468 - handle the rectangles in the unlock too
3469 - handle pitch correctly...
3471 static void d3ddevice_lock_update(IDirectDrawSurfaceImpl* This, LPCRECT pRect, DWORD dwFlags)
3473 IDirect3DDeviceImpl *d3d_dev = This->d3ddevice;
3474 IDirect3DDeviceGLImpl* gl_d3d_dev = (IDirect3DDeviceGLImpl*) d3d_dev;
3475 WINE_GL_BUFFER_TYPE buffer_type;
3478 if ((This->surface_desc.ddsCaps.dwCaps & (DDSCAPS_FRONTBUFFER|DDSCAPS_PRIMARYSURFACE)) != 0) {
3479 buffer_type = WINE_GL_BUFFER_FRONT;
3480 if ((gl_d3d_dev->state[WINE_GL_BUFFER_FRONT] != SURFACE_GL) &&
3481 (gl_d3d_dev->lock_surf[WINE_GL_BUFFER_FRONT] != This)) {
3482 ERR("Change of front buffer.. Expect graphic corruptions !\n");
3484 gl_d3d_dev->lock_surf[WINE_GL_BUFFER_FRONT] = This;
3485 } else if ((This->surface_desc.ddsCaps.dwCaps & (DDSCAPS_BACKBUFFER)) == (DDSCAPS_BACKBUFFER)) {
3486 buffer_type = WINE_GL_BUFFER_BACK;
3487 if ((gl_d3d_dev->state[WINE_GL_BUFFER_BACK] != SURFACE_GL) &&
3488 (gl_d3d_dev->lock_surf[WINE_GL_BUFFER_BACK] != This)) {
3489 ERR("Change of back buffer.. Expect graphic corruptions !\n");
3491 gl_d3d_dev->lock_surf[WINE_GL_BUFFER_BACK] = This;
3493 ERR("Wrong surface type for locking !\n");
3497 if (pRect == NULL) {
3500 loc_rect.bottom = This->surface_desc.dwHeight;
3501 loc_rect.right = This->surface_desc.dwWidth;
3505 /* Try to acquire the device critical section */
3506 EnterCriticalSection(&(d3d_dev->crit));
3508 if (gl_d3d_dev->lock_rect_valid[buffer_type] == TRUE) {
3509 ERR("Two consecutive locks on %s buffer... Expect problems !\n",
3510 (buffer_type == WINE_GL_BUFFER_BACK ? "back" : "front"));
3512 gl_d3d_dev->lock_rect_valid[buffer_type] = TRUE;
3514 if (gl_d3d_dev->state[buffer_type] != SURFACE_GL) {
3515 /* Check if the new rectangle is in the previous one or not.
3516 If it is not, flush first the previous locks on screen.
3518 if ((pRect->top < gl_d3d_dev->lock_rect[buffer_type].top) ||
3519 (pRect->left < gl_d3d_dev->lock_rect[buffer_type].left) ||
3520 (pRect->right > gl_d3d_dev->lock_rect[buffer_type].right) ||
3521 (pRect->bottom > gl_d3d_dev->lock_rect[buffer_type].bottom)) {
3522 if (gl_d3d_dev->state[buffer_type] == SURFACE_MEMORY_DIRTY) {
3523 TRACE(" flushing back to %s buffer as new rect : (%ldx%ld) - (%ldx%ld) not included in old rect : (%ldx%ld) - (%ldx%ld)\n",
3524 (buffer_type == WINE_GL_BUFFER_BACK ? "back" : "front"),
3525 pRect->left, pRect->top, pRect->right, pRect->bottom,
3526 gl_d3d_dev->lock_rect[buffer_type].left, gl_d3d_dev->lock_rect[buffer_type].top,
3527 gl_d3d_dev->lock_rect[buffer_type].right, gl_d3d_dev->lock_rect[buffer_type].bottom);
3528 d3d_dev->flush_to_framebuffer(d3d_dev, &(gl_d3d_dev->lock_rect[buffer_type]), gl_d3d_dev->lock_surf[buffer_type]);
3530 gl_d3d_dev->state[buffer_type] = SURFACE_GL;
3531 gl_d3d_dev->lock_rect[buffer_type] = *pRect;
3533 /* In the other case, do not upgrade the locking rectangle as it's no need... */
3535 gl_d3d_dev->lock_rect[buffer_type] = *pRect;
3538 if (gl_d3d_dev->state[buffer_type] == SURFACE_GL) {
3539 /* If the surface is already in memory, no need to do anything here... */
3540 GLenum buffer_format;
3541 GLenum buffer_color;
3545 TRACE(" copying %s buffer to main memory with rectangle (%ldx%ld) - (%ldx%ld).\n", (buffer_type == WINE_GL_BUFFER_BACK ? "back" : "front"),
3546 pRect->left, pRect->top, pRect->right, pRect->bottom);
3548 /* Note that here we cannot do 'optmizations' about the WriteOnly flag... Indeed, a game
3549 may only write to the device... But when we will blit it back to the screen, we need
3550 also to blit correctly the parts the application did not overwrite... */
3552 if (((This->surface_desc.u4.ddpfPixelFormat.dwFlags & DDPF_RGB) != 0) &&
3553 (((This->surface_desc.u4.ddpfPixelFormat.dwFlags & DDPF_ALPHAPIXELS) == 0) ||
3554 (This->surface_desc.u4.ddpfPixelFormat.u5.dwRGBAlphaBitMask == 0x00000000))) {
3555 if ((This->surface_desc.u4.ddpfPixelFormat.u1.dwRGBBitCount == 16) &&
3556 (This->surface_desc.u4.ddpfPixelFormat.u2.dwRBitMask == 0xF800) &&
3557 (This->surface_desc.u4.ddpfPixelFormat.u3.dwGBitMask == 0x07E0) &&
3558 (This->surface_desc.u4.ddpfPixelFormat.u4.dwBBitMask == 0x001F)) {
3559 buffer_format = GL_UNSIGNED_SHORT_5_6_5;
3560 buffer_color = GL_RGB;
3561 } else if ((This->surface_desc.u4.ddpfPixelFormat.u1.dwRGBBitCount == 24) &&
3562 (This->surface_desc.u4.ddpfPixelFormat.u2.dwRBitMask == 0xFF0000) &&
3563 (This->surface_desc.u4.ddpfPixelFormat.u3.dwGBitMask == 0x00FF00) &&
3564 (This->surface_desc.u4.ddpfPixelFormat.u4.dwBBitMask == 0x0000FF)) {
3565 buffer_format = GL_UNSIGNED_BYTE;
3566 buffer_color = GL_RGB;
3567 } else if ((This->surface_desc.u4.ddpfPixelFormat.u1.dwRGBBitCount == 32) &&
3568 (This->surface_desc.u4.ddpfPixelFormat.u2.dwRBitMask == 0x00FF0000) &&
3569 (This->surface_desc.u4.ddpfPixelFormat.u3.dwGBitMask == 0x0000FF00) &&
3570 (This->surface_desc.u4.ddpfPixelFormat.u4.dwBBitMask == 0x000000FF)) {
3571 buffer_format = GL_UNSIGNED_INT_8_8_8_8_REV;
3572 buffer_color = GL_BGRA;
3574 ERR(" unsupported pixel format at device locking.\n");
3578 ERR(" unsupported pixel format at device locking - alpha on frame buffer.\n");
3584 if (buffer_type == WINE_GL_BUFFER_FRONT)
3585 /* Application wants to lock the front buffer */
3586 glReadBuffer(GL_FRONT);
3588 /* Application wants to lock the back buffer */
3589 glReadBuffer(GL_BACK);
3591 dst = ((char *)This->surface_desc.lpSurface) +
3592 (pRect->top * This->surface_desc.u1.lPitch) + (pRect->left * GET_BPP(This->surface_desc));
3593 for (y = (This->surface_desc.dwHeight - pRect->top - 1);
3594 y >= ((int) This->surface_desc.dwHeight - (int) pRect->bottom);
3596 glReadPixels(pRect->left, y,
3597 pRect->right - pRect->left, 1,
3598 buffer_color, buffer_format, dst);
3599 dst += This->surface_desc.u1.lPitch;
3602 gl_d3d_dev->state[buffer_type] = SURFACE_MEMORY;
3605 /* I keep this code here as it's very useful to debug :-) */
3607 static int flush_count = 0;
3611 if ((++flush_count % 50) == 0) {
3612 sprintf(buf, "lock_%06d.pnm", flush_count);
3613 f = fopen(buf, "wb");
3614 DDRAW_dump_surface_to_disk(This, f);
3623 static void d3ddevice_flush_to_frame_buffer(IDirect3DDeviceImpl *d3d_dev, LPCRECT pRect, IDirectDrawSurfaceImpl *surf) {
3625 IDirect3DDeviceGLImpl* gl_d3d_dev = (IDirect3DDeviceGLImpl*) d3d_dev;
3630 /* Note : no need here to lock the 'device critical section' as we are already protected by
3631 the GL critical section. */
3633 if (pRect == NULL) {
3636 loc_rect.bottom = d3d_dev->surface->surface_desc.dwHeight;
3637 loc_rect.right = d3d_dev->surface->surface_desc.dwWidth;
3641 TRACE(" flushing memory back to screen memory (%ld,%ld) x (%ld,%ld).\n", pRect->top, pRect->left, pRect->right, pRect->bottom);
3643 opt_bitmap = d3ddevice_set_state_for_flush(d3d_dev, pRect, FALSE, &initial);
3645 if (upload_surface_to_tex_memory_init(surf, 0, &gl_d3d_dev->current_internal_format,
3646 initial, FALSE, UNLOCK_TEX_SIZE, UNLOCK_TEX_SIZE) != DD_OK) {
3647 ERR(" unsupported pixel format at frame buffer flush.\n");
3651 for (y = pRect->top; y < pRect->bottom; y += UNLOCK_TEX_SIZE) {
3655 flush_rect.bottom = (y + UNLOCK_TEX_SIZE > pRect->bottom) ? pRect->bottom : (y + UNLOCK_TEX_SIZE);
3657 for (x = pRect->left; x < pRect->right; x += UNLOCK_TEX_SIZE) {
3658 /* First, upload the texture... */
3659 flush_rect.left = x;
3660 flush_rect.right = (x + UNLOCK_TEX_SIZE > pRect->right) ? pRect->right : (x + UNLOCK_TEX_SIZE);
3662 upload_surface_to_tex_memory(&flush_rect, 0, 0, &(gl_d3d_dev->surface_ptr));
3665 glTexCoord2f(0.0, 0.0);
3666 glVertex3d(x, y, 0.5);
3667 glTexCoord2f(1.0, 0.0);
3668 glVertex3d(x + UNLOCK_TEX_SIZE, y, 0.5);
3669 glTexCoord2f(1.0, 1.0);
3670 glVertex3d(x + UNLOCK_TEX_SIZE, y + UNLOCK_TEX_SIZE, 0.5);
3671 glTexCoord2f(0.0, 1.0);
3672 glVertex3d(x, y + UNLOCK_TEX_SIZE, 0.5);
3677 upload_surface_to_tex_memory_release();
3678 d3ddevice_restore_state_after_flush(d3d_dev, opt_bitmap, FALSE);
3681 /* I keep this code here as it's very useful to debug :-) */
3683 static int flush_count = 0;
3687 if ((++flush_count % 50) == 0) {
3688 sprintf(buf, "flush_%06d.pnm", flush_count);
3689 f = fopen(buf, "wb");
3690 DDRAW_dump_surface_to_disk(surf, f);
3696 static void d3ddevice_unlock_update(IDirectDrawSurfaceImpl* This, LPCRECT pRect)
3698 WINE_GL_BUFFER_TYPE buffer_type;
3699 IDirect3DDeviceImpl *d3d_dev = This->d3ddevice;
3700 IDirect3DDeviceGLImpl* gl_d3d_dev = (IDirect3DDeviceGLImpl*) d3d_dev;
3702 if ((This->surface_desc.ddsCaps.dwCaps & (DDSCAPS_FRONTBUFFER|DDSCAPS_PRIMARYSURFACE)) != 0) {
3703 buffer_type = WINE_GL_BUFFER_FRONT;
3704 } else if ((This->surface_desc.ddsCaps.dwCaps & (DDSCAPS_BACKBUFFER)) == (DDSCAPS_BACKBUFFER)) {
3705 buffer_type = WINE_GL_BUFFER_BACK;
3707 ERR("Wrong surface type for locking !\n");
3711 if (gl_d3d_dev->lock_rect_valid[buffer_type] == FALSE) {
3712 ERR("Unlock without prior lock on %s buffer... Expect problems !\n",
3713 (buffer_type == WINE_GL_BUFFER_BACK ? "back" : "front"));
3715 gl_d3d_dev->lock_rect_valid[buffer_type] = FALSE;
3717 /* First, check if we need to do anything. For the backbuffer, flushing is done at the next 3D activity. */
3718 if ((This->lastlocktype & DDLOCK_READONLY) == 0) {
3719 if (buffer_type == WINE_GL_BUFFER_FRONT) {
3722 TRACE(" flushing front buffer immediatly on screen.\n");
3725 glGetIntegerv(GL_DRAW_BUFFER, &prev_draw);
3726 glDrawBuffer(GL_FRONT);
3727 /* Note: we do not use the application provided lock rectangle but our own stored at
3728 lock time. This is because in old D3D versions, the 'lock' parameter did not
3731 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]);
3732 glDrawBuffer(prev_draw);
3735 gl_d3d_dev->state[WINE_GL_BUFFER_BACK] = SURFACE_MEMORY_DIRTY;
3739 /* And 'frees' the device critical section */
3740 LeaveCriticalSection(&(d3d_dev->crit));
3744 apply_texture_state(IDirect3DDeviceImpl *This)
3748 /* Initialize texture stages states */
3749 for (stage = 0; stage < MAX_TEXTURES; stage++) {
3750 for (state = 0; state < HIGHEST_TEXTURE_STAGE_STATE; state += 1) {
3751 if (This->state_block.set_flags.texture_stage_state[stage][state] == TRUE) {
3752 IDirect3DDevice7_SetTextureStageState(ICOM_INTERFACE(This, IDirect3DDevice7),
3753 stage, state + 1, This->state_block.texture_stage_state[stage][state]);
3760 d3ddevice_create(IDirect3DDeviceImpl **obj, IDirectDrawImpl *d3d, IDirectDrawSurfaceImpl *surface, BOOLEAN from_surface)
3762 IDirect3DDeviceImpl *object;
3763 IDirect3DDeviceGLImpl *gl_object;
3764 IDirectDrawSurfaceImpl *surf;
3769 XVisualInfo template;
3770 GLenum buffer = GL_FRONT;
3773 object = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(IDirect3DDeviceGLImpl));
3774 if (object == NULL) return DDERR_OUTOFMEMORY;
3776 gl_object = (IDirect3DDeviceGLImpl *) object;
3780 object->surface = surface;
3781 object->set_context = set_context;
3782 object->clear = d3ddevice_clear_back;
3783 object->set_matrices = d3ddevice_set_matrices;
3784 object->matrices_updated = d3ddevice_matrices_updated;
3785 object->flush_to_framebuffer = d3ddevice_flush_to_frame_buffer;
3787 TRACE(" creating OpenGL device for surface = %p, d3d = %p\n", surface, d3d);
3789 InitializeCriticalSection(&(object->crit));
3791 TRACE(" device critical section : %p\n", &(object->crit));
3793 /* This is just a hack for some badly done games :-/ */
3795 gl_object->version = 1;
3796 TRACE(" using D3D1 special hacks.\n");
3798 gl_object->version = 7;
3800 device_context = GetDC(surface->ddraw_owner->window);
3801 gl_object->display = get_display(device_context);
3802 gl_object->drawable = get_drawable(device_context);
3803 ReleaseDC(surface->ddraw_owner->window,device_context);
3806 template.visualid = (VisualID)GetPropA( GetDesktopWindow(), "__wine_x11_visual_id" );
3807 vis = XGetVisualInfo(gl_object->display, VisualIDMask, &template, &num);
3809 HeapFree(GetProcessHeap(), 0, object);
3810 ERR("No visual found !\n");
3812 return DDERR_INVALIDPARAMS;
3814 TRACE(" visual found\n");
3817 gl_object->gl_context = glXCreateContext(gl_object->display, vis,
3820 if (gl_object->gl_context == NULL) {
3821 HeapFree(GetProcessHeap(), 0, object);
3822 ERR("Error in context creation !\n");
3824 return DDERR_INVALIDPARAMS;
3826 TRACE(" context created (%p)\n", gl_object->gl_context);
3829 /* Look for the front buffer and override its surface's Flip method (if in double buffering) */
3830 for (surf = surface; surf != NULL; surf = surf->surface_owner) {
3831 if ((surf->surface_desc.ddsCaps.dwCaps&(DDSCAPS_FLIP|DDSCAPS_FRONTBUFFER)) == (DDSCAPS_FLIP|DDSCAPS_FRONTBUFFER)) {
3832 surf->aux_ctx = (LPVOID) object;
3833 surf->aux_data = (LPVOID) gl_object->drawable;
3834 surf->aux_flip = opengl_flip;
3839 /* We are not doing any double buffering.. Then force OpenGL to draw on the front buffer */
3841 TRACE(" no double buffering : drawing on the front buffer\n");
3845 for (surf = surface; surf != NULL; surf = surf->surface_owner) {
3846 IDirectDrawSurfaceImpl *surf2;
3847 for (surf2 = surf; surf2->prev_attached != NULL; surf2 = surf2->prev_attached) ;
3848 for (; surf2 != NULL; surf2 = surf2->next_attached) {
3849 TRACE(" checking surface %p :", surf2);
3850 if (((surf2->surface_desc.ddsCaps.dwCaps & (DDSCAPS_3DDEVICE)) == (DDSCAPS_3DDEVICE)) &&
3851 ((surf2->surface_desc.ddsCaps.dwCaps & (DDSCAPS_ZBUFFER)) != (DDSCAPS_ZBUFFER))) {
3852 /* Override the Lock / Unlock function for all these surfaces */
3853 surf2->lock_update_prev = surf2->lock_update;
3854 surf2->lock_update = d3ddevice_lock_update;
3855 surf2->unlock_update_prev = surf2->unlock_update;
3856 surf2->unlock_update = d3ddevice_unlock_update;
3857 /* And install also the blt / bltfast overrides */
3858 surf2->aux_blt = d3ddevice_blt;
3859 surf2->aux_bltfast = d3ddevice_bltfast;
3861 TRACE(" overiding direct surface access.\n");
3863 TRACE(" no overide.\n");
3865 surf2->d3ddevice = object;
3869 /* Set the various light parameters */
3870 for (light = 0; light < MAX_LIGHTS; light++) {
3871 /* Only set the fields that are not zero-created */
3872 object->light_parameters[light].dltType = D3DLIGHT_DIRECTIONAL;
3873 object->light_parameters[light].dcvDiffuse.u1.r = 1.0;
3874 object->light_parameters[light].dcvDiffuse.u2.g = 1.0;
3875 object->light_parameters[light].dcvDiffuse.u3.b = 1.0;
3876 object->light_parameters[light].dvDirection.u3.z = 1.0;
3879 /* Allocate memory for the matrices */
3880 object->world_mat = (D3DMATRIX *) HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, 16 * sizeof(float));
3881 object->view_mat = (D3DMATRIX *) HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, 16 * sizeof(float));
3882 object->proj_mat = (D3DMATRIX *) HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, 16 * sizeof(float));
3883 memcpy(object->world_mat, id_mat, 16 * sizeof(float));
3884 memcpy(object->view_mat , id_mat, 16 * sizeof(float));
3885 memcpy(object->proj_mat , id_mat, 16 * sizeof(float));
3886 for (tex_num = 0; tex_num < MAX_TEXTURES; tex_num++) {
3887 object->tex_mat[tex_num] = (D3DMATRIX *) HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, 16 * sizeof(float));
3888 memcpy(object->tex_mat[tex_num], id_mat, 16 * sizeof(float));
3889 object->tex_mat_is_identity[tex_num] = TRUE;
3892 /* Initialisation */
3893 TRACE(" setting current context\n");
3894 object->set_context(object);
3895 TRACE(" current context set\n");
3897 /* allocate the clipping planes */
3898 object->max_clipping_planes = opengl_device_caps.wMaxUserClipPlanes;
3899 object->clipping_planes = (d3d7clippingplane*)HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, object->max_clipping_planes * sizeof(d3d7clippingplane));
3901 glHint(GL_FOG_HINT,GL_NICEST);
3903 /* Initialize the various GL contexts to be in sync with what we store locally */
3906 glClearColor(0.0, 0.0, 0.0, 0.0);
3907 glDepthMask(GL_TRUE);
3908 gl_object->depth_mask = TRUE;
3909 glEnable(GL_DEPTH_TEST);
3910 gl_object->depth_test = TRUE;
3911 glDisable(GL_ALPHA_TEST);
3912 glDisable(GL_STENCIL_TEST);
3913 glDisable(GL_CULL_FACE);
3914 glDisable(GL_LIGHTING);
3915 glDisable(GL_BLEND);
3917 glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);
3918 gl_object->current_tex_env = GL_REPLACE;
3919 gl_object->current_active_tex_unit = GL_TEXTURE0_WINE;
3920 if (GL_extensions.glActiveTexture != NULL) {
3921 GL_extensions.glActiveTexture(GL_TEXTURE0_WINE);
3923 gl_object->current_alpha_test_ref = 0.0;
3924 gl_object->current_alpha_test_func = GL_ALWAYS;
3925 glAlphaFunc(GL_ALWAYS, 0.0);
3927 glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
3928 glDrawBuffer(buffer);
3929 glReadBuffer(buffer);
3930 /* glDisable(GL_DEPTH_TEST); Need here to check for the presence of a ZBuffer and to reenable it when the ZBuffer is attached */
3933 gl_object->state[WINE_GL_BUFFER_BACK] = SURFACE_GL;
3934 gl_object->state[WINE_GL_BUFFER_FRONT] = SURFACE_GL;
3936 /* fill_device_capabilities(d3d->ddraw); */
3938 ICOM_INIT_INTERFACE(object, IDirect3DDevice, VTABLE_IDirect3DDevice);
3939 ICOM_INIT_INTERFACE(object, IDirect3DDevice2, VTABLE_IDirect3DDevice2);
3940 ICOM_INIT_INTERFACE(object, IDirect3DDevice3, VTABLE_IDirect3DDevice3);
3941 ICOM_INIT_INTERFACE(object, IDirect3DDevice7, VTABLE_IDirect3DDevice7);
3945 TRACE(" creating implementation at %p.\n", *obj);
3947 /* And finally warn D3D that this device is now present */
3948 object->d3d->d3d_added_device(object->d3d, object);
3950 /* FIXME: Should handle other versions than just 7 */
3951 InitDefaultStateBlock(&object->state_block, 7);
3952 /* Apply default render state and texture stage state values */
3953 apply_render_state(object, &object->state_block);
3954 apply_texture_state(object);
3956 /* And fill the fog table with the default fog value */
3957 build_fog_table(gl_object->fog_table, object->state_block.render_state[D3DRENDERSTATE_FOGCOLOR - 1]);
3962 static void fill_opengl_primcaps(D3DPRIMCAPS *pc)
3964 pc->dwSize = sizeof(*pc);
3965 pc->dwMiscCaps = D3DPMISCCAPS_CONFORMANT | D3DPMISCCAPS_CULLCCW | D3DPMISCCAPS_CULLCW |
3966 D3DPMISCCAPS_LINEPATTERNREP | D3DPMISCCAPS_MASKPLANES | D3DPMISCCAPS_MASKZ;
3967 pc->dwRasterCaps = D3DPRASTERCAPS_DITHER | D3DPRASTERCAPS_FOGRANGE | D3DPRASTERCAPS_FOGTABLE |
3968 D3DPRASTERCAPS_FOGVERTEX | D3DPRASTERCAPS_STIPPLE | D3DPRASTERCAPS_ZBIAS | D3DPRASTERCAPS_ZTEST | D3DPRASTERCAPS_SUBPIXEL |
3969 D3DPRASTERCAPS_ZFOG;
3970 if (GL_extensions.mipmap_lodbias == TRUE) {
3971 pc->dwRasterCaps |= D3DPRASTERCAPS_MIPMAPLODBIAS;
3973 pc->dwZCmpCaps = D3DPCMPCAPS_ALWAYS | D3DPCMPCAPS_EQUAL | D3DPCMPCAPS_GREATER | D3DPCMPCAPS_GREATEREQUAL |
3974 D3DPCMPCAPS_LESS | D3DPCMPCAPS_LESSEQUAL | D3DPCMPCAPS_NEVER | D3DPCMPCAPS_NOTEQUAL;
3975 pc->dwSrcBlendCaps = D3DPBLENDCAPS_ZERO | D3DPBLENDCAPS_ONE | D3DPBLENDCAPS_DESTCOLOR | D3DPBLENDCAPS_INVDESTCOLOR |
3976 D3DPBLENDCAPS_SRCALPHA | D3DPBLENDCAPS_INVSRCALPHA | D3DPBLENDCAPS_DESTALPHA | D3DPBLENDCAPS_INVDESTALPHA | D3DPBLENDCAPS_SRCALPHASAT |
3977 D3DPBLENDCAPS_BOTHSRCALPHA | D3DPBLENDCAPS_BOTHINVSRCALPHA;
3978 pc->dwDestBlendCaps = D3DPBLENDCAPS_ZERO | D3DPBLENDCAPS_ONE | D3DPBLENDCAPS_SRCCOLOR | D3DPBLENDCAPS_INVSRCCOLOR |
3979 D3DPBLENDCAPS_SRCALPHA | D3DPBLENDCAPS_INVSRCALPHA | D3DPBLENDCAPS_DESTALPHA | D3DPBLENDCAPS_INVDESTALPHA | D3DPBLENDCAPS_SRCALPHASAT |
3980 D3DPBLENDCAPS_BOTHSRCALPHA | D3DPBLENDCAPS_BOTHINVSRCALPHA;
3981 pc->dwAlphaCmpCaps = D3DPCMPCAPS_ALWAYS | D3DPCMPCAPS_EQUAL | D3DPCMPCAPS_GREATER | D3DPCMPCAPS_GREATEREQUAL |
3982 D3DPCMPCAPS_LESS | D3DPCMPCAPS_LESSEQUAL | D3DPCMPCAPS_NEVER | D3DPCMPCAPS_NOTEQUAL;
3983 pc->dwShadeCaps = D3DPSHADECAPS_ALPHAFLATBLEND | D3DPSHADECAPS_ALPHAGOURAUDBLEND | D3DPSHADECAPS_COLORFLATRGB | D3DPSHADECAPS_COLORGOURAUDRGB |
3984 D3DPSHADECAPS_FOGFLAT | D3DPSHADECAPS_FOGGOURAUD | D3DPSHADECAPS_SPECULARFLATRGB | D3DPSHADECAPS_SPECULARGOURAUDRGB;
3985 pc->dwTextureCaps = D3DPTEXTURECAPS_ALPHA | D3DPTEXTURECAPS_ALPHAPALETTE | D3DPTEXTURECAPS_BORDER | D3DPTEXTURECAPS_PERSPECTIVE |
3986 D3DPTEXTURECAPS_POW2 | D3DPTEXTURECAPS_TRANSPARENCY;
3987 pc->dwTextureFilterCaps = D3DPTFILTERCAPS_LINEAR | D3DPTFILTERCAPS_LINEARMIPLINEAR | D3DPTFILTERCAPS_LINEARMIPNEAREST |
3988 D3DPTFILTERCAPS_MIPLINEAR | D3DPTFILTERCAPS_MIPNEAREST | D3DPTFILTERCAPS_NEAREST | D3DPTFILTERCAPS_MAGFLINEAR |
3989 D3DPTFILTERCAPS_MAGFPOINT | D3DPTFILTERCAPS_MINFLINEAR | D3DPTFILTERCAPS_MINFPOINT | D3DPTFILTERCAPS_MIPFLINEAR |
3990 D3DPTFILTERCAPS_MIPFPOINT;
3991 pc->dwTextureBlendCaps = D3DPTBLENDCAPS_ADD | D3DPTBLENDCAPS_COPY | D3DPTBLENDCAPS_DECAL | D3DPTBLENDCAPS_DECALALPHA | D3DPTBLENDCAPS_DECALMASK |
3992 D3DPTBLENDCAPS_MODULATE | D3DPTBLENDCAPS_MODULATEALPHA | D3DPTBLENDCAPS_MODULATEMASK;
3993 pc->dwTextureAddressCaps = D3DPTADDRESSCAPS_BORDER | D3DPTADDRESSCAPS_CLAMP | D3DPTADDRESSCAPS_WRAP | D3DPTADDRESSCAPS_INDEPENDENTUV;
3994 if (GL_extensions.mirrored_repeat == TRUE) {
3995 pc->dwTextureAddressCaps |= D3DPTADDRESSCAPS_MIRROR;
3997 pc->dwStippleWidth = 32;
3998 pc->dwStippleHeight = 32;
4001 static void fill_caps(void)
4003 GLint max_clip_planes;
4006 /* Fill first all the fields with default values which will be overriden later on with
4007 correct ones from the GL code
4009 opengl_device_caps.dwDevCaps = D3DDEVCAPS_CANRENDERAFTERFLIP | D3DDEVCAPS_DRAWPRIMTLVERTEX | D3DDEVCAPS_EXECUTESYSTEMMEMORY |
4010 D3DDEVCAPS_EXECUTEVIDEOMEMORY | D3DDEVCAPS_FLOATTLVERTEX | D3DDEVCAPS_TEXTURENONLOCALVIDMEM | D3DDEVCAPS_TEXTURESYSTEMMEMORY |
4011 D3DDEVCAPS_TEXTUREVIDEOMEMORY | D3DDEVCAPS_TLVERTEXSYSTEMMEMORY | D3DDEVCAPS_TLVERTEXVIDEOMEMORY |
4012 /* D3D 7 capabilities */
4013 D3DDEVCAPS_DRAWPRIMITIVES2 | D3DDEVCAPS_HWTRANSFORMANDLIGHT | D3DDEVCAPS_HWRASTERIZATION;
4014 fill_opengl_primcaps(&(opengl_device_caps.dpcLineCaps));
4015 fill_opengl_primcaps(&(opengl_device_caps.dpcTriCaps));
4016 opengl_device_caps.dwDeviceRenderBitDepth = DDBD_16|DDBD_24|DDBD_32;
4017 opengl_device_caps.dwMinTextureWidth = 1;
4018 opengl_device_caps.dwMinTextureHeight = 1;
4019 opengl_device_caps.dwMaxTextureWidth = 1024;
4020 opengl_device_caps.dwMaxTextureHeight = 1024;
4021 opengl_device_caps.dwMaxTextureRepeat = 16;
4022 opengl_device_caps.dwMaxTextureAspectRatio = 1024;
4023 opengl_device_caps.dwMaxAnisotropy = 0;
4024 opengl_device_caps.dvGuardBandLeft = 0.0;
4025 opengl_device_caps.dvGuardBandRight = 0.0;
4026 opengl_device_caps.dvGuardBandTop = 0.0;
4027 opengl_device_caps.dvGuardBandBottom = 0.0;
4028 opengl_device_caps.dvExtentsAdjust = 0.0;
4029 opengl_device_caps.dwStencilCaps = D3DSTENCILCAPS_DECRSAT | D3DSTENCILCAPS_INCRSAT | D3DSTENCILCAPS_INVERT | D3DSTENCILCAPS_KEEP |
4030 D3DSTENCILCAPS_REPLACE | D3DSTENCILCAPS_ZERO;
4031 opengl_device_caps.dwTextureOpCaps = D3DTEXOPCAPS_DISABLE | D3DTEXOPCAPS_SELECTARG1 | D3DTEXOPCAPS_SELECTARG2 | D3DTEXOPCAPS_MODULATE4X |
4032 D3DTEXOPCAPS_MODULATE2X | D3DTEXOPCAPS_MODULATE | D3DTEXOPCAPS_ADD | D3DTEXOPCAPS_ADDSIGNED2X | D3DTEXOPCAPS_ADDSIGNED |
4033 D3DTEXOPCAPS_BLENDDIFFUSEALPHA | D3DTEXOPCAPS_BLENDTEXTUREALPHA | D3DTEXOPCAPS_BLENDFACTORALPHA | D3DTEXOPCAPS_BLENDCURRENTALPHA;
4034 if (GL_extensions.max_texture_units != 0) {
4035 opengl_device_caps.wMaxTextureBlendStages = GL_extensions.max_texture_units;
4036 opengl_device_caps.wMaxSimultaneousTextures = GL_extensions.max_texture_units;
4037 opengl_device_caps.dwFVFCaps = D3DFVFCAPS_DONOTSTRIPELEMENTS | GL_extensions.max_texture_units;
4039 opengl_device_caps.wMaxTextureBlendStages = 1;
4040 opengl_device_caps.wMaxSimultaneousTextures = 1;
4041 opengl_device_caps.dwFVFCaps = D3DFVFCAPS_DONOTSTRIPELEMENTS | 1;
4043 opengl_device_caps.dwMaxActiveLights = 16;
4044 opengl_device_caps.dvMaxVertexW = 100000000.0; /* No idea exactly what to put here... */
4045 opengl_device_caps.deviceGUID = IID_IDirect3DTnLHalDevice;
4046 opengl_device_caps.wMaxUserClipPlanes = 1;
4047 opengl_device_caps.wMaxVertexBlendMatrices = 0;
4048 opengl_device_caps.dwVertexProcessingCaps = D3DVTXPCAPS_TEXGEN | D3DVTXPCAPS_MATERIALSOURCE7 | D3DVTXPCAPS_VERTEXFOG |
4049 D3DVTXPCAPS_DIRECTIONALLIGHTS | D3DVTXPCAPS_POSITIONALLIGHTS | D3DVTXPCAPS_LOCALVIEWER;
4050 opengl_device_caps.dwReserved1 = 0;
4051 opengl_device_caps.dwReserved2 = 0;
4052 opengl_device_caps.dwReserved3 = 0;
4053 opengl_device_caps.dwReserved4 = 0;
4055 /* And now some GL overides :-) */
4056 glGetIntegerv(GL_MAX_TEXTURE_SIZE, (GLint *) &opengl_device_caps.dwMaxTextureWidth);
4057 opengl_device_caps.dwMaxTextureHeight = opengl_device_caps.dwMaxTextureWidth;
4058 opengl_device_caps.dwMaxTextureAspectRatio = opengl_device_caps.dwMaxTextureWidth;
4059 TRACE(": max texture size = %ld\n", opengl_device_caps.dwMaxTextureWidth);
4061 glGetIntegerv(GL_MAX_LIGHTS, (GLint *) &opengl_device_caps.dwMaxActiveLights);
4062 TRACE(": max active lights = %ld\n", opengl_device_caps.dwMaxActiveLights);
4064 glGetIntegerv(GL_MAX_CLIP_PLANES, &max_clip_planes);
4065 opengl_device_caps.wMaxUserClipPlanes = max_clip_planes;
4066 TRACE(": max clipping planes = %d\n", opengl_device_caps.wMaxUserClipPlanes);
4068 glGetIntegerv(GL_DEPTH_BITS, &depth_bits);
4069 TRACE(": Z bits = %d\n", depth_bits);
4070 switch (depth_bits) {
4071 case 16: opengl_device_caps.dwDeviceZBufferBitDepth = DDBD_16; break;
4072 case 24: opengl_device_caps.dwDeviceZBufferBitDepth = DDBD_16|DDBD_24; break;
4074 default: opengl_device_caps.dwDeviceZBufferBitDepth = DDBD_16|DDBD_24|DDBD_32; break;
4079 d3ddevice_init_at_startup(void *gl_handle)
4081 XVisualInfo template;
4086 Drawable drawable = (Drawable) GetPropA(GetDesktopWindow(), "__wine_x11_whole_window");
4087 XWindowAttributes win_attr;
4088 GLXContext gl_context;
4090 const char *glExtensions;
4091 const char *glVersion;
4092 const char *glXExtensions = NULL;
4093 const void *(*pglXGetProcAddressARB)(const GLubyte *) = NULL;
4094 int major, minor, patch, num_parsed;
4096 TRACE("Initializing GL...\n");
4098 /* Get a default rendering context to have the 'caps' function query some info from GL */
4099 device_context = GetDC(0);
4100 display = get_display(device_context);
4101 ReleaseDC(0, device_context);
4104 if (XGetWindowAttributes(display, drawable, &win_attr)) {
4105 visual = win_attr.visual;
4107 visual = DefaultVisual(display, DefaultScreen(display));
4109 template.visualid = XVisualIDFromVisual(visual);
4110 vis = XGetVisualInfo(display, VisualIDMask, &template, &num);
4113 WARN("Error creating visual info for capabilities initialization - D3D support disabled !\n");
4116 gl_context = glXCreateContext(display, vis, NULL, GL_TRUE);
4118 if (gl_context == NULL) {
4120 WARN("Error creating default context for capabilities initialization - D3D support disabled !\n");
4123 if (glXMakeCurrent(display, drawable, gl_context) == False) {
4124 glXDestroyContext(display, gl_context);
4126 WARN("Error setting default context as current for capabilities initialization - D3D support disabled !\n");
4130 /* Then, query all extensions */
4131 glXExtensions = glXQueryExtensionsString(display, DefaultScreen(display));
4132 glExtensions = (const char *) glGetString(GL_EXTENSIONS);
4133 glVersion = (const char *) glGetString(GL_VERSION);
4134 if ((glXExtensions != NULL) && (gl_handle != NULL) && (strstr(glXExtensions, "GLX_ARB_get_proc_address"))) {
4135 pglXGetProcAddressARB = wine_dlsym(gl_handle, "glXGetProcAddressARB", NULL, 0);
4138 /* Parse the GL version string */
4139 num_parsed = sscanf(glVersion, "%d.%d.%d", &major, &minor, &patch);
4140 if (num_parsed == 1) {
4143 } else if (num_parsed == 2) {
4146 TRACE("GL version %d.%d.%d\n", major, minor, patch);
4148 /* And starts to fill the extension context properly */
4149 memset(&GL_extensions, 0, sizeof(GL_extensions));
4150 TRACE("GL supports following extensions used by Wine :\n");
4152 /* Mirrored Repeat extension :
4153 - GL_ARB_texture_mirrored_repeat
4154 - GL_IBM_texture_mirrored_repeat
4157 if ((strstr(glExtensions, "GL_ARB_texture_mirrored_repeat")) ||
4158 (strstr(glExtensions, "GL_IBM_texture_mirrored_repeat")) ||
4160 ((major == 1) && (minor >= 4))) {
4161 TRACE(" - mirrored repeat\n");
4162 GL_extensions.mirrored_repeat = TRUE;
4165 /* Texture LOD Bias :
4166 - GL_EXT_texture_lod_bias
4168 if (strstr(glExtensions, "GL_EXT_texture_lod_bias")) {
4169 TRACE(" - texture lod bias\n");
4170 GL_extensions.mipmap_lodbias = TRUE;
4173 /* For all subsequent extensions, we need glXGetProcAddress */
4174 if (pglXGetProcAddressARB != NULL) {
4175 /* Multi-texturing :
4176 - GL_ARB_multitexture
4179 if ((strstr(glExtensions, "GL_ARB_multitexture")) ||
4181 ((major == 1) && (minor > 2)) ||
4182 ((major == 1) && (minor == 2) && (patch >= 1))) {
4183 glGetIntegerv(GL_MAX_TEXTURE_UNITS_WINE, &(GL_extensions.max_texture_units));
4184 TRACE(" - multi-texturing (%d stages)\n", GL_extensions.max_texture_units);
4185 /* We query the ARB version to be the most portable we can... */
4186 GL_extensions.glActiveTexture = pglXGetProcAddressARB("glActiveTextureARB");
4187 GL_extensions.glMultiTexCoord2fv = pglXGetProcAddressARB("glMultiTexCoord2fv");
4191 /* Fill the D3D capabilities according to what GL tells us... */
4194 /* And frees this now-useless context */
4195 glXMakeCurrent(display, None, NULL);
4196 glXDestroyContext(display, gl_context);