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 (((d3d_dev->state_block.render_state[D3DRENDERSTATE_ALPHAREF - 1] & 0x000000FF) != 0x00) ||
167 ((d3d_dev->state_block.render_state[D3DRENDERSTATE_ALPHAFUNC - 1]) != D3DCMP_GREATER)) {
168 glAlphaFunc(GL_GREATER, 0.0);
171 if (gl_d3d_dev->alpha_test != FALSE) glDisable(GL_ALPHA_TEST);
173 if (gl_d3d_dev->stencil_test != FALSE) glDisable(GL_STENCIL_TEST);
174 if (gl_d3d_dev->blending != FALSE) glDisable(GL_BLEND);
175 if (gl_d3d_dev->fogging != FALSE) glDisable(GL_FOG);
176 if (gl_d3d_dev->current_tex_env != GL_REPLACE)
177 glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);
182 static void d3ddevice_restore_state_after_flush(IDirect3DDeviceImpl *d3d_dev, DWORD opt_bitmap, BOOLEAN use_alpha) {
183 IDirect3DDeviceGLImpl* gl_d3d_dev = (IDirect3DDeviceGLImpl*) d3d_dev;
185 /* And restore all the various states modified by this code */
186 if (gl_d3d_dev->depth_test != 0) glEnable(GL_DEPTH_TEST);
187 if (gl_d3d_dev->lighting != 0) glEnable(GL_LIGHTING);
188 if ((gl_d3d_dev->alpha_test != 0) && (use_alpha == 0))
189 glEnable(GL_ALPHA_TEST);
190 else if ((gl_d3d_dev->alpha_test == 0) && (use_alpha != 0))
191 glDisable(GL_ALPHA_TEST);
193 if (((d3d_dev->state_block.render_state[D3DRENDERSTATE_ALPHAREF - 1] & 0x000000FF) != 0x00) ||
194 ((d3d_dev->state_block.render_state[D3DRENDERSTATE_ALPHAFUNC - 1]) != D3DCMP_GREATER)) {
195 glAlphaFunc(convert_D3D_compare_to_GL(d3d_dev->state_block.render_state[D3DRENDERSTATE_ALPHAFUNC - 1]),
196 (d3d_dev->state_block.render_state[D3DRENDERSTATE_ALPHAREF - 1] & 0x000000FF) / 255.0);
199 if (gl_d3d_dev->stencil_test != 0) glEnable(GL_STENCIL_TEST);
200 if (gl_d3d_dev->cull_face != 0) glEnable(GL_CULL_FACE);
201 if (gl_d3d_dev->blending != 0) glEnable(GL_BLEND);
202 if (gl_d3d_dev->fogging != 0) glEnable(GL_FOG);
203 glDisable(GL_SCISSOR_TEST);
204 glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, gl_d3d_dev->current_tex_env);
205 if (opt_bitmap & DEPTH_RANGE_BIT) {
206 glDepthRange(d3d_dev->active_viewport.dvMinZ, d3d_dev->active_viewport.dvMaxZ);
208 if (opt_bitmap & VIEWPORT_BIT) {
209 glViewport(d3d_dev->active_viewport.dwX,
210 d3d_dev->surface->surface_desc.dwHeight - (d3d_dev->active_viewport.dwHeight + d3d_dev->active_viewport.dwY),
211 d3d_dev->active_viewport.dwWidth, d3d_dev->active_viewport.dwHeight);
213 if (d3d_dev->tex_mat_is_identity[0] == FALSE) {
214 d3d_dev->matrices_updated(d3d_dev, TEXMAT0_CHANGED);
217 /* This is a hack to prevent querying the current texture from GL. Basically, at the next
218 DrawPrimitive call, this will bind the correct texture to this stage. */
219 gl_d3d_dev->current_bound_texture[0] = (IDirectDrawSurfaceImpl *) 0x00000001;
220 gl_d3d_dev->current_bound_texture[1] = (IDirectDrawSurfaceImpl *) 0x00000000;
221 if (d3d_dev->state_block.texture_stage_state[0][D3DTSS_COLOROP - 1] == D3DTOP_DISABLE) glDisable(GL_TEXTURE_2D);
224 /* retrieve the X drawable to use on a given DC */
225 inline static Drawable get_drawable( HDC hdc )
228 enum x11drv_escape_codes escape = X11DRV_GET_DRAWABLE;
230 if (!ExtEscape( hdc, X11DRV_ESCAPE, sizeof(escape), (LPCSTR)&escape,
231 sizeof(drawable), (LPSTR)&drawable )) drawable = 0;
236 /* This is unnecessarely complicated :-) */
237 #define MEASUREMENT_WINDOW 5
238 #define NUMBER_OF_WINDOWS 10
240 static LONGLONG perf_freq;
241 static LONGLONG perf_storage[NUMBER_OF_WINDOWS];
242 static LONGLONG prev_time = 0;
243 static unsigned int current_window;
244 static unsigned int measurements_in_window;
245 static unsigned int valid_windows;
247 static BOOL opengl_flip( LPVOID dev, LPVOID drawable)
249 IDirect3DDeviceImpl *d3d_dev = (IDirect3DDeviceImpl *) dev;
250 IDirect3DDeviceGLImpl *gl_d3d_dev = (IDirect3DDeviceGLImpl *) dev;
252 TRACE("(%p, %ld)\n", gl_d3d_dev->display,(Drawable)drawable);
254 if (gl_d3d_dev->state[WINE_GL_BUFFER_BACK] == SURFACE_MEMORY_DIRTY) {
255 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]);
257 gl_d3d_dev->state[WINE_GL_BUFFER_BACK] = SURFACE_GL;
258 gl_d3d_dev->state[WINE_GL_BUFFER_FRONT] = SURFACE_GL;
259 glXSwapBuffers(gl_d3d_dev->display, (Drawable)drawable);
262 if (TRACE_ON(ddraw_fps)) {
263 LONGLONG current_time;
264 LONGLONG frame_duration;
265 QueryPerformanceCounter((LARGE_INTEGER *) ¤t_time);
267 if (prev_time != 0) {
268 LONGLONG total_time = 0;
271 frame_duration = current_time - prev_time;
272 prev_time = current_time;
274 perf_storage[current_window] += frame_duration;
275 measurements_in_window++;
277 if (measurements_in_window >= MEASUREMENT_WINDOW) {
281 if (valid_windows < NUMBER_OF_WINDOWS) {
283 tot_meas = valid_windows * MEASUREMENT_WINDOW;
284 for (i = 0; i < valid_windows; i++) {
285 total_time += perf_storage[i];
289 tot_meas = NUMBER_OF_WINDOWS * MEASUREMENT_WINDOW;
290 for (i = 0; i < NUMBER_OF_WINDOWS; i++) {
291 total_time += perf_storage[i];
295 TRACE_(ddraw_fps)(" %9.5f\n", (double) (perf_freq * tot_meas) / (double) total_time);
297 if (current_window >= NUMBER_OF_WINDOWS) {
300 perf_storage[current_window] = 0;
301 measurements_in_window = 0;
304 prev_time = current_time;
305 memset(perf_storage, 0, sizeof(perf_storage));
308 measurements_in_window = 0;
309 QueryPerformanceFrequency((LARGE_INTEGER *) &perf_freq);
317 /*******************************************************************************
318 * OpenGL static functions
320 static void set_context(IDirect3DDeviceImpl* This)
322 IDirect3DDeviceGLImpl* glThis = (IDirect3DDeviceGLImpl*) This;
324 TRACE("glxMakeCurrent %p, %ld, %p\n",glThis->display,glThis->drawable, glThis->gl_context);
326 if (glXMakeCurrent(glThis->display, glThis->drawable, glThis->gl_context) == False) {
327 ERR("Error in setting current context (context %p drawable %ld)!\n",
328 glThis->gl_context, glThis->drawable);
333 static void fill_opengl_caps(D3DDEVICEDESC *d1)
335 d1->dwSize = sizeof(*d1);
336 d1->dwFlags = D3DDD_COLORMODEL | D3DDD_DEVCAPS | D3DDD_TRANSFORMCAPS | D3DDD_BCLIPPING | D3DDD_LIGHTINGCAPS |
337 D3DDD_LINECAPS | D3DDD_TRICAPS | D3DDD_DEVICERENDERBITDEPTH | D3DDD_DEVICEZBUFFERBITDEPTH |
338 D3DDD_MAXBUFFERSIZE | D3DDD_MAXVERTEXCOUNT;
339 d1->dcmColorModel = D3DCOLOR_RGB;
340 d1->dwDevCaps = opengl_device_caps.dwDevCaps;
341 d1->dtcTransformCaps.dwSize = sizeof(D3DTRANSFORMCAPS);
342 d1->dtcTransformCaps.dwCaps = D3DTRANSFORMCAPS_CLIP;
343 d1->bClipping = TRUE;
344 d1->dlcLightingCaps.dwSize = sizeof(D3DLIGHTINGCAPS);
345 d1->dlcLightingCaps.dwCaps = D3DLIGHTCAPS_DIRECTIONAL | D3DLIGHTCAPS_PARALLELPOINT | D3DLIGHTCAPS_POINT | D3DLIGHTCAPS_SPOT;
346 d1->dlcLightingCaps.dwLightingModel = D3DLIGHTINGMODEL_RGB;
347 d1->dlcLightingCaps.dwNumLights = opengl_device_caps.dwMaxActiveLights;
348 d1->dpcLineCaps = opengl_device_caps.dpcLineCaps;
349 d1->dpcTriCaps = opengl_device_caps.dpcTriCaps;
350 d1->dwDeviceRenderBitDepth = opengl_device_caps.dwDeviceRenderBitDepth;
351 d1->dwDeviceZBufferBitDepth = opengl_device_caps.dwDeviceZBufferBitDepth;
352 d1->dwMaxBufferSize = 0;
353 d1->dwMaxVertexCount = 65536;
354 d1->dwMinTextureWidth = opengl_device_caps.dwMinTextureWidth;
355 d1->dwMinTextureHeight = opengl_device_caps.dwMinTextureHeight;
356 d1->dwMaxTextureWidth = opengl_device_caps.dwMaxTextureWidth;
357 d1->dwMaxTextureHeight = opengl_device_caps.dwMaxTextureHeight;
358 d1->dwMinStippleWidth = 1;
359 d1->dwMinStippleHeight = 1;
360 d1->dwMaxStippleWidth = 32;
361 d1->dwMaxStippleHeight = 32;
362 d1->dwMaxTextureRepeat = opengl_device_caps.dwMaxTextureRepeat;
363 d1->dwMaxTextureAspectRatio = opengl_device_caps.dwMaxTextureAspectRatio;
364 d1->dwMaxAnisotropy = opengl_device_caps.dwMaxAnisotropy;
365 d1->dvGuardBandLeft = opengl_device_caps.dvGuardBandLeft;
366 d1->dvGuardBandRight = opengl_device_caps.dvGuardBandRight;
367 d1->dvGuardBandTop = opengl_device_caps.dvGuardBandTop;
368 d1->dvGuardBandBottom = opengl_device_caps.dvGuardBandBottom;
369 d1->dvExtentsAdjust = opengl_device_caps.dvExtentsAdjust;
370 d1->dwStencilCaps = opengl_device_caps.dwStencilCaps;
371 d1->dwFVFCaps = opengl_device_caps.dwFVFCaps;
372 d1->dwTextureOpCaps = opengl_device_caps.dwTextureOpCaps;
373 d1->wMaxTextureBlendStages = opengl_device_caps.wMaxTextureBlendStages;
374 d1->wMaxSimultaneousTextures = opengl_device_caps.wMaxSimultaneousTextures;
377 static void fill_opengl_caps_7(D3DDEVICEDESC7 *d)
379 *d = opengl_device_caps;
382 HRESULT d3ddevice_enumerate(LPD3DENUMDEVICESCALLBACK cb, LPVOID context, DWORD version)
384 D3DDEVICEDESC dref, d1, d2;
387 /* Some games (Motoracer 2 demo) have the bad idea to modify the device name string.
388 Let's put the string in a sufficiently sized array in writable memory. */
389 char device_name[50];
390 strcpy(device_name,"direct3d");
392 fill_opengl_caps(&dref);
395 /* It seems that enumerating the reference IID on Direct3D 1 games (AvP / Motoracer2) breaks them */
396 char interface_name[] = "WINE Reference Direct3DX using OpenGL";
397 TRACE(" enumerating OpenGL D3DDevice interface using reference IID (IID %s).\n", debugstr_guid(&IID_IDirect3DRefDevice));
400 ret_value = cb((LPIID) &IID_IDirect3DRefDevice, interface_name, device_name, &d1, &d2, context);
401 if (ret_value != D3DENUMRET_OK)
406 char interface_name[] = "WINE Direct3DX using OpenGL";
407 TRACE(" enumerating OpenGL D3DDevice interface (IID %s).\n", debugstr_guid(&IID_D3DDEVICE_OpenGL));
410 ret_value = cb((LPIID) &IID_D3DDEVICE_OpenGL, interface_name, device_name, &d1, &d2, context);
411 if (ret_value != D3DENUMRET_OK)
415 return D3DENUMRET_OK;
418 HRESULT d3ddevice_enumerate7(LPD3DENUMDEVICESCALLBACK7 cb, LPVOID context)
420 D3DDEVICEDESC7 ddesc;
421 char interface_name[] = "WINE Direct3D7 using OpenGL";
422 char device_name[] = "Wine D3D7 device";
424 fill_opengl_caps_7(&ddesc);
426 TRACE(" enumerating OpenGL D3DDevice7 interface.\n");
428 return cb(interface_name, device_name, &ddesc, context);
432 GL_IDirect3DDeviceImpl_7_3T_2T_1T_Release(LPDIRECT3DDEVICE7 iface)
434 ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice7, iface);
435 IDirect3DDeviceGLImpl *glThis = (IDirect3DDeviceGLImpl *) This;
437 TRACE("(%p/%p)->() decrementing from %lu.\n", This, iface, This->ref);
438 if (!--(This->ref)) {
440 IDirectDrawSurfaceImpl *surface = This->surface, *surf;
442 /* Release texture associated with the device */
443 for (i = 0; i < MAX_TEXTURES; i++) {
444 if (This->current_texture[i] != NULL)
445 IDirectDrawSurface7_Release(ICOM_INTERFACE(This->current_texture[i], IDirectDrawSurface7));
446 HeapFree(GetProcessHeap(), 0, This->tex_mat[i]);
449 /* Look for the front buffer and override its surface's Flip method (if in double buffering) */
450 for (surf = surface; surf != NULL; surf = surf->surface_owner) {
451 if ((surf->surface_desc.ddsCaps.dwCaps&(DDSCAPS_FLIP|DDSCAPS_FRONTBUFFER)) == (DDSCAPS_FLIP|DDSCAPS_FRONTBUFFER)) {
452 surf->aux_ctx = NULL;
453 surf->aux_data = NULL;
454 surf->aux_flip = NULL;
458 for (surf = surface; surf != NULL; surf = surf->surface_owner) {
459 IDirectDrawSurfaceImpl *surf2;
460 for (surf2 = surf; surf2->prev_attached != NULL; surf2 = surf2->prev_attached) ;
461 for (; surf2 != NULL; surf2 = surf2->next_attached) {
462 if (((surf2->surface_desc.ddsCaps.dwCaps & (DDSCAPS_3DDEVICE)) == (DDSCAPS_3DDEVICE)) &&
463 ((surf2->surface_desc.ddsCaps.dwCaps & (DDSCAPS_ZBUFFER)) != (DDSCAPS_ZBUFFER))) {
464 /* Override the Lock / Unlock function for all these surfaces */
465 surf2->lock_update = surf2->lock_update_prev;
466 surf2->unlock_update = surf2->unlock_update_prev;
467 /* And install also the blt / bltfast overrides */
468 surf2->aux_blt = NULL;
469 surf2->aux_bltfast = NULL;
471 surf2->d3ddevice = NULL;
475 /* And warn the D3D object that this device is no longer active... */
476 This->d3d->d3d_removed_device(This->d3d, This);
478 HeapFree(GetProcessHeap(), 0, This->world_mat);
479 HeapFree(GetProcessHeap(), 0, This->view_mat);
480 HeapFree(GetProcessHeap(), 0, This->proj_mat);
482 if (glThis->surface_ptr)
483 HeapFree(GetProcessHeap(), 0, glThis->surface_ptr);
485 DeleteCriticalSection(&(This->crit));
488 if (glThis->unlock_tex)
489 glDeleteTextures(1, &(glThis->unlock_tex));
490 glXDestroyContext(glThis->display, glThis->gl_context);
492 HeapFree(GetProcessHeap(), 0, This->clipping_planes);
494 HeapFree(GetProcessHeap(), 0, This);
501 GL_IDirect3DDeviceImpl_3_2T_1T_GetCaps(LPDIRECT3DDEVICE3 iface,
502 LPD3DDEVICEDESC lpD3DHWDevDesc,
503 LPD3DDEVICEDESC lpD3DHELDevDesc)
505 ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice3, iface);
509 TRACE("(%p/%p)->(%p,%p)\n", This, iface, lpD3DHWDevDesc, lpD3DHELDevDesc);
511 fill_opengl_caps(&desc);
512 dwSize = lpD3DHWDevDesc->dwSize;
513 memset(lpD3DHWDevDesc, 0, dwSize);
514 memcpy(lpD3DHWDevDesc, &desc, (dwSize <= desc.dwSize ? dwSize : desc.dwSize));
516 dwSize = lpD3DHELDevDesc->dwSize;
517 memset(lpD3DHELDevDesc, 0, dwSize);
518 memcpy(lpD3DHELDevDesc, &desc, (dwSize <= desc.dwSize ? dwSize : desc.dwSize));
520 TRACE(" returning caps : (no dump function yet)\n");
525 static HRESULT enum_texture_format_OpenGL(LPD3DENUMTEXTUREFORMATSCALLBACK cb_1,
526 LPD3DENUMPIXELFORMATSCALLBACK cb_2,
530 LPDDPIXELFORMAT pformat;
532 /* Do the texture enumeration */
533 sdesc.dwSize = sizeof(DDSURFACEDESC);
534 sdesc.dwFlags = DDSD_PIXELFORMAT | DDSD_CAPS;
535 sdesc.ddsCaps.dwCaps = DDSCAPS_TEXTURE;
536 pformat = &(sdesc.ddpfPixelFormat);
537 pformat->dwSize = sizeof(DDPIXELFORMAT);
538 pformat->dwFourCC = 0;
540 TRACE("Enumerating GL_RGBA unpacked (32)\n");
541 pformat->dwFlags = DDPF_RGB | DDPF_ALPHAPIXELS;
542 pformat->u1.dwRGBBitCount = 32;
543 pformat->u2.dwRBitMask = 0x00FF0000;
544 pformat->u3.dwGBitMask = 0x0000FF00;
545 pformat->u4.dwBBitMask = 0x000000FF;
546 pformat->u5.dwRGBAlphaBitMask = 0xFF000000;
547 if (cb_1) if (cb_1(&sdesc , context) == 0) return DD_OK;
548 if (cb_2) if (cb_2(pformat, context) == 0) return DD_OK;
550 TRACE("Enumerating GL_RGB unpacked (32)\n");
551 pformat->dwFlags = DDPF_RGB;
552 pformat->u1.dwRGBBitCount = 32;
553 pformat->u2.dwRBitMask = 0x00FF0000;
554 pformat->u3.dwGBitMask = 0x0000FF00;
555 pformat->u4.dwBBitMask = 0x000000FF;
556 pformat->u5.dwRGBAlphaBitMask = 0x00000000;
557 if (cb_1) if (cb_1(&sdesc , context) == 0) return DD_OK;
558 if (cb_2) if (cb_2(pformat, context) == 0) return DD_OK;
560 TRACE("Enumerating GL_RGB unpacked (24)\n");
561 pformat->dwFlags = DDPF_RGB;
562 pformat->u1.dwRGBBitCount = 24;
563 pformat->u2.dwRBitMask = 0x00FF0000;
564 pformat->u3.dwGBitMask = 0x0000FF00;
565 pformat->u4.dwBBitMask = 0x000000FF;
566 pformat->u5.dwRGBAlphaBitMask = 0x00000000;
567 if (cb_1) if (cb_1(&sdesc , context) == 0) return DD_OK;
568 if (cb_2) if (cb_2(pformat, context) == 0) return DD_OK;
570 /* Note : even if this is an 'emulated' texture format, it needs to be first
571 as some dumb applications seem to rely on that. */
572 TRACE("Enumerating GL_RGBA packed GL_UNSIGNED_SHORT_1_5_5_5 (ARGB) (16)\n");
573 pformat->dwFlags = DDPF_RGB | DDPF_ALPHAPIXELS;
574 pformat->u1.dwRGBBitCount = 16;
575 pformat->u2.dwRBitMask = 0x00007C00;
576 pformat->u3.dwGBitMask = 0x000003E0;
577 pformat->u4.dwBBitMask = 0x0000001F;
578 pformat->u5.dwRGBAlphaBitMask = 0x00008000;
579 if (cb_1) if (cb_1(&sdesc , context) == 0) return DD_OK;
580 if (cb_2) if (cb_2(pformat, context) == 0) return DD_OK;
582 TRACE("Enumerating GL_RGBA packed GL_UNSIGNED_SHORT_4_4_4_4 (ARGB) (16)\n");
583 pformat->dwFlags = DDPF_RGB | DDPF_ALPHAPIXELS;
584 pformat->u1.dwRGBBitCount = 16;
585 pformat->u2.dwRBitMask = 0x00000F00;
586 pformat->u3.dwGBitMask = 0x000000F0;
587 pformat->u4.dwBBitMask = 0x0000000F;
588 pformat->u5.dwRGBAlphaBitMask = 0x0000F000;
589 if (cb_1) if (cb_1(&sdesc , context) == 0) return DD_OK;
590 if (cb_2) if (cb_2(pformat, context) == 0) return DD_OK;
592 TRACE("Enumerating GL_RGB packed GL_UNSIGNED_SHORT_5_6_5 (16)\n");
593 pformat->dwFlags = DDPF_RGB;
594 pformat->u1.dwRGBBitCount = 16;
595 pformat->u2.dwRBitMask = 0x0000F800;
596 pformat->u3.dwGBitMask = 0x000007E0;
597 pformat->u4.dwBBitMask = 0x0000001F;
598 pformat->u5.dwRGBAlphaBitMask = 0x00000000;
599 if (cb_1) if (cb_1(&sdesc , context) == 0) return DD_OK;
600 if (cb_2) if (cb_2(pformat, context) == 0) return DD_OK;
602 TRACE("Enumerating GL_RGB packed GL_UNSIGNED_SHORT_5_5_5 (16)\n");
603 pformat->dwFlags = DDPF_RGB;
604 pformat->u1.dwRGBBitCount = 16;
605 pformat->u2.dwRBitMask = 0x00007C00;
606 pformat->u3.dwGBitMask = 0x000003E0;
607 pformat->u4.dwBBitMask = 0x0000001F;
608 pformat->u5.dwRGBAlphaBitMask = 0x00000000;
609 if (cb_1) if (cb_1(&sdesc , context) == 0) return DD_OK;
610 if (cb_2) if (cb_2(pformat, context) == 0) return DD_OK;
613 /* This is a compromise : some games choose the first 16 bit texture format with alpha they
614 find enumerated, others the last one. And both want to have the ARGB one.
616 So basically, forget our OpenGL roots and do not even enumerate our RGBA ones.
618 /* See argument about the RGBA format for 'packed' texture formats */
619 TRACE("Enumerating GL_RGBA unpacked (32)\n");
620 pformat->dwFlags = DDPF_RGB | DDPF_ALPHAPIXELS;
621 pformat->u1.dwRGBBitCount = 32;
622 pformat->u2.dwRBitMask = 0xFF000000;
623 pformat->u3.dwGBitMask = 0x00FF0000;
624 pformat->u4.dwBBitMask = 0x0000FF00;
625 pformat->u5.dwRGBAlphaBitMask = 0x000000FF;
626 if (cb_1) if (cb_1(&sdesc , context) == 0) return DD_OK;
627 if (cb_2) if (cb_2(pformat, context) == 0) return DD_OK;
629 TRACE("Enumerating GL_RGBA packed GL_UNSIGNED_SHORT_4_4_4_4 (16)\n");
630 pformat->dwFlags = DDPF_RGB | DDPF_ALPHAPIXELS;
631 pformat->u1.dwRGBBitCount = 16;
632 pformat->u2.dwRBitMask = 0x0000F000;
633 pformat->u3.dwGBitMask = 0x00000F00;
634 pformat->u4.dwBBitMask = 0x000000F0;
635 pformat->u5.dwRGBAlphaBitMask = 0x0000000F;
636 if (cb_1) if (cb_1(&sdesc , context) == 0) return DD_OK;
637 if (cb_2) if (cb_2(pformat, context) == 0) return DD_OK;
639 TRACE("Enumerating GL_RGBA packed GL_UNSIGNED_SHORT_5_5_5_1 (16)\n");
640 pformat->dwFlags = DDPF_RGB | DDPF_ALPHAPIXELS;
641 pformat->u1.dwRGBBitCount = 16;
642 pformat->u2.dwRBitMask = 0x0000F800;
643 pformat->u3.dwGBitMask = 0x000007C0;
644 pformat->u4.dwBBitMask = 0x0000003E;
645 pformat->u5.dwRGBAlphaBitMask = 0x00000001;
646 if (cb_1) if (cb_1(&sdesc , context) == 0) return DD_OK;
647 if (cb_2) if (cb_2(pformat, context) == 0) return DD_OK;
650 TRACE("Enumerating GL_RGB packed GL_UNSIGNED_BYTE_3_3_2 (8)\n");
651 pformat->dwFlags = DDPF_RGB;
652 pformat->u1.dwRGBBitCount = 8;
653 pformat->u2.dwRBitMask = 0x000000E0;
654 pformat->u3.dwGBitMask = 0x0000001C;
655 pformat->u4.dwBBitMask = 0x00000003;
656 pformat->u5.dwRGBAlphaBitMask = 0x00000000;
657 if (cb_1) if (cb_1(&sdesc , context) == 0) return DD_OK;
658 if (cb_2) if (cb_2(pformat, context) == 0) return DD_OK;
660 TRACE("Enumerating Paletted (8)\n");
661 pformat->dwFlags = DDPF_PALETTEINDEXED8;
662 pformat->u1.dwRGBBitCount = 8;
663 pformat->u2.dwRBitMask = 0x00000000;
664 pformat->u3.dwGBitMask = 0x00000000;
665 pformat->u4.dwBBitMask = 0x00000000;
666 pformat->u5.dwRGBAlphaBitMask = 0x00000000;
667 if (cb_1) if (cb_1(&sdesc , context) == 0) return DD_OK;
668 if (cb_2) if (cb_2(pformat, context) == 0) return DD_OK;
670 TRACE("End of enumeration\n");
676 d3ddevice_find(IDirectDrawImpl *d3d,
677 LPD3DFINDDEVICESEARCH lpD3DDFS,
678 LPD3DFINDDEVICERESULT lplpD3DDevice)
682 if ((lpD3DDFS->dwFlags & D3DFDS_COLORMODEL) &&
683 (lpD3DDFS->dcmColorModel != D3DCOLOR_RGB)) {
684 TRACE(" trying to request a non-RGB D3D color model. Not supported.\n");
685 return DDERR_INVALIDPARAMS; /* No real idea what to return here :-) */
687 if (lpD3DDFS->dwFlags & D3DFDS_GUID) {
688 TRACE(" trying to match guid %s.\n", debugstr_guid(&(lpD3DDFS->guid)));
689 if ((IsEqualGUID(&IID_D3DDEVICE_OpenGL, &(lpD3DDFS->guid)) == 0) &&
690 (IsEqualGUID(&IID_IDirect3DHALDevice, &(lpD3DDFS->guid)) == 0) &&
691 (IsEqualGUID(&IID_IDirect3DRefDevice, &(lpD3DDFS->guid)) == 0)) {
692 TRACE(" no match for this GUID.\n");
693 return DDERR_INVALIDPARAMS;
697 /* Now return our own GUID */
698 lplpD3DDevice->guid = IID_D3DDEVICE_OpenGL;
699 fill_opengl_caps(&desc);
700 lplpD3DDevice->ddHwDesc = desc;
701 lplpD3DDevice->ddSwDesc = desc;
703 TRACE(" returning Wine's OpenGL device with (undumped) capabilities\n");
709 GL_IDirect3DDeviceImpl_2_1T_EnumTextureFormats(LPDIRECT3DDEVICE2 iface,
710 LPD3DENUMTEXTUREFORMATSCALLBACK lpD3DEnumTextureProc,
713 ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice2, iface);
714 TRACE("(%p/%p)->(%p,%p)\n", This, iface, lpD3DEnumTextureProc, lpArg);
715 return enum_texture_format_OpenGL(lpD3DEnumTextureProc, NULL, lpArg);
719 GL_IDirect3DDeviceImpl_7_3T_EnumTextureFormats(LPDIRECT3DDEVICE7 iface,
720 LPD3DENUMPIXELFORMATSCALLBACK lpD3DEnumPixelProc,
723 ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice7, iface);
724 TRACE("(%p/%p)->(%p,%p)\n", This, iface, lpD3DEnumPixelProc, lpArg);
725 return enum_texture_format_OpenGL(NULL, lpD3DEnumPixelProc, lpArg);
729 GL_IDirect3DDeviceImpl_7_3T_2T_SetRenderState(LPDIRECT3DDEVICE7 iface,
730 D3DRENDERSTATETYPE dwRenderStateType,
733 ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice7, iface);
734 TRACE("(%p/%p)->(%08x,%08lx)\n", This, iface, dwRenderStateType, dwRenderState);
736 /* Call the render state functions */
737 store_render_state(This, dwRenderStateType, dwRenderState, &This->state_block);
738 set_render_state(This, dwRenderStateType, &This->state_block);
744 GL_IDirect3DDeviceImpl_7_3T_2T_GetRenderState(LPDIRECT3DDEVICE7 iface,
745 D3DRENDERSTATETYPE dwRenderStateType,
746 LPDWORD lpdwRenderState)
748 ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice7, iface);
749 TRACE("(%p/%p)->(%08x,%p)\n", This, iface, dwRenderStateType, lpdwRenderState);
751 /* Call the render state functions */
752 get_render_state(This, dwRenderStateType, lpdwRenderState, &This->state_block);
754 TRACE(" - asked for rendering state : %s, returning value %08lx.\n", _get_renderstate(dwRenderStateType), *lpdwRenderState);
760 GL_IDirect3DDeviceImpl_3_2T_SetLightState(LPDIRECT3DDEVICE3 iface,
761 D3DLIGHTSTATETYPE dwLightStateType,
764 ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice3, iface);
766 TRACE("(%p/%p)->(%08x,%08lx)\n", This, iface, dwLightStateType, dwLightState);
768 if (!dwLightStateType && (dwLightStateType > D3DLIGHTSTATE_COLORVERTEX))
769 TRACE("Unexpected Light State Type\n");
770 return DDERR_INVALIDPARAMS;
772 if (dwLightStateType == D3DLIGHTSTATE_MATERIAL /* 1 */) {
773 IDirect3DMaterialImpl *mat = (IDirect3DMaterialImpl *) dwLightState;
778 ERR(" D3DLIGHTSTATE_MATERIAL called with NULL material !!!\n");
780 } else if (dwLightStateType == D3DLIGHTSTATE_COLORMODEL /* 3 */) {
781 switch (dwLightState) {
783 ERR("DDCOLOR_MONO should not happen!\n");
786 /* We are already in this mode */
789 ERR("Unknown color model!\n");
793 D3DRENDERSTATETYPE rs;
794 switch (dwLightStateType) {
796 case D3DLIGHTSTATE_AMBIENT: /* 2 */
797 rs = D3DRENDERSTATE_AMBIENT;
799 case D3DLIGHTSTATE_FOGMODE: /* 4 */
800 rs = D3DRENDERSTATE_FOGVERTEXMODE;
802 case D3DLIGHTSTATE_FOGSTART: /* 5 */
803 rs = D3DRENDERSTATE_FOGSTART;
805 case D3DLIGHTSTATE_FOGEND: /* 6 */
806 rs = D3DRENDERSTATE_FOGEND;
808 case D3DLIGHTSTATE_FOGDENSITY: /* 7 */
809 rs = D3DRENDERSTATE_FOGDENSITY;
811 case D3DLIGHTSTATE_COLORVERTEX: /* 8 */
812 rs = D3DRENDERSTATE_COLORVERTEX;
818 IDirect3DDevice7_SetRenderState(ICOM_INTERFACE(This, IDirect3DDevice7),
825 static void draw_primitive_start_GL(D3DPRIMITIVETYPE d3dpt)
828 case D3DPT_POINTLIST:
829 TRACE("Start POINTS\n");
834 TRACE("Start LINES\n");
838 case D3DPT_LINESTRIP:
839 TRACE("Start LINE_STRIP\n");
840 glBegin(GL_LINE_STRIP);
843 case D3DPT_TRIANGLELIST:
844 TRACE("Start TRIANGLES\n");
845 glBegin(GL_TRIANGLES);
848 case D3DPT_TRIANGLESTRIP:
849 TRACE("Start TRIANGLE_STRIP\n");
850 glBegin(GL_TRIANGLE_STRIP);
853 case D3DPT_TRIANGLEFAN:
854 TRACE("Start TRIANGLE_FAN\n");
855 glBegin(GL_TRIANGLE_FAN);
859 FIXME("Unhandled primitive %08x\n", d3dpt);
864 /* This function calculate the Z coordinate from Zproj */
865 static float ZfromZproj(IDirect3DDeviceImpl *This, D3DVALUE Zproj)
868 /* Assume that X = Y = 0 and W = 1 */
869 a = This->proj_mat->_33;
870 b = This->proj_mat->_34;
871 c = This->proj_mat->_43;
872 d = This->proj_mat->_44;
873 /* We have in homogenous coordinates Z' = a * Z + c and W' = b * Z + d
874 * So in non homogenous coordinates we have Zproj = (a * Z + c) / (b * Z + d)
875 * And finally Z = (d * Zproj - c) / (a - b * Zproj)
877 return (d*Zproj - c) / (a - b*Zproj);
880 static void build_fog_table(BYTE *fog_table, DWORD fog_color) {
883 TRACE(" rebuilding fog table (%06lx)...\n", fog_color & 0x00FFFFFF);
885 for (i = 0; i < 3; i++) {
886 BYTE fog_color_component = (fog_color >> (8 * i)) & 0xFF;
888 for (elt = 0; elt < 0x10000; elt++) {
889 /* We apply the fog transformation and cache the result */
890 DWORD fog_intensity = elt & 0xFF;
891 DWORD vertex_color = (elt >> 8) & 0xFF;
892 fog_table[(i * 0x10000) + elt] = ((fog_intensity * vertex_color) + ((0xFF - fog_intensity) * fog_color_component)) / 0xFF;
897 static void draw_primitive_handle_GL_state(IDirect3DDeviceImpl *This,
898 BOOLEAN vertex_transformed,
899 BOOLEAN vertex_lit) {
900 IDirect3DDeviceGLImpl* glThis = (IDirect3DDeviceGLImpl*) This;
902 /* Puts GL in the correct lighting / transformation mode */
903 if ((vertex_transformed == FALSE) &&
904 (glThis->transform_state != GL_TRANSFORM_NORMAL)) {
905 /* Need to put the correct transformation again if we go from Transformed
906 vertices to non-transformed ones.
908 This->set_matrices(This, VIEWMAT_CHANGED|WORLDMAT_CHANGED|PROJMAT_CHANGED,
909 This->world_mat, This->view_mat, This->proj_mat);
910 glThis->transform_state = GL_TRANSFORM_NORMAL;
912 } else if ((vertex_transformed == TRUE) &&
913 (glThis->transform_state != GL_TRANSFORM_ORTHO)) {
914 /* Set our orthographic projection */
915 if (glThis->transform_state != GL_TRANSFORM_ORTHO) {
916 glThis->transform_state = GL_TRANSFORM_ORTHO;
917 d3ddevice_set_ortho(This);
921 /* TODO: optimize this to not always reset all the fog stuff on all DrawPrimitive call
922 if no fogging state change occurred */
923 if (This->state_block.render_state[D3DRENDERSTATE_FOGENABLE - 1] == TRUE) {
924 if (vertex_transformed == TRUE) {
925 if (glThis->fogging != 0) {
929 /* Now check if our fog_table still corresponds to the current vertex color.
930 Element '0x..00' is always the fog color as it corresponds to maximum fog intensity */
931 if ((glThis->fog_table[0 * 0x10000 + 0x0000] != ((This->state_block.render_state[D3DRENDERSTATE_FOGCOLOR - 1] >> 0) & 0xFF)) ||
932 (glThis->fog_table[1 * 0x10000 + 0x0000] != ((This->state_block.render_state[D3DRENDERSTATE_FOGCOLOR - 1] >> 8) & 0xFF)) ||
933 (glThis->fog_table[2 * 0x10000 + 0x0000] != ((This->state_block.render_state[D3DRENDERSTATE_FOGCOLOR - 1] >> 16) & 0xFF))) {
934 /* We need to rebuild our fog table.... */
935 build_fog_table(glThis->fog_table, This->state_block.render_state[D3DRENDERSTATE_FOGCOLOR - 1]);
938 if (This->state_block.render_state[D3DRENDERSTATE_FOGTABLEMODE - 1] != D3DFOG_NONE) {
939 switch (This->state_block.render_state[D3DRENDERSTATE_FOGTABLEMODE - 1]) {
940 case D3DFOG_LINEAR: glFogi(GL_FOG_MODE, GL_LINEAR); break;
941 case D3DFOG_EXP: glFogi(GL_FOG_MODE, GL_EXP); break;
942 case D3DFOG_EXP2: glFogi(GL_FOG_MODE, GL_EXP2); break;
944 if (vertex_lit == FALSE) {
945 glFogf(GL_FOG_START, *(float*)&This->state_block.render_state[D3DRENDERSTATE_FOGSTART - 1]);
946 glFogf(GL_FOG_END, *(float*)&This->state_block.render_state[D3DRENDERSTATE_FOGEND - 1]);
948 /* Special case of 'pixel fog' */
949 glFogf(GL_FOG_START, ZfromZproj(This, *(float*)&This->state_block.render_state[D3DRENDERSTATE_FOGSTART - 1]));
950 glFogf(GL_FOG_END, ZfromZproj(This, *(float*)&This->state_block.render_state[D3DRENDERSTATE_FOGEND - 1]));
952 if (glThis->fogging == 0) {
957 if (glThis->fogging != 0) {
964 if (glThis->fogging != 0) {
970 /* Handle the 'no-normal' case */
971 if ((vertex_lit == FALSE) && (This->state_block.render_state[D3DRENDERSTATE_LIGHTING - 1] == TRUE)) {
972 if (glThis->lighting == 0) {
973 glEnable(GL_LIGHTING);
974 glThis->lighting = 1;
977 if (glThis->lighting != 0) {
978 glDisable(GL_LIGHTING);
979 glThis->lighting = 0;
983 /* Handle the code for pre-vertex material properties */
984 if (vertex_transformed == FALSE) {
985 if ((This->state_block.render_state[D3DRENDERSTATE_LIGHTING - 1] == TRUE) &&
986 (This->state_block.render_state[D3DRENDERSTATE_COLORVERTEX - 1] == TRUE)) {
987 if ((This->state_block.render_state[D3DRENDERSTATE_DIFFUSEMATERIALSOURCE - 1] != D3DMCS_MATERIAL) ||
988 (This->state_block.render_state[D3DRENDERSTATE_AMBIENTMATERIALSOURCE - 1] != D3DMCS_MATERIAL) ||
989 (This->state_block.render_state[D3DRENDERSTATE_EMISSIVEMATERIALSOURCE - 1] != D3DMCS_MATERIAL) ||
990 (This->state_block.render_state[D3DRENDERSTATE_SPECULARMATERIALSOURCE - 1] != D3DMCS_MATERIAL)) {
991 glEnable(GL_COLOR_MATERIAL);
998 inline static void draw_primitive(IDirect3DDeviceImpl *This, DWORD maxvert, WORD *index,
999 D3DVERTEXTYPE d3dvt, D3DPRIMITIVETYPE d3dpt, void *lpvertex)
1001 D3DDRAWPRIMITIVESTRIDEDDATA strided;
1004 case D3DVT_VERTEX: {
1005 strided.position.lpvData = &((D3DVERTEX *) lpvertex)->u1.x;
1006 strided.position.dwStride = sizeof(D3DVERTEX);
1007 strided.normal.lpvData = &((D3DVERTEX *) lpvertex)->u4.nx;
1008 strided.normal.dwStride = sizeof(D3DVERTEX);
1009 strided.textureCoords[0].lpvData = &((D3DVERTEX *) lpvertex)->u7.tu;
1010 strided.textureCoords[0].dwStride = sizeof(D3DVERTEX);
1011 draw_primitive_strided(This, d3dpt, D3DFVF_VERTEX, &strided, 0 /* Unused */, index, maxvert, 0 /* Unused */);
1014 case D3DVT_LVERTEX: {
1015 strided.position.lpvData = &((D3DLVERTEX *) lpvertex)->u1.x;
1016 strided.position.dwStride = sizeof(D3DLVERTEX);
1017 strided.diffuse.lpvData = &((D3DLVERTEX *) lpvertex)->u4.color;
1018 strided.diffuse.dwStride = sizeof(D3DLVERTEX);
1019 strided.specular.lpvData = &((D3DLVERTEX *) lpvertex)->u5.specular;
1020 strided.specular.dwStride = sizeof(D3DLVERTEX);
1021 strided.textureCoords[0].lpvData = &((D3DLVERTEX *) lpvertex)->u6.tu;
1022 strided.textureCoords[0].dwStride = sizeof(D3DLVERTEX);
1023 draw_primitive_strided(This, d3dpt, D3DFVF_LVERTEX, &strided, 0 /* Unused */, index, maxvert, 0 /* Unused */);
1026 case D3DVT_TLVERTEX: {
1027 strided.position.lpvData = &((D3DTLVERTEX *) lpvertex)->u1.sx;
1028 strided.position.dwStride = sizeof(D3DTLVERTEX);
1029 strided.diffuse.lpvData = &((D3DTLVERTEX *) lpvertex)->u5.color;
1030 strided.diffuse.dwStride = sizeof(D3DTLVERTEX);
1031 strided.specular.lpvData = &((D3DTLVERTEX *) lpvertex)->u6.specular;
1032 strided.specular.dwStride = sizeof(D3DTLVERTEX);
1033 strided.textureCoords[0].lpvData = &((D3DTLVERTEX *) lpvertex)->u7.tu;
1034 strided.textureCoords[0].dwStride = sizeof(D3DTLVERTEX);
1035 draw_primitive_strided(This, d3dpt, D3DFVF_TLVERTEX, &strided, 0 /* Unused */, index, maxvert, 0 /* Unused */);
1039 FIXME("Unhandled vertex type %08x\n", d3dvt);
1045 GL_IDirect3DDeviceImpl_2_DrawPrimitive(LPDIRECT3DDEVICE2 iface,
1046 D3DPRIMITIVETYPE d3dptPrimitiveType,
1047 D3DVERTEXTYPE d3dvtVertexType,
1049 DWORD dwVertexCount,
1052 ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice2, iface);
1054 TRACE("(%p/%p)->(%08x,%08x,%p,%08lx,%08lx)\n", This, iface, d3dptPrimitiveType, d3dvtVertexType, lpvVertices, dwVertexCount, dwFlags);
1055 if (TRACE_ON(ddraw)) {
1056 TRACE(" - flags : "); dump_DPFLAGS(dwFlags);
1059 draw_primitive(This, dwVertexCount, NULL, d3dvtVertexType, d3dptPrimitiveType, lpvVertices);
1065 GL_IDirect3DDeviceImpl_2_DrawIndexedPrimitive(LPDIRECT3DDEVICE2 iface,
1066 D3DPRIMITIVETYPE d3dptPrimitiveType,
1067 D3DVERTEXTYPE d3dvtVertexType,
1069 DWORD dwVertexCount,
1074 ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice2, iface);
1075 TRACE("(%p/%p)->(%08x,%08x,%p,%08lx,%p,%08lx,%08lx)\n", This, iface, d3dptPrimitiveType, d3dvtVertexType, lpvVertices, dwVertexCount, dwIndices, dwIndexCount, dwFlags);
1076 if (TRACE_ON(ddraw)) {
1077 TRACE(" - flags : "); dump_DPFLAGS(dwFlags);
1080 draw_primitive(This, dwIndexCount, dwIndices, d3dvtVertexType, d3dptPrimitiveType, lpvVertices);
1086 GL_IDirect3DDeviceImpl_1_CreateExecuteBuffer(LPDIRECT3DDEVICE iface,
1087 LPD3DEXECUTEBUFFERDESC lpDesc,
1088 LPDIRECT3DEXECUTEBUFFER* lplpDirect3DExecuteBuffer,
1089 IUnknown* pUnkOuter)
1091 ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice, iface);
1092 IDirect3DExecuteBufferImpl *ret;
1095 TRACE("(%p/%p)->(%p,%p,%p)\n", This, iface, lpDesc, lplpDirect3DExecuteBuffer, pUnkOuter);
1097 ret_value = d3dexecutebuffer_create(&ret, This->d3d, This, lpDesc);
1098 *lplpDirect3DExecuteBuffer = ICOM_INTERFACE(ret, IDirect3DExecuteBuffer);
1100 TRACE(" returning %p.\n", *lplpDirect3DExecuteBuffer);
1105 static void flush_zbuffer_to_GL(IDirect3DDeviceImpl *d3d_dev, LPCRECT pRect, IDirectDrawSurfaceImpl *surf) {
1106 static BOOLEAN first = TRUE;
1107 IDirect3DDeviceGLImpl* gl_d3d_dev = (IDirect3DDeviceGLImpl*) d3d_dev;
1111 if (first == TRUE) {
1112 MESSAGE("Warning : application does direct locking of ZBuffer - expect slowdowns on many GL implementations :-)\n");
1116 TRACE("flushing ZBuffer back to GL\n");
1118 if (gl_d3d_dev->transform_state != GL_TRANSFORM_ORTHO) {
1119 gl_d3d_dev->transform_state = GL_TRANSFORM_ORTHO;
1120 d3ddevice_set_ortho(d3d_dev);
1123 glMatrixMode(GL_MODELVIEW);
1126 if (gl_d3d_dev->depth_test == 0) glEnable(GL_DEPTH_TEST);
1127 if (d3d_dev->state_block.render_state[D3DRENDERSTATE_ZFUNC - 1] != D3DCMP_ALWAYS) glDepthFunc(GL_ALWAYS);
1128 glColorMask(GL_FALSE, GL_FALSE, GL_FALSE, GL_FALSE);
1130 /* This loop here is to prevent using PixelZoom that may be unoptimized for the 1.0 / -1.0 case
1133 switch (surf->surface_desc.u4.ddpfPixelFormat.u1.dwZBufferBitDepth) {
1134 case 16: type = GL_UNSIGNED_SHORT; break;
1135 case 32: type = GL_UNSIGNED_INT; break;
1136 default: FIXME("Unhandled ZBuffer format !\n"); goto restore_state;
1139 for (row = 0; row < surf->surface_desc.dwHeight; row++) {
1140 /* glRasterPos3d(0.0, row + 1.0, 0.5); */
1141 glRasterPos2i(0, row + 1);
1142 glDrawPixels(surf->surface_desc.dwWidth, 1, GL_DEPTH_COMPONENT, type,
1143 ((unsigned char *) surf->surface_desc.lpSurface) + (row * surf->surface_desc.u1.lPitch));
1147 glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
1148 if (d3d_dev->state_block.render_state[D3DRENDERSTATE_ZFUNC - 1] != D3DCMP_ALWAYS)
1149 glDepthFunc(convert_D3D_compare_to_GL(d3d_dev->state_block.render_state[D3DRENDERSTATE_ZFUNC - 1]));
1150 if (gl_d3d_dev->depth_test == 0) glDisable(GL_DEPTH_TEST);
1153 /* These are the various handler used in the generic path */
1154 inline static void handle_xyz(D3DVALUE *coords) {
1155 glVertex3fv(coords);
1157 inline static void handle_xyzrhw(D3DVALUE *coords) {
1158 if (coords[3] < 1e-8)
1159 glVertex3fv(coords);
1161 GLfloat w = 1.0 / coords[3];
1163 glVertex4f(coords[0] * w,
1169 inline static void handle_normal(D3DVALUE *coords) {
1170 glNormal3fv(coords);
1173 inline static void handle_diffuse_base(STATEBLOCK *sb, DWORD *color) {
1174 if ((sb->render_state[D3DRENDERSTATE_ALPHATESTENABLE - 1] == TRUE) ||
1175 (sb->render_state[D3DRENDERSTATE_ALPHABLENDENABLE - 1] == TRUE)) {
1176 glColor4ub((*color >> 16) & 0xFF,
1177 (*color >> 8) & 0xFF,
1178 (*color >> 0) & 0xFF,
1179 (*color >> 24) & 0xFF);
1181 glColor3ub((*color >> 16) & 0xFF,
1182 (*color >> 8) & 0xFF,
1183 (*color >> 0) & 0xFF);
1187 inline static void handle_specular_base(STATEBLOCK *sb, DWORD *color) {
1188 glColor4ub((*color >> 16) & 0xFF,
1189 (*color >> 8) & 0xFF,
1190 (*color >> 0) & 0xFF,
1191 (*color >> 24) & 0xFF); /* No idea if the alpha field is really used.. */
1194 inline static void handle_diffuse(STATEBLOCK *sb, DWORD *color, BOOLEAN lighted) {
1195 if ((lighted == FALSE) &&
1196 (sb->render_state[D3DRENDERSTATE_LIGHTING - 1] == TRUE) &&
1197 (sb->render_state[D3DRENDERSTATE_COLORVERTEX - 1] == TRUE)) {
1198 if (sb->render_state[D3DRENDERSTATE_DIFFUSEMATERIALSOURCE - 1] == D3DMCS_COLOR1) {
1199 glColorMaterial(GL_FRONT_AND_BACK, GL_DIFFUSE);
1200 handle_diffuse_base(sb, color);
1202 if (sb->render_state[D3DRENDERSTATE_AMBIENTMATERIALSOURCE - 1] == D3DMCS_COLOR1) {
1203 glColorMaterial(GL_FRONT_AND_BACK, GL_AMBIENT);
1204 handle_diffuse_base(sb, color);
1206 if ((sb->render_state[D3DRENDERSTATE_SPECULARMATERIALSOURCE - 1] == D3DMCS_COLOR1) &&
1207 (sb->render_state[D3DRENDERSTATE_SPECULARENABLE - 1] == TRUE)) {
1208 glColorMaterial(GL_FRONT_AND_BACK, GL_SPECULAR);
1209 handle_diffuse_base(sb, color);
1211 if (sb->render_state[D3DRENDERSTATE_EMISSIVEMATERIALSOURCE - 1] == D3DMCS_COLOR1) {
1212 glColorMaterial(GL_FRONT_AND_BACK, GL_EMISSION);
1213 handle_diffuse_base(sb, color);
1216 handle_diffuse_base(sb, color);
1220 inline static void handle_specular(STATEBLOCK *sb, DWORD *color, BOOLEAN lighted) {
1221 if ((lighted == FALSE) &&
1222 (sb->render_state[D3DRENDERSTATE_LIGHTING - 1] == TRUE) &&
1223 (sb->render_state[D3DRENDERSTATE_COLORVERTEX - 1] == TRUE)) {
1224 if (sb->render_state[D3DRENDERSTATE_DIFFUSEMATERIALSOURCE - 1] == D3DMCS_COLOR2) {
1225 glColorMaterial(GL_FRONT_AND_BACK, GL_DIFFUSE);
1226 handle_specular_base(sb, color);
1228 if (sb->render_state[D3DRENDERSTATE_AMBIENTMATERIALSOURCE - 1] == D3DMCS_COLOR2) {
1229 glColorMaterial(GL_FRONT_AND_BACK, GL_AMBIENT);
1230 handle_specular_base(sb, color);
1232 if ((sb->render_state[D3DRENDERSTATE_SPECULARMATERIALSOURCE - 1] == D3DMCS_COLOR2) &&
1233 (sb->render_state[D3DRENDERSTATE_SPECULARENABLE - 1] == TRUE)) {
1234 glColorMaterial(GL_FRONT_AND_BACK, GL_SPECULAR);
1235 handle_specular_base(sb, color);
1237 if (sb->render_state[D3DRENDERSTATE_EMISSIVEMATERIALSOURCE - 1] == D3DMCS_COLOR2) {
1238 glColorMaterial(GL_FRONT_AND_BACK, GL_EMISSION);
1239 handle_specular_base(sb, color);
1242 /* No else here as we do not know how to handle 'specular' on its own in any case.. */
1245 inline static void handle_diffuse_and_specular(STATEBLOCK *sb, BYTE *fog_table, DWORD *color_d, DWORD *color_s, BOOLEAN lighted) {
1246 if (lighted == TRUE) {
1247 DWORD color = *color_d;
1248 if (sb->render_state[D3DRENDERSTATE_FOGENABLE - 1] == TRUE) {
1249 /* Special case where the specular value is used to do fogging */
1250 BYTE fog_intensity = *color_s >> 24; /* The alpha value of the specular component is the fog 'intensity' for this vertex */
1251 color &= 0xFF000000; /* Only keep the alpha component */
1252 color |= fog_table[((*color_d >> 0) & 0xFF) << 8 | fog_intensity] << 0;
1253 color |= fog_table[((*color_d >> 8) & 0xFF) << 8 | fog_intensity] << 8;
1254 color |= fog_table[((*color_d >> 16) & 0xFF) << 8 | fog_intensity] << 16;
1256 if (sb->render_state[D3DRENDERSTATE_SPECULARENABLE - 1] == TRUE) {
1257 /* Standard specular value in transformed mode. TODO */
1259 handle_diffuse_base(sb, &color);
1261 if (sb->render_state[D3DRENDERSTATE_LIGHTING - 1] == TRUE) {
1262 handle_diffuse(sb, color_d, FALSE);
1263 handle_specular(sb, color_s, FALSE);
1265 /* In that case, only put the diffuse color... */
1266 handle_diffuse_base(sb, color_d);
1271 inline static void handle_texture(D3DVALUE *coords) {
1272 glTexCoord2fv(coords);
1274 inline static void handle_textures(D3DVALUE *coords, int tex_stage) {
1275 if (GL_extensions.glMultiTexCoord2fv) {
1276 GL_extensions.glMultiTexCoord2fv(GL_TEXTURE0_WINE + tex_stage, coords);
1278 if (tex_stage == 0) glTexCoord2fv(coords);
1282 static void draw_primitive_strided(IDirect3DDeviceImpl *This,
1283 D3DPRIMITIVETYPE d3dptPrimitiveType,
1284 DWORD d3dvtVertexType,
1285 LPD3DDRAWPRIMITIVESTRIDEDDATA lpD3DDrawPrimStrideData,
1286 DWORD dwVertexCount,
1291 BOOLEAN vertex_lighted = FALSE;
1292 IDirect3DDeviceGLImpl* glThis = (IDirect3DDeviceGLImpl*) This;
1293 int num_active_stages = 0;
1295 /* I put the trace before the various locks... So as to better understand where locks occur :-) */
1296 if (TRACE_ON(ddraw)) {
1297 TRACE(" Vertex format : "); dump_flexible_vertex(d3dvtVertexType);
1300 /* This is to prevent 'thread contention' between a thread locking the device and another
1301 doing 3D display on it... */
1302 EnterCriticalSection(&(This->crit));
1305 if (glThis->state[WINE_GL_BUFFER_BACK] == SURFACE_MEMORY_DIRTY) {
1306 This->flush_to_framebuffer(This, &(glThis->lock_rect[WINE_GL_BUFFER_BACK]), glThis->lock_surf[WINE_GL_BUFFER_BACK]);
1308 glThis->state[WINE_GL_BUFFER_BACK] = SURFACE_GL;
1310 if (This->current_zbuffer == NULL) {
1311 /* Search for an attached ZBuffer */
1312 static const DDSCAPS2 zbuf_caps = { DDSCAPS_ZBUFFER, 0, 0, 0 };
1313 LPDIRECTDRAWSURFACE7 zbuf;
1316 hr = IDirectDrawSurface7_GetAttachedSurface(ICOM_INTERFACE(This->surface, IDirectDrawSurface7),
1317 (DDSCAPS2 *) &zbuf_caps, &zbuf);
1319 This->current_zbuffer = ICOM_OBJECT(IDirectDrawSurfaceImpl, IDirectDrawSurface7, zbuf);
1320 IDirectDrawSurface7_Release(zbuf);
1323 if (This->current_zbuffer != NULL) {
1324 if (This->current_zbuffer->get_dirty_status(This->current_zbuffer, NULL)) {
1325 flush_zbuffer_to_GL(This, NULL, This->current_zbuffer);
1329 if ( ((d3dvtVertexType & D3DFVF_POSITION_MASK) != D3DFVF_XYZ) ||
1330 ((d3dvtVertexType & D3DFVF_NORMAL) == 0) )
1331 vertex_lighted = TRUE;
1333 /* Compute the number of active texture stages and set the various texture parameters */
1334 num_active_stages = draw_primitive_handle_textures(This);
1336 /* And restore to handle '0' in the case we use glTexCorrd calls */
1337 if (glThis->current_active_tex_unit != GL_TEXTURE0_WINE) {
1338 GL_extensions.glActiveTexture(GL_TEXTURE0_WINE);
1339 glThis->current_active_tex_unit = GL_TEXTURE0_WINE;
1342 draw_primitive_handle_GL_state(This,
1343 (d3dvtVertexType & D3DFVF_POSITION_MASK) != D3DFVF_XYZ,
1345 draw_primitive_start_GL(d3dptPrimitiveType);
1347 /* Some fast paths first before the generic case.... */
1348 if ((d3dvtVertexType == D3DFVF_VERTEX) && (num_active_stages <= 1)) {
1351 for (index = 0; index < dwIndexCount; index++) {
1352 int i = (dwIndices == NULL) ? index : dwIndices[index];
1354 (D3DVALUE *) (((char *) lpD3DDrawPrimStrideData->normal.lpvData) + i * lpD3DDrawPrimStrideData->normal.dwStride);
1355 D3DVALUE *tex_coord =
1356 (D3DVALUE *) (((char *) lpD3DDrawPrimStrideData->textureCoords[0].lpvData) + i * lpD3DDrawPrimStrideData->textureCoords[0].dwStride);
1357 D3DVALUE *position =
1358 (D3DVALUE *) (((char *) lpD3DDrawPrimStrideData->position.lpvData) + i * lpD3DDrawPrimStrideData->position.dwStride);
1360 handle_normal(normal);
1361 handle_texture(tex_coord);
1362 handle_xyz(position);
1364 TRACE_(ddraw_geom)(" %f %f %f / %f %f %f (%f %f)\n",
1365 position[0], position[1], position[2],
1366 normal[0], normal[1], normal[2],
1367 tex_coord[0], tex_coord[1]);
1369 } else if ((d3dvtVertexType == D3DFVF_TLVERTEX) && (num_active_stages <= 1)) {
1372 for (index = 0; index < dwIndexCount; index++) {
1373 int i = (dwIndices == NULL) ? index : dwIndices[index];
1375 (DWORD *) (((char *) lpD3DDrawPrimStrideData->diffuse.lpvData) + i * lpD3DDrawPrimStrideData->diffuse.dwStride);
1377 (DWORD *) (((char *) lpD3DDrawPrimStrideData->specular.lpvData) + i * lpD3DDrawPrimStrideData->specular.dwStride);
1378 D3DVALUE *tex_coord =
1379 (D3DVALUE *) (((char *) lpD3DDrawPrimStrideData->textureCoords[0].lpvData) + i * lpD3DDrawPrimStrideData->textureCoords[0].dwStride);
1380 D3DVALUE *position =
1381 (D3DVALUE *) (((char *) lpD3DDrawPrimStrideData->position.lpvData) + i * lpD3DDrawPrimStrideData->position.dwStride);
1383 handle_diffuse_and_specular(&(This->state_block), glThis->fog_table, color_d, color_s, TRUE);
1384 handle_texture(tex_coord);
1385 handle_xyzrhw(position);
1387 TRACE_(ddraw_geom)(" %f %f %f %f / %02lx %02lx %02lx %02lx - %02lx %02lx %02lx %02lx (%f %f)\n",
1388 position[0], position[1], position[2], position[3],
1389 (*color_d >> 16) & 0xFF,
1390 (*color_d >> 8) & 0xFF,
1391 (*color_d >> 0) & 0xFF,
1392 (*color_d >> 24) & 0xFF,
1393 (*color_s >> 16) & 0xFF,
1394 (*color_s >> 8) & 0xFF,
1395 (*color_s >> 0) & 0xFF,
1396 (*color_s >> 24) & 0xFF,
1397 tex_coord[0], tex_coord[1]);
1399 } else if (((d3dvtVertexType & D3DFVF_POSITION_MASK) == D3DFVF_XYZ) ||
1400 ((d3dvtVertexType & D3DFVF_POSITION_MASK) == D3DFVF_XYZRHW)) {
1401 /* This is the 'slow path' but that should support all possible vertex formats out there...
1402 Note that people should write a fast path for all vertex formats out there...
1405 int num_tex_index = ((d3dvtVertexType & D3DFVF_TEXCOUNT_MASK) >> D3DFVF_TEXCOUNT_SHIFT);
1406 static const D3DVALUE no_index[] = { 0.0, 0.0, 0.0, 0.0 };
1408 for (index = 0; index < dwIndexCount; index++) {
1409 int i = (dwIndices == NULL) ? index : dwIndices[index];
1412 if (d3dvtVertexType & D3DFVF_NORMAL) {
1414 (D3DVALUE *) (((char *) lpD3DDrawPrimStrideData->normal.lpvData) + i * lpD3DDrawPrimStrideData->normal.dwStride);
1415 handle_normal(normal);
1417 if ((d3dvtVertexType & (D3DFVF_DIFFUSE|D3DFVF_SPECULAR)) == (D3DFVF_DIFFUSE|D3DFVF_SPECULAR)) {
1419 (DWORD *) (((char *) lpD3DDrawPrimStrideData->diffuse.lpvData) + i * lpD3DDrawPrimStrideData->diffuse.dwStride);
1421 (DWORD *) (((char *) lpD3DDrawPrimStrideData->specular.lpvData) + i * lpD3DDrawPrimStrideData->specular.dwStride);
1422 handle_diffuse_and_specular(&(This->state_block), glThis->fog_table, color_d, color_s, vertex_lighted);
1424 if (d3dvtVertexType & D3DFVF_SPECULAR) {
1426 (DWORD *) (((char *) lpD3DDrawPrimStrideData->specular.lpvData) + i * lpD3DDrawPrimStrideData->specular.dwStride);
1427 handle_specular(&(This->state_block), color_s, vertex_lighted);
1428 } else if (d3dvtVertexType & D3DFVF_DIFFUSE) {
1430 (DWORD *) (((char *) lpD3DDrawPrimStrideData->diffuse.lpvData) + i * lpD3DDrawPrimStrideData->diffuse.dwStride);
1431 handle_diffuse(&(This->state_block), color_d, vertex_lighted);
1435 for (tex_stage = 0; tex_stage < num_active_stages; tex_stage++) {
1436 int tex_index = This->state_block.texture_stage_state[tex_stage][D3DTSS_TEXCOORDINDEX - 1] & 0x0000FFFF;
1437 if (tex_index >= num_tex_index) {
1438 handle_textures((D3DVALUE *) no_index, tex_stage);
1440 D3DVALUE *tex_coord =
1441 (D3DVALUE *) (((char *) lpD3DDrawPrimStrideData->textureCoords[tex_index].lpvData) +
1442 i * lpD3DDrawPrimStrideData->textureCoords[tex_index].dwStride);
1443 handle_textures(tex_coord, tex_stage);
1447 if ((d3dvtVertexType & D3DFVF_POSITION_MASK) == D3DFVF_XYZ) {
1448 D3DVALUE *position =
1449 (D3DVALUE *) (((char *) lpD3DDrawPrimStrideData->position.lpvData) + i * lpD3DDrawPrimStrideData->position.dwStride);
1450 handle_xyz(position);
1451 } else if ((d3dvtVertexType & D3DFVF_POSITION_MASK) == D3DFVF_XYZRHW) {
1452 D3DVALUE *position =
1453 (D3DVALUE *) (((char *) lpD3DDrawPrimStrideData->position.lpvData) + i * lpD3DDrawPrimStrideData->position.dwStride);
1454 handle_xyzrhw(position);
1457 if (TRACE_ON(ddraw_geom)) {
1460 if ((d3dvtVertexType & D3DFVF_POSITION_MASK) == D3DFVF_XYZ) {
1461 D3DVALUE *position =
1462 (D3DVALUE *) (((char *) lpD3DDrawPrimStrideData->position.lpvData) + i * lpD3DDrawPrimStrideData->position.dwStride);
1463 TRACE_(ddraw_geom)(" %f %f %f", position[0], position[1], position[2]);
1464 } else if ((d3dvtVertexType & D3DFVF_POSITION_MASK) == D3DFVF_XYZRHW) {
1465 D3DVALUE *position =
1466 (D3DVALUE *) (((char *) lpD3DDrawPrimStrideData->position.lpvData) + i * lpD3DDrawPrimStrideData->position.dwStride);
1467 TRACE_(ddraw_geom)(" %f %f %f %f", position[0], position[1], position[2], position[3]);
1469 if (d3dvtVertexType & D3DFVF_NORMAL) {
1471 (D3DVALUE *) (((char *) lpD3DDrawPrimStrideData->normal.lpvData) + i * lpD3DDrawPrimStrideData->normal.dwStride);
1472 TRACE_(ddraw_geom)(" / %f %f %f", normal[0], normal[1], normal[2]);
1474 if (d3dvtVertexType & D3DFVF_DIFFUSE) {
1476 (DWORD *) (((char *) lpD3DDrawPrimStrideData->diffuse.lpvData) + i * lpD3DDrawPrimStrideData->diffuse.dwStride);
1477 TRACE_(ddraw_geom)(" / %02lx %02lx %02lx %02lx",
1478 (*color_d >> 16) & 0xFF,
1479 (*color_d >> 8) & 0xFF,
1480 (*color_d >> 0) & 0xFF,
1481 (*color_d >> 24) & 0xFF);
1483 if (d3dvtVertexType & D3DFVF_SPECULAR) {
1485 (DWORD *) (((char *) lpD3DDrawPrimStrideData->specular.lpvData) + i * lpD3DDrawPrimStrideData->specular.dwStride);
1486 TRACE_(ddraw_geom)(" / %02lx %02lx %02lx %02lx",
1487 (*color_s >> 16) & 0xFF,
1488 (*color_s >> 8) & 0xFF,
1489 (*color_s >> 0) & 0xFF,
1490 (*color_s >> 24) & 0xFF);
1492 for (tex_index = 0; tex_index < ((d3dvtVertexType & D3DFVF_TEXCOUNT_MASK) >> D3DFVF_TEXCOUNT_SHIFT); tex_index++) {
1493 D3DVALUE *tex_coord =
1494 (D3DVALUE *) (((char *) lpD3DDrawPrimStrideData->textureCoords[tex_index].lpvData) +
1495 i * lpD3DDrawPrimStrideData->textureCoords[tex_index].dwStride);
1496 TRACE_(ddraw_geom)(" / %f %f", tex_coord[0], tex_coord[1]);
1498 TRACE_(ddraw_geom)("\n");
1502 ERR(" matrix weighting not handled yet....\n");
1507 /* Whatever the case, disable the color material stuff */
1508 glDisable(GL_COLOR_MATERIAL);
1513 LeaveCriticalSection(&(This->crit));
1517 GL_IDirect3DDeviceImpl_7_3T_DrawPrimitive(LPDIRECT3DDEVICE7 iface,
1518 D3DPRIMITIVETYPE d3dptPrimitiveType,
1519 DWORD d3dvtVertexType,
1521 DWORD dwVertexCount,
1524 ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice7, iface);
1525 D3DDRAWPRIMITIVESTRIDEDDATA strided;
1527 TRACE("(%p/%p)->(%08x,%08lx,%p,%08lx,%08lx)\n", This, iface, d3dptPrimitiveType, d3dvtVertexType, lpvVertices, dwVertexCount, dwFlags);
1528 if (TRACE_ON(ddraw)) {
1529 TRACE(" - flags : "); dump_DPFLAGS(dwFlags);
1532 convert_FVF_to_strided_data(d3dvtVertexType, lpvVertices, &strided, 0);
1533 draw_primitive_strided(This, d3dptPrimitiveType, d3dvtVertexType, &strided, dwVertexCount, NULL, dwVertexCount, dwFlags);
1539 GL_IDirect3DDeviceImpl_7_3T_DrawIndexedPrimitive(LPDIRECT3DDEVICE7 iface,
1540 D3DPRIMITIVETYPE d3dptPrimitiveType,
1541 DWORD d3dvtVertexType,
1543 DWORD dwVertexCount,
1548 ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice7, iface);
1549 D3DDRAWPRIMITIVESTRIDEDDATA strided;
1551 TRACE("(%p/%p)->(%08x,%08lx,%p,%08lx,%p,%08lx,%08lx)\n", This, iface, d3dptPrimitiveType, d3dvtVertexType, lpvVertices, dwVertexCount, dwIndices, dwIndexCount, dwFlags);
1552 if (TRACE_ON(ddraw)) {
1553 TRACE(" - flags : "); dump_DPFLAGS(dwFlags);
1556 convert_FVF_to_strided_data(d3dvtVertexType, lpvVertices, &strided, 0);
1557 draw_primitive_strided(This, d3dptPrimitiveType, d3dvtVertexType, &strided, dwVertexCount, dwIndices, dwIndexCount, dwFlags);
1563 GL_IDirect3DDeviceImpl_7_3T_DrawPrimitiveStrided(LPDIRECT3DDEVICE7 iface,
1564 D3DPRIMITIVETYPE d3dptPrimitiveType,
1566 LPD3DDRAWPRIMITIVESTRIDEDDATA lpD3DDrawPrimStrideData,
1567 DWORD dwVertexCount,
1570 ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice7, iface);
1572 TRACE("(%p/%p)->(%08x,%08lx,%p,%08lx,%08lx)\n", This, iface, d3dptPrimitiveType, dwVertexType, lpD3DDrawPrimStrideData, dwVertexCount, dwFlags);
1573 if (TRACE_ON(ddraw)) {
1574 TRACE(" - flags : "); dump_DPFLAGS(dwFlags);
1576 draw_primitive_strided(This, d3dptPrimitiveType, dwVertexType, lpD3DDrawPrimStrideData, dwVertexCount, NULL, dwVertexCount, dwFlags);
1582 GL_IDirect3DDeviceImpl_7_3T_DrawIndexedPrimitiveStrided(LPDIRECT3DDEVICE7 iface,
1583 D3DPRIMITIVETYPE d3dptPrimitiveType,
1585 LPD3DDRAWPRIMITIVESTRIDEDDATA lpD3DDrawPrimStrideData,
1586 DWORD dwVertexCount,
1591 ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice7, iface);
1593 TRACE("(%p/%p)->(%08x,%08lx,%p,%08lx,%p,%08lx,%08lx)\n", This, iface, d3dptPrimitiveType, dwVertexType, lpD3DDrawPrimStrideData, dwVertexCount, lpIndex, dwIndexCount, dwFlags);
1594 if (TRACE_ON(ddraw)) {
1595 TRACE(" - flags : "); dump_DPFLAGS(dwFlags);
1598 draw_primitive_strided(This, d3dptPrimitiveType, dwVertexType, lpD3DDrawPrimStrideData, dwVertexCount, lpIndex, dwIndexCount, dwFlags);
1604 GL_IDirect3DDeviceImpl_7_3T_DrawPrimitiveVB(LPDIRECT3DDEVICE7 iface,
1605 D3DPRIMITIVETYPE d3dptPrimitiveType,
1606 LPDIRECT3DVERTEXBUFFER7 lpD3DVertexBuf,
1607 DWORD dwStartVertex,
1608 DWORD dwNumVertices,
1611 ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice7, iface);
1612 IDirect3DVertexBufferImpl *vb_impl = ICOM_OBJECT(IDirect3DVertexBufferImpl, IDirect3DVertexBuffer7, lpD3DVertexBuf);
1613 D3DDRAWPRIMITIVESTRIDEDDATA strided;
1615 TRACE("(%p/%p)->(%08x,%p,%08lx,%08lx,%08lx)\n", This, iface, d3dptPrimitiveType, lpD3DVertexBuf, dwStartVertex, dwNumVertices, dwFlags);
1616 if (TRACE_ON(ddraw)) {
1617 TRACE(" - flags : "); dump_DPFLAGS(dwFlags);
1620 if (vb_impl->processed == TRUE) {
1621 IDirect3DVertexBufferGLImpl *vb_glimp = (IDirect3DVertexBufferGLImpl *) vb_impl;
1622 IDirect3DDeviceGLImpl *glThis = (IDirect3DDeviceGLImpl *) This;
1624 glThis->transform_state = GL_TRANSFORM_VERTEXBUFFER;
1625 This->set_matrices(This, VIEWMAT_CHANGED|WORLDMAT_CHANGED|PROJMAT_CHANGED,
1626 &(vb_glimp->world_mat), &(vb_glimp->view_mat), &(vb_glimp->proj_mat));
1628 convert_FVF_to_strided_data(vb_glimp->dwVertexTypeDesc, vb_glimp->vertices, &strided, dwStartVertex);
1629 draw_primitive_strided(This, d3dptPrimitiveType, vb_glimp->dwVertexTypeDesc, &strided, dwNumVertices, NULL, dwNumVertices, dwFlags);
1632 convert_FVF_to_strided_data(vb_impl->desc.dwFVF, vb_impl->vertices, &strided, dwStartVertex);
1633 draw_primitive_strided(This, d3dptPrimitiveType, vb_impl->desc.dwFVF, &strided, dwNumVertices, NULL, dwNumVertices, dwFlags);
1640 GL_IDirect3DDeviceImpl_7_3T_DrawIndexedPrimitiveVB(LPDIRECT3DDEVICE7 iface,
1641 D3DPRIMITIVETYPE d3dptPrimitiveType,
1642 LPDIRECT3DVERTEXBUFFER7 lpD3DVertexBuf,
1643 DWORD dwStartVertex,
1644 DWORD dwNumVertices,
1649 ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice7, iface);
1650 IDirect3DVertexBufferImpl *vb_impl = ICOM_OBJECT(IDirect3DVertexBufferImpl, IDirect3DVertexBuffer7, lpD3DVertexBuf);
1651 D3DDRAWPRIMITIVESTRIDEDDATA strided;
1653 TRACE("(%p/%p)->(%08x,%p,%08lx,%08lx,%p,%08lx,%08lx)\n", This, iface, d3dptPrimitiveType, lpD3DVertexBuf, dwStartVertex, dwNumVertices, lpwIndices, dwIndexCount, dwFlags);
1654 if (TRACE_ON(ddraw)) {
1655 TRACE(" - flags : "); dump_DPFLAGS(dwFlags);
1658 if (vb_impl->processed == TRUE) {
1659 IDirect3DVertexBufferGLImpl *vb_glimp = (IDirect3DVertexBufferGLImpl *) vb_impl;
1660 IDirect3DDeviceGLImpl *glThis = (IDirect3DDeviceGLImpl *) This;
1662 glThis->transform_state = GL_TRANSFORM_VERTEXBUFFER;
1663 This->set_matrices(This, VIEWMAT_CHANGED|WORLDMAT_CHANGED|PROJMAT_CHANGED,
1664 &(vb_glimp->world_mat), &(vb_glimp->view_mat), &(vb_glimp->proj_mat));
1666 convert_FVF_to_strided_data(vb_glimp->dwVertexTypeDesc, vb_glimp->vertices, &strided, dwStartVertex);
1667 draw_primitive_strided(This, d3dptPrimitiveType, vb_glimp->dwVertexTypeDesc, &strided, dwNumVertices, lpwIndices, dwIndexCount, dwFlags);
1670 convert_FVF_to_strided_data(vb_impl->desc.dwFVF, vb_impl->vertices, &strided, dwStartVertex);
1671 draw_primitive_strided(This, d3dptPrimitiveType, vb_impl->desc.dwFVF, &strided, dwNumVertices, lpwIndices, dwIndexCount, dwFlags);
1677 /* We need a static function for that to handle the 'special' case of 'SELECT_ARG2' */
1679 handle_color_alpha_args(IDirect3DDeviceImpl *This, DWORD dwStage, D3DTEXTURESTAGESTATETYPE d3dTexStageStateType, DWORD dwState, D3DTEXTUREOP tex_op)
1681 BOOLEAN is_complement = FALSE;
1682 BOOLEAN is_alpha_replicate = FALSE;
1683 BOOLEAN handled = TRUE;
1685 BOOLEAN is_color = ((d3dTexStageStateType == D3DTSS_COLORARG1) || (d3dTexStageStateType == D3DTSS_COLORARG2));
1689 if (d3dTexStageStateType == D3DTSS_COLORARG1) num = 0;
1690 else if (d3dTexStageStateType == D3DTSS_COLORARG2) num = 1;
1695 if (tex_op == D3DTOP_SELECTARG2) {
1699 if (d3dTexStageStateType == D3DTSS_ALPHAARG1) num = 0;
1700 else if (d3dTexStageStateType == D3DTSS_ALPHAARG2) num = 1;
1705 if (tex_op == D3DTOP_SELECTARG2) {
1710 if (dwState & D3DTA_COMPLEMENT) {
1711 is_complement = TRUE;
1713 if (dwState & D3DTA_ALPHAREPLICATE) {
1714 is_alpha_replicate = TRUE;
1716 dwState &= D3DTA_SELECTMASK;
1717 if ((dwStage == 0) && (dwState == D3DTA_CURRENT)) {
1718 dwState = D3DTA_DIFFUSE;
1722 case D3DTA_CURRENT: src = GL_PREVIOUS_EXT; break;
1723 case D3DTA_DIFFUSE: src = GL_PRIMARY_COLOR_EXT; break;
1724 case D3DTA_TEXTURE: src = GL_TEXTURE; break;
1725 case D3DTA_TFACTOR: {
1726 /* Get the constant value from the current rendering state */
1728 DWORD col = This->state_block.render_state[D3DRENDERSTATE_TEXTUREFACTOR - 1];
1730 color[0] = ((col >> 16) & 0xFF) / 255.0f;
1731 color[1] = ((col >> 8) & 0xFF) / 255.0f;
1732 color[2] = ((col >> 0) & 0xFF) / 255.0f;
1733 color[3] = ((col >> 24) & 0xFF) / 255.0f;
1734 glTexEnvfv(GL_TEXTURE_ENV, GL_TEXTURE_ENV_COLOR, color);
1736 src = GL_CONSTANT_EXT;
1738 default: src = GL_TEXTURE; handled = FALSE; break;
1742 glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_RGB_EXT + num, src);
1743 if (is_alpha_replicate) {
1744 glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND0_RGB_EXT + num, is_complement ? GL_ONE_MINUS_SRC_ALPHA : GL_SRC_ALPHA);
1746 glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND0_RGB_EXT + num, is_complement ? GL_ONE_MINUS_SRC_COLOR : GL_SRC_COLOR);
1749 glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_ALPHA_EXT + num, src);
1750 glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND0_ALPHA_EXT + num, is_complement ? GL_ONE_MINUS_SRC_ALPHA : GL_SRC_ALPHA);
1757 GL_IDirect3DDeviceImpl_7_3T_SetTextureStageState(LPDIRECT3DDEVICE7 iface,
1759 D3DTEXTURESTAGESTATETYPE d3dTexStageStateType,
1762 ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice7, iface);
1763 IDirect3DDeviceGLImpl *glThis = (IDirect3DDeviceGLImpl *) This;
1768 TRACE("(%p/%p)->(%08lx,%08x,%08lx)\n", This, iface, dwStage, d3dTexStageStateType, dwState);
1770 if (((GL_extensions.max_texture_units == 0) && (dwStage > 0)) ||
1771 ((GL_extensions.max_texture_units != 0) && (dwStage >= GL_extensions.max_texture_units))) {
1775 unit = GL_TEXTURE0_WINE + dwStage;
1776 if (unit != glThis->current_active_tex_unit) {
1777 GL_extensions.glActiveTexture(unit);
1778 glThis->current_active_tex_unit = unit;
1781 switch (d3dTexStageStateType) {
1782 #define GEN_CASE(a) case a: type = #a; break
1783 GEN_CASE(D3DTSS_COLOROP);
1784 GEN_CASE(D3DTSS_COLORARG1);
1785 GEN_CASE(D3DTSS_COLORARG2);
1786 GEN_CASE(D3DTSS_ALPHAOP);
1787 GEN_CASE(D3DTSS_ALPHAARG1);
1788 GEN_CASE(D3DTSS_ALPHAARG2);
1789 GEN_CASE(D3DTSS_BUMPENVMAT00);
1790 GEN_CASE(D3DTSS_BUMPENVMAT01);
1791 GEN_CASE(D3DTSS_BUMPENVMAT10);
1792 GEN_CASE(D3DTSS_BUMPENVMAT11);
1793 GEN_CASE(D3DTSS_TEXCOORDINDEX);
1794 GEN_CASE(D3DTSS_ADDRESS);
1795 GEN_CASE(D3DTSS_ADDRESSU);
1796 GEN_CASE(D3DTSS_ADDRESSV);
1797 GEN_CASE(D3DTSS_BORDERCOLOR);
1798 GEN_CASE(D3DTSS_MAGFILTER);
1799 GEN_CASE(D3DTSS_MINFILTER);
1800 GEN_CASE(D3DTSS_MIPFILTER);
1801 GEN_CASE(D3DTSS_MIPMAPLODBIAS);
1802 GEN_CASE(D3DTSS_MAXMIPLEVEL);
1803 GEN_CASE(D3DTSS_MAXANISOTROPY);
1804 GEN_CASE(D3DTSS_BUMPENVLSCALE);
1805 GEN_CASE(D3DTSS_BUMPENVLOFFSET);
1806 GEN_CASE(D3DTSS_TEXTURETRANSFORMFLAGS);
1808 default: type = "UNKNOWN";
1811 /* Store the values in the state array */
1812 prev_state = This->state_block.texture_stage_state[dwStage][d3dTexStageStateType - 1];
1813 This->state_block.texture_stage_state[dwStage][d3dTexStageStateType - 1] = dwState;
1814 /* Some special cases when one state modifies more than one... */
1815 if (d3dTexStageStateType == D3DTSS_ADDRESS) {
1816 This->state_block.texture_stage_state[dwStage][D3DTSS_ADDRESSU - 1] = dwState;
1817 This->state_block.texture_stage_state[dwStage][D3DTSS_ADDRESSV - 1] = dwState;
1822 switch (d3dTexStageStateType) {
1823 case D3DTSS_MINFILTER:
1824 case D3DTSS_MIPFILTER:
1825 if (TRACE_ON(ddraw)) {
1826 if (d3dTexStageStateType == D3DTSS_MINFILTER) {
1827 switch ((D3DTEXTUREMINFILTER) dwState) {
1828 case D3DTFN_POINT: TRACE(" Stage type is : D3DTSS_MINFILTER => D3DTFN_POINT\n"); break;
1829 case D3DTFN_LINEAR: TRACE(" Stage type is : D3DTSS_MINFILTER => D3DTFN_LINEAR\n"); break;
1830 default: FIXME(" Unhandled stage type : D3DTSS_MINFILTER => %08lx\n", dwState); break;
1833 switch ((D3DTEXTUREMIPFILTER) dwState) {
1834 case D3DTFP_NONE: TRACE(" Stage type is : D3DTSS_MIPFILTER => D3DTFP_NONE\n"); break;
1835 case D3DTFP_POINT: TRACE(" Stage type is : D3DTSS_MIPFILTER => D3DTFP_POINT\n"); break;
1836 case D3DTFP_LINEAR: TRACE(" Stage type is : D3DTSS_MIPFILTER => D3DTFP_LINEAR\n"); break;
1837 default: FIXME(" Unhandled stage type : D3DTSS_MIPFILTER => %08lx\n", dwState); break;
1843 case D3DTSS_MAGFILTER:
1844 if (TRACE_ON(ddraw)) {
1845 switch ((D3DTEXTUREMAGFILTER) dwState) {
1846 case D3DTFG_POINT: TRACE(" Stage type is : D3DTSS_MAGFILTER => D3DTFG_POINT\n"); break;
1847 case D3DTFG_LINEAR: TRACE(" Stage type is : D3DTSS_MAGFILTER => D3DTFG_LINEAR\n"); break;
1848 default: FIXME(" Unhandled stage type : D3DTSS_MAGFILTER => %08lx\n", dwState); break;
1853 case D3DTSS_ADDRESS:
1854 case D3DTSS_ADDRESSU:
1855 case D3DTSS_ADDRESSV: {
1856 switch ((D3DTEXTUREADDRESS) dwState) {
1857 case D3DTADDRESS_WRAP: TRACE(" Stage type is : %s => D3DTADDRESS_WRAP\n", type); break;
1858 case D3DTADDRESS_CLAMP: TRACE(" Stage type is : %s => D3DTADDRESS_CLAMP\n", type); break;
1859 case D3DTADDRESS_BORDER: TRACE(" Stage type is : %s => D3DTADDRESS_BORDER\n", type); break;
1860 case D3DTADDRESS_MIRROR:
1861 if (GL_extensions.mirrored_repeat == TRUE) {
1862 TRACE(" Stage type is : %s => D3DTADDRESS_MIRROR\n", type);
1864 FIXME(" Stage type is : %s => D3DTADDRESS_MIRROR - not supported by GL !\n", type);
1867 default: FIXME(" Unhandled stage type : %s => %08lx\n", type, dwState); break;
1871 case D3DTSS_ALPHAOP:
1872 case D3DTSS_COLOROP: {
1874 GLenum parm = (d3dTexStageStateType == D3DTSS_ALPHAOP) ? GL_COMBINE_ALPHA_EXT : GL_COMBINE_RGB_EXT;
1879 #define GEN_CASE(a) case a: value = #a; break
1880 GEN_CASE(D3DTOP_DISABLE);
1881 GEN_CASE(D3DTOP_SELECTARG1);
1882 GEN_CASE(D3DTOP_SELECTARG2);
1883 GEN_CASE(D3DTOP_MODULATE);
1884 GEN_CASE(D3DTOP_MODULATE2X);
1885 GEN_CASE(D3DTOP_MODULATE4X);
1886 GEN_CASE(D3DTOP_ADD);
1887 GEN_CASE(D3DTOP_ADDSIGNED);
1888 GEN_CASE(D3DTOP_ADDSIGNED2X);
1889 GEN_CASE(D3DTOP_SUBTRACT);
1890 GEN_CASE(D3DTOP_ADDSMOOTH);
1891 GEN_CASE(D3DTOP_BLENDDIFFUSEALPHA);
1892 GEN_CASE(D3DTOP_BLENDTEXTUREALPHA);
1893 GEN_CASE(D3DTOP_BLENDFACTORALPHA);
1894 GEN_CASE(D3DTOP_BLENDTEXTUREALPHAPM);
1895 GEN_CASE(D3DTOP_BLENDCURRENTALPHA);
1896 GEN_CASE(D3DTOP_PREMODULATE);
1897 GEN_CASE(D3DTOP_MODULATEALPHA_ADDCOLOR);
1898 GEN_CASE(D3DTOP_MODULATECOLOR_ADDALPHA);
1899 GEN_CASE(D3DTOP_MODULATEINVALPHA_ADDCOLOR);
1900 GEN_CASE(D3DTOP_MODULATEINVCOLOR_ADDALPHA);
1901 GEN_CASE(D3DTOP_BUMPENVMAP);
1902 GEN_CASE(D3DTOP_BUMPENVMAPLUMINANCE);
1903 GEN_CASE(D3DTOP_DOTPRODUCT3);
1904 GEN_CASE(D3DTOP_FORCE_DWORD);
1906 default: value = "UNKNOWN";
1909 if ((d3dTexStageStateType == D3DTSS_COLOROP) && (dwState == D3DTOP_DISABLE)) {
1910 glDisable(GL_TEXTURE_2D);
1911 TRACE(" disabling 2D texturing.\n");
1913 /* Re-enable texturing */
1914 if (This->current_texture[0] != NULL) {
1915 glEnable(GL_TEXTURE_2D);
1916 TRACE(" enabling 2D texturing.\n");
1919 /* Re-Enable GL_TEXTURE_ENV_MODE, GL_COMBINE_EXT */
1920 if (dwState != D3DTOP_DISABLE) {
1921 if (glThis->current_tex_env != GL_COMBINE_EXT) {
1922 glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE_EXT);
1923 glThis->current_tex_env = GL_COMBINE_EXT;
1927 /* Now set up the operand correctly */
1929 case D3DTOP_DISABLE:
1930 /* Contrary to the docs, alpha can be disabled when colorop is enabled
1931 and it works, so ignore this op */
1932 TRACE(" Note : disable ALPHAOP but COLOROP enabled!\n");
1935 case D3DTOP_SELECTARG1:
1936 case D3DTOP_SELECTARG2:
1937 glTexEnvi(GL_TEXTURE_ENV, parm, GL_REPLACE);
1940 case D3DTOP_MODULATE4X:
1941 scale = scale * 2; /* Drop through */
1942 case D3DTOP_MODULATE2X:
1943 scale = scale * 2; /* Drop through */
1944 case D3DTOP_MODULATE:
1945 glTexEnvi(GL_TEXTURE_ENV, parm, GL_MODULATE);
1949 glTexEnvi(GL_TEXTURE_ENV, parm, GL_ADD);
1952 case D3DTOP_ADDSIGNED2X:
1953 scale = scale * 2; /* Drop through */
1954 case D3DTOP_ADDSIGNED:
1955 glTexEnvi(GL_TEXTURE_ENV, parm, GL_ADD_SIGNED_EXT);
1958 /* For the four blending modes, use the Arg2 parameter */
1959 case D3DTOP_BLENDDIFFUSEALPHA:
1960 case D3DTOP_BLENDTEXTUREALPHA:
1961 case D3DTOP_BLENDFACTORALPHA:
1962 case D3DTOP_BLENDCURRENTALPHA: {
1963 GLenum src = GL_PRIMARY_COLOR_EXT; /* Just to prevent a compiler warning.. */
1966 case D3DTOP_BLENDDIFFUSEALPHA: src = GL_PRIMARY_COLOR_EXT;
1967 case D3DTOP_BLENDTEXTUREALPHA: src = GL_TEXTURE;
1968 case D3DTOP_BLENDFACTORALPHA: src = GL_CONSTANT_EXT;
1969 case D3DTOP_BLENDCURRENTALPHA: src = GL_PREVIOUS_EXT;
1972 glTexEnvi(GL_TEXTURE_ENV, parm, GL_INTERPOLATE_EXT);
1973 glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE2_RGB_EXT, src);
1974 glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND2_RGB_EXT, GL_SRC_ALPHA);
1975 glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE2_ALPHA_EXT, src);
1976 glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND2_ALPHA_EXT, GL_SRC_ALPHA);
1985 if (((prev_state == D3DTOP_SELECTARG2) && (dwState != D3DTOP_SELECTARG2)) ||
1986 ((dwState == D3DTOP_SELECTARG2) && (prev_state != D3DTOP_SELECTARG2))) {
1987 /* Switch the arguments if needed... */
1988 if (d3dTexStageStateType == D3DTSS_COLOROP) {
1989 handle_color_alpha_args(This, dwStage, D3DTSS_COLORARG1,
1990 This->state_block.texture_stage_state[dwStage][D3DTSS_COLORARG1 - 1],
1992 handle_color_alpha_args(This, dwStage, D3DTSS_COLORARG2,
1993 This->state_block.texture_stage_state[dwStage][D3DTSS_COLORARG2 - 1],
1996 handle_color_alpha_args(This, dwStage, D3DTSS_ALPHAARG1,
1997 This->state_block.texture_stage_state[dwStage][D3DTSS_ALPHAARG1 - 1],
1999 handle_color_alpha_args(This, dwStage, D3DTSS_ALPHAARG2,
2000 This->state_block.texture_stage_state[dwStage][D3DTSS_ALPHAARG2 - 1],
2006 if (d3dTexStageStateType == D3DTSS_ALPHAOP) {
2007 glTexEnvi(GL_TEXTURE_ENV, GL_ALPHA_SCALE, scale);
2009 glTexEnvi(GL_TEXTURE_ENV, GL_RGB_SCALE_EXT, scale);
2011 TRACE(" Stage type is : %s => %s\n", type, value);
2013 FIXME(" Unhandled stage type is : %s => %s\n", type, value);
2017 case D3DTSS_COLORARG1:
2018 case D3DTSS_COLORARG2:
2019 case D3DTSS_ALPHAARG1:
2020 case D3DTSS_ALPHAARG2: {
2021 const char *value, *value_comp = "", *value_alpha = "";
2023 D3DTEXTUREOP tex_op;
2025 switch (dwState & D3DTA_SELECTMASK) {
2026 #define GEN_CASE(a) case a: value = #a; break
2027 GEN_CASE(D3DTA_DIFFUSE);
2028 GEN_CASE(D3DTA_CURRENT);
2029 GEN_CASE(D3DTA_TEXTURE);
2030 GEN_CASE(D3DTA_TFACTOR);
2031 GEN_CASE(D3DTA_SPECULAR);
2033 default: value = "UNKNOWN";
2035 if (dwState & D3DTA_COMPLEMENT) {
2036 value_comp = " | D3DTA_COMPLEMENT";
2038 if (dwState & D3DTA_ALPHAREPLICATE) {
2039 value_alpha = " | D3DTA_ALPHAREPLICATE";
2042 if ((d3dTexStageStateType == D3DTSS_COLORARG1) || (d3dTexStageStateType == D3DTSS_COLORARG2)) {
2043 tex_op = This->state_block.texture_stage_state[dwStage][D3DTSS_COLOROP - 1];
2045 tex_op = This->state_block.texture_stage_state[dwStage][D3DTSS_ALPHAOP - 1];
2048 handled = handle_color_alpha_args(This, dwStage, d3dTexStageStateType, dwState, tex_op);
2051 TRACE(" Stage type : %s => %s%s%s\n", type, value, value_comp, value_alpha);
2053 FIXME(" Unhandled stage type : %s => %s%s%s\n", type, value, value_comp, value_alpha);
2057 case D3DTSS_MIPMAPLODBIAS: {
2058 D3DVALUE value = *((D3DVALUE *) &dwState);
2059 BOOLEAN handled = TRUE;
2061 if ((value != 0.0) && (GL_extensions.mipmap_lodbias == FALSE))
2065 TRACE(" Stage type : D3DTSS_MIPMAPLODBIAS => %f\n", value);
2066 glTexEnvf(GL_TEXTURE_FILTER_CONTROL_WINE, GL_TEXTURE_LOD_BIAS_WINE, value);
2068 FIXME(" Unhandled stage type : D3DTSS_MIPMAPLODBIAS => %f\n", value);
2072 case D3DTSS_MAXMIPLEVEL:
2073 TRACE(" Stage type : D3DTSS_MAXMIPLEVEL => %ld\n", dwState);
2076 case D3DTSS_BORDERCOLOR:
2077 TRACE(" Stage type : D3DTSS_BORDERCOLOR => %02lx %02lx %02lx %02lx (RGBA)\n",
2078 ((dwState >> 16) & 0xFF),
2079 ((dwState >> 8) & 0xFF),
2080 ((dwState >> 0) & 0xFF),
2081 ((dwState >> 24) & 0xFF));
2084 case D3DTSS_TEXCOORDINDEX: {
2085 BOOLEAN handled = TRUE;
2088 switch (dwState & 0xFFFF0000) {
2089 #define GEN_CASE(a) case a: value = #a; break
2090 GEN_CASE(D3DTSS_TCI_PASSTHRU);
2091 GEN_CASE(D3DTSS_TCI_CAMERASPACENORMAL);
2092 GEN_CASE(D3DTSS_TCI_CAMERASPACEPOSITION);
2093 GEN_CASE(D3DTSS_TCI_CAMERASPACEREFLECTIONVECTOR);
2095 default: value = "UNKNOWN";
2097 if ((dwState & 0xFFFF0000) != D3DTSS_TCI_PASSTHRU)
2101 TRACE(" Stage type : D3DTSS_TEXCOORDINDEX => %ld | %s\n", dwState & 0x0000FFFF, value);
2103 FIXME(" Unhandled stage type : D3DTSS_TEXCOORDINDEX => %ld | %s\n", dwState & 0x0000FFFF, value);
2107 case D3DTSS_TEXTURETRANSFORMFLAGS: {
2108 const char *projected = "", *value;
2109 BOOLEAN handled = TRUE;
2110 switch (dwState & 0xFF) {
2111 #define GEN_CASE(a) case a: value = #a; break
2112 GEN_CASE(D3DTTFF_DISABLE);
2113 GEN_CASE(D3DTTFF_COUNT1);
2114 GEN_CASE(D3DTTFF_COUNT2);
2115 GEN_CASE(D3DTTFF_COUNT3);
2116 GEN_CASE(D3DTTFF_COUNT4);
2118 default: value = "UNKNOWN";
2120 if (dwState & D3DTTFF_PROJECTED) {
2121 projected = " | D3DTTFF_PROJECTED";
2125 if ((dwState & 0xFF) != D3DTTFF_DISABLE) {
2126 This->matrices_updated(This, TEXMAT0_CHANGED << dwStage);
2129 if (handled == TRUE) {
2130 TRACE(" Stage type : D3DTSS_TEXTURETRANSFORMFLAGS => %s%s\n", value, projected);
2132 FIXME(" Unhandled stage type : D3DTSS_TEXTURETRANSFORMFLAGS => %s%s\n", value, projected);
2137 FIXME(" Unhandled stage type : %s => %08lx\n", type, dwState);
2147 draw_primitive_handle_textures(IDirect3DDeviceImpl *This)
2149 IDirect3DDeviceGLImpl *glThis = (IDirect3DDeviceGLImpl *) This;
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);
2213 GL_IDirect3DDeviceImpl_7_3T_SetTexture(LPDIRECT3DDEVICE7 iface,
2215 LPDIRECTDRAWSURFACE7 lpTexture2)
2217 ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice7, iface);
2219 TRACE("(%p/%p)->(%08lx,%p)\n", This, iface, dwStage, lpTexture2);
2221 if (((GL_extensions.max_texture_units == 0) && (dwStage > 0)) ||
2222 ((GL_extensions.max_texture_units != 0) && (dwStage >= GL_extensions.max_texture_units))) {
2223 if (lpTexture2 != NULL) {
2224 WARN(" setting a texture to a non-supported texture stage !\n");
2229 if (This->current_texture[dwStage] != NULL) {
2230 IDirectDrawSurface7_Release(ICOM_INTERFACE(This->current_texture[dwStage], IDirectDrawSurface7));
2233 if (lpTexture2 == NULL) {
2234 This->current_texture[dwStage] = NULL;
2236 IDirectDrawSurfaceImpl *tex_impl = ICOM_OBJECT(IDirectDrawSurfaceImpl, IDirectDrawSurface7, lpTexture2);
2237 IDirectDrawSurface7_AddRef(ICOM_INTERFACE(tex_impl, IDirectDrawSurface7));
2238 This->current_texture[dwStage] = tex_impl;
2245 GL_IDirect3DDeviceImpl_7_GetCaps(LPDIRECT3DDEVICE7 iface,
2246 LPD3DDEVICEDESC7 lpD3DHELDevDesc)
2248 ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice7, iface);
2249 TRACE("(%p/%p)->(%p)\n", This, iface, lpD3DHELDevDesc);
2251 fill_opengl_caps_7(lpD3DHELDevDesc);
2253 TRACE(" returning caps : no dump function yet.\n");
2259 GL_IDirect3DDeviceImpl_7_SetMaterial(LPDIRECT3DDEVICE7 iface,
2260 LPD3DMATERIAL7 lpMat)
2262 ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice7, iface);
2263 TRACE("(%p/%p)->(%p)\n", This, iface, lpMat);
2265 if (TRACE_ON(ddraw)) {
2266 TRACE(" material is : \n");
2267 dump_D3DMATERIAL7(lpMat);
2270 This->current_material = *lpMat;
2273 glMaterialfv(GL_FRONT_AND_BACK,
2275 (float *) &(This->current_material.u.diffuse));
2276 glMaterialfv(GL_FRONT_AND_BACK,
2278 (float *) &(This->current_material.u1.ambient));
2279 glMaterialfv(GL_FRONT_AND_BACK,
2281 (float *) &(This->current_material.u2.specular));
2282 glMaterialfv(GL_FRONT_AND_BACK,
2284 (float *) &(This->current_material.u3.emissive));
2285 glMaterialf(GL_FRONT_AND_BACK,
2287 This->current_material.u4.power); /* Not sure about this... */
2295 GL_IDirect3DDeviceImpl_7_SetLight(LPDIRECT3DDEVICE7 iface,
2297 LPD3DLIGHT7 lpLight)
2299 ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice7, iface);
2300 IDirect3DDeviceGLImpl *glThis = (IDirect3DDeviceGLImpl *) This;
2301 TRACE("(%p/%p)->(%08lx,%p)\n", This, iface, dwLightIndex, lpLight);
2303 if (TRACE_ON(ddraw)) {
2304 TRACE(" setting light : \n");
2305 dump_D3DLIGHT7(lpLight);
2308 if (dwLightIndex >= MAX_LIGHTS) return DDERR_INVALIDPARAMS;
2309 This->set_lights |= 0x00000001 << dwLightIndex;
2310 This->light_parameters[dwLightIndex] = *lpLight;
2312 /* Some checks to print out nice warnings :-) */
2313 switch (lpLight->dltType) {
2314 case D3DLIGHT_DIRECTIONAL:
2315 case D3DLIGHT_POINT:
2316 /* These are handled properly... */
2320 if ((lpLight->dvTheta != 0.0) ||
2321 (lpLight->dvTheta != lpLight->dvPhi)) {
2322 ERR("dvTheta not fully supported yet !\n");
2327 ERR("Light type not handled yet : %08x !\n", lpLight->dltType);
2330 /* This will force the Light setting on next drawing of primitives */
2331 glThis->transform_state = GL_TRANSFORM_NONE;
2337 GL_IDirect3DDeviceImpl_7_LightEnable(LPDIRECT3DDEVICE7 iface,
2341 ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice7, iface);
2342 TRACE("(%p/%p)->(%08lx,%d)\n", This, iface, dwLightIndex, bEnable);
2344 if (dwLightIndex >= MAX_LIGHTS) return DDERR_INVALIDPARAMS;
2348 if (((0x00000001 << dwLightIndex) & This->set_lights) == 0) {
2349 /* Set the default parameters.. */
2350 TRACE(" setting default light parameters...\n");
2351 GL_IDirect3DDeviceImpl_7_SetLight(iface, dwLightIndex, &(This->light_parameters[dwLightIndex]));
2353 glEnable(GL_LIGHT0 + dwLightIndex);
2354 if ((This->active_lights & (0x00000001 << dwLightIndex)) == 0) {
2355 /* This light gets active... Need to update its parameters to GL before the next drawing */
2356 IDirect3DDeviceGLImpl *glThis = (IDirect3DDeviceGLImpl *) This;
2358 This->active_lights |= 0x00000001 << dwLightIndex;
2359 glThis->transform_state = GL_TRANSFORM_NONE;
2362 glDisable(GL_LIGHT0 + dwLightIndex);
2363 This->active_lights &= ~(0x00000001 << dwLightIndex);
2371 GL_IDirect3DDeviceImpl_7_SetClipPlane(LPDIRECT3DDEVICE7 iface, DWORD dwIndex, CONST D3DVALUE* pPlaneEquation)
2373 ICOM_THIS(IDirect3DDeviceImpl,iface);
2374 IDirect3DDeviceGLImpl* glThis = (IDirect3DDeviceGLImpl*) This;
2376 TRACE("(%p)->(%ld,%p)\n", This, dwIndex, pPlaneEquation);
2378 if (dwIndex >= This->max_clipping_planes) {
2379 return DDERR_INVALIDPARAMS;
2382 TRACE(" clip plane %ld : %f %f %f %f\n", dwIndex, pPlaneEquation[0], pPlaneEquation[1], pPlaneEquation[2], pPlaneEquation[3] );
2384 memcpy(This->clipping_planes[dwIndex].plane, pPlaneEquation, sizeof(D3DVALUE[4]));
2386 /* This is to force the reset of the transformation matrices on the next drawing.
2387 * This is needed to use the correct matrices for the various clipping planes.
2389 glThis->transform_state = GL_TRANSFORM_NONE;
2395 GL_IDirect3DDeviceImpl_7_SetViewport(LPDIRECT3DDEVICE7 iface,
2396 LPD3DVIEWPORT7 lpData)
2398 ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice7, iface);
2399 TRACE("(%p/%p)->(%p)\n", This, iface, lpData);
2401 if (TRACE_ON(ddraw)) {
2402 TRACE(" viewport is : \n");
2403 TRACE(" - dwX = %ld dwY = %ld\n",
2404 lpData->dwX, lpData->dwY);
2405 TRACE(" - dwWidth = %ld dwHeight = %ld\n",
2406 lpData->dwWidth, lpData->dwHeight);
2407 TRACE(" - dvMinZ = %f dvMaxZ = %f\n",
2408 lpData->dvMinZ, lpData->dvMaxZ);
2412 /* Set the viewport */
2413 if ((lpData->dvMinZ != This->active_viewport.dvMinZ) ||
2414 (lpData->dvMaxZ != This->active_viewport.dvMaxZ)) {
2415 glDepthRange(lpData->dvMinZ, lpData->dvMaxZ);
2417 if ((lpData->dwX != This->active_viewport.dwX) ||
2418 (lpData->dwY != This->active_viewport.dwY) ||
2419 (lpData->dwWidth != This->active_viewport.dwWidth) ||
2420 (lpData->dwHeight != This->active_viewport.dwHeight)) {
2421 glViewport(lpData->dwX,
2422 This->surface->surface_desc.dwHeight - (lpData->dwHeight + lpData->dwY),
2423 lpData->dwWidth, lpData->dwHeight);
2428 This->active_viewport = *lpData;
2433 #if !defined(__STRICT_ANSI__) && defined(__GNUC__)
2434 # define XCAST(fun) (typeof(VTABLE_IDirect3DDevice7.fun))
2436 # define XCAST(fun) (void*)
2439 ICOM_VTABLE(IDirect3DDevice7) VTABLE_IDirect3DDevice7 =
2441 ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
2442 XCAST(QueryInterface) Main_IDirect3DDeviceImpl_7_3T_2T_1T_QueryInterface,
2443 XCAST(AddRef) Main_IDirect3DDeviceImpl_7_3T_2T_1T_AddRef,
2444 XCAST(Release) GL_IDirect3DDeviceImpl_7_3T_2T_1T_Release,
2445 XCAST(GetCaps) GL_IDirect3DDeviceImpl_7_GetCaps,
2446 XCAST(EnumTextureFormats) GL_IDirect3DDeviceImpl_7_3T_EnumTextureFormats,
2447 XCAST(BeginScene) Main_IDirect3DDeviceImpl_7_3T_2T_1T_BeginScene,
2448 XCAST(EndScene) Main_IDirect3DDeviceImpl_7_3T_2T_1T_EndScene,
2449 XCAST(GetDirect3D) Main_IDirect3DDeviceImpl_7_3T_2T_1T_GetDirect3D,
2450 XCAST(SetRenderTarget) Main_IDirect3DDeviceImpl_7_3T_2T_SetRenderTarget,
2451 XCAST(GetRenderTarget) Main_IDirect3DDeviceImpl_7_3T_2T_GetRenderTarget,
2452 XCAST(Clear) Main_IDirect3DDeviceImpl_7_Clear,
2453 XCAST(SetTransform) Main_IDirect3DDeviceImpl_7_3T_2T_SetTransform,
2454 XCAST(GetTransform) Main_IDirect3DDeviceImpl_7_3T_2T_GetTransform,
2455 XCAST(SetViewport) GL_IDirect3DDeviceImpl_7_SetViewport,
2456 XCAST(MultiplyTransform) Main_IDirect3DDeviceImpl_7_3T_2T_MultiplyTransform,
2457 XCAST(GetViewport) Main_IDirect3DDeviceImpl_7_GetViewport,
2458 XCAST(SetMaterial) GL_IDirect3DDeviceImpl_7_SetMaterial,
2459 XCAST(GetMaterial) Main_IDirect3DDeviceImpl_7_GetMaterial,
2460 XCAST(SetLight) GL_IDirect3DDeviceImpl_7_SetLight,
2461 XCAST(GetLight) Main_IDirect3DDeviceImpl_7_GetLight,
2462 XCAST(SetRenderState) GL_IDirect3DDeviceImpl_7_3T_2T_SetRenderState,
2463 XCAST(GetRenderState) GL_IDirect3DDeviceImpl_7_3T_2T_GetRenderState,
2464 XCAST(BeginStateBlock) Main_IDirect3DDeviceImpl_7_BeginStateBlock,
2465 XCAST(EndStateBlock) Main_IDirect3DDeviceImpl_7_EndStateBlock,
2466 XCAST(PreLoad) Main_IDirect3DDeviceImpl_7_PreLoad,
2467 XCAST(DrawPrimitive) GL_IDirect3DDeviceImpl_7_3T_DrawPrimitive,
2468 XCAST(DrawIndexedPrimitive) GL_IDirect3DDeviceImpl_7_3T_DrawIndexedPrimitive,
2469 XCAST(SetClipStatus) Main_IDirect3DDeviceImpl_7_3T_2T_SetClipStatus,
2470 XCAST(GetClipStatus) Main_IDirect3DDeviceImpl_7_3T_2T_GetClipStatus,
2471 XCAST(DrawPrimitiveStrided) GL_IDirect3DDeviceImpl_7_3T_DrawPrimitiveStrided,
2472 XCAST(DrawIndexedPrimitiveStrided) GL_IDirect3DDeviceImpl_7_3T_DrawIndexedPrimitiveStrided,
2473 XCAST(DrawPrimitiveVB) GL_IDirect3DDeviceImpl_7_3T_DrawPrimitiveVB,
2474 XCAST(DrawIndexedPrimitiveVB) GL_IDirect3DDeviceImpl_7_3T_DrawIndexedPrimitiveVB,
2475 XCAST(ComputeSphereVisibility) Main_IDirect3DDeviceImpl_7_3T_ComputeSphereVisibility,
2476 XCAST(GetTexture) Main_IDirect3DDeviceImpl_7_3T_GetTexture,
2477 XCAST(SetTexture) GL_IDirect3DDeviceImpl_7_3T_SetTexture,
2478 XCAST(GetTextureStageState) Main_IDirect3DDeviceImpl_7_3T_GetTextureStageState,
2479 XCAST(SetTextureStageState) GL_IDirect3DDeviceImpl_7_3T_SetTextureStageState,
2480 XCAST(ValidateDevice) Main_IDirect3DDeviceImpl_7_3T_ValidateDevice,
2481 XCAST(ApplyStateBlock) Main_IDirect3DDeviceImpl_7_ApplyStateBlock,
2482 XCAST(CaptureStateBlock) Main_IDirect3DDeviceImpl_7_CaptureStateBlock,
2483 XCAST(DeleteStateBlock) Main_IDirect3DDeviceImpl_7_DeleteStateBlock,
2484 XCAST(CreateStateBlock) Main_IDirect3DDeviceImpl_7_CreateStateBlock,
2485 XCAST(Load) Main_IDirect3DDeviceImpl_7_Load,
2486 XCAST(LightEnable) GL_IDirect3DDeviceImpl_7_LightEnable,
2487 XCAST(GetLightEnable) Main_IDirect3DDeviceImpl_7_GetLightEnable,
2488 XCAST(SetClipPlane) GL_IDirect3DDeviceImpl_7_SetClipPlane,
2489 XCAST(GetClipPlane) Main_IDirect3DDeviceImpl_7_GetClipPlane,
2490 XCAST(GetInfo) Main_IDirect3DDeviceImpl_7_GetInfo,
2493 #if !defined(__STRICT_ANSI__) && defined(__GNUC__)
2498 #if !defined(__STRICT_ANSI__) && defined(__GNUC__)
2499 # define XCAST(fun) (typeof(VTABLE_IDirect3DDevice3.fun))
2501 # define XCAST(fun) (void*)
2504 ICOM_VTABLE(IDirect3DDevice3) VTABLE_IDirect3DDevice3 =
2506 ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
2507 XCAST(QueryInterface) Thunk_IDirect3DDeviceImpl_3_QueryInterface,
2508 XCAST(AddRef) Thunk_IDirect3DDeviceImpl_3_AddRef,
2509 XCAST(Release) Thunk_IDirect3DDeviceImpl_3_Release,
2510 XCAST(GetCaps) GL_IDirect3DDeviceImpl_3_2T_1T_GetCaps,
2511 XCAST(GetStats) Main_IDirect3DDeviceImpl_3_2T_1T_GetStats,
2512 XCAST(AddViewport) Main_IDirect3DDeviceImpl_3_2T_1T_AddViewport,
2513 XCAST(DeleteViewport) Main_IDirect3DDeviceImpl_3_2T_1T_DeleteViewport,
2514 XCAST(NextViewport) Main_IDirect3DDeviceImpl_3_2T_1T_NextViewport,
2515 XCAST(EnumTextureFormats) Thunk_IDirect3DDeviceImpl_3_EnumTextureFormats,
2516 XCAST(BeginScene) Thunk_IDirect3DDeviceImpl_3_BeginScene,
2517 XCAST(EndScene) Thunk_IDirect3DDeviceImpl_3_EndScene,
2518 XCAST(GetDirect3D) Thunk_IDirect3DDeviceImpl_3_GetDirect3D,
2519 XCAST(SetCurrentViewport) Main_IDirect3DDeviceImpl_3_2T_SetCurrentViewport,
2520 XCAST(GetCurrentViewport) Main_IDirect3DDeviceImpl_3_2T_GetCurrentViewport,
2521 XCAST(SetRenderTarget) Thunk_IDirect3DDeviceImpl_3_SetRenderTarget,
2522 XCAST(GetRenderTarget) Thunk_IDirect3DDeviceImpl_3_GetRenderTarget,
2523 XCAST(Begin) Main_IDirect3DDeviceImpl_3_Begin,
2524 XCAST(BeginIndexed) Main_IDirect3DDeviceImpl_3_BeginIndexed,
2525 XCAST(Vertex) Main_IDirect3DDeviceImpl_3_2T_Vertex,
2526 XCAST(Index) Main_IDirect3DDeviceImpl_3_2T_Index,
2527 XCAST(End) Main_IDirect3DDeviceImpl_3_2T_End,
2528 XCAST(GetRenderState) Thunk_IDirect3DDeviceImpl_3_GetRenderState,
2529 XCAST(SetRenderState) Thunk_IDirect3DDeviceImpl_3_SetRenderState,
2530 XCAST(GetLightState) Main_IDirect3DDeviceImpl_3_2T_GetLightState,
2531 XCAST(SetLightState) GL_IDirect3DDeviceImpl_3_2T_SetLightState,
2532 XCAST(SetTransform) Thunk_IDirect3DDeviceImpl_3_SetTransform,
2533 XCAST(GetTransform) Thunk_IDirect3DDeviceImpl_3_GetTransform,
2534 XCAST(MultiplyTransform) Thunk_IDirect3DDeviceImpl_3_MultiplyTransform,
2535 XCAST(DrawPrimitive) Thunk_IDirect3DDeviceImpl_3_DrawPrimitive,
2536 XCAST(DrawIndexedPrimitive) Thunk_IDirect3DDeviceImpl_3_DrawIndexedPrimitive,
2537 XCAST(SetClipStatus) Thunk_IDirect3DDeviceImpl_3_SetClipStatus,
2538 XCAST(GetClipStatus) Thunk_IDirect3DDeviceImpl_3_GetClipStatus,
2539 XCAST(DrawPrimitiveStrided) Thunk_IDirect3DDeviceImpl_3_DrawPrimitiveStrided,
2540 XCAST(DrawIndexedPrimitiveStrided) Thunk_IDirect3DDeviceImpl_3_DrawIndexedPrimitiveStrided,
2541 XCAST(DrawPrimitiveVB) Thunk_IDirect3DDeviceImpl_3_DrawPrimitiveVB,
2542 XCAST(DrawIndexedPrimitiveVB) Thunk_IDirect3DDeviceImpl_3_DrawIndexedPrimitiveVB,
2543 XCAST(ComputeSphereVisibility) Thunk_IDirect3DDeviceImpl_3_ComputeSphereVisibility,
2544 XCAST(GetTexture) Thunk_IDirect3DDeviceImpl_3_GetTexture,
2545 XCAST(SetTexture) Thunk_IDirect3DDeviceImpl_3_SetTexture,
2546 XCAST(GetTextureStageState) Thunk_IDirect3DDeviceImpl_3_GetTextureStageState,
2547 XCAST(SetTextureStageState) Thunk_IDirect3DDeviceImpl_3_SetTextureStageState,
2548 XCAST(ValidateDevice) Thunk_IDirect3DDeviceImpl_3_ValidateDevice,
2551 #if !defined(__STRICT_ANSI__) && defined(__GNUC__)
2556 #if !defined(__STRICT_ANSI__) && defined(__GNUC__)
2557 # define XCAST(fun) (typeof(VTABLE_IDirect3DDevice2.fun))
2559 # define XCAST(fun) (void*)
2562 ICOM_VTABLE(IDirect3DDevice2) VTABLE_IDirect3DDevice2 =
2564 ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
2565 XCAST(QueryInterface) Thunk_IDirect3DDeviceImpl_2_QueryInterface,
2566 XCAST(AddRef) Thunk_IDirect3DDeviceImpl_2_AddRef,
2567 XCAST(Release) Thunk_IDirect3DDeviceImpl_2_Release,
2568 XCAST(GetCaps) Thunk_IDirect3DDeviceImpl_2_GetCaps,
2569 XCAST(SwapTextureHandles) Main_IDirect3DDeviceImpl_2_1T_SwapTextureHandles,
2570 XCAST(GetStats) Thunk_IDirect3DDeviceImpl_2_GetStats,
2571 XCAST(AddViewport) Thunk_IDirect3DDeviceImpl_2_AddViewport,
2572 XCAST(DeleteViewport) Thunk_IDirect3DDeviceImpl_2_DeleteViewport,
2573 XCAST(NextViewport) Thunk_IDirect3DDeviceImpl_2_NextViewport,
2574 XCAST(EnumTextureFormats) GL_IDirect3DDeviceImpl_2_1T_EnumTextureFormats,
2575 XCAST(BeginScene) Thunk_IDirect3DDeviceImpl_2_BeginScene,
2576 XCAST(EndScene) Thunk_IDirect3DDeviceImpl_2_EndScene,
2577 XCAST(GetDirect3D) Thunk_IDirect3DDeviceImpl_2_GetDirect3D,
2578 XCAST(SetCurrentViewport) Thunk_IDirect3DDeviceImpl_2_SetCurrentViewport,
2579 XCAST(GetCurrentViewport) Thunk_IDirect3DDeviceImpl_2_GetCurrentViewport,
2580 XCAST(SetRenderTarget) Thunk_IDirect3DDeviceImpl_2_SetRenderTarget,
2581 XCAST(GetRenderTarget) Thunk_IDirect3DDeviceImpl_2_GetRenderTarget,
2582 XCAST(Begin) Main_IDirect3DDeviceImpl_2_Begin,
2583 XCAST(BeginIndexed) Main_IDirect3DDeviceImpl_2_BeginIndexed,
2584 XCAST(Vertex) Thunk_IDirect3DDeviceImpl_2_Vertex,
2585 XCAST(Index) Thunk_IDirect3DDeviceImpl_2_Index,
2586 XCAST(End) Thunk_IDirect3DDeviceImpl_2_End,
2587 XCAST(GetRenderState) Thunk_IDirect3DDeviceImpl_2_GetRenderState,
2588 XCAST(SetRenderState) Thunk_IDirect3DDeviceImpl_2_SetRenderState,
2589 XCAST(GetLightState) Thunk_IDirect3DDeviceImpl_2_GetLightState,
2590 XCAST(SetLightState) Thunk_IDirect3DDeviceImpl_2_SetLightState,
2591 XCAST(SetTransform) Thunk_IDirect3DDeviceImpl_2_SetTransform,
2592 XCAST(GetTransform) Thunk_IDirect3DDeviceImpl_2_GetTransform,
2593 XCAST(MultiplyTransform) Thunk_IDirect3DDeviceImpl_2_MultiplyTransform,
2594 XCAST(DrawPrimitive) GL_IDirect3DDeviceImpl_2_DrawPrimitive,
2595 XCAST(DrawIndexedPrimitive) GL_IDirect3DDeviceImpl_2_DrawIndexedPrimitive,
2596 XCAST(SetClipStatus) Thunk_IDirect3DDeviceImpl_2_SetClipStatus,
2597 XCAST(GetClipStatus) Thunk_IDirect3DDeviceImpl_2_GetClipStatus,
2600 #if !defined(__STRICT_ANSI__) && defined(__GNUC__)
2605 #if !defined(__STRICT_ANSI__) && defined(__GNUC__)
2606 # define XCAST(fun) (typeof(VTABLE_IDirect3DDevice.fun))
2608 # define XCAST(fun) (void*)
2611 ICOM_VTABLE(IDirect3DDevice) VTABLE_IDirect3DDevice =
2613 ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
2614 XCAST(QueryInterface) Thunk_IDirect3DDeviceImpl_1_QueryInterface,
2615 XCAST(AddRef) Thunk_IDirect3DDeviceImpl_1_AddRef,
2616 XCAST(Release) Thunk_IDirect3DDeviceImpl_1_Release,
2617 XCAST(Initialize) Main_IDirect3DDeviceImpl_1_Initialize,
2618 XCAST(GetCaps) Thunk_IDirect3DDeviceImpl_1_GetCaps,
2619 XCAST(SwapTextureHandles) Thunk_IDirect3DDeviceImpl_1_SwapTextureHandles,
2620 XCAST(CreateExecuteBuffer) GL_IDirect3DDeviceImpl_1_CreateExecuteBuffer,
2621 XCAST(GetStats) Thunk_IDirect3DDeviceImpl_1_GetStats,
2622 XCAST(Execute) Main_IDirect3DDeviceImpl_1_Execute,
2623 XCAST(AddViewport) Thunk_IDirect3DDeviceImpl_1_AddViewport,
2624 XCAST(DeleteViewport) Thunk_IDirect3DDeviceImpl_1_DeleteViewport,
2625 XCAST(NextViewport) Thunk_IDirect3DDeviceImpl_1_NextViewport,
2626 XCAST(Pick) Main_IDirect3DDeviceImpl_1_Pick,
2627 XCAST(GetPickRecords) Main_IDirect3DDeviceImpl_1_GetPickRecords,
2628 XCAST(EnumTextureFormats) Thunk_IDirect3DDeviceImpl_1_EnumTextureFormats,
2629 XCAST(CreateMatrix) Main_IDirect3DDeviceImpl_1_CreateMatrix,
2630 XCAST(SetMatrix) Main_IDirect3DDeviceImpl_1_SetMatrix,
2631 XCAST(GetMatrix) Main_IDirect3DDeviceImpl_1_GetMatrix,
2632 XCAST(DeleteMatrix) Main_IDirect3DDeviceImpl_1_DeleteMatrix,
2633 XCAST(BeginScene) Thunk_IDirect3DDeviceImpl_1_BeginScene,
2634 XCAST(EndScene) Thunk_IDirect3DDeviceImpl_1_EndScene,
2635 XCAST(GetDirect3D) Thunk_IDirect3DDeviceImpl_1_GetDirect3D,
2638 #if !defined(__STRICT_ANSI__) && defined(__GNUC__)
2642 static HRESULT d3ddevice_clear(IDirect3DDeviceImpl *This,
2643 WINE_GL_BUFFER_TYPE buffer_type,
2651 IDirect3DDeviceGLImpl *glThis = (IDirect3DDeviceGLImpl *) This;
2652 GLbitfield bitfield = 0;
2656 TRACE("(%p)->(%08lx,%p,%08lx,%08lx,%f,%08lx)\n", This, dwCount, lpRects, dwFlags, dwColor, dvZ, dwStencil);
2657 if (TRACE_ON(ddraw)) {
2660 TRACE(" rectangles : \n");
2661 for (i = 0; i < dwCount; i++) {
2662 TRACE(" - %ld x %ld %ld x %ld\n", lpRects[i].u1.x1, lpRects[i].u2.y1, lpRects[i].u3.x2, lpRects[i].u4.y2);
2671 rect.u3.x2 = This->surface->surface_desc.dwWidth;
2672 rect.u4.y2 = This->surface->surface_desc.dwHeight;
2676 /* Clears the screen */
2679 if (dwFlags & D3DCLEAR_TARGET) {
2680 if (glThis->state[buffer_type] == SURFACE_MEMORY_DIRTY) {
2681 /* TODO: optimize here the case where Clear changes all the screen... */
2682 This->flush_to_framebuffer(This, &(glThis->lock_rect[buffer_type]), glThis->lock_surf[buffer_type]);
2684 glThis->state[buffer_type] = SURFACE_GL;
2687 if (dwFlags & D3DCLEAR_ZBUFFER) {
2688 bitfield |= GL_DEPTH_BUFFER_BIT;
2689 if (glThis->depth_mask == FALSE) {
2690 glDepthMask(GL_TRUE); /* Enables Z writing to be sure to delete also the Z buffer */
2692 if (dvZ != glThis->prev_clear_Z) {
2694 glThis->prev_clear_Z = dvZ;
2696 TRACE(" depth value : %f\n", dvZ);
2698 if (dwFlags & D3DCLEAR_STENCIL) {
2699 bitfield |= GL_STENCIL_BUFFER_BIT;
2700 if (dwStencil != glThis->prev_clear_stencil) {
2701 glClearStencil(dwStencil);
2702 glThis->prev_clear_stencil = dwStencil;
2704 TRACE(" stencil value : %ld\n", dwStencil);
2706 if (dwFlags & D3DCLEAR_TARGET) {
2707 bitfield |= GL_COLOR_BUFFER_BIT;
2708 if (dwColor != glThis->prev_clear_color) {
2709 glClearColor(((dwColor >> 16) & 0xFF) / 255.0,
2710 ((dwColor >> 8) & 0xFF) / 255.0,
2711 ((dwColor >> 0) & 0xFF) / 255.0,
2712 ((dwColor >> 24) & 0xFF) / 255.0);
2713 glThis->prev_clear_color = dwColor;
2715 TRACE(" color value (ARGB) : %08lx\n", dwColor);
2718 glEnable(GL_SCISSOR_TEST);
2719 for (i = 0; i < dwCount; i++) {
2720 glScissor(lpRects[i].u1.x1, This->surface->surface_desc.dwHeight - lpRects[i].u4.y2,
2721 lpRects[i].u3.x2 - lpRects[i].u1.x1, lpRects[i].u4.y2 - lpRects[i].u2.y1);
2724 glDisable(GL_SCISSOR_TEST);
2726 if (dwFlags & D3DCLEAR_ZBUFFER) {
2727 if (glThis->depth_mask == FALSE) glDepthMask(GL_FALSE);
2735 static HRESULT d3ddevice_clear_back(IDirect3DDeviceImpl *This,
2743 return d3ddevice_clear(This, WINE_GL_BUFFER_BACK, dwCount, lpRects, dwFlags, dwColor, dvZ, dwStencil);
2747 setup_rect_and_surface_for_blt(IDirectDrawSurfaceImpl *This,
2748 WINE_GL_BUFFER_TYPE *buffer_type_p, D3DRECT *rect)
2750 IDirect3DDeviceGLImpl *gl_d3d_dev = (IDirect3DDeviceGLImpl *) This->d3ddevice;
2751 WINE_GL_BUFFER_TYPE buffer_type;
2753 /* First check if we BLT to the backbuffer... */
2754 if ((This->surface_desc.ddsCaps.dwCaps & (DDSCAPS_BACKBUFFER)) != 0) {
2755 buffer_type = WINE_GL_BUFFER_BACK;
2756 } else if ((This->surface_desc.ddsCaps.dwCaps & (DDSCAPS_FRONTBUFFER|DDSCAPS_PRIMARYSURFACE)) != 0) {
2757 buffer_type = WINE_GL_BUFFER_FRONT;
2759 ERR("Only BLT override to front or back-buffer is supported for now !\n");
2760 return DDERR_INVALIDPARAMS;
2763 if ((gl_d3d_dev->state[buffer_type] == SURFACE_MEMORY_DIRTY) &&
2764 (rect->u1.x1 >= gl_d3d_dev->lock_rect[buffer_type].left) &&
2765 (rect->u2.y1 >= gl_d3d_dev->lock_rect[buffer_type].top) &&
2766 (rect->u3.x2 <= gl_d3d_dev->lock_rect[buffer_type].right) &&
2767 (rect->u4.y2 <= gl_d3d_dev->lock_rect[buffer_type].bottom)) {
2768 /* If the memory zone is already dirty, use the standard 'in memory' blit operations and not
2771 return DDERR_INVALIDPARAMS;
2773 *buffer_type_p = buffer_type;
2779 d3ddevice_blt(IDirectDrawSurfaceImpl *This, LPRECT rdst,
2780 LPDIRECTDRAWSURFACE7 src, LPRECT rsrc,
2781 DWORD dwFlags, LPDDBLTFX lpbltfx)
2783 WINE_GL_BUFFER_TYPE buffer_type;
2787 rect.u1.x1 = rdst->left;
2788 rect.u2.y1 = rdst->top;
2789 rect.u3.x2 = rdst->right;
2790 rect.u4.y2 = rdst->bottom;
2794 rect.u3.x2 = This->surface_desc.dwWidth;
2795 rect.u4.y2 = This->surface_desc.dwHeight;
2798 if (setup_rect_and_surface_for_blt(This, &buffer_type, &rect) != DD_OK) return DDERR_INVALIDPARAMS;
2800 if (dwFlags & DDBLT_COLORFILL) {
2801 /* This is easy to handle for the D3D Device... */
2805 /* The color as given in the Blt function is in the format of the frame-buffer...
2806 * 'clear' expect it in ARGB format => we need to do some conversion :-)
2808 if (This->surface_desc.u4.ddpfPixelFormat.dwFlags & DDPF_PALETTEINDEXED8) {
2809 if (This->palette) {
2810 color = ((0xFF000000) |
2811 (This->palette->palents[lpbltfx->u5.dwFillColor].peRed << 16) |
2812 (This->palette->palents[lpbltfx->u5.dwFillColor].peGreen << 8) |
2813 (This->palette->palents[lpbltfx->u5.dwFillColor].peBlue));
2817 } else if ((This->surface_desc.u4.ddpfPixelFormat.dwFlags & DDPF_RGB) &&
2818 (((This->surface_desc.u4.ddpfPixelFormat.dwFlags & DDPF_ALPHAPIXELS) == 0) ||
2819 (This->surface_desc.u4.ddpfPixelFormat.u5.dwRGBAlphaBitMask == 0x00000000))) {
2820 if ((This->surface_desc.u4.ddpfPixelFormat.u1.dwRGBBitCount == 16) &&
2821 (This->surface_desc.u4.ddpfPixelFormat.u2.dwRBitMask == 0xF800) &&
2822 (This->surface_desc.u4.ddpfPixelFormat.u3.dwGBitMask == 0x07E0) &&
2823 (This->surface_desc.u4.ddpfPixelFormat.u4.dwBBitMask == 0x001F)) {
2824 if (lpbltfx->u5.dwFillColor == 0xFFFF) {
2827 color = ((0xFF000000) |
2828 ((lpbltfx->u5.dwFillColor & 0xF800) << 8) |
2829 ((lpbltfx->u5.dwFillColor & 0x07E0) << 5) |
2830 ((lpbltfx->u5.dwFillColor & 0x001F) << 3));
2832 } else if (((This->surface_desc.u4.ddpfPixelFormat.u1.dwRGBBitCount == 32) ||
2833 (This->surface_desc.u4.ddpfPixelFormat.u1.dwRGBBitCount == 24)) &&
2834 (This->surface_desc.u4.ddpfPixelFormat.u2.dwRBitMask == 0x00FF0000) &&
2835 (This->surface_desc.u4.ddpfPixelFormat.u3.dwGBitMask == 0x0000FF00) &&
2836 (This->surface_desc.u4.ddpfPixelFormat.u4.dwBBitMask == 0x000000FF)) {
2837 color = 0xFF000000 | lpbltfx->u5.dwFillColor;
2839 ERR("Wrong surface type for BLT override (unknown RGB format) !\n");
2840 return DDERR_INVALIDPARAMS;
2843 ERR("Wrong surface type for BLT override !\n");
2844 return DDERR_INVALIDPARAMS;
2847 TRACE(" executing D3D Device override.\n");
2851 glGetIntegerv(GL_DRAW_BUFFER, &prev_draw);
2852 if (buffer_type == WINE_GL_BUFFER_FRONT)
2853 glDrawBuffer(GL_FRONT);
2855 glDrawBuffer(GL_BACK);
2857 d3ddevice_clear(This->d3ddevice, buffer_type, 1, &rect, D3DCLEAR_TARGET, color, 0.0, 0x00000000);
2859 if (((buffer_type == WINE_GL_BUFFER_FRONT) && (prev_draw == GL_BACK)) ||
2860 ((buffer_type == WINE_GL_BUFFER_BACK) && (prev_draw == GL_FRONT)))
2861 glDrawBuffer(prev_draw);
2866 } else if ((dwFlags & (~(DDBLT_KEYSRC|DDBLT_WAIT|DDBLT_ASYNC))) == 0) {
2867 /* Normal blit without any special case... */
2869 /* And which has a SRC surface */
2870 IDirectDrawSurfaceImpl *src_impl = ICOM_OBJECT(IDirectDrawSurfaceImpl, IDirectDrawSurface7, src);
2872 if ((src_impl->surface_desc.ddsCaps.dwCaps & DDSCAPS_3DDEVICE) &&
2873 (src_impl->d3ddevice == This->d3ddevice) &&
2874 ((dwFlags & DDBLT_KEYSRC) == 0)) {
2875 /* Both are 3D devices and using the same GL device and the Blt is without color-keying */
2879 WINE_GL_BUFFER_TYPE src_buffer_type;
2880 IDirect3DDeviceGLImpl *gl_d3d_dev = (IDirect3DDeviceGLImpl *) This->d3ddevice;
2886 src_rect.u1.x1 = rsrc->left;
2887 src_rect.u2.y1 = rsrc->top;
2888 src_rect.u3.x2 = rsrc->right;
2889 src_rect.u4.y2 = rsrc->bottom;
2893 src_rect.u3.x2 = src_impl->surface_desc.dwWidth;
2894 src_rect.u4.y2 = src_impl->surface_desc.dwHeight;
2897 width = src_rect.u3.x2 - src_rect.u1.x1;
2898 height = src_rect.u4.y2 - src_rect.u2.y1;
2900 if ((width != (rect.u3.x2 - rect.u1.x1)) ||
2901 (height != (rect.u4.y2 - rect.u2.y1))) {
2902 FIXME(" buffer to buffer copy not supported with stretching yet !\n");
2903 return DDERR_INVALIDPARAMS;
2906 /* First check if we BLT from the backbuffer... */
2907 if ((src_impl->surface_desc.ddsCaps.dwCaps & (DDSCAPS_BACKBUFFER)) != 0) {
2908 src_buffer_type = WINE_GL_BUFFER_BACK;
2909 } else if ((src_impl->surface_desc.ddsCaps.dwCaps & (DDSCAPS_FRONTBUFFER|DDSCAPS_PRIMARYSURFACE)) != 0) {
2910 src_buffer_type = WINE_GL_BUFFER_FRONT;
2912 ERR("Unexpected case in direct buffer to buffer copy !\n");
2913 return DDERR_INVALIDPARAMS;
2916 TRACE(" using direct buffer to buffer copy.\n");
2920 opt_bitmap = d3ddevice_set_state_for_flush(This->d3ddevice, (LPCRECT) &rect, FALSE, &initial);
2922 if (upload_surface_to_tex_memory_init(This, 0, &gl_d3d_dev->current_internal_format,
2923 initial, FALSE, UNLOCK_TEX_SIZE, UNLOCK_TEX_SIZE) != DD_OK) {
2924 ERR(" unsupported pixel format at direct buffer to buffer copy.\n");
2926 return DDERR_INVALIDPARAMS;
2929 glGetIntegerv(GL_DRAW_BUFFER, &prev_draw);
2930 if (buffer_type == WINE_GL_BUFFER_FRONT)
2931 glDrawBuffer(GL_FRONT);
2933 glDrawBuffer(GL_BACK);
2935 if (src_buffer_type == WINE_GL_BUFFER_FRONT)
2936 glReadBuffer(GL_FRONT);
2938 glReadBuffer(GL_BACK);
2940 /* Now the serious stuff happens. Basically, we copy from the source buffer to the texture memory.
2941 And directly re-draws this on the destination buffer. */
2942 for (y = 0; y < height; y += UNLOCK_TEX_SIZE) {
2945 if ((src_rect.u2.y1 + y + UNLOCK_TEX_SIZE) > src_impl->surface_desc.dwHeight)
2946 get_height = src_impl->surface_desc.dwHeight - (src_rect.u2.y1 + y);
2948 get_height = UNLOCK_TEX_SIZE;
2950 for (x = 0; x < width; x += UNLOCK_TEX_SIZE) {
2953 if ((src_rect.u1.x1 + x + UNLOCK_TEX_SIZE) > src_impl->surface_desc.dwWidth)
2954 get_width = src_impl->surface_desc.dwWidth - (src_rect.u1.x1 + x);
2956 get_width = UNLOCK_TEX_SIZE;
2958 glCopyTexSubImage2D(GL_TEXTURE_2D, 0,
2959 0, UNLOCK_TEX_SIZE - get_height,
2960 src_rect.u1.x1 + x, src_impl->surface_desc.dwHeight - (src_rect.u2.y1 + y + get_height),
2961 get_width, get_height);
2964 glTexCoord2f(0.0, 0.0);
2965 glVertex3d(rect.u1.x1 + x,
2966 rect.u2.y1 + y + UNLOCK_TEX_SIZE,
2968 glTexCoord2f(1.0, 0.0);
2969 glVertex3d(rect.u1.x1 + x + UNLOCK_TEX_SIZE,
2970 rect.u2.y1 + y + UNLOCK_TEX_SIZE,
2972 glTexCoord2f(1.0, 1.0);
2973 glVertex3d(rect.u1.x1 + x + UNLOCK_TEX_SIZE,
2976 glTexCoord2f(0.0, 1.0);
2977 glVertex3d(rect.u1.x1 + x,
2984 upload_surface_to_tex_memory_release();
2985 d3ddevice_restore_state_after_flush(This->d3ddevice, opt_bitmap, FALSE);
2987 if (((buffer_type == WINE_GL_BUFFER_FRONT) && (prev_draw == GL_BACK)) ||
2988 ((buffer_type == WINE_GL_BUFFER_BACK) && (prev_draw == GL_FRONT)))
2989 glDrawBuffer(prev_draw);
2995 /* This is the normal 'with source' Blit. Use the texture engine to do the Blt for us
2996 (this prevents calling glReadPixels) */
3000 IDirect3DDeviceGLImpl *gl_d3d_dev = (IDirect3DDeviceGLImpl *) This->d3ddevice;
3004 double x_stretch, y_stretch;
3007 src_rect.u1.x1 = rsrc->left;
3008 src_rect.u2.y1 = rsrc->top;
3009 src_rect.u3.x2 = rsrc->right;
3010 src_rect.u4.y2 = rsrc->bottom;
3014 src_rect.u3.x2 = src_impl->surface_desc.dwWidth;
3015 src_rect.u4.y2 = src_impl->surface_desc.dwHeight;
3018 width = src_rect.u3.x2 - src_rect.u1.x1;
3019 height = src_rect.u4.y2 - src_rect.u2.y1;
3021 x_stretch = (double) (rect.u3.x2 - rect.u1.x1) / (double) width;
3022 y_stretch = (double) (rect.u4.y2 - rect.u2.y1) / (double) height;
3024 TRACE(" using memory to buffer Blt overide.\n");
3028 opt_bitmap = d3ddevice_set_state_for_flush(This->d3ddevice, (LPCRECT) &rect, ((dwFlags & DDBLT_KEYSRC) != 0), &initial);
3030 if (upload_surface_to_tex_memory_init(src_impl, 0, &gl_d3d_dev->current_internal_format,
3031 initial, ((dwFlags & DDBLT_KEYSRC) != 0), UNLOCK_TEX_SIZE, UNLOCK_TEX_SIZE) != DD_OK) {
3032 ERR(" unsupported pixel format at memory to buffer Blt overide.\n");
3034 return DDERR_INVALIDPARAMS;
3037 glGetIntegerv(GL_DRAW_BUFFER, &prev_draw);
3038 if (buffer_type == WINE_GL_BUFFER_FRONT)
3039 glDrawBuffer(GL_FRONT);
3041 glDrawBuffer(GL_BACK);
3043 /* Now the serious stuff happens. This is basically the same code that for the memory
3044 flush to frame buffer ... with stretching and different rectangles added :-) */
3045 for (y = 0; y < height; y += UNLOCK_TEX_SIZE) {
3048 flush_rect.top = src_rect.u2.y1 + y;
3049 flush_rect.bottom = ((src_rect.u2.y1 + y + UNLOCK_TEX_SIZE > src_rect.u4.y2) ?
3051 (src_rect.u2.y1 + y + UNLOCK_TEX_SIZE));
3053 for (x = 0; x < width; x += UNLOCK_TEX_SIZE) {
3054 flush_rect.left = src_rect.u1.x1 + x;
3055 flush_rect.right = ((src_rect.u1.x1 + x + UNLOCK_TEX_SIZE > src_rect.u3.x2) ?
3057 (src_rect.u1.x1 + x + UNLOCK_TEX_SIZE));
3059 upload_surface_to_tex_memory(&flush_rect, 0, 0, &(gl_d3d_dev->surface_ptr));
3062 glTexCoord2f(0.0, 0.0);
3063 glVertex3d(rect.u1.x1 + (x * x_stretch),
3064 rect.u2.y1 + (y * y_stretch),
3066 glTexCoord2f(1.0, 0.0);
3067 glVertex3d(rect.u1.x1 + ((x + UNLOCK_TEX_SIZE) * x_stretch),
3068 rect.u2.y1 + (y * y_stretch),
3070 glTexCoord2f(1.0, 1.0);
3071 glVertex3d(rect.u1.x1 + ((x + UNLOCK_TEX_SIZE) * x_stretch),
3072 rect.u2.y1 + ((y + UNLOCK_TEX_SIZE) * y_stretch),
3074 glTexCoord2f(0.0, 1.0);
3075 glVertex3d(rect.u1.x1 + (x * x_stretch),
3076 rect.u2.y1 + ((y + UNLOCK_TEX_SIZE) * y_stretch),
3082 upload_surface_to_tex_memory_release();
3083 d3ddevice_restore_state_after_flush(This->d3ddevice, opt_bitmap, ((dwFlags & DDBLT_KEYSRC) != 0));
3085 if (((buffer_type == WINE_GL_BUFFER_FRONT) && (prev_draw == GL_BACK)) ||
3086 ((buffer_type == WINE_GL_BUFFER_BACK) && (prev_draw == GL_FRONT)))
3087 glDrawBuffer(prev_draw);
3095 return DDERR_INVALIDPARAMS;
3099 d3ddevice_bltfast(IDirectDrawSurfaceImpl *This, DWORD dstx,
3100 DWORD dsty, LPDIRECTDRAWSURFACE7 src,
3101 LPRECT rsrc, DWORD trans)
3105 IDirectDrawSurfaceImpl *src_impl = ICOM_OBJECT(IDirectDrawSurfaceImpl, IDirectDrawSurface7, src);
3106 IDirect3DDeviceGLImpl *gl_d3d_dev = (IDirect3DDeviceGLImpl *) This->d3ddevice;
3107 WINE_GL_BUFFER_TYPE buffer_type;
3111 int width, height, x, y;
3113 /* Cannot support DSTCOLORKEY blitting... */
3114 if ((trans & DDBLTFAST_DESTCOLORKEY) != 0) return DDERR_INVALIDPARAMS;
3117 WARN("rsrc is NULL - getting the whole surface !!\n");
3119 rsrc->left = rsrc->top = 0;
3120 rsrc->right = src_impl->surface_desc.dwWidth;
3121 rsrc->bottom = src_impl->surface_desc.dwHeight;
3129 rdst.right = dstx + (rsrc->right - rsrc->left);
3130 if (rdst.right > This->surface_desc.dwWidth) {
3131 rsrc->right -= (This->surface_desc.dwWidth - rdst.right);
3132 rdst.right = This->surface_desc.dwWidth;
3134 rdst.bottom = dsty + (rsrc->bottom - rsrc->top);
3135 if (rdst.bottom > This->surface_desc.dwHeight) {
3136 rsrc->bottom -= (This->surface_desc.dwHeight - rdst.bottom);
3137 rdst.bottom = This->surface_desc.dwHeight;
3140 width = rsrc->right - rsrc->left;
3141 height = rsrc->bottom - rsrc->top;
3143 if (setup_rect_and_surface_for_blt(This, &buffer_type, (D3DRECT *) &rdst) != DD_OK) return DDERR_INVALIDPARAMS;
3145 TRACE(" using BltFast memory to frame buffer overide.\n");
3149 opt_bitmap = d3ddevice_set_state_for_flush(This->d3ddevice, &rdst, (trans & DDBLTFAST_SRCCOLORKEY) != 0, &initial);
3151 if (upload_surface_to_tex_memory_init(src_impl, 0, &gl_d3d_dev->current_internal_format,
3152 initial, (trans & DDBLTFAST_SRCCOLORKEY) != 0,
3153 UNLOCK_TEX_SIZE, UNLOCK_TEX_SIZE) != DD_OK) {
3154 ERR(" unsupported pixel format at memory to buffer Blt overide.\n");
3156 return DDERR_INVALIDPARAMS;
3159 glGetIntegerv(GL_DRAW_BUFFER, &prev_draw);
3160 if (buffer_type == WINE_GL_BUFFER_FRONT)
3161 glDrawBuffer(GL_FRONT);
3163 glDrawBuffer(GL_BACK);
3165 /* Now the serious stuff happens. This is basically the same code that for the memory
3166 flush to frame buffer but with different rectangles for source and destination :-) */
3167 for (y = 0; y < height; y += UNLOCK_TEX_SIZE) {
3170 flush_rect.top = rsrc->top + y;
3171 flush_rect.bottom = ((rsrc->top + y + UNLOCK_TEX_SIZE > rsrc->bottom) ?
3173 (rsrc->top + y + UNLOCK_TEX_SIZE));
3175 for (x = 0; x < width; x += UNLOCK_TEX_SIZE) {
3176 flush_rect.left = rsrc->left + x;
3177 flush_rect.right = ((rsrc->left + x + UNLOCK_TEX_SIZE > rsrc->right) ?
3179 (rsrc->left + x + UNLOCK_TEX_SIZE));
3181 upload_surface_to_tex_memory(&flush_rect, 0, 0, &(gl_d3d_dev->surface_ptr));
3184 glTexCoord2f(0.0, 0.0);
3185 glVertex3d(rdst.left + x,
3188 glTexCoord2f(1.0, 0.0);
3189 glVertex3d(rdst.left + (x + UNLOCK_TEX_SIZE),
3192 glTexCoord2f(1.0, 1.0);
3193 glVertex3d(rdst.left + (x + UNLOCK_TEX_SIZE),
3194 rdst.top + (y + UNLOCK_TEX_SIZE),
3196 glTexCoord2f(0.0, 1.0);
3197 glVertex3d(rdst.left + x,
3198 rdst.top + (y + UNLOCK_TEX_SIZE),
3204 upload_surface_to_tex_memory_release();
3205 d3ddevice_restore_state_after_flush(This->d3ddevice, opt_bitmap, (trans & DDBLTFAST_SRCCOLORKEY) != 0);
3207 if (((buffer_type == WINE_GL_BUFFER_FRONT) && (prev_draw == GL_BACK)) ||
3208 ((buffer_type == WINE_GL_BUFFER_BACK) && (prev_draw == GL_FRONT)))
3209 glDrawBuffer(prev_draw);
3217 d3ddevice_set_ortho(IDirect3DDeviceImpl *This)
3219 GLfloat height, width;
3220 GLfloat trans_mat[16];
3222 TRACE("(%p)\n", This);
3224 width = This->surface->surface_desc.dwWidth;
3225 height = This->surface->surface_desc.dwHeight;
3227 /* The X axis is straighforward.. For the Y axis, we need to convert 'D3D' screen coordinates
3228 to OpenGL screen coordinates (ie the upper left corner is not the same).
3229 For Z, the mystery is what should it be mapped to ? Ie should the resulting range be between
3230 -1.0 and 1.0 (as the X and Y coordinates) or between 0.0 and 1.0 ? */
3231 trans_mat[ 0] = 2.0 / width; trans_mat[ 4] = 0.0; trans_mat[ 8] = 0.0; trans_mat[12] = -1.0;
3232 trans_mat[ 1] = 0.0; trans_mat[ 5] = -2.0 / height; trans_mat[ 9] = 0.0; trans_mat[13] = 1.0;
3233 trans_mat[ 2] = 0.0; trans_mat[ 6] = 0.0; trans_mat[10] = 2.0; trans_mat[14] = -1.0;
3234 trans_mat[ 3] = 0.0; trans_mat[ 7] = 0.0; trans_mat[11] = 0.0; trans_mat[15] = 1.0;
3237 glMatrixMode(GL_MODELVIEW);
3239 /* See the OpenGL Red Book for an explanation of the following translation (in the OpenGL
3240 Correctness Tips section).
3242 Basically, from what I understood, if the game does not filter the font texture,
3243 as the 'real' pixel will lie at the middle of the two texels, OpenGL may choose the wrong
3244 one and we will have strange artifacts (as the rounding and stuff may give different results
3245 for different pixels, ie sometimes take the left pixel, sometimes the right).
3247 glTranslatef(0.375, 0.375, 0);
3248 glMatrixMode(GL_PROJECTION);
3249 glLoadMatrixf(trans_mat);
3254 d3ddevice_set_matrices(IDirect3DDeviceImpl *This, DWORD matrices,
3255 D3DMATRIX *world_mat, D3DMATRIX *view_mat, D3DMATRIX *proj_mat)
3257 TRACE("(%p,%08lx,%p,%p,%p)\n", This, matrices, world_mat, view_mat, proj_mat);
3260 if ((matrices & (VIEWMAT_CHANGED|WORLDMAT_CHANGED)) != 0) {
3261 glMatrixMode(GL_MODELVIEW);
3262 glLoadMatrixf((float *) view_mat);
3264 /* Now also re-loads all the Lights and Clipping Planes using the new matrices */
3265 if (This->state_block.render_state[D3DRENDERSTATE_CLIPPING - 1] != FALSE) {
3268 for (i = 0, runner = 0x00000001; i < This->max_clipping_planes; i++, runner <<= 1) {
3269 if (runner & This->state_block.render_state[D3DRENDERSTATE_CLIPPLANEENABLE - 1]) {
3272 plane[0] = This->clipping_planes[i].plane[0];
3273 plane[1] = This->clipping_planes[i].plane[1];
3274 plane[2] = This->clipping_planes[i].plane[2];
3275 plane[3] = This->clipping_planes[i].plane[3];
3277 glClipPlane( GL_CLIP_PLANE0 + i, (const GLdouble*) (&plane) );
3281 if (This->state_block.render_state[D3DRENDERSTATE_LIGHTING - 1] != FALSE) {
3285 for (i = 0, runner = 0x00000001; i < MAX_LIGHTS; i++, runner <<= 1) {
3286 if (runner & This->active_lights) {
3287 switch (This->light_parameters[i].dltType) {
3288 case D3DLIGHT_DIRECTIONAL: {
3290 float cut_off = 180.0;
3292 glLightfv(GL_LIGHT0 + i, GL_AMBIENT, (float *) &(This->light_parameters[i].dcvAmbient));
3293 glLightfv(GL_LIGHT0 + i, GL_DIFFUSE, (float *) &(This->light_parameters[i].dcvDiffuse));
3294 glLightfv(GL_LIGHT0 + i, GL_SPECULAR, (float *) &(This->light_parameters[i].dcvSpecular));
3295 glLightfv(GL_LIGHT0 + i, GL_SPOT_CUTOFF, &cut_off);
3297 direction[0] = This->light_parameters[i].dvDirection.u1.x;
3298 direction[1] = This->light_parameters[i].dvDirection.u2.y;
3299 direction[2] = This->light_parameters[i].dvDirection.u3.z;
3301 glLightfv(GL_LIGHT0 + i, GL_POSITION, (float *) direction);
3304 case D3DLIGHT_POINT: {
3306 float cut_off = 180.0;
3308 glLightfv(GL_LIGHT0 + i, GL_AMBIENT, (float *) &(This->light_parameters[i].dcvAmbient));
3309 glLightfv(GL_LIGHT0 + i, GL_DIFFUSE, (float *) &(This->light_parameters[i].dcvDiffuse));
3310 glLightfv(GL_LIGHT0 + i, GL_SPECULAR, (float *) &(This->light_parameters[i].dcvSpecular));
3311 position[0] = This->light_parameters[i].dvPosition.u1.x;
3312 position[1] = This->light_parameters[i].dvPosition.u2.y;
3313 position[2] = This->light_parameters[i].dvPosition.u3.z;
3315 glLightfv(GL_LIGHT0 + i, GL_POSITION, (float *) position);
3316 glLightfv(GL_LIGHT0 + i, GL_CONSTANT_ATTENUATION, &(This->light_parameters[i].dvAttenuation0));
3317 glLightfv(GL_LIGHT0 + i, GL_LINEAR_ATTENUATION, &(This->light_parameters[i].dvAttenuation1));
3318 glLightfv(GL_LIGHT0 + i, GL_QUADRATIC_ATTENUATION, &(This->light_parameters[i].dvAttenuation2));
3319 glLightfv(GL_LIGHT0 + i, GL_SPOT_CUTOFF, &cut_off);
3322 case D3DLIGHT_SPOT: {
3325 float cut_off = 90.0 * (This->light_parameters[i].dvPhi / M_PI);
3327 glLightfv(GL_LIGHT0 + i, GL_AMBIENT, (float *) &(This->light_parameters[i].dcvAmbient));
3328 glLightfv(GL_LIGHT0 + i, GL_DIFFUSE, (float *) &(This->light_parameters[i].dcvDiffuse));
3329 glLightfv(GL_LIGHT0 + i, GL_SPECULAR, (float *) &(This->light_parameters[i].dcvSpecular));
3331 direction[0] = This->light_parameters[i].dvDirection.u1.x;
3332 direction[1] = This->light_parameters[i].dvDirection.u2.y;
3333 direction[2] = This->light_parameters[i].dvDirection.u3.z;
3335 glLightfv(GL_LIGHT0 + i, GL_SPOT_DIRECTION, (float *) direction);
3336 position[0] = This->light_parameters[i].dvPosition.u1.x;
3337 position[1] = This->light_parameters[i].dvPosition.u2.y;
3338 position[2] = This->light_parameters[i].dvPosition.u3.z;
3340 glLightfv(GL_LIGHT0 + i, GL_POSITION, (float *) position);
3341 glLightfv(GL_LIGHT0 + i, GL_CONSTANT_ATTENUATION, &(This->light_parameters[i].dvAttenuation0));
3342 glLightfv(GL_LIGHT0 + i, GL_LINEAR_ATTENUATION, &(This->light_parameters[i].dvAttenuation1));
3343 glLightfv(GL_LIGHT0 + i, GL_QUADRATIC_ATTENUATION, &(This->light_parameters[i].dvAttenuation2));
3344 glLightfv(GL_LIGHT0 + i, GL_SPOT_CUTOFF, &cut_off);
3345 glLightfv(GL_LIGHT0 + i, GL_SPOT_EXPONENT, &(This->light_parameters[i].dvFalloff));
3349 /* No warning here as it's already done at light setting */
3356 glMultMatrixf((float *) world_mat);
3358 if ((matrices & PROJMAT_CHANGED) != 0) {
3359 glMatrixMode(GL_PROJECTION);
3360 glLoadMatrixf((float *) proj_mat);
3366 d3ddevice_matrices_updated(IDirect3DDeviceImpl *This, DWORD matrices)
3368 IDirect3DDeviceGLImpl *glThis = (IDirect3DDeviceGLImpl *) This;
3369 DWORD tex_mat, tex_stage;
3371 TRACE("(%p,%08lx)\n", This, matrices);
3373 if (matrices & (VIEWMAT_CHANGED|WORLDMAT_CHANGED|PROJMAT_CHANGED)) {
3374 if (glThis->transform_state == GL_TRANSFORM_NORMAL) {
3375 /* This will force an update of the transform state at the next drawing. */
3376 glThis->transform_state = GL_TRANSFORM_NONE;
3379 if (matrices & (TEXMAT0_CHANGED|TEXMAT1_CHANGED|TEXMAT2_CHANGED|TEXMAT3_CHANGED|
3380 TEXMAT4_CHANGED|TEXMAT5_CHANGED|TEXMAT6_CHANGED|TEXMAT7_CHANGED))
3383 for (tex_mat = TEXMAT0_CHANGED, tex_stage = 0; tex_mat <= TEXMAT7_CHANGED; tex_mat <<= 1, tex_stage++) {
3384 GLenum unit = GL_TEXTURE0_WINE + tex_stage;
3385 if (matrices & tex_mat) {
3386 if (This->state_block.texture_stage_state[tex_stage][D3DTSS_TEXTURETRANSFORMFLAGS - 1] != D3DTTFF_DISABLE) {
3387 int is_identity = (memcmp(This->tex_mat[tex_stage], id_mat, 16 * sizeof(D3DVALUE)) != 0);
3389 if (This->tex_mat_is_identity[tex_stage] != is_identity) {
3390 if (glThis->current_active_tex_unit != unit) {
3391 GL_extensions.glActiveTexture(unit);
3392 glThis->current_active_tex_unit = unit;
3394 glMatrixMode(GL_TEXTURE);
3395 glLoadMatrixf((float *) This->tex_mat[tex_stage]);
3397 This->tex_mat_is_identity[tex_stage] = is_identity;
3399 if (This->tex_mat_is_identity[tex_stage] == FALSE) {
3400 if (glThis->current_active_tex_unit != unit) {
3401 GL_extensions.glActiveTexture(unit);
3402 glThis->current_active_tex_unit = unit;
3404 glMatrixMode(GL_TEXTURE);
3406 This->tex_mat_is_identity[tex_stage] = TRUE;
3415 /* TODO for both these functions :
3416 - change / restore OpenGL parameters for pictures transfers in case they are ever modified
3417 by other OpenGL code in D3D
3418 - handle the case where no 'Begin / EndScene' was done between two locks
3419 - handle the rectangles in the unlock too
3420 - handle pitch correctly...
3422 static void d3ddevice_lock_update(IDirectDrawSurfaceImpl* This, LPCRECT pRect, DWORD dwFlags)
3424 IDirect3DDeviceImpl *d3d_dev = This->d3ddevice;
3425 IDirect3DDeviceGLImpl* gl_d3d_dev = (IDirect3DDeviceGLImpl*) d3d_dev;
3426 WINE_GL_BUFFER_TYPE buffer_type;
3429 if ((This->surface_desc.ddsCaps.dwCaps & (DDSCAPS_FRONTBUFFER|DDSCAPS_PRIMARYSURFACE)) != 0) {
3430 buffer_type = WINE_GL_BUFFER_FRONT;
3431 if ((gl_d3d_dev->state[WINE_GL_BUFFER_FRONT] != SURFACE_GL) &&
3432 (gl_d3d_dev->lock_surf[WINE_GL_BUFFER_FRONT] != This)) {
3433 ERR("Change of front buffer.. Expect graphic corruptions !\n");
3435 gl_d3d_dev->lock_surf[WINE_GL_BUFFER_FRONT] = This;
3436 } else if ((This->surface_desc.ddsCaps.dwCaps & (DDSCAPS_BACKBUFFER)) == (DDSCAPS_BACKBUFFER)) {
3437 buffer_type = WINE_GL_BUFFER_BACK;
3438 if ((gl_d3d_dev->state[WINE_GL_BUFFER_BACK] != SURFACE_GL) &&
3439 (gl_d3d_dev->lock_surf[WINE_GL_BUFFER_BACK] != This)) {
3440 ERR("Change of back buffer.. Expect graphic corruptions !\n");
3442 gl_d3d_dev->lock_surf[WINE_GL_BUFFER_BACK] = This;
3444 ERR("Wrong surface type for locking !\n");
3448 if (pRect == NULL) {
3451 loc_rect.bottom = This->surface_desc.dwHeight;
3452 loc_rect.right = This->surface_desc.dwWidth;
3456 /* Try to acquire the device critical section */
3457 EnterCriticalSection(&(d3d_dev->crit));
3459 if (gl_d3d_dev->lock_rect_valid[buffer_type] == TRUE) {
3460 ERR("Two consecutive locks on %s buffer... Expect problems !\n",
3461 (buffer_type == WINE_GL_BUFFER_BACK ? "back" : "front"));
3463 gl_d3d_dev->lock_rect_valid[buffer_type] = TRUE;
3465 if (gl_d3d_dev->state[buffer_type] != SURFACE_GL) {
3466 /* Check if the new rectangle is in the previous one or not.
3467 If it is not, flush first the previous locks on screen.
3469 if ((pRect->top < gl_d3d_dev->lock_rect[buffer_type].top) ||
3470 (pRect->left < gl_d3d_dev->lock_rect[buffer_type].left) ||
3471 (pRect->right > gl_d3d_dev->lock_rect[buffer_type].right) ||
3472 (pRect->bottom > gl_d3d_dev->lock_rect[buffer_type].bottom)) {
3473 if (gl_d3d_dev->state[buffer_type] == SURFACE_MEMORY_DIRTY) {
3474 TRACE(" flushing back to %s buffer as new rect : (%ldx%ld) - (%ldx%ld) not included in old rect : (%ldx%ld) - (%ldx%ld)\n",
3475 (buffer_type == WINE_GL_BUFFER_BACK ? "back" : "front"),
3476 pRect->left, pRect->top, pRect->right, pRect->bottom,
3477 gl_d3d_dev->lock_rect[buffer_type].left, gl_d3d_dev->lock_rect[buffer_type].top,
3478 gl_d3d_dev->lock_rect[buffer_type].right, gl_d3d_dev->lock_rect[buffer_type].bottom);
3479 d3d_dev->flush_to_framebuffer(d3d_dev, &(gl_d3d_dev->lock_rect[buffer_type]), gl_d3d_dev->lock_surf[buffer_type]);
3481 gl_d3d_dev->state[buffer_type] = SURFACE_GL;
3482 gl_d3d_dev->lock_rect[buffer_type] = *pRect;
3484 /* In the other case, do not upgrade the locking rectangle as it's no need... */
3486 gl_d3d_dev->lock_rect[buffer_type] = *pRect;
3489 if (gl_d3d_dev->state[buffer_type] == SURFACE_GL) {
3490 /* If the surface is already in memory, no need to do anything here... */
3491 GLenum buffer_format;
3492 GLenum buffer_color;
3496 TRACE(" copying %s buffer to main memory with rectangle (%ldx%ld) - (%ldx%ld).\n", (buffer_type == WINE_GL_BUFFER_BACK ? "back" : "front"),
3497 pRect->left, pRect->top, pRect->right, pRect->bottom);
3499 /* Note that here we cannot do 'optmizations' about the WriteOnly flag... Indeed, a game
3500 may only write to the device... But when we will blit it back to the screen, we need
3501 also to blit correctly the parts the application did not overwrite... */
3503 if (((This->surface_desc.u4.ddpfPixelFormat.dwFlags & DDPF_RGB) != 0) &&
3504 (((This->surface_desc.u4.ddpfPixelFormat.dwFlags & DDPF_ALPHAPIXELS) == 0) ||
3505 (This->surface_desc.u4.ddpfPixelFormat.u5.dwRGBAlphaBitMask == 0x00000000))) {
3506 if ((This->surface_desc.u4.ddpfPixelFormat.u1.dwRGBBitCount == 16) &&
3507 (This->surface_desc.u4.ddpfPixelFormat.u2.dwRBitMask == 0xF800) &&
3508 (This->surface_desc.u4.ddpfPixelFormat.u3.dwGBitMask == 0x07E0) &&
3509 (This->surface_desc.u4.ddpfPixelFormat.u4.dwBBitMask == 0x001F)) {
3510 buffer_format = GL_UNSIGNED_SHORT_5_6_5;
3511 buffer_color = GL_RGB;
3512 } else if ((This->surface_desc.u4.ddpfPixelFormat.u1.dwRGBBitCount == 24) &&
3513 (This->surface_desc.u4.ddpfPixelFormat.u2.dwRBitMask == 0xFF0000) &&
3514 (This->surface_desc.u4.ddpfPixelFormat.u3.dwGBitMask == 0x00FF00) &&
3515 (This->surface_desc.u4.ddpfPixelFormat.u4.dwBBitMask == 0x0000FF)) {
3516 buffer_format = GL_UNSIGNED_BYTE;
3517 buffer_color = GL_RGB;
3518 } else if ((This->surface_desc.u4.ddpfPixelFormat.u1.dwRGBBitCount == 32) &&
3519 (This->surface_desc.u4.ddpfPixelFormat.u2.dwRBitMask == 0x00FF0000) &&
3520 (This->surface_desc.u4.ddpfPixelFormat.u3.dwGBitMask == 0x0000FF00) &&
3521 (This->surface_desc.u4.ddpfPixelFormat.u4.dwBBitMask == 0x000000FF)) {
3522 buffer_format = GL_UNSIGNED_INT_8_8_8_8_REV;
3523 buffer_color = GL_BGRA;
3525 ERR(" unsupported pixel format at device locking.\n");
3529 ERR(" unsupported pixel format at device locking - alpha on frame buffer.\n");
3535 if (buffer_type == WINE_GL_BUFFER_FRONT)
3536 /* Application wants to lock the front buffer */
3537 glReadBuffer(GL_FRONT);
3539 /* Application wants to lock the back buffer */
3540 glReadBuffer(GL_BACK);
3542 dst = ((char *)This->surface_desc.lpSurface) +
3543 (pRect->top * This->surface_desc.u1.lPitch) + (pRect->left * GET_BPP(This->surface_desc));
3544 for (y = (This->surface_desc.dwHeight - pRect->top - 1);
3545 y >= ((int) This->surface_desc.dwHeight - (int) pRect->bottom);
3547 glReadPixels(pRect->left, y,
3548 pRect->right - pRect->left, 1,
3549 buffer_color, buffer_format, dst);
3550 dst += This->surface_desc.u1.lPitch;
3553 gl_d3d_dev->state[buffer_type] = SURFACE_MEMORY;
3556 /* I keep this code here as it's very useful to debug :-) */
3558 static int flush_count = 0;
3562 if ((++flush_count % 50) == 0) {
3563 sprintf(buf, "lock_%06d.pnm", flush_count);
3564 f = fopen(buf, "wb");
3565 DDRAW_dump_surface_to_disk(This, f);
3574 static void d3ddevice_flush_to_frame_buffer(IDirect3DDeviceImpl *d3d_dev, LPCRECT pRect, IDirectDrawSurfaceImpl *surf) {
3576 IDirect3DDeviceGLImpl* gl_d3d_dev = (IDirect3DDeviceGLImpl*) d3d_dev;
3581 /* Note : no need here to lock the 'device critical section' as we are already protected by
3582 the GL critical section. */
3584 if (pRect == NULL) {
3587 loc_rect.bottom = d3d_dev->surface->surface_desc.dwHeight;
3588 loc_rect.right = d3d_dev->surface->surface_desc.dwWidth;
3592 TRACE(" flushing memory back to screen memory (%ld,%ld) x (%ld,%ld).\n", pRect->top, pRect->left, pRect->right, pRect->bottom);
3594 opt_bitmap = d3ddevice_set_state_for_flush(d3d_dev, pRect, FALSE, &initial);
3596 if (upload_surface_to_tex_memory_init(surf, 0, &gl_d3d_dev->current_internal_format,
3597 initial, FALSE, UNLOCK_TEX_SIZE, UNLOCK_TEX_SIZE) != DD_OK) {
3598 ERR(" unsupported pixel format at frame buffer flush.\n");
3602 for (y = pRect->top; y < pRect->bottom; y += UNLOCK_TEX_SIZE) {
3606 flush_rect.bottom = (y + UNLOCK_TEX_SIZE > pRect->bottom) ? pRect->bottom : (y + UNLOCK_TEX_SIZE);
3608 for (x = pRect->left; x < pRect->right; x += UNLOCK_TEX_SIZE) {
3609 /* First, upload the texture... */
3610 flush_rect.left = x;
3611 flush_rect.right = (x + UNLOCK_TEX_SIZE > pRect->right) ? pRect->right : (x + UNLOCK_TEX_SIZE);
3613 upload_surface_to_tex_memory(&flush_rect, 0, 0, &(gl_d3d_dev->surface_ptr));
3616 glTexCoord2f(0.0, 0.0);
3617 glVertex3d(x, y, 0.5);
3618 glTexCoord2f(1.0, 0.0);
3619 glVertex3d(x + UNLOCK_TEX_SIZE, y, 0.5);
3620 glTexCoord2f(1.0, 1.0);
3621 glVertex3d(x + UNLOCK_TEX_SIZE, y + UNLOCK_TEX_SIZE, 0.5);
3622 glTexCoord2f(0.0, 1.0);
3623 glVertex3d(x, y + UNLOCK_TEX_SIZE, 0.5);
3628 upload_surface_to_tex_memory_release();
3629 d3ddevice_restore_state_after_flush(d3d_dev, opt_bitmap, FALSE);
3632 /* I keep this code here as it's very useful to debug :-) */
3634 static int flush_count = 0;
3638 if ((++flush_count % 50) == 0) {
3639 sprintf(buf, "flush_%06d.pnm", flush_count);
3640 f = fopen(buf, "wb");
3641 DDRAW_dump_surface_to_disk(surf, f);
3647 static void d3ddevice_unlock_update(IDirectDrawSurfaceImpl* This, LPCRECT pRect)
3649 WINE_GL_BUFFER_TYPE buffer_type;
3650 IDirect3DDeviceImpl *d3d_dev = This->d3ddevice;
3651 IDirect3DDeviceGLImpl* gl_d3d_dev = (IDirect3DDeviceGLImpl*) d3d_dev;
3653 if ((This->surface_desc.ddsCaps.dwCaps & (DDSCAPS_FRONTBUFFER|DDSCAPS_PRIMARYSURFACE)) != 0) {
3654 buffer_type = WINE_GL_BUFFER_FRONT;
3655 } else if ((This->surface_desc.ddsCaps.dwCaps & (DDSCAPS_BACKBUFFER)) == (DDSCAPS_BACKBUFFER)) {
3656 buffer_type = WINE_GL_BUFFER_BACK;
3658 ERR("Wrong surface type for locking !\n");
3662 if (gl_d3d_dev->lock_rect_valid[buffer_type] == FALSE) {
3663 ERR("Unlock without prior lock on %s buffer... Expect problems !\n",
3664 (buffer_type == WINE_GL_BUFFER_BACK ? "back" : "front"));
3666 gl_d3d_dev->lock_rect_valid[buffer_type] = FALSE;
3668 /* First, check if we need to do anything. For the backbuffer, flushing is done at the next 3D activity. */
3669 if ((This->lastlocktype & DDLOCK_READONLY) == 0) {
3670 if (buffer_type == WINE_GL_BUFFER_FRONT) {
3673 TRACE(" flushing front buffer immediatly on screen.\n");
3676 glGetIntegerv(GL_DRAW_BUFFER, &prev_draw);
3677 glDrawBuffer(GL_FRONT);
3678 /* Note: we do not use the application provided lock rectangle but our own stored at
3679 lock time. This is because in old D3D versions, the 'lock' parameter did not
3682 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]);
3683 glDrawBuffer(prev_draw);
3686 gl_d3d_dev->state[WINE_GL_BUFFER_BACK] = SURFACE_MEMORY_DIRTY;
3690 /* And 'frees' the device critical section */
3691 LeaveCriticalSection(&(d3d_dev->crit));
3695 apply_texture_state(IDirect3DDeviceImpl *This)
3699 /* Initialize texture stages states */
3700 for (stage = 0; stage < MAX_TEXTURES; stage++) {
3701 for (state = 0; state < HIGHEST_TEXTURE_STAGE_STATE; state += 1) {
3702 if (This->state_block.set_flags.texture_stage_state[stage][state] == TRUE) {
3703 IDirect3DDevice7_SetTextureStageState(ICOM_INTERFACE(This, IDirect3DDevice7),
3704 stage, state + 1, This->state_block.texture_stage_state[stage][state]);
3711 d3ddevice_create(IDirect3DDeviceImpl **obj, IDirectDrawImpl *d3d, IDirectDrawSurfaceImpl *surface)
3713 IDirect3DDeviceImpl *object;
3714 IDirect3DDeviceGLImpl *gl_object;
3715 IDirectDrawSurfaceImpl *surf;
3720 XVisualInfo template;
3721 GLenum buffer = GL_FRONT;
3724 object = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(IDirect3DDeviceGLImpl));
3725 if (object == NULL) return DDERR_OUTOFMEMORY;
3727 gl_object = (IDirect3DDeviceGLImpl *) object;
3731 object->surface = surface;
3732 object->set_context = set_context;
3733 object->clear = d3ddevice_clear_back;
3734 object->set_matrices = d3ddevice_set_matrices;
3735 object->matrices_updated = d3ddevice_matrices_updated;
3736 object->flush_to_framebuffer = d3ddevice_flush_to_frame_buffer;
3738 TRACE(" creating OpenGL device for surface = %p, d3d = %p\n", surface, d3d);
3740 InitializeCriticalSection(&(object->crit));
3742 TRACE(" device critical section : %p\n", &(object->crit));
3744 device_context = GetDC(surface->ddraw_owner->window);
3745 gl_object->display = get_display(device_context);
3746 gl_object->drawable = get_drawable(device_context);
3747 ReleaseDC(surface->ddraw_owner->window,device_context);
3750 template.visualid = (VisualID)GetPropA( GetDesktopWindow(), "__wine_x11_visual_id" );
3751 vis = XGetVisualInfo(gl_object->display, VisualIDMask, &template, &num);
3753 HeapFree(GetProcessHeap(), 0, object);
3754 ERR("No visual found !\n");
3756 return DDERR_INVALIDPARAMS;
3758 TRACE(" visual found\n");
3761 gl_object->gl_context = glXCreateContext(gl_object->display, vis,
3764 if (gl_object->gl_context == NULL) {
3765 HeapFree(GetProcessHeap(), 0, object);
3766 ERR("Error in context creation !\n");
3768 return DDERR_INVALIDPARAMS;
3770 TRACE(" context created (%p)\n", gl_object->gl_context);
3773 /* Look for the front buffer and override its surface's Flip method (if in double buffering) */
3774 for (surf = surface; surf != NULL; surf = surf->surface_owner) {
3775 if ((surf->surface_desc.ddsCaps.dwCaps&(DDSCAPS_FLIP|DDSCAPS_FRONTBUFFER)) == (DDSCAPS_FLIP|DDSCAPS_FRONTBUFFER)) {
3776 surf->aux_ctx = (LPVOID) object;
3777 surf->aux_data = (LPVOID) gl_object->drawable;
3778 surf->aux_flip = opengl_flip;
3783 /* We are not doing any double buffering.. Then force OpenGL to draw on the front buffer */
3785 TRACE(" no double buffering : drawing on the front buffer\n");
3789 for (surf = surface; surf != NULL; surf = surf->surface_owner) {
3790 IDirectDrawSurfaceImpl *surf2;
3791 for (surf2 = surf; surf2->prev_attached != NULL; surf2 = surf2->prev_attached) ;
3792 for (; surf2 != NULL; surf2 = surf2->next_attached) {
3793 TRACE(" checking surface %p :", surf2);
3794 if (((surf2->surface_desc.ddsCaps.dwCaps & (DDSCAPS_3DDEVICE)) == (DDSCAPS_3DDEVICE)) &&
3795 ((surf2->surface_desc.ddsCaps.dwCaps & (DDSCAPS_ZBUFFER)) != (DDSCAPS_ZBUFFER))) {
3796 /* Override the Lock / Unlock function for all these surfaces */
3797 surf2->lock_update_prev = surf2->lock_update;
3798 surf2->lock_update = d3ddevice_lock_update;
3799 surf2->unlock_update_prev = surf2->unlock_update;
3800 surf2->unlock_update = d3ddevice_unlock_update;
3801 /* And install also the blt / bltfast overrides */
3802 surf2->aux_blt = d3ddevice_blt;
3803 surf2->aux_bltfast = d3ddevice_bltfast;
3805 TRACE(" overiding direct surface access.\n");
3807 TRACE(" no overide.\n");
3809 surf2->d3ddevice = object;
3813 /* Set the various light parameters */
3814 for (light = 0; light < MAX_LIGHTS; light++) {
3815 /* Only set the fields that are not zero-created */
3816 object->light_parameters[light].dltType = D3DLIGHT_DIRECTIONAL;
3817 object->light_parameters[light].dcvDiffuse.u1.r = 1.0;
3818 object->light_parameters[light].dcvDiffuse.u2.g = 1.0;
3819 object->light_parameters[light].dcvDiffuse.u3.b = 1.0;
3820 object->light_parameters[light].dvDirection.u3.z = 1.0;
3823 /* Allocate memory for the matrices */
3824 object->world_mat = (D3DMATRIX *) HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, 16 * sizeof(float));
3825 object->view_mat = (D3DMATRIX *) HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, 16 * sizeof(float));
3826 object->proj_mat = (D3DMATRIX *) HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, 16 * sizeof(float));
3827 memcpy(object->world_mat, id_mat, 16 * sizeof(float));
3828 memcpy(object->view_mat , id_mat, 16 * sizeof(float));
3829 memcpy(object->proj_mat , id_mat, 16 * sizeof(float));
3830 for (tex_num = 0; tex_num < MAX_TEXTURES; tex_num++) {
3831 object->tex_mat[tex_num] = (D3DMATRIX *) HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, 16 * sizeof(float));
3832 memcpy(object->tex_mat[tex_num], id_mat, 16 * sizeof(float));
3833 object->tex_mat_is_identity[tex_num] = TRUE;
3836 /* Initialisation */
3837 TRACE(" setting current context\n");
3838 object->set_context(object);
3839 TRACE(" current context set\n");
3841 /* allocate the clipping planes */
3842 object->max_clipping_planes = opengl_device_caps.wMaxUserClipPlanes;
3843 object->clipping_planes = (d3d7clippingplane*)HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, object->max_clipping_planes * sizeof(d3d7clippingplane));
3845 glHint(GL_FOG_HINT,GL_NICEST);
3847 /* Initialize the various GL contexts to be in sync with what we store locally */
3850 glClearColor(0.0, 0.0, 0.0, 0.0);
3851 glDepthMask(GL_TRUE);
3852 gl_object->depth_mask = TRUE;
3853 glEnable(GL_DEPTH_TEST);
3854 gl_object->depth_test = TRUE;
3855 glDisable(GL_ALPHA_TEST);
3856 glDisable(GL_STENCIL_TEST);
3857 glDisable(GL_CULL_FACE);
3858 glDisable(GL_LIGHTING);
3859 glDisable(GL_BLEND);
3861 glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);
3862 gl_object->current_tex_env = GL_REPLACE;
3863 gl_object->current_active_tex_unit = GL_TEXTURE0_WINE;
3864 if (GL_extensions.glActiveTexture != NULL) {
3865 GL_extensions.glActiveTexture(GL_TEXTURE0_WINE);
3868 glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
3869 glDrawBuffer(buffer);
3870 glReadBuffer(buffer);
3871 /* glDisable(GL_DEPTH_TEST); Need here to check for the presence of a ZBuffer and to reenable it when the ZBuffer is attached */
3874 gl_object->state[WINE_GL_BUFFER_BACK] = SURFACE_GL;
3875 gl_object->state[WINE_GL_BUFFER_FRONT] = SURFACE_GL;
3877 /* fill_device_capabilities(d3d->ddraw); */
3879 ICOM_INIT_INTERFACE(object, IDirect3DDevice, VTABLE_IDirect3DDevice);
3880 ICOM_INIT_INTERFACE(object, IDirect3DDevice2, VTABLE_IDirect3DDevice2);
3881 ICOM_INIT_INTERFACE(object, IDirect3DDevice3, VTABLE_IDirect3DDevice3);
3882 ICOM_INIT_INTERFACE(object, IDirect3DDevice7, VTABLE_IDirect3DDevice7);
3886 TRACE(" creating implementation at %p.\n", *obj);
3888 /* And finally warn D3D that this device is now present */
3889 object->d3d->d3d_added_device(object->d3d, object);
3891 /* FIXME: Should handle other versions than just 7 */
3892 InitDefaultStateBlock(&object->state_block, 7);
3893 /* Apply default render state and texture stage state values */
3894 apply_render_state(object, &object->state_block);
3895 apply_texture_state(object);
3897 /* And fill the fog table with the default fog value */
3898 build_fog_table(gl_object->fog_table, object->state_block.render_state[D3DRENDERSTATE_FOGCOLOR - 1]);
3903 static void fill_opengl_primcaps(D3DPRIMCAPS *pc)
3905 pc->dwSize = sizeof(*pc);
3906 pc->dwMiscCaps = D3DPMISCCAPS_CONFORMANT | D3DPMISCCAPS_CULLCCW | D3DPMISCCAPS_CULLCW |
3907 D3DPMISCCAPS_LINEPATTERNREP | D3DPMISCCAPS_MASKPLANES | D3DPMISCCAPS_MASKZ;
3908 pc->dwRasterCaps = D3DPRASTERCAPS_DITHER | D3DPRASTERCAPS_FOGRANGE | D3DPRASTERCAPS_FOGTABLE |
3909 D3DPRASTERCAPS_FOGVERTEX | D3DPRASTERCAPS_STIPPLE | D3DPRASTERCAPS_ZBIAS | D3DPRASTERCAPS_ZTEST | D3DPRASTERCAPS_SUBPIXEL |
3910 D3DPRASTERCAPS_ZFOG;
3911 if (GL_extensions.mipmap_lodbias == TRUE) {
3912 pc->dwRasterCaps |= D3DPRASTERCAPS_MIPMAPLODBIAS;
3914 pc->dwZCmpCaps = D3DPCMPCAPS_ALWAYS | D3DPCMPCAPS_EQUAL | D3DPCMPCAPS_GREATER | D3DPCMPCAPS_GREATEREQUAL |
3915 D3DPCMPCAPS_LESS | D3DPCMPCAPS_LESSEQUAL | D3DPCMPCAPS_NEVER | D3DPCMPCAPS_NOTEQUAL;
3916 pc->dwSrcBlendCaps = D3DPBLENDCAPS_ZERO | D3DPBLENDCAPS_ONE | D3DPBLENDCAPS_DESTCOLOR | D3DPBLENDCAPS_INVDESTCOLOR |
3917 D3DPBLENDCAPS_SRCALPHA | D3DPBLENDCAPS_INVSRCALPHA | D3DPBLENDCAPS_DESTALPHA | D3DPBLENDCAPS_INVDESTALPHA | D3DPBLENDCAPS_SRCALPHASAT |
3918 D3DPBLENDCAPS_BOTHSRCALPHA | D3DPBLENDCAPS_BOTHINVSRCALPHA;
3919 pc->dwDestBlendCaps = D3DPBLENDCAPS_ZERO | D3DPBLENDCAPS_ONE | D3DPBLENDCAPS_SRCCOLOR | D3DPBLENDCAPS_INVSRCCOLOR |
3920 D3DPBLENDCAPS_SRCALPHA | D3DPBLENDCAPS_INVSRCALPHA | D3DPBLENDCAPS_DESTALPHA | D3DPBLENDCAPS_INVDESTALPHA | D3DPBLENDCAPS_SRCALPHASAT |
3921 D3DPBLENDCAPS_BOTHSRCALPHA | D3DPBLENDCAPS_BOTHINVSRCALPHA;
3922 pc->dwAlphaCmpCaps = D3DPCMPCAPS_ALWAYS | D3DPCMPCAPS_EQUAL | D3DPCMPCAPS_GREATER | D3DPCMPCAPS_GREATEREQUAL |
3923 D3DPCMPCAPS_LESS | D3DPCMPCAPS_LESSEQUAL | D3DPCMPCAPS_NEVER | D3DPCMPCAPS_NOTEQUAL;
3924 pc->dwShadeCaps = D3DPSHADECAPS_ALPHAFLATBLEND | D3DPSHADECAPS_ALPHAGOURAUDBLEND | D3DPSHADECAPS_COLORFLATRGB | D3DPSHADECAPS_COLORGOURAUDRGB |
3925 D3DPSHADECAPS_FOGFLAT | D3DPSHADECAPS_FOGGOURAUD | D3DPSHADECAPS_SPECULARFLATRGB | D3DPSHADECAPS_SPECULARGOURAUDRGB;
3926 pc->dwTextureCaps = D3DPTEXTURECAPS_ALPHA | D3DPTEXTURECAPS_ALPHAPALETTE | D3DPTEXTURECAPS_BORDER | D3DPTEXTURECAPS_PERSPECTIVE |
3927 D3DPTEXTURECAPS_POW2 | D3DPTEXTURECAPS_TRANSPARENCY;
3928 pc->dwTextureFilterCaps = D3DPTFILTERCAPS_LINEAR | D3DPTFILTERCAPS_LINEARMIPLINEAR | D3DPTFILTERCAPS_LINEARMIPNEAREST |
3929 D3DPTFILTERCAPS_MIPLINEAR | D3DPTFILTERCAPS_MIPNEAREST | D3DPTFILTERCAPS_NEAREST | D3DPTFILTERCAPS_MAGFLINEAR |
3930 D3DPTFILTERCAPS_MAGFPOINT | D3DPTFILTERCAPS_MINFLINEAR | D3DPTFILTERCAPS_MINFPOINT | D3DPTFILTERCAPS_MIPFLINEAR |
3931 D3DPTFILTERCAPS_MIPFPOINT;
3932 pc->dwTextureBlendCaps = D3DPTBLENDCAPS_ADD | D3DPTBLENDCAPS_COPY | D3DPTBLENDCAPS_DECAL | D3DPTBLENDCAPS_DECALALPHA | D3DPTBLENDCAPS_DECALMASK |
3933 D3DPTBLENDCAPS_MODULATE | D3DPTBLENDCAPS_MODULATEALPHA | D3DPTBLENDCAPS_MODULATEMASK;
3934 pc->dwTextureAddressCaps = D3DPTADDRESSCAPS_BORDER | D3DPTADDRESSCAPS_CLAMP | D3DPTADDRESSCAPS_WRAP | D3DPTADDRESSCAPS_INDEPENDENTUV;
3935 if (GL_extensions.mirrored_repeat == TRUE) {
3936 pc->dwTextureAddressCaps |= D3DPTADDRESSCAPS_MIRROR;
3938 pc->dwStippleWidth = 32;
3939 pc->dwStippleHeight = 32;
3942 static void fill_caps(void)
3944 GLint max_clip_planes;
3947 /* Fill first all the fields with default values which will be overriden later on with
3948 correct ones from the GL code
3950 opengl_device_caps.dwDevCaps = D3DDEVCAPS_CANRENDERAFTERFLIP | D3DDEVCAPS_DRAWPRIMTLVERTEX | D3DDEVCAPS_EXECUTESYSTEMMEMORY |
3951 D3DDEVCAPS_EXECUTEVIDEOMEMORY | D3DDEVCAPS_FLOATTLVERTEX | D3DDEVCAPS_TEXTURENONLOCALVIDMEM | D3DDEVCAPS_TEXTURESYSTEMMEMORY |
3952 D3DDEVCAPS_TEXTUREVIDEOMEMORY | D3DDEVCAPS_TLVERTEXSYSTEMMEMORY | D3DDEVCAPS_TLVERTEXVIDEOMEMORY |
3953 /* D3D 7 capabilities */
3954 D3DDEVCAPS_DRAWPRIMITIVES2 | D3DDEVCAPS_HWTRANSFORMANDLIGHT | D3DDEVCAPS_HWRASTERIZATION;
3955 fill_opengl_primcaps(&(opengl_device_caps.dpcLineCaps));
3956 fill_opengl_primcaps(&(opengl_device_caps.dpcTriCaps));
3957 opengl_device_caps.dwDeviceRenderBitDepth = DDBD_16|DDBD_24|DDBD_32;
3958 opengl_device_caps.dwMinTextureWidth = 1;
3959 opengl_device_caps.dwMinTextureHeight = 1;
3960 opengl_device_caps.dwMaxTextureWidth = 1024;
3961 opengl_device_caps.dwMaxTextureHeight = 1024;
3962 opengl_device_caps.dwMaxTextureRepeat = 16;
3963 opengl_device_caps.dwMaxTextureAspectRatio = 1024;
3964 opengl_device_caps.dwMaxAnisotropy = 0;
3965 opengl_device_caps.dvGuardBandLeft = 0.0;
3966 opengl_device_caps.dvGuardBandRight = 0.0;
3967 opengl_device_caps.dvGuardBandTop = 0.0;
3968 opengl_device_caps.dvGuardBandBottom = 0.0;
3969 opengl_device_caps.dvExtentsAdjust = 0.0;
3970 opengl_device_caps.dwStencilCaps = D3DSTENCILCAPS_DECRSAT | D3DSTENCILCAPS_INCRSAT | D3DSTENCILCAPS_INVERT | D3DSTENCILCAPS_KEEP |
3971 D3DSTENCILCAPS_REPLACE | D3DSTENCILCAPS_ZERO;
3972 opengl_device_caps.dwTextureOpCaps = D3DTEXOPCAPS_DISABLE | D3DTEXOPCAPS_SELECTARG1 | D3DTEXOPCAPS_SELECTARG2 | D3DTEXOPCAPS_MODULATE4X |
3973 D3DTEXOPCAPS_MODULATE2X | D3DTEXOPCAPS_MODULATE | D3DTEXOPCAPS_ADD | D3DTEXOPCAPS_ADDSIGNED2X | D3DTEXOPCAPS_ADDSIGNED |
3974 D3DTEXOPCAPS_BLENDDIFFUSEALPHA | D3DTEXOPCAPS_BLENDTEXTUREALPHA | D3DTEXOPCAPS_BLENDFACTORALPHA | D3DTEXOPCAPS_BLENDCURRENTALPHA;
3975 if (GL_extensions.max_texture_units != 0) {
3976 opengl_device_caps.wMaxTextureBlendStages = GL_extensions.max_texture_units;
3977 opengl_device_caps.wMaxSimultaneousTextures = GL_extensions.max_texture_units;
3978 opengl_device_caps.dwFVFCaps = D3DFVFCAPS_DONOTSTRIPELEMENTS | GL_extensions.max_texture_units;
3980 opengl_device_caps.wMaxTextureBlendStages = 1;
3981 opengl_device_caps.wMaxSimultaneousTextures = 1;
3982 opengl_device_caps.dwFVFCaps = D3DFVFCAPS_DONOTSTRIPELEMENTS | 1;
3984 opengl_device_caps.dwMaxActiveLights = 16;
3985 opengl_device_caps.dvMaxVertexW = 100000000.0; /* No idea exactly what to put here... */
3986 opengl_device_caps.deviceGUID = IID_IDirect3DTnLHalDevice;
3987 opengl_device_caps.wMaxUserClipPlanes = 1;
3988 opengl_device_caps.wMaxVertexBlendMatrices = 0;
3989 opengl_device_caps.dwVertexProcessingCaps = D3DVTXPCAPS_TEXGEN | D3DVTXPCAPS_MATERIALSOURCE7 | D3DVTXPCAPS_VERTEXFOG |
3990 D3DVTXPCAPS_DIRECTIONALLIGHTS | D3DVTXPCAPS_POSITIONALLIGHTS | D3DVTXPCAPS_LOCALVIEWER;
3991 opengl_device_caps.dwReserved1 = 0;
3992 opengl_device_caps.dwReserved2 = 0;
3993 opengl_device_caps.dwReserved3 = 0;
3994 opengl_device_caps.dwReserved4 = 0;
3996 /* And now some GL overides :-) */
3997 glGetIntegerv(GL_MAX_TEXTURE_SIZE, (GLint *) &opengl_device_caps.dwMaxTextureWidth);
3998 opengl_device_caps.dwMaxTextureHeight = opengl_device_caps.dwMaxTextureWidth;
3999 opengl_device_caps.dwMaxTextureAspectRatio = opengl_device_caps.dwMaxTextureWidth;
4000 TRACE(": max texture size = %ld\n", opengl_device_caps.dwMaxTextureWidth);
4002 glGetIntegerv(GL_MAX_LIGHTS, (GLint *) &opengl_device_caps.dwMaxActiveLights);
4003 TRACE(": max active lights = %ld\n", opengl_device_caps.dwMaxActiveLights);
4005 glGetIntegerv(GL_MAX_CLIP_PLANES, &max_clip_planes);
4006 opengl_device_caps.wMaxUserClipPlanes = max_clip_planes;
4007 TRACE(": max clipping planes = %d\n", opengl_device_caps.wMaxUserClipPlanes);
4009 glGetIntegerv(GL_DEPTH_BITS, &depth_bits);
4010 TRACE(": Z bits = %d\n", depth_bits);
4011 switch (depth_bits) {
4012 case 16: opengl_device_caps.dwDeviceZBufferBitDepth = DDBD_16; break;
4013 case 24: opengl_device_caps.dwDeviceZBufferBitDepth = DDBD_24; break;
4014 case 32: opengl_device_caps.dwDeviceZBufferBitDepth = DDBD_32; break;
4015 default: opengl_device_caps.dwDeviceZBufferBitDepth = DDBD_16|DDBD_24|DDBD_32; break;
4020 d3ddevice_init_at_startup(void *gl_handle)
4022 XVisualInfo template;
4027 Drawable drawable = (Drawable) GetPropA(GetDesktopWindow(), "__wine_x11_whole_window");
4028 XWindowAttributes win_attr;
4029 GLXContext gl_context;
4031 const char *glExtensions;
4032 const char *glVersion;
4033 const char *glXExtensions = NULL;
4034 const void *(*pglXGetProcAddressARB)(const GLubyte *) = NULL;
4035 int major, minor, patch;
4037 TRACE("Initializing GL...\n");
4039 /* Get a default rendering context to have the 'caps' function query some info from GL */
4040 device_context = GetDC(0);
4041 display = get_display(device_context);
4042 ReleaseDC(0, device_context);
4045 if (XGetWindowAttributes(display, drawable, &win_attr)) {
4046 visual = win_attr.visual;
4048 visual = DefaultVisual(display, DefaultScreen(display));
4050 template.visualid = XVisualIDFromVisual(visual);
4051 vis = XGetVisualInfo(display, VisualIDMask, &template, &num);
4054 WARN("Error creating visual info for capabilities initialization - D3D support disabled !\n");
4057 gl_context = glXCreateContext(display, vis, NULL, GL_TRUE);
4059 if (gl_context == NULL) {
4061 WARN("Error creating default context for capabilities initialization - D3D support disabled !\n");
4064 if (glXMakeCurrent(display, drawable, gl_context) == False) {
4065 glXDestroyContext(display, gl_context);
4067 WARN("Error setting default context as current for capabilities initialization - D3D support disabled !\n");
4071 /* Then, query all extensions */
4072 glXExtensions = glXQueryExtensionsString(display, DefaultScreen(display));
4073 glExtensions = (const char *) glGetString(GL_EXTENSIONS);
4074 glVersion = (const char *) glGetString(GL_VERSION);
4075 if ((glXExtensions != NULL) && (gl_handle != NULL) && (strstr(glXExtensions, "GLX_ARB_get_proc_address"))) {
4076 pglXGetProcAddressARB = wine_dlsym(gl_handle, "glXGetProcAddressARB", NULL, 0);
4079 /* Parse the GL version string */
4080 sscanf(glVersion, "%d.%d.%d", &major, &minor, &patch);
4081 TRACE("GL version %d.%d.%d\n", major, minor, patch);
4083 /* And starts to fill the extension context properly */
4084 memset(&GL_extensions, 0, sizeof(GL_extensions));
4085 TRACE("GL supports following extensions used by Wine :\n");
4087 /* Mirrored Repeat extension :
4088 - GL_ARB_texture_mirrored_repeat
4089 - GL_IBM_texture_mirrored_repeat
4092 if ((strstr(glExtensions, "GL_ARB_texture_mirrored_repeat")) ||
4093 (strstr(glExtensions, "GL_IBM_texture_mirrored_repeat")) ||
4095 ((major == 1) && (minor >= 4))) {
4096 TRACE(" - mirrored repeat\n");
4097 GL_extensions.mirrored_repeat = TRUE;
4100 /* Texture LOD Bias :
4101 - GL_EXT_texture_lod_bias
4103 if (strstr(glExtensions, "GL_EXT_texture_lod_bias")) {
4104 TRACE(" - texture lod bias\n");
4105 GL_extensions.mipmap_lodbias = TRUE;
4108 /* For all subsequent extensions, we need glXGetProcAddress */
4109 if (pglXGetProcAddressARB != NULL) {
4110 /* Multi-texturing :
4111 - GL_ARB_multitexture
4114 if ((strstr(glExtensions, "GL_ARB_multitexture")) ||
4116 ((major == 1) && (minor > 2)) ||
4117 ((major == 1) && (minor == 2) && (patch >= 1))) {
4118 glGetIntegerv(GL_MAX_TEXTURE_UNITS_WINE, &(GL_extensions.max_texture_units));
4119 TRACE(" - multi-texturing (%d stages)\n", GL_extensions.max_texture_units);
4120 /* We query the ARB version to be the most portable we can... */
4121 GL_extensions.glActiveTexture = pglXGetProcAddressARB("glActiveTextureARB");
4122 GL_extensions.glMultiTexCoord2fv = pglXGetProcAddressARB("glMultiTexCoord2fv");
4126 /* Fill the D3D capabilities according to what GL tells us... */
4129 /* And frees this now-useless context */
4130 glXMakeCurrent(display, None, NULL);
4131 glXDestroyContext(display, gl_context);