2 * Copyright (c) 1998-2004 Lionel ULMER
3 * Copyright (c) 2002-2004 Christian Costa
5 * This file contains the MESA implementation of all the D3D devices that
8 * This library is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU Lesser General Public
10 * License as published by the Free Software Foundation; either
11 * version 2.1 of the License, or (at your option) any later version.
13 * This library is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 * Lesser General Public License for more details.
18 * You should have received a copy of the GNU Lesser General Public
19 * License along with this library; if not, write to the Free Software
20 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
24 #include "wine/port.h"
30 #define NONAMELESSUNION
31 #define NONAMELESSSTRUCT
39 #include "wine/debug.h"
40 #include "wine/library.h"
42 #include "mesa_private.h"
45 WINE_DEFAULT_DEBUG_CHANNEL(ddraw
);
46 WINE_DECLARE_DEBUG_CHANNEL(ddraw_geom
);
48 /* x11drv GDI escapes */
49 #define X11DRV_ESCAPE 6789
50 enum x11drv_escape_codes
52 X11DRV_GET_DISPLAY
, /* get X11 display for a DC */
53 X11DRV_GET_DRAWABLE
, /* get current drawable for a DC */
54 X11DRV_GET_FONT
, /* get current X font for a DC */
57 /* They are non-static as they are used by Direct3D in the creation function */
58 const GUID IID_D3DDEVICE_OpenGL
= {
62 { 0x82,0x2d,0xa8,0xd5,0x31,0x87,0xca,0xfa }
65 const float id_mat
[16] = {
72 /* This is filled at DLL loading time */
73 static D3DDEVICEDESC7 opengl_device_caps
;
74 GL_EXTENSIONS_LIST GL_extensions
;
76 static void draw_primitive_strided(IDirect3DDeviceImpl
*This
,
77 D3DPRIMITIVETYPE d3dptPrimitiveType
,
78 DWORD d3dvtVertexType
,
79 LPD3DDRAWPRIMITIVESTRIDEDDATA lpD3DDrawPrimStrideData
,
85 static DWORD
draw_primitive_handle_textures(IDirect3DDeviceImpl
*This
);
87 /* retrieve the X display to use on a given DC */
88 inline static Display
*get_display( HDC hdc
)
91 enum x11drv_escape_codes escape
= X11DRV_GET_DISPLAY
;
93 if (!ExtEscape( hdc
, X11DRV_ESCAPE
, sizeof(escape
), (LPCSTR
)&escape
,
94 sizeof(display
), (LPSTR
)&display
)) display
= NULL
;
99 #define UNLOCK_TEX_SIZE 256
101 #define DEPTH_RANGE_BIT (0x00000001 << 0)
102 #define VIEWPORT_BIT (0x00000001 << 1)
104 static DWORD
d3ddevice_set_state_for_flush(IDirect3DDeviceImpl
*d3d_dev
, LPCRECT pRect
, BOOLEAN use_alpha
, BOOLEAN
*initial
) {
105 IDirect3DDeviceGLImpl
* gl_d3d_dev
= (IDirect3DDeviceGLImpl
*) d3d_dev
;
106 DWORD opt_bitmap
= 0x00000000;
108 if ((gl_d3d_dev
->current_bound_texture
[1] != NULL
) &&
109 ((d3d_dev
->state_block
.texture_stage_state
[1][D3DTSS_COLOROP
- 1] != D3DTOP_DISABLE
))) {
110 if (gl_d3d_dev
->current_active_tex_unit
!= GL_TEXTURE1_WINE
) {
111 GL_extensions
.glActiveTexture(GL_TEXTURE1_WINE
);
112 gl_d3d_dev
->current_active_tex_unit
= GL_TEXTURE1_WINE
;
114 /* Disable multi-texturing for level 1 to disable all others */
115 glDisable(GL_TEXTURE_2D
);
117 if (gl_d3d_dev
->current_active_tex_unit
!= GL_TEXTURE0_WINE
) {
118 GL_extensions
.glActiveTexture(GL_TEXTURE0_WINE
);
119 gl_d3d_dev
->current_active_tex_unit
= GL_TEXTURE0_WINE
;
121 if ((gl_d3d_dev
->current_bound_texture
[0] == NULL
) ||
122 (d3d_dev
->state_block
.texture_stage_state
[0][D3DTSS_COLOROP
- 1] == D3DTOP_DISABLE
))
123 glEnable(GL_TEXTURE_2D
);
124 if (gl_d3d_dev
->unlock_tex
== 0) {
125 glGenTextures(1, &gl_d3d_dev
->unlock_tex
);
126 glBindTexture(GL_TEXTURE_2D
, gl_d3d_dev
->unlock_tex
);
128 glTexParameteri(GL_TEXTURE_2D
, GL_TEXTURE_MAG_FILTER
, GL_NEAREST
);
129 glTexParameteri(GL_TEXTURE_2D
, GL_TEXTURE_MIN_FILTER
, GL_NEAREST
);
130 glTexParameteri(GL_TEXTURE_2D
, GL_TEXTURE_WRAP_S
, GL_CLAMP
);
131 glTexParameteri(GL_TEXTURE_2D
, GL_TEXTURE_WRAP_T
, GL_CLAMP
);
133 glBindTexture(GL_TEXTURE_2D
, gl_d3d_dev
->unlock_tex
);
136 if (d3d_dev
->tex_mat_is_identity
[0] == FALSE
) {
137 glMatrixMode(GL_TEXTURE
);
141 if (gl_d3d_dev
->transform_state
!= GL_TRANSFORM_ORTHO
) {
142 gl_d3d_dev
->transform_state
= GL_TRANSFORM_ORTHO
;
143 d3ddevice_set_ortho(d3d_dev
);
146 if (gl_d3d_dev
->depth_test
!= FALSE
) glDisable(GL_DEPTH_TEST
);
147 glEnable(GL_SCISSOR_TEST
);
148 if ((d3d_dev
->active_viewport
.dvMinZ
!= 0.0) ||
149 (d3d_dev
->active_viewport
.dvMaxZ
!= 1.0)) {
150 glDepthRange(0.0, 1.0);
151 opt_bitmap
|= DEPTH_RANGE_BIT
;
153 if ((d3d_dev
->active_viewport
.dwX
!= 0) ||
154 (d3d_dev
->active_viewport
.dwY
!= 0) ||
155 (d3d_dev
->active_viewport
.dwWidth
!= d3d_dev
->surface
->surface_desc
.dwWidth
) ||
156 (d3d_dev
->active_viewport
.dwHeight
!= d3d_dev
->surface
->surface_desc
.dwHeight
)) {
157 glViewport(0, 0, d3d_dev
->surface
->surface_desc
.dwWidth
, d3d_dev
->surface
->surface_desc
.dwHeight
);
158 opt_bitmap
|= VIEWPORT_BIT
;
160 glScissor(pRect
->left
, d3d_dev
->surface
->surface_desc
.dwHeight
- pRect
->bottom
,
161 pRect
->right
- pRect
->left
, pRect
->bottom
- pRect
->top
);
162 if (gl_d3d_dev
->lighting
!= FALSE
) glDisable(GL_LIGHTING
);
163 if (gl_d3d_dev
->cull_face
!= FALSE
) glDisable(GL_CULL_FACE
);
165 if (gl_d3d_dev
->alpha_test
== FALSE
) glEnable(GL_ALPHA_TEST
);
166 if ((gl_d3d_dev
->current_alpha_test_func
!= GL_NOTEQUAL
) || (gl_d3d_dev
->current_alpha_test_ref
!= 0.0))
167 glAlphaFunc(GL_NOTEQUAL
, 0.0);
169 if (gl_d3d_dev
->alpha_test
!= FALSE
) glDisable(GL_ALPHA_TEST
);
171 if (gl_d3d_dev
->stencil_test
!= FALSE
) glDisable(GL_STENCIL_TEST
);
172 if (gl_d3d_dev
->blending
!= FALSE
) glDisable(GL_BLEND
);
173 if (gl_d3d_dev
->fogging
!= FALSE
) glDisable(GL_FOG
);
174 if (gl_d3d_dev
->current_tex_env
!= GL_REPLACE
)
175 glTexEnvi(GL_TEXTURE_ENV
, GL_TEXTURE_ENV_MODE
, GL_REPLACE
);
180 static void d3ddevice_restore_state_after_flush(IDirect3DDeviceImpl
*d3d_dev
, DWORD opt_bitmap
, BOOLEAN use_alpha
) {
181 IDirect3DDeviceGLImpl
* gl_d3d_dev
= (IDirect3DDeviceGLImpl
*) d3d_dev
;
183 /* And restore all the various states modified by this code */
184 if (gl_d3d_dev
->depth_test
!= 0) glEnable(GL_DEPTH_TEST
);
185 if (gl_d3d_dev
->lighting
!= 0) glEnable(GL_LIGHTING
);
186 if ((gl_d3d_dev
->alpha_test
!= 0) && (use_alpha
== 0))
187 glEnable(GL_ALPHA_TEST
);
188 else if ((gl_d3d_dev
->alpha_test
== 0) && (use_alpha
!= 0))
189 glDisable(GL_ALPHA_TEST
);
191 if ((gl_d3d_dev
->current_alpha_test_func
!= GL_NOTEQUAL
) || (gl_d3d_dev
->current_alpha_test_ref
!= 0.0))
192 glAlphaFunc(gl_d3d_dev
->current_alpha_test_func
, gl_d3d_dev
->current_alpha_test_ref
);
194 if (gl_d3d_dev
->stencil_test
!= 0) glEnable(GL_STENCIL_TEST
);
195 if (gl_d3d_dev
->cull_face
!= 0) glEnable(GL_CULL_FACE
);
196 if (gl_d3d_dev
->blending
!= 0) glEnable(GL_BLEND
);
197 if (gl_d3d_dev
->fogging
!= 0) glEnable(GL_FOG
);
198 glDisable(GL_SCISSOR_TEST
);
199 if (opt_bitmap
& DEPTH_RANGE_BIT
) {
200 glDepthRange(d3d_dev
->active_viewport
.dvMinZ
, d3d_dev
->active_viewport
.dvMaxZ
);
202 if (opt_bitmap
& VIEWPORT_BIT
) {
203 glViewport(d3d_dev
->active_viewport
.dwX
,
204 d3d_dev
->surface
->surface_desc
.dwHeight
- (d3d_dev
->active_viewport
.dwHeight
+ d3d_dev
->active_viewport
.dwY
),
205 d3d_dev
->active_viewport
.dwWidth
, d3d_dev
->active_viewport
.dwHeight
);
207 if (d3d_dev
->tex_mat_is_identity
[0] == FALSE
) {
208 d3d_dev
->matrices_updated(d3d_dev
, TEXMAT0_CHANGED
);
211 if (gl_d3d_dev
->current_active_tex_unit
!= GL_TEXTURE0_WINE
) {
212 GL_extensions
.glActiveTexture(GL_TEXTURE0_WINE
);
213 gl_d3d_dev
->current_active_tex_unit
= GL_TEXTURE0_WINE
;
215 glTexEnvi(GL_TEXTURE_ENV
, GL_TEXTURE_ENV_MODE
, gl_d3d_dev
->current_tex_env
);
216 /* Note that here we could directly re-bind the previous texture... But it would in some case be a spurious
217 bind if ever the game changes the texture just after.
219 So choose 0x00000001 to postpone the binding to the next time we draw something on screen. */
220 gl_d3d_dev
->current_bound_texture
[0] = (IDirectDrawSurfaceImpl
*) 0x00000001;
221 if (d3d_dev
->state_block
.texture_stage_state
[0][D3DTSS_COLOROP
- 1] == D3DTOP_DISABLE
) glDisable(GL_TEXTURE_2D
);
223 /* And re-enabled if needed texture level 1 */
224 if ((gl_d3d_dev
->current_bound_texture
[1] != NULL
) &&
225 (d3d_dev
->state_block
.texture_stage_state
[1][D3DTSS_COLOROP
- 1] != D3DTOP_DISABLE
)) {
226 if (gl_d3d_dev
->current_active_tex_unit
!= GL_TEXTURE1_WINE
) {
227 GL_extensions
.glActiveTexture(GL_TEXTURE1_WINE
);
228 gl_d3d_dev
->current_active_tex_unit
= GL_TEXTURE1_WINE
;
230 glEnable(GL_TEXTURE_2D
);
234 /* retrieve the X drawable to use on a given DC */
235 inline static Drawable
get_drawable( HDC hdc
)
238 enum x11drv_escape_codes escape
= X11DRV_GET_DRAWABLE
;
240 if (!ExtEscape( hdc
, X11DRV_ESCAPE
, sizeof(escape
), (LPCSTR
)&escape
,
241 sizeof(drawable
), (LPSTR
)&drawable
)) drawable
= 0;
246 static BOOL
opengl_flip( LPVOID dev
, LPVOID drawable
)
248 IDirect3DDeviceImpl
*d3d_dev
= (IDirect3DDeviceImpl
*) dev
;
249 IDirect3DDeviceGLImpl
*gl_d3d_dev
= (IDirect3DDeviceGLImpl
*) dev
;
251 TRACE("(%p, %ld)\n", gl_d3d_dev
->display
,(Drawable
)drawable
);
253 if (gl_d3d_dev
->state
[WINE_GL_BUFFER_BACK
] == SURFACE_MEMORY_DIRTY
) {
254 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
]);
256 gl_d3d_dev
->state
[WINE_GL_BUFFER_BACK
] = SURFACE_GL
;
257 gl_d3d_dev
->state
[WINE_GL_BUFFER_FRONT
] = SURFACE_GL
;
258 glXSwapBuffers(gl_d3d_dev
->display
, (Drawable
)drawable
);
265 /*******************************************************************************
266 * OpenGL static functions
268 static void set_context(IDirect3DDeviceImpl
* This
)
270 IDirect3DDeviceGLImpl
* glThis
= (IDirect3DDeviceGLImpl
*) This
;
272 TRACE("glxMakeCurrent %p, %ld, %p\n",glThis
->display
,glThis
->drawable
, glThis
->gl_context
);
274 if (glXMakeCurrent(glThis
->display
, glThis
->drawable
, glThis
->gl_context
) == False
) {
275 ERR("Error in setting current context (context %p drawable %ld)!\n",
276 glThis
->gl_context
, glThis
->drawable
);
281 static void fill_opengl_caps(D3DDEVICEDESC
*d1
)
283 d1
->dwSize
= sizeof(*d1
);
284 d1
->dwFlags
= D3DDD_COLORMODEL
| D3DDD_DEVCAPS
| D3DDD_TRANSFORMCAPS
| D3DDD_BCLIPPING
| D3DDD_LIGHTINGCAPS
|
285 D3DDD_LINECAPS
| D3DDD_TRICAPS
| D3DDD_DEVICERENDERBITDEPTH
| D3DDD_DEVICEZBUFFERBITDEPTH
|
286 D3DDD_MAXBUFFERSIZE
| D3DDD_MAXVERTEXCOUNT
;
287 d1
->dcmColorModel
= D3DCOLOR_RGB
;
288 d1
->dwDevCaps
= opengl_device_caps
.dwDevCaps
;
289 d1
->dtcTransformCaps
.dwSize
= sizeof(D3DTRANSFORMCAPS
);
290 d1
->dtcTransformCaps
.dwCaps
= D3DTRANSFORMCAPS_CLIP
;
291 d1
->bClipping
= TRUE
;
292 d1
->dlcLightingCaps
.dwSize
= sizeof(D3DLIGHTINGCAPS
);
293 d1
->dlcLightingCaps
.dwCaps
= D3DLIGHTCAPS_DIRECTIONAL
| D3DLIGHTCAPS_PARALLELPOINT
| D3DLIGHTCAPS_POINT
| D3DLIGHTCAPS_SPOT
;
294 d1
->dlcLightingCaps
.dwLightingModel
= D3DLIGHTINGMODEL_RGB
;
295 d1
->dlcLightingCaps
.dwNumLights
= opengl_device_caps
.dwMaxActiveLights
;
296 d1
->dpcLineCaps
= opengl_device_caps
.dpcLineCaps
;
297 d1
->dpcTriCaps
= opengl_device_caps
.dpcTriCaps
;
298 d1
->dwDeviceRenderBitDepth
= opengl_device_caps
.dwDeviceRenderBitDepth
;
299 d1
->dwDeviceZBufferBitDepth
= opengl_device_caps
.dwDeviceZBufferBitDepth
;
300 d1
->dwMaxBufferSize
= 0;
301 d1
->dwMaxVertexCount
= 65536;
302 d1
->dwMinTextureWidth
= opengl_device_caps
.dwMinTextureWidth
;
303 d1
->dwMinTextureHeight
= opengl_device_caps
.dwMinTextureHeight
;
304 d1
->dwMaxTextureWidth
= opengl_device_caps
.dwMaxTextureWidth
;
305 d1
->dwMaxTextureHeight
= opengl_device_caps
.dwMaxTextureHeight
;
306 d1
->dwMinStippleWidth
= 1;
307 d1
->dwMinStippleHeight
= 1;
308 d1
->dwMaxStippleWidth
= 32;
309 d1
->dwMaxStippleHeight
= 32;
310 d1
->dwMaxTextureRepeat
= opengl_device_caps
.dwMaxTextureRepeat
;
311 d1
->dwMaxTextureAspectRatio
= opengl_device_caps
.dwMaxTextureAspectRatio
;
312 d1
->dwMaxAnisotropy
= opengl_device_caps
.dwMaxAnisotropy
;
313 d1
->dvGuardBandLeft
= opengl_device_caps
.dvGuardBandLeft
;
314 d1
->dvGuardBandRight
= opengl_device_caps
.dvGuardBandRight
;
315 d1
->dvGuardBandTop
= opengl_device_caps
.dvGuardBandTop
;
316 d1
->dvGuardBandBottom
= opengl_device_caps
.dvGuardBandBottom
;
317 d1
->dvExtentsAdjust
= opengl_device_caps
.dvExtentsAdjust
;
318 d1
->dwStencilCaps
= opengl_device_caps
.dwStencilCaps
;
319 d1
->dwFVFCaps
= opengl_device_caps
.dwFVFCaps
;
320 d1
->dwTextureOpCaps
= opengl_device_caps
.dwTextureOpCaps
;
321 d1
->wMaxTextureBlendStages
= opengl_device_caps
.wMaxTextureBlendStages
;
322 d1
->wMaxSimultaneousTextures
= opengl_device_caps
.wMaxSimultaneousTextures
;
325 static void fill_opengl_caps_7(D3DDEVICEDESC7
*d
)
327 *d
= opengl_device_caps
;
330 HRESULT
d3ddevice_enumerate(LPD3DENUMDEVICESCALLBACK cb
, LPVOID context
, DWORD version
)
332 D3DDEVICEDESC dref
, d1
, d2
;
335 /* Some games (Motoracer 2 demo) have the bad idea to modify the device name string.
336 Let's put the string in a sufficiently sized array in writable memory. */
337 char device_name
[50];
338 strcpy(device_name
,"direct3d");
340 fill_opengl_caps(&dref
);
343 /* It seems that enumerating the reference IID on Direct3D 1 games (AvP / Motoracer2) breaks them */
344 char interface_name
[] = "WINE Reference Direct3DX using OpenGL";
345 TRACE(" enumerating OpenGL D3DDevice interface using reference IID (IID %s).\n", debugstr_guid(&IID_IDirect3DRefDevice
));
348 ret_value
= cb((LPIID
) &IID_IDirect3DRefDevice
, interface_name
, device_name
, &d1
, &d2
, context
);
349 if (ret_value
!= D3DENUMRET_OK
)
354 char interface_name
[] = "WINE Direct3DX using OpenGL";
355 TRACE(" enumerating OpenGL D3DDevice interface (IID %s).\n", debugstr_guid(&IID_D3DDEVICE_OpenGL
));
358 ret_value
= cb((LPIID
) &IID_D3DDEVICE_OpenGL
, interface_name
, device_name
, &d1
, &d2
, context
);
359 if (ret_value
!= D3DENUMRET_OK
)
363 return D3DENUMRET_OK
;
366 HRESULT
d3ddevice_enumerate7(LPD3DENUMDEVICESCALLBACK7 cb
, LPVOID context
)
368 D3DDEVICEDESC7 ddesc
;
369 char interface_name
[] = "WINE Direct3D7 using OpenGL";
370 char device_name
[] = "Wine D3D7 device";
372 fill_opengl_caps_7(&ddesc
);
374 TRACE(" enumerating OpenGL D3DDevice7 interface.\n");
376 return cb(interface_name
, device_name
, &ddesc
, context
);
380 GL_IDirect3DDeviceImpl_7_3T_2T_1T_Release(LPDIRECT3DDEVICE7 iface
)
382 ICOM_THIS_FROM(IDirect3DDeviceImpl
, IDirect3DDevice7
, iface
);
383 IDirect3DDeviceGLImpl
*glThis
= (IDirect3DDeviceGLImpl
*) This
;
384 ULONG ref
= InterlockedDecrement(&This
->ref
);
386 TRACE("(%p/%p)->() decrementing from %lu.\n", This
, iface
, ref
+ 1);
390 IDirectDrawSurfaceImpl
*surface
= This
->surface
, *surf
;
392 /* Release texture associated with the device */
393 for (i
= 0; i
< MAX_TEXTURES
; i
++) {
394 if (This
->current_texture
[i
] != NULL
)
395 IDirectDrawSurface7_Release(ICOM_INTERFACE(This
->current_texture
[i
], IDirectDrawSurface7
));
396 HeapFree(GetProcessHeap(), 0, This
->tex_mat
[i
]);
399 /* Look for the front buffer and override its surface's Flip method (if in double buffering) */
400 for (surf
= surface
; surf
!= NULL
; surf
= surf
->surface_owner
) {
401 if ((surf
->surface_desc
.ddsCaps
.dwCaps
&(DDSCAPS_FLIP
|DDSCAPS_FRONTBUFFER
)) == (DDSCAPS_FLIP
|DDSCAPS_FRONTBUFFER
)) {
402 surf
->aux_ctx
= NULL
;
403 surf
->aux_data
= NULL
;
404 surf
->aux_flip
= NULL
;
408 for (surf
= surface
; surf
!= NULL
; surf
= surf
->surface_owner
) {
409 IDirectDrawSurfaceImpl
*surf2
;
410 for (surf2
= surf
; surf2
->prev_attached
!= NULL
; surf2
= surf2
->prev_attached
) ;
411 for (; surf2
!= NULL
; surf2
= surf2
->next_attached
) {
412 if (((surf2
->surface_desc
.ddsCaps
.dwCaps
& (DDSCAPS_3DDEVICE
)) == (DDSCAPS_3DDEVICE
)) &&
413 ((surf2
->surface_desc
.ddsCaps
.dwCaps
& (DDSCAPS_ZBUFFER
)) != (DDSCAPS_ZBUFFER
))) {
414 /* Override the Lock / Unlock function for all these surfaces */
415 surf2
->lock_update
= surf2
->lock_update_prev
;
416 surf2
->unlock_update
= surf2
->unlock_update_prev
;
417 /* And install also the blt / bltfast overrides */
418 surf2
->aux_blt
= NULL
;
419 surf2
->aux_bltfast
= NULL
;
421 surf2
->d3ddevice
= NULL
;
425 /* And warn the D3D object that this device is no longer active... */
426 This
->d3d
->d3d_removed_device(This
->d3d
, This
);
428 HeapFree(GetProcessHeap(), 0, This
->world_mat
);
429 HeapFree(GetProcessHeap(), 0, This
->view_mat
);
430 HeapFree(GetProcessHeap(), 0, This
->proj_mat
);
432 if (glThis
->surface_ptr
)
433 HeapFree(GetProcessHeap(), 0, glThis
->surface_ptr
);
435 DeleteCriticalSection(&(This
->crit
));
438 if (glThis
->unlock_tex
)
439 glDeleteTextures(1, &(glThis
->unlock_tex
));
440 glXDestroyContext(glThis
->display
, glThis
->gl_context
);
442 HeapFree(GetProcessHeap(), 0, This
->clipping_planes
);
444 HeapFree(GetProcessHeap(), 0, This
);
451 GL_IDirect3DDeviceImpl_3_2T_1T_GetCaps(LPDIRECT3DDEVICE3 iface
,
452 LPD3DDEVICEDESC lpD3DHWDevDesc
,
453 LPD3DDEVICEDESC lpD3DHELDevDesc
)
455 ICOM_THIS_FROM(IDirect3DDeviceImpl
, IDirect3DDevice3
, iface
);
459 TRACE("(%p/%p)->(%p,%p)\n", This
, iface
, lpD3DHWDevDesc
, lpD3DHELDevDesc
);
461 fill_opengl_caps(&desc
);
462 dwSize
= lpD3DHWDevDesc
->dwSize
;
463 memset(lpD3DHWDevDesc
, 0, dwSize
);
464 memcpy(lpD3DHWDevDesc
, &desc
, (dwSize
<= desc
.dwSize
? dwSize
: desc
.dwSize
));
466 dwSize
= lpD3DHELDevDesc
->dwSize
;
467 memset(lpD3DHELDevDesc
, 0, dwSize
);
468 memcpy(lpD3DHELDevDesc
, &desc
, (dwSize
<= desc
.dwSize
? dwSize
: desc
.dwSize
));
470 TRACE(" returning caps : (no dump function yet)\n");
475 static HRESULT
enum_texture_format_OpenGL(LPD3DENUMTEXTUREFORMATSCALLBACK cb_1
,
476 LPD3DENUMPIXELFORMATSCALLBACK cb_2
,
477 LPVOID context
, int version
)
480 LPDDPIXELFORMAT pformat
;
482 /* Do the texture enumeration */
483 sdesc
.dwSize
= sizeof(DDSURFACEDESC
);
484 sdesc
.dwFlags
= DDSD_PIXELFORMAT
| DDSD_CAPS
;
485 sdesc
.ddsCaps
.dwCaps
= DDSCAPS_TEXTURE
;
486 pformat
= &(sdesc
.ddpfPixelFormat
);
487 pformat
->dwSize
= sizeof(DDPIXELFORMAT
);
488 pformat
->dwFourCC
= 0;
490 TRACE("Enumerating GL_RGBA unpacked (32)\n");
491 pformat
->dwFlags
= DDPF_RGB
| DDPF_ALPHAPIXELS
;
492 pformat
->u1
.dwRGBBitCount
= 32;
493 pformat
->u2
.dwRBitMask
= 0x00FF0000;
494 pformat
->u3
.dwGBitMask
= 0x0000FF00;
495 pformat
->u4
.dwBBitMask
= 0x000000FF;
496 pformat
->u5
.dwRGBAlphaBitMask
= 0xFF000000;
497 if (cb_1
) if (cb_1(&sdesc
, context
) == 0) return DD_OK
;
498 if (cb_2
) if (cb_2(pformat
, context
) == 0) return DD_OK
;
500 TRACE("Enumerating GL_RGB unpacked (32)\n");
501 pformat
->dwFlags
= DDPF_RGB
;
502 pformat
->u1
.dwRGBBitCount
= 32;
503 pformat
->u2
.dwRBitMask
= 0x00FF0000;
504 pformat
->u3
.dwGBitMask
= 0x0000FF00;
505 pformat
->u4
.dwBBitMask
= 0x000000FF;
506 pformat
->u5
.dwRGBAlphaBitMask
= 0x00000000;
507 if (cb_1
) if (cb_1(&sdesc
, context
) == 0) return DD_OK
;
508 if (cb_2
) if (cb_2(pformat
, context
) == 0) return DD_OK
;
510 TRACE("Enumerating GL_RGB unpacked (24)\n");
511 pformat
->dwFlags
= DDPF_RGB
;
512 pformat
->u1
.dwRGBBitCount
= 24;
513 pformat
->u2
.dwRBitMask
= 0x00FF0000;
514 pformat
->u3
.dwGBitMask
= 0x0000FF00;
515 pformat
->u4
.dwBBitMask
= 0x000000FF;
516 pformat
->u5
.dwRGBAlphaBitMask
= 0x00000000;
517 if (cb_1
) if (cb_1(&sdesc
, context
) == 0) return DD_OK
;
518 if (cb_2
) if (cb_2(pformat
, context
) == 0) return DD_OK
;
520 /* Note : even if this is an 'emulated' texture format, it needs to be first
521 as some dumb applications seem to rely on that. */
522 TRACE("Enumerating GL_RGBA packed GL_UNSIGNED_SHORT_1_5_5_5 (ARGB) (16)\n");
523 pformat
->dwFlags
= DDPF_RGB
| DDPF_ALPHAPIXELS
;
524 pformat
->u1
.dwRGBBitCount
= 16;
525 pformat
->u2
.dwRBitMask
= 0x00007C00;
526 pformat
->u3
.dwGBitMask
= 0x000003E0;
527 pformat
->u4
.dwBBitMask
= 0x0000001F;
528 pformat
->u5
.dwRGBAlphaBitMask
= 0x00008000;
529 if (cb_1
) if (cb_1(&sdesc
, context
) == 0) return DD_OK
;
530 if (cb_2
) if (cb_2(pformat
, context
) == 0) return DD_OK
;
532 TRACE("Enumerating GL_RGBA packed GL_UNSIGNED_SHORT_4_4_4_4 (ARGB) (16)\n");
533 pformat
->dwFlags
= DDPF_RGB
| DDPF_ALPHAPIXELS
;
534 pformat
->u1
.dwRGBBitCount
= 16;
535 pformat
->u2
.dwRBitMask
= 0x00000F00;
536 pformat
->u3
.dwGBitMask
= 0x000000F0;
537 pformat
->u4
.dwBBitMask
= 0x0000000F;
538 pformat
->u5
.dwRGBAlphaBitMask
= 0x0000F000;
539 if (cb_1
) if (cb_1(&sdesc
, context
) == 0) return DD_OK
;
540 if (cb_2
) if (cb_2(pformat
, context
) == 0) return DD_OK
;
542 TRACE("Enumerating GL_RGB packed GL_UNSIGNED_SHORT_5_6_5 (16)\n");
543 pformat
->dwFlags
= DDPF_RGB
;
544 pformat
->u1
.dwRGBBitCount
= 16;
545 pformat
->u2
.dwRBitMask
= 0x0000F800;
546 pformat
->u3
.dwGBitMask
= 0x000007E0;
547 pformat
->u4
.dwBBitMask
= 0x0000001F;
548 pformat
->u5
.dwRGBAlphaBitMask
= 0x00000000;
549 if (cb_1
) if (cb_1(&sdesc
, context
) == 0) return DD_OK
;
550 if (cb_2
) if (cb_2(pformat
, context
) == 0) return DD_OK
;
552 TRACE("Enumerating GL_RGB packed GL_UNSIGNED_SHORT_5_5_5 (16)\n");
553 pformat
->dwFlags
= DDPF_RGB
;
554 pformat
->u1
.dwRGBBitCount
= 16;
555 pformat
->u2
.dwRBitMask
= 0x00007C00;
556 pformat
->u3
.dwGBitMask
= 0x000003E0;
557 pformat
->u4
.dwBBitMask
= 0x0000001F;
558 pformat
->u5
.dwRGBAlphaBitMask
= 0x00000000;
559 if (cb_1
) if (cb_1(&sdesc
, context
) == 0) return DD_OK
;
560 if (cb_2
) if (cb_2(pformat
, context
) == 0) return DD_OK
;
563 /* This is a compromise : some games choose the first 16 bit texture format with alpha they
564 find enumerated, others the last one. And both want to have the ARGB one.
566 So basically, forget our OpenGL roots and do not even enumerate our RGBA ones.
568 /* See argument about the RGBA format for 'packed' texture formats */
569 TRACE("Enumerating GL_RGBA unpacked (32)\n");
570 pformat
->dwFlags
= DDPF_RGB
| DDPF_ALPHAPIXELS
;
571 pformat
->u1
.dwRGBBitCount
= 32;
572 pformat
->u2
.dwRBitMask
= 0xFF000000;
573 pformat
->u3
.dwGBitMask
= 0x00FF0000;
574 pformat
->u4
.dwBBitMask
= 0x0000FF00;
575 pformat
->u5
.dwRGBAlphaBitMask
= 0x000000FF;
576 if (cb_1
) if (cb_1(&sdesc
, context
) == 0) return DD_OK
;
577 if (cb_2
) if (cb_2(pformat
, context
) == 0) return DD_OK
;
579 TRACE("Enumerating GL_RGBA packed GL_UNSIGNED_SHORT_4_4_4_4 (16)\n");
580 pformat
->dwFlags
= DDPF_RGB
| DDPF_ALPHAPIXELS
;
581 pformat
->u1
.dwRGBBitCount
= 16;
582 pformat
->u2
.dwRBitMask
= 0x0000F000;
583 pformat
->u3
.dwGBitMask
= 0x00000F00;
584 pformat
->u4
.dwBBitMask
= 0x000000F0;
585 pformat
->u5
.dwRGBAlphaBitMask
= 0x0000000F;
586 if (cb_1
) if (cb_1(&sdesc
, context
) == 0) return DD_OK
;
587 if (cb_2
) if (cb_2(pformat
, context
) == 0) return DD_OK
;
589 TRACE("Enumerating GL_RGBA packed GL_UNSIGNED_SHORT_5_5_5_1 (16)\n");
590 pformat
->dwFlags
= DDPF_RGB
| DDPF_ALPHAPIXELS
;
591 pformat
->u1
.dwRGBBitCount
= 16;
592 pformat
->u2
.dwRBitMask
= 0x0000F800;
593 pformat
->u3
.dwGBitMask
= 0x000007C0;
594 pformat
->u4
.dwBBitMask
= 0x0000003E;
595 pformat
->u5
.dwRGBAlphaBitMask
= 0x00000001;
596 if (cb_1
) if (cb_1(&sdesc
, context
) == 0) return DD_OK
;
597 if (cb_2
) if (cb_2(pformat
, context
) == 0) return DD_OK
;
600 TRACE("Enumerating GL_RGB packed GL_UNSIGNED_BYTE_3_3_2 (8)\n");
601 pformat
->dwFlags
= DDPF_RGB
;
602 pformat
->u1
.dwRGBBitCount
= 8;
603 pformat
->u2
.dwRBitMask
= 0x000000E0;
604 pformat
->u3
.dwGBitMask
= 0x0000001C;
605 pformat
->u4
.dwBBitMask
= 0x00000003;
606 pformat
->u5
.dwRGBAlphaBitMask
= 0x00000000;
607 if (cb_1
) if (cb_1(&sdesc
, context
) == 0) return DD_OK
;
608 if (cb_2
) if (cb_2(pformat
, context
) == 0) return DD_OK
;
610 TRACE("Enumerating Paletted (8)\n");
611 pformat
->dwFlags
= DDPF_PALETTEINDEXED8
;
612 pformat
->u1
.dwRGBBitCount
= 8;
613 pformat
->u2
.dwRBitMask
= 0x00000000;
614 pformat
->u3
.dwGBitMask
= 0x00000000;
615 pformat
->u4
.dwBBitMask
= 0x00000000;
616 pformat
->u5
.dwRGBAlphaBitMask
= 0x00000000;
617 if (cb_1
) if (cb_1(&sdesc
, context
) == 0) return DD_OK
;
618 if (cb_2
) if (cb_2(pformat
, context
) == 0) return DD_OK
;
620 /* DXT textures only exist for devices created from IDirect3D3 and above */
621 if ((version
>= 3) && GL_extensions
.s3tc_compressed_texture
) {
622 TRACE("Enumerating DXT1\n");
623 pformat
->dwFlags
= DDPF_FOURCC
;
624 pformat
->dwFourCC
= MAKE_FOURCC('D','X','T','1');
625 if (cb_1
) if (cb_1(&sdesc
, context
) == 0) return DD_OK
;
626 if (cb_2
) if (cb_2(pformat
, context
) == 0) return DD_OK
;
628 TRACE("Enumerating DXT3\n");
629 pformat
->dwFlags
= DDPF_FOURCC
;
630 pformat
->dwFourCC
= MAKE_FOURCC('D','X','T','3');
631 if (cb_1
) if (cb_1(&sdesc
, context
) == 0) return DD_OK
;
632 if (cb_2
) if (cb_2(pformat
, context
) == 0) return DD_OK
;
634 TRACE("Enumerating DXT5\n");
635 pformat
->dwFlags
= DDPF_FOURCC
;
636 pformat
->dwFourCC
= MAKE_FOURCC('D','X','T','5');
637 if (cb_1
) if (cb_1(&sdesc
, context
) == 0) return DD_OK
;
638 if (cb_2
) if (cb_2(pformat
, context
) == 0) return DD_OK
;
641 TRACE("End of enumeration\n");
647 d3ddevice_find(IDirectDrawImpl
*d3d
,
648 LPD3DFINDDEVICESEARCH lpD3DDFS
,
649 LPD3DFINDDEVICERESULT lplpD3DDevice
)
653 if ((lpD3DDFS
->dwFlags
& D3DFDS_COLORMODEL
) &&
654 (lpD3DDFS
->dcmColorModel
!= D3DCOLOR_RGB
)) {
655 TRACE(" trying to request a non-RGB D3D color model. Not supported.\n");
656 return DDERR_INVALIDPARAMS
; /* No real idea what to return here :-) */
658 if (lpD3DDFS
->dwFlags
& D3DFDS_GUID
) {
659 TRACE(" trying to match guid %s.\n", debugstr_guid(&(lpD3DDFS
->guid
)));
660 if ((IsEqualGUID(&IID_D3DDEVICE_OpenGL
, &(lpD3DDFS
->guid
)) == 0) &&
661 (IsEqualGUID(&IID_IDirect3DHALDevice
, &(lpD3DDFS
->guid
)) == 0) &&
662 (IsEqualGUID(&IID_IDirect3DRefDevice
, &(lpD3DDFS
->guid
)) == 0)) {
663 TRACE(" no match for this GUID.\n");
664 return DDERR_INVALIDPARAMS
;
668 /* Now return our own GUID */
669 lplpD3DDevice
->guid
= IID_D3DDEVICE_OpenGL
;
670 fill_opengl_caps(&desc
);
671 lplpD3DDevice
->ddHwDesc
= desc
;
672 lplpD3DDevice
->ddSwDesc
= desc
;
674 TRACE(" returning Wine's OpenGL device with (undumped) capabilities\n");
680 GL_IDirect3DDeviceImpl_2_1T_EnumTextureFormats(LPDIRECT3DDEVICE2 iface
,
681 LPD3DENUMTEXTUREFORMATSCALLBACK lpD3DEnumTextureProc
,
684 ICOM_THIS_FROM(IDirect3DDeviceImpl
, IDirect3DDevice2
, iface
);
685 TRACE("(%p/%p)->(%p,%p)\n", This
, iface
, lpD3DEnumTextureProc
, lpArg
);
686 return enum_texture_format_OpenGL(lpD3DEnumTextureProc
, NULL
, lpArg
, This
->version
);
690 GL_IDirect3DDeviceImpl_7_3T_EnumTextureFormats(LPDIRECT3DDEVICE7 iface
,
691 LPD3DENUMPIXELFORMATSCALLBACK lpD3DEnumPixelProc
,
694 ICOM_THIS_FROM(IDirect3DDeviceImpl
, IDirect3DDevice7
, iface
);
695 TRACE("(%p/%p)->(%p,%p)\n", This
, iface
, lpD3DEnumPixelProc
, lpArg
);
696 return enum_texture_format_OpenGL(NULL
, lpD3DEnumPixelProc
, lpArg
, This
->version
);
700 GL_IDirect3DDeviceImpl_7_3T_2T_SetRenderState(LPDIRECT3DDEVICE7 iface
,
701 D3DRENDERSTATETYPE dwRenderStateType
,
704 ICOM_THIS_FROM(IDirect3DDeviceImpl
, IDirect3DDevice7
, iface
);
705 TRACE("(%p/%p)->(%08x,%08lx)\n", This
, iface
, dwRenderStateType
, dwRenderState
);
707 /* Call the render state functions */
708 store_render_state(This
, dwRenderStateType
, dwRenderState
, &This
->state_block
);
709 set_render_state(This
, dwRenderStateType
, &This
->state_block
);
715 GL_IDirect3DDeviceImpl_7_3T_2T_GetRenderState(LPDIRECT3DDEVICE7 iface
,
716 D3DRENDERSTATETYPE dwRenderStateType
,
717 LPDWORD lpdwRenderState
)
719 ICOM_THIS_FROM(IDirect3DDeviceImpl
, IDirect3DDevice7
, iface
);
720 TRACE("(%p/%p)->(%08x,%p)\n", This
, iface
, dwRenderStateType
, lpdwRenderState
);
722 /* Call the render state functions */
723 get_render_state(This
, dwRenderStateType
, lpdwRenderState
, &This
->state_block
);
725 TRACE(" - asked for rendering state : %s, returning value %08lx.\n", _get_renderstate(dwRenderStateType
), *lpdwRenderState
);
731 GL_IDirect3DDeviceImpl_3_2T_GetLightState(LPDIRECT3DDEVICE3 iface
,
732 D3DLIGHTSTATETYPE dwLightStateType
,
733 LPDWORD lpdwLightState
)
735 ICOM_THIS_FROM(IDirect3DDeviceImpl
, IDirect3DDevice3
, iface
);
737 TRACE("(%p/%p)->(%08x,%p)\n", This
, iface
, dwLightStateType
, lpdwLightState
);
739 if (!dwLightStateType
&& (dwLightStateType
> D3DLIGHTSTATE_COLORVERTEX
)) {
740 TRACE("Unexpected Light State Type\n");
741 return DDERR_INVALIDPARAMS
;
744 if (dwLightStateType
== D3DLIGHTSTATE_MATERIAL
/* 1 */) {
745 *lpdwLightState
= This
->material
;
746 } else if (dwLightStateType
== D3DLIGHTSTATE_COLORMODEL
/* 3 */) {
747 *lpdwLightState
= D3DCOLOR_RGB
;
749 D3DRENDERSTATETYPE rs
;
750 switch (dwLightStateType
) {
751 case D3DLIGHTSTATE_AMBIENT
: /* 2 */
752 rs
= D3DRENDERSTATE_AMBIENT
;
754 case D3DLIGHTSTATE_FOGMODE
: /* 4 */
755 rs
= D3DRENDERSTATE_FOGVERTEXMODE
;
757 case D3DLIGHTSTATE_FOGSTART
: /* 5 */
758 rs
= D3DRENDERSTATE_FOGSTART
;
760 case D3DLIGHTSTATE_FOGEND
: /* 6 */
761 rs
= D3DRENDERSTATE_FOGEND
;
763 case D3DLIGHTSTATE_FOGDENSITY
: /* 7 */
764 rs
= D3DRENDERSTATE_FOGDENSITY
;
766 case D3DLIGHTSTATE_COLORVERTEX
: /* 8 */
767 rs
= D3DRENDERSTATE_COLORVERTEX
;
770 ERR("Unknown D3DLIGHTSTATETYPE %d.\n", dwLightStateType
);
771 return DDERR_INVALIDPARAMS
;
774 IDirect3DDevice7_GetRenderState(ICOM_INTERFACE(This
, IDirect3DDevice7
),
782 GL_IDirect3DDeviceImpl_3_2T_SetLightState(LPDIRECT3DDEVICE3 iface
,
783 D3DLIGHTSTATETYPE dwLightStateType
,
786 ICOM_THIS_FROM(IDirect3DDeviceImpl
, IDirect3DDevice3
, iface
);
788 TRACE("(%p/%p)->(%08x,%08lx)\n", This
, iface
, dwLightStateType
, dwLightState
);
790 if (!dwLightStateType
&& (dwLightStateType
> D3DLIGHTSTATE_COLORVERTEX
)) {
791 TRACE("Unexpected Light State Type\n");
792 return DDERR_INVALIDPARAMS
;
795 if (dwLightStateType
== D3DLIGHTSTATE_MATERIAL
/* 1 */) {
796 IDirect3DMaterialImpl
*mat
= (IDirect3DMaterialImpl
*) dwLightState
;
799 TRACE(" activating material %p.\n", mat
);
802 FIXME(" D3DLIGHTSTATE_MATERIAL called with NULL material !!!\n");
804 This
->material
= dwLightState
;
805 } else if (dwLightStateType
== D3DLIGHTSTATE_COLORMODEL
/* 3 */) {
806 switch (dwLightState
) {
808 ERR("DDCOLOR_MONO should not happen!\n");
811 /* We are already in this mode */
812 TRACE("Setting color model to RGB (no-op).\n");
815 ERR("Unknown color model!\n");
816 return DDERR_INVALIDPARAMS
;
819 D3DRENDERSTATETYPE rs
;
820 switch (dwLightStateType
) {
821 case D3DLIGHTSTATE_AMBIENT
: /* 2 */
822 rs
= D3DRENDERSTATE_AMBIENT
;
824 case D3DLIGHTSTATE_FOGMODE
: /* 4 */
825 rs
= D3DRENDERSTATE_FOGVERTEXMODE
;
827 case D3DLIGHTSTATE_FOGSTART
: /* 5 */
828 rs
= D3DRENDERSTATE_FOGSTART
;
830 case D3DLIGHTSTATE_FOGEND
: /* 6 */
831 rs
= D3DRENDERSTATE_FOGEND
;
833 case D3DLIGHTSTATE_FOGDENSITY
: /* 7 */
834 rs
= D3DRENDERSTATE_FOGDENSITY
;
836 case D3DLIGHTSTATE_COLORVERTEX
: /* 8 */
837 rs
= D3DRENDERSTATE_COLORVERTEX
;
840 ERR("Unknown D3DLIGHTSTATETYPE %d.\n", dwLightStateType
);
841 return DDERR_INVALIDPARAMS
;
844 IDirect3DDevice7_SetRenderState(ICOM_INTERFACE(This
, IDirect3DDevice7
),
851 static GLenum
convert_D3D_ptype_to_GL(D3DPRIMITIVETYPE d3dpt
)
854 case D3DPT_POINTLIST
:
855 TRACE(" primitive type is POINTS\n");
859 TRACE(" primitive type is LINES\n");
862 case D3DPT_LINESTRIP
:
863 TRACE(" primitive type is LINE_STRIP\n");
864 return GL_LINE_STRIP
;
866 case D3DPT_TRIANGLELIST
:
867 TRACE(" primitive type is TRIANGLES\n");
870 case D3DPT_TRIANGLESTRIP
:
871 TRACE(" primitive type is TRIANGLE_STRIP\n");
872 return GL_TRIANGLE_STRIP
;
874 case D3DPT_TRIANGLEFAN
:
875 TRACE(" primitive type is TRIANGLE_FAN\n");
876 return GL_TRIANGLE_FAN
;
879 FIXME("Unhandled primitive %08x\n", d3dpt
);
884 /* This function calculate the Z coordinate from Zproj */
885 static float ZfromZproj(IDirect3DDeviceImpl
*This
, D3DVALUE Zproj
)
888 /* Assume that X = Y = 0 and W = 1 */
889 a
= This
->proj_mat
->_33
;
890 b
= This
->proj_mat
->_34
;
891 c
= This
->proj_mat
->_43
;
892 d
= This
->proj_mat
->_44
;
893 /* We have in homogenous coordinates Z' = a * Z + c and W' = b * Z + d
894 * So in non homogenous coordinates we have Zproj = (a * Z + c) / (b * Z + d)
895 * And finally Z = (d * Zproj - c) / (a - b * Zproj)
897 return (d
*Zproj
- c
) / (a
- b
*Zproj
);
900 static void build_fog_table(BYTE
*fog_table
, DWORD fog_color
) {
903 TRACE(" rebuilding fog table (%06lx)...\n", fog_color
& 0x00FFFFFF);
905 for (i
= 0; i
< 3; i
++) {
906 BYTE fog_color_component
= (fog_color
>> (8 * i
)) & 0xFF;
908 for (elt
= 0; elt
< 0x10000; elt
++) {
909 /* We apply the fog transformation and cache the result */
910 DWORD fog_intensity
= elt
& 0xFF;
911 DWORD vertex_color
= (elt
>> 8) & 0xFF;
912 fog_table
[(i
* 0x10000) + elt
] = ((fog_intensity
* vertex_color
) + ((0xFF - fog_intensity
) * fog_color_component
)) / 0xFF;
917 static void draw_primitive_handle_GL_state(IDirect3DDeviceImpl
*This
,
918 BOOLEAN vertex_transformed
,
919 BOOLEAN vertex_lit
) {
920 IDirect3DDeviceGLImpl
* glThis
= (IDirect3DDeviceGLImpl
*) This
;
922 /* Puts GL in the correct lighting / transformation mode */
923 if ((vertex_transformed
== FALSE
) &&
924 (glThis
->transform_state
!= GL_TRANSFORM_NORMAL
)) {
925 /* Need to put the correct transformation again if we go from Transformed
926 vertices to non-transformed ones.
928 This
->set_matrices(This
, VIEWMAT_CHANGED
|WORLDMAT_CHANGED
|PROJMAT_CHANGED
,
929 This
->world_mat
, This
->view_mat
, This
->proj_mat
);
930 glThis
->transform_state
= GL_TRANSFORM_NORMAL
;
932 } else if (vertex_transformed
&&
933 (glThis
->transform_state
!= GL_TRANSFORM_ORTHO
)) {
934 /* Set our orthographic projection */
935 if (glThis
->transform_state
!= GL_TRANSFORM_ORTHO
) {
936 glThis
->transform_state
= GL_TRANSFORM_ORTHO
;
937 d3ddevice_set_ortho(This
);
941 /* TODO: optimize this to not always reset all the fog stuff on all DrawPrimitive call
942 if no fogging state change occurred */
943 if (This
->state_block
.render_state
[D3DRENDERSTATE_FOGENABLE
- 1]) {
944 if (vertex_transformed
) {
945 if (glThis
->fogging
!= 0) {
949 /* Now check if our fog_table still corresponds to the current vertex color.
950 Element '0x..00' is always the fog color as it corresponds to maximum fog intensity */
951 if ((glThis
->fog_table
[0 * 0x10000 + 0x0000] != ((This
->state_block
.render_state
[D3DRENDERSTATE_FOGCOLOR
- 1] >> 0) & 0xFF)) ||
952 (glThis
->fog_table
[1 * 0x10000 + 0x0000] != ((This
->state_block
.render_state
[D3DRENDERSTATE_FOGCOLOR
- 1] >> 8) & 0xFF)) ||
953 (glThis
->fog_table
[2 * 0x10000 + 0x0000] != ((This
->state_block
.render_state
[D3DRENDERSTATE_FOGCOLOR
- 1] >> 16) & 0xFF))) {
954 /* We need to rebuild our fog table.... */
955 build_fog_table(glThis
->fog_table
, This
->state_block
.render_state
[D3DRENDERSTATE_FOGCOLOR
- 1]);
958 if (This
->state_block
.render_state
[D3DRENDERSTATE_FOGTABLEMODE
- 1] != D3DFOG_NONE
) {
959 switch (This
->state_block
.render_state
[D3DRENDERSTATE_FOGTABLEMODE
- 1]) {
960 case D3DFOG_LINEAR
: glFogi(GL_FOG_MODE
, GL_LINEAR
); break;
961 case D3DFOG_EXP
: glFogi(GL_FOG_MODE
, GL_EXP
); break;
962 case D3DFOG_EXP2
: glFogi(GL_FOG_MODE
, GL_EXP2
); break;
964 if (vertex_lit
== FALSE
) {
965 glFogf(GL_FOG_START
, *(float*)&This
->state_block
.render_state
[D3DRENDERSTATE_FOGSTART
- 1]);
966 glFogf(GL_FOG_END
, *(float*)&This
->state_block
.render_state
[D3DRENDERSTATE_FOGEND
- 1]);
968 /* Special case of 'pixel fog' */
969 glFogf(GL_FOG_START
, ZfromZproj(This
, *(float*)&This
->state_block
.render_state
[D3DRENDERSTATE_FOGSTART
- 1]));
970 glFogf(GL_FOG_END
, ZfromZproj(This
, *(float*)&This
->state_block
.render_state
[D3DRENDERSTATE_FOGEND
- 1]));
972 if (glThis
->fogging
== 0) {
977 if (glThis
->fogging
!= 0) {
984 if (glThis
->fogging
!= 0) {
990 /* Handle the 'no-normal' case */
991 if ((vertex_lit
== FALSE
) && This
->state_block
.render_state
[D3DRENDERSTATE_LIGHTING
- 1]) {
992 if (glThis
->lighting
== 0) {
993 glEnable(GL_LIGHTING
);
994 glThis
->lighting
= 1;
997 if (glThis
->lighting
!= 0) {
998 glDisable(GL_LIGHTING
);
999 glThis
->lighting
= 0;
1003 /* Handle the code for pre-vertex material properties */
1004 if (vertex_transformed
== FALSE
) {
1005 if (This
->state_block
.render_state
[D3DRENDERSTATE_LIGHTING
- 1] &&
1006 This
->state_block
.render_state
[D3DRENDERSTATE_COLORVERTEX
- 1]) {
1007 if ((This
->state_block
.render_state
[D3DRENDERSTATE_DIFFUSEMATERIALSOURCE
- 1] != D3DMCS_MATERIAL
) ||
1008 (This
->state_block
.render_state
[D3DRENDERSTATE_AMBIENTMATERIALSOURCE
- 1] != D3DMCS_MATERIAL
) ||
1009 (This
->state_block
.render_state
[D3DRENDERSTATE_EMISSIVEMATERIALSOURCE
- 1] != D3DMCS_MATERIAL
) ||
1010 (This
->state_block
.render_state
[D3DRENDERSTATE_SPECULARMATERIALSOURCE
- 1] != D3DMCS_MATERIAL
)) {
1011 glEnable(GL_COLOR_MATERIAL
);
1018 inline static void draw_primitive(IDirect3DDeviceImpl
*This
, DWORD maxvert
, WORD
*index
,
1019 D3DVERTEXTYPE d3dvt
, D3DPRIMITIVETYPE d3dpt
, void *lpvertex
)
1021 D3DDRAWPRIMITIVESTRIDEDDATA strided
;
1024 case D3DVT_VERTEX
: {
1025 strided
.position
.lpvData
= &((D3DVERTEX
*) lpvertex
)->u1
.x
;
1026 strided
.position
.dwStride
= sizeof(D3DVERTEX
);
1027 strided
.normal
.lpvData
= &((D3DVERTEX
*) lpvertex
)->u4
.nx
;
1028 strided
.normal
.dwStride
= sizeof(D3DVERTEX
);
1029 strided
.textureCoords
[0].lpvData
= &((D3DVERTEX
*) lpvertex
)->u7
.tu
;
1030 strided
.textureCoords
[0].dwStride
= sizeof(D3DVERTEX
);
1031 draw_primitive_strided(This
, d3dpt
, D3DFVF_VERTEX
, &strided
, 0 /* Unused */, index
, maxvert
, 0 /* Unused */);
1034 case D3DVT_LVERTEX
: {
1035 strided
.position
.lpvData
= &((D3DLVERTEX
*) lpvertex
)->u1
.x
;
1036 strided
.position
.dwStride
= sizeof(D3DLVERTEX
);
1037 strided
.diffuse
.lpvData
= &((D3DLVERTEX
*) lpvertex
)->u4
.color
;
1038 strided
.diffuse
.dwStride
= sizeof(D3DLVERTEX
);
1039 strided
.specular
.lpvData
= &((D3DLVERTEX
*) lpvertex
)->u5
.specular
;
1040 strided
.specular
.dwStride
= sizeof(D3DLVERTEX
);
1041 strided
.textureCoords
[0].lpvData
= &((D3DLVERTEX
*) lpvertex
)->u6
.tu
;
1042 strided
.textureCoords
[0].dwStride
= sizeof(D3DLVERTEX
);
1043 draw_primitive_strided(This
, d3dpt
, D3DFVF_LVERTEX
, &strided
, 0 /* Unused */, index
, maxvert
, 0 /* Unused */);
1046 case D3DVT_TLVERTEX
: {
1047 strided
.position
.lpvData
= &((D3DTLVERTEX
*) lpvertex
)->u1
.sx
;
1048 strided
.position
.dwStride
= sizeof(D3DTLVERTEX
);
1049 strided
.diffuse
.lpvData
= &((D3DTLVERTEX
*) lpvertex
)->u5
.color
;
1050 strided
.diffuse
.dwStride
= sizeof(D3DTLVERTEX
);
1051 strided
.specular
.lpvData
= &((D3DTLVERTEX
*) lpvertex
)->u6
.specular
;
1052 strided
.specular
.dwStride
= sizeof(D3DTLVERTEX
);
1053 strided
.textureCoords
[0].lpvData
= &((D3DTLVERTEX
*) lpvertex
)->u7
.tu
;
1054 strided
.textureCoords
[0].dwStride
= sizeof(D3DTLVERTEX
);
1055 draw_primitive_strided(This
, d3dpt
, D3DFVF_TLVERTEX
, &strided
, 0 /* Unused */, index
, maxvert
, 0 /* Unused */);
1059 FIXME("Unhandled vertex type %08x\n", d3dvt
);
1065 GL_IDirect3DDeviceImpl_2_DrawPrimitive(LPDIRECT3DDEVICE2 iface
,
1066 D3DPRIMITIVETYPE d3dptPrimitiveType
,
1067 D3DVERTEXTYPE d3dvtVertexType
,
1069 DWORD dwVertexCount
,
1072 ICOM_THIS_FROM(IDirect3DDeviceImpl
, IDirect3DDevice2
, iface
);
1074 TRACE("(%p/%p)->(%08x,%08x,%p,%08lx,%08lx)\n", This
, iface
, d3dptPrimitiveType
, d3dvtVertexType
, lpvVertices
, dwVertexCount
, dwFlags
);
1075 if (TRACE_ON(ddraw
)) {
1076 TRACE(" - flags : "); dump_DPFLAGS(dwFlags
);
1079 draw_primitive(This
, dwVertexCount
, NULL
, d3dvtVertexType
, d3dptPrimitiveType
, lpvVertices
);
1085 GL_IDirect3DDeviceImpl_2_DrawIndexedPrimitive(LPDIRECT3DDEVICE2 iface
,
1086 D3DPRIMITIVETYPE d3dptPrimitiveType
,
1087 D3DVERTEXTYPE d3dvtVertexType
,
1089 DWORD dwVertexCount
,
1094 ICOM_THIS_FROM(IDirect3DDeviceImpl
, IDirect3DDevice2
, iface
);
1095 TRACE("(%p/%p)->(%08x,%08x,%p,%08lx,%p,%08lx,%08lx)\n", This
, iface
, d3dptPrimitiveType
, d3dvtVertexType
, lpvVertices
, dwVertexCount
, dwIndices
, dwIndexCount
, dwFlags
);
1096 if (TRACE_ON(ddraw
)) {
1097 TRACE(" - flags : "); dump_DPFLAGS(dwFlags
);
1100 draw_primitive(This
, dwIndexCount
, dwIndices
, d3dvtVertexType
, d3dptPrimitiveType
, lpvVertices
);
1106 GL_IDirect3DDeviceImpl_1_CreateExecuteBuffer(LPDIRECT3DDEVICE iface
,
1107 LPD3DEXECUTEBUFFERDESC lpDesc
,
1108 LPDIRECT3DEXECUTEBUFFER
* lplpDirect3DExecuteBuffer
,
1109 IUnknown
* pUnkOuter
)
1111 ICOM_THIS_FROM(IDirect3DDeviceImpl
, IDirect3DDevice
, iface
);
1112 IDirect3DExecuteBufferImpl
*ret
;
1115 TRACE("(%p/%p)->(%p,%p,%p)\n", This
, iface
, lpDesc
, lplpDirect3DExecuteBuffer
, pUnkOuter
);
1117 ret_value
= d3dexecutebuffer_create(&ret
, This
->d3d
, This
, lpDesc
);
1118 *lplpDirect3DExecuteBuffer
= ICOM_INTERFACE(ret
, IDirect3DExecuteBuffer
);
1120 TRACE(" returning %p.\n", *lplpDirect3DExecuteBuffer
);
1125 static void flush_zbuffer_to_GL(IDirect3DDeviceImpl
*d3d_dev
, LPCRECT pRect
, IDirectDrawSurfaceImpl
*surf
) {
1126 static BOOLEAN first
= TRUE
;
1127 IDirect3DDeviceGLImpl
* gl_d3d_dev
= (IDirect3DDeviceGLImpl
*) d3d_dev
;
1132 MESSAGE("Warning : application does direct locking of ZBuffer - expect slowdowns on many GL implementations :-)\n");
1136 TRACE("flushing ZBuffer back to GL\n");
1138 if (gl_d3d_dev
->transform_state
!= GL_TRANSFORM_ORTHO
) {
1139 gl_d3d_dev
->transform_state
= GL_TRANSFORM_ORTHO
;
1140 d3ddevice_set_ortho(d3d_dev
);
1143 glMatrixMode(GL_MODELVIEW
);
1146 if (gl_d3d_dev
->depth_test
== 0) glEnable(GL_DEPTH_TEST
);
1147 if (d3d_dev
->state_block
.render_state
[D3DRENDERSTATE_ZFUNC
- 1] != D3DCMP_ALWAYS
) glDepthFunc(GL_ALWAYS
);
1148 glColorMask(GL_FALSE
, GL_FALSE
, GL_FALSE
, GL_FALSE
);
1150 /* This loop here is to prevent using PixelZoom that may be unoptimized for the 1.0 / -1.0 case
1153 switch (surf
->surface_desc
.u4
.ddpfPixelFormat
.u1
.dwZBufferBitDepth
) {
1154 case 16: type
= GL_UNSIGNED_SHORT
; break;
1155 case 32: type
= GL_UNSIGNED_INT
; break;
1156 default: FIXME("Unhandled ZBuffer format !\n"); goto restore_state
;
1159 for (row
= 0; row
< surf
->surface_desc
.dwHeight
; row
++) {
1160 /* glRasterPos3d(0.0, row + 1.0, 0.5); */
1161 glRasterPos2i(0, row
+ 1);
1162 glDrawPixels(surf
->surface_desc
.dwWidth
, 1, GL_DEPTH_COMPONENT
, type
,
1163 ((unsigned char *) surf
->surface_desc
.lpSurface
) + (row
* surf
->surface_desc
.u1
.lPitch
));
1167 glColorMask(GL_TRUE
, GL_TRUE
, GL_TRUE
, GL_TRUE
);
1168 if (d3d_dev
->state_block
.render_state
[D3DRENDERSTATE_ZFUNC
- 1] != D3DCMP_ALWAYS
)
1169 glDepthFunc(convert_D3D_compare_to_GL(d3d_dev
->state_block
.render_state
[D3DRENDERSTATE_ZFUNC
- 1]));
1170 if (gl_d3d_dev
->depth_test
== 0) glDisable(GL_DEPTH_TEST
);
1173 /* These are the various handler used in the generic path */
1174 inline static void handle_xyz(D3DVALUE
*coords
) {
1175 glVertex3fv(coords
);
1177 inline static void handle_xyzrhw(D3DVALUE
*coords
) {
1178 if ((coords
[3] < 1e-8) && (coords
[3] > -1e-8))
1179 glVertex3fv(coords
);
1181 GLfloat w
= 1.0 / coords
[3];
1183 glVertex4f(coords
[0] * w
,
1189 inline static void handle_normal(D3DVALUE
*coords
) {
1190 glNormal3fv(coords
);
1193 inline static void handle_diffuse_base(STATEBLOCK
*sb
, DWORD
*color
) {
1194 if (sb
->render_state
[D3DRENDERSTATE_ALPHATESTENABLE
- 1] ||
1195 sb
->render_state
[D3DRENDERSTATE_ALPHABLENDENABLE
- 1]) {
1196 glColor4ub((*color
>> 16) & 0xFF,
1197 (*color
>> 8) & 0xFF,
1198 (*color
>> 0) & 0xFF,
1199 (*color
>> 24) & 0xFF);
1201 glColor3ub((*color
>> 16) & 0xFF,
1202 (*color
>> 8) & 0xFF,
1203 (*color
>> 0) & 0xFF);
1207 inline static void handle_specular_base(STATEBLOCK
*sb
, DWORD
*color
) {
1208 glColor4ub((*color
>> 16) & 0xFF,
1209 (*color
>> 8) & 0xFF,
1210 (*color
>> 0) & 0xFF,
1211 (*color
>> 24) & 0xFF); /* No idea if the alpha field is really used.. */
1214 inline static void handle_diffuse(STATEBLOCK
*sb
, DWORD
*color
, BOOLEAN lighted
) {
1215 if ((lighted
== FALSE
) &&
1216 sb
->render_state
[D3DRENDERSTATE_LIGHTING
- 1] &&
1217 sb
->render_state
[D3DRENDERSTATE_COLORVERTEX
- 1]) {
1218 if (sb
->render_state
[D3DRENDERSTATE_DIFFUSEMATERIALSOURCE
- 1] == D3DMCS_COLOR1
) {
1219 glColorMaterial(GL_FRONT_AND_BACK
, GL_DIFFUSE
);
1220 handle_diffuse_base(sb
, color
);
1222 if (sb
->render_state
[D3DRENDERSTATE_AMBIENTMATERIALSOURCE
- 1] == D3DMCS_COLOR1
) {
1223 glColorMaterial(GL_FRONT_AND_BACK
, GL_AMBIENT
);
1224 handle_diffuse_base(sb
, color
);
1226 if ((sb
->render_state
[D3DRENDERSTATE_SPECULARMATERIALSOURCE
- 1] == D3DMCS_COLOR1
) &&
1227 sb
->render_state
[D3DRENDERSTATE_SPECULARENABLE
- 1]) {
1228 glColorMaterial(GL_FRONT_AND_BACK
, GL_SPECULAR
);
1229 handle_diffuse_base(sb
, color
);
1231 if (sb
->render_state
[D3DRENDERSTATE_EMISSIVEMATERIALSOURCE
- 1] == D3DMCS_COLOR1
) {
1232 glColorMaterial(GL_FRONT_AND_BACK
, GL_EMISSION
);
1233 handle_diffuse_base(sb
, color
);
1236 handle_diffuse_base(sb
, color
);
1240 inline static void handle_specular(STATEBLOCK
*sb
, DWORD
*color
, BOOLEAN lighted
) {
1241 if ((lighted
== FALSE
) &&
1242 sb
->render_state
[D3DRENDERSTATE_LIGHTING
- 1] &&
1243 sb
->render_state
[D3DRENDERSTATE_COLORVERTEX
- 1]) {
1244 if (sb
->render_state
[D3DRENDERSTATE_DIFFUSEMATERIALSOURCE
- 1] == D3DMCS_COLOR2
) {
1245 glColorMaterial(GL_FRONT_AND_BACK
, GL_DIFFUSE
);
1246 handle_specular_base(sb
, color
);
1248 if (sb
->render_state
[D3DRENDERSTATE_AMBIENTMATERIALSOURCE
- 1] == D3DMCS_COLOR2
) {
1249 glColorMaterial(GL_FRONT_AND_BACK
, GL_AMBIENT
);
1250 handle_specular_base(sb
, color
);
1252 if ((sb
->render_state
[D3DRENDERSTATE_SPECULARMATERIALSOURCE
- 1] == D3DMCS_COLOR2
) &&
1253 sb
->render_state
[D3DRENDERSTATE_SPECULARENABLE
- 1]) {
1254 glColorMaterial(GL_FRONT_AND_BACK
, GL_SPECULAR
);
1255 handle_specular_base(sb
, color
);
1257 if (sb
->render_state
[D3DRENDERSTATE_EMISSIVEMATERIALSOURCE
- 1] == D3DMCS_COLOR2
) {
1258 glColorMaterial(GL_FRONT_AND_BACK
, GL_EMISSION
);
1259 handle_specular_base(sb
, color
);
1262 /* No else here as we do not know how to handle 'specular' on its own in any case.. */
1265 inline static void handle_diffuse_and_specular(STATEBLOCK
*sb
, BYTE
*fog_table
, DWORD
*color_d
, DWORD
*color_s
, BOOLEAN lighted
) {
1267 DWORD color
= *color_d
;
1268 if (sb
->render_state
[D3DRENDERSTATE_FOGENABLE
- 1]) {
1269 /* Special case where the specular value is used to do fogging */
1270 BYTE fog_intensity
= *color_s
>> 24; /* The alpha value of the specular component is the fog 'intensity' for this vertex */
1271 color
&= 0xFF000000; /* Only keep the alpha component */
1272 color
|= fog_table
[((*color_d
>> 0) & 0xFF) << 8 | fog_intensity
] << 0;
1273 color
|= fog_table
[((*color_d
>> 8) & 0xFF) << 8 | fog_intensity
] << 8;
1274 color
|= fog_table
[((*color_d
>> 16) & 0xFF) << 8 | fog_intensity
] << 16;
1276 if (sb
->render_state
[D3DRENDERSTATE_SPECULARENABLE
- 1]) {
1277 /* Standard specular value in transformed mode. TODO */
1279 handle_diffuse_base(sb
, &color
);
1281 if (sb
->render_state
[D3DRENDERSTATE_LIGHTING
- 1]) {
1282 handle_diffuse(sb
, color_d
, FALSE
);
1283 handle_specular(sb
, color_s
, FALSE
);
1285 /* In that case, only put the diffuse color... */
1286 handle_diffuse_base(sb
, color_d
);
1291 inline static void handle_texture(D3DVALUE
*coords
) {
1292 glTexCoord2fv(coords
);
1294 inline static void handle_textures(const D3DVALUE
*coords
, int tex_stage
) {
1295 if (GL_extensions
.glMultiTexCoord2fv
) {
1296 GL_extensions
.glMultiTexCoord2fv(GL_TEXTURE0_WINE
+ tex_stage
, coords
);
1298 if (tex_stage
== 0) glTexCoord2fv(coords
);
1302 static void draw_primitive_strided(IDirect3DDeviceImpl
*This
,
1303 D3DPRIMITIVETYPE d3dptPrimitiveType
,
1304 DWORD d3dvtVertexType
,
1305 LPD3DDRAWPRIMITIVESTRIDEDDATA lpD3DDrawPrimStrideData
,
1306 DWORD dwVertexCount
,
1311 BOOLEAN vertex_lighted
= FALSE
;
1312 IDirect3DDeviceGLImpl
* glThis
= (IDirect3DDeviceGLImpl
*) This
;
1313 int num_active_stages
= 0;
1314 int num_tex_index
= ((d3dvtVertexType
& D3DFVF_TEXCOUNT_MASK
) >> D3DFVF_TEXCOUNT_SHIFT
);
1316 /* I put the trace before the various locks... So as to better understand where locks occur :-) */
1317 if (TRACE_ON(ddraw
)) {
1318 TRACE(" Vertex format : "); dump_flexible_vertex(d3dvtVertexType
);
1321 /* This is to prevent 'thread contention' between a thread locking the device and another
1322 doing 3D display on it... */
1323 EnterCriticalSection(&(This
->crit
));
1326 if (glThis
->state
[WINE_GL_BUFFER_BACK
] == SURFACE_MEMORY_DIRTY
) {
1327 This
->flush_to_framebuffer(This
, &(glThis
->lock_rect
[WINE_GL_BUFFER_BACK
]), glThis
->lock_surf
[WINE_GL_BUFFER_BACK
]);
1329 glThis
->state
[WINE_GL_BUFFER_BACK
] = SURFACE_GL
;
1331 if (This
->current_zbuffer
== NULL
) {
1332 /* Search for an attached ZBuffer */
1333 static const DDSCAPS2 zbuf_caps
= { DDSCAPS_ZBUFFER
, 0, 0, 0 };
1334 LPDIRECTDRAWSURFACE7 zbuf
;
1337 hr
= IDirectDrawSurface7_GetAttachedSurface(ICOM_INTERFACE(This
->surface
, IDirectDrawSurface7
),
1338 (DDSCAPS2
*) &zbuf_caps
, &zbuf
);
1340 This
->current_zbuffer
= ICOM_OBJECT(IDirectDrawSurfaceImpl
, IDirectDrawSurface7
, zbuf
);
1341 IDirectDrawSurface7_Release(zbuf
);
1344 if (This
->current_zbuffer
!= NULL
) {
1345 if (This
->current_zbuffer
->get_dirty_status(This
->current_zbuffer
, NULL
)) {
1346 flush_zbuffer_to_GL(This
, NULL
, This
->current_zbuffer
);
1350 if ( ((d3dvtVertexType
& D3DFVF_POSITION_MASK
) != D3DFVF_XYZ
) ||
1351 ((d3dvtVertexType
& D3DFVF_NORMAL
) == 0) )
1352 vertex_lighted
= TRUE
;
1354 /* Compute the number of active texture stages and set the various texture parameters */
1355 num_active_stages
= draw_primitive_handle_textures(This
);
1357 /* And restore to handle '0' in the case we use glTexCoord calls */
1358 if (glThis
->current_active_tex_unit
!= GL_TEXTURE0_WINE
) {
1359 GL_extensions
.glActiveTexture(GL_TEXTURE0_WINE
);
1360 glThis
->current_active_tex_unit
= GL_TEXTURE0_WINE
;
1363 draw_primitive_handle_GL_state(This
,
1364 (d3dvtVertexType
& D3DFVF_POSITION_MASK
) != D3DFVF_XYZ
,
1367 /* First, see if we can use the OpenGL vertex arrays... This is very limited
1368 for now to some 'special' cases where we can do a direct mapping between D3D
1371 Note: in the future all calls will go through vertex arrays but the arrays
1372 will be generated by this function.
1374 Note2: colours cannot be mapped directly because they are stored as BGRA in memory
1375 (ie not as an array of R, G, B, A as OpenGL does it but as a LWORD 0xAARRGGBB
1376 which, as we are little indian, gives a B, G, R, A storage in memory.
1378 if (((d3dvtVertexType
& D3DFVF_POSITION_MASK
) == D3DFVF_XYZ
) && /* Standard XYZ vertices */
1379 ((d3dvtVertexType
& (D3DFVF_DIFFUSE
|D3DFVF_SPECULAR
)) == 0)) {
1381 TRACE(" using GL vertex arrays for performance !\n");
1382 /* First, the vertices (we are sure we have some :-) */
1383 glEnableClientState(GL_VERTEX_ARRAY
);
1384 glVertexPointer(3, GL_FLOAT
, lpD3DDrawPrimStrideData
->position
.dwStride
, lpD3DDrawPrimStrideData
->position
.lpvData
);
1385 /* Then the normals */
1386 if (d3dvtVertexType
& D3DFVF_NORMAL
) {
1387 glEnableClientState(GL_NORMAL_ARRAY
);
1388 glNormalPointer(GL_FLOAT
, lpD3DDrawPrimStrideData
->normal
.dwStride
, lpD3DDrawPrimStrideData
->normal
.lpvData
);
1390 /* Then the diffuse colour */
1391 if (d3dvtVertexType
& D3DFVF_DIFFUSE
) {
1392 glEnableClientState(GL_COLOR_ARRAY
);
1393 glColorPointer(3, GL_UNSIGNED_BYTE
, lpD3DDrawPrimStrideData
->normal
.dwStride
,
1394 ((char *) lpD3DDrawPrimStrideData
->diffuse
.lpvData
));
1396 /* Then the various textures */
1397 for (tex_stage
= 0; tex_stage
< num_active_stages
; tex_stage
++) {
1398 int tex_index
= This
->state_block
.texture_stage_state
[tex_stage
][D3DTSS_TEXCOORDINDEX
- 1] & 0x0000FFFF;
1399 if (tex_index
>= num_tex_index
) {
1400 WARN("Default texture coordinate not handled in the vertex array path !!!\n");
1401 tex_index
= num_tex_index
- 1;
1403 if (GL_extensions
.glClientActiveTexture
) {
1404 GL_extensions
.glClientActiveTexture(GL_TEXTURE0_WINE
+ tex_stage
);
1406 glEnableClientState(GL_TEXTURE_COORD_ARRAY
);
1407 glTexCoordPointer(2, GL_FLOAT
, lpD3DDrawPrimStrideData
->textureCoords
[tex_index
].dwStride
,
1408 lpD3DDrawPrimStrideData
->textureCoords
[tex_index
].lpvData
);
1410 if (dwIndices
!= NULL
) {
1411 glDrawElements(convert_D3D_ptype_to_GL(d3dptPrimitiveType
), dwIndexCount
, GL_UNSIGNED_SHORT
, dwIndices
);
1413 glDrawArrays(convert_D3D_ptype_to_GL(d3dptPrimitiveType
), 0, dwIndexCount
);
1415 glDisableClientState(GL_VERTEX_ARRAY
);
1416 if (d3dvtVertexType
& D3DFVF_NORMAL
) {
1417 glDisableClientState(GL_NORMAL_ARRAY
);
1419 if (d3dvtVertexType
& D3DFVF_DIFFUSE
) {
1420 glDisableClientState(GL_COLOR_ARRAY
);
1422 for (tex_stage
= 0; tex_stage
< num_active_stages
; tex_stage
++) {
1423 if (GL_extensions
.glClientActiveTexture
) {
1424 GL_extensions
.glClientActiveTexture(GL_TEXTURE0_WINE
+ tex_stage
);
1426 glDisableClientState(GL_TEXTURE_COORD_ARRAY
);
1429 glBegin(convert_D3D_ptype_to_GL(d3dptPrimitiveType
));
1431 /* Some fast paths first before the generic case.... */
1432 if ((d3dvtVertexType
== D3DFVF_VERTEX
) && (num_active_stages
<= 1)) {
1435 for (index
= 0; index
< dwIndexCount
; index
++) {
1436 int i
= (dwIndices
== NULL
) ? index
: dwIndices
[index
];
1438 (D3DVALUE
*) (((char *) lpD3DDrawPrimStrideData
->normal
.lpvData
) + i
* lpD3DDrawPrimStrideData
->normal
.dwStride
);
1439 D3DVALUE
*tex_coord
=
1440 (D3DVALUE
*) (((char *) lpD3DDrawPrimStrideData
->textureCoords
[0].lpvData
) + i
* lpD3DDrawPrimStrideData
->textureCoords
[0].dwStride
);
1441 D3DVALUE
*position
=
1442 (D3DVALUE
*) (((char *) lpD3DDrawPrimStrideData
->position
.lpvData
) + i
* lpD3DDrawPrimStrideData
->position
.dwStride
);
1444 handle_normal(normal
);
1445 handle_texture(tex_coord
);
1446 handle_xyz(position
);
1448 TRACE_(ddraw_geom
)(" %f %f %f / %f %f %f (%f %f)\n",
1449 position
[0], position
[1], position
[2],
1450 normal
[0], normal
[1], normal
[2],
1451 tex_coord
[0], tex_coord
[1]);
1453 } else if ((d3dvtVertexType
== D3DFVF_TLVERTEX
) && (num_active_stages
<= 1)) {
1456 for (index
= 0; index
< dwIndexCount
; index
++) {
1457 int i
= (dwIndices
== NULL
) ? index
: dwIndices
[index
];
1459 (DWORD
*) (((char *) lpD3DDrawPrimStrideData
->diffuse
.lpvData
) + i
* lpD3DDrawPrimStrideData
->diffuse
.dwStride
);
1461 (DWORD
*) (((char *) lpD3DDrawPrimStrideData
->specular
.lpvData
) + i
* lpD3DDrawPrimStrideData
->specular
.dwStride
);
1462 D3DVALUE
*tex_coord
=
1463 (D3DVALUE
*) (((char *) lpD3DDrawPrimStrideData
->textureCoords
[0].lpvData
) + i
* lpD3DDrawPrimStrideData
->textureCoords
[0].dwStride
);
1464 D3DVALUE
*position
=
1465 (D3DVALUE
*) (((char *) lpD3DDrawPrimStrideData
->position
.lpvData
) + i
* lpD3DDrawPrimStrideData
->position
.dwStride
);
1467 handle_diffuse_and_specular(&(This
->state_block
), glThis
->fog_table
, color_d
, color_s
, TRUE
);
1468 handle_texture(tex_coord
);
1469 handle_xyzrhw(position
);
1471 TRACE_(ddraw_geom
)(" %f %f %f %f / %02lx %02lx %02lx %02lx - %02lx %02lx %02lx %02lx (%f %f)\n",
1472 position
[0], position
[1], position
[2], position
[3],
1473 (*color_d
>> 16) & 0xFF,
1474 (*color_d
>> 8) & 0xFF,
1475 (*color_d
>> 0) & 0xFF,
1476 (*color_d
>> 24) & 0xFF,
1477 (*color_s
>> 16) & 0xFF,
1478 (*color_s
>> 8) & 0xFF,
1479 (*color_s
>> 0) & 0xFF,
1480 (*color_s
>> 24) & 0xFF,
1481 tex_coord
[0], tex_coord
[1]);
1483 } else if (((d3dvtVertexType
& D3DFVF_POSITION_MASK
) == D3DFVF_XYZ
) ||
1484 ((d3dvtVertexType
& D3DFVF_POSITION_MASK
) == D3DFVF_XYZRHW
)) {
1485 /* This is the 'slow path' but that should support all possible vertex formats out there...
1486 Note that people should write a fast path for all vertex formats out there...
1489 static const D3DVALUE no_index
[] = { 0.0, 0.0, 0.0, 0.0 };
1491 for (index
= 0; index
< dwIndexCount
; index
++) {
1492 int i
= (dwIndices
== NULL
) ? index
: dwIndices
[index
];
1495 if (d3dvtVertexType
& D3DFVF_NORMAL
) {
1497 (D3DVALUE
*) (((char *) lpD3DDrawPrimStrideData
->normal
.lpvData
) + i
* lpD3DDrawPrimStrideData
->normal
.dwStride
);
1498 handle_normal(normal
);
1500 if ((d3dvtVertexType
& (D3DFVF_DIFFUSE
|D3DFVF_SPECULAR
)) == (D3DFVF_DIFFUSE
|D3DFVF_SPECULAR
)) {
1502 (DWORD
*) (((char *) lpD3DDrawPrimStrideData
->diffuse
.lpvData
) + i
* lpD3DDrawPrimStrideData
->diffuse
.dwStride
);
1504 (DWORD
*) (((char *) lpD3DDrawPrimStrideData
->specular
.lpvData
) + i
* lpD3DDrawPrimStrideData
->specular
.dwStride
);
1505 handle_diffuse_and_specular(&(This
->state_block
), glThis
->fog_table
, color_d
, color_s
, vertex_lighted
);
1507 if (d3dvtVertexType
& D3DFVF_SPECULAR
) {
1509 (DWORD
*) (((char *) lpD3DDrawPrimStrideData
->specular
.lpvData
) + i
* lpD3DDrawPrimStrideData
->specular
.dwStride
);
1510 handle_specular(&(This
->state_block
), color_s
, vertex_lighted
);
1511 } else if (d3dvtVertexType
& D3DFVF_DIFFUSE
) {
1513 (DWORD
*) (((char *) lpD3DDrawPrimStrideData
->diffuse
.lpvData
) + i
* lpD3DDrawPrimStrideData
->diffuse
.dwStride
);
1514 handle_diffuse(&(This
->state_block
), color_d
, vertex_lighted
);
1518 for (tex_stage
= 0; tex_stage
< num_active_stages
; tex_stage
++) {
1519 int tex_index
= This
->state_block
.texture_stage_state
[tex_stage
][D3DTSS_TEXCOORDINDEX
- 1] & 0x0000FFFF;
1520 if (tex_index
>= num_tex_index
) {
1521 handle_textures((const D3DVALUE
*) no_index
, tex_stage
);
1523 D3DVALUE
*tex_coord
=
1524 (D3DVALUE
*) (((char *) lpD3DDrawPrimStrideData
->textureCoords
[tex_index
].lpvData
) +
1525 i
* lpD3DDrawPrimStrideData
->textureCoords
[tex_index
].dwStride
);
1526 handle_textures(tex_coord
, tex_stage
);
1530 if ((d3dvtVertexType
& D3DFVF_POSITION_MASK
) == D3DFVF_XYZ
) {
1531 D3DVALUE
*position
=
1532 (D3DVALUE
*) (((char *) lpD3DDrawPrimStrideData
->position
.lpvData
) + i
* lpD3DDrawPrimStrideData
->position
.dwStride
);
1533 handle_xyz(position
);
1534 } else if ((d3dvtVertexType
& D3DFVF_POSITION_MASK
) == D3DFVF_XYZRHW
) {
1535 D3DVALUE
*position
=
1536 (D3DVALUE
*) (((char *) lpD3DDrawPrimStrideData
->position
.lpvData
) + i
* lpD3DDrawPrimStrideData
->position
.dwStride
);
1537 handle_xyzrhw(position
);
1540 if (TRACE_ON(ddraw_geom
)) {
1541 unsigned int tex_index
;
1543 if ((d3dvtVertexType
& D3DFVF_POSITION_MASK
) == D3DFVF_XYZ
) {
1544 D3DVALUE
*position
=
1545 (D3DVALUE
*) (((char *) lpD3DDrawPrimStrideData
->position
.lpvData
) + i
* lpD3DDrawPrimStrideData
->position
.dwStride
);
1546 TRACE_(ddraw_geom
)(" %f %f %f", position
[0], position
[1], position
[2]);
1547 } else if ((d3dvtVertexType
& D3DFVF_POSITION_MASK
) == D3DFVF_XYZRHW
) {
1548 D3DVALUE
*position
=
1549 (D3DVALUE
*) (((char *) lpD3DDrawPrimStrideData
->position
.lpvData
) + i
* lpD3DDrawPrimStrideData
->position
.dwStride
);
1550 TRACE_(ddraw_geom
)(" %f %f %f %f", position
[0], position
[1], position
[2], position
[3]);
1552 if (d3dvtVertexType
& D3DFVF_NORMAL
) {
1554 (D3DVALUE
*) (((char *) lpD3DDrawPrimStrideData
->normal
.lpvData
) + i
* lpD3DDrawPrimStrideData
->normal
.dwStride
);
1555 TRACE_(ddraw_geom
)(" / %f %f %f", normal
[0], normal
[1], normal
[2]);
1557 if (d3dvtVertexType
& D3DFVF_DIFFUSE
) {
1559 (DWORD
*) (((char *) lpD3DDrawPrimStrideData
->diffuse
.lpvData
) + i
* lpD3DDrawPrimStrideData
->diffuse
.dwStride
);
1560 TRACE_(ddraw_geom
)(" / %02lx %02lx %02lx %02lx",
1561 (*color_d
>> 16) & 0xFF,
1562 (*color_d
>> 8) & 0xFF,
1563 (*color_d
>> 0) & 0xFF,
1564 (*color_d
>> 24) & 0xFF);
1566 if (d3dvtVertexType
& D3DFVF_SPECULAR
) {
1568 (DWORD
*) (((char *) lpD3DDrawPrimStrideData
->specular
.lpvData
) + i
* lpD3DDrawPrimStrideData
->specular
.dwStride
);
1569 TRACE_(ddraw_geom
)(" / %02lx %02lx %02lx %02lx",
1570 (*color_s
>> 16) & 0xFF,
1571 (*color_s
>> 8) & 0xFF,
1572 (*color_s
>> 0) & 0xFF,
1573 (*color_s
>> 24) & 0xFF);
1575 for (tex_index
= 0; tex_index
< ((d3dvtVertexType
& D3DFVF_TEXCOUNT_MASK
) >> D3DFVF_TEXCOUNT_SHIFT
); tex_index
++) {
1576 D3DVALUE
*tex_coord
=
1577 (D3DVALUE
*) (((char *) lpD3DDrawPrimStrideData
->textureCoords
[tex_index
].lpvData
) +
1578 i
* lpD3DDrawPrimStrideData
->textureCoords
[tex_index
].dwStride
);
1579 TRACE_(ddraw_geom
)(" / %f %f", tex_coord
[0], tex_coord
[1]);
1581 TRACE_(ddraw_geom
)("\n");
1585 ERR(" matrix weighting not handled yet....\n");
1591 /* Whatever the case, disable the color material stuff */
1592 glDisable(GL_COLOR_MATERIAL
);
1597 LeaveCriticalSection(&(This
->crit
));
1601 GL_IDirect3DDeviceImpl_7_3T_DrawPrimitive(LPDIRECT3DDEVICE7 iface
,
1602 D3DPRIMITIVETYPE d3dptPrimitiveType
,
1603 DWORD d3dvtVertexType
,
1605 DWORD dwVertexCount
,
1608 ICOM_THIS_FROM(IDirect3DDeviceImpl
, IDirect3DDevice7
, iface
);
1609 D3DDRAWPRIMITIVESTRIDEDDATA strided
;
1611 TRACE("(%p/%p)->(%08x,%08lx,%p,%08lx,%08lx)\n", This
, iface
, d3dptPrimitiveType
, d3dvtVertexType
, lpvVertices
, dwVertexCount
, dwFlags
);
1612 if (TRACE_ON(ddraw
)) {
1613 TRACE(" - flags : "); dump_DPFLAGS(dwFlags
);
1616 convert_FVF_to_strided_data(d3dvtVertexType
, lpvVertices
, &strided
, 0);
1617 draw_primitive_strided(This
, d3dptPrimitiveType
, d3dvtVertexType
, &strided
, dwVertexCount
, NULL
, dwVertexCount
, dwFlags
);
1623 GL_IDirect3DDeviceImpl_7_3T_DrawIndexedPrimitive(LPDIRECT3DDEVICE7 iface
,
1624 D3DPRIMITIVETYPE d3dptPrimitiveType
,
1625 DWORD d3dvtVertexType
,
1627 DWORD dwVertexCount
,
1632 ICOM_THIS_FROM(IDirect3DDeviceImpl
, IDirect3DDevice7
, iface
);
1633 D3DDRAWPRIMITIVESTRIDEDDATA strided
;
1635 TRACE("(%p/%p)->(%08x,%08lx,%p,%08lx,%p,%08lx,%08lx)\n", This
, iface
, d3dptPrimitiveType
, d3dvtVertexType
, lpvVertices
, dwVertexCount
, dwIndices
, dwIndexCount
, dwFlags
);
1636 if (TRACE_ON(ddraw
)) {
1637 TRACE(" - flags : "); dump_DPFLAGS(dwFlags
);
1640 convert_FVF_to_strided_data(d3dvtVertexType
, lpvVertices
, &strided
, 0);
1641 draw_primitive_strided(This
, d3dptPrimitiveType
, d3dvtVertexType
, &strided
, dwVertexCount
, dwIndices
, dwIndexCount
, dwFlags
);
1647 GL_IDirect3DDeviceImpl_7_3T_DrawPrimitiveStrided(LPDIRECT3DDEVICE7 iface
,
1648 D3DPRIMITIVETYPE d3dptPrimitiveType
,
1650 LPD3DDRAWPRIMITIVESTRIDEDDATA lpD3DDrawPrimStrideData
,
1651 DWORD dwVertexCount
,
1654 ICOM_THIS_FROM(IDirect3DDeviceImpl
, IDirect3DDevice7
, iface
);
1656 TRACE("(%p/%p)->(%08x,%08lx,%p,%08lx,%08lx)\n", This
, iface
, d3dptPrimitiveType
, dwVertexType
, lpD3DDrawPrimStrideData
, dwVertexCount
, dwFlags
);
1657 if (TRACE_ON(ddraw
)) {
1658 TRACE(" - flags : "); dump_DPFLAGS(dwFlags
);
1660 draw_primitive_strided(This
, d3dptPrimitiveType
, dwVertexType
, lpD3DDrawPrimStrideData
, dwVertexCount
, NULL
, dwVertexCount
, dwFlags
);
1666 GL_IDirect3DDeviceImpl_7_3T_DrawIndexedPrimitiveStrided(LPDIRECT3DDEVICE7 iface
,
1667 D3DPRIMITIVETYPE d3dptPrimitiveType
,
1669 LPD3DDRAWPRIMITIVESTRIDEDDATA lpD3DDrawPrimStrideData
,
1670 DWORD dwVertexCount
,
1675 ICOM_THIS_FROM(IDirect3DDeviceImpl
, IDirect3DDevice7
, iface
);
1677 TRACE("(%p/%p)->(%08x,%08lx,%p,%08lx,%p,%08lx,%08lx)\n", This
, iface
, d3dptPrimitiveType
, dwVertexType
, lpD3DDrawPrimStrideData
, dwVertexCount
, lpIndex
, dwIndexCount
, dwFlags
);
1678 if (TRACE_ON(ddraw
)) {
1679 TRACE(" - flags : "); dump_DPFLAGS(dwFlags
);
1682 draw_primitive_strided(This
, d3dptPrimitiveType
, dwVertexType
, lpD3DDrawPrimStrideData
, dwVertexCount
, lpIndex
, dwIndexCount
, dwFlags
);
1688 GL_IDirect3DDeviceImpl_7_3T_DrawPrimitiveVB(LPDIRECT3DDEVICE7 iface
,
1689 D3DPRIMITIVETYPE d3dptPrimitiveType
,
1690 LPDIRECT3DVERTEXBUFFER7 lpD3DVertexBuf
,
1691 DWORD dwStartVertex
,
1692 DWORD dwNumVertices
,
1695 ICOM_THIS_FROM(IDirect3DDeviceImpl
, IDirect3DDevice7
, iface
);
1696 IDirect3DVertexBufferImpl
*vb_impl
= ICOM_OBJECT(IDirect3DVertexBufferImpl
, IDirect3DVertexBuffer7
, lpD3DVertexBuf
);
1697 D3DDRAWPRIMITIVESTRIDEDDATA strided
;
1699 TRACE("(%p/%p)->(%08x,%p,%08lx,%08lx,%08lx)\n", This
, iface
, d3dptPrimitiveType
, lpD3DVertexBuf
, dwStartVertex
, dwNumVertices
, dwFlags
);
1700 if (TRACE_ON(ddraw
)) {
1701 TRACE(" - flags : "); dump_DPFLAGS(dwFlags
);
1704 if (vb_impl
->processed
) {
1705 IDirect3DVertexBufferGLImpl
*vb_glimp
= (IDirect3DVertexBufferGLImpl
*) vb_impl
;
1706 IDirect3DDeviceGLImpl
*glThis
= (IDirect3DDeviceGLImpl
*) This
;
1708 glThis
->transform_state
= GL_TRANSFORM_VERTEXBUFFER
;
1709 This
->set_matrices(This
, VIEWMAT_CHANGED
|WORLDMAT_CHANGED
|PROJMAT_CHANGED
,
1710 &(vb_glimp
->world_mat
), &(vb_glimp
->view_mat
), &(vb_glimp
->proj_mat
));
1712 convert_FVF_to_strided_data(vb_glimp
->dwVertexTypeDesc
, vb_glimp
->vertices
, &strided
, dwStartVertex
);
1713 draw_primitive_strided(This
, d3dptPrimitiveType
, vb_glimp
->dwVertexTypeDesc
, &strided
, dwNumVertices
, NULL
, dwNumVertices
, dwFlags
);
1716 convert_FVF_to_strided_data(vb_impl
->desc
.dwFVF
, vb_impl
->vertices
, &strided
, dwStartVertex
);
1717 draw_primitive_strided(This
, d3dptPrimitiveType
, vb_impl
->desc
.dwFVF
, &strided
, dwNumVertices
, NULL
, dwNumVertices
, dwFlags
);
1724 GL_IDirect3DDeviceImpl_7_3T_DrawIndexedPrimitiveVB(LPDIRECT3DDEVICE7 iface
,
1725 D3DPRIMITIVETYPE d3dptPrimitiveType
,
1726 LPDIRECT3DVERTEXBUFFER7 lpD3DVertexBuf
,
1727 DWORD dwStartVertex
,
1728 DWORD dwNumVertices
,
1733 ICOM_THIS_FROM(IDirect3DDeviceImpl
, IDirect3DDevice7
, iface
);
1734 IDirect3DVertexBufferImpl
*vb_impl
= ICOM_OBJECT(IDirect3DVertexBufferImpl
, IDirect3DVertexBuffer7
, lpD3DVertexBuf
);
1735 D3DDRAWPRIMITIVESTRIDEDDATA strided
;
1737 TRACE("(%p/%p)->(%08x,%p,%08lx,%08lx,%p,%08lx,%08lx)\n", This
, iface
, d3dptPrimitiveType
, lpD3DVertexBuf
, dwStartVertex
, dwNumVertices
, lpwIndices
, dwIndexCount
, dwFlags
);
1738 if (TRACE_ON(ddraw
)) {
1739 TRACE(" - flags : "); dump_DPFLAGS(dwFlags
);
1742 if (vb_impl
->processed
) {
1743 IDirect3DVertexBufferGLImpl
*vb_glimp
= (IDirect3DVertexBufferGLImpl
*) vb_impl
;
1744 IDirect3DDeviceGLImpl
*glThis
= (IDirect3DDeviceGLImpl
*) This
;
1746 glThis
->transform_state
= GL_TRANSFORM_VERTEXBUFFER
;
1747 This
->set_matrices(This
, VIEWMAT_CHANGED
|WORLDMAT_CHANGED
|PROJMAT_CHANGED
,
1748 &(vb_glimp
->world_mat
), &(vb_glimp
->view_mat
), &(vb_glimp
->proj_mat
));
1750 convert_FVF_to_strided_data(vb_glimp
->dwVertexTypeDesc
, vb_glimp
->vertices
, &strided
, dwStartVertex
);
1751 draw_primitive_strided(This
, d3dptPrimitiveType
, vb_glimp
->dwVertexTypeDesc
, &strided
, dwNumVertices
, lpwIndices
, dwIndexCount
, dwFlags
);
1754 convert_FVF_to_strided_data(vb_impl
->desc
.dwFVF
, vb_impl
->vertices
, &strided
, dwStartVertex
);
1755 draw_primitive_strided(This
, d3dptPrimitiveType
, vb_impl
->desc
.dwFVF
, &strided
, dwNumVertices
, lpwIndices
, dwIndexCount
, dwFlags
);
1761 /* We need a static function for that to handle the 'special' case of 'SELECT_ARG2' */
1763 handle_color_alpha_args(IDirect3DDeviceImpl
*This
, DWORD dwStage
, D3DTEXTURESTAGESTATETYPE d3dTexStageStateType
, DWORD dwState
, D3DTEXTUREOP tex_op
)
1765 BOOLEAN is_complement
= FALSE
;
1766 BOOLEAN is_alpha_replicate
= FALSE
;
1767 BOOLEAN handled
= TRUE
;
1769 BOOLEAN is_color
= ((d3dTexStageStateType
== D3DTSS_COLORARG1
) || (d3dTexStageStateType
== D3DTSS_COLORARG2
));
1773 if (d3dTexStageStateType
== D3DTSS_COLORARG1
) num
= 0;
1774 else if (d3dTexStageStateType
== D3DTSS_COLORARG2
) num
= 1;
1779 if (tex_op
== D3DTOP_SELECTARG2
) {
1783 if (d3dTexStageStateType
== D3DTSS_ALPHAARG1
) num
= 0;
1784 else if (d3dTexStageStateType
== D3DTSS_ALPHAARG2
) num
= 1;
1789 if (tex_op
== D3DTOP_SELECTARG2
) {
1794 if (dwState
& D3DTA_COMPLEMENT
) {
1795 is_complement
= TRUE
;
1797 if (dwState
& D3DTA_ALPHAREPLICATE
) {
1798 is_alpha_replicate
= TRUE
;
1800 dwState
&= D3DTA_SELECTMASK
;
1801 if ((dwStage
== 0) && (dwState
== D3DTA_CURRENT
)) {
1802 dwState
= D3DTA_DIFFUSE
;
1806 case D3DTA_CURRENT
: src
= GL_PREVIOUS_EXT
; break;
1807 case D3DTA_DIFFUSE
: src
= GL_PRIMARY_COLOR_EXT
; break;
1808 case D3DTA_TEXTURE
: src
= GL_TEXTURE
; break;
1809 case D3DTA_TFACTOR
: {
1810 /* Get the constant value from the current rendering state */
1812 DWORD col
= This
->state_block
.render_state
[D3DRENDERSTATE_TEXTUREFACTOR
- 1];
1814 color
[0] = ((col
>> 16) & 0xFF) / 255.0f
;
1815 color
[1] = ((col
>> 8) & 0xFF) / 255.0f
;
1816 color
[2] = ((col
>> 0) & 0xFF) / 255.0f
;
1817 color
[3] = ((col
>> 24) & 0xFF) / 255.0f
;
1818 glTexEnvfv(GL_TEXTURE_ENV
, GL_TEXTURE_ENV_COLOR
, color
);
1820 src
= GL_CONSTANT_EXT
;
1822 default: src
= GL_TEXTURE
; handled
= FALSE
; break;
1826 glTexEnvi(GL_TEXTURE_ENV
, GL_SOURCE0_RGB_EXT
+ num
, src
);
1827 if (is_alpha_replicate
) {
1828 glTexEnvi(GL_TEXTURE_ENV
, GL_OPERAND0_RGB_EXT
+ num
, is_complement
? GL_ONE_MINUS_SRC_ALPHA
: GL_SRC_ALPHA
);
1830 glTexEnvi(GL_TEXTURE_ENV
, GL_OPERAND0_RGB_EXT
+ num
, is_complement
? GL_ONE_MINUS_SRC_COLOR
: GL_SRC_COLOR
);
1833 glTexEnvi(GL_TEXTURE_ENV
, GL_SOURCE0_ALPHA_EXT
+ num
, src
);
1834 glTexEnvi(GL_TEXTURE_ENV
, GL_OPERAND0_ALPHA_EXT
+ num
, is_complement
? GL_ONE_MINUS_SRC_ALPHA
: GL_SRC_ALPHA
);
1841 GL_IDirect3DDeviceImpl_7_3T_SetTextureStageState(LPDIRECT3DDEVICE7 iface
,
1843 D3DTEXTURESTAGESTATETYPE d3dTexStageStateType
,
1846 ICOM_THIS_FROM(IDirect3DDeviceImpl
, IDirect3DDevice7
, iface
);
1847 IDirect3DDeviceGLImpl
*glThis
= (IDirect3DDeviceGLImpl
*) This
;
1852 TRACE("(%p/%p)->(%08lx,%08x,%08lx)\n", This
, iface
, dwStage
, d3dTexStageStateType
, dwState
);
1854 if (((GL_extensions
.max_texture_units
== 0) && (dwStage
> 0)) ||
1855 ((GL_extensions
.max_texture_units
!= 0) && (dwStage
>= GL_extensions
.max_texture_units
))) {
1859 unit
= GL_TEXTURE0_WINE
+ dwStage
;
1860 if (unit
!= glThis
->current_active_tex_unit
) {
1861 GL_extensions
.glActiveTexture(unit
);
1862 glThis
->current_active_tex_unit
= unit
;
1865 switch (d3dTexStageStateType
) {
1866 #define GEN_CASE(a) case a: type = #a; break
1867 GEN_CASE(D3DTSS_COLOROP
);
1868 GEN_CASE(D3DTSS_COLORARG1
);
1869 GEN_CASE(D3DTSS_COLORARG2
);
1870 GEN_CASE(D3DTSS_ALPHAOP
);
1871 GEN_CASE(D3DTSS_ALPHAARG1
);
1872 GEN_CASE(D3DTSS_ALPHAARG2
);
1873 GEN_CASE(D3DTSS_BUMPENVMAT00
);
1874 GEN_CASE(D3DTSS_BUMPENVMAT01
);
1875 GEN_CASE(D3DTSS_BUMPENVMAT10
);
1876 GEN_CASE(D3DTSS_BUMPENVMAT11
);
1877 GEN_CASE(D3DTSS_TEXCOORDINDEX
);
1878 GEN_CASE(D3DTSS_ADDRESS
);
1879 GEN_CASE(D3DTSS_ADDRESSU
);
1880 GEN_CASE(D3DTSS_ADDRESSV
);
1881 GEN_CASE(D3DTSS_BORDERCOLOR
);
1882 GEN_CASE(D3DTSS_MAGFILTER
);
1883 GEN_CASE(D3DTSS_MINFILTER
);
1884 GEN_CASE(D3DTSS_MIPFILTER
);
1885 GEN_CASE(D3DTSS_MIPMAPLODBIAS
);
1886 GEN_CASE(D3DTSS_MAXMIPLEVEL
);
1887 GEN_CASE(D3DTSS_MAXANISOTROPY
);
1888 GEN_CASE(D3DTSS_BUMPENVLSCALE
);
1889 GEN_CASE(D3DTSS_BUMPENVLOFFSET
);
1890 GEN_CASE(D3DTSS_TEXTURETRANSFORMFLAGS
);
1892 default: type
= "UNKNOWN";
1895 /* Store the values in the state array */
1896 prev_state
= This
->state_block
.texture_stage_state
[dwStage
][d3dTexStageStateType
- 1];
1897 This
->state_block
.texture_stage_state
[dwStage
][d3dTexStageStateType
- 1] = dwState
;
1898 /* Some special cases when one state modifies more than one... */
1899 if (d3dTexStageStateType
== D3DTSS_ADDRESS
) {
1900 This
->state_block
.texture_stage_state
[dwStage
][D3DTSS_ADDRESSU
- 1] = dwState
;
1901 This
->state_block
.texture_stage_state
[dwStage
][D3DTSS_ADDRESSV
- 1] = dwState
;
1906 switch (d3dTexStageStateType
) {
1907 case D3DTSS_MINFILTER
:
1908 case D3DTSS_MIPFILTER
:
1909 if (TRACE_ON(ddraw
)) {
1910 if (d3dTexStageStateType
== D3DTSS_MINFILTER
) {
1911 switch ((D3DTEXTUREMINFILTER
) dwState
) {
1912 case D3DTFN_POINT
: TRACE(" Stage type is : D3DTSS_MINFILTER => D3DTFN_POINT\n"); break;
1913 case D3DTFN_LINEAR
: TRACE(" Stage type is : D3DTSS_MINFILTER => D3DTFN_LINEAR\n"); break;
1914 default: FIXME(" Unhandled stage type : D3DTSS_MINFILTER => %08lx\n", dwState
); break;
1917 switch ((D3DTEXTUREMIPFILTER
) dwState
) {
1918 case D3DTFP_NONE
: TRACE(" Stage type is : D3DTSS_MIPFILTER => D3DTFP_NONE\n"); break;
1919 case D3DTFP_POINT
: TRACE(" Stage type is : D3DTSS_MIPFILTER => D3DTFP_POINT\n"); break;
1920 case D3DTFP_LINEAR
: TRACE(" Stage type is : D3DTSS_MIPFILTER => D3DTFP_LINEAR\n"); break;
1921 default: FIXME(" Unhandled stage type : D3DTSS_MIPFILTER => %08lx\n", dwState
); break;
1927 case D3DTSS_MAGFILTER
:
1928 if (TRACE_ON(ddraw
)) {
1929 switch ((D3DTEXTUREMAGFILTER
) dwState
) {
1930 case D3DTFG_POINT
: TRACE(" Stage type is : D3DTSS_MAGFILTER => D3DTFG_POINT\n"); break;
1931 case D3DTFG_LINEAR
: TRACE(" Stage type is : D3DTSS_MAGFILTER => D3DTFG_LINEAR\n"); break;
1932 default: FIXME(" Unhandled stage type : D3DTSS_MAGFILTER => %08lx\n", dwState
); break;
1937 case D3DTSS_ADDRESS
:
1938 case D3DTSS_ADDRESSU
:
1939 case D3DTSS_ADDRESSV
: {
1940 switch ((D3DTEXTUREADDRESS
) dwState
) {
1941 case D3DTADDRESS_WRAP
: TRACE(" Stage type is : %s => D3DTADDRESS_WRAP\n", type
); break;
1942 case D3DTADDRESS_CLAMP
: TRACE(" Stage type is : %s => D3DTADDRESS_CLAMP\n", type
); break;
1943 case D3DTADDRESS_BORDER
: TRACE(" Stage type is : %s => D3DTADDRESS_BORDER\n", type
); break;
1944 case D3DTADDRESS_MIRROR
:
1945 if (GL_extensions
.mirrored_repeat
) {
1946 TRACE(" Stage type is : %s => D3DTADDRESS_MIRROR\n", type
);
1948 FIXME(" Stage type is : %s => D3DTADDRESS_MIRROR - not supported by GL !\n", type
);
1951 default: FIXME(" Unhandled stage type : %s => %08lx\n", type
, dwState
); break;
1955 case D3DTSS_ALPHAOP
:
1956 case D3DTSS_COLOROP
: {
1958 GLenum parm
= (d3dTexStageStateType
== D3DTSS_ALPHAOP
) ? GL_COMBINE_ALPHA_EXT
: GL_COMBINE_RGB_EXT
;
1963 #define GEN_CASE(a) case a: value = #a; break
1964 GEN_CASE(D3DTOP_DISABLE
);
1965 GEN_CASE(D3DTOP_SELECTARG1
);
1966 GEN_CASE(D3DTOP_SELECTARG2
);
1967 GEN_CASE(D3DTOP_MODULATE
);
1968 GEN_CASE(D3DTOP_MODULATE2X
);
1969 GEN_CASE(D3DTOP_MODULATE4X
);
1970 GEN_CASE(D3DTOP_ADD
);
1971 GEN_CASE(D3DTOP_ADDSIGNED
);
1972 GEN_CASE(D3DTOP_ADDSIGNED2X
);
1973 GEN_CASE(D3DTOP_SUBTRACT
);
1974 GEN_CASE(D3DTOP_ADDSMOOTH
);
1975 GEN_CASE(D3DTOP_BLENDDIFFUSEALPHA
);
1976 GEN_CASE(D3DTOP_BLENDTEXTUREALPHA
);
1977 GEN_CASE(D3DTOP_BLENDFACTORALPHA
);
1978 GEN_CASE(D3DTOP_BLENDTEXTUREALPHAPM
);
1979 GEN_CASE(D3DTOP_BLENDCURRENTALPHA
);
1980 GEN_CASE(D3DTOP_PREMODULATE
);
1981 GEN_CASE(D3DTOP_MODULATEALPHA_ADDCOLOR
);
1982 GEN_CASE(D3DTOP_MODULATECOLOR_ADDALPHA
);
1983 GEN_CASE(D3DTOP_MODULATEINVALPHA_ADDCOLOR
);
1984 GEN_CASE(D3DTOP_MODULATEINVCOLOR_ADDALPHA
);
1985 GEN_CASE(D3DTOP_BUMPENVMAP
);
1986 GEN_CASE(D3DTOP_BUMPENVMAPLUMINANCE
);
1987 GEN_CASE(D3DTOP_DOTPRODUCT3
);
1988 GEN_CASE(D3DTOP_FORCE_DWORD
);
1990 default: value
= "UNKNOWN";
1993 if ((d3dTexStageStateType
== D3DTSS_COLOROP
) && (dwState
== D3DTOP_DISABLE
)) {
1994 glDisable(GL_TEXTURE_2D
);
1995 TRACE(" disabling 2D texturing.\n");
1997 /* Re-enable texturing only if COLOROP was not already disabled... */
1998 if ((glThis
->current_bound_texture
[dwStage
] != NULL
) &&
1999 (This
->state_block
.texture_stage_state
[dwStage
][D3DTSS_COLOROP
- 1] != D3DTOP_DISABLE
)) {
2000 glEnable(GL_TEXTURE_2D
);
2001 TRACE(" enabling 2D texturing.\n");
2004 /* Re-Enable GL_TEXTURE_ENV_MODE, GL_COMBINE_EXT */
2005 if ((dwState
!= D3DTOP_DISABLE
) &&
2006 (This
->state_block
.texture_stage_state
[dwStage
][D3DTSS_COLOROP
- 1] != D3DTOP_DISABLE
)) {
2007 if (glThis
->current_tex_env
!= GL_COMBINE_EXT
) {
2008 glTexEnvi(GL_TEXTURE_ENV
, GL_TEXTURE_ENV_MODE
, GL_COMBINE_EXT
);
2009 glThis
->current_tex_env
= GL_COMBINE_EXT
;
2013 /* Now set up the operand correctly */
2015 case D3DTOP_DISABLE
:
2016 /* Contrary to the docs, alpha can be disabled when colorop is enabled
2017 and it works, so ignore this op */
2018 TRACE(" Note : disable ALPHAOP but COLOROP enabled!\n");
2021 case D3DTOP_SELECTARG1
:
2022 case D3DTOP_SELECTARG2
:
2023 glTexEnvi(GL_TEXTURE_ENV
, parm
, GL_REPLACE
);
2026 case D3DTOP_MODULATE4X
:
2027 scale
= scale
* 2; /* Drop through */
2028 case D3DTOP_MODULATE2X
:
2029 scale
= scale
* 2; /* Drop through */
2030 case D3DTOP_MODULATE
:
2031 glTexEnvi(GL_TEXTURE_ENV
, parm
, GL_MODULATE
);
2035 glTexEnvi(GL_TEXTURE_ENV
, parm
, GL_ADD
);
2038 case D3DTOP_ADDSIGNED2X
:
2039 scale
= scale
* 2; /* Drop through */
2040 case D3DTOP_ADDSIGNED
:
2041 glTexEnvi(GL_TEXTURE_ENV
, parm
, GL_ADD_SIGNED_EXT
);
2044 /* For the four blending modes, use the Arg2 parameter */
2045 case D3DTOP_BLENDDIFFUSEALPHA
:
2046 case D3DTOP_BLENDTEXTUREALPHA
:
2047 case D3DTOP_BLENDFACTORALPHA
:
2048 case D3DTOP_BLENDCURRENTALPHA
: {
2049 GLenum src
= GL_PRIMARY_COLOR_EXT
; /* Just to prevent a compiler warning.. */
2052 case D3DTOP_BLENDDIFFUSEALPHA
: src
= GL_PRIMARY_COLOR_EXT
;
2053 case D3DTOP_BLENDTEXTUREALPHA
: src
= GL_TEXTURE
;
2054 case D3DTOP_BLENDFACTORALPHA
: src
= GL_CONSTANT_EXT
;
2055 case D3DTOP_BLENDCURRENTALPHA
: src
= GL_PREVIOUS_EXT
;
2058 glTexEnvi(GL_TEXTURE_ENV
, parm
, GL_INTERPOLATE_EXT
);
2059 glTexEnvi(GL_TEXTURE_ENV
, GL_SOURCE2_RGB_EXT
, src
);
2060 glTexEnvi(GL_TEXTURE_ENV
, GL_OPERAND2_RGB_EXT
, GL_SRC_ALPHA
);
2061 glTexEnvi(GL_TEXTURE_ENV
, GL_SOURCE2_ALPHA_EXT
, src
);
2062 glTexEnvi(GL_TEXTURE_ENV
, GL_OPERAND2_ALPHA_EXT
, GL_SRC_ALPHA
);
2071 if (((prev_state
== D3DTOP_SELECTARG2
) && (dwState
!= D3DTOP_SELECTARG2
)) ||
2072 ((dwState
== D3DTOP_SELECTARG2
) && (prev_state
!= D3DTOP_SELECTARG2
))) {
2073 /* Switch the arguments if needed... */
2074 if (d3dTexStageStateType
== D3DTSS_COLOROP
) {
2075 handle_color_alpha_args(This
, dwStage
, D3DTSS_COLORARG1
,
2076 This
->state_block
.texture_stage_state
[dwStage
][D3DTSS_COLORARG1
- 1],
2078 handle_color_alpha_args(This
, dwStage
, D3DTSS_COLORARG2
,
2079 This
->state_block
.texture_stage_state
[dwStage
][D3DTSS_COLORARG2
- 1],
2082 handle_color_alpha_args(This
, dwStage
, D3DTSS_ALPHAARG1
,
2083 This
->state_block
.texture_stage_state
[dwStage
][D3DTSS_ALPHAARG1
- 1],
2085 handle_color_alpha_args(This
, dwStage
, D3DTSS_ALPHAARG2
,
2086 This
->state_block
.texture_stage_state
[dwStage
][D3DTSS_ALPHAARG2
- 1],
2092 if (d3dTexStageStateType
== D3DTSS_ALPHAOP
) {
2093 glTexEnvi(GL_TEXTURE_ENV
, GL_ALPHA_SCALE
, scale
);
2095 glTexEnvi(GL_TEXTURE_ENV
, GL_RGB_SCALE_EXT
, scale
);
2097 TRACE(" Stage type is : %s => %s\n", type
, value
);
2099 FIXME(" Unhandled stage type is : %s => %s\n", type
, value
);
2103 case D3DTSS_COLORARG1
:
2104 case D3DTSS_COLORARG2
:
2105 case D3DTSS_ALPHAARG1
:
2106 case D3DTSS_ALPHAARG2
: {
2107 const char *value
, *value_comp
= "", *value_alpha
= "";
2109 D3DTEXTUREOP tex_op
;
2111 switch (dwState
& D3DTA_SELECTMASK
) {
2112 #define GEN_CASE(a) case a: value = #a; break
2113 GEN_CASE(D3DTA_DIFFUSE
);
2114 GEN_CASE(D3DTA_CURRENT
);
2115 GEN_CASE(D3DTA_TEXTURE
);
2116 GEN_CASE(D3DTA_TFACTOR
);
2117 GEN_CASE(D3DTA_SPECULAR
);
2119 default: value
= "UNKNOWN";
2121 if (dwState
& D3DTA_COMPLEMENT
) {
2122 value_comp
= " | D3DTA_COMPLEMENT";
2124 if (dwState
& D3DTA_ALPHAREPLICATE
) {
2125 value_alpha
= " | D3DTA_ALPHAREPLICATE";
2128 if ((d3dTexStageStateType
== D3DTSS_COLORARG1
) || (d3dTexStageStateType
== D3DTSS_COLORARG2
)) {
2129 tex_op
= This
->state_block
.texture_stage_state
[dwStage
][D3DTSS_COLOROP
- 1];
2131 tex_op
= This
->state_block
.texture_stage_state
[dwStage
][D3DTSS_ALPHAOP
- 1];
2134 handled
= handle_color_alpha_args(This
, dwStage
, d3dTexStageStateType
, dwState
, tex_op
);
2137 TRACE(" Stage type : %s => %s%s%s\n", type
, value
, value_comp
, value_alpha
);
2139 FIXME(" Unhandled stage type : %s => %s%s%s\n", type
, value
, value_comp
, value_alpha
);
2143 case D3DTSS_MIPMAPLODBIAS
: {
2144 D3DVALUE value
= *((D3DVALUE
*) &dwState
);
2145 BOOLEAN handled
= TRUE
;
2147 if ((value
!= 0.0) && (GL_extensions
.mipmap_lodbias
== FALSE
))
2151 TRACE(" Stage type : D3DTSS_MIPMAPLODBIAS => %f\n", value
);
2152 glTexEnvf(GL_TEXTURE_FILTER_CONTROL_WINE
, GL_TEXTURE_LOD_BIAS_WINE
, value
);
2154 FIXME(" Unhandled stage type : D3DTSS_MIPMAPLODBIAS => %f\n", value
);
2158 case D3DTSS_MAXMIPLEVEL
:
2159 TRACE(" Stage type : D3DTSS_MAXMIPLEVEL => %ld\n", dwState
);
2162 case D3DTSS_BORDERCOLOR
:
2163 TRACE(" Stage type : D3DTSS_BORDERCOLOR => %02lx %02lx %02lx %02lx (RGBA)\n",
2164 ((dwState
>> 16) & 0xFF),
2165 ((dwState
>> 8) & 0xFF),
2166 ((dwState
>> 0) & 0xFF),
2167 ((dwState
>> 24) & 0xFF));
2170 case D3DTSS_TEXCOORDINDEX
: {
2171 BOOLEAN handled
= TRUE
;
2174 switch (dwState
& 0xFFFF0000) {
2175 #define GEN_CASE(a) case a: value = #a; break
2176 GEN_CASE(D3DTSS_TCI_PASSTHRU
);
2177 GEN_CASE(D3DTSS_TCI_CAMERASPACENORMAL
);
2178 GEN_CASE(D3DTSS_TCI_CAMERASPACEPOSITION
);
2179 GEN_CASE(D3DTSS_TCI_CAMERASPACEREFLECTIONVECTOR
);
2181 default: value
= "UNKNOWN";
2183 if ((dwState
& 0xFFFF0000) != D3DTSS_TCI_PASSTHRU
)
2187 TRACE(" Stage type : D3DTSS_TEXCOORDINDEX => %ld | %s\n", dwState
& 0x0000FFFF, value
);
2189 FIXME(" Unhandled stage type : D3DTSS_TEXCOORDINDEX => %ld | %s\n", dwState
& 0x0000FFFF, value
);
2193 case D3DTSS_TEXTURETRANSFORMFLAGS
: {
2194 const char *projected
= "", *value
;
2195 BOOLEAN handled
= TRUE
;
2196 switch (dwState
& 0xFF) {
2197 #define GEN_CASE(a) case a: value = #a; break
2198 GEN_CASE(D3DTTFF_DISABLE
);
2199 GEN_CASE(D3DTTFF_COUNT1
);
2200 GEN_CASE(D3DTTFF_COUNT2
);
2201 GEN_CASE(D3DTTFF_COUNT3
);
2202 GEN_CASE(D3DTTFF_COUNT4
);
2204 default: value
= "UNKNOWN";
2206 if (dwState
& D3DTTFF_PROJECTED
) {
2207 projected
= " | D3DTTFF_PROJECTED";
2211 if ((dwState
& 0xFF) != D3DTTFF_DISABLE
) {
2212 This
->matrices_updated(This
, TEXMAT0_CHANGED
<< dwStage
);
2216 TRACE(" Stage type : D3DTSS_TEXTURETRANSFORMFLAGS => %s%s\n", value
, projected
);
2218 FIXME(" Unhandled stage type : D3DTSS_TEXTURETRANSFORMFLAGS => %s%s\n", value
, projected
);
2223 FIXME(" Unhandled stage type : %s => %08lx\n", type
, dwState
);
2233 draw_primitive_handle_textures(IDirect3DDeviceImpl
*This
)
2235 IDirect3DDeviceGLImpl
*glThis
= (IDirect3DDeviceGLImpl
*) This
;
2237 BOOLEAN enable_colorkey
= FALSE
;
2239 for (stage
= 0; stage
< MAX_TEXTURES
; stage
++) {
2240 IDirectDrawSurfaceImpl
*surf_ptr
= This
->current_texture
[stage
];
2243 /* If this stage is disabled, no need to go further... */
2244 if (This
->state_block
.texture_stage_state
[stage
][D3DTSS_COLOROP
- 1] == D3DTOP_DISABLE
)
2247 /* First check if we need to bind any other texture for this stage */
2248 if (This
->current_texture
[stage
] != glThis
->current_bound_texture
[stage
]) {
2249 if (This
->current_texture
[stage
] == NULL
) {
2250 TRACE(" disabling 2D texturing for stage %ld.\n", stage
);
2252 unit
= GL_TEXTURE0_WINE
+ stage
;
2253 if (unit
!= glThis
->current_active_tex_unit
) {
2254 GL_extensions
.glActiveTexture(unit
);
2255 glThis
->current_active_tex_unit
= unit
;
2257 glBindTexture(GL_TEXTURE_2D
, 0);
2258 glDisable(GL_TEXTURE_2D
);
2260 GLenum tex_name
= gltex_get_tex_name(surf_ptr
);
2262 unit
= GL_TEXTURE0_WINE
+ stage
;
2263 if (unit
!= glThis
->current_active_tex_unit
) {
2264 GL_extensions
.glActiveTexture(unit
);
2265 glThis
->current_active_tex_unit
= unit
;
2268 if (glThis
->current_bound_texture
[stage
] == NULL
) {
2269 if (This
->state_block
.texture_stage_state
[stage
][D3DTSS_COLOROP
- 1] != D3DTOP_DISABLE
) {
2270 TRACE(" enabling 2D texturing and");
2271 glEnable(GL_TEXTURE_2D
);
2274 TRACE(" activating OpenGL texture id %d for stage %ld.\n", tex_name
, stage
);
2275 glBindTexture(GL_TEXTURE_2D
, tex_name
);
2278 glThis
->current_bound_texture
[stage
] = This
->current_texture
[stage
];
2280 if (glThis
->current_bound_texture
[stage
] == NULL
) {
2281 TRACE(" displaying without texturing activated for stage %ld.\n", stage
);
2283 TRACE(" using already bound texture id %d for stage %ld.\n",
2284 ((IDirect3DTextureGLImpl
*) (glThis
->current_bound_texture
[stage
])->tex_private
)->tex_name
, stage
);
2288 /* If no texure valid for this stage, go out of the loop */
2289 if (This
->current_texture
[stage
] == NULL
) break;
2291 /* Then check if we need to flush this texture to GL or not (ie did it change) ?.
2292 This will also update the various texture parameters if needed.
2294 gltex_upload_texture(surf_ptr
, This
, stage
);
2296 /* And finally check for color-keying (only on first stage) */
2297 if (This
->current_texture
[stage
]->surface_desc
.dwFlags
& DDSD_CKSRCBLT
) {
2299 enable_colorkey
= TRUE
;
2301 static BOOL warn
= FALSE
;
2302 if (warn
== FALSE
) {
2304 WARN(" Surface has color keying on stage different from 0 (%ld) !", stage
);
2309 enable_colorkey
= FALSE
;
2314 /* Apparently, whatever the state of BLEND, color keying is always activated for 'old' D3D versions */
2315 if (((This
->state_block
.render_state
[D3DRENDERSTATE_COLORKEYENABLE
- 1]) ||
2316 (glThis
->parent
.version
== 1)) &&
2317 (enable_colorkey
)) {
2318 TRACE(" colorkey activated.\n");
2320 if (glThis
->alpha_test
== FALSE
) {
2321 glEnable(GL_ALPHA_TEST
);
2322 glThis
->alpha_test
= TRUE
;
2324 if ((glThis
->current_alpha_test_func
!= GL_NOTEQUAL
) || (glThis
->current_alpha_test_ref
!= 0.0)) {
2325 if (This
->state_block
.render_state
[D3DRENDERSTATE_ALPHATESTENABLE
- 1]) {
2326 static BOOL warn
= FALSE
;
2327 if (warn
== FALSE
) {
2329 WARN(" Overriding application-given alpha test values - some graphical glitches may appear !\n");
2332 glThis
->current_alpha_test_func
= GL_NOTEQUAL
;
2333 glThis
->current_alpha_test_ref
= 0.0;
2334 glAlphaFunc(GL_NOTEQUAL
, 0.0);
2336 /* Some sanity checks should be added here if a game mixes alphatest + color keying...
2337 Only one has been found for now, and the ALPHAFUNC is 'Always' so it works :-) */
2339 if (This
->state_block
.render_state
[D3DRENDERSTATE_ALPHATESTENABLE
- 1] == FALSE
) {
2340 glDisable(GL_ALPHA_TEST
);
2341 glThis
->alpha_test
= FALSE
;
2343 /* Maybe we should restore here the application-given alpha test states ? */
2350 GL_IDirect3DDeviceImpl_7_3T_SetTexture(LPDIRECT3DDEVICE7 iface
,
2352 LPDIRECTDRAWSURFACE7 lpTexture2
)
2354 ICOM_THIS_FROM(IDirect3DDeviceImpl
, IDirect3DDevice7
, iface
);
2356 TRACE("(%p/%p)->(%08lx,%p)\n", This
, iface
, dwStage
, lpTexture2
);
2358 if (((GL_extensions
.max_texture_units
== 0) && (dwStage
> 0)) ||
2359 ((GL_extensions
.max_texture_units
!= 0) && (dwStage
>= GL_extensions
.max_texture_units
))) {
2360 if (lpTexture2
!= NULL
) {
2361 WARN(" setting a texture to a non-supported texture stage !\n");
2366 if (This
->current_texture
[dwStage
] != NULL
) {
2367 IDirectDrawSurface7_Release(ICOM_INTERFACE(This
->current_texture
[dwStage
], IDirectDrawSurface7
));
2370 if (lpTexture2
== NULL
) {
2371 This
->current_texture
[dwStage
] = NULL
;
2373 IDirectDrawSurfaceImpl
*tex_impl
= ICOM_OBJECT(IDirectDrawSurfaceImpl
, IDirectDrawSurface7
, lpTexture2
);
2374 IDirectDrawSurface7_AddRef(ICOM_INTERFACE(tex_impl
, IDirectDrawSurface7
));
2375 This
->current_texture
[dwStage
] = tex_impl
;
2382 GL_IDirect3DDeviceImpl_7_GetCaps(LPDIRECT3DDEVICE7 iface
,
2383 LPD3DDEVICEDESC7 lpD3DHELDevDesc
)
2385 ICOM_THIS_FROM(IDirect3DDeviceImpl
, IDirect3DDevice7
, iface
);
2386 TRACE("(%p/%p)->(%p)\n", This
, iface
, lpD3DHELDevDesc
);
2388 fill_opengl_caps_7(lpD3DHELDevDesc
);
2390 TRACE(" returning caps : no dump function yet.\n");
2396 GL_IDirect3DDeviceImpl_7_SetMaterial(LPDIRECT3DDEVICE7 iface
,
2397 LPD3DMATERIAL7 lpMat
)
2399 ICOM_THIS_FROM(IDirect3DDeviceImpl
, IDirect3DDevice7
, iface
);
2400 TRACE("(%p/%p)->(%p)\n", This
, iface
, lpMat
);
2402 if (TRACE_ON(ddraw
)) {
2403 TRACE(" material is : \n");
2404 dump_D3DMATERIAL7(lpMat
);
2407 This
->current_material
= *lpMat
;
2410 glMaterialfv(GL_FRONT_AND_BACK
,
2412 (float *) &(This
->current_material
.u
.diffuse
));
2413 glMaterialfv(GL_FRONT_AND_BACK
,
2415 (float *) &(This
->current_material
.u1
.ambient
));
2416 glMaterialfv(GL_FRONT_AND_BACK
,
2418 (float *) &(This
->current_material
.u2
.specular
));
2419 glMaterialfv(GL_FRONT_AND_BACK
,
2421 (float *) &(This
->current_material
.u3
.emissive
));
2422 glMaterialf(GL_FRONT_AND_BACK
,
2424 This
->current_material
.u4
.power
); /* Not sure about this... */
2432 GL_IDirect3DDeviceImpl_7_SetLight(LPDIRECT3DDEVICE7 iface
,
2434 LPD3DLIGHT7 lpLight
)
2436 ICOM_THIS_FROM(IDirect3DDeviceImpl
, IDirect3DDevice7
, iface
);
2437 IDirect3DDeviceGLImpl
*glThis
= (IDirect3DDeviceGLImpl
*) This
;
2438 TRACE("(%p/%p)->(%08lx,%p)\n", This
, iface
, dwLightIndex
, lpLight
);
2440 if (TRACE_ON(ddraw
)) {
2441 TRACE(" setting light : \n");
2442 dump_D3DLIGHT7(lpLight
);
2445 if (dwLightIndex
>= MAX_LIGHTS
) return DDERR_INVALIDPARAMS
;
2446 This
->set_lights
|= 0x00000001 << dwLightIndex
;
2447 This
->light_parameters
[dwLightIndex
] = *lpLight
;
2449 /* Some checks to print out nice warnings :-) */
2450 switch (lpLight
->dltType
) {
2451 case D3DLIGHT_DIRECTIONAL
:
2452 case D3DLIGHT_POINT
:
2453 /* These are handled properly... */
2457 if ((lpLight
->dvTheta
!= 0.0) ||
2458 (lpLight
->dvTheta
!= lpLight
->dvPhi
)) {
2459 ERR("dvTheta not fully supported yet !\n");
2464 ERR("Light type not handled yet : %08x !\n", lpLight
->dltType
);
2467 /* This will force the Light setting on next drawing of primitives */
2468 glThis
->transform_state
= GL_TRANSFORM_NONE
;
2474 GL_IDirect3DDeviceImpl_7_LightEnable(LPDIRECT3DDEVICE7 iface
,
2478 ICOM_THIS_FROM(IDirect3DDeviceImpl
, IDirect3DDevice7
, iface
);
2479 TRACE("(%p/%p)->(%08lx,%d)\n", This
, iface
, dwLightIndex
, bEnable
);
2481 if (dwLightIndex
>= MAX_LIGHTS
) return DDERR_INVALIDPARAMS
;
2485 if (((0x00000001 << dwLightIndex
) & This
->set_lights
) == 0) {
2486 /* Set the default parameters.. */
2487 TRACE(" setting default light parameters...\n");
2488 GL_IDirect3DDeviceImpl_7_SetLight(iface
, dwLightIndex
, &(This
->light_parameters
[dwLightIndex
]));
2490 glEnable(GL_LIGHT0
+ dwLightIndex
);
2491 if ((This
->active_lights
& (0x00000001 << dwLightIndex
)) == 0) {
2492 /* This light gets active... Need to update its parameters to GL before the next drawing */
2493 IDirect3DDeviceGLImpl
*glThis
= (IDirect3DDeviceGLImpl
*) This
;
2495 This
->active_lights
|= 0x00000001 << dwLightIndex
;
2496 glThis
->transform_state
= GL_TRANSFORM_NONE
;
2499 glDisable(GL_LIGHT0
+ dwLightIndex
);
2500 This
->active_lights
&= ~(0x00000001 << dwLightIndex
);
2508 GL_IDirect3DDeviceImpl_7_SetClipPlane(LPDIRECT3DDEVICE7 iface
, DWORD dwIndex
, CONST D3DVALUE
* pPlaneEquation
)
2510 IDirect3DDeviceImpl
*This
= (IDirect3DDeviceImpl
*)iface
;
2511 IDirect3DDeviceGLImpl
* glThis
= (IDirect3DDeviceGLImpl
*) This
;
2513 TRACE("(%p)->(%ld,%p)\n", This
, dwIndex
, pPlaneEquation
);
2515 if (dwIndex
>= This
->max_clipping_planes
) {
2516 return DDERR_INVALIDPARAMS
;
2519 TRACE(" clip plane %ld : %f %f %f %f\n", dwIndex
, pPlaneEquation
[0], pPlaneEquation
[1], pPlaneEquation
[2], pPlaneEquation
[3] );
2521 memcpy(This
->clipping_planes
[dwIndex
].plane
, pPlaneEquation
, sizeof(D3DVALUE
[4]));
2523 /* This is to force the reset of the transformation matrices on the next drawing.
2524 * This is needed to use the correct matrices for the various clipping planes.
2526 glThis
->transform_state
= GL_TRANSFORM_NONE
;
2532 GL_IDirect3DDeviceImpl_7_SetViewport(LPDIRECT3DDEVICE7 iface
,
2533 LPD3DVIEWPORT7 lpData
)
2535 ICOM_THIS_FROM(IDirect3DDeviceImpl
, IDirect3DDevice7
, iface
);
2536 TRACE("(%p/%p)->(%p)\n", This
, iface
, lpData
);
2538 if (TRACE_ON(ddraw
)) {
2539 TRACE(" viewport is : \n");
2540 TRACE(" - dwX = %ld dwY = %ld\n",
2541 lpData
->dwX
, lpData
->dwY
);
2542 TRACE(" - dwWidth = %ld dwHeight = %ld\n",
2543 lpData
->dwWidth
, lpData
->dwHeight
);
2544 TRACE(" - dvMinZ = %f dvMaxZ = %f\n",
2545 lpData
->dvMinZ
, lpData
->dvMaxZ
);
2549 /* Set the viewport */
2550 if ((lpData
->dvMinZ
!= This
->active_viewport
.dvMinZ
) ||
2551 (lpData
->dvMaxZ
!= This
->active_viewport
.dvMaxZ
)) {
2552 glDepthRange(lpData
->dvMinZ
, lpData
->dvMaxZ
);
2554 if ((lpData
->dwX
!= This
->active_viewport
.dwX
) ||
2555 (lpData
->dwY
!= This
->active_viewport
.dwY
) ||
2556 (lpData
->dwWidth
!= This
->active_viewport
.dwWidth
) ||
2557 (lpData
->dwHeight
!= This
->active_viewport
.dwHeight
)) {
2558 glViewport(lpData
->dwX
,
2559 This
->surface
->surface_desc
.dwHeight
- (lpData
->dwHeight
+ lpData
->dwY
),
2560 lpData
->dwWidth
, lpData
->dwHeight
);
2565 This
->active_viewport
= *lpData
;
2570 #if !defined(__STRICT_ANSI__) && defined(__GNUC__)
2571 # define XCAST(fun) (typeof(VTABLE_IDirect3DDevice7.fun))
2573 # define XCAST(fun) (void*)
2576 IDirect3DDevice7Vtbl VTABLE_IDirect3DDevice7
=
2578 XCAST(QueryInterface
) Main_IDirect3DDeviceImpl_7_3T_2T_1T_QueryInterface
,
2579 XCAST(AddRef
) Main_IDirect3DDeviceImpl_7_3T_2T_1T_AddRef
,
2580 XCAST(Release
) GL_IDirect3DDeviceImpl_7_3T_2T_1T_Release
,
2581 XCAST(GetCaps
) GL_IDirect3DDeviceImpl_7_GetCaps
,
2582 XCAST(EnumTextureFormats
) GL_IDirect3DDeviceImpl_7_3T_EnumTextureFormats
,
2583 XCAST(BeginScene
) Main_IDirect3DDeviceImpl_7_3T_2T_1T_BeginScene
,
2584 XCAST(EndScene
) Main_IDirect3DDeviceImpl_7_3T_2T_1T_EndScene
,
2585 XCAST(GetDirect3D
) Main_IDirect3DDeviceImpl_7_3T_2T_1T_GetDirect3D
,
2586 XCAST(SetRenderTarget
) Main_IDirect3DDeviceImpl_7_3T_2T_SetRenderTarget
,
2587 XCAST(GetRenderTarget
) Main_IDirect3DDeviceImpl_7_3T_2T_GetRenderTarget
,
2588 XCAST(Clear
) Main_IDirect3DDeviceImpl_7_Clear
,
2589 XCAST(SetTransform
) Main_IDirect3DDeviceImpl_7_3T_2T_SetTransform
,
2590 XCAST(GetTransform
) Main_IDirect3DDeviceImpl_7_3T_2T_GetTransform
,
2591 XCAST(SetViewport
) GL_IDirect3DDeviceImpl_7_SetViewport
,
2592 XCAST(MultiplyTransform
) Main_IDirect3DDeviceImpl_7_3T_2T_MultiplyTransform
,
2593 XCAST(GetViewport
) Main_IDirect3DDeviceImpl_7_GetViewport
,
2594 XCAST(SetMaterial
) GL_IDirect3DDeviceImpl_7_SetMaterial
,
2595 XCAST(GetMaterial
) Main_IDirect3DDeviceImpl_7_GetMaterial
,
2596 XCAST(SetLight
) GL_IDirect3DDeviceImpl_7_SetLight
,
2597 XCAST(GetLight
) Main_IDirect3DDeviceImpl_7_GetLight
,
2598 XCAST(SetRenderState
) GL_IDirect3DDeviceImpl_7_3T_2T_SetRenderState
,
2599 XCAST(GetRenderState
) GL_IDirect3DDeviceImpl_7_3T_2T_GetRenderState
,
2600 XCAST(BeginStateBlock
) Main_IDirect3DDeviceImpl_7_BeginStateBlock
,
2601 XCAST(EndStateBlock
) Main_IDirect3DDeviceImpl_7_EndStateBlock
,
2602 XCAST(PreLoad
) Main_IDirect3DDeviceImpl_7_PreLoad
,
2603 XCAST(DrawPrimitive
) GL_IDirect3DDeviceImpl_7_3T_DrawPrimitive
,
2604 XCAST(DrawIndexedPrimitive
) GL_IDirect3DDeviceImpl_7_3T_DrawIndexedPrimitive
,
2605 XCAST(SetClipStatus
) Main_IDirect3DDeviceImpl_7_3T_2T_SetClipStatus
,
2606 XCAST(GetClipStatus
) Main_IDirect3DDeviceImpl_7_3T_2T_GetClipStatus
,
2607 XCAST(DrawPrimitiveStrided
) GL_IDirect3DDeviceImpl_7_3T_DrawPrimitiveStrided
,
2608 XCAST(DrawIndexedPrimitiveStrided
) GL_IDirect3DDeviceImpl_7_3T_DrawIndexedPrimitiveStrided
,
2609 XCAST(DrawPrimitiveVB
) GL_IDirect3DDeviceImpl_7_3T_DrawPrimitiveVB
,
2610 XCAST(DrawIndexedPrimitiveVB
) GL_IDirect3DDeviceImpl_7_3T_DrawIndexedPrimitiveVB
,
2611 XCAST(ComputeSphereVisibility
) Main_IDirect3DDeviceImpl_7_3T_ComputeSphereVisibility
,
2612 XCAST(GetTexture
) Main_IDirect3DDeviceImpl_7_3T_GetTexture
,
2613 XCAST(SetTexture
) GL_IDirect3DDeviceImpl_7_3T_SetTexture
,
2614 XCAST(GetTextureStageState
) Main_IDirect3DDeviceImpl_7_3T_GetTextureStageState
,
2615 XCAST(SetTextureStageState
) GL_IDirect3DDeviceImpl_7_3T_SetTextureStageState
,
2616 XCAST(ValidateDevice
) Main_IDirect3DDeviceImpl_7_3T_ValidateDevice
,
2617 XCAST(ApplyStateBlock
) Main_IDirect3DDeviceImpl_7_ApplyStateBlock
,
2618 XCAST(CaptureStateBlock
) Main_IDirect3DDeviceImpl_7_CaptureStateBlock
,
2619 XCAST(DeleteStateBlock
) Main_IDirect3DDeviceImpl_7_DeleteStateBlock
,
2620 XCAST(CreateStateBlock
) Main_IDirect3DDeviceImpl_7_CreateStateBlock
,
2621 XCAST(Load
) Main_IDirect3DDeviceImpl_7_Load
,
2622 XCAST(LightEnable
) GL_IDirect3DDeviceImpl_7_LightEnable
,
2623 XCAST(GetLightEnable
) Main_IDirect3DDeviceImpl_7_GetLightEnable
,
2624 XCAST(SetClipPlane
) GL_IDirect3DDeviceImpl_7_SetClipPlane
,
2625 XCAST(GetClipPlane
) Main_IDirect3DDeviceImpl_7_GetClipPlane
,
2626 XCAST(GetInfo
) Main_IDirect3DDeviceImpl_7_GetInfo
,
2629 #if !defined(__STRICT_ANSI__) && defined(__GNUC__)
2634 #if !defined(__STRICT_ANSI__) && defined(__GNUC__)
2635 # define XCAST(fun) (typeof(VTABLE_IDirect3DDevice3.fun))
2637 # define XCAST(fun) (void*)
2640 IDirect3DDevice3Vtbl VTABLE_IDirect3DDevice3
=
2642 XCAST(QueryInterface
) Thunk_IDirect3DDeviceImpl_3_QueryInterface
,
2643 XCAST(AddRef
) Thunk_IDirect3DDeviceImpl_3_AddRef
,
2644 XCAST(Release
) Thunk_IDirect3DDeviceImpl_3_Release
,
2645 XCAST(GetCaps
) GL_IDirect3DDeviceImpl_3_2T_1T_GetCaps
,
2646 XCAST(GetStats
) Main_IDirect3DDeviceImpl_3_2T_1T_GetStats
,
2647 XCAST(AddViewport
) Main_IDirect3DDeviceImpl_3_2T_1T_AddViewport
,
2648 XCAST(DeleteViewport
) Main_IDirect3DDeviceImpl_3_2T_1T_DeleteViewport
,
2649 XCAST(NextViewport
) Main_IDirect3DDeviceImpl_3_2T_1T_NextViewport
,
2650 XCAST(EnumTextureFormats
) Thunk_IDirect3DDeviceImpl_3_EnumTextureFormats
,
2651 XCAST(BeginScene
) Thunk_IDirect3DDeviceImpl_3_BeginScene
,
2652 XCAST(EndScene
) Thunk_IDirect3DDeviceImpl_3_EndScene
,
2653 XCAST(GetDirect3D
) Thunk_IDirect3DDeviceImpl_3_GetDirect3D
,
2654 XCAST(SetCurrentViewport
) Main_IDirect3DDeviceImpl_3_2T_SetCurrentViewport
,
2655 XCAST(GetCurrentViewport
) Main_IDirect3DDeviceImpl_3_2T_GetCurrentViewport
,
2656 XCAST(SetRenderTarget
) Thunk_IDirect3DDeviceImpl_3_SetRenderTarget
,
2657 XCAST(GetRenderTarget
) Thunk_IDirect3DDeviceImpl_3_GetRenderTarget
,
2658 XCAST(Begin
) Main_IDirect3DDeviceImpl_3_Begin
,
2659 XCAST(BeginIndexed
) Main_IDirect3DDeviceImpl_3_BeginIndexed
,
2660 XCAST(Vertex
) Main_IDirect3DDeviceImpl_3_2T_Vertex
,
2661 XCAST(Index
) Main_IDirect3DDeviceImpl_3_2T_Index
,
2662 XCAST(End
) Main_IDirect3DDeviceImpl_3_2T_End
,
2663 XCAST(GetRenderState
) Thunk_IDirect3DDeviceImpl_3_GetRenderState
,
2664 XCAST(SetRenderState
) Thunk_IDirect3DDeviceImpl_3_SetRenderState
,
2665 XCAST(GetLightState
) GL_IDirect3DDeviceImpl_3_2T_GetLightState
,
2666 XCAST(SetLightState
) GL_IDirect3DDeviceImpl_3_2T_SetLightState
,
2667 XCAST(SetTransform
) Thunk_IDirect3DDeviceImpl_3_SetTransform
,
2668 XCAST(GetTransform
) Thunk_IDirect3DDeviceImpl_3_GetTransform
,
2669 XCAST(MultiplyTransform
) Thunk_IDirect3DDeviceImpl_3_MultiplyTransform
,
2670 XCAST(DrawPrimitive
) Thunk_IDirect3DDeviceImpl_3_DrawPrimitive
,
2671 XCAST(DrawIndexedPrimitive
) Thunk_IDirect3DDeviceImpl_3_DrawIndexedPrimitive
,
2672 XCAST(SetClipStatus
) Thunk_IDirect3DDeviceImpl_3_SetClipStatus
,
2673 XCAST(GetClipStatus
) Thunk_IDirect3DDeviceImpl_3_GetClipStatus
,
2674 XCAST(DrawPrimitiveStrided
) Thunk_IDirect3DDeviceImpl_3_DrawPrimitiveStrided
,
2675 XCAST(DrawIndexedPrimitiveStrided
) Thunk_IDirect3DDeviceImpl_3_DrawIndexedPrimitiveStrided
,
2676 XCAST(DrawPrimitiveVB
) Thunk_IDirect3DDeviceImpl_3_DrawPrimitiveVB
,
2677 XCAST(DrawIndexedPrimitiveVB
) Thunk_IDirect3DDeviceImpl_3_DrawIndexedPrimitiveVB
,
2678 XCAST(ComputeSphereVisibility
) Thunk_IDirect3DDeviceImpl_3_ComputeSphereVisibility
,
2679 XCAST(GetTexture
) Thunk_IDirect3DDeviceImpl_3_GetTexture
,
2680 XCAST(SetTexture
) Thunk_IDirect3DDeviceImpl_3_SetTexture
,
2681 XCAST(GetTextureStageState
) Thunk_IDirect3DDeviceImpl_3_GetTextureStageState
,
2682 XCAST(SetTextureStageState
) Thunk_IDirect3DDeviceImpl_3_SetTextureStageState
,
2683 XCAST(ValidateDevice
) Thunk_IDirect3DDeviceImpl_3_ValidateDevice
,
2686 #if !defined(__STRICT_ANSI__) && defined(__GNUC__)
2691 #if !defined(__STRICT_ANSI__) && defined(__GNUC__)
2692 # define XCAST(fun) (typeof(VTABLE_IDirect3DDevice2.fun))
2694 # define XCAST(fun) (void*)
2697 IDirect3DDevice2Vtbl VTABLE_IDirect3DDevice2
=
2699 XCAST(QueryInterface
) Thunk_IDirect3DDeviceImpl_2_QueryInterface
,
2700 XCAST(AddRef
) Thunk_IDirect3DDeviceImpl_2_AddRef
,
2701 XCAST(Release
) Thunk_IDirect3DDeviceImpl_2_Release
,
2702 XCAST(GetCaps
) Thunk_IDirect3DDeviceImpl_2_GetCaps
,
2703 XCAST(SwapTextureHandles
) Main_IDirect3DDeviceImpl_2_1T_SwapTextureHandles
,
2704 XCAST(GetStats
) Thunk_IDirect3DDeviceImpl_2_GetStats
,
2705 XCAST(AddViewport
) Thunk_IDirect3DDeviceImpl_2_AddViewport
,
2706 XCAST(DeleteViewport
) Thunk_IDirect3DDeviceImpl_2_DeleteViewport
,
2707 XCAST(NextViewport
) Thunk_IDirect3DDeviceImpl_2_NextViewport
,
2708 XCAST(EnumTextureFormats
) GL_IDirect3DDeviceImpl_2_1T_EnumTextureFormats
,
2709 XCAST(BeginScene
) Thunk_IDirect3DDeviceImpl_2_BeginScene
,
2710 XCAST(EndScene
) Thunk_IDirect3DDeviceImpl_2_EndScene
,
2711 XCAST(GetDirect3D
) Thunk_IDirect3DDeviceImpl_2_GetDirect3D
,
2712 XCAST(SetCurrentViewport
) Thunk_IDirect3DDeviceImpl_2_SetCurrentViewport
,
2713 XCAST(GetCurrentViewport
) Thunk_IDirect3DDeviceImpl_2_GetCurrentViewport
,
2714 XCAST(SetRenderTarget
) Thunk_IDirect3DDeviceImpl_2_SetRenderTarget
,
2715 XCAST(GetRenderTarget
) Thunk_IDirect3DDeviceImpl_2_GetRenderTarget
,
2716 XCAST(Begin
) Main_IDirect3DDeviceImpl_2_Begin
,
2717 XCAST(BeginIndexed
) Main_IDirect3DDeviceImpl_2_BeginIndexed
,
2718 XCAST(Vertex
) Thunk_IDirect3DDeviceImpl_2_Vertex
,
2719 XCAST(Index
) Thunk_IDirect3DDeviceImpl_2_Index
,
2720 XCAST(End
) Thunk_IDirect3DDeviceImpl_2_End
,
2721 XCAST(GetRenderState
) Thunk_IDirect3DDeviceImpl_2_GetRenderState
,
2722 XCAST(SetRenderState
) Thunk_IDirect3DDeviceImpl_2_SetRenderState
,
2723 XCAST(GetLightState
) Thunk_IDirect3DDeviceImpl_2_GetLightState
,
2724 XCAST(SetLightState
) Thunk_IDirect3DDeviceImpl_2_SetLightState
,
2725 XCAST(SetTransform
) Thunk_IDirect3DDeviceImpl_2_SetTransform
,
2726 XCAST(GetTransform
) Thunk_IDirect3DDeviceImpl_2_GetTransform
,
2727 XCAST(MultiplyTransform
) Thunk_IDirect3DDeviceImpl_2_MultiplyTransform
,
2728 XCAST(DrawPrimitive
) GL_IDirect3DDeviceImpl_2_DrawPrimitive
,
2729 XCAST(DrawIndexedPrimitive
) GL_IDirect3DDeviceImpl_2_DrawIndexedPrimitive
,
2730 XCAST(SetClipStatus
) Thunk_IDirect3DDeviceImpl_2_SetClipStatus
,
2731 XCAST(GetClipStatus
) Thunk_IDirect3DDeviceImpl_2_GetClipStatus
,
2734 #if !defined(__STRICT_ANSI__) && defined(__GNUC__)
2739 #if !defined(__STRICT_ANSI__) && defined(__GNUC__)
2740 # define XCAST(fun) (typeof(VTABLE_IDirect3DDevice.fun))
2742 # define XCAST(fun) (void*)
2745 IDirect3DDeviceVtbl VTABLE_IDirect3DDevice
=
2747 XCAST(QueryInterface
) Thunk_IDirect3DDeviceImpl_1_QueryInterface
,
2748 XCAST(AddRef
) Thunk_IDirect3DDeviceImpl_1_AddRef
,
2749 XCAST(Release
) Thunk_IDirect3DDeviceImpl_1_Release
,
2750 XCAST(Initialize
) Main_IDirect3DDeviceImpl_1_Initialize
,
2751 XCAST(GetCaps
) Thunk_IDirect3DDeviceImpl_1_GetCaps
,
2752 XCAST(SwapTextureHandles
) Thunk_IDirect3DDeviceImpl_1_SwapTextureHandles
,
2753 XCAST(CreateExecuteBuffer
) GL_IDirect3DDeviceImpl_1_CreateExecuteBuffer
,
2754 XCAST(GetStats
) Thunk_IDirect3DDeviceImpl_1_GetStats
,
2755 XCAST(Execute
) Main_IDirect3DDeviceImpl_1_Execute
,
2756 XCAST(AddViewport
) Thunk_IDirect3DDeviceImpl_1_AddViewport
,
2757 XCAST(DeleteViewport
) Thunk_IDirect3DDeviceImpl_1_DeleteViewport
,
2758 XCAST(NextViewport
) Thunk_IDirect3DDeviceImpl_1_NextViewport
,
2759 XCAST(Pick
) Main_IDirect3DDeviceImpl_1_Pick
,
2760 XCAST(GetPickRecords
) Main_IDirect3DDeviceImpl_1_GetPickRecords
,
2761 XCAST(EnumTextureFormats
) Thunk_IDirect3DDeviceImpl_1_EnumTextureFormats
,
2762 XCAST(CreateMatrix
) Main_IDirect3DDeviceImpl_1_CreateMatrix
,
2763 XCAST(SetMatrix
) Main_IDirect3DDeviceImpl_1_SetMatrix
,
2764 XCAST(GetMatrix
) Main_IDirect3DDeviceImpl_1_GetMatrix
,
2765 XCAST(DeleteMatrix
) Main_IDirect3DDeviceImpl_1_DeleteMatrix
,
2766 XCAST(BeginScene
) Thunk_IDirect3DDeviceImpl_1_BeginScene
,
2767 XCAST(EndScene
) Thunk_IDirect3DDeviceImpl_1_EndScene
,
2768 XCAST(GetDirect3D
) Thunk_IDirect3DDeviceImpl_1_GetDirect3D
,
2771 #if !defined(__STRICT_ANSI__) && defined(__GNUC__)
2775 static HRESULT
d3ddevice_clear(IDirect3DDeviceImpl
*This
,
2776 WINE_GL_BUFFER_TYPE buffer_type
,
2784 IDirect3DDeviceGLImpl
*glThis
= (IDirect3DDeviceGLImpl
*) This
;
2785 GLbitfield bitfield
= 0;
2789 TRACE("(%p)->(%08lx,%p,%08lx,%08lx,%f,%08lx)\n", This
, dwCount
, lpRects
, dwFlags
, dwColor
, dvZ
, dwStencil
);
2790 if (TRACE_ON(ddraw
)) {
2793 TRACE(" rectangles : \n");
2794 for (i
= 0; i
< dwCount
; i
++) {
2795 TRACE(" - %ld x %ld %ld x %ld\n", lpRects
[i
].u1
.x1
, lpRects
[i
].u2
.y1
, lpRects
[i
].u3
.x2
, lpRects
[i
].u4
.y2
);
2804 rect
.u3
.x2
= This
->surface
->surface_desc
.dwWidth
;
2805 rect
.u4
.y2
= This
->surface
->surface_desc
.dwHeight
;
2809 /* Clears the screen */
2812 if (dwFlags
& D3DCLEAR_TARGET
) {
2813 if (glThis
->state
[buffer_type
] == SURFACE_MEMORY_DIRTY
) {
2814 /* TODO: optimize here the case where Clear changes all the screen... */
2815 This
->flush_to_framebuffer(This
, &(glThis
->lock_rect
[buffer_type
]), glThis
->lock_surf
[buffer_type
]);
2817 glThis
->state
[buffer_type
] = SURFACE_GL
;
2820 if (dwFlags
& D3DCLEAR_ZBUFFER
) {
2821 bitfield
|= GL_DEPTH_BUFFER_BIT
;
2822 if (glThis
->depth_mask
== FALSE
) {
2823 glDepthMask(GL_TRUE
); /* Enables Z writing to be sure to delete also the Z buffer */
2825 if (dvZ
!= glThis
->prev_clear_Z
) {
2827 glThis
->prev_clear_Z
= dvZ
;
2829 TRACE(" depth value : %f\n", dvZ
);
2831 if (dwFlags
& D3DCLEAR_STENCIL
) {
2832 bitfield
|= GL_STENCIL_BUFFER_BIT
;
2833 if (dwStencil
!= glThis
->prev_clear_stencil
) {
2834 glClearStencil(dwStencil
);
2835 glThis
->prev_clear_stencil
= dwStencil
;
2837 TRACE(" stencil value : %ld\n", dwStencil
);
2839 if (dwFlags
& D3DCLEAR_TARGET
) {
2840 bitfield
|= GL_COLOR_BUFFER_BIT
;
2841 if (dwColor
!= glThis
->prev_clear_color
) {
2842 glClearColor(((dwColor
>> 16) & 0xFF) / 255.0,
2843 ((dwColor
>> 8) & 0xFF) / 255.0,
2844 ((dwColor
>> 0) & 0xFF) / 255.0,
2845 ((dwColor
>> 24) & 0xFF) / 255.0);
2846 glThis
->prev_clear_color
= dwColor
;
2848 TRACE(" color value (ARGB) : %08lx\n", dwColor
);
2851 glEnable(GL_SCISSOR_TEST
);
2852 for (i
= 0; i
< dwCount
; i
++) {
2853 glScissor(lpRects
[i
].u1
.x1
, This
->surface
->surface_desc
.dwHeight
- lpRects
[i
].u4
.y2
,
2854 lpRects
[i
].u3
.x2
- lpRects
[i
].u1
.x1
, lpRects
[i
].u4
.y2
- lpRects
[i
].u2
.y1
);
2857 glDisable(GL_SCISSOR_TEST
);
2859 if (dwFlags
& D3DCLEAR_ZBUFFER
) {
2860 if (glThis
->depth_mask
== FALSE
) glDepthMask(GL_FALSE
);
2868 static HRESULT
d3ddevice_clear_back(IDirect3DDeviceImpl
*This
,
2876 return d3ddevice_clear(This
, WINE_GL_BUFFER_BACK
, dwCount
, lpRects
, dwFlags
, dwColor
, dvZ
, dwStencil
);
2880 setup_rect_and_surface_for_blt(IDirectDrawSurfaceImpl
*This
,
2881 WINE_GL_BUFFER_TYPE
*buffer_type_p
, D3DRECT
*rect
)
2883 IDirect3DDeviceGLImpl
*gl_d3d_dev
= (IDirect3DDeviceGLImpl
*) This
->d3ddevice
;
2884 WINE_GL_BUFFER_TYPE buffer_type
;
2886 /* First check if we BLT to the backbuffer... */
2887 if ((This
->surface_desc
.ddsCaps
.dwCaps
& (DDSCAPS_BACKBUFFER
)) != 0) {
2888 buffer_type
= WINE_GL_BUFFER_BACK
;
2889 } else if ((This
->surface_desc
.ddsCaps
.dwCaps
& (DDSCAPS_FRONTBUFFER
|DDSCAPS_PRIMARYSURFACE
)) != 0) {
2890 buffer_type
= WINE_GL_BUFFER_FRONT
;
2892 ERR("Only BLT override to front or back-buffer is supported for now !\n");
2893 return DDERR_INVALIDPARAMS
;
2896 if ((gl_d3d_dev
->state
[buffer_type
] == SURFACE_MEMORY_DIRTY
) &&
2897 (rect
->u1
.x1
>= gl_d3d_dev
->lock_rect
[buffer_type
].left
) &&
2898 (rect
->u2
.y1
>= gl_d3d_dev
->lock_rect
[buffer_type
].top
) &&
2899 (rect
->u3
.x2
<= gl_d3d_dev
->lock_rect
[buffer_type
].right
) &&
2900 (rect
->u4
.y2
<= gl_d3d_dev
->lock_rect
[buffer_type
].bottom
)) {
2901 /* If the memory zone is already dirty, use the standard 'in memory' blit operations and not
2904 return DDERR_INVALIDPARAMS
;
2906 *buffer_type_p
= buffer_type
;
2912 d3ddevice_blt(IDirectDrawSurfaceImpl
*This
, LPRECT rdst
,
2913 LPDIRECTDRAWSURFACE7 src
, LPRECT rsrc
,
2914 DWORD dwFlags
, LPDDBLTFX lpbltfx
)
2916 WINE_GL_BUFFER_TYPE buffer_type
;
2920 rect
.u1
.x1
= rdst
->left
;
2921 rect
.u2
.y1
= rdst
->top
;
2922 rect
.u3
.x2
= rdst
->right
;
2923 rect
.u4
.y2
= rdst
->bottom
;
2927 rect
.u3
.x2
= This
->surface_desc
.dwWidth
;
2928 rect
.u4
.y2
= This
->surface_desc
.dwHeight
;
2931 if (setup_rect_and_surface_for_blt(This
, &buffer_type
, &rect
) != DD_OK
) return DDERR_INVALIDPARAMS
;
2933 if (dwFlags
& DDBLT_COLORFILL
) {
2934 /* This is easy to handle for the D3D Device... */
2938 /* The color as given in the Blt function is in the format of the frame-buffer...
2939 * 'clear' expect it in ARGB format => we need to do some conversion :-)
2941 if (This
->surface_desc
.u4
.ddpfPixelFormat
.dwFlags
& DDPF_PALETTEINDEXED8
) {
2942 if (This
->palette
) {
2943 color
= ((0xFF000000) |
2944 (This
->palette
->palents
[lpbltfx
->u5
.dwFillColor
].peRed
<< 16) |
2945 (This
->palette
->palents
[lpbltfx
->u5
.dwFillColor
].peGreen
<< 8) |
2946 (This
->palette
->palents
[lpbltfx
->u5
.dwFillColor
].peBlue
));
2950 } else if ((This
->surface_desc
.u4
.ddpfPixelFormat
.dwFlags
& DDPF_RGB
) &&
2951 (((This
->surface_desc
.u4
.ddpfPixelFormat
.dwFlags
& DDPF_ALPHAPIXELS
) == 0) ||
2952 (This
->surface_desc
.u4
.ddpfPixelFormat
.u5
.dwRGBAlphaBitMask
== 0x00000000))) {
2953 if ((This
->surface_desc
.u4
.ddpfPixelFormat
.u1
.dwRGBBitCount
== 16) &&
2954 (This
->surface_desc
.u4
.ddpfPixelFormat
.u2
.dwRBitMask
== 0xF800) &&
2955 (This
->surface_desc
.u4
.ddpfPixelFormat
.u3
.dwGBitMask
== 0x07E0) &&
2956 (This
->surface_desc
.u4
.ddpfPixelFormat
.u4
.dwBBitMask
== 0x001F)) {
2957 if (lpbltfx
->u5
.dwFillColor
== 0xFFFF) {
2960 color
= ((0xFF000000) |
2961 ((lpbltfx
->u5
.dwFillColor
& 0xF800) << 8) |
2962 ((lpbltfx
->u5
.dwFillColor
& 0x07E0) << 5) |
2963 ((lpbltfx
->u5
.dwFillColor
& 0x001F) << 3));
2965 } else if (((This
->surface_desc
.u4
.ddpfPixelFormat
.u1
.dwRGBBitCount
== 32) ||
2966 (This
->surface_desc
.u4
.ddpfPixelFormat
.u1
.dwRGBBitCount
== 24)) &&
2967 (This
->surface_desc
.u4
.ddpfPixelFormat
.u2
.dwRBitMask
== 0x00FF0000) &&
2968 (This
->surface_desc
.u4
.ddpfPixelFormat
.u3
.dwGBitMask
== 0x0000FF00) &&
2969 (This
->surface_desc
.u4
.ddpfPixelFormat
.u4
.dwBBitMask
== 0x000000FF)) {
2970 color
= 0xFF000000 | lpbltfx
->u5
.dwFillColor
;
2972 ERR("Wrong surface type for BLT override (unknown RGB format) !\n");
2973 return DDERR_INVALIDPARAMS
;
2976 ERR("Wrong surface type for BLT override !\n");
2977 return DDERR_INVALIDPARAMS
;
2980 TRACE(" executing D3D Device override.\n");
2984 glGetIntegerv(GL_DRAW_BUFFER
, &prev_draw
);
2985 if (buffer_type
== WINE_GL_BUFFER_FRONT
)
2986 glDrawBuffer(GL_FRONT
);
2988 glDrawBuffer(GL_BACK
);
2990 d3ddevice_clear(This
->d3ddevice
, buffer_type
, 1, &rect
, D3DCLEAR_TARGET
, color
, 0.0, 0x00000000);
2992 if (((buffer_type
== WINE_GL_BUFFER_FRONT
) && (prev_draw
== GL_BACK
)) ||
2993 ((buffer_type
== WINE_GL_BUFFER_BACK
) && (prev_draw
== GL_FRONT
)))
2994 glDrawBuffer(prev_draw
);
2999 } else if ((dwFlags
& (~(DDBLT_KEYSRC
|DDBLT_WAIT
|DDBLT_ASYNC
))) == 0) {
3000 /* Normal blit without any special case... */
3002 /* And which has a SRC surface */
3003 IDirectDrawSurfaceImpl
*src_impl
= ICOM_OBJECT(IDirectDrawSurfaceImpl
, IDirectDrawSurface7
, src
);
3005 if ((src_impl
->surface_desc
.ddsCaps
.dwCaps
& DDSCAPS_3DDEVICE
) &&
3006 (src_impl
->d3ddevice
== This
->d3ddevice
) &&
3007 ((dwFlags
& DDBLT_KEYSRC
) == 0)) {
3008 /* Both are 3D devices and using the same GL device and the Blt is without color-keying */
3012 WINE_GL_BUFFER_TYPE src_buffer_type
;
3013 IDirect3DDeviceGLImpl
*gl_d3d_dev
= (IDirect3DDeviceGLImpl
*) This
->d3ddevice
;
3019 src_rect
.u1
.x1
= rsrc
->left
;
3020 src_rect
.u2
.y1
= rsrc
->top
;
3021 src_rect
.u3
.x2
= rsrc
->right
;
3022 src_rect
.u4
.y2
= rsrc
->bottom
;
3026 src_rect
.u3
.x2
= src_impl
->surface_desc
.dwWidth
;
3027 src_rect
.u4
.y2
= src_impl
->surface_desc
.dwHeight
;
3030 width
= src_rect
.u3
.x2
- src_rect
.u1
.x1
;
3031 height
= src_rect
.u4
.y2
- src_rect
.u2
.y1
;
3033 if ((width
!= (rect
.u3
.x2
- rect
.u1
.x1
)) ||
3034 (height
!= (rect
.u4
.y2
- rect
.u2
.y1
))) {
3035 FIXME(" buffer to buffer copy not supported with stretching yet !\n");
3036 return DDERR_INVALIDPARAMS
;
3039 /* First check if we BLT from the backbuffer... */
3040 if ((src_impl
->surface_desc
.ddsCaps
.dwCaps
& (DDSCAPS_BACKBUFFER
)) != 0) {
3041 src_buffer_type
= WINE_GL_BUFFER_BACK
;
3042 } else if ((src_impl
->surface_desc
.ddsCaps
.dwCaps
& (DDSCAPS_FRONTBUFFER
|DDSCAPS_PRIMARYSURFACE
)) != 0) {
3043 src_buffer_type
= WINE_GL_BUFFER_FRONT
;
3045 ERR("Unexpected case in direct buffer to buffer copy !\n");
3046 return DDERR_INVALIDPARAMS
;
3049 TRACE(" using direct buffer to buffer copy.\n");
3053 opt_bitmap
= d3ddevice_set_state_for_flush(This
->d3ddevice
, (LPCRECT
) &rect
, FALSE
, &initial
);
3055 if (upload_surface_to_tex_memory_init(This
, 0, &gl_d3d_dev
->current_internal_format
,
3056 initial
, FALSE
, UNLOCK_TEX_SIZE
, UNLOCK_TEX_SIZE
) != DD_OK
) {
3057 ERR(" unsupported pixel format at direct buffer to buffer copy.\n");
3059 return DDERR_INVALIDPARAMS
;
3062 glGetIntegerv(GL_DRAW_BUFFER
, &prev_draw
);
3063 if (buffer_type
== WINE_GL_BUFFER_FRONT
)
3064 glDrawBuffer(GL_FRONT
);
3066 glDrawBuffer(GL_BACK
);
3068 if (src_buffer_type
== WINE_GL_BUFFER_FRONT
)
3069 glReadBuffer(GL_FRONT
);
3071 glReadBuffer(GL_BACK
);
3073 /* Now the serious stuff happens. Basically, we copy from the source buffer to the texture memory.
3074 And directly re-draws this on the destination buffer. */
3075 for (y
= 0; y
< height
; y
+= UNLOCK_TEX_SIZE
) {
3078 if ((src_rect
.u2
.y1
+ y
+ UNLOCK_TEX_SIZE
) > src_impl
->surface_desc
.dwHeight
)
3079 get_height
= src_impl
->surface_desc
.dwHeight
- (src_rect
.u2
.y1
+ y
);
3081 get_height
= UNLOCK_TEX_SIZE
;
3083 for (x
= 0; x
< width
; x
+= UNLOCK_TEX_SIZE
) {
3086 if ((src_rect
.u1
.x1
+ x
+ UNLOCK_TEX_SIZE
) > src_impl
->surface_desc
.dwWidth
)
3087 get_width
= src_impl
->surface_desc
.dwWidth
- (src_rect
.u1
.x1
+ x
);
3089 get_width
= UNLOCK_TEX_SIZE
;
3091 glCopyTexSubImage2D(GL_TEXTURE_2D
, 0,
3092 0, UNLOCK_TEX_SIZE
- get_height
,
3093 src_rect
.u1
.x1
+ x
, src_impl
->surface_desc
.dwHeight
- (src_rect
.u2
.y1
+ y
+ get_height
),
3094 get_width
, get_height
);
3097 glTexCoord2f(0.0, 0.0);
3098 glVertex3d(rect
.u1
.x1
+ x
,
3099 rect
.u2
.y1
+ y
+ UNLOCK_TEX_SIZE
,
3101 glTexCoord2f(1.0, 0.0);
3102 glVertex3d(rect
.u1
.x1
+ x
+ UNLOCK_TEX_SIZE
,
3103 rect
.u2
.y1
+ y
+ UNLOCK_TEX_SIZE
,
3105 glTexCoord2f(1.0, 1.0);
3106 glVertex3d(rect
.u1
.x1
+ x
+ UNLOCK_TEX_SIZE
,
3109 glTexCoord2f(0.0, 1.0);
3110 glVertex3d(rect
.u1
.x1
+ x
,
3117 upload_surface_to_tex_memory_release();
3118 d3ddevice_restore_state_after_flush(This
->d3ddevice
, opt_bitmap
, FALSE
);
3120 if (((buffer_type
== WINE_GL_BUFFER_FRONT
) && (prev_draw
== GL_BACK
)) ||
3121 ((buffer_type
== WINE_GL_BUFFER_BACK
) && (prev_draw
== GL_FRONT
)))
3122 glDrawBuffer(prev_draw
);
3128 /* This is the normal 'with source' Blit. Use the texture engine to do the Blt for us
3129 (this prevents calling glReadPixels) */
3133 IDirect3DDeviceGLImpl
*gl_d3d_dev
= (IDirect3DDeviceGLImpl
*) This
->d3ddevice
;
3137 double x_stretch
, y_stretch
;
3140 src_rect
.u1
.x1
= rsrc
->left
;
3141 src_rect
.u2
.y1
= rsrc
->top
;
3142 src_rect
.u3
.x2
= rsrc
->right
;
3143 src_rect
.u4
.y2
= rsrc
->bottom
;
3147 src_rect
.u3
.x2
= src_impl
->surface_desc
.dwWidth
;
3148 src_rect
.u4
.y2
= src_impl
->surface_desc
.dwHeight
;
3151 width
= src_rect
.u3
.x2
- src_rect
.u1
.x1
;
3152 height
= src_rect
.u4
.y2
- src_rect
.u2
.y1
;
3154 x_stretch
= (double) (rect
.u3
.x2
- rect
.u1
.x1
) / (double) width
;
3155 y_stretch
= (double) (rect
.u4
.y2
- rect
.u2
.y1
) / (double) height
;
3157 TRACE(" using memory to buffer Blt override.\n");
3161 opt_bitmap
= d3ddevice_set_state_for_flush(This
->d3ddevice
, (LPCRECT
) &rect
, ((dwFlags
& DDBLT_KEYSRC
) != 0), &initial
);
3163 if (upload_surface_to_tex_memory_init(src_impl
, 0, &gl_d3d_dev
->current_internal_format
,
3164 initial
, ((dwFlags
& DDBLT_KEYSRC
) != 0), UNLOCK_TEX_SIZE
, UNLOCK_TEX_SIZE
) != DD_OK
) {
3165 ERR(" unsupported pixel format at memory to buffer Blt override.\n");
3167 return DDERR_INVALIDPARAMS
;
3170 glGetIntegerv(GL_DRAW_BUFFER
, &prev_draw
);
3171 if (buffer_type
== WINE_GL_BUFFER_FRONT
)
3172 glDrawBuffer(GL_FRONT
);
3174 glDrawBuffer(GL_BACK
);
3176 /* Now the serious stuff happens. This is basically the same code as for the memory
3177 flush to frame buffer ... with stretching and different rectangles added :-) */
3178 for (y
= 0; y
< height
; y
+= UNLOCK_TEX_SIZE
) {
3181 flush_rect
.top
= src_rect
.u2
.y1
+ y
;
3182 flush_rect
.bottom
= ((src_rect
.u2
.y1
+ y
+ UNLOCK_TEX_SIZE
> src_rect
.u4
.y2
) ?
3184 (src_rect
.u2
.y1
+ y
+ UNLOCK_TEX_SIZE
));
3186 for (x
= 0; x
< width
; x
+= UNLOCK_TEX_SIZE
) {
3187 flush_rect
.left
= src_rect
.u1
.x1
+ x
;
3188 flush_rect
.right
= ((src_rect
.u1
.x1
+ x
+ UNLOCK_TEX_SIZE
> src_rect
.u3
.x2
) ?
3190 (src_rect
.u1
.x1
+ x
+ UNLOCK_TEX_SIZE
));
3192 upload_surface_to_tex_memory(&flush_rect
, 0, 0, &(gl_d3d_dev
->surface_ptr
));
3195 glTexCoord2f(0.0, 0.0);
3196 glVertex3d(rect
.u1
.x1
+ (x
* x_stretch
),
3197 rect
.u2
.y1
+ (y
* y_stretch
),
3199 glTexCoord2f(1.0, 0.0);
3200 glVertex3d(rect
.u1
.x1
+ ((x
+ UNLOCK_TEX_SIZE
) * x_stretch
),
3201 rect
.u2
.y1
+ (y
* y_stretch
),
3203 glTexCoord2f(1.0, 1.0);
3204 glVertex3d(rect
.u1
.x1
+ ((x
+ UNLOCK_TEX_SIZE
) * x_stretch
),
3205 rect
.u2
.y1
+ ((y
+ UNLOCK_TEX_SIZE
) * y_stretch
),
3207 glTexCoord2f(0.0, 1.0);
3208 glVertex3d(rect
.u1
.x1
+ (x
* x_stretch
),
3209 rect
.u2
.y1
+ ((y
+ UNLOCK_TEX_SIZE
) * y_stretch
),
3215 upload_surface_to_tex_memory_release();
3216 d3ddevice_restore_state_after_flush(This
->d3ddevice
, opt_bitmap
, ((dwFlags
& DDBLT_KEYSRC
) != 0));
3218 if (((buffer_type
== WINE_GL_BUFFER_FRONT
) && (prev_draw
== GL_BACK
)) ||
3219 ((buffer_type
== WINE_GL_BUFFER_BACK
) && (prev_draw
== GL_FRONT
)))
3220 glDrawBuffer(prev_draw
);
3228 return DDERR_INVALIDPARAMS
;
3232 d3ddevice_bltfast(IDirectDrawSurfaceImpl
*This
, DWORD dstx
,
3233 DWORD dsty
, LPDIRECTDRAWSURFACE7 src
,
3234 LPRECT rsrc
, DWORD trans
)
3238 IDirectDrawSurfaceImpl
*src_impl
= ICOM_OBJECT(IDirectDrawSurfaceImpl
, IDirectDrawSurface7
, src
);
3239 IDirect3DDeviceGLImpl
*gl_d3d_dev
= (IDirect3DDeviceGLImpl
*) This
->d3ddevice
;
3240 WINE_GL_BUFFER_TYPE buffer_type
;
3244 int width
, height
, x
, y
;
3246 /* Cannot support DSTCOLORKEY blitting... */
3247 if ((trans
& DDBLTFAST_DESTCOLORKEY
) != 0) return DDERR_INVALIDPARAMS
;
3250 WARN("rsrc is NULL - getting the whole surface !!\n");
3252 rsrc
->left
= rsrc
->top
= 0;
3253 rsrc
->right
= src_impl
->surface_desc
.dwWidth
;
3254 rsrc
->bottom
= src_impl
->surface_desc
.dwHeight
;
3262 rdst
.right
= dstx
+ (rsrc
->right
- rsrc
->left
);
3263 if (rdst
.right
> This
->surface_desc
.dwWidth
) {
3264 rsrc
->right
-= (This
->surface_desc
.dwWidth
- rdst
.right
);
3265 rdst
.right
= This
->surface_desc
.dwWidth
;
3267 rdst
.bottom
= dsty
+ (rsrc
->bottom
- rsrc
->top
);
3268 if (rdst
.bottom
> This
->surface_desc
.dwHeight
) {
3269 rsrc
->bottom
-= (This
->surface_desc
.dwHeight
- rdst
.bottom
);
3270 rdst
.bottom
= This
->surface_desc
.dwHeight
;
3273 width
= rsrc
->right
- rsrc
->left
;
3274 height
= rsrc
->bottom
- rsrc
->top
;
3276 if (setup_rect_and_surface_for_blt(This
, &buffer_type
, (D3DRECT
*) &rdst
) != DD_OK
) return DDERR_INVALIDPARAMS
;
3278 TRACE(" using BltFast memory to frame buffer override.\n");
3282 opt_bitmap
= d3ddevice_set_state_for_flush(This
->d3ddevice
, &rdst
, (trans
& DDBLTFAST_SRCCOLORKEY
) != 0, &initial
);
3284 if (upload_surface_to_tex_memory_init(src_impl
, 0, &gl_d3d_dev
->current_internal_format
,
3285 initial
, (trans
& DDBLTFAST_SRCCOLORKEY
) != 0,
3286 UNLOCK_TEX_SIZE
, UNLOCK_TEX_SIZE
) != DD_OK
) {
3287 ERR(" unsupported pixel format at memory to buffer Blt override.\n");
3289 return DDERR_INVALIDPARAMS
;
3292 glGetIntegerv(GL_DRAW_BUFFER
, &prev_draw
);
3293 if (buffer_type
== WINE_GL_BUFFER_FRONT
)
3294 glDrawBuffer(GL_FRONT
);
3296 glDrawBuffer(GL_BACK
);
3298 /* Now the serious stuff happens. This is basically the same code that for the memory
3299 flush to frame buffer but with different rectangles for source and destination :-) */
3300 for (y
= 0; y
< height
; y
+= UNLOCK_TEX_SIZE
) {
3303 flush_rect
.top
= rsrc
->top
+ y
;
3304 flush_rect
.bottom
= ((rsrc
->top
+ y
+ UNLOCK_TEX_SIZE
> rsrc
->bottom
) ?
3306 (rsrc
->top
+ y
+ UNLOCK_TEX_SIZE
));
3308 for (x
= 0; x
< width
; x
+= UNLOCK_TEX_SIZE
) {
3309 flush_rect
.left
= rsrc
->left
+ x
;
3310 flush_rect
.right
= ((rsrc
->left
+ x
+ UNLOCK_TEX_SIZE
> rsrc
->right
) ?
3312 (rsrc
->left
+ x
+ UNLOCK_TEX_SIZE
));
3314 upload_surface_to_tex_memory(&flush_rect
, 0, 0, &(gl_d3d_dev
->surface_ptr
));
3317 glTexCoord2f(0.0, 0.0);
3318 glVertex3d(rdst
.left
+ x
,
3321 glTexCoord2f(1.0, 0.0);
3322 glVertex3d(rdst
.left
+ (x
+ UNLOCK_TEX_SIZE
),
3325 glTexCoord2f(1.0, 1.0);
3326 glVertex3d(rdst
.left
+ (x
+ UNLOCK_TEX_SIZE
),
3327 rdst
.top
+ (y
+ UNLOCK_TEX_SIZE
),
3329 glTexCoord2f(0.0, 1.0);
3330 glVertex3d(rdst
.left
+ x
,
3331 rdst
.top
+ (y
+ UNLOCK_TEX_SIZE
),
3337 upload_surface_to_tex_memory_release();
3338 d3ddevice_restore_state_after_flush(This
->d3ddevice
, opt_bitmap
, (trans
& DDBLTFAST_SRCCOLORKEY
) != 0);
3340 if (((buffer_type
== WINE_GL_BUFFER_FRONT
) && (prev_draw
== GL_BACK
)) ||
3341 ((buffer_type
== WINE_GL_BUFFER_BACK
) && (prev_draw
== GL_FRONT
)))
3342 glDrawBuffer(prev_draw
);
3350 d3ddevice_set_ortho(IDirect3DDeviceImpl
*This
)
3352 GLfloat height
, width
;
3353 GLfloat trans_mat
[16];
3355 TRACE("(%p)\n", This
);
3357 width
= This
->surface
->surface_desc
.dwWidth
;
3358 height
= This
->surface
->surface_desc
.dwHeight
;
3360 /* The X axis is straighforward.. For the Y axis, we need to convert 'D3D' screen coordinates
3361 * to OpenGL screen coordinates (ie the upper left corner is not the same).
3363 trans_mat
[ 0] = 2.0 / width
; trans_mat
[ 4] = 0.0; trans_mat
[ 8] = 0.0; trans_mat
[12] = -1.0;
3364 trans_mat
[ 1] = 0.0; trans_mat
[ 5] = -2.0 / height
; trans_mat
[ 9] = 0.0; trans_mat
[13] = 1.0;
3366 /* It has been checked that in Messiah, which mixes XYZ and XYZRHZ vertex format in the same scene,
3367 * that the Z coordinate needs to be given to GL unchanged.
3369 trans_mat
[ 2] = 0.0; trans_mat
[ 6] = 0.0; trans_mat
[10] = 2.0; trans_mat
[14] = -1.0;
3371 trans_mat
[ 2] = 0.0; trans_mat
[ 6] = 0.0; trans_mat
[10] = 1.0; trans_mat
[14] = 0.0;
3372 trans_mat
[ 3] = 0.0; trans_mat
[ 7] = 0.0; trans_mat
[11] = 0.0; trans_mat
[15] = 1.0;
3375 glMatrixMode(GL_MODELVIEW
);
3377 /* See the OpenGL Red Book for an explanation of the following translation (in the OpenGL
3378 Correctness Tips section).
3380 Basically, from what I understood, if the game does not filter the font texture,
3381 as the 'real' pixel will lie at the middle of the two texels, OpenGL may choose the wrong
3382 one and we will have strange artifacts (as the rounding and stuff may give different results
3383 for different pixels, ie sometimes take the left pixel, sometimes the right).
3385 glTranslatef(0.375, 0.375, 0);
3386 glMatrixMode(GL_PROJECTION
);
3387 glLoadMatrixf(trans_mat
);
3392 d3ddevice_set_matrices(IDirect3DDeviceImpl
*This
, DWORD matrices
,
3393 D3DMATRIX
*world_mat
, D3DMATRIX
*view_mat
, D3DMATRIX
*proj_mat
)
3395 TRACE("(%p,%08lx,%p,%p,%p)\n", This
, matrices
, world_mat
, view_mat
, proj_mat
);
3398 if ((matrices
& (VIEWMAT_CHANGED
|WORLDMAT_CHANGED
)) != 0) {
3399 glMatrixMode(GL_MODELVIEW
);
3400 glLoadMatrixf((float *) view_mat
);
3402 /* Now also re-loads all the Lights and Clipping Planes using the new matrices */
3403 if (This
->state_block
.render_state
[D3DRENDERSTATE_CLIPPING
- 1] != FALSE
) {
3406 for (i
= 0, runner
= 0x00000001; i
< This
->max_clipping_planes
; i
++, runner
<<= 1) {
3407 if (runner
& This
->state_block
.render_state
[D3DRENDERSTATE_CLIPPLANEENABLE
- 1]) {
3410 plane
[0] = This
->clipping_planes
[i
].plane
[0];
3411 plane
[1] = This
->clipping_planes
[i
].plane
[1];
3412 plane
[2] = This
->clipping_planes
[i
].plane
[2];
3413 plane
[3] = This
->clipping_planes
[i
].plane
[3];
3415 glClipPlane( GL_CLIP_PLANE0
+ i
, (const GLdouble
*) (&plane
) );
3419 if (This
->state_block
.render_state
[D3DRENDERSTATE_LIGHTING
- 1] != FALSE
) {
3423 for (i
= 0, runner
= 0x00000001; i
< MAX_LIGHTS
; i
++, runner
<<= 1) {
3424 if (runner
& This
->active_lights
) {
3425 switch (This
->light_parameters
[i
].dltType
) {
3426 case D3DLIGHT_DIRECTIONAL
: {
3428 float cut_off
= 180.0;
3430 glLightfv(GL_LIGHT0
+ i
, GL_AMBIENT
, (float *) &(This
->light_parameters
[i
].dcvAmbient
));
3431 glLightfv(GL_LIGHT0
+ i
, GL_DIFFUSE
, (float *) &(This
->light_parameters
[i
].dcvDiffuse
));
3432 glLightfv(GL_LIGHT0
+ i
, GL_SPECULAR
, (float *) &(This
->light_parameters
[i
].dcvSpecular
));
3433 glLightfv(GL_LIGHT0
+ i
, GL_SPOT_CUTOFF
, &cut_off
);
3435 direction
[0] = This
->light_parameters
[i
].dvDirection
.u1
.x
;
3436 direction
[1] = This
->light_parameters
[i
].dvDirection
.u2
.y
;
3437 direction
[2] = This
->light_parameters
[i
].dvDirection
.u3
.z
;
3439 glLightfv(GL_LIGHT0
+ i
, GL_POSITION
, (float *) direction
);
3442 case D3DLIGHT_POINT
: {
3444 float cut_off
= 180.0;
3446 glLightfv(GL_LIGHT0
+ i
, GL_AMBIENT
, (float *) &(This
->light_parameters
[i
].dcvAmbient
));
3447 glLightfv(GL_LIGHT0
+ i
, GL_DIFFUSE
, (float *) &(This
->light_parameters
[i
].dcvDiffuse
));
3448 glLightfv(GL_LIGHT0
+ i
, GL_SPECULAR
, (float *) &(This
->light_parameters
[i
].dcvSpecular
));
3449 position
[0] = This
->light_parameters
[i
].dvPosition
.u1
.x
;
3450 position
[1] = This
->light_parameters
[i
].dvPosition
.u2
.y
;
3451 position
[2] = This
->light_parameters
[i
].dvPosition
.u3
.z
;
3453 glLightfv(GL_LIGHT0
+ i
, GL_POSITION
, (float *) position
);
3454 glLightfv(GL_LIGHT0
+ i
, GL_CONSTANT_ATTENUATION
, &(This
->light_parameters
[i
].dvAttenuation0
));
3455 glLightfv(GL_LIGHT0
+ i
, GL_LINEAR_ATTENUATION
, &(This
->light_parameters
[i
].dvAttenuation1
));
3456 glLightfv(GL_LIGHT0
+ i
, GL_QUADRATIC_ATTENUATION
, &(This
->light_parameters
[i
].dvAttenuation2
));
3457 glLightfv(GL_LIGHT0
+ i
, GL_SPOT_CUTOFF
, &cut_off
);
3460 case D3DLIGHT_SPOT
: {
3463 float cut_off
= 90.0 * (This
->light_parameters
[i
].dvPhi
/ M_PI
);
3465 glLightfv(GL_LIGHT0
+ i
, GL_AMBIENT
, (float *) &(This
->light_parameters
[i
].dcvAmbient
));
3466 glLightfv(GL_LIGHT0
+ i
, GL_DIFFUSE
, (float *) &(This
->light_parameters
[i
].dcvDiffuse
));
3467 glLightfv(GL_LIGHT0
+ i
, GL_SPECULAR
, (float *) &(This
->light_parameters
[i
].dcvSpecular
));
3469 direction
[0] = This
->light_parameters
[i
].dvDirection
.u1
.x
;
3470 direction
[1] = This
->light_parameters
[i
].dvDirection
.u2
.y
;
3471 direction
[2] = This
->light_parameters
[i
].dvDirection
.u3
.z
;
3473 glLightfv(GL_LIGHT0
+ i
, GL_SPOT_DIRECTION
, (float *) direction
);
3474 position
[0] = This
->light_parameters
[i
].dvPosition
.u1
.x
;
3475 position
[1] = This
->light_parameters
[i
].dvPosition
.u2
.y
;
3476 position
[2] = This
->light_parameters
[i
].dvPosition
.u3
.z
;
3478 glLightfv(GL_LIGHT0
+ i
, GL_POSITION
, (float *) position
);
3479 glLightfv(GL_LIGHT0
+ i
, GL_CONSTANT_ATTENUATION
, &(This
->light_parameters
[i
].dvAttenuation0
));
3480 glLightfv(GL_LIGHT0
+ i
, GL_LINEAR_ATTENUATION
, &(This
->light_parameters
[i
].dvAttenuation1
));
3481 glLightfv(GL_LIGHT0
+ i
, GL_QUADRATIC_ATTENUATION
, &(This
->light_parameters
[i
].dvAttenuation2
));
3482 glLightfv(GL_LIGHT0
+ i
, GL_SPOT_CUTOFF
, &cut_off
);
3483 glLightfv(GL_LIGHT0
+ i
, GL_SPOT_EXPONENT
, &(This
->light_parameters
[i
].dvFalloff
));
3487 /* No warning here as it's already done at light setting */
3494 glMultMatrixf((float *) world_mat
);
3496 if ((matrices
& PROJMAT_CHANGED
) != 0) {
3497 glMatrixMode(GL_PROJECTION
);
3498 glLoadMatrixf((float *) proj_mat
);
3504 d3ddevice_matrices_updated(IDirect3DDeviceImpl
*This
, DWORD matrices
)
3506 IDirect3DDeviceGLImpl
*glThis
= (IDirect3DDeviceGLImpl
*) This
;
3507 DWORD tex_mat
, tex_stage
;
3509 TRACE("(%p,%08lx)\n", This
, matrices
);
3511 if (matrices
& (VIEWMAT_CHANGED
|WORLDMAT_CHANGED
|PROJMAT_CHANGED
)) {
3512 if (glThis
->transform_state
== GL_TRANSFORM_NORMAL
) {
3513 /* This will force an update of the transform state at the next drawing. */
3514 glThis
->transform_state
= GL_TRANSFORM_NONE
;
3517 if (matrices
& (TEXMAT0_CHANGED
|TEXMAT1_CHANGED
|TEXMAT2_CHANGED
|TEXMAT3_CHANGED
|
3518 TEXMAT4_CHANGED
|TEXMAT5_CHANGED
|TEXMAT6_CHANGED
|TEXMAT7_CHANGED
))
3521 for (tex_mat
= TEXMAT0_CHANGED
, tex_stage
= 0; tex_mat
<= TEXMAT7_CHANGED
; tex_mat
<<= 1, tex_stage
++) {
3522 GLenum unit
= GL_TEXTURE0_WINE
+ tex_stage
;
3523 if (matrices
& tex_mat
) {
3524 if (This
->state_block
.texture_stage_state
[tex_stage
][D3DTSS_TEXTURETRANSFORMFLAGS
- 1] != D3DTTFF_DISABLE
) {
3525 int is_identity
= (memcmp(This
->tex_mat
[tex_stage
], id_mat
, 16 * sizeof(D3DVALUE
)) != 0);
3527 if (This
->tex_mat_is_identity
[tex_stage
] != is_identity
) {
3528 if (glThis
->current_active_tex_unit
!= unit
) {
3529 GL_extensions
.glActiveTexture(unit
);
3530 glThis
->current_active_tex_unit
= unit
;
3532 glMatrixMode(GL_TEXTURE
);
3533 glLoadMatrixf((float *) This
->tex_mat
[tex_stage
]);
3535 This
->tex_mat_is_identity
[tex_stage
] = is_identity
;
3537 if (This
->tex_mat_is_identity
[tex_stage
] == FALSE
) {
3538 if (glThis
->current_active_tex_unit
!= unit
) {
3539 GL_extensions
.glActiveTexture(unit
);
3540 glThis
->current_active_tex_unit
= unit
;
3542 glMatrixMode(GL_TEXTURE
);
3544 This
->tex_mat_is_identity
[tex_stage
] = TRUE
;
3553 /* TODO for both these functions :
3554 - change / restore OpenGL parameters for pictures transfers in case they are ever modified
3555 by other OpenGL code in D3D
3556 - handle the case where no 'Begin / EndScene' was done between two locks
3557 - handle the rectangles in the unlock too
3558 - handle pitch correctly...
3560 static void d3ddevice_lock_update(IDirectDrawSurfaceImpl
* This
, LPCRECT pRect
, DWORD dwFlags
)
3562 IDirect3DDeviceImpl
*d3d_dev
= This
->d3ddevice
;
3563 IDirect3DDeviceGLImpl
* gl_d3d_dev
= (IDirect3DDeviceGLImpl
*) d3d_dev
;
3564 WINE_GL_BUFFER_TYPE buffer_type
;
3567 if ((This
->surface_desc
.ddsCaps
.dwCaps
& (DDSCAPS_FRONTBUFFER
|DDSCAPS_PRIMARYSURFACE
)) != 0) {
3568 buffer_type
= WINE_GL_BUFFER_FRONT
;
3569 if ((gl_d3d_dev
->state
[WINE_GL_BUFFER_FRONT
] != SURFACE_GL
) &&
3570 (gl_d3d_dev
->lock_surf
[WINE_GL_BUFFER_FRONT
] != This
)) {
3571 ERR("Change of front buffer.. Expect graphic corruptions !\n");
3573 gl_d3d_dev
->lock_surf
[WINE_GL_BUFFER_FRONT
] = This
;
3574 } else if ((This
->surface_desc
.ddsCaps
.dwCaps
& (DDSCAPS_BACKBUFFER
)) == (DDSCAPS_BACKBUFFER
)) {
3575 buffer_type
= WINE_GL_BUFFER_BACK
;
3576 if ((gl_d3d_dev
->state
[WINE_GL_BUFFER_BACK
] != SURFACE_GL
) &&
3577 (gl_d3d_dev
->lock_surf
[WINE_GL_BUFFER_BACK
] != This
)) {
3578 ERR("Change of back buffer.. Expect graphic corruptions !\n");
3580 gl_d3d_dev
->lock_surf
[WINE_GL_BUFFER_BACK
] = This
;
3582 ERR("Wrong surface type for locking !\n");
3586 if (pRect
== NULL
) {
3589 loc_rect
.bottom
= This
->surface_desc
.dwHeight
;
3590 loc_rect
.right
= This
->surface_desc
.dwWidth
;
3594 /* Try to acquire the device critical section */
3595 EnterCriticalSection(&(d3d_dev
->crit
));
3597 if (gl_d3d_dev
->lock_rect_valid
[buffer_type
]) {
3598 ERR("Two consecutive locks on %s buffer... Expect problems !\n",
3599 (buffer_type
== WINE_GL_BUFFER_BACK
? "back" : "front"));
3601 gl_d3d_dev
->lock_rect_valid
[buffer_type
] = TRUE
;
3603 if (gl_d3d_dev
->state
[buffer_type
] != SURFACE_GL
) {
3604 /* Check if the new rectangle is in the previous one or not.
3605 If it is not, flush first the previous locks on screen.
3607 if ((pRect
->top
< gl_d3d_dev
->lock_rect
[buffer_type
].top
) ||
3608 (pRect
->left
< gl_d3d_dev
->lock_rect
[buffer_type
].left
) ||
3609 (pRect
->right
> gl_d3d_dev
->lock_rect
[buffer_type
].right
) ||
3610 (pRect
->bottom
> gl_d3d_dev
->lock_rect
[buffer_type
].bottom
)) {
3611 if (gl_d3d_dev
->state
[buffer_type
] == SURFACE_MEMORY_DIRTY
) {
3612 TRACE(" flushing back to %s buffer as new rect : (%ldx%ld) - (%ldx%ld) not included in old rect : (%ldx%ld) - (%ldx%ld)\n",
3613 (buffer_type
== WINE_GL_BUFFER_BACK
? "back" : "front"),
3614 pRect
->left
, pRect
->top
, pRect
->right
, pRect
->bottom
,
3615 gl_d3d_dev
->lock_rect
[buffer_type
].left
, gl_d3d_dev
->lock_rect
[buffer_type
].top
,
3616 gl_d3d_dev
->lock_rect
[buffer_type
].right
, gl_d3d_dev
->lock_rect
[buffer_type
].bottom
);
3617 d3d_dev
->flush_to_framebuffer(d3d_dev
, &(gl_d3d_dev
->lock_rect
[buffer_type
]), gl_d3d_dev
->lock_surf
[buffer_type
]);
3619 gl_d3d_dev
->state
[buffer_type
] = SURFACE_GL
;
3620 gl_d3d_dev
->lock_rect
[buffer_type
] = *pRect
;
3622 /* In the other case, do not upgrade the locking rectangle as it's no need... */
3624 gl_d3d_dev
->lock_rect
[buffer_type
] = *pRect
;
3627 if (gl_d3d_dev
->state
[buffer_type
] == SURFACE_GL
) {
3628 /* If the surface is already in memory, no need to do anything here... */
3629 GLenum buffer_format
;
3630 GLenum buffer_color
;
3634 TRACE(" copying %s buffer to main memory with rectangle (%ldx%ld) - (%ldx%ld).\n", (buffer_type
== WINE_GL_BUFFER_BACK
? "back" : "front"),
3635 pRect
->left
, pRect
->top
, pRect
->right
, pRect
->bottom
);
3637 /* Note that here we cannot do 'optmizations' about the WriteOnly flag... Indeed, a game
3638 may only write to the device... But when we will blit it back to the screen, we need
3639 also to blit correctly the parts the application did not overwrite... */
3641 if (((This
->surface_desc
.u4
.ddpfPixelFormat
.dwFlags
& DDPF_RGB
) != 0) &&
3642 (((This
->surface_desc
.u4
.ddpfPixelFormat
.dwFlags
& DDPF_ALPHAPIXELS
) == 0) ||
3643 (This
->surface_desc
.u4
.ddpfPixelFormat
.u5
.dwRGBAlphaBitMask
== 0x00000000))) {
3644 if ((This
->surface_desc
.u4
.ddpfPixelFormat
.u1
.dwRGBBitCount
== 16) &&
3645 (This
->surface_desc
.u4
.ddpfPixelFormat
.u2
.dwRBitMask
== 0xF800) &&
3646 (This
->surface_desc
.u4
.ddpfPixelFormat
.u3
.dwGBitMask
== 0x07E0) &&
3647 (This
->surface_desc
.u4
.ddpfPixelFormat
.u4
.dwBBitMask
== 0x001F)) {
3648 buffer_format
= GL_UNSIGNED_SHORT_5_6_5
;
3649 buffer_color
= GL_RGB
;
3650 } else if ((This
->surface_desc
.u4
.ddpfPixelFormat
.u1
.dwRGBBitCount
== 24) &&
3651 (This
->surface_desc
.u4
.ddpfPixelFormat
.u2
.dwRBitMask
== 0xFF0000) &&
3652 (This
->surface_desc
.u4
.ddpfPixelFormat
.u3
.dwGBitMask
== 0x00FF00) &&
3653 (This
->surface_desc
.u4
.ddpfPixelFormat
.u4
.dwBBitMask
== 0x0000FF)) {
3654 buffer_format
= GL_UNSIGNED_BYTE
;
3655 buffer_color
= GL_RGB
;
3656 } else if ((This
->surface_desc
.u4
.ddpfPixelFormat
.u1
.dwRGBBitCount
== 32) &&
3657 (This
->surface_desc
.u4
.ddpfPixelFormat
.u2
.dwRBitMask
== 0x00FF0000) &&
3658 (This
->surface_desc
.u4
.ddpfPixelFormat
.u3
.dwGBitMask
== 0x0000FF00) &&
3659 (This
->surface_desc
.u4
.ddpfPixelFormat
.u4
.dwBBitMask
== 0x000000FF)) {
3660 buffer_format
= GL_UNSIGNED_INT_8_8_8_8_REV
;
3661 buffer_color
= GL_BGRA
;
3663 ERR(" unsupported pixel format at device locking.\n");
3667 ERR(" unsupported pixel format at device locking - alpha on frame buffer.\n");
3673 if (buffer_type
== WINE_GL_BUFFER_FRONT
)
3674 /* Application wants to lock the front buffer */
3675 glReadBuffer(GL_FRONT
);
3677 /* Application wants to lock the back buffer */
3678 glReadBuffer(GL_BACK
);
3680 dst
= ((char *)This
->surface_desc
.lpSurface
) +
3681 (pRect
->top
* This
->surface_desc
.u1
.lPitch
) + (pRect
->left
* GET_BPP(This
->surface_desc
));
3683 if (This
->surface_desc
.u1
.lPitch
!= (GET_BPP(This
->surface_desc
) * This
->surface_desc
.dwWidth
)) {
3684 /* Slow-path in case of 'odd' surfaces. This could be fixed using some GL options, but I
3685 * could not be bothered considering the rare cases where it may be useful :-)
3687 for (y
= (This
->surface_desc
.dwHeight
- pRect
->top
- 1);
3688 y
>= ((int) This
->surface_desc
.dwHeight
- (int) pRect
->bottom
);
3690 glReadPixels(pRect
->left
, y
,
3691 pRect
->right
- pRect
->left
, 1,
3692 buffer_color
, buffer_format
, dst
);
3693 dst
+= This
->surface_desc
.u1
.lPitch
;
3696 /* Faster path for surface copy. Note that I can use static variables here as I am
3697 * protected by the OpenGL critical section so this function won't be called by
3698 * two threads at the same time.
3700 static char *buffer
= NULL
;
3701 static int buffer_width
= 0;
3702 char *dst2
= dst
+ ((pRect
->bottom
- pRect
->top
) - 1) * This
->surface_desc
.u1
.lPitch
;
3703 int current_width
= (pRect
->right
- pRect
->left
) * GET_BPP(This
->surface_desc
);
3705 glReadPixels(pRect
->left
, ((int) This
->surface_desc
.dwHeight
- (int) pRect
->bottom
),
3706 pRect
->right
- pRect
->left
, pRect
->bottom
- pRect
->top
,
3707 buffer_color
, buffer_format
, dst
);
3709 if (current_width
> buffer_width
) {
3710 if (buffer
!= NULL
) HeapFree(GetProcessHeap(), 0, buffer
);
3711 buffer_width
= current_width
;
3712 buffer
= HeapAlloc(GetProcessHeap(), 0, buffer_width
);
3714 for (y
= 0; y
< ((pRect
->bottom
- pRect
->top
) / 2); y
++) {
3715 memcpy(buffer
, dst
, current_width
);
3716 memcpy(dst
, dst2
, current_width
);
3717 memcpy(dst2
, buffer
, current_width
);
3718 dst
+= This
->surface_desc
.u1
.lPitch
;
3719 dst2
-= This
->surface_desc
.u1
.lPitch
;
3723 gl_d3d_dev
->state
[buffer_type
] = SURFACE_MEMORY
;
3726 /* I keep this code here as it's very useful to debug :-) */
3728 static int flush_count
= 0;
3732 if ((++flush_count
% 50) == 0) {
3733 sprintf(buf
, "lock_%06d.pnm", flush_count
);
3734 f
= fopen(buf
, "wb");
3735 DDRAW_dump_surface_to_disk(This
, f
);
3744 static void d3ddevice_flush_to_frame_buffer(IDirect3DDeviceImpl
*d3d_dev
, LPCRECT pRect
, IDirectDrawSurfaceImpl
*surf
) {
3746 IDirect3DDeviceGLImpl
* gl_d3d_dev
= (IDirect3DDeviceGLImpl
*) d3d_dev
;
3751 /* Note : no need here to lock the 'device critical section' as we are already protected by
3752 the GL critical section. */
3754 if (pRect
== NULL
) {
3757 loc_rect
.bottom
= d3d_dev
->surface
->surface_desc
.dwHeight
;
3758 loc_rect
.right
= d3d_dev
->surface
->surface_desc
.dwWidth
;
3762 TRACE(" flushing memory back to screen memory (%ld,%ld) x (%ld,%ld).\n", pRect
->top
, pRect
->left
, pRect
->right
, pRect
->bottom
);
3764 opt_bitmap
= d3ddevice_set_state_for_flush(d3d_dev
, pRect
, FALSE
, &initial
);
3766 if (upload_surface_to_tex_memory_init(surf
, 0, &gl_d3d_dev
->current_internal_format
,
3767 initial
, FALSE
, UNLOCK_TEX_SIZE
, UNLOCK_TEX_SIZE
) != DD_OK
) {
3768 ERR(" unsupported pixel format at frame buffer flush.\n");
3772 for (y
= pRect
->top
; y
< pRect
->bottom
; y
+= UNLOCK_TEX_SIZE
) {
3776 flush_rect
.bottom
= (y
+ UNLOCK_TEX_SIZE
> pRect
->bottom
) ? pRect
->bottom
: (y
+ UNLOCK_TEX_SIZE
);
3778 for (x
= pRect
->left
; x
< pRect
->right
; x
+= UNLOCK_TEX_SIZE
) {
3779 /* First, upload the texture... */
3780 flush_rect
.left
= x
;
3781 flush_rect
.right
= (x
+ UNLOCK_TEX_SIZE
> pRect
->right
) ? pRect
->right
: (x
+ UNLOCK_TEX_SIZE
);
3783 upload_surface_to_tex_memory(&flush_rect
, 0, 0, &(gl_d3d_dev
->surface_ptr
));
3786 glTexCoord2f(0.0, 0.0);
3787 glVertex3d(x
, y
, 0.5);
3788 glTexCoord2f(1.0, 0.0);
3789 glVertex3d(x
+ UNLOCK_TEX_SIZE
, y
, 0.5);
3790 glTexCoord2f(1.0, 1.0);
3791 glVertex3d(x
+ UNLOCK_TEX_SIZE
, y
+ UNLOCK_TEX_SIZE
, 0.5);
3792 glTexCoord2f(0.0, 1.0);
3793 glVertex3d(x
, y
+ UNLOCK_TEX_SIZE
, 0.5);
3798 upload_surface_to_tex_memory_release();
3799 d3ddevice_restore_state_after_flush(d3d_dev
, opt_bitmap
, FALSE
);
3802 /* I keep this code here as it's very useful to debug :-) */
3804 static int flush_count
= 0;
3808 if ((++flush_count
% 50) == 0) {
3809 sprintf(buf
, "flush_%06d.pnm", flush_count
);
3810 f
= fopen(buf
, "wb");
3811 DDRAW_dump_surface_to_disk(surf
, f
);
3817 static void d3ddevice_unlock_update(IDirectDrawSurfaceImpl
* This
, LPCRECT pRect
)
3819 WINE_GL_BUFFER_TYPE buffer_type
;
3820 IDirect3DDeviceImpl
*d3d_dev
= This
->d3ddevice
;
3821 IDirect3DDeviceGLImpl
* gl_d3d_dev
= (IDirect3DDeviceGLImpl
*) d3d_dev
;
3823 if ((This
->surface_desc
.ddsCaps
.dwCaps
& (DDSCAPS_FRONTBUFFER
|DDSCAPS_PRIMARYSURFACE
)) != 0) {
3824 buffer_type
= WINE_GL_BUFFER_FRONT
;
3825 } else if ((This
->surface_desc
.ddsCaps
.dwCaps
& (DDSCAPS_BACKBUFFER
)) == (DDSCAPS_BACKBUFFER
)) {
3826 buffer_type
= WINE_GL_BUFFER_BACK
;
3828 ERR("Wrong surface type for locking !\n");
3832 if (gl_d3d_dev
->lock_rect_valid
[buffer_type
] == FALSE
) {
3833 ERR("Unlock without prior lock on %s buffer... Expect problems !\n",
3834 (buffer_type
== WINE_GL_BUFFER_BACK
? "back" : "front"));
3836 gl_d3d_dev
->lock_rect_valid
[buffer_type
] = FALSE
;
3838 /* First, check if we need to do anything. For the backbuffer, flushing is done at the next 3D activity. */
3839 if ((This
->lastlocktype
& DDLOCK_READONLY
) == 0) {
3840 if (buffer_type
== WINE_GL_BUFFER_FRONT
) {
3843 TRACE(" flushing front buffer immediately on screen.\n");
3846 glGetIntegerv(GL_DRAW_BUFFER
, &prev_draw
);
3847 glDrawBuffer(GL_FRONT
);
3848 /* Note: we do not use the application provided lock rectangle but our own stored at
3849 lock time. This is because in old D3D versions, the 'lock' parameter did not
3852 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
]);
3853 glDrawBuffer(prev_draw
);
3856 gl_d3d_dev
->state
[WINE_GL_BUFFER_BACK
] = SURFACE_MEMORY_DIRTY
;
3860 /* And 'frees' the device critical section */
3861 LeaveCriticalSection(&(d3d_dev
->crit
));
3865 apply_texture_state(IDirect3DDeviceImpl
*This
)
3869 /* Initialize texture stages states */
3870 for (stage
= 0; stage
< MAX_TEXTURES
; stage
++) {
3871 for (state
= 0; state
< HIGHEST_TEXTURE_STAGE_STATE
; state
+= 1) {
3872 if (This
->state_block
.set_flags
.texture_stage_state
[stage
][state
]) {
3873 IDirect3DDevice7_SetTextureStageState(ICOM_INTERFACE(This
, IDirect3DDevice7
),
3874 stage
, state
+ 1, This
->state_block
.texture_stage_state
[stage
][state
]);
3881 d3ddevice_create(IDirect3DDeviceImpl
**obj
, IDirectDrawImpl
*d3d
, IDirectDrawSurfaceImpl
*surface
, int version
)
3883 IDirect3DDeviceImpl
*object
;
3884 IDirect3DDeviceGLImpl
*gl_object
;
3885 IDirectDrawSurfaceImpl
*surf
;
3890 XVisualInfo
template;
3891 GLenum buffer
= GL_FRONT
;
3894 object
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, sizeof(IDirect3DDeviceGLImpl
));
3895 if (object
== NULL
) return DDERR_OUTOFMEMORY
;
3897 gl_object
= (IDirect3DDeviceGLImpl
*) object
;
3901 object
->surface
= surface
;
3902 object
->set_context
= set_context
;
3903 object
->clear
= d3ddevice_clear_back
;
3904 object
->set_matrices
= d3ddevice_set_matrices
;
3905 object
->matrices_updated
= d3ddevice_matrices_updated
;
3906 object
->flush_to_framebuffer
= d3ddevice_flush_to_frame_buffer
;
3907 object
->version
= version
;
3909 TRACE(" creating OpenGL device for surface = %p, d3d = %p\n", surface
, d3d
);
3911 InitializeCriticalSection(&(object
->crit
));
3913 TRACE(" device critical section : %p\n", &(object
->crit
));
3915 device_context
= GetDC(surface
->ddraw_owner
->window
);
3916 gl_object
->display
= get_display(device_context
);
3917 gl_object
->drawable
= get_drawable(device_context
);
3918 ReleaseDC(surface
->ddraw_owner
->window
,device_context
);
3921 template.visualid
= (VisualID
)GetPropA( GetDesktopWindow(), "__wine_x11_visual_id" );
3922 vis
= XGetVisualInfo(gl_object
->display
, VisualIDMask
, &template, &num
);
3924 HeapFree(GetProcessHeap(), 0, object
);
3925 ERR("No visual found !\n");
3927 return DDERR_INVALIDPARAMS
;
3929 TRACE(" visual found\n");
3932 gl_object
->gl_context
= glXCreateContext(gl_object
->display
, vis
,
3935 if (gl_object
->gl_context
== NULL
) {
3936 HeapFree(GetProcessHeap(), 0, object
);
3937 ERR("Error in context creation !\n");
3939 return DDERR_INVALIDPARAMS
;
3941 TRACE(" context created (%p)\n", gl_object
->gl_context
);
3944 /* Look for the front buffer and override its surface's Flip method (if in double buffering) */
3945 for (surf
= surface
; surf
!= NULL
; surf
= surf
->surface_owner
) {
3946 if ((surf
->surface_desc
.ddsCaps
.dwCaps
&(DDSCAPS_FLIP
|DDSCAPS_FRONTBUFFER
)) == (DDSCAPS_FLIP
|DDSCAPS_FRONTBUFFER
)) {
3947 surf
->aux_ctx
= (LPVOID
) object
;
3948 surf
->aux_data
= (LPVOID
) gl_object
->drawable
;
3949 surf
->aux_flip
= opengl_flip
;
3954 /* We are not doing any double buffering.. Then force OpenGL to draw on the front buffer */
3956 TRACE(" no double buffering : drawing on the front buffer\n");
3960 for (surf
= surface
; surf
!= NULL
; surf
= surf
->surface_owner
) {
3961 IDirectDrawSurfaceImpl
*surf2
;
3962 for (surf2
= surf
; surf2
->prev_attached
!= NULL
; surf2
= surf2
->prev_attached
) ;
3963 for (; surf2
!= NULL
; surf2
= surf2
->next_attached
) {
3964 TRACE(" checking surface %p :", surf2
);
3965 if (((surf2
->surface_desc
.ddsCaps
.dwCaps
& (DDSCAPS_3DDEVICE
)) == (DDSCAPS_3DDEVICE
)) &&
3966 ((surf2
->surface_desc
.ddsCaps
.dwCaps
& (DDSCAPS_ZBUFFER
)) != (DDSCAPS_ZBUFFER
))) {
3967 /* Override the Lock / Unlock function for all these surfaces */
3968 surf2
->lock_update_prev
= surf2
->lock_update
;
3969 surf2
->lock_update
= d3ddevice_lock_update
;
3970 surf2
->unlock_update_prev
= surf2
->unlock_update
;
3971 surf2
->unlock_update
= d3ddevice_unlock_update
;
3972 /* And install also the blt / bltfast overrides */
3973 surf2
->aux_blt
= d3ddevice_blt
;
3974 surf2
->aux_bltfast
= d3ddevice_bltfast
;
3976 TRACE(" overriding direct surface access.\n");
3978 TRACE(" no override.\n");
3980 surf2
->d3ddevice
= object
;
3984 /* Set the various light parameters */
3985 for (light
= 0; light
< MAX_LIGHTS
; light
++) {
3986 /* Only set the fields that are not zero-created */
3987 object
->light_parameters
[light
].dltType
= D3DLIGHT_DIRECTIONAL
;
3988 object
->light_parameters
[light
].dcvDiffuse
.u1
.r
= 1.0;
3989 object
->light_parameters
[light
].dcvDiffuse
.u2
.g
= 1.0;
3990 object
->light_parameters
[light
].dcvDiffuse
.u3
.b
= 1.0;
3991 object
->light_parameters
[light
].dvDirection
.u3
.z
= 1.0;
3994 /* Allocate memory for the matrices */
3995 object
->world_mat
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, 16 * sizeof(float));
3996 object
->view_mat
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, 16 * sizeof(float));
3997 object
->proj_mat
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, 16 * sizeof(float));
3998 memcpy(object
->world_mat
, id_mat
, 16 * sizeof(float));
3999 memcpy(object
->view_mat
, id_mat
, 16 * sizeof(float));
4000 memcpy(object
->proj_mat
, id_mat
, 16 * sizeof(float));
4001 for (tex_num
= 0; tex_num
< MAX_TEXTURES
; tex_num
++) {
4002 object
->tex_mat
[tex_num
] = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, 16 * sizeof(float));
4003 memcpy(object
->tex_mat
[tex_num
], id_mat
, 16 * sizeof(float));
4004 object
->tex_mat_is_identity
[tex_num
] = TRUE
;
4007 /* Initialisation */
4008 TRACE(" setting current context\n");
4009 object
->set_context(object
);
4010 TRACE(" current context set\n");
4012 /* allocate the clipping planes */
4013 object
->max_clipping_planes
= opengl_device_caps
.wMaxUserClipPlanes
;
4014 object
->clipping_planes
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, object
->max_clipping_planes
* sizeof(d3d7clippingplane
));
4016 glHint(GL_FOG_HINT
,GL_NICEST
);
4018 /* Initialize the various GL contexts to be in sync with what we store locally */
4021 glClearColor(0.0, 0.0, 0.0, 0.0);
4022 glDepthMask(GL_TRUE
);
4023 gl_object
->depth_mask
= TRUE
;
4024 glEnable(GL_DEPTH_TEST
);
4025 gl_object
->depth_test
= TRUE
;
4026 glDisable(GL_ALPHA_TEST
);
4027 glDisable(GL_STENCIL_TEST
);
4028 glDisable(GL_CULL_FACE
);
4029 glDisable(GL_LIGHTING
);
4030 glDisable(GL_BLEND
);
4032 glTexEnvi(GL_TEXTURE_ENV
, GL_TEXTURE_ENV_MODE
, GL_REPLACE
);
4033 gl_object
->current_tex_env
= GL_REPLACE
;
4034 gl_object
->current_active_tex_unit
= GL_TEXTURE0_WINE
;
4035 if (GL_extensions
.glActiveTexture
!= NULL
) {
4036 GL_extensions
.glActiveTexture(GL_TEXTURE0_WINE
);
4038 gl_object
->current_alpha_test_ref
= 0.0;
4039 gl_object
->current_alpha_test_func
= GL_ALWAYS
;
4040 glAlphaFunc(GL_ALWAYS
, 0.0);
4042 glClear(GL_COLOR_BUFFER_BIT
| GL_DEPTH_BUFFER_BIT
| GL_STENCIL_BUFFER_BIT
);
4043 glDrawBuffer(buffer
);
4044 glReadBuffer(buffer
);
4045 /* glDisable(GL_DEPTH_TEST); Need here to check for the presence of a ZBuffer and to reenable it when the ZBuffer is attached */
4048 gl_object
->state
[WINE_GL_BUFFER_BACK
] = SURFACE_GL
;
4049 gl_object
->state
[WINE_GL_BUFFER_FRONT
] = SURFACE_GL
;
4051 /* fill_device_capabilities(d3d->ddraw); */
4053 ICOM_INIT_INTERFACE(object
, IDirect3DDevice
, VTABLE_IDirect3DDevice
);
4054 ICOM_INIT_INTERFACE(object
, IDirect3DDevice2
, VTABLE_IDirect3DDevice2
);
4055 ICOM_INIT_INTERFACE(object
, IDirect3DDevice3
, VTABLE_IDirect3DDevice3
);
4056 ICOM_INIT_INTERFACE(object
, IDirect3DDevice7
, VTABLE_IDirect3DDevice7
);
4060 TRACE(" creating implementation at %p.\n", *obj
);
4062 /* And finally warn D3D that this device is now present */
4063 object
->d3d
->d3d_added_device(object
->d3d
, object
);
4065 InitDefaultStateBlock(&object
->state_block
, object
->version
);
4066 /* Apply default render state and texture stage state values */
4067 apply_render_state(object
, &object
->state_block
);
4068 apply_texture_state(object
);
4070 /* And fill the fog table with the default fog value */
4071 build_fog_table(gl_object
->fog_table
, object
->state_block
.render_state
[D3DRENDERSTATE_FOGCOLOR
- 1]);
4076 static void fill_opengl_primcaps(D3DPRIMCAPS
*pc
)
4078 pc
->dwSize
= sizeof(*pc
);
4079 pc
->dwMiscCaps
= D3DPMISCCAPS_CONFORMANT
| D3DPMISCCAPS_CULLCCW
| D3DPMISCCAPS_CULLCW
|
4080 D3DPMISCCAPS_LINEPATTERNREP
| D3DPMISCCAPS_MASKPLANES
| D3DPMISCCAPS_MASKZ
;
4081 pc
->dwRasterCaps
= D3DPRASTERCAPS_DITHER
| D3DPRASTERCAPS_FOGRANGE
| D3DPRASTERCAPS_FOGTABLE
|
4082 D3DPRASTERCAPS_FOGVERTEX
| D3DPRASTERCAPS_STIPPLE
| D3DPRASTERCAPS_ZBIAS
| D3DPRASTERCAPS_ZTEST
| D3DPRASTERCAPS_SUBPIXEL
|
4083 D3DPRASTERCAPS_ZFOG
;
4084 if (GL_extensions
.mipmap_lodbias
) {
4085 pc
->dwRasterCaps
|= D3DPRASTERCAPS_MIPMAPLODBIAS
;
4087 pc
->dwZCmpCaps
= D3DPCMPCAPS_ALWAYS
| D3DPCMPCAPS_EQUAL
| D3DPCMPCAPS_GREATER
| D3DPCMPCAPS_GREATEREQUAL
|
4088 D3DPCMPCAPS_LESS
| D3DPCMPCAPS_LESSEQUAL
| D3DPCMPCAPS_NEVER
| D3DPCMPCAPS_NOTEQUAL
;
4089 pc
->dwSrcBlendCaps
= D3DPBLENDCAPS_ZERO
| D3DPBLENDCAPS_ONE
| D3DPBLENDCAPS_DESTCOLOR
| D3DPBLENDCAPS_INVDESTCOLOR
|
4090 D3DPBLENDCAPS_SRCALPHA
| D3DPBLENDCAPS_INVSRCALPHA
| D3DPBLENDCAPS_DESTALPHA
| D3DPBLENDCAPS_INVDESTALPHA
| D3DPBLENDCAPS_SRCALPHASAT
|
4091 D3DPBLENDCAPS_BOTHSRCALPHA
| D3DPBLENDCAPS_BOTHINVSRCALPHA
;
4092 pc
->dwDestBlendCaps
= D3DPBLENDCAPS_ZERO
| D3DPBLENDCAPS_ONE
| D3DPBLENDCAPS_SRCCOLOR
| D3DPBLENDCAPS_INVSRCCOLOR
|
4093 D3DPBLENDCAPS_SRCALPHA
| D3DPBLENDCAPS_INVSRCALPHA
| D3DPBLENDCAPS_DESTALPHA
| D3DPBLENDCAPS_INVDESTALPHA
| D3DPBLENDCAPS_SRCALPHASAT
|
4094 D3DPBLENDCAPS_BOTHSRCALPHA
| D3DPBLENDCAPS_BOTHINVSRCALPHA
;
4095 pc
->dwAlphaCmpCaps
= D3DPCMPCAPS_ALWAYS
| D3DPCMPCAPS_EQUAL
| D3DPCMPCAPS_GREATER
| D3DPCMPCAPS_GREATEREQUAL
|
4096 D3DPCMPCAPS_LESS
| D3DPCMPCAPS_LESSEQUAL
| D3DPCMPCAPS_NEVER
| D3DPCMPCAPS_NOTEQUAL
;
4097 pc
->dwShadeCaps
= D3DPSHADECAPS_ALPHAFLATBLEND
| D3DPSHADECAPS_ALPHAGOURAUDBLEND
| D3DPSHADECAPS_COLORFLATRGB
| D3DPSHADECAPS_COLORGOURAUDRGB
|
4098 D3DPSHADECAPS_FOGFLAT
| D3DPSHADECAPS_FOGGOURAUD
| D3DPSHADECAPS_SPECULARFLATRGB
| D3DPSHADECAPS_SPECULARGOURAUDRGB
;
4099 pc
->dwTextureCaps
= D3DPTEXTURECAPS_ALPHA
| D3DPTEXTURECAPS_ALPHAPALETTE
| D3DPTEXTURECAPS_BORDER
| D3DPTEXTURECAPS_PERSPECTIVE
|
4100 D3DPTEXTURECAPS_POW2
| D3DPTEXTURECAPS_TRANSPARENCY
;
4101 pc
->dwTextureFilterCaps
= D3DPTFILTERCAPS_LINEAR
| D3DPTFILTERCAPS_LINEARMIPLINEAR
| D3DPTFILTERCAPS_LINEARMIPNEAREST
|
4102 D3DPTFILTERCAPS_MIPLINEAR
| D3DPTFILTERCAPS_MIPNEAREST
| D3DPTFILTERCAPS_NEAREST
| D3DPTFILTERCAPS_MAGFLINEAR
|
4103 D3DPTFILTERCAPS_MAGFPOINT
| D3DPTFILTERCAPS_MINFLINEAR
| D3DPTFILTERCAPS_MINFPOINT
| D3DPTFILTERCAPS_MIPFLINEAR
|
4104 D3DPTFILTERCAPS_MIPFPOINT
;
4105 pc
->dwTextureBlendCaps
= D3DPTBLENDCAPS_ADD
| D3DPTBLENDCAPS_COPY
| D3DPTBLENDCAPS_DECAL
| D3DPTBLENDCAPS_DECALALPHA
| D3DPTBLENDCAPS_DECALMASK
|
4106 D3DPTBLENDCAPS_MODULATE
| D3DPTBLENDCAPS_MODULATEALPHA
| D3DPTBLENDCAPS_MODULATEMASK
;
4107 pc
->dwTextureAddressCaps
= D3DPTADDRESSCAPS_BORDER
| D3DPTADDRESSCAPS_CLAMP
| D3DPTADDRESSCAPS_WRAP
| D3DPTADDRESSCAPS_INDEPENDENTUV
;
4108 if (GL_extensions
.mirrored_repeat
) {
4109 pc
->dwTextureAddressCaps
|= D3DPTADDRESSCAPS_MIRROR
;
4111 pc
->dwStippleWidth
= 32;
4112 pc
->dwStippleHeight
= 32;
4115 static void fill_caps(void)
4117 GLint max_clip_planes
;
4120 /* Fill first all the fields with default values which will be overriden later on with
4121 correct ones from the GL code
4123 opengl_device_caps
.dwDevCaps
= D3DDEVCAPS_CANRENDERAFTERFLIP
| D3DDEVCAPS_DRAWPRIMTLVERTEX
| D3DDEVCAPS_EXECUTESYSTEMMEMORY
|
4124 D3DDEVCAPS_EXECUTEVIDEOMEMORY
| D3DDEVCAPS_FLOATTLVERTEX
| D3DDEVCAPS_TEXTURENONLOCALVIDMEM
| D3DDEVCAPS_TEXTURESYSTEMMEMORY
|
4125 D3DDEVCAPS_TEXTUREVIDEOMEMORY
| D3DDEVCAPS_TLVERTEXSYSTEMMEMORY
| D3DDEVCAPS_TLVERTEXVIDEOMEMORY
|
4126 /* D3D 7 capabilities */
4127 D3DDEVCAPS_DRAWPRIMITIVES2
/*| D3DDEVCAPS_HWTRANSFORMANDLIGHT*/ | D3DDEVCAPS_HWRASTERIZATION
| D3DDEVCAPS_DRAWPRIMITIVES2EX
;
4128 fill_opengl_primcaps(&(opengl_device_caps
.dpcLineCaps
));
4129 fill_opengl_primcaps(&(opengl_device_caps
.dpcTriCaps
));
4130 opengl_device_caps
.dwDeviceRenderBitDepth
= DDBD_16
|DDBD_24
|DDBD_32
;
4131 opengl_device_caps
.dwMinTextureWidth
= 1;
4132 opengl_device_caps
.dwMinTextureHeight
= 1;
4133 opengl_device_caps
.dwMaxTextureWidth
= 1024;
4134 opengl_device_caps
.dwMaxTextureHeight
= 1024;
4135 opengl_device_caps
.dwMaxTextureRepeat
= 16;
4136 opengl_device_caps
.dwMaxTextureAspectRatio
= 1024;
4137 opengl_device_caps
.dwMaxAnisotropy
= 0;
4138 opengl_device_caps
.dvGuardBandLeft
= 0.0;
4139 opengl_device_caps
.dvGuardBandRight
= 0.0;
4140 opengl_device_caps
.dvGuardBandTop
= 0.0;
4141 opengl_device_caps
.dvGuardBandBottom
= 0.0;
4142 opengl_device_caps
.dvExtentsAdjust
= 0.0;
4143 opengl_device_caps
.dwStencilCaps
= D3DSTENCILCAPS_DECRSAT
| D3DSTENCILCAPS_INCRSAT
| D3DSTENCILCAPS_INVERT
| D3DSTENCILCAPS_KEEP
|
4144 D3DSTENCILCAPS_REPLACE
| D3DSTENCILCAPS_ZERO
;
4145 opengl_device_caps
.dwTextureOpCaps
= D3DTEXOPCAPS_DISABLE
| D3DTEXOPCAPS_SELECTARG1
| D3DTEXOPCAPS_SELECTARG2
| D3DTEXOPCAPS_MODULATE4X
|
4146 D3DTEXOPCAPS_MODULATE2X
| D3DTEXOPCAPS_MODULATE
| D3DTEXOPCAPS_ADD
| D3DTEXOPCAPS_ADDSIGNED2X
| D3DTEXOPCAPS_ADDSIGNED
|
4147 D3DTEXOPCAPS_BLENDDIFFUSEALPHA
| D3DTEXOPCAPS_BLENDTEXTUREALPHA
| D3DTEXOPCAPS_BLENDFACTORALPHA
| D3DTEXOPCAPS_BLENDCURRENTALPHA
;
4148 if (GL_extensions
.max_texture_units
!= 0) {
4149 opengl_device_caps
.wMaxTextureBlendStages
= GL_extensions
.max_texture_units
;
4150 opengl_device_caps
.wMaxSimultaneousTextures
= GL_extensions
.max_texture_units
;
4151 opengl_device_caps
.dwFVFCaps
= D3DFVFCAPS_DONOTSTRIPELEMENTS
| GL_extensions
.max_texture_units
;
4153 opengl_device_caps
.wMaxTextureBlendStages
= 1;
4154 opengl_device_caps
.wMaxSimultaneousTextures
= 1;
4155 opengl_device_caps
.dwFVFCaps
= D3DFVFCAPS_DONOTSTRIPELEMENTS
| 1;
4157 opengl_device_caps
.dwMaxActiveLights
= 16;
4158 opengl_device_caps
.dvMaxVertexW
= 100000000.0; /* No idea exactly what to put here... */
4159 opengl_device_caps
.deviceGUID
= IID_IDirect3DTnLHalDevice
;
4160 opengl_device_caps
.wMaxUserClipPlanes
= 1;
4161 opengl_device_caps
.wMaxVertexBlendMatrices
= 0;
4162 opengl_device_caps
.dwVertexProcessingCaps
= D3DVTXPCAPS_TEXGEN
| D3DVTXPCAPS_MATERIALSOURCE7
| D3DVTXPCAPS_VERTEXFOG
|
4163 D3DVTXPCAPS_DIRECTIONALLIGHTS
| D3DVTXPCAPS_POSITIONALLIGHTS
| D3DVTXPCAPS_LOCALVIEWER
;
4164 opengl_device_caps
.dwReserved1
= 0;
4165 opengl_device_caps
.dwReserved2
= 0;
4166 opengl_device_caps
.dwReserved3
= 0;
4167 opengl_device_caps
.dwReserved4
= 0;
4169 /* And now some GL overrides :-) */
4170 glGetIntegerv(GL_MAX_TEXTURE_SIZE
, (GLint
*) &opengl_device_caps
.dwMaxTextureWidth
);
4171 opengl_device_caps
.dwMaxTextureHeight
= opengl_device_caps
.dwMaxTextureWidth
;
4172 opengl_device_caps
.dwMaxTextureAspectRatio
= opengl_device_caps
.dwMaxTextureWidth
;
4173 TRACE(": max texture size = %ld\n", opengl_device_caps
.dwMaxTextureWidth
);
4175 glGetIntegerv(GL_MAX_LIGHTS
, (GLint
*) &opengl_device_caps
.dwMaxActiveLights
);
4176 TRACE(": max active lights = %ld\n", opengl_device_caps
.dwMaxActiveLights
);
4178 glGetIntegerv(GL_MAX_CLIP_PLANES
, &max_clip_planes
);
4179 opengl_device_caps
.wMaxUserClipPlanes
= max_clip_planes
;
4180 TRACE(": max clipping planes = %d\n", opengl_device_caps
.wMaxUserClipPlanes
);
4182 glGetIntegerv(GL_DEPTH_BITS
, &depth_bits
);
4183 TRACE(": Z bits = %d\n", depth_bits
);
4184 switch (depth_bits
) {
4185 case 16: opengl_device_caps
.dwDeviceZBufferBitDepth
= DDBD_16
; break;
4186 case 24: opengl_device_caps
.dwDeviceZBufferBitDepth
= DDBD_16
|DDBD_24
; break;
4188 default: opengl_device_caps
.dwDeviceZBufferBitDepth
= DDBD_16
|DDBD_24
|DDBD_32
; break;
4193 d3ddevice_init_at_startup(void *gl_handle
)
4195 XVisualInfo
template;
4200 Drawable drawable
= (Drawable
) GetPropA(GetDesktopWindow(), "__wine_x11_whole_window");
4201 XWindowAttributes win_attr
;
4202 GLXContext gl_context
;
4204 const char *glExtensions
;
4205 const char *glVersion
;
4206 const char *glXExtensions
= NULL
;
4207 const void *(*pglXGetProcAddressARB
)(const GLubyte
*) = NULL
;
4208 int major
, minor
, patch
, num_parsed
;
4210 TRACE("Initializing GL...\n");
4214 WARN("x11drv not loaded - D3D support disabled!\n");
4218 /* Get a default rendering context to have the 'caps' function query some info from GL */
4219 device_context
= GetDC(0);
4220 display
= get_display(device_context
);
4221 ReleaseDC(0, device_context
);
4224 if (XGetWindowAttributes(display
, drawable
, &win_attr
)) {
4225 visual
= win_attr
.visual
;
4227 visual
= DefaultVisual(display
, DefaultScreen(display
));
4229 template.visualid
= XVisualIDFromVisual(visual
);
4230 vis
= XGetVisualInfo(display
, VisualIDMask
, &template, &num
);
4233 WARN("Error creating visual info for capabilities initialization - D3D support disabled !\n");
4236 gl_context
= glXCreateContext(display
, vis
, NULL
, GL_TRUE
);
4238 if (gl_context
== NULL
) {
4240 WARN("Error creating default context for capabilities initialization - D3D support disabled !\n");
4243 if (glXMakeCurrent(display
, drawable
, gl_context
) == False
) {
4244 glXDestroyContext(display
, gl_context
);
4246 WARN("Error setting default context as current for capabilities initialization - D3D support disabled !\n");
4250 /* Then, query all extensions */
4251 glXExtensions
= glXQueryExtensionsString(display
, DefaultScreen(display
)); /* Note: not used right now but will for PBuffers */
4252 glExtensions
= (const char *) glGetString(GL_EXTENSIONS
);
4253 glVersion
= (const char *) glGetString(GL_VERSION
);
4254 if (gl_handle
!= NULL
) {
4255 pglXGetProcAddressARB
= wine_dlsym(gl_handle
, "glXGetProcAddressARB", NULL
, 0);
4258 /* Parse the GL version string */
4259 num_parsed
= sscanf(glVersion
, "%d.%d.%d", &major
, &minor
, &patch
);
4260 if (num_parsed
== 1) {
4263 } else if (num_parsed
== 2) {
4266 TRACE("GL version %d.%d.%d\n", major
, minor
, patch
);
4268 /* And starts to fill the extension context properly */
4269 memset(&GL_extensions
, 0, sizeof(GL_extensions
));
4270 TRACE("GL supports following extensions used by Wine :\n");
4272 /* Mirrored Repeat extension :
4273 - GL_ARB_texture_mirrored_repeat
4274 - GL_IBM_texture_mirrored_repeat
4277 if ((strstr(glExtensions
, "GL_ARB_texture_mirrored_repeat")) ||
4278 (strstr(glExtensions
, "GL_IBM_texture_mirrored_repeat")) ||
4280 ((major
== 1) && (minor
>= 4))) {
4281 TRACE(" - mirrored repeat\n");
4282 GL_extensions
.mirrored_repeat
= TRUE
;
4285 /* Texture LOD Bias :
4286 - GL_EXT_texture_lod_bias
4288 if (strstr(glExtensions
, "GL_EXT_texture_lod_bias")) {
4289 TRACE(" - texture lod bias\n");
4290 GL_extensions
.mipmap_lodbias
= TRUE
;
4293 /* For all subsequent extensions, we need glXGetProcAddress */
4294 if (pglXGetProcAddressARB
!= NULL
) {
4295 /* Multi-texturing :
4296 - GL_ARB_multitexture
4299 if ((strstr(glExtensions
, "GL_ARB_multitexture")) ||
4301 ((major
== 1) && (minor
> 2)) ||
4302 ((major
== 1) && (minor
== 2) && (patch
>= 1))) {
4303 glGetIntegerv(GL_MAX_TEXTURE_UNITS_WINE
, &(GL_extensions
.max_texture_units
));
4304 TRACE(" - multi-texturing (%d stages)\n", GL_extensions
.max_texture_units
);
4305 /* We query the ARB version to be the most portable we can... */
4306 GL_extensions
.glActiveTexture
= pglXGetProcAddressARB("glActiveTextureARB");
4307 GL_extensions
.glMultiTexCoord2fv
= pglXGetProcAddressARB("glMultiTexCoord2fv");
4308 GL_extensions
.glClientActiveTexture
= pglXGetProcAddressARB("glClientActiveTextureARB");
4311 if (strstr(glExtensions
, "GL_EXT_texture_compression_s3tc")) {
4312 TRACE(" - S3TC compression supported\n");
4313 GL_extensions
.s3tc_compressed_texture
= TRUE
;
4314 GL_extensions
.glCompressedTexImage2D
= pglXGetProcAddressARB("glCompressedTexImage2D");
4315 GL_extensions
.glCompressedTexSubImage2D
= pglXGetProcAddressARB("glCompressedTexSubImage2D");
4319 /* Fill the D3D capabilities according to what GL tells us... */
4322 /* And frees this now-useless context */
4323 glXMakeCurrent(display
, None
, NULL
);
4324 glXDestroyContext(display
, gl_context
);