2 * IWineD3DDevice implementation
4 * Copyright 2002 Lionel Ulmer
5 * Copyright 2002-2005 Jason Edmeades
6 * Copyright 2003-2004 Raphael Junqueira
7 * Copyright 2004 Christian Costa
8 * Copyright 2005 Oliver Stieber
9 * Copyright 2006 Stefan Dösinger for CodeWeavers
11 * This library is free software; you can redistribute it and/or
12 * modify it under the terms of the GNU Lesser General Public
13 * License as published by the Free Software Foundation; either
14 * version 2.1 of the License, or (at your option) any later version.
16 * This library is distributed in the hope that it will be useful,
17 * but WITHOUT ANY WARRANTY; without even the implied warranty of
18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
19 * Lesser General Public License for more details.
21 * You should have received a copy of the GNU Lesser General Public
22 * License along with this library; if not, write to the Free Software
23 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
31 #include "wined3d_private.h"
33 WINE_DEFAULT_DEBUG_CHANNEL(d3d
);
34 WINE_DECLARE_DEBUG_CHANNEL(d3d_shader
);
35 #define GLINFO_LOCATION ((IWineD3DImpl *)(This->wineD3D))->gl_info
37 /* Define the default light parameters as specified by MSDN */
38 const WINED3DLIGHT WINED3D_default_light
= {
40 D3DLIGHT_DIRECTIONAL
, /* Type */
41 { 1.0, 1.0, 1.0, 0.0 }, /* Diffuse r,g,b,a */
42 { 0.0, 0.0, 0.0, 0.0 }, /* Specular r,g,b,a */
43 { 0.0, 0.0, 0.0, 0.0 }, /* Ambient r,g,b,a, */
44 { 0.0, 0.0, 0.0 }, /* Position x,y,z */
45 { 0.0, 0.0, 1.0 }, /* Direction x,y,z */
48 0.0, 0.0, 0.0, /* Attenuation 0,1,2 */
53 /* x11drv GDI escapes */
54 #define X11DRV_ESCAPE 6789
55 enum x11drv_escape_codes
57 X11DRV_GET_DISPLAY
, /* get X11 display for a DC */
58 X11DRV_GET_DRAWABLE
, /* get current drawable for a DC */
59 X11DRV_GET_FONT
, /* get current X font for a DC */
62 /* retrieve the X display to use on a given DC */
63 inline static Display
*get_display( HDC hdc
)
66 enum x11drv_escape_codes escape
= X11DRV_GET_DISPLAY
;
68 if (!ExtEscape( hdc
, X11DRV_ESCAPE
, sizeof(escape
), (LPCSTR
)&escape
,
69 sizeof(display
), (LPSTR
)&display
)) display
= NULL
;
73 /* TODO: setup some flags in the regestry to enable, disable pbuffer support */
74 /* enable pbuffer support for offscreen textures */
75 BOOL pbuffer_support
= FALSE
;
76 /* allocate one pbuffer per surface */
77 BOOL pbuffer_per_surface
= FALSE
;
79 /* static function declarations */
80 static void WINAPI
IWineD3DDeviceImpl_AddResource(IWineD3DDevice
*iface
, IWineD3DResource
*resource
);
82 static void WINAPI
IWineD3DDeviceImpl_ApplyTextureUnitState(IWineD3DDevice
*iface
, DWORD Stage
, WINED3DTEXTURESTAGESTATETYPE Type
);
85 #define D3DMEMCHECK(object, ppResult) if(NULL == object) { *ppResult = NULL; WARN("Out of memory\n"); return WINED3DERR_OUTOFVIDEOMEMORY;}
87 #define D3DCREATEOBJECTINSTANCE(object, type) { \
88 object=HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(IWineD3D##type##Impl)); \
89 D3DMEMCHECK(object, pp##type); \
90 object->lpVtbl = &IWineD3D##type##_Vtbl; \
91 object->wineD3DDevice = This; \
92 object->parent = parent; \
94 *pp##type = (IWineD3D##type *) object; \
97 #define D3DCREATERESOURCEOBJECTINSTANCE(object, type, d3dtype, _size){ \
98 object=HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(IWineD3D##type##Impl)); \
99 D3DMEMCHECK(object, pp##type); \
100 object->lpVtbl = &IWineD3D##type##_Vtbl; \
101 object->resource.wineD3DDevice = This; \
102 object->resource.parent = parent; \
103 object->resource.resourceType = d3dtype; \
104 object->resource.ref = 1; \
105 object->resource.pool = Pool; \
106 object->resource.format = Format; \
107 object->resource.usage = Usage; \
108 object->resource.size = _size; \
109 /* Check that we have enough video ram left */ \
110 if (Pool == WINED3DPOOL_DEFAULT) { \
111 if (IWineD3DDevice_GetAvailableTextureMem(iface) <= _size) { \
112 WARN("Out of 'bogus' video memory\n"); \
113 HeapFree(GetProcessHeap(), 0, object); \
115 return WINED3DERR_OUTOFVIDEOMEMORY; \
117 globalChangeGlRam(_size); \
119 object->resource.allocatedMemory = (0 == _size ? NULL : Pool == WINED3DPOOL_DEFAULT ? NULL : HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, _size)); \
120 if (object->resource.allocatedMemory == NULL && _size != 0 && Pool != WINED3DPOOL_DEFAULT) { \
121 FIXME("Out of memory!\n"); \
122 HeapFree(GetProcessHeap(), 0, object); \
124 return WINED3DERR_OUTOFVIDEOMEMORY; \
126 *pp##type = (IWineD3D##type *) object; \
127 IWineD3DDeviceImpl_AddResource(iface, (IWineD3DResource *)object) ;\
128 TRACE("(%p) : Created resource %p\n", This, object); \
131 #define D3DINITIALIZEBASETEXTURE(_basetexture) { \
132 _basetexture.levels = Levels; \
133 _basetexture.filterType = (Usage & WINED3DUSAGE_AUTOGENMIPMAP) ? WINED3DTEXF_LINEAR : WINED3DTEXF_NONE; \
134 _basetexture.LOD = 0; \
135 _basetexture.dirty = TRUE; \
138 /**********************************************************
139 * Global variable / Constants follow
140 **********************************************************/
141 const float identity
[16] = {1,0,0,0, 0,1,0,0, 0,0,1,0, 0,0,0,1}; /* When needed for comparisons */
143 /**********************************************************
144 * Utility functions follow
145 **********************************************************/
146 /* Convert the D3DLIGHT properties into equivalent gl lights */
147 static void setup_light(IWineD3DDevice
*iface
, LONG Index
, PLIGHTINFOEL
*lightInfo
) {
150 float colRGBA
[] = {0.0, 0.0, 0.0, 0.0};
151 IWineD3DDeviceImpl
*This
= (IWineD3DDeviceImpl
*)iface
;
153 /* Light settings are affected by the model view in OpenGL, the View transform in direct3d*/
154 glMatrixMode(GL_MODELVIEW
);
156 glLoadMatrixf((float *)&This
->stateBlock
->transforms
[WINED3DTS_VIEW
].u
.m
[0][0]);
159 colRGBA
[0] = lightInfo
->OriginalParms
.Diffuse
.r
;
160 colRGBA
[1] = lightInfo
->OriginalParms
.Diffuse
.g
;
161 colRGBA
[2] = lightInfo
->OriginalParms
.Diffuse
.b
;
162 colRGBA
[3] = lightInfo
->OriginalParms
.Diffuse
.a
;
163 glLightfv(GL_LIGHT0
+Index
, GL_DIFFUSE
, colRGBA
);
164 checkGLcall("glLightfv");
167 colRGBA
[0] = lightInfo
->OriginalParms
.Specular
.r
;
168 colRGBA
[1] = lightInfo
->OriginalParms
.Specular
.g
;
169 colRGBA
[2] = lightInfo
->OriginalParms
.Specular
.b
;
170 colRGBA
[3] = lightInfo
->OriginalParms
.Specular
.a
;
171 glLightfv(GL_LIGHT0
+Index
, GL_SPECULAR
, colRGBA
);
172 checkGLcall("glLightfv");
175 colRGBA
[0] = lightInfo
->OriginalParms
.Ambient
.r
;
176 colRGBA
[1] = lightInfo
->OriginalParms
.Ambient
.g
;
177 colRGBA
[2] = lightInfo
->OriginalParms
.Ambient
.b
;
178 colRGBA
[3] = lightInfo
->OriginalParms
.Ambient
.a
;
179 glLightfv(GL_LIGHT0
+Index
, GL_AMBIENT
, colRGBA
);
180 checkGLcall("glLightfv");
182 /* Attenuation - Are these right? guessing... */
183 glLightf(GL_LIGHT0
+Index
, GL_CONSTANT_ATTENUATION
, lightInfo
->OriginalParms
.Attenuation0
);
184 checkGLcall("glLightf");
185 glLightf(GL_LIGHT0
+Index
, GL_LINEAR_ATTENUATION
, lightInfo
->OriginalParms
.Attenuation1
);
186 checkGLcall("glLightf");
188 if ((lightInfo
->OriginalParms
.Range
*lightInfo
->OriginalParms
.Range
) >= FLT_MIN
) {
189 quad_att
= 1.4/(lightInfo
->OriginalParms
.Range
*lightInfo
->OriginalParms
.Range
);
191 quad_att
= 0; /* 0 or MAX? (0 seems to be ok) */
194 if (quad_att
< lightInfo
->OriginalParms
.Attenuation2
) quad_att
= lightInfo
->OriginalParms
.Attenuation2
;
195 glLightf(GL_LIGHT0
+Index
, GL_QUADRATIC_ATTENUATION
, quad_att
);
196 checkGLcall("glLightf");
198 switch (lightInfo
->OriginalParms
.Type
) {
201 glLightfv(GL_LIGHT0
+Index
, GL_POSITION
, &lightInfo
->lightPosn
[0]);
202 checkGLcall("glLightfv");
203 glLightf(GL_LIGHT0
+ Index
, GL_SPOT_CUTOFF
, lightInfo
->cutoff
);
204 checkGLcall("glLightf");
210 glLightfv(GL_LIGHT0
+Index
, GL_POSITION
, &lightInfo
->lightPosn
[0]);
211 checkGLcall("glLightfv");
213 glLightfv(GL_LIGHT0
+Index
, GL_SPOT_DIRECTION
, &lightInfo
->lightDirn
[0]);
214 checkGLcall("glLightfv");
215 glLightf(GL_LIGHT0
+ Index
, GL_SPOT_EXPONENT
, lightInfo
->exponent
);
216 checkGLcall("glLightf");
217 glLightf(GL_LIGHT0
+ Index
, GL_SPOT_CUTOFF
, lightInfo
->cutoff
);
218 checkGLcall("glLightf");
222 case D3DLIGHT_DIRECTIONAL
:
224 glLightfv(GL_LIGHT0
+Index
, GL_POSITION
, &lightInfo
->lightPosn
[0]); /* Note gl uses w position of 0 for direction! */
225 checkGLcall("glLightfv");
226 glLightf(GL_LIGHT0
+Index
, GL_SPOT_CUTOFF
, lightInfo
->cutoff
);
227 checkGLcall("glLightf");
228 glLightf(GL_LIGHT0
+Index
, GL_SPOT_EXPONENT
, 0.0f
);
229 checkGLcall("glLightf");
233 FIXME("Unrecognized light type %d\n", lightInfo
->OriginalParms
.Type
);
236 /* Restore the modelview matrix */
240 /**********************************************************
241 * GLSL helper functions follow
242 **********************************************************/
244 /** Attach a GLSL pixel or vertex shader object to the shader program */
245 static void attach_glsl_shader(IWineD3DDevice
*iface
, IWineD3DBaseShader
* shader
) {
247 IWineD3DDeviceImpl
*This
= (IWineD3DDeviceImpl
*)iface
;
248 GLhandleARB shaderObj
= ((IWineD3DBaseShaderImpl
*)shader
)->baseShader
.prgId
;
249 if (This
->stateBlock
->shaderPrgId
!= 0 && shaderObj
!= 0) {
250 TRACE_(d3d_shader
)("Attaching GLSL shader object %u to program %u\n", shaderObj
, This
->stateBlock
->shaderPrgId
);
251 GL_EXTCALL(glAttachObjectARB(This
->stateBlock
->shaderPrgId
, shaderObj
));
252 checkGLcall("glAttachObjectARB");
256 /** Sets the GLSL program ID for the given pixel and vertex shader combination.
257 * It sets the programId on the current StateBlock (because it should be called
258 * inside of the DrawPrimitive() part of the render loop).
260 * If a program for the given combination does not exist, create one, and store
261 * the program in the list. If it creates a program, it will link the given
264 * We keep the shader programs around on a list because linking
265 * shader objects together is an expensive operation. It's much
266 * faster to loop through a list of pre-compiled & linked programs
267 * each time that the application sets a new pixel or vertex shader
268 * than it is to re-link them together at that time.
270 * The list will be deleted in IWineD3DDevice::Release().
272 void set_glsl_shader_program(IWineD3DDevice
*iface
) {
274 IWineD3DDeviceImpl
*This
= (IWineD3DDeviceImpl
*)iface
;
275 IWineD3DPixelShader
*pshader
= This
->stateBlock
->pixelShader
;
276 IWineD3DVertexShader
*vshader
= This
->stateBlock
->vertexShader
;
277 struct glsl_shader_prog_link
*curLink
= NULL
;
278 struct glsl_shader_prog_link
*newLink
= NULL
;
279 struct list
*ptr
= NULL
;
280 GLhandleARB programId
= 0;
282 ptr
= list_head( &This
->glsl_shader_progs
);
284 /* At least one program exists - see if it matches our ps/vs combination */
285 curLink
= LIST_ENTRY( ptr
, struct glsl_shader_prog_link
, entry
);
286 if (vshader
== curLink
->vertexShader
&& pshader
== curLink
->pixelShader
) {
287 /* Existing Program found, use it */
288 TRACE_(d3d_shader
)("Found existing program (%u) for this vertex/pixel shader combination\n",
290 This
->stateBlock
->shaderPrgId
= curLink
->programId
;
293 /* This isn't the entry we need - try the next one */
294 ptr
= list_next( &This
->glsl_shader_progs
, ptr
);
297 /* If we get to this point, then no matching program exists, so we create one */
298 programId
= GL_EXTCALL(glCreateProgramObjectARB());
299 TRACE_(d3d_shader
)("Created new GLSL shader program %u\n", programId
);
300 This
->stateBlock
->shaderPrgId
= programId
;
302 /* Allocate a new link for the list of programs */
303 newLink
= HeapAlloc(GetProcessHeap(), 0, sizeof(struct glsl_shader_prog_link
));
304 newLink
->programId
= programId
;
306 /* Attach GLSL vshader */
307 if (NULL
!= vshader
&& wined3d_settings
.vs_selected_mode
== SHADER_GLSL
) {
309 int max_attribs
= 16; /* TODO: Will this always be the case? It is at the moment... */
312 TRACE("Attaching vertex shader to GLSL program\n");
313 attach_glsl_shader(iface
, (IWineD3DBaseShader
*)vshader
);
315 /* Bind vertex attributes to a corresponding index number to match
316 * the same index numbers as ARB_vertex_programs (makes loading
317 * vertex attributes simpler). With this method, we can use the
318 * exact same code to load the attributes later for both ARB and
321 * We have to do this here because we need to know the Program ID
322 * in order to make the bindings work, and it has to be done prior
323 * to linking the GLSL program. */
324 for (i
= 0; i
< max_attribs
; ++i
) {
325 snprintf(tmp_name
, sizeof(tmp_name
), "attrib%i", i
);
326 GL_EXTCALL(glBindAttribLocationARB(programId
, i
, tmp_name
));
328 checkGLcall("glBindAttribLocationARB");
329 newLink
->vertexShader
= vshader
;
332 /* Attach GLSL pshader */
333 if (NULL
!= pshader
&& wined3d_settings
.ps_selected_mode
== SHADER_GLSL
) {
334 TRACE("Attaching pixel shader to GLSL program\n");
335 attach_glsl_shader(iface
, (IWineD3DBaseShader
*)pshader
);
336 newLink
->pixelShader
= pshader
;
339 /* Link the program */
340 TRACE_(d3d_shader
)("Linking GLSL shader program %u\n", programId
);
341 GL_EXTCALL(glLinkProgramARB(programId
));
342 print_glsl_info_log(&GLINFO_LOCATION
, programId
);
343 list_add_head( &This
->glsl_shader_progs
, &newLink
->entry
);
347 /** Detach the GLSL pixel or vertex shader object from the shader program */
348 static void detach_glsl_shader(IWineD3DDevice
*iface
, GLhandleARB shaderObj
, GLhandleARB programId
) {
350 IWineD3DDeviceImpl
*This
= (IWineD3DDeviceImpl
*)iface
;
352 if (shaderObj
!= 0 && programId
!= 0) {
353 TRACE_(d3d_shader
)("Detaching GLSL shader object %u from program %u\n", shaderObj
, programId
);
354 GL_EXTCALL(glDetachObjectARB(programId
, shaderObj
));
355 checkGLcall("glDetachObjectARB");
359 /** Delete a GLSL shader program */
360 static void delete_glsl_shader_program(IWineD3DDevice
*iface
, GLhandleARB obj
) {
362 IWineD3DDeviceImpl
*This
= (IWineD3DDeviceImpl
*)iface
;
365 TRACE_(d3d_shader
)("Deleting GLSL shader program %u\n", obj
);
366 GL_EXTCALL(glDeleteObjectARB(obj
));
367 checkGLcall("glDeleteObjectARB");
371 /** Delete the list of linked programs this shader is associated with.
372 * Also at this point, check to see if there are any objects left attached
373 * to each GLSL program. If not, delete the GLSL program object.
374 * This will be run when a device is released. */
375 static void delete_glsl_shader_list(IWineD3DDevice
* iface
) {
377 struct list
*ptr
= NULL
;
378 struct glsl_shader_prog_link
*curLink
= NULL
;
379 IWineD3DDeviceImpl
*This
= (IWineD3DDeviceImpl
*)iface
;
383 GLhandleARB objList
[2]; /* There should never be more than 2 objects attached
384 (one pixel shader and one vertex shader at most) */
386 ptr
= list_head( &This
->glsl_shader_progs
);
388 /* First, get the current item,
389 * save the link to the next pointer,
390 * detach and delete shader objects,
391 * then de-allocate the list item's memory */
392 curLink
= LIST_ENTRY( ptr
, struct glsl_shader_prog_link
, entry
);
393 ptr
= list_next( &This
->glsl_shader_progs
, ptr
);
395 /* See if this object is still attached to the program - it may have been detached already */
396 GL_EXTCALL(glGetAttachedObjectsARB(curLink
->programId
, 2, &numAttached
, objList
));
397 TRACE_(d3d_shader
)("%i GLSL objects are currently attached to program %u\n", numAttached
, curLink
->programId
);
398 for (i
= 0; i
< numAttached
; i
++) {
399 detach_glsl_shader(iface
, objList
[i
], curLink
->programId
);
402 delete_glsl_shader_program(iface
, curLink
->programId
);
404 /* Free the memory for this list item */
405 HeapFree(GetProcessHeap(), 0, curLink
);
410 /* Apply the current values to the specified texture stage */
411 static void WINAPI
IWineD3DDeviceImpl_SetupTextureStates(IWineD3DDevice
*iface
, DWORD Sampler
, DWORD texture_idx
, DWORD Flags
) {
412 IWineD3DDeviceImpl
*This
= (IWineD3DDeviceImpl
*)iface
;
420 /* In addition, IDirect3DDevice9::SetSamplerState will now be used for filtering, tiling,
421 clamping, MIPLOD, etc. This will work for up to 16 samplers.
424 if (Sampler
>= GL_LIMITS(sampler_stages
)) {
425 FIXME("Trying to set the state of more samplers %ld than are supported %d by this openGL implementation\n", Sampler
, GL_LIMITS(sampler_stages
));
428 VTRACE(("Activating appropriate texture state %ld\n", Sampler
));
429 if (GL_SUPPORT(ARB_MULTITEXTURE
)) {
431 GL_EXTCALL(glActiveTextureARB(GL_TEXTURE0_ARB
+ texture_idx
));
432 checkGLcall("glActiveTextureARB");
434 /* Could we use bindTexture and then apply the states instead of GLACTIVETEXTURE */
435 } else if (Sampler
> 0) {
436 FIXME("Program using multiple concurrent textures which this opengl implementation doesn't support\n");
440 /* TODO: change this to a lookup table
441 LOOKUP_TEXTURE_STATES lists all texture states that should be applied.
442 LOOKUP_CONTEXT_SATES list all context applicable states that can be applied
443 etc.... it's a lot cleaner, quicker and possibly easier to maintain than running a switch and setting a skip flag...
444 especially when there are a number of groups of states. */
446 TRACE("-----------------------> Updating the texture at Sampler %ld to have new texture state information\n", Sampler
);
448 /* The list of states not to apply is a big as the list of states to apply, so it makes sense to produce an inclusive list */
449 #define APPLY_STATE(_state) IWineD3DDeviceImpl_ApplyTextureUnitState(iface, Sampler, _state)
450 /* these are the only two supported states that need to be applied */
451 APPLY_STATE(WINED3DTSS_TEXCOORDINDEX
);
452 APPLY_STATE(WINED3DTSS_TEXTURETRANSFORMFLAGS
);
453 #if 0 /* not supported at the moment */
454 APPLY_STATE(WINED3DTSS_BUMPENVMAT00
);
455 APPLY_STATE(WINED3DTSS_BUMPENVMAT01
);
456 APPLY_STATE(WINED3DTSS_BUMPENVMAT10
);
457 APPLY_STATE(WINED3DTSS_BUMPENVMAT11
);
458 APPLY_STATE(WINED3DTSS_BUMPENVLSCALE
);
459 APPLY_STATE(WINED3DTSS_BUMPENVLOFFSET
);
460 APPLY_STATE(WINED3DTSS_RESULTARG
);
461 APPLY_STATE(WINED3DTSS_CONSTANT
);
463 /* a quick sanity check in case someone forgot to update this function */
464 if (WINED3D_HIGHEST_TEXTURE_STATE
> WINED3DTSS_CONSTANT
) {
465 FIXME("(%p) : There are more texture states than expected, update device.c to match\n", This
);
469 /* apply any sampler states that always need applying */
470 if (GL_SUPPORT(EXT_TEXTURE_LOD_BIAS
)) {
471 tmpvalue
.d
= This
->stateBlock
->samplerState
[Sampler
][WINED3DSAMP_MIPMAPLODBIAS
];
472 glTexEnvf(GL_TEXTURE_FILTER_CONTROL_EXT
,
473 GL_TEXTURE_LOD_BIAS_EXT
,
475 checkGLcall("glTexEnvi GL_TEXTURE_LOD_BIAS_EXT ...");
478 /* Note the D3DRS value applies to all textures, but GL has one
479 * per texture, so apply it now ready to be used!
481 D3DCOLORTOGLFLOAT4(This
->stateBlock
->renderState
[WINED3DRS_TEXTUREFACTOR
], col
);
482 /* Set the default alpha blend color */
483 if (GL_SUPPORT(ARB_IMAGING
)) {
484 GL_EXTCALL(glBlendColor(col
[0], col
[1], col
[2], col
[3]));
485 checkGLcall("glBlendColor");
487 WARN("Unsupported in local OpenGL implementation: glBlendColor\n");
490 D3DCOLORTOGLFLOAT4(This
->stateBlock
->renderState
[WINED3DRS_TEXTUREFACTOR
], col
);
491 glTexEnvfv(GL_TEXTURE_ENV
, GL_TEXTURE_ENV_COLOR
, &col
[0]);
492 checkGLcall("glTexEnvfv(GL_TEXTURE_ENV, GL_TEXTURE_ENV_COLOR, color);");
494 /* TODO: NV_POINT_SPRITE */
495 if (GL_SUPPORT(ARB_POINT_SPRITE
)) {
496 if (This
->stateBlock
->renderState
[WINED3DRS_POINTSPRITEENABLE
] != FALSE
) {
497 /* Doesn't work with GL_POINT_SMOOTH on on my ATI 9600, but then ATI drivers are buggered! */
498 glDisable(GL_POINT_SMOOTH
);
500 /* Centre the texture on the vertex */
501 VTRACE(("glTexEnvf( GL_POINT_SPRITE_ARB, GL_COORD_REPLACE_ARB, GL_TRUE)\n"));
502 glTexEnvf( GL_POINT_SPRITE_ARB
, GL_COORD_REPLACE_ARB
, GL_TRUE
);
504 VTRACE(("glTexEnvf( GL_POINT_SPRITE_ARB, GL_COORD_REPLACE_ARB, GL_TRUE)\n"));
505 glTexEnvf( GL_POINT_SPRITE_ARB
, GL_COORD_REPLACE_ARB
, GL_TRUE
);
506 checkGLcall("glTexEnvf(...)");
507 VTRACE(("glEnable( GL_POINT_SPRITE_ARB )\n"));
508 glEnable( GL_POINT_SPRITE_ARB
);
509 checkGLcall("glEnable(...)");
511 VTRACE(("glDisable( GL_POINT_SPRITE_ARB )\n"));
512 glDisable( GL_POINT_SPRITE_ARB
);
513 checkGLcall("glEnable(...)");
517 TRACE("-----------------------> Updated the texture at Sampler %ld to have new texture state information\n", Sampler
);
520 /**********************************************************
521 * IUnknown parts follows
522 **********************************************************/
524 static HRESULT WINAPI
IWineD3DDeviceImpl_QueryInterface(IWineD3DDevice
*iface
,REFIID riid
,LPVOID
*ppobj
)
526 IWineD3DDeviceImpl
*This
= (IWineD3DDeviceImpl
*)iface
;
528 TRACE("(%p)->(%s,%p)\n",This
,debugstr_guid(riid
),ppobj
);
529 if (IsEqualGUID(riid
, &IID_IUnknown
)
530 || IsEqualGUID(riid
, &IID_IWineD3DBase
)
531 || IsEqualGUID(riid
, &IID_IWineD3DDevice
)) {
532 IUnknown_AddRef(iface
);
537 return E_NOINTERFACE
;
540 static ULONG WINAPI
IWineD3DDeviceImpl_AddRef(IWineD3DDevice
*iface
) {
541 IWineD3DDeviceImpl
*This
= (IWineD3DDeviceImpl
*)iface
;
542 ULONG refCount
= InterlockedIncrement(&This
->ref
);
544 TRACE("(%p) : AddRef increasing from %ld\n", This
, refCount
- 1);
548 static ULONG WINAPI
IWineD3DDeviceImpl_Release(IWineD3DDevice
*iface
) {
549 IWineD3DDeviceImpl
*This
= (IWineD3DDeviceImpl
*)iface
;
550 ULONG refCount
= InterlockedDecrement(&This
->ref
);
552 TRACE("(%p) : Releasing from %ld\n", This
, refCount
+ 1);
555 /* TODO: Clean up all the surfaces and textures! */
556 /* NOTE: You must release the parent if the object was created via a callback
557 ** ***************************/
559 /* Delete any GLSL shader programs that may exist */
560 if (wined3d_settings
.vs_selected_mode
== SHADER_GLSL
||
561 wined3d_settings
.ps_selected_mode
== SHADER_GLSL
)
562 delete_glsl_shader_list(iface
);
564 /* Release the update stateblock */
565 if(IWineD3DStateBlock_Release((IWineD3DStateBlock
*)This
->updateStateBlock
) > 0){
566 if(This
->updateStateBlock
!= This
->stateBlock
)
567 FIXME("(%p) Something's still holding the Update stateblock\n",This
);
569 This
->updateStateBlock
= NULL
;
570 { /* because were not doing proper internal refcounts releasing the primary state block
571 causes recursion with the extra checks in ResourceReleased, to avoid this we have
572 to set this->stateBlock = NULL; first */
573 IWineD3DStateBlock
*stateBlock
= (IWineD3DStateBlock
*)This
->stateBlock
;
574 This
->stateBlock
= NULL
;
576 /* Release the stateblock */
577 if(IWineD3DStateBlock_Release(stateBlock
) > 0){
578 FIXME("(%p) Something's still holding the Update stateblock\n",This
);
582 if (This
->resources
!= NULL
) {
583 FIXME("(%p) Device released with resources still bound, acceptable but unexpected\n", This
);
584 dumpResources(This
->resources
);
588 IWineD3D_Release(This
->wineD3D
);
589 This
->wineD3D
= NULL
;
590 HeapFree(GetProcessHeap(), 0, This
);
591 TRACE("Freed device %p\n", This
);
597 /**********************************************************
598 * IWineD3DDevice implementation follows
599 **********************************************************/
600 static HRESULT WINAPI
IWineD3DDeviceImpl_GetParent(IWineD3DDevice
*iface
, IUnknown
**pParent
) {
601 IWineD3DDeviceImpl
*This
= (IWineD3DDeviceImpl
*)iface
;
602 *pParent
= This
->parent
;
603 IUnknown_AddRef(This
->parent
);
607 static void CreateVBO(IWineD3DVertexBufferImpl
*object
) {
608 IWineD3DDeviceImpl
*This
= object
->resource
.wineD3DDevice
; /* Needed for GL_EXTCALL */
609 GLenum error
, glUsage
;
610 DWORD vboUsage
= object
->resource
.usage
;
611 if(object
->Flags
& VBFLAG_VBOCREATEFAIL
) {
612 WARN("Creating a vbo failed once, not trying again\n");
616 TRACE("Creating an OpenGL vertex buffer object for IWineD3DVertexBuffer %p Usage(%s)\n", object
, debug_d3dusage(vboUsage
));
619 /* Make sure that the gl error is cleared. Do not use checkGLcall
620 * here because checkGLcall just prints a fixme and continues. However,
621 * if an error during VBO creation occurs we can fall back to non-vbo operation
622 * with full functionality(but performance loss)
624 while(glGetError() != GL_NO_ERROR
);
626 /* Basically the FVF parameter passed to CreateVertexBuffer is no good
627 * It is the FVF set with IWineD3DDevice::SetFVF or the Vertex Declaration set with
628 * IWineD3DDevice::SetVertexDeclaration that decides how the vertices in the buffer
629 * look like. This means that on each DrawPrimitive call the vertex buffer has to be verified
630 * to check if the rhw and color values are in the correct format.
633 GL_EXTCALL(glGenBuffersARB(1, &object
->vbo
));
634 error
= glGetError();
635 if(object
->vbo
== 0 || error
!= GL_NO_ERROR
) {
636 WARN("Failed to create a VBO with error %d\n", error
);
640 GL_EXTCALL(glBindBufferARB(GL_ARRAY_BUFFER_ARB
, object
->vbo
));
641 error
= glGetError();
642 if(error
!= GL_NO_ERROR
) {
643 WARN("Failed to bind the VBO, error %d\n", error
);
647 /* Transformed vertices are horribly inflexible. If the app specifies an
648 * vertex buffer with transformed vertices in default pool without DYNAMIC
649 * usage assume DYNAMIC usage and print a warning. The app will have to update
650 * the vertices regularily for them to be useful
652 if(((object
->fvf
& D3DFVF_POSITION_MASK
) == D3DFVF_XYZRHW
) &&
653 !(vboUsage
& WINED3DUSAGE_DYNAMIC
)) {
654 WARN("Application creates a vertex buffer holding transformed vertices which doesn't specify dynamic usage\n");
655 vboUsage
|= WINED3DUSAGE_DYNAMIC
;
658 /* Don't use static, because dx apps tend to update the buffer
659 * quite often even if they specify 0 usage
661 switch(vboUsage
& (D3DUSAGE_WRITEONLY
| D3DUSAGE_DYNAMIC
) ) {
662 case D3DUSAGE_WRITEONLY
| D3DUSAGE_DYNAMIC
:
663 TRACE("Gl usage = GL_STREAM_DRAW\n");
664 glUsage
= GL_STREAM_DRAW_ARB
;
666 case D3DUSAGE_WRITEONLY
:
667 TRACE("Gl usage = GL_DYNAMIC_DRAW\n");
668 glUsage
= GL_DYNAMIC_DRAW_ARB
;
670 case D3DUSAGE_DYNAMIC
:
671 TRACE("Gl usage = GL_STREAM_COPY\n");
672 glUsage
= GL_STREAM_COPY_ARB
;
675 TRACE("Gl usage = GL_DYNAMIC_COPY\n");
676 glUsage
= GL_DYNAMIC_COPY_ARB
;
680 /* Reserve memory for the buffer. The amount of data won't change
681 * so we are safe with calling glBufferData once with a NULL ptr and
682 * calling glBufferSubData on updates
684 GL_EXTCALL(glBufferDataARB(GL_ARRAY_BUFFER_ARB
, object
->resource
.size
, NULL
, glUsage
));
685 error
= glGetError();
686 if(error
!= GL_NO_ERROR
) {
687 WARN("glBufferDataARB failed with error %d\n", error
);
695 /* Clean up all vbo init, but continue because we can work without a vbo :-) */
696 FIXME("Failed to create a vertex buffer object. Continuing, but performance issues can occur\n");
697 if(object
->vbo
) GL_EXTCALL(glDeleteBuffersARB(1, &object
->vbo
));
699 object
->Flags
|= VBFLAG_VBOCREATEFAIL
;
704 static HRESULT WINAPI
IWineD3DDeviceImpl_CreateVertexBuffer(IWineD3DDevice
*iface
, UINT Size
, DWORD Usage
,
705 DWORD FVF
, WINED3DPOOL Pool
, IWineD3DVertexBuffer
** ppVertexBuffer
, HANDLE
*sharedHandle
,
707 IWineD3DDeviceImpl
*This
= (IWineD3DDeviceImpl
*)iface
;
708 IWineD3DVertexBufferImpl
*object
;
709 WINED3DFORMAT Format
= WINED3DFMT_VERTEXDATA
; /* Dummy format for now */
710 int dxVersion
= ( (IWineD3DImpl
*) This
->wineD3D
)->dxVersion
;
712 D3DCREATERESOURCEOBJECTINSTANCE(object
, VertexBuffer
, WINED3DRTYPE_VERTEXBUFFER
, Size
)
714 TRACE("(%p) : Size=%d, Usage=%ld, FVF=%lx, Pool=%d - Memory@%p, Iface@%p\n", This
, Size
, Usage
, FVF
, Pool
, object
->resource
.allocatedMemory
, object
);
715 *ppVertexBuffer
= (IWineD3DVertexBuffer
*)object
;
717 if(Size
== 0) return WINED3DERR_INVALIDCALL
;
719 if (Pool
== WINED3DPOOL_DEFAULT
) { /* Allocate some system memory for now */
720 object
->resource
.allocatedMemory
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, object
->resource
.size
);
724 /* Observations show that drawStridedSlow is faster on dynamic VBs than converting +
725 * drawStridedFast (half-life 2).
727 * Basically converting the vertices in the buffer is quite expensive, and observations
728 * show that drawStridedSlow is faster than converting + uploading + drawStridedFast.
729 * Therefore do not create a VBO for WINED3DUSAGE_DYNAMIC buffers.
731 * Direct3D7 has another problem: Its vertexbuffer api doesn't offer a way to specify
732 * the range of vertices being locked, so each lock will require the whole buffer to be transformed.
733 * Moreover geometry data in dx7 is quite simple, so drawStridedSlow isn't a big hit. A plus
734 * is that the vertex buffers fvf can be trusted in dx7. So only create non-converted vbos for
736 * There is a IDirect3DVertexBuffer7::Optimize call after which the buffer can't be locked any
737 * more. In this call we can convert dx7 buffers too.
739 conv
= ((FVF
& D3DFVF_POSITION_MASK
) == D3DFVF_XYZRHW
) || (FVF
& (D3DFVF_DIFFUSE
| D3DFVF_SPECULAR
));
740 if( GL_SUPPORT(ARB_VERTEX_BUFFER_OBJECT
) && Pool
!= WINED3DPOOL_SYSTEMMEM
&& !(Usage
& WINED3DUSAGE_DYNAMIC
) &&
741 (dxVersion
> 7 || !conv
) ) {
744 /* DX7 buffers can be locked directly into the VBO (no conversion, see above */
745 if(dxVersion
== 7 && object
->vbo
) {
746 HeapFree(GetProcessHeap(), 0, object
->resource
.allocatedMemory
);
747 object
->resource
.allocatedMemory
= NULL
;
754 static HRESULT WINAPI
IWineD3DDeviceImpl_CreateIndexBuffer(IWineD3DDevice
*iface
, UINT Length
, DWORD Usage
,
755 WINED3DFORMAT Format
, WINED3DPOOL Pool
, IWineD3DIndexBuffer
** ppIndexBuffer
,
756 HANDLE
*sharedHandle
, IUnknown
*parent
) {
757 IWineD3DDeviceImpl
*This
= (IWineD3DDeviceImpl
*)iface
;
758 IWineD3DIndexBufferImpl
*object
;
759 TRACE("(%p) Creating index buffer\n", This
);
761 /* Allocate the storage for the device */
762 D3DCREATERESOURCEOBJECTINSTANCE(object
,IndexBuffer
,WINED3DRTYPE_INDEXBUFFER
, Length
)
765 if (Pool
== WINED3DPOOL_DEFAULT
) { /* Allocate some system memory for now */
766 object
->resource
.allocatedMemory
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
,object
->resource
.size
);
769 TRACE("(%p) : Len=%d, Use=%lx, Format=(%u,%s), Pool=%d - Memory@%p, Iface@%p\n", This
, Length
, Usage
, Format
,
770 debug_d3dformat(Format
), Pool
, object
, object
->resource
.allocatedMemory
);
771 *ppIndexBuffer
= (IWineD3DIndexBuffer
*) object
;
776 static HRESULT WINAPI
IWineD3DDeviceImpl_CreateStateBlock(IWineD3DDevice
* iface
, WINED3DSTATEBLOCKTYPE Type
, IWineD3DStateBlock
** ppStateBlock
, IUnknown
*parent
) {
778 IWineD3DDeviceImpl
*This
= (IWineD3DDeviceImpl
*)iface
;
779 IWineD3DStateBlockImpl
*object
;
783 D3DCREATEOBJECTINSTANCE(object
, StateBlock
)
784 object
->blockType
= Type
;
786 /* Special case - Used during initialization to produce a placeholder stateblock
787 so other functions called can update a state block */
788 if (Type
== WINED3DSBT_INIT
) {
789 /* Don't bother increasing the reference count otherwise a device will never
790 be freed due to circular dependencies */
794 temp_result
= allocate_shader_constants(object
);
795 if (WINED3D_OK
!= temp_result
)
798 /* Otherwise, might as well set the whole state block to the appropriate values */
799 if (This
->stateBlock
!= NULL
)
800 stateblock_copy((IWineD3DStateBlock
*) object
, (IWineD3DStateBlock
*) This
->stateBlock
);
802 memset(object
->streamFreq
, 1, sizeof(object
->streamFreq
));
804 /* Reset the ref and type after kludging it */
805 object
->wineD3DDevice
= This
;
807 object
->blockType
= Type
;
809 TRACE("Updating changed flags appropriate for type %d\n", Type
);
811 if (Type
== WINED3DSBT_ALL
) {
813 TRACE("ALL => Pretend everything has changed\n");
814 stateblock_savedstates_set((IWineD3DStateBlock
*) object
, &object
->changed
, TRUE
);
816 } else if (Type
== WINED3DSBT_PIXELSTATE
) {
818 TRACE("PIXELSTATE => Pretend all pixel shates have changed\n");
819 stateblock_savedstates_set((IWineD3DStateBlock
*) object
, &object
->changed
, FALSE
);
821 object
->changed
.pixelShader
= TRUE
;
823 /* Pixel Shader Constants */
824 for (i
= 0; i
< GL_LIMITS(pshader_constantsF
); ++i
)
825 object
->changed
.pixelShaderConstantsF
[i
] = TRUE
;
826 for (i
= 0; i
< MAX_CONST_B
; ++i
)
827 object
->changed
.pixelShaderConstantsB
[i
] = TRUE
;
828 for (i
= 0; i
< MAX_CONST_I
; ++i
)
829 object
->changed
.pixelShaderConstantsI
[i
] = TRUE
;
831 for (i
= 0; i
< NUM_SAVEDPIXELSTATES_R
; i
++) {
832 object
->changed
.renderState
[SavedPixelStates_R
[i
]] = TRUE
;
834 for (j
= 0; j
< GL_LIMITS(texture_stages
); j
++) {
835 for (i
= 0; i
< NUM_SAVEDPIXELSTATES_T
; i
++) {
836 object
->changed
.textureState
[j
][SavedPixelStates_T
[i
]] = TRUE
;
839 for (j
= 0 ; j
< 16; j
++) {
840 for (i
=0; i
< NUM_SAVEDPIXELSTATES_S
;i
++) {
842 object
->changed
.samplerState
[j
][SavedPixelStates_S
[i
]] = TRUE
;
846 } else if (Type
== WINED3DSBT_VERTEXSTATE
) {
848 TRACE("VERTEXSTATE => Pretend all vertex shates have changed\n");
849 stateblock_savedstates_set((IWineD3DStateBlock
*) object
, &object
->changed
, FALSE
);
851 object
->changed
.vertexShader
= TRUE
;
853 /* Vertex Shader Constants */
854 for (i
= 0; i
< GL_LIMITS(vshader_constantsF
); ++i
)
855 object
->changed
.vertexShaderConstantsF
[i
] = TRUE
;
856 for (i
= 0; i
< MAX_CONST_B
; ++i
)
857 object
->changed
.vertexShaderConstantsB
[i
] = TRUE
;
858 for (i
= 0; i
< MAX_CONST_I
; ++i
)
859 object
->changed
.vertexShaderConstantsI
[i
] = TRUE
;
861 for (i
= 0; i
< NUM_SAVEDVERTEXSTATES_R
; i
++) {
862 object
->changed
.renderState
[SavedVertexStates_R
[i
]] = TRUE
;
864 for (j
= 0; j
< GL_LIMITS(texture_stages
); j
++) {
865 for (i
= 0; i
< NUM_SAVEDVERTEXSTATES_T
; i
++) {
866 object
->changed
.textureState
[j
][SavedVertexStates_T
[i
]] = TRUE
;
869 for (j
= 0 ; j
< 16; j
++){
870 for (i
=0; i
< NUM_SAVEDVERTEXSTATES_S
;i
++) {
871 object
->changed
.samplerState
[j
][SavedVertexStates_S
[i
]] = TRUE
;
875 /* Duplicate light chain */
877 PLIGHTINFOEL
*src
= NULL
;
878 PLIGHTINFOEL
*dst
= NULL
;
879 PLIGHTINFOEL
*newEl
= NULL
;
880 src
= This
->stateBlock
->lights
;
881 object
->lights
= NULL
;
885 newEl
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, sizeof(PLIGHTINFOEL
));
886 if (newEl
== NULL
) return WINED3DERR_OUTOFVIDEOMEMORY
;
887 memcpy(newEl
, src
, sizeof(PLIGHTINFOEL
));
889 newEl
->changed
= TRUE
;
890 newEl
->enabledChanged
= TRUE
;
892 object
->lights
= newEl
;
903 FIXME("Unrecognized state block type %d\n", Type
);
906 TRACE("(%p) returning token (ptr to stateblock) of %p\n", This
, object
);
911 /* ************************************
913 [in] Render targets are not lockable unless the application specifies TRUE for Lockable. Note that lockable render targets reduce performance on some graphics hardware.
916 [in] Set this flag to TRUE to enable z-buffer discarding, and FALSE otherwise.
918 If this flag is set, the contents of the depth stencil buffer will be invalid after calling either IDirect3DDevice9::Present or IDirect3DDevice9::SetDepthStencilSurface with a different depth surface.
920 ******************************** */
922 static HRESULT WINAPI
IWineD3DDeviceImpl_CreateSurface(IWineD3DDevice
*iface
, UINT Width
, UINT Height
, WINED3DFORMAT Format
, BOOL Lockable
, BOOL Discard
, UINT Level
, IWineD3DSurface
**ppSurface
,WINED3DRESOURCETYPE Type
, DWORD Usage
, WINED3DPOOL Pool
, WINED3DMULTISAMPLE_TYPE MultiSample
,DWORD MultisampleQuality
, HANDLE
* pSharedHandle
, WINED3DSURFTYPE Impl
, IUnknown
*parent
) {
923 IWineD3DDeviceImpl
*This
= (IWineD3DDeviceImpl
*)iface
;
924 IWineD3DSurfaceImpl
*object
; /*NOTE: impl ref allowed since this is a create function */
925 unsigned int pow2Width
, pow2Height
;
926 unsigned int Size
= 1;
927 const PixelFormatDesc
*tableEntry
= getFormatDescEntry(Format
);
928 TRACE("(%p) Create surface\n",This
);
930 /** FIXME: Check ranges on the inputs are valid
933 * [in] Quality level. The valid range is between zero and one less than the level
934 * returned by pQualityLevels used by IDirect3D9::CheckDeviceMultiSampleType.
935 * Passing a larger value returns the error WINED3DERR_INVALIDCALL. The MultisampleQuality
936 * values of paired render targets, depth stencil surfaces, and the MultiSample type
938 *******************************/
943 * [in] Set this flag to TRUE to enable z-buffer discarding, and FALSE otherwise.
945 * If this flag is set, the contents of the depth stencil buffer will be
946 * invalid after calling either IDirect3DDevice9::Present or * IDirect3DDevice9::SetDepthStencilSurface
947 * with a different depth surface.
949 *This flag has the same behavior as the constant, D3DPRESENTFLAG_DISCARD_DEPTHSTENCIL, in D3DPRESENTFLAG.
950 ***************************/
952 if(MultisampleQuality
< 0) {
953 FIXME("Invalid multisample level %ld\n", MultisampleQuality
);
954 return WINED3DERR_INVALIDCALL
; /* TODO: Check that this is the case! */
957 if(MultisampleQuality
> 0) {
958 FIXME("MultisampleQuality set to %ld, substituting 0\n", MultisampleQuality
);
959 MultisampleQuality
=0;
962 /** FIXME: Check that the format is supported
964 *******************************/
966 /* Non-power2 support */
968 /* Find the nearest pow2 match */
969 pow2Width
= pow2Height
= 1;
970 while (pow2Width
< Width
) pow2Width
<<= 1;
971 while (pow2Height
< Height
) pow2Height
<<= 1;
973 if (pow2Width
> Width
|| pow2Height
> Height
) {
974 /** TODO: add support for non power two compressed textures (OpenGL 2 provices support for * non-power-two textures gratis) **/
975 if (Format
== WINED3DFMT_DXT1
|| Format
== WINED3DFMT_DXT2
|| Format
== WINED3DFMT_DXT3
976 || Format
== WINED3DFMT_DXT4
|| Format
== WINED3DFMT_DXT5
) {
977 FIXME("(%p) Compressed non-power-two textures are not supported w(%d) h(%d)\n",
978 This
, Width
, Height
);
979 return WINED3DERR_NOTAVAILABLE
;
983 /** DXTn mipmaps use the same number of 'levels' down to eg. 8x1, but since
984 * it is based around 4x4 pixel blocks it requires padding, so allocate enough
986 *********************************/
987 if (WINED3DFMT_UNKNOWN
== Format
) {
989 } else if (Format
== WINED3DFMT_DXT1
) {
990 /* DXT1 is half byte per pixel */
991 Size
= ((max(pow2Width
,4) * tableEntry
->bpp
) * max(pow2Height
,4)) >> 1;
993 } else if (Format
== WINED3DFMT_DXT2
|| Format
== WINED3DFMT_DXT3
||
994 Format
== WINED3DFMT_DXT4
|| Format
== WINED3DFMT_DXT5
) {
995 Size
= ((max(pow2Width
,4) * tableEntry
->bpp
) * max(pow2Height
,4));
997 Size
= (pow2Width
* tableEntry
->bpp
) * pow2Height
;
1000 /** Create and initialise the surface resource **/
1001 D3DCREATERESOURCEOBJECTINSTANCE(object
,Surface
,WINED3DRTYPE_SURFACE
, Size
)
1002 /* "Standalone" surface */
1003 IWineD3DSurface_SetContainer((IWineD3DSurface
*)object
, NULL
);
1005 object
->currentDesc
.Width
= Width
;
1006 object
->currentDesc
.Height
= Height
;
1007 object
->currentDesc
.MultiSampleType
= MultiSample
;
1008 object
->currentDesc
.MultiSampleQuality
= MultisampleQuality
;
1010 /* Setup some glformat defaults */
1011 object
->glDescription
.glFormat
= tableEntry
->glFormat
;
1012 object
->glDescription
.glFormatInternal
= tableEntry
->glInternal
;
1013 object
->glDescription
.glType
= tableEntry
->glType
;
1015 object
->glDescription
.textureName
= 0;
1016 object
->glDescription
.level
= Level
;
1017 object
->glDescription
.target
= GL_TEXTURE_2D
;
1020 object
->pow2Width
= pow2Width
;
1021 object
->pow2Height
= pow2Height
;
1024 object
->Flags
= 0; /* We start without flags set */
1025 object
->Flags
|= (pow2Width
!= Width
|| pow2Height
!= Height
) ? SFLAG_NONPOW2
: 0;
1026 object
->Flags
|= Discard
? SFLAG_DISCARD
: 0;
1027 object
->Flags
|= (WINED3DFMT_D16_LOCKABLE
== Format
) ? SFLAG_LOCKABLE
: 0;
1028 object
->Flags
|= Lockable
? SFLAG_LOCKABLE
: 0;
1031 if (WINED3DFMT_UNKNOWN
!= Format
) {
1032 object
->bytesPerPixel
= tableEntry
->bpp
;
1033 object
->pow2Size
= (pow2Width
* object
->bytesPerPixel
) * pow2Height
;
1035 object
->bytesPerPixel
= 0;
1036 object
->pow2Size
= 0;
1039 /** TODO: change this into a texture transform matrix so that it's processed in hardware **/
1041 TRACE("Pool %d %d %d %d",Pool
, WINED3DPOOL_DEFAULT
, WINED3DPOOL_MANAGED
, WINED3DPOOL_SYSTEMMEM
);
1043 /** Quick lockable sanity check TODO: remove this after surfaces, usage and locablility have been debugged properly
1044 * this function is too deap to need to care about things like this.
1045 * Levels need to be checked too, and possibly Type wince they all affect what can be done.
1046 * ****************************************/
1048 case WINED3DPOOL_SCRATCH
:
1049 if(Lockable
== FALSE
)
1050 FIXME("Create suface called with a pool of SCRATCH and a Lockable of FALSE \
1051 which are mutually exclusive, setting lockable to true\n");
1054 case WINED3DPOOL_SYSTEMMEM
:
1055 if(Lockable
== FALSE
) FIXME("Create surface called with a pool of SYSTEMMEM and a Lockable of FALSE, \
1056 this is acceptable but unexpected (I can't know how the surface can be usable!)\n");
1057 case WINED3DPOOL_MANAGED
:
1058 if(Usage
== WINED3DUSAGE_DYNAMIC
) FIXME("Create surface called with a pool of MANAGED and a \
1059 Usage of DYNAMIC which are mutually exclusive, not doing \
1060 anything just telling you.\n");
1062 case WINED3DPOOL_DEFAULT
: /*TODO: Create offscreen plain can cause this check to fail..., find out if it should */
1063 if(!(Usage
& WINED3DUSAGE_DYNAMIC
) && !(Usage
& WINED3DUSAGE_RENDERTARGET
)
1064 && !(Usage
&& WINED3DUSAGE_DEPTHSTENCIL
) && Lockable
)
1065 WARN("Creating a surface with a POOL of DEFAULT with Lockable true, that doesn't specify DYNAMIC usage.\n");
1068 FIXME("(%p) Unknown pool %d\n", This
, Pool
);
1072 if (Usage
& WINED3DUSAGE_RENDERTARGET
&& Pool
!= WINED3DPOOL_DEFAULT
) {
1073 FIXME("Trying to create a render target that isn't in the default pool\n");
1076 /* mark the texture as dirty so that it get's loaded first time around*/
1077 IWineD3DSurface_AddDirtyRect(*ppSurface
, NULL
);
1078 TRACE("(%p) : w(%d) h(%d) fmt(%d,%s) lockable(%d) surf@%p, surfmem@%p, %d bytes\n",
1079 This
, Width
, Height
, Format
, debug_d3dformat(Format
),
1080 (WINED3DFMT_D16_LOCKABLE
== Format
), *ppSurface
, object
->resource
.allocatedMemory
, object
->resource
.size
);
1082 /* Store the DirectDraw primary surface. This is the first rendertarget surface created */
1083 if( (Usage
& WINED3DUSAGE_RENDERTARGET
) && (!This
->ddraw_primary
) )
1084 This
->ddraw_primary
= (IWineD3DSurface
*) object
;
1086 /* Look at the implementation and set the correct Vtable */
1088 case SURFACE_OPENGL
:
1089 /* Nothing to do, it's set already */
1093 object
->lpVtbl
= &IWineGDISurface_Vtbl
;
1097 /* To be sure to catch this */
1098 ERR("Unknown requested surface implementation %d!\n", Impl
);
1099 IWineD3DSurface_Release((IWineD3DSurface
*) object
);
1100 return WINED3DERR_INVALIDCALL
;
1103 /* Call the private setup routine */
1104 return IWineD3DSurface_PrivateSetup( (IWineD3DSurface
*) object
);
1108 static HRESULT WINAPI
IWineD3DDeviceImpl_CreateTexture(IWineD3DDevice
*iface
, UINT Width
, UINT Height
, UINT Levels
,
1109 DWORD Usage
, WINED3DFORMAT Format
, WINED3DPOOL Pool
,
1110 IWineD3DTexture
** ppTexture
, HANDLE
* pSharedHandle
, IUnknown
*parent
,
1111 D3DCB_CREATESURFACEFN D3DCB_CreateSurface
) {
1113 IWineD3DDeviceImpl
*This
= (IWineD3DDeviceImpl
*)iface
;
1114 IWineD3DTextureImpl
*object
;
1119 unsigned int pow2Width
= Width
;
1120 unsigned int pow2Height
= Height
;
1123 TRACE("(%p) : Width %d, Height %d, Levels %d, Usage %#lx\n", This
, Width
, Height
, Levels
, Usage
);
1124 TRACE("Format %#x (%s), Pool %#x, ppTexture %p, pSharedHandle %p, parent %p\n",
1125 Format
, debug_d3dformat(Format
), Pool
, ppTexture
, pSharedHandle
, parent
);
1127 /* TODO: It should only be possible to create textures for formats
1128 that are reported as supported */
1129 if (WINED3DFMT_UNKNOWN
>= Format
) {
1130 WARN("(%p) : Texture cannot be created with a format of D3DFMT_UNKNOWN\n", This
);
1131 return WINED3DERR_INVALIDCALL
;
1134 D3DCREATERESOURCEOBJECTINSTANCE(object
, Texture
, WINED3DRTYPE_TEXTURE
, 0);
1135 D3DINITIALIZEBASETEXTURE(object
->baseTexture
);
1136 object
->width
= Width
;
1137 object
->height
= Height
;
1139 /** Non-power2 support **/
1140 /* Find the nearest pow2 match */
1141 pow2Width
= pow2Height
= 1;
1142 while (pow2Width
< Width
) pow2Width
<<= 1;
1143 while (pow2Height
< Height
) pow2Height
<<= 1;
1145 /** FIXME: add support for real non-power-two if it's provided by the video card **/
1146 /* Precalculated scaling for 'faked' non power of two texture coords */
1147 object
->pow2scalingFactorX
= (((float)Width
) / ((float)pow2Width
));
1148 object
->pow2scalingFactorY
= (((float)Height
) / ((float)pow2Height
));
1149 TRACE(" xf(%f) yf(%f)\n", object
->pow2scalingFactorX
, object
->pow2scalingFactorY
);
1151 /* Calculate levels for mip mapping */
1153 TRACE("calculating levels %d\n", object
->baseTexture
.levels
);
1154 object
->baseTexture
.levels
++;
1157 while (tmpW
> 1 || tmpH
> 1) {
1158 tmpW
= max(1, tmpW
>> 1);
1159 tmpH
= max(1, tmpH
>> 1);
1160 object
->baseTexture
.levels
++;
1162 TRACE("Calculated levels = %d\n", object
->baseTexture
.levels
);
1165 /* Generate all the surfaces */
1168 for (i
= 0; i
< object
->baseTexture
.levels
; i
++)
1170 /* use the callback to create the texture surface */
1171 hr
= D3DCB_CreateSurface(This
->parent
, tmpW
, tmpH
, Format
, Usage
, Pool
, i
, &object
->surfaces
[i
],NULL
);
1172 if (hr
!= WINED3D_OK
|| ( (IWineD3DSurfaceImpl
*) object
->surfaces
[i
])->Flags
& SFLAG_OVERSIZE
) {
1173 FIXME("Failed to create surface %p\n", object
);
1175 object
->surfaces
[i
] = NULL
;
1176 IWineD3DTexture_Release((IWineD3DTexture
*)object
);
1182 IWineD3DSurface_SetContainer(object
->surfaces
[i
], (IWineD3DBase
*)object
);
1183 TRACE("Created surface level %d @ %p\n", i
, object
->surfaces
[i
]);
1184 /* calculate the next mipmap level */
1185 tmpW
= max(1, tmpW
>> 1);
1186 tmpH
= max(1, tmpH
>> 1);
1189 TRACE("(%p) : Created texture %p\n", This
, object
);
1193 static HRESULT WINAPI
IWineD3DDeviceImpl_CreateVolumeTexture(IWineD3DDevice
*iface
,
1194 UINT Width
, UINT Height
, UINT Depth
,
1195 UINT Levels
, DWORD Usage
,
1196 WINED3DFORMAT Format
, WINED3DPOOL Pool
,
1197 IWineD3DVolumeTexture
**ppVolumeTexture
,
1198 HANDLE
*pSharedHandle
, IUnknown
*parent
,
1199 D3DCB_CREATEVOLUMEFN D3DCB_CreateVolume
) {
1201 IWineD3DDeviceImpl
*This
= (IWineD3DDeviceImpl
*)iface
;
1202 IWineD3DVolumeTextureImpl
*object
;
1208 /* TODO: It should only be possible to create textures for formats
1209 that are reported as supported */
1210 if (WINED3DFMT_UNKNOWN
>= Format
) {
1211 WARN("(%p) : Texture cannot be created with a format of D3DFMT_UNKNOWN\n", This
);
1212 return WINED3DERR_INVALIDCALL
;
1215 D3DCREATERESOURCEOBJECTINSTANCE(object
, VolumeTexture
, WINED3DRTYPE_VOLUMETEXTURE
, 0);
1216 D3DINITIALIZEBASETEXTURE(object
->baseTexture
);
1218 TRACE("(%p) : W(%d) H(%d) D(%d), Lvl(%d) Usage(%ld), Fmt(%u,%s), Pool(%s)\n", This
, Width
, Height
,
1219 Depth
, Levels
, Usage
, Format
, debug_d3dformat(Format
), debug_d3dpool(Pool
));
1221 object
->width
= Width
;
1222 object
->height
= Height
;
1223 object
->depth
= Depth
;
1225 /* Calculate levels for mip mapping */
1227 object
->baseTexture
.levels
++;
1231 while (tmpW
> 1 || tmpH
> 1 || tmpD
> 1) {
1232 tmpW
= max(1, tmpW
>> 1);
1233 tmpH
= max(1, tmpH
>> 1);
1234 tmpD
= max(1, tmpD
>> 1);
1235 object
->baseTexture
.levels
++;
1237 TRACE("Calculated levels = %d\n", object
->baseTexture
.levels
);
1240 /* Generate all the surfaces */
1245 for (i
= 0; i
< object
->baseTexture
.levels
; i
++)
1247 /* Create the volume */
1248 D3DCB_CreateVolume(This
->parent
, Width
, Height
, Depth
, Format
, Pool
, Usage
,
1249 (IWineD3DVolume
**)&object
->volumes
[i
], pSharedHandle
);
1251 /* Set it's container to this object */
1252 IWineD3DVolume_SetContainer(object
->volumes
[i
], (IWineD3DBase
*)object
);
1254 /* calcualte the next mipmap level */
1255 tmpW
= max(1, tmpW
>> 1);
1256 tmpH
= max(1, tmpH
>> 1);
1257 tmpD
= max(1, tmpD
>> 1);
1260 *ppVolumeTexture
= (IWineD3DVolumeTexture
*) object
;
1261 TRACE("(%p) : Created volume texture %p\n", This
, object
);
1265 static HRESULT WINAPI
IWineD3DDeviceImpl_CreateVolume(IWineD3DDevice
*iface
,
1266 UINT Width
, UINT Height
, UINT Depth
,
1268 WINED3DFORMAT Format
, WINED3DPOOL Pool
,
1269 IWineD3DVolume
** ppVolume
,
1270 HANDLE
* pSharedHandle
, IUnknown
*parent
) {
1272 IWineD3DDeviceImpl
*This
= (IWineD3DDeviceImpl
*)iface
;
1273 IWineD3DVolumeImpl
*object
; /** NOTE: impl ref allowed since this is a create function **/
1274 const PixelFormatDesc
*formatDesc
= getFormatDescEntry(Format
);
1276 D3DCREATERESOURCEOBJECTINSTANCE(object
, Volume
, WINED3DRTYPE_VOLUME
, ((Width
* formatDesc
->bpp
) * Height
* Depth
))
1278 TRACE("(%p) : W(%d) H(%d) D(%d), Usage(%ld), Fmt(%u,%s), Pool(%s)\n", This
, Width
, Height
,
1279 Depth
, Usage
, Format
, debug_d3dformat(Format
), debug_d3dpool(Pool
));
1281 object
->currentDesc
.Width
= Width
;
1282 object
->currentDesc
.Height
= Height
;
1283 object
->currentDesc
.Depth
= Depth
;
1284 object
->bytesPerPixel
= formatDesc
->bpp
;
1286 /** Note: Volume textures cannot be dxtn, hence no need to check here **/
1287 object
->lockable
= TRUE
;
1288 object
->locked
= FALSE
;
1289 memset(&object
->lockedBox
, 0, sizeof(WINED3DBOX
));
1290 object
->dirty
= TRUE
;
1292 return IWineD3DVolume_AddDirtyBox((IWineD3DVolume
*) object
, NULL
);
1295 static HRESULT WINAPI
IWineD3DDeviceImpl_CreateCubeTexture(IWineD3DDevice
*iface
, UINT EdgeLength
,
1296 UINT Levels
, DWORD Usage
,
1297 WINED3DFORMAT Format
, WINED3DPOOL Pool
,
1298 IWineD3DCubeTexture
**ppCubeTexture
,
1299 HANDLE
*pSharedHandle
, IUnknown
*parent
,
1300 D3DCB_CREATESURFACEFN D3DCB_CreateSurface
) {
1302 IWineD3DDeviceImpl
*This
= (IWineD3DDeviceImpl
*)iface
;
1303 IWineD3DCubeTextureImpl
*object
; /** NOTE: impl ref allowed since this is a create function **/
1307 unsigned int pow2EdgeLength
= EdgeLength
;
1309 /* TODO: It should only be possible to create textures for formats
1310 that are reported as supported */
1311 if (WINED3DFMT_UNKNOWN
>= Format
) {
1312 WARN("(%p) : Texture cannot be created with a format of D3DFMT_UNKNOWN\n", This
);
1313 return WINED3DERR_INVALIDCALL
;
1316 D3DCREATERESOURCEOBJECTINSTANCE(object
, CubeTexture
, WINED3DRTYPE_CUBETEXTURE
, 0);
1317 D3DINITIALIZEBASETEXTURE(object
->baseTexture
);
1319 TRACE("(%p) Create Cube Texture\n", This
);
1321 /** Non-power2 support **/
1323 /* Find the nearest pow2 match */
1325 while (pow2EdgeLength
< EdgeLength
) pow2EdgeLength
<<= 1;
1327 object
->edgeLength
= EdgeLength
;
1328 /* TODO: support for native non-power 2 */
1329 /* Precalculated scaling for 'faked' non power of two texture coords */
1330 object
->pow2scalingFactor
= ((float)EdgeLength
) / ((float)pow2EdgeLength
);
1332 /* Calculate levels for mip mapping */
1334 object
->baseTexture
.levels
++;
1337 tmpW
= max(1, tmpW
>> 1);
1338 object
->baseTexture
.levels
++;
1340 TRACE("Calculated levels = %d\n", object
->baseTexture
.levels
);
1343 /* Generate all the surfaces */
1345 for (i
= 0; i
< object
->baseTexture
.levels
; i
++) {
1347 /* Create the 6 faces */
1348 for (j
= 0; j
< 6; j
++) {
1350 hr
=D3DCB_CreateSurface(This
->parent
, tmpW
, tmpW
, Format
, Usage
, Pool
,
1351 i
/* Level */, &object
->surfaces
[j
][i
],pSharedHandle
);
1353 if(hr
!= WINED3D_OK
) {
1357 for (l
= 0; l
< j
; l
++) {
1358 IWineD3DSurface_Release(object
->surfaces
[j
][i
]);
1360 for (k
= 0; k
< i
; k
++) {
1361 for (l
= 0; l
< 6; l
++) {
1362 IWineD3DSurface_Release(object
->surfaces
[l
][j
]);
1366 FIXME("(%p) Failed to create surface\n",object
);
1367 HeapFree(GetProcessHeap(),0,object
);
1368 *ppCubeTexture
= NULL
;
1371 IWineD3DSurface_SetContainer(object
->surfaces
[j
][i
], (IWineD3DBase
*)object
);
1372 TRACE("Created surface level %d @ %p,\n", i
, object
->surfaces
[j
][i
]);
1374 tmpW
= max(1, tmpW
>> 1);
1377 TRACE("(%p) : Created Cube Texture %p\n", This
, object
);
1378 *ppCubeTexture
= (IWineD3DCubeTexture
*) object
;
1382 static HRESULT WINAPI
IWineD3DDeviceImpl_CreateQuery(IWineD3DDevice
*iface
, WINED3DQUERYTYPE Type
, IWineD3DQuery
**ppQuery
, IUnknown
* parent
) {
1383 IWineD3DDeviceImpl
*This
= (IWineD3DDeviceImpl
*)iface
;
1384 IWineD3DQueryImpl
*object
; /*NOTE: impl ref allowed since this is a create function */
1386 if (NULL
== ppQuery
) {
1387 /* Just a check to see if we support this type of query */
1388 HRESULT hr
= WINED3DERR_NOTAVAILABLE
;
1390 case WINED3DQUERYTYPE_OCCLUSION
:
1391 TRACE("(%p) occlusion query\n", This
);
1392 if (GL_SUPPORT(ARB_OCCLUSION_QUERY
))
1395 WARN("Unsupported in local OpenGL implementation: ARB_OCCLUSION_QUERY/NV_OCCLUSION_QUERY\n");
1397 case WINED3DQUERYTYPE_VCACHE
:
1398 case WINED3DQUERYTYPE_RESOURCEMANAGER
:
1399 case WINED3DQUERYTYPE_VERTEXSTATS
:
1400 case WINED3DQUERYTYPE_EVENT
:
1401 case WINED3DQUERYTYPE_TIMESTAMP
:
1402 case WINED3DQUERYTYPE_TIMESTAMPDISJOINT
:
1403 case WINED3DQUERYTYPE_TIMESTAMPFREQ
:
1404 case WINED3DQUERYTYPE_PIPELINETIMINGS
:
1405 case WINED3DQUERYTYPE_INTERFACETIMINGS
:
1406 case WINED3DQUERYTYPE_VERTEXTIMINGS
:
1407 case WINED3DQUERYTYPE_PIXELTIMINGS
:
1408 case WINED3DQUERYTYPE_BANDWIDTHTIMINGS
:
1409 case WINED3DQUERYTYPE_CACHEUTILIZATION
:
1411 FIXME("(%p) Unhandled query type %d\n", This
, Type
);
1416 D3DCREATEOBJECTINSTANCE(object
, Query
)
1417 object
->type
= Type
;
1418 /* allocated the 'extended' data based on the type of query requested */
1420 case D3DQUERYTYPE_OCCLUSION
:
1421 if(GL_SUPPORT(ARB_OCCLUSION_QUERY
)) {
1422 TRACE("(%p) Allocating data for an occlusion query\n", This
);
1423 object
->extendedData
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, sizeof(WineQueryOcclusionData
));
1424 GL_EXTCALL(glGenQueriesARB(1, &((WineQueryOcclusionData
*)(object
->extendedData
))->queryId
));
1427 case D3DQUERYTYPE_VCACHE
:
1428 case D3DQUERYTYPE_RESOURCEMANAGER
:
1429 case D3DQUERYTYPE_VERTEXSTATS
:
1430 case D3DQUERYTYPE_EVENT
:
1431 case D3DQUERYTYPE_TIMESTAMP
:
1432 case D3DQUERYTYPE_TIMESTAMPDISJOINT
:
1433 case D3DQUERYTYPE_TIMESTAMPFREQ
:
1434 case D3DQUERYTYPE_PIPELINETIMINGS
:
1435 case D3DQUERYTYPE_INTERFACETIMINGS
:
1436 case D3DQUERYTYPE_VERTEXTIMINGS
:
1437 case D3DQUERYTYPE_PIXELTIMINGS
:
1438 case D3DQUERYTYPE_BANDWIDTHTIMINGS
:
1439 case D3DQUERYTYPE_CACHEUTILIZATION
:
1441 object
->extendedData
= 0;
1442 FIXME("(%p) Unhandled query type %d\n",This
, Type
);
1444 TRACE("(%p) : Created Query %p\n", This
, object
);
1448 /* example at http://www.fairyengine.com/articles/dxmultiviews.htm */
1449 static HRESULT WINAPI
IWineD3DDeviceImpl_CreateAdditionalSwapChain(IWineD3DDevice
* iface
, WINED3DPRESENT_PARAMETERS
* pPresentationParameters
, IWineD3DSwapChain
** ppSwapChain
,
1451 D3DCB_CREATERENDERTARGETFN D3DCB_CreateRenderTarget
,
1452 D3DCB_CREATEDEPTHSTENCILSURFACEFN D3DCB_CreateDepthStencil
) {
1453 IWineD3DDeviceImpl
*This
= (IWineD3DDeviceImpl
*)iface
;
1456 IWineD3DSwapChainImpl
*object
; /** NOTE: impl ref allowed since this is a create function **/
1458 XVisualInfo
template;
1459 GLXContext oldContext
;
1460 Drawable oldDrawable
;
1461 HRESULT hr
= WINED3D_OK
;
1463 TRACE("(%p) : Created Aditional Swap Chain\n", This
);
1465 /** FIXME: Test under windows to find out what the life cycle of a swap chain is,
1466 * does a device hold a reference to a swap chain giving them a lifetime of the device
1467 * or does the swap chain notify the device of its destruction.
1468 *******************************/
1470 /* Check the params */
1471 if(*pPresentationParameters
->BackBufferCount
> D3DPRESENT_BACK_BUFFER_MAX
) {
1472 ERR("App requested %d back buffers, this is not supported for now\n", *pPresentationParameters
->BackBufferCount
);
1473 return WINED3DERR_INVALIDCALL
;
1474 } else if (*pPresentationParameters
->BackBufferCount
> 1) {
1475 FIXME("The app requests more than one back buffer, this can't be supported properly. Please configure the application to use double buffering(=1 back buffer) if possible\n");
1478 D3DCREATEOBJECTINSTANCE(object
, SwapChain
)
1480 /*********************
1481 * Lookup the window Handle and the relating X window handle
1482 ********************/
1484 /* Setup hwnd we are using, plus which display this equates to */
1485 object
->win_handle
= *(pPresentationParameters
->hDeviceWindow
);
1486 if (!object
->win_handle
) {
1487 object
->win_handle
= This
->createParms
.hFocusWindow
;
1490 object
->win_handle
= GetAncestor(object
->win_handle
, GA_ROOT
);
1491 if ( !( object
->win
= (Window
)GetPropA(object
->win_handle
, "__wine_x11_whole_window") ) ) {
1492 ERR("Can't get drawable (window), HWND:%p doesn't have the property __wine_x11_whole_window\n", object
->win_handle
);
1493 return WINED3DERR_NOTAVAILABLE
;
1495 hDc
= GetDC(object
->win_handle
);
1496 object
->display
= get_display(hDc
);
1497 ReleaseDC(object
->win_handle
, hDc
);
1498 TRACE("Using a display of %p %p\n", object
->display
, hDc
);
1500 if (NULL
== object
->display
|| NULL
== hDc
) {
1501 WARN("Failed to get a display and HDc for Window %p\n", object
->win_handle
);
1502 return WINED3DERR_NOTAVAILABLE
;
1505 if (object
->win
== 0) {
1506 WARN("Failed to get a valid XVisuial ID for the window %p\n", object
->win_handle
);
1507 return WINED3DERR_NOTAVAILABLE
;
1510 * Create an opengl context for the display visual
1511 * NOTE: the visual is chosen as the window is created and the glcontext cannot
1512 * use different properties after that point in time. FIXME: How to handle when requested format
1513 * doesn't match actual visual? Cannot choose one here - code removed as it ONLY works if the one
1514 * it chooses is identical to the one already being used!
1515 **********************************/
1517 /** FIXME: Handle stencil appropriately via EnableAutoDepthStencil / AutoDepthStencilFormat **/
1520 /* Create a new context for this swapchain */
1521 template.visualid
= (VisualID
)GetPropA(GetDesktopWindow(), "__wine_x11_visual_id");
1522 /* TODO: change this to find a similar visual, but one with a stencil/zbuffer buffer that matches the request
1523 (or the best possible if none is requested) */
1524 TRACE("Found x visual ID : %ld\n", template.visualid
);
1526 object
->visInfo
= XGetVisualInfo(object
->display
, VisualIDMask
, &template, &num
);
1527 if (NULL
== object
->visInfo
) {
1528 ERR("cannot really get XVisual\n");
1530 return WINED3DERR_NOTAVAILABLE
;
1533 /* Write out some debug info about the visual/s */
1534 TRACE("Using x visual ID : %ld\n", template.visualid
);
1535 TRACE(" visual info: %p\n", object
->visInfo
);
1536 TRACE(" num items : %d\n", num
);
1537 for (n
= 0;n
< num
; n
++) {
1538 TRACE("=====item=====: %d\n", n
+ 1);
1539 TRACE(" visualid : %ld\n", object
->visInfo
[n
].visualid
);
1540 TRACE(" screen : %d\n", object
->visInfo
[n
].screen
);
1541 TRACE(" depth : %u\n", object
->visInfo
[n
].depth
);
1542 TRACE(" class : %d\n", object
->visInfo
[n
].class);
1543 TRACE(" red_mask : %ld\n", object
->visInfo
[n
].red_mask
);
1544 TRACE(" green_mask : %ld\n", object
->visInfo
[n
].green_mask
);
1545 TRACE(" blue_mask : %ld\n", object
->visInfo
[n
].blue_mask
);
1546 TRACE(" colormap_size : %d\n", object
->visInfo
[n
].colormap_size
);
1547 TRACE(" bits_per_rgb : %d\n", object
->visInfo
[n
].bits_per_rgb
);
1548 /* log some extra glx info */
1549 glXGetConfig(object
->display
, object
->visInfo
, GLX_AUX_BUFFERS
, &value
);
1550 TRACE(" gl_aux_buffers : %d\n", value
);
1551 glXGetConfig(object
->display
, object
->visInfo
, GLX_BUFFER_SIZE
,&value
);
1552 TRACE(" gl_buffer_size : %d\n", value
);
1553 glXGetConfig(object
->display
, object
->visInfo
, GLX_RED_SIZE
, &value
);
1554 TRACE(" gl_red_size : %d\n", value
);
1555 glXGetConfig(object
->display
, object
->visInfo
, GLX_GREEN_SIZE
, &value
);
1556 TRACE(" gl_green_size : %d\n", value
);
1557 glXGetConfig(object
->display
, object
->visInfo
, GLX_BLUE_SIZE
, &value
);
1558 TRACE(" gl_blue_size : %d\n", value
);
1559 glXGetConfig(object
->display
, object
->visInfo
, GLX_ALPHA_SIZE
, &value
);
1560 TRACE(" gl_alpha_size : %d\n", value
);
1561 glXGetConfig(object
->display
, object
->visInfo
, GLX_DEPTH_SIZE
,&value
);
1562 TRACE(" gl_depth_size : %d\n", value
);
1563 glXGetConfig(object
->display
, object
->visInfo
, GLX_STENCIL_SIZE
, &value
);
1564 TRACE(" gl_stencil_size : %d\n", value
);
1566 /* Now choose a simila visual ID*/
1568 #ifdef USE_CONTEXT_MANAGER
1570 /** TODO: use a context mamager **/
1574 IWineD3DSwapChain
*implSwapChain
;
1575 if (WINED3D_OK
!= IWineD3DDevice_GetSwapChain(iface
, 0, &implSwapChain
)) {
1576 /* The first time around we create the context that is shared with all other swapchains and render targets */
1577 object
->glCtx
= glXCreateContext(object
->display
, object
->visInfo
, NULL
, GL_TRUE
);
1578 TRACE("Creating implicit context for vis %p, hwnd %p\n", object
->display
, object
->visInfo
);
1581 TRACE("Creating context for vis %p, hwnd %p\n", object
->display
, object
->visInfo
);
1582 /* TODO: don't use Impl structures outside of create functions! (a context manager will replace the ->glCtx) */
1583 /* and create a new context with the implicit swapchains context as the shared context */
1584 object
->glCtx
= glXCreateContext(object
->display
, object
->visInfo
, ((IWineD3DSwapChainImpl
*)implSwapChain
)->glCtx
, GL_TRUE
);
1585 IWineD3DSwapChain_Release(implSwapChain
);
1590 XFree(object
->visInfo
);
1591 object
->visInfo
= NULL
;
1595 if (!object
->glCtx
) {
1596 ERR("Failed to create GLX context\n");
1597 return WINED3DERR_NOTAVAILABLE
;
1599 TRACE("Context created (HWND=%p, glContext=%p, Window=%ld, VisInfo=%p)\n",
1600 object
->win_handle
, object
->glCtx
, object
->win
, object
->visInfo
);
1603 /*********************
1604 * Windowed / Fullscreen
1605 *******************/
1608 * TODO: MSDN says that we are only allowed one fullscreen swapchain per device,
1609 * so we should really check to see if there is a fullscreen swapchain already
1610 * I think Windows and X have different ideas about fullscreen, does a single head count as full screen?
1611 **************************************/
1613 if (!*(pPresentationParameters
->Windowed
)) {
1619 /* Get info on the current display setup */
1620 hdc
= CreateDCA("DISPLAY", NULL
, NULL
, NULL
);
1621 bpp
= GetDeviceCaps(hdc
, BITSPIXEL
);
1624 /* Change the display settings */
1625 memset(&devmode
, 0, sizeof(DEVMODEW
));
1626 devmode
.dmFields
= DM_BITSPERPEL
| DM_PELSWIDTH
| DM_PELSHEIGHT
;
1627 devmode
.dmBitsPerPel
= (bpp
>= 24) ? 32 : bpp
; /* Stupid XVidMode cannot change bpp */
1628 devmode
.dmPelsWidth
= *(pPresentationParameters
->BackBufferWidth
);
1629 devmode
.dmPelsHeight
= *(pPresentationParameters
->BackBufferHeight
);
1630 MultiByteToWideChar(CP_ACP
, 0, "Gamers CG", -1, devmode
.dmDeviceName
, CCHDEVICENAME
);
1631 ChangeDisplaySettingsExW(devmode
.dmDeviceName
, &devmode
, object
->win_handle
, CDS_FULLSCREEN
, NULL
);
1633 /* Make popup window */
1634 SetWindowLongA(object
->win_handle
, GWL_STYLE
, WS_POPUP
);
1635 SetWindowPos(object
->win_handle
, HWND_TOP
, 0, 0,
1636 *(pPresentationParameters
->BackBufferWidth
),
1637 *(pPresentationParameters
->BackBufferHeight
), SWP_SHOWWINDOW
| SWP_FRAMECHANGED
);
1639 /* For GetDisplayMode */
1640 This
->ddraw_width
= devmode
.dmPelsWidth
;
1641 This
->ddraw_height
= devmode
.dmPelsHeight
;
1642 This
->ddraw_format
= *(pPresentationParameters
->BackBufferFormat
);
1646 /** MSDN: If Windowed is TRUE and either of the BackBufferWidth/Height values is zero,
1647 * then the corresponding dimension of the client area of the hDeviceWindow
1648 * (or the focus window, if hDeviceWindow is NULL) is taken.
1649 **********************/
1651 if (*(pPresentationParameters
->Windowed
) &&
1652 ((*(pPresentationParameters
->BackBufferWidth
) == 0) ||
1653 (*(pPresentationParameters
->BackBufferHeight
) == 0))) {
1656 GetClientRect(object
->win_handle
, &Rect
);
1658 if (*(pPresentationParameters
->BackBufferWidth
) == 0) {
1659 *(pPresentationParameters
->BackBufferWidth
) = Rect
.right
;
1660 TRACE("Updating width to %d\n", *(pPresentationParameters
->BackBufferWidth
));
1662 if (*(pPresentationParameters
->BackBufferHeight
) == 0) {
1663 *(pPresentationParameters
->BackBufferHeight
) = Rect
.bottom
;
1664 TRACE("Updating height to %d\n", *(pPresentationParameters
->BackBufferHeight
));
1668 /*********************
1669 * finish off parameter initialization
1670 *******************/
1672 /* Put the correct figures in the presentation parameters */
1673 TRACE("Coppying accross presentaion paraneters\n");
1674 object
->presentParms
.BackBufferWidth
= *(pPresentationParameters
->BackBufferWidth
);
1675 object
->presentParms
.BackBufferHeight
= *(pPresentationParameters
->BackBufferHeight
);
1676 object
->presentParms
.BackBufferFormat
= *(pPresentationParameters
->BackBufferFormat
);
1677 object
->presentParms
.BackBufferCount
= *(pPresentationParameters
->BackBufferCount
);
1678 object
->presentParms
.MultiSampleType
= *(pPresentationParameters
->MultiSampleType
);
1679 object
->presentParms
.MultiSampleQuality
= NULL
== pPresentationParameters
->MultiSampleQuality
? 0 : *(pPresentationParameters
->MultiSampleQuality
);
1680 object
->presentParms
.SwapEffect
= *(pPresentationParameters
->SwapEffect
);
1681 object
->presentParms
.hDeviceWindow
= *(pPresentationParameters
->hDeviceWindow
);
1682 object
->presentParms
.Windowed
= *(pPresentationParameters
->Windowed
);
1683 object
->presentParms
.EnableAutoDepthStencil
= *(pPresentationParameters
->EnableAutoDepthStencil
);
1684 object
->presentParms
.AutoDepthStencilFormat
= *(pPresentationParameters
->AutoDepthStencilFormat
);
1685 object
->presentParms
.Flags
= *(pPresentationParameters
->Flags
);
1686 object
->presentParms
.FullScreen_RefreshRateInHz
= *(pPresentationParameters
->FullScreen_RefreshRateInHz
);
1687 object
->presentParms
.PresentationInterval
= *(pPresentationParameters
->PresentationInterval
);
1690 /*********************
1691 * Create the back, front and stencil buffers
1692 *******************/
1694 TRACE("calling rendertarget CB\n");
1695 hr
= D3DCB_CreateRenderTarget((IUnknown
*) This
->parent
,
1696 object
->presentParms
.BackBufferWidth
,
1697 object
->presentParms
.BackBufferHeight
,
1698 object
->presentParms
.BackBufferFormat
,
1699 object
->presentParms
.MultiSampleType
,
1700 object
->presentParms
.MultiSampleQuality
,
1701 TRUE
/* Lockable */,
1702 &object
->frontBuffer
,
1703 NULL
/* pShared (always null)*/);
1704 if (object
->frontBuffer
!= NULL
)
1705 IWineD3DSurface_SetContainer(object
->frontBuffer
, (IWineD3DBase
*)object
);
1707 if(object
->presentParms
.BackBufferCount
> 0) {
1710 object
->backBuffer
= HeapAlloc(GetProcessHeap(), 0, sizeof(IWineD3DSurface
*) * object
->presentParms
.BackBufferCount
);
1711 if(!object
->backBuffer
) {
1712 ERR("Out of memory\n");
1714 if (object
->frontBuffer
) {
1715 IUnknown
*bufferParent
;
1716 IWineD3DSurface_GetParent(object
->frontBuffer
, &bufferParent
);
1717 IUnknown_Release(bufferParent
); /* once for the get parent */
1718 if (IUnknown_Release(bufferParent
) > 0) {
1719 FIXME("(%p) Something's still holding the front buffer\n",This
);
1722 HeapFree(GetProcessHeap(), 0, object
);
1723 return E_OUTOFMEMORY
;
1726 for(i
= 0; i
< object
->presentParms
.BackBufferCount
; i
++) {
1727 TRACE("calling rendertarget CB\n");
1728 hr
= D3DCB_CreateRenderTarget((IUnknown
*) This
->parent
,
1729 object
->presentParms
.BackBufferWidth
,
1730 object
->presentParms
.BackBufferHeight
,
1731 object
->presentParms
.BackBufferFormat
,
1732 object
->presentParms
.MultiSampleType
,
1733 object
->presentParms
.MultiSampleQuality
,
1734 TRUE
/* Lockable */,
1735 &object
->backBuffer
[i
],
1736 NULL
/* pShared (always null)*/);
1737 if(hr
== WINED3D_OK
&& object
->backBuffer
[i
]) {
1738 IWineD3DSurface_SetContainer(object
->backBuffer
[i
], (IWineD3DBase
*)object
);
1744 object
->backBuffer
= NULL
;
1747 if (object
->backBuffer
!= NULL
) {
1749 glDrawBuffer(GL_BACK
);
1750 checkGLcall("glDrawBuffer(GL_BACK)");
1753 /* Single buffering - draw to front buffer */
1755 glDrawBuffer(GL_FRONT
);
1756 checkGLcall("glDrawBuffer(GL_FRONT)");
1760 /* Under directX swapchains share the depth stencil, so only create one depth-stencil */
1761 if (*(pPresentationParameters
->EnableAutoDepthStencil
) && hr
== WINED3D_OK
) {
1762 TRACE("Creating depth stencil buffer\n");
1763 if (This
->depthStencilBuffer
== NULL
) {
1764 hr
= D3DCB_CreateDepthStencil((IUnknown
*) This
->parent
,
1765 object
->presentParms
.BackBufferWidth
,
1766 object
->presentParms
.BackBufferHeight
,
1767 object
->presentParms
.AutoDepthStencilFormat
,
1768 object
->presentParms
.MultiSampleType
,
1769 object
->presentParms
.MultiSampleQuality
,
1770 FALSE
/* FIXME: Discard */,
1771 &This
->depthStencilBuffer
,
1772 NULL
/* pShared (always null)*/ );
1773 if (This
->depthStencilBuffer
!= NULL
)
1774 IWineD3DSurface_SetContainer(This
->depthStencilBuffer
, 0);
1777 /** TODO: A check on width, height and multisample types
1778 *(since the zbuffer must be at least as large as the render target and have the same multisample parameters)
1779 ****************************/
1780 object
->wantsDepthStencilBuffer
= TRUE
;
1782 object
->wantsDepthStencilBuffer
= FALSE
;
1785 TRACE("FrontBuf @ %p, BackBuf @ %p, DepthStencil %d\n",object
->frontBuffer
, object
->backBuffer
? object
->backBuffer
[0] : NULL
, object
->wantsDepthStencilBuffer
);
1788 /*********************
1789 * init the default renderTarget management
1790 *******************/
1791 object
->drawable
= object
->win
;
1792 object
->render_ctx
= object
->glCtx
;
1794 if (hr
== WINED3D_OK
) {
1795 /*********************
1796 * Setup some defaults and clear down the buffers
1797 *******************/
1799 /** save current context and drawable **/
1800 oldContext
= glXGetCurrentContext();
1801 oldDrawable
= glXGetCurrentDrawable();
1803 TRACE("Activating context (display %p context %p drawable %ld)!\n", object
->display
, object
->glCtx
, object
->win
);
1804 if (glXMakeCurrent(object
->display
, object
->win
, object
->glCtx
) == False
) {
1805 ERR("Error in setting current context (display %p context %p drawable %ld)!\n", object
->display
, object
->glCtx
, object
->win
);
1807 checkGLcall("glXMakeCurrent");
1809 TRACE("Setting up the screen\n");
1810 /* Clear the screen */
1811 glClearColor(1.0, 0.0, 0.0, 0.0);
1812 checkGLcall("glClearColor");
1815 glClearStencil(0xffff);
1817 checkGLcall("glClear");
1819 glColor3f(1.0, 1.0, 1.0);
1820 checkGLcall("glColor3f");
1822 glEnable(GL_LIGHTING
);
1823 checkGLcall("glEnable");
1825 glLightModeli(GL_LIGHT_MODEL_LOCAL_VIEWER
, GL_TRUE
);
1826 checkGLcall("glLightModeli(GL_LIGHT_MODEL_LOCAL_VIEWER, GL_TRUE);");
1828 glTexEnvf(GL_TEXTURE_ENV
, GL_TEXTURE_ENV_MODE
, GL_COMBINE_EXT
);
1829 checkGLcall("glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE_EXT);");
1831 glLightModeli(GL_LIGHT_MODEL_COLOR_CONTROL
, GL_SEPARATE_SPECULAR_COLOR
);
1832 checkGLcall("glLightModeli(GL_LIGHT_MODEL_COLOR_CONTROL, GL_SEPARATE_SPECULAR_COLOR);");
1834 /* switch back to the original context (if there was one)*/
1835 if (This
->swapchains
) {
1836 /** TODO: restore the context and drawable **/
1837 glXMakeCurrent(object
->display
, oldDrawable
, oldContext
);
1842 TRACE("Set swapchain to %p\n", object
);
1843 } else { /* something went wrong so clean up */
1844 IUnknown
* bufferParent
;
1845 if (object
->frontBuffer
) {
1847 IWineD3DSurface_GetParent(object
->frontBuffer
, &bufferParent
);
1848 IUnknown_Release(bufferParent
); /* once for the get parent */
1849 if (IUnknown_Release(bufferParent
) > 0) {
1850 FIXME("(%p) Something's still holding the front buffer\n",This
);
1853 if (object
->backBuffer
) {
1855 for(i
= 0; i
< object
->presentParms
.BackBufferCount
; i
++) {
1856 if(object
->backBuffer
[i
]) {
1857 IWineD3DSurface_GetParent(object
->backBuffer
[i
], &bufferParent
);
1858 IUnknown_Release(bufferParent
); /* once for the get parent */
1859 if (IUnknown_Release(bufferParent
) > 0) {
1860 FIXME("(%p) Something's still holding the back buffer\n",This
);
1864 HeapFree(GetProcessHeap(), 0, object
->backBuffer
);
1865 object
->backBuffer
= NULL
;
1867 /* NOTE: don't clean up the depthstencil buffer because it belongs to the device */
1868 /* Clean up the context */
1869 /* check that we are the current context first (we shouldn't be though!) */
1870 if (object
->glCtx
!= 0) {
1871 if(glXGetCurrentContext() == object
->glCtx
) {
1872 glXMakeCurrent(object
->display
, None
, NULL
);
1874 glXDestroyContext(object
->display
, object
->glCtx
);
1876 HeapFree(GetProcessHeap(), 0, object
);
1883 /** NOTE: These are ahead of the other getters and setters to save using a forward declaration **/
1884 static UINT WINAPI
IWineD3DDeviceImpl_GetNumberOfSwapChains(IWineD3DDevice
*iface
) {
1885 IWineD3DDeviceImpl
*This
= (IWineD3DDeviceImpl
*)iface
;
1886 TRACE("(%p)\n", This
);
1888 return This
->NumberOfSwapChains
;
1891 static HRESULT WINAPI
IWineD3DDeviceImpl_GetSwapChain(IWineD3DDevice
*iface
, UINT iSwapChain
, IWineD3DSwapChain
**pSwapChain
) {
1892 IWineD3DDeviceImpl
*This
= (IWineD3DDeviceImpl
*)iface
;
1893 TRACE("(%p) : swapchain %d\n", This
, iSwapChain
);
1895 if(iSwapChain
< This
->NumberOfSwapChains
) {
1896 *pSwapChain
= This
->swapchains
[iSwapChain
];
1897 IWineD3DSwapChain_AddRef(*pSwapChain
);
1898 TRACE("(%p) returning %p\n", This
, *pSwapChain
);
1901 TRACE("Swapchain out of range\n");
1903 return WINED3DERR_INVALIDCALL
;
1908 * Vertex Declaration
1910 static HRESULT WINAPI
IWineD3DDeviceImpl_CreateVertexDeclaration(IWineD3DDevice
* iface
, CONST VOID
* pDeclaration
, IWineD3DVertexDeclaration
** ppVertexDeclaration
, IUnknown
*parent
) {
1911 IWineD3DDeviceImpl
*This
= (IWineD3DDeviceImpl
*)iface
;
1912 IWineD3DVertexDeclarationImpl
*object
= NULL
;
1913 HRESULT hr
= WINED3D_OK
;
1914 TRACE("(%p) : directXVersion=%u, pFunction=%p, ppDecl=%p\n", This
, ((IWineD3DImpl
*)This
->wineD3D
)->dxVersion
, pDeclaration
, ppVertexDeclaration
);
1915 D3DCREATEOBJECTINSTANCE(object
, VertexDeclaration
)
1918 hr
= IWineD3DVertexDeclaration_SetDeclaration((IWineD3DVertexDeclaration
*)object
, (void *)pDeclaration
);
1923 /* http://msdn.microsoft.com/archive/default.asp?url=/archive/en-us/directx9_c/directx/graphics/programmingguide/programmable/vertexshaders/vscreate.asp */
1924 static HRESULT WINAPI
IWineD3DDeviceImpl_CreateVertexShader(IWineD3DDevice
*iface
, CONST DWORD
*pDeclaration
, CONST DWORD
*pFunction
, IWineD3DVertexShader
**ppVertexShader
, IUnknown
*parent
) {
1925 IWineD3DDeviceImpl
*This
= (IWineD3DDeviceImpl
*)iface
;
1926 IWineD3DVertexShaderImpl
*object
; /* NOTE: impl usage is ok, this is a create */
1927 HRESULT hr
= WINED3D_OK
;
1928 D3DCREATEOBJECTINSTANCE(object
, VertexShader
)
1929 object
->baseShader
.shader_ins
= IWineD3DVertexShaderImpl_shader_ins
;
1931 TRACE("(%p) : Created Vertex shader %p\n", This
, *ppVertexShader
);
1933 /* If a vertex declaration has been passed, save it to the vertex shader, this affects d3d8 only. */
1934 /* Further it needs to be set before calling SetFunction as SetFunction needs the declaration. */
1935 if (pDeclaration
!= NULL
) {
1936 IWineD3DVertexDeclaration
*vertexDeclaration
;
1937 hr
= IWineD3DDevice_CreateVertexDeclaration(iface
, pDeclaration
, &vertexDeclaration
,NULL
);
1938 if (WINED3D_OK
== hr
) {
1939 TRACE("(%p) : Setting vertex declaration to %p\n", This
, vertexDeclaration
);
1940 object
->vertexDeclaration
= vertexDeclaration
;
1942 FIXME("(%p) : Failed to set the declaration, returning WINED3DERR_INVALIDCALL\n", iface
);
1943 IWineD3DVertexShader_Release(*ppVertexShader
);
1944 return WINED3DERR_INVALIDCALL
;
1948 hr
= IWineD3DVertexShader_SetFunction(*ppVertexShader
, pFunction
);
1950 if (WINED3D_OK
!= hr
) {
1951 FIXME("(%p) : Failed to set the function, returning WINED3DERR_INVALIDCALL\n", iface
);
1952 IWineD3DVertexShader_Release(*ppVertexShader
);
1953 return WINED3DERR_INVALIDCALL
;
1956 #if 0 /* TODO: In D3D* SVP is atatched to the shader, in D3D9 it's attached to the device and isn't stored in the stateblock. */
1957 if(Usage
== WINED3DUSAGE_SOFTWAREVERTEXPROCESSING
) {
1968 static HRESULT WINAPI
IWineD3DDeviceImpl_CreatePixelShader(IWineD3DDevice
*iface
, CONST DWORD
*pFunction
, IWineD3DPixelShader
**ppPixelShader
, IUnknown
*parent
) {
1969 IWineD3DDeviceImpl
*This
= (IWineD3DDeviceImpl
*)iface
;
1970 IWineD3DPixelShaderImpl
*object
; /* NOTE: impl allowed, this is a create */
1971 HRESULT hr
= WINED3D_OK
;
1973 D3DCREATEOBJECTINSTANCE(object
, PixelShader
)
1974 object
->baseShader
.shader_ins
= IWineD3DPixelShaderImpl_shader_ins
;
1975 hr
= IWineD3DPixelShader_SetFunction(*ppPixelShader
, pFunction
);
1976 if (WINED3D_OK
== hr
) {
1977 TRACE("(%p) : Created Pixel shader %p\n", This
, *ppPixelShader
);
1979 WARN("(%p) : Failed to create pixel shader\n", This
);
1985 static HRESULT WINAPI
IWineD3DDeviceImpl_CreatePalette(IWineD3DDevice
*iface
, DWORD Flags
, PALETTEENTRY
*PalEnt
, IWineD3DPalette
**Palette
, IUnknown
*Parent
) {
1986 IWineD3DDeviceImpl
*This
= (IWineD3DDeviceImpl
*) iface
;
1987 IWineD3DPaletteImpl
*object
;
1989 TRACE("(%p)->(%lx, %p, %p, %p)\n", This
, Flags
, PalEnt
, Palette
, Parent
);
1991 /* Create the new object */
1992 object
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, sizeof(IWineD3DPaletteImpl
));
1994 ERR("Out of memory when allocating memory for a IWineD3DPalette implementation\n");
1995 return E_OUTOFMEMORY
;
1998 object
->lpVtbl
= &IWineD3DPalette_Vtbl
;
2000 object
->Flags
= Flags
;
2001 object
->parent
= Parent
;
2002 object
->wineD3DDevice
= This
;
2003 object
->palNumEntries
= IWineD3DPaletteImpl_Size(Flags
);
2005 object
->hpal
= CreatePalette((const LOGPALETTE
*)&(object
->palVersion
));
2008 HeapFree( GetProcessHeap(), 0, object
);
2009 return E_OUTOFMEMORY
;
2012 hr
= IWineD3DPalette_SetEntries((IWineD3DPalette
*) object
, 0, 0, IWineD3DPaletteImpl_Size(Flags
), PalEnt
);
2014 IWineD3DPalette_Release((IWineD3DPalette
*) object
);
2018 *Palette
= (IWineD3DPalette
*) object
;
2023 static HRESULT WINAPI
IWineD3DDeviceImpl_Init3D(IWineD3DDevice
*iface
, WINED3DPRESENT_PARAMETERS
* pPresentationParameters
, D3DCB_CREATEADDITIONALSWAPCHAIN D3DCB_CreateAdditionalSwapChain
) {
2024 IWineD3DDeviceImpl
*This
= (IWineD3DDeviceImpl
*) iface
;
2025 IWineD3DSwapChainImpl
*swapchain
;
2027 TRACE("(%p)->(%p,%p)\n", This
, pPresentationParameters
, D3DCB_CreateAdditionalSwapChain
);
2028 if(This
->d3d_initialized
) return WINED3DERR_INVALIDCALL
;
2030 /* TODO: Test if OpenGL is compiled in and loaded */
2032 /* Setup the implicit swapchain */
2033 TRACE("Creating implicit swapchain\n");
2034 if (D3D_OK
!= D3DCB_CreateAdditionalSwapChain((IUnknown
*) This
->parent
, pPresentationParameters
, (IWineD3DSwapChain
**)&swapchain
) || swapchain
== NULL
) {
2035 WARN("Failed to create implicit swapchain\n");
2036 return WINED3DERR_INVALIDCALL
;
2039 This
->NumberOfSwapChains
= 1;
2040 This
->swapchains
= HeapAlloc(GetProcessHeap(), 0, This
->NumberOfSwapChains
* sizeof(IWineD3DSwapChain
*));
2041 if(!This
->swapchains
) {
2042 ERR("Out of memory!\n");
2043 IWineD3DSwapChain_Release( (IWineD3DSwapChain
*) swapchain
);
2044 return E_OUTOFMEMORY
;
2046 This
->swapchains
[0] = (IWineD3DSwapChain
*) swapchain
;
2048 if(swapchain
->backBuffer
&& swapchain
->backBuffer
[0]) {
2049 TRACE("Setting rendertarget to %p\n", swapchain
->backBuffer
);
2050 This
->renderTarget
= swapchain
->backBuffer
[0];
2053 TRACE("Setting rendertarget to %p\n", swapchain
->frontBuffer
);
2054 This
->renderTarget
= swapchain
->frontBuffer
;
2056 IWineD3DSurface_AddRef(This
->renderTarget
);
2057 /* Depth Stencil support */
2058 This
->stencilBufferTarget
= This
->depthStencilBuffer
;
2059 if (NULL
!= This
->stencilBufferTarget
) {
2060 IWineD3DSurface_AddRef(This
->stencilBufferTarget
);
2063 /* Set up some starting GL setup */
2066 * Initialize openGL extension related variables
2067 * with Default values
2070 ((IWineD3DImpl
*) This
->wineD3D
)->isGLInfoValid
= IWineD3DImpl_FillGLCaps( This
->wineD3D
, swapchain
->display
);
2071 /* Setup all the devices defaults */
2072 IWineD3DStateBlock_InitStartupStateBlock((IWineD3DStateBlock
*)This
->stateBlock
);
2074 IWineD3DImpl_CheckGraphicsMemory();
2078 /* Initialize our list of GLSL programs */
2079 list_init(&This
->glsl_shader_progs
);
2081 { /* Set a default viewport */
2085 vp
.Width
= *(pPresentationParameters
->BackBufferWidth
);
2086 vp
.Height
= *(pPresentationParameters
->BackBufferHeight
);
2089 IWineD3DDevice_SetViewport((IWineD3DDevice
*)This
, &vp
);
2092 /* Initialize the current view state */
2093 This
->modelview_valid
= 1;
2094 This
->proj_valid
= 0;
2095 This
->view_ident
= 1;
2096 This
->last_was_rhw
= 0;
2097 glGetIntegerv(GL_MAX_LIGHTS
, &This
->maxConcurrentLights
);
2098 TRACE("(%p) All defaults now set up, leaving Init3D with %p\n", This
, This
);
2100 /* Clear the screen */
2101 IWineD3DDevice_Clear((IWineD3DDevice
*) This
, 0, NULL
, D3DCLEAR_STENCIL
|D3DCLEAR_ZBUFFER
|D3DCLEAR_TARGET
, 0x00, 1.0, 0);
2103 This
->d3d_initialized
= TRUE
;
2107 static HRESULT WINAPI
IWineD3DDeviceImpl_Uninit3D(IWineD3DDevice
*iface
) {
2108 IWineD3DDeviceImpl
*This
= (IWineD3DDeviceImpl
*) iface
;
2110 IUnknown
* stencilBufferParent
;
2111 IUnknown
* swapChainParent
;
2113 TRACE("(%p)\n", This
);
2115 if(!This
->d3d_initialized
) return WINED3DERR_INVALIDCALL
;
2117 /* Delete the mouse cursor texture */
2118 if(This
->cursorTexture
) {
2120 glDeleteTextures(1, &This
->cursorTexture
);
2122 This
->cursorTexture
= 0;
2125 for(sampler
= 0; sampler
< GL_LIMITS(sampler_stages
); ++sampler
) {
2126 IWineD3DDevice_SetTexture(iface
, sampler
, NULL
);
2129 /* Release the buffers (with sanity checks)*/
2130 TRACE("Releasing the depth stencil buffer at %p\n", This
->stencilBufferTarget
);
2131 if(This
->stencilBufferTarget
!= NULL
&& (IWineD3DSurface_Release(This
->stencilBufferTarget
) >0)){
2132 if(This
->depthStencilBuffer
!= This
->stencilBufferTarget
)
2133 FIXME("(%p) Something's still holding the depthStencilBuffer\n",This
);
2135 This
->stencilBufferTarget
= NULL
;
2137 TRACE("Releasing the render target at %p\n", This
->renderTarget
);
2138 if(IWineD3DSurface_Release(This
->renderTarget
) >0){
2139 /* This check is a bit silly, itshould be in swapchain_release FIXME("(%p) Something's still holding the renderTarget\n",This); */
2141 TRACE("Setting rendertarget to NULL\n");
2142 This
->renderTarget
= NULL
;
2144 if (This
->depthStencilBuffer
) {
2145 IWineD3DSurface_GetParent(This
->depthStencilBuffer
, &stencilBufferParent
);
2146 IUnknown_Release(stencilBufferParent
); /* once for the get parent */
2147 if(IUnknown_Release(stencilBufferParent
) >0){ /* the second time for when it was created */
2148 FIXME("(%p) Something's still holding the depthStencilBuffer\n",This
);
2150 This
->depthStencilBuffer
= NULL
;
2153 for(i
=0; i
< This
->NumberOfSwapChains
; i
++) {
2154 TRACE("Releasing the implicit swapchain %d\n", i
);
2155 /* Swapchain 0 is special because it's created in startup with a hanging parent, so we have to release its parent now */
2156 IWineD3DSwapChain_GetParent(This
->swapchains
[i
], &swapChainParent
);
2157 IUnknown_Release(swapChainParent
); /* once for the get parent */
2158 if (IUnknown_Release(swapChainParent
) > 0) { /* the second time for when it was created */
2159 FIXME("(%p) Something's still holding the implicit swapchain\n", This
);
2163 HeapFree(GetProcessHeap(), 0, This
->swapchains
);
2164 This
->swapchains
= NULL
;
2165 This
->NumberOfSwapChains
= 0;
2167 This
->d3d_initialized
= FALSE
;
2171 static HRESULT WINAPI
IWineD3DDeviceImpl_EnumDisplayModes(IWineD3DDevice
*iface
, DWORD Flags
, UINT Width
, UINT Height
, WINED3DFORMAT pixelformat
, LPVOID context
, D3DCB_ENUMDISPLAYMODESCALLBACK callback
) {
2172 IWineD3DDeviceImpl
*This
= (IWineD3DDeviceImpl
*)iface
;
2176 const PixelFormatDesc
*formatDesc
= getFormatDescEntry(pixelformat
);
2178 TRACE("(%p)->(%lx,%d,%d,%d,%p,%p)\n", This
, Flags
, Width
, Height
, pixelformat
, context
, callback
);
2180 for (i
= 0; EnumDisplaySettingsExW(NULL
, i
, &DevModeW
, 0); i
++) {
2181 /* Ignore some modes if a description was passed */
2182 if ( (Width
> 0) && (Width
!= DevModeW
.dmPelsWidth
)) continue;
2183 if ( (Height
> 0) && (Height
!= DevModeW
.dmPelsHeight
)) continue;
2184 if ( (pixelformat
!= WINED3DFMT_UNKNOWN
) && ( formatDesc
->bpp
!= DevModeW
.dmBitsPerPel
) ) continue;
2186 TRACE("Enumerating %ldx%ld@%s\n", DevModeW
.dmPelsWidth
, DevModeW
.dmPelsHeight
, debug_d3dformat(pixelformat_for_depth(DevModeW
.dmBitsPerPel
)));
2188 if (callback((IUnknown
*) This
, (UINT
) DevModeW
.dmPelsWidth
, (UINT
) DevModeW
.dmPelsHeight
, pixelformat_for_depth(DevModeW
.dmBitsPerPel
), 60.0, context
) == DDENUMRET_CANCEL
)
2195 static HRESULT WINAPI
IWineD3DDeviceImpl_SetDisplayMode(IWineD3DDevice
*iface
, UINT iSwapChain
, WINED3DDISPLAYMODE
* pMode
) {
2197 IWineD3DDeviceImpl
*This
= (IWineD3DDeviceImpl
*)iface
;
2199 const PixelFormatDesc
*formatDesc
= getFormatDescEntry(pMode
->Format
);
2201 TRACE("(%p)->(%d,%p) Mode=%dx%dx@%d, %s\n", This
, iSwapChain
, pMode
, pMode
->Width
, pMode
->Height
, pMode
->RefreshRate
, debug_d3dformat(pMode
->Format
));
2203 /* Resize the screen even without a window:
2204 * The app could have unset it with SetCooperativeLevel, but not called
2205 * RestoreDisplayMode first. Then the release will call RestoreDisplayMode,
2206 * but we don't have any hwnd
2209 devmode
.dmFields
= DM_BITSPERPEL
| DM_PELSWIDTH
| DM_PELSHEIGHT
;
2210 devmode
.dmBitsPerPel
= formatDesc
->bpp
* 8;
2211 if(devmode
.dmBitsPerPel
== 24) devmode
.dmBitsPerPel
= 32;
2212 devmode
.dmPelsWidth
= pMode
->Width
;
2213 devmode
.dmPelsHeight
= pMode
->Height
;
2215 devmode
.dmDisplayFrequency
= pMode
->RefreshRate
;
2216 if (pMode
->RefreshRate
!= 0) {
2217 devmode
.dmFields
|= DM_DISPLAYFREQUENCY
;
2220 /* Only change the mode if necessary */
2221 if( (This
->ddraw_width
== pMode
->Width
) &&
2222 (This
->ddraw_height
== pMode
->Height
) &&
2223 (This
->ddraw_format
== pMode
->Format
) &&
2224 (pMode
->RefreshRate
== 0) ) {
2228 ret
= ChangeDisplaySettingsExW(NULL
, &devmode
, NULL
, CDS_FULLSCREEN
, NULL
);
2229 if (ret
!= DISP_CHANGE_SUCCESSFUL
) {
2230 if(devmode
.dmDisplayFrequency
!= 0) {
2231 WARN("ChangeDisplaySettingsExW failed, trying without the refresh rate\n");
2232 devmode
.dmFields
&= ~DM_DISPLAYFREQUENCY
;
2233 devmode
.dmDisplayFrequency
= 0;
2234 ret
= ChangeDisplaySettingsExW(NULL
, &devmode
, NULL
, CDS_FULLSCREEN
, NULL
) != DISP_CHANGE_SUCCESSFUL
;
2236 if(ret
!= DISP_CHANGE_SUCCESSFUL
) {
2237 return DDERR_INVALIDMODE
;
2241 /* Store the new values */
2242 This
->ddraw_width
= pMode
->Width
;
2243 This
->ddraw_height
= pMode
->Height
;
2244 This
->ddraw_format
= pMode
->Format
;
2246 /* Only do this with a window of course */
2247 if(This
->ddraw_window
)
2248 MoveWindow(This
->ddraw_window
, 0, 0, pMode
->Width
, pMode
->Height
, TRUE
);
2253 static HRESULT WINAPI
IWineD3DDeviceImpl_GetDirect3D(IWineD3DDevice
*iface
, IWineD3D
**ppD3D
) {
2254 IWineD3DDeviceImpl
*This
= (IWineD3DDeviceImpl
*)iface
;
2255 *ppD3D
= This
->wineD3D
;
2256 TRACE("(%p) : wineD3D returning %p\n", This
, *ppD3D
);
2257 IWineD3D_AddRef(*ppD3D
);
2261 static UINT WINAPI
IWineD3DDeviceImpl_GetAvailableTextureMem(IWineD3DDevice
*iface
) {
2262 /** NOTE: There's a probably a hack-around for this one by putting as many pbuffers, VBO's (or whatever)
2263 * Into the video ram as possible and seeing how many fit
2264 * you can also get the correct initial value from nvidia and ATI's driver via X
2265 * texture memory is video memory + AGP memory
2266 *******************/
2267 IWineD3DDeviceImpl
*This
= (IWineD3DDeviceImpl
*)iface
;
2268 static BOOL showfixmes
= TRUE
;
2270 FIXME("(%p) : stub, simulating %dMB for now, returning %dMB left\n", This
,
2271 (wined3d_settings
.emulated_textureram
/(1024*1024)),
2272 ((wined3d_settings
.emulated_textureram
- wineD3DGlobalStatistics
->glsurfaceram
) / (1024*1024)));
2275 TRACE("(%p) : simulating %dMB, returning %dMB left\n", This
,
2276 (wined3d_settings
.emulated_textureram
/(1024*1024)),
2277 ((wined3d_settings
.emulated_textureram
- wineD3DGlobalStatistics
->glsurfaceram
) / (1024*1024)));
2278 /* return simulated texture memory left */
2279 return (wined3d_settings
.emulated_textureram
- wineD3DGlobalStatistics
->glsurfaceram
);
2287 static HRESULT WINAPI
IWineD3DDeviceImpl_SetFVF(IWineD3DDevice
*iface
, DWORD fvf
) {
2288 IWineD3DDeviceImpl
*This
= (IWineD3DDeviceImpl
*)iface
;
2289 HRESULT hr
= WINED3D_OK
;
2291 /* Update the current state block */
2292 This
->updateStateBlock
->fvf
= fvf
;
2293 This
->updateStateBlock
->changed
.fvf
= TRUE
;
2294 This
->updateStateBlock
->set
.fvf
= TRUE
;
2296 TRACE("(%p) : FVF Shader FVF set to %lx\n", This
, fvf
);
2301 static HRESULT WINAPI
IWineD3DDeviceImpl_GetFVF(IWineD3DDevice
*iface
, DWORD
*pfvf
) {
2302 IWineD3DDeviceImpl
*This
= (IWineD3DDeviceImpl
*)iface
;
2303 TRACE("(%p) : GetFVF returning %lx\n", This
, This
->stateBlock
->fvf
);
2304 *pfvf
= This
->stateBlock
->fvf
;
2309 * Get / Set Stream Source
2311 static HRESULT WINAPI
IWineD3DDeviceImpl_SetStreamSource(IWineD3DDevice
*iface
, UINT StreamNumber
,IWineD3DVertexBuffer
* pStreamData
, UINT OffsetInBytes
, UINT Stride
) {
2312 IWineD3DDeviceImpl
*This
= (IWineD3DDeviceImpl
*)iface
;
2313 IWineD3DVertexBuffer
*oldSrc
;
2315 /**TODO: instance and index data, see
2316 http://msdn.microsoft.com/library/default.asp?url=/library/en-us/directx9_c/directx/graphics/programmingguide/advancedtopics/DrawingMultipleInstances.asp
2318 http://msdn.microsoft.com/library/default.asp?url=/library/en-us/directx9_c/directx/graphics/reference/d3d/interfaces/idirect3ddevice9/SetStreamSourceFreq.asp
2321 /* D3d9 only, but shouldn't hurt d3d8 */
2324 streamFlags
= StreamNumber
&(D3DSTREAMSOURCE_INDEXEDDATA
| D3DSTREAMSOURCE_INSTANCEDATA
);
2326 if (streamFlags
& D3DSTREAMSOURCE_INDEXEDDATA
) {
2327 FIXME("stream index data not supported\n");
2329 if (streamFlags
& D3DSTREAMSOURCE_INDEXEDDATA
) {
2330 FIXME("stream instance data not supported\n");
2334 StreamNumber
&= ~(D3DSTREAMSOURCE_INDEXEDDATA
| D3DSTREAMSOURCE_INSTANCEDATA
);
2336 if (StreamNumber
>= MAX_STREAMS
) {
2337 WARN("Stream out of range %d\n", StreamNumber
);
2338 return WINED3DERR_INVALIDCALL
;
2341 oldSrc
= This
->stateBlock
->streamSource
[StreamNumber
];
2342 TRACE("(%p) : StreamNo: %d, OldStream (%p), NewStream (%p), NewStride %d\n", This
, StreamNumber
, oldSrc
, pStreamData
, Stride
);
2344 This
->updateStateBlock
->changed
.streamSource
[StreamNumber
] = TRUE
;
2345 This
->updateStateBlock
->set
.streamSource
[StreamNumber
] = TRUE
;
2346 This
->updateStateBlock
->streamStride
[StreamNumber
] = Stride
;
2347 This
->updateStateBlock
->streamSource
[StreamNumber
] = pStreamData
;
2348 This
->updateStateBlock
->streamOffset
[StreamNumber
] = OffsetInBytes
;
2349 This
->updateStateBlock
->streamFlags
[StreamNumber
] = streamFlags
;
2351 /* Handle recording of state blocks */
2352 if (This
->isRecordingState
) {
2353 TRACE("Recording... not performing anything\n");
2357 /* Same stream object: no action */
2358 if (oldSrc
== pStreamData
)
2361 /* Need to do a getParent and pass the reffs up */
2362 /* MSDN says ..... When an application no longer holds a references to this interface, the interface will automatically be freed.
2363 which suggests that we shouldn't be ref counting? and do need a _release on the stream source to reset the stream source
2364 so for now, just count internally */
2365 if (pStreamData
!= NULL
) {
2366 IWineD3DVertexBufferImpl
*vbImpl
= (IWineD3DVertexBufferImpl
*) pStreamData
;
2367 if( (vbImpl
->Flags
& VBFLAG_STREAM
) && vbImpl
->stream
!= StreamNumber
) {
2368 WARN("Assigning a Vertex Buffer to stream %d which is already assigned to stream %d\n", StreamNumber
, vbImpl
->stream
);
2370 vbImpl
->stream
= StreamNumber
;
2371 vbImpl
->Flags
|= VBFLAG_STREAM
;
2372 IWineD3DVertexBuffer_AddRef(pStreamData
);
2374 if (oldSrc
!= NULL
) {
2375 ((IWineD3DVertexBufferImpl
*) oldSrc
)->Flags
&= ~VBFLAG_STREAM
;
2376 IWineD3DVertexBuffer_Release(oldSrc
);
2382 static HRESULT WINAPI
IWineD3DDeviceImpl_GetStreamSource(IWineD3DDevice
*iface
, UINT StreamNumber
,IWineD3DVertexBuffer
** pStream
, UINT
*pOffset
, UINT
* pStride
) {
2383 IWineD3DDeviceImpl
*This
= (IWineD3DDeviceImpl
*)iface
;
2386 TRACE("(%p) : StreamNo: %d, Stream (%p), Stride %d\n", This
, StreamNumber
,
2387 This
->stateBlock
->streamSource
[StreamNumber
], This
->stateBlock
->streamStride
[StreamNumber
]);
2390 streamFlags
= StreamNumber
&(D3DSTREAMSOURCE_INDEXEDDATA
| D3DSTREAMSOURCE_INSTANCEDATA
);
2392 if (streamFlags
& D3DSTREAMSOURCE_INDEXEDDATA
) {
2393 FIXME("stream index data not supported\n");
2395 if (streamFlags
& D3DSTREAMSOURCE_INDEXEDDATA
) {
2396 FIXME("stream instance data not supported\n");
2400 StreamNumber
&= ~(D3DSTREAMSOURCE_INDEXEDDATA
| D3DSTREAMSOURCE_INSTANCEDATA
);
2402 if (StreamNumber
>= MAX_STREAMS
) {
2403 WARN("Stream out of range %d\n", StreamNumber
);
2404 return WINED3DERR_INVALIDCALL
;
2406 *pStream
= This
->stateBlock
->streamSource
[StreamNumber
];
2407 *pStride
= This
->stateBlock
->streamStride
[StreamNumber
];
2409 *pOffset
= This
->stateBlock
->streamOffset
[StreamNumber
];
2412 if (*pStream
== NULL
) {
2413 FIXME("Attempting to get an empty stream %d, returning WINED3DERR_INVALIDCALL\n", StreamNumber
);
2414 return WINED3DERR_INVALIDCALL
;
2417 IWineD3DVertexBuffer_AddRef(*pStream
); /* We have created a new reference to the VB */
2421 /*Should be quite easy, just an extension of vertexdata
2423 http://msdn.microsoft.com/archive/default.asp?url=/archive/en-us/directx9_c_Summer_04/directx/graphics/programmingguide/advancedtopics/DrawingMultipleInstances.asp
2425 The divider is a bit odd though
2427 VertexOffset = StartVertex / Divider * StreamStride +
2428 VertexIndex / Divider * StreamStride + StreamOffset
2431 static HRESULT WINAPI
IWineD3DDeviceImpl_SetStreamSourceFreq(IWineD3DDevice
*iface
, UINT StreamNumber
, UINT Divider
) {
2432 IWineD3DDeviceImpl
*This
= (IWineD3DDeviceImpl
*)iface
;
2434 TRACE("(%p) StreamNumber(%d), Divider(%d)\n", This
, StreamNumber
, Divider
);
2435 This
->updateStateBlock
->streamFlags
[StreamNumber
] = Divider
& (D3DSTREAMSOURCE_INSTANCEDATA
| D3DSTREAMSOURCE_INDEXEDDATA
);
2437 This
->updateStateBlock
->changed
.streamFreq
[StreamNumber
] = TRUE
;
2438 This
->updateStateBlock
->set
.streamFreq
[StreamNumber
] = TRUE
;
2439 This
->updateStateBlock
->streamFreq
[StreamNumber
] = Divider
& 0x7FFFFF;
2441 if (This
->updateStateBlock
->streamFlags
[StreamNumber
] || This
->updateStateBlock
->streamFreq
[StreamNumber
] != 1) {
2442 FIXME("Stream indexing not fully supported\n");
2448 static HRESULT WINAPI
IWineD3DDeviceImpl_GetStreamSourceFreq(IWineD3DDevice
*iface
, UINT StreamNumber
, UINT
* Divider
) {
2449 IWineD3DDeviceImpl
*This
= (IWineD3DDeviceImpl
*)iface
;
2451 TRACE("(%p) StreamNumber(%d), Divider(%p)\n", This
, StreamNumber
, Divider
);
2452 *Divider
= This
->updateStateBlock
->streamFreq
[StreamNumber
] | This
->updateStateBlock
->streamFlags
[StreamNumber
];
2454 TRACE("(%p) : returning %d\n", This
, *Divider
);
2460 * Get / Set & Multiply Transform
2462 static HRESULT WINAPI
IWineD3DDeviceImpl_SetTransform(IWineD3DDevice
*iface
, D3DTRANSFORMSTATETYPE d3dts
, CONST D3DMATRIX
* lpmatrix
) {
2463 IWineD3DDeviceImpl
*This
= (IWineD3DDeviceImpl
*)iface
;
2465 /* Most of this routine, comments included copied from ddraw tree initially: */
2466 TRACE("(%p) : Transform State=%s\n", This
, debug_d3dtstype(d3dts
));
2468 /* Handle recording of state blocks */
2469 if (This
->isRecordingState
) {
2470 TRACE("Recording... not performing anything\n");
2471 This
->updateStateBlock
->changed
.transform
[d3dts
] = TRUE
;
2472 This
->updateStateBlock
->set
.transform
[d3dts
] = TRUE
;
2473 memcpy(&This
->updateStateBlock
->transforms
[d3dts
], lpmatrix
, sizeof(D3DMATRIX
));
2478 * If the new matrix is the same as the current one,
2479 * we cut off any further processing. this seems to be a reasonable
2480 * optimization because as was noticed, some apps (warcraft3 for example)
2481 * tend towards setting the same matrix repeatedly for some reason.
2483 * From here on we assume that the new matrix is different, wherever it matters.
2485 if (!memcmp(&This
->stateBlock
->transforms
[d3dts
].u
.m
[0][0], lpmatrix
, sizeof(D3DMATRIX
))) {
2486 TRACE("The app is setting the same matrix over again\n");
2489 conv_mat(lpmatrix
, &This
->stateBlock
->transforms
[d3dts
].u
.m
[0][0]);
2493 ScreenCoord = ProjectionMat * ViewMat * WorldMat * ObjectCoord
2494 where ViewMat = Camera space, WorldMat = world space.
2496 In OpenGL, camera and world space is combined into GL_MODELVIEW
2497 matrix. The Projection matrix stay projection matrix.
2500 /* Capture the times we can just ignore the change for now */
2501 if (d3dts
== WINED3DTS_WORLDMATRIX(0)) {
2502 This
->modelview_valid
= FALSE
;
2505 } else if (d3dts
== WINED3DTS_PROJECTION
) {
2506 This
->proj_valid
= FALSE
;
2509 } else if (d3dts
>= WINED3DTS_WORLDMATRIX(1) && d3dts
<= WINED3DTS_WORLDMATRIX(255)) {
2510 /* Indexed Vertex Blending Matrices 256 -> 511 */
2511 /* Use arb_vertex_blend or NV_VERTEX_WEIGHTING? */
2512 FIXME("WINED3DTS_WORLDMATRIX(1..255) not handled\n");
2516 /* Now we really are going to have to change a matrix */
2519 if (d3dts
>= WINED3DTS_TEXTURE0
&& d3dts
<= WINED3DTS_TEXTURE7
) { /* handle texture matrices */
2520 /* This is now set with the texture unit states, it may be a good idea to flag the change though! */
2521 } else if (d3dts
== WINED3DTS_VIEW
) { /* handle the VIEW matrice */
2524 /* If we are changing the View matrix, reset the light and clipping planes to the new view
2525 * NOTE: We have to reset the positions even if the light/plane is not currently
2526 * enabled, since the call to enable it will not reset the position.
2527 * NOTE2: Apparently texture transforms do NOT need reapplying
2530 PLIGHTINFOEL
*lightChain
= NULL
;
2531 This
->modelview_valid
= FALSE
;
2532 This
->view_ident
= !memcmp(lpmatrix
, identity
, 16 * sizeof(float));
2534 glMatrixMode(GL_MODELVIEW
);
2535 checkGLcall("glMatrixMode(GL_MODELVIEW)");
2537 glLoadMatrixf((float *)lpmatrix
);
2538 checkGLcall("glLoadMatrixf(...)");
2541 lightChain
= This
->stateBlock
->lights
;
2542 while (lightChain
&& lightChain
->glIndex
!= -1) {
2543 glLightfv(GL_LIGHT0
+ lightChain
->glIndex
, GL_POSITION
, lightChain
->lightPosn
);
2544 checkGLcall("glLightfv posn");
2545 glLightfv(GL_LIGHT0
+ lightChain
->glIndex
, GL_SPOT_DIRECTION
, lightChain
->lightDirn
);
2546 checkGLcall("glLightfv dirn");
2547 lightChain
= lightChain
->next
;
2550 /* Reset Clipping Planes if clipping is enabled */
2551 for (k
= 0; k
< GL_LIMITS(clipplanes
); k
++) {
2552 glClipPlane(GL_CLIP_PLANE0
+ k
, This
->stateBlock
->clipplane
[k
]);
2553 checkGLcall("glClipPlane");
2557 } else { /* What was requested!?? */
2558 WARN("invalid matrix specified: %i\n", d3dts
);
2561 /* Release lock, all done */
2566 static HRESULT WINAPI
IWineD3DDeviceImpl_GetTransform(IWineD3DDevice
*iface
, D3DTRANSFORMSTATETYPE State
, D3DMATRIX
* pMatrix
) {
2567 IWineD3DDeviceImpl
*This
= (IWineD3DDeviceImpl
*)iface
;
2568 TRACE("(%p) : for Transform State %s\n", This
, debug_d3dtstype(State
));
2569 memcpy(pMatrix
, &This
->stateBlock
->transforms
[State
], sizeof(D3DMATRIX
));
2573 static HRESULT WINAPI
IWineD3DDeviceImpl_MultiplyTransform(IWineD3DDevice
*iface
, D3DTRANSFORMSTATETYPE State
, CONST D3DMATRIX
* pMatrix
) {
2574 D3DMATRIX
*mat
= NULL
;
2577 /* Note: Using 'updateStateBlock' rather than 'stateblock' in the code
2578 * below means it will be recorded in a state block change, but it
2579 * works regardless where it is recorded.
2580 * If this is found to be wrong, change to StateBlock.
2582 IWineD3DDeviceImpl
*This
= (IWineD3DDeviceImpl
*)iface
;
2583 TRACE("(%p) : For state %s\n", This
, debug_d3dtstype(State
));
2585 if (State
< HIGHEST_TRANSFORMSTATE
)
2587 mat
= &This
->updateStateBlock
->transforms
[State
];
2589 FIXME("Unhandled transform state!!\n");
2592 multiply_matrix(&temp
, mat
, (D3DMATRIX
*) pMatrix
);
2594 /* Apply change via set transform - will reapply to eg. lights this way */
2595 return IWineD3DDeviceImpl_SetTransform(iface
, State
, &temp
);
2600 * WARNING: This code relies on the fact that D3DLIGHT8 == D3DLIGHT9
2602 /* Note lights are real special cases. Although the device caps state only eg. 8 are supported,
2603 you can reference any indexes you want as long as that number max are enabled at any
2604 one point in time! Therefore since the indexes can be anything, we need a linked list of them.
2605 However, this causes stateblock problems. When capturing the state block, I duplicate the list,
2606 but when recording, just build a chain pretty much of commands to be replayed. */
2608 static HRESULT WINAPI
IWineD3DDeviceImpl_SetLight(IWineD3DDevice
*iface
, DWORD Index
, CONST WINED3DLIGHT
* pLight
) {
2610 PLIGHTINFOEL
*object
, *temp
;
2612 IWineD3DDeviceImpl
*This
= (IWineD3DDeviceImpl
*)iface
;
2613 TRACE("(%p) : Idx(%ld), pLight(%p)\n", This
, Index
, pLight
);
2615 /* If recording state block, just add to end of lights chain */
2616 if (This
->isRecordingState
) {
2617 object
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, sizeof(PLIGHTINFOEL
));
2618 if (NULL
== object
) {
2619 return WINED3DERR_OUTOFVIDEOMEMORY
;
2621 memcpy(&object
->OriginalParms
, pLight
, sizeof(D3DLIGHT9
));
2622 object
->OriginalIndex
= Index
;
2623 object
->glIndex
= -1;
2624 object
->changed
= TRUE
;
2626 /* Add to the END of the chain of lights changes to be replayed */
2627 if (This
->updateStateBlock
->lights
== NULL
) {
2628 This
->updateStateBlock
->lights
= object
;
2630 temp
= This
->updateStateBlock
->lights
;
2631 while (temp
->next
!= NULL
) temp
=temp
->next
;
2632 temp
->next
= object
;
2634 TRACE("Recording... not performing anything more\n");
2638 /* Ok, not recording any longer so do real work */
2639 object
= This
->stateBlock
->lights
;
2640 while (object
!= NULL
&& object
->OriginalIndex
!= Index
) object
= object
->next
;
2642 /* If we didn't find it in the list of lights, time to add it */
2643 if (object
== NULL
) {
2644 PLIGHTINFOEL
*insertAt
,*prevPos
;
2646 object
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, sizeof(PLIGHTINFOEL
));
2647 if (NULL
== object
) {
2648 return WINED3DERR_OUTOFVIDEOMEMORY
;
2650 object
->OriginalIndex
= Index
;
2651 object
->glIndex
= -1;
2653 /* Add it to the front of list with the idea that lights will be changed as needed
2654 BUT after any lights currently assigned GL indexes */
2655 insertAt
= This
->stateBlock
->lights
;
2657 while (insertAt
!= NULL
&& insertAt
->glIndex
!= -1) {
2659 insertAt
= insertAt
->next
;
2662 if (insertAt
== NULL
&& prevPos
== NULL
) { /* Start of list */
2663 This
->stateBlock
->lights
= object
;
2664 } else if (insertAt
== NULL
) { /* End of list */
2665 prevPos
->next
= object
;
2666 object
->prev
= prevPos
;
2667 } else { /* Middle of chain */
2668 if (prevPos
== NULL
) {
2669 This
->stateBlock
->lights
= object
;
2671 prevPos
->next
= object
;
2673 object
->prev
= prevPos
;
2674 object
->next
= insertAt
;
2675 insertAt
->prev
= object
;
2679 /* Initialize the object */
2680 TRACE("Light %ld setting to type %d, Diffuse(%f,%f,%f,%f), Specular(%f,%f,%f,%f), Ambient(%f,%f,%f,%f)\n", Index
, pLight
->Type
,
2681 pLight
->Diffuse
.r
, pLight
->Diffuse
.g
, pLight
->Diffuse
.b
, pLight
->Diffuse
.a
,
2682 pLight
->Specular
.r
, pLight
->Specular
.g
, pLight
->Specular
.b
, pLight
->Specular
.a
,
2683 pLight
->Ambient
.r
, pLight
->Ambient
.g
, pLight
->Ambient
.b
, pLight
->Ambient
.a
);
2684 TRACE("... Pos(%f,%f,%f), Dirn(%f,%f,%f)\n", pLight
->Position
.x
, pLight
->Position
.y
, pLight
->Position
.z
,
2685 pLight
->Direction
.x
, pLight
->Direction
.y
, pLight
->Direction
.z
);
2686 TRACE("... Range(%f), Falloff(%f), Theta(%f), Phi(%f)\n", pLight
->Range
, pLight
->Falloff
, pLight
->Theta
, pLight
->Phi
);
2688 /* Save away the information */
2689 memcpy(&object
->OriginalParms
, pLight
, sizeof(D3DLIGHT9
));
2691 switch (pLight
->Type
) {
2692 case D3DLIGHT_POINT
:
2694 object
->lightPosn
[0] = pLight
->Position
.x
;
2695 object
->lightPosn
[1] = pLight
->Position
.y
;
2696 object
->lightPosn
[2] = pLight
->Position
.z
;
2697 object
->lightPosn
[3] = 1.0f
;
2698 object
->cutoff
= 180.0f
;
2702 case D3DLIGHT_DIRECTIONAL
:
2704 object
->lightPosn
[0] = -pLight
->Direction
.x
;
2705 object
->lightPosn
[1] = -pLight
->Direction
.y
;
2706 object
->lightPosn
[2] = -pLight
->Direction
.z
;
2707 object
->lightPosn
[3] = 0.0;
2708 object
->exponent
= 0.0f
;
2709 object
->cutoff
= 180.0f
;
2714 object
->lightPosn
[0] = pLight
->Position
.x
;
2715 object
->lightPosn
[1] = pLight
->Position
.y
;
2716 object
->lightPosn
[2] = pLight
->Position
.z
;
2717 object
->lightPosn
[3] = 1.0;
2720 object
->lightDirn
[0] = pLight
->Direction
.x
;
2721 object
->lightDirn
[1] = pLight
->Direction
.y
;
2722 object
->lightDirn
[2] = pLight
->Direction
.z
;
2723 object
->lightDirn
[3] = 1.0;
2726 * opengl-ish and d3d-ish spot lights use too different models for the
2727 * light "intensity" as a function of the angle towards the main light direction,
2728 * so we only can approximate very roughly.
2729 * however spot lights are rather rarely used in games (if ever used at all).
2730 * furthermore if still used, probably nobody pays attention to such details.
2732 if (pLight
->Falloff
== 0) {
2735 rho
= pLight
->Theta
+ (pLight
->Phi
- pLight
->Theta
)/(2*pLight
->Falloff
);
2737 if (rho
< 0.0001) rho
= 0.0001f
;
2738 object
->exponent
= -0.3/log(cos(rho
/2));
2739 object
->cutoff
= pLight
->Phi
*90/M_PI
;
2745 FIXME("Unrecognized light type %d\n", pLight
->Type
);
2748 /* Update the live definitions if the light is currently assigned a glIndex */
2749 if (object
->glIndex
!= -1) {
2750 setup_light(iface
, object
->glIndex
, object
);
2755 static HRESULT WINAPI
IWineD3DDeviceImpl_GetLight(IWineD3DDevice
*iface
, DWORD Index
, WINED3DLIGHT
* pLight
) {
2756 PLIGHTINFOEL
*lightInfo
= NULL
;
2757 IWineD3DDeviceImpl
*This
= (IWineD3DDeviceImpl
*)iface
;
2758 TRACE("(%p) : Idx(%ld), pLight(%p)\n", This
, Index
, pLight
);
2760 /* Locate the light in the live lights */
2761 lightInfo
= This
->stateBlock
->lights
;
2762 while (lightInfo
!= NULL
&& lightInfo
->OriginalIndex
!= Index
) lightInfo
= lightInfo
->next
;
2764 if (lightInfo
== NULL
) {
2765 TRACE("Light information requested but light not defined\n");
2766 return WINED3DERR_INVALIDCALL
;
2769 memcpy(pLight
, &lightInfo
->OriginalParms
, sizeof(D3DLIGHT9
));
2774 * Get / Set Light Enable
2775 * (Note for consistency, renamed d3dx function by adding the 'set' prefix)
2777 static HRESULT WINAPI
IWineD3DDeviceImpl_SetLightEnable(IWineD3DDevice
*iface
, DWORD Index
, BOOL Enable
) {
2778 PLIGHTINFOEL
*lightInfo
= NULL
;
2779 IWineD3DDeviceImpl
*This
= (IWineD3DDeviceImpl
*)iface
;
2780 TRACE("(%p) : Idx(%ld), enable? %d\n", This
, Index
, Enable
);
2782 /* Tests show true = 128...not clear why */
2784 Enable
= Enable
? 128: 0;
2786 /* If recording state block, just add to end of lights chain with changedEnable set to true */
2787 if (This
->isRecordingState
) {
2788 lightInfo
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, sizeof(PLIGHTINFOEL
));
2789 if (NULL
== lightInfo
) {
2790 return WINED3DERR_OUTOFVIDEOMEMORY
;
2792 lightInfo
->OriginalIndex
= Index
;
2793 lightInfo
->glIndex
= -1;
2794 lightInfo
->enabledChanged
= TRUE
;
2795 lightInfo
->lightEnabled
= Enable
;
2797 /* Add to the END of the chain of lights changes to be replayed */
2798 if (This
->updateStateBlock
->lights
== NULL
) {
2799 This
->updateStateBlock
->lights
= lightInfo
;
2801 PLIGHTINFOEL
*temp
= This
->updateStateBlock
->lights
;
2802 while (temp
->next
!= NULL
) temp
=temp
->next
;
2803 temp
->next
= lightInfo
;
2805 TRACE("Recording... not performing anything more\n");
2809 /* Not recording... So, locate the light in the live lights */
2810 lightInfo
= This
->stateBlock
->lights
;
2811 while (lightInfo
!= NULL
&& lightInfo
->OriginalIndex
!= Index
) lightInfo
= lightInfo
->next
;
2813 /* Special case - enabling an undefined light creates one with a strict set of parms! */
2814 if (lightInfo
== NULL
) {
2816 TRACE("Light enabled requested but light not defined, so defining one!\n");
2817 IWineD3DDeviceImpl_SetLight(iface
, Index
, &WINED3D_default_light
);
2819 /* Search for it again! Should be fairly quick as near head of list */
2820 lightInfo
= This
->stateBlock
->lights
;
2821 while (lightInfo
!= NULL
&& lightInfo
->OriginalIndex
!= Index
) lightInfo
= lightInfo
->next
;
2822 if (lightInfo
== NULL
) {
2823 FIXME("Adding default lights has failed dismally\n");
2824 return WINED3DERR_INVALIDCALL
;
2828 /* OK, we now have a light... */
2829 if (Enable
== FALSE
) {
2831 /* If we are disabling it, check it was enabled, and
2832 still only do something if it has assigned a glIndex (which it should have!) */
2833 if ((lightInfo
->lightEnabled
) && (lightInfo
->glIndex
!= -1)) {
2834 TRACE("Disabling light set up at gl idx %ld\n", lightInfo
->glIndex
);
2836 glDisable(GL_LIGHT0
+ lightInfo
->glIndex
);
2837 checkGLcall("glDisable GL_LIGHT0+Index");
2840 TRACE("Nothing to do as light was not enabled\n");
2842 lightInfo
->lightEnabled
= Enable
;
2845 /* We are enabling it. If it is enabled, it's really simple */
2846 if (lightInfo
->lightEnabled
) {
2848 TRACE("Nothing to do as light was enabled\n");
2850 /* If it already has a glIndex, it's still simple */
2851 } else if (lightInfo
->glIndex
!= -1) {
2852 TRACE("Reusing light as already set up at gl idx %ld\n", lightInfo
->glIndex
);
2853 lightInfo
->lightEnabled
= Enable
;
2855 glEnable(GL_LIGHT0
+ lightInfo
->glIndex
);
2856 checkGLcall("glEnable GL_LIGHT0+Index already setup");
2859 /* Otherwise got to find space - lights are ordered gl indexes first */
2861 PLIGHTINFOEL
*bsf
= NULL
;
2862 PLIGHTINFOEL
*pos
= This
->stateBlock
->lights
;
2863 PLIGHTINFOEL
*prev
= NULL
;
2867 /* Try to minimize changes as much as possible */
2868 while (pos
!= NULL
&& pos
->glIndex
!= -1 && Index
< This
->maxConcurrentLights
) {
2870 /* Try to remember which index can be replaced if necessary */
2871 if (bsf
==NULL
&& pos
->lightEnabled
== FALSE
) {
2872 /* Found a light we can replace, save as best replacement */
2876 /* Step to next space */
2882 /* If we have too many active lights, fail the call */
2883 if ((Index
== This
->maxConcurrentLights
) && (bsf
== NULL
)) {
2884 FIXME("Program requests too many concurrent lights\n");
2885 return WINED3DERR_INVALIDCALL
;
2887 /* If we have allocated all lights, but not all are enabled,
2888 reuse one which is not enabled */
2889 } else if (Index
== This
->maxConcurrentLights
) {
2890 /* use bsf - Simply swap the new light and the BSF one */
2891 PLIGHTINFOEL
*bsfNext
= bsf
->next
;
2892 PLIGHTINFOEL
*bsfPrev
= bsf
->prev
;
2895 if (lightInfo
->next
!= NULL
) lightInfo
->next
->prev
= bsf
;
2896 if (bsf
->prev
!= NULL
) {
2897 bsf
->prev
->next
= lightInfo
;
2899 This
->stateBlock
->lights
= lightInfo
;
2902 /* If not side by side, lots of chains to update */
2903 if (bsf
->next
!= lightInfo
) {
2904 lightInfo
->prev
->next
= bsf
;
2905 bsf
->next
->prev
= lightInfo
;
2906 bsf
->next
= lightInfo
->next
;
2907 bsf
->prev
= lightInfo
->prev
;
2908 lightInfo
->next
= bsfNext
;
2909 lightInfo
->prev
= bsfPrev
;
2913 bsf
->prev
= lightInfo
;
2914 bsf
->next
= lightInfo
->next
;
2915 lightInfo
->next
= bsf
;
2916 lightInfo
->prev
= bsfPrev
;
2921 glIndex
= bsf
->glIndex
;
2923 lightInfo
->glIndex
= glIndex
;
2924 lightInfo
->lightEnabled
= Enable
;
2926 /* Finally set up the light in gl itself */
2927 TRACE("Replacing light which was set up at gl idx %ld\n", lightInfo
->glIndex
);
2929 setup_light(iface
, glIndex
, lightInfo
);
2930 glEnable(GL_LIGHT0
+ glIndex
);
2931 checkGLcall("glEnable GL_LIGHT0 new setup");
2934 /* If we reached the end of the allocated lights, with space in the
2935 gl lights, setup a new light */
2936 } else if (pos
->glIndex
== -1) {
2938 /* We reached the end of the allocated gl lights, so already
2939 know the index of the next one! */
2941 lightInfo
->glIndex
= glIndex
;
2942 lightInfo
->lightEnabled
= Enable
;
2944 /* In an ideal world, it's already in the right place */
2945 if (lightInfo
->prev
== NULL
|| lightInfo
->prev
->glIndex
!=-1) {
2946 /* No need to move it */
2948 /* Remove this light from the list */
2949 lightInfo
->prev
->next
= lightInfo
->next
;
2950 if (lightInfo
->next
!= NULL
) {
2951 lightInfo
->next
->prev
= lightInfo
->prev
;
2954 /* Add in at appropriate place (inbetween prev and pos) */
2955 lightInfo
->prev
= prev
;
2956 lightInfo
->next
= pos
;
2958 This
->stateBlock
->lights
= lightInfo
;
2960 prev
->next
= lightInfo
;
2963 pos
->prev
= lightInfo
;
2967 /* Finally set up the light in gl itself */
2968 TRACE("Defining new light at gl idx %ld\n", lightInfo
->glIndex
);
2970 setup_light(iface
, glIndex
, lightInfo
);
2971 glEnable(GL_LIGHT0
+ glIndex
);
2972 checkGLcall("glEnable GL_LIGHT0 new setup");
2981 static HRESULT WINAPI
IWineD3DDeviceImpl_GetLightEnable(IWineD3DDevice
*iface
, DWORD Index
,BOOL
* pEnable
) {
2983 PLIGHTINFOEL
*lightInfo
= NULL
;
2984 IWineD3DDeviceImpl
*This
= (IWineD3DDeviceImpl
*)iface
;
2985 TRACE("(%p) : for idx(%ld)\n", This
, Index
);
2987 /* Locate the light in the live lights */
2988 lightInfo
= This
->stateBlock
->lights
;
2989 while (lightInfo
!= NULL
&& lightInfo
->OriginalIndex
!= Index
) lightInfo
= lightInfo
->next
;
2991 if (lightInfo
== NULL
) {
2992 TRACE("Light enabled state requested but light not defined\n");
2993 return WINED3DERR_INVALIDCALL
;
2995 *pEnable
= lightInfo
->lightEnabled
;
3000 * Get / Set Clip Planes
3002 static HRESULT WINAPI
IWineD3DDeviceImpl_SetClipPlane(IWineD3DDevice
*iface
, DWORD Index
, CONST
float *pPlane
) {
3003 IWineD3DDeviceImpl
*This
= (IWineD3DDeviceImpl
*)iface
;
3004 TRACE("(%p) : for idx %ld, %p\n", This
, Index
, pPlane
);
3006 /* Validate Index */
3007 if (Index
>= GL_LIMITS(clipplanes
)) {
3008 TRACE("Application has requested clipplane this device doesn't support\n");
3009 return WINED3DERR_INVALIDCALL
;
3012 This
->updateStateBlock
->changed
.clipplane
[Index
] = TRUE
;
3013 This
->updateStateBlock
->set
.clipplane
[Index
] = TRUE
;
3014 This
->updateStateBlock
->clipplane
[Index
][0] = pPlane
[0];
3015 This
->updateStateBlock
->clipplane
[Index
][1] = pPlane
[1];
3016 This
->updateStateBlock
->clipplane
[Index
][2] = pPlane
[2];
3017 This
->updateStateBlock
->clipplane
[Index
][3] = pPlane
[3];
3019 /* Handle recording of state blocks */
3020 if (This
->isRecordingState
) {
3021 TRACE("Recording... not performing anything\n");
3029 /* Clip Plane settings are affected by the model view in OpenGL, the View transform in direct3d */
3030 glMatrixMode(GL_MODELVIEW
);
3032 glLoadMatrixf((float *) &This
->stateBlock
->transforms
[WINED3DTS_VIEW
].u
.m
[0][0]);
3034 TRACE("Clipplane [%f,%f,%f,%f]\n",
3035 This
->updateStateBlock
->clipplane
[Index
][0],
3036 This
->updateStateBlock
->clipplane
[Index
][1],
3037 This
->updateStateBlock
->clipplane
[Index
][2],
3038 This
->updateStateBlock
->clipplane
[Index
][3]);
3039 glClipPlane(GL_CLIP_PLANE0
+ Index
, This
->updateStateBlock
->clipplane
[Index
]);
3040 checkGLcall("glClipPlane");
3048 static HRESULT WINAPI
IWineD3DDeviceImpl_GetClipPlane(IWineD3DDevice
*iface
, DWORD Index
, float *pPlane
) {
3049 IWineD3DDeviceImpl
*This
= (IWineD3DDeviceImpl
*)iface
;
3050 TRACE("(%p) : for idx %ld\n", This
, Index
);
3052 /* Validate Index */
3053 if (Index
>= GL_LIMITS(clipplanes
)) {
3054 TRACE("Application has requested clipplane this device doesn't support\n");
3055 return WINED3DERR_INVALIDCALL
;
3058 pPlane
[0] = This
->stateBlock
->clipplane
[Index
][0];
3059 pPlane
[1] = This
->stateBlock
->clipplane
[Index
][1];
3060 pPlane
[2] = This
->stateBlock
->clipplane
[Index
][2];
3061 pPlane
[3] = This
->stateBlock
->clipplane
[Index
][3];
3066 * Get / Set Clip Plane Status
3067 * WARNING: This code relies on the fact that D3DCLIPSTATUS8 == D3DCLIPSTATUS9
3069 static HRESULT WINAPI
IWineD3DDeviceImpl_SetClipStatus(IWineD3DDevice
*iface
, CONST WINED3DCLIPSTATUS
* pClipStatus
) {
3070 IWineD3DDeviceImpl
*This
= (IWineD3DDeviceImpl
*)iface
;
3071 FIXME("(%p) : stub\n", This
);
3072 if (NULL
== pClipStatus
) {
3073 return WINED3DERR_INVALIDCALL
;
3075 This
->updateStateBlock
->clip_status
.ClipUnion
= pClipStatus
->ClipUnion
;
3076 This
->updateStateBlock
->clip_status
.ClipIntersection
= pClipStatus
->ClipIntersection
;
3080 static HRESULT WINAPI
IWineD3DDeviceImpl_GetClipStatus(IWineD3DDevice
*iface
, WINED3DCLIPSTATUS
* pClipStatus
) {
3081 IWineD3DDeviceImpl
*This
= (IWineD3DDeviceImpl
*)iface
;
3082 FIXME("(%p) : stub\n", This
);
3083 if (NULL
== pClipStatus
) {
3084 return WINED3DERR_INVALIDCALL
;
3086 pClipStatus
->ClipUnion
= This
->updateStateBlock
->clip_status
.ClipUnion
;
3087 pClipStatus
->ClipIntersection
= This
->updateStateBlock
->clip_status
.ClipIntersection
;
3092 * Get / Set Material
3093 * WARNING: This code relies on the fact that D3DMATERIAL8 == D3DMATERIAL9
3095 static HRESULT WINAPI
IWineD3DDeviceImpl_SetMaterial(IWineD3DDevice
*iface
, CONST WINED3DMATERIAL
* pMaterial
) {
3096 IWineD3DDeviceImpl
*This
= (IWineD3DDeviceImpl
*)iface
;
3098 This
->updateStateBlock
->changed
.material
= TRUE
;
3099 This
->updateStateBlock
->set
.material
= TRUE
;
3100 memcpy(&This
->updateStateBlock
->material
, pMaterial
, sizeof(WINED3DMATERIAL
));
3102 /* Handle recording of state blocks */
3103 if (This
->isRecordingState
) {
3104 TRACE("Recording... not performing anything\n");
3109 TRACE("(%p) : Diffuse (%f,%f,%f,%f)\n", This
, pMaterial
->Diffuse
.r
, pMaterial
->Diffuse
.g
,
3110 pMaterial
->Diffuse
.b
, pMaterial
->Diffuse
.a
);
3111 TRACE("(%p) : Ambient (%f,%f,%f,%f)\n", This
, pMaterial
->Ambient
.r
, pMaterial
->Ambient
.g
,
3112 pMaterial
->Ambient
.b
, pMaterial
->Ambient
.a
);
3113 TRACE("(%p) : Specular (%f,%f,%f,%f)\n", This
, pMaterial
->Specular
.r
, pMaterial
->Specular
.g
,
3114 pMaterial
->Specular
.b
, pMaterial
->Specular
.a
);
3115 TRACE("(%p) : Emissive (%f,%f,%f,%f)\n", This
, pMaterial
->Emissive
.r
, pMaterial
->Emissive
.g
,
3116 pMaterial
->Emissive
.b
, pMaterial
->Emissive
.a
);
3117 TRACE("(%p) : Power (%f)\n", This
, pMaterial
->Power
);
3119 glMaterialfv(GL_FRONT_AND_BACK
, GL_AMBIENT
, (float*) &This
->updateStateBlock
->material
.Ambient
);
3120 checkGLcall("glMaterialfv(GL_AMBIENT)");
3121 glMaterialfv(GL_FRONT_AND_BACK
, GL_DIFFUSE
, (float*) &This
->updateStateBlock
->material
.Diffuse
);
3122 checkGLcall("glMaterialfv(GL_DIFFUSE)");
3124 /* Only change material color if specular is enabled, otherwise it is set to black */
3125 if (This
->stateBlock
->renderState
[WINED3DRS_SPECULARENABLE
]) {
3126 glMaterialfv(GL_FRONT_AND_BACK
, GL_SPECULAR
, (float*) &This
->updateStateBlock
->material
.Specular
);
3127 checkGLcall("glMaterialfv(GL_SPECULAR");
3129 float black
[4] = {0.0f
, 0.0f
, 0.0f
, 0.0f
};
3130 glMaterialfv(GL_FRONT_AND_BACK
, GL_SPECULAR
, &black
[0]);
3131 checkGLcall("glMaterialfv(GL_SPECULAR");
3133 glMaterialfv(GL_FRONT_AND_BACK
, GL_EMISSION
, (float*) &This
->updateStateBlock
->material
.Emissive
);
3134 checkGLcall("glMaterialfv(GL_EMISSION)");
3135 glMaterialf(GL_FRONT_AND_BACK
, GL_SHININESS
, This
->updateStateBlock
->material
.Power
);
3136 checkGLcall("glMaterialf(GL_SHININESS");
3142 static HRESULT WINAPI
IWineD3DDeviceImpl_GetMaterial(IWineD3DDevice
*iface
, WINED3DMATERIAL
* pMaterial
) {
3143 IWineD3DDeviceImpl
*This
= (IWineD3DDeviceImpl
*)iface
;
3144 memcpy(pMaterial
, &This
->updateStateBlock
->material
, sizeof (WINED3DMATERIAL
));
3145 TRACE("(%p) : Diffuse (%f,%f,%f,%f)\n", This
, pMaterial
->Diffuse
.r
, pMaterial
->Diffuse
.g
,
3146 pMaterial
->Diffuse
.b
, pMaterial
->Diffuse
.a
);
3147 TRACE("(%p) : Ambient (%f,%f,%f,%f)\n", This
, pMaterial
->Ambient
.r
, pMaterial
->Ambient
.g
,
3148 pMaterial
->Ambient
.b
, pMaterial
->Ambient
.a
);
3149 TRACE("(%p) : Specular (%f,%f,%f,%f)\n", This
, pMaterial
->Specular
.r
, pMaterial
->Specular
.g
,
3150 pMaterial
->Specular
.b
, pMaterial
->Specular
.a
);
3151 TRACE("(%p) : Emissive (%f,%f,%f,%f)\n", This
, pMaterial
->Emissive
.r
, pMaterial
->Emissive
.g
,
3152 pMaterial
->Emissive
.b
, pMaterial
->Emissive
.a
);
3153 TRACE("(%p) : Power (%f)\n", This
, pMaterial
->Power
);
3161 static HRESULT WINAPI
IWineD3DDeviceImpl_SetIndices(IWineD3DDevice
*iface
, IWineD3DIndexBuffer
* pIndexData
,
3162 UINT BaseVertexIndex
) {
3163 IWineD3DDeviceImpl
*This
= (IWineD3DDeviceImpl
*)iface
;
3164 IWineD3DIndexBuffer
*oldIdxs
;
3166 TRACE("(%p) : Setting to %p, base %d\n", This
, pIndexData
, BaseVertexIndex
);
3167 oldIdxs
= This
->updateStateBlock
->pIndexData
;
3169 This
->updateStateBlock
->changed
.indices
= TRUE
;
3170 This
->updateStateBlock
->set
.indices
= TRUE
;
3171 This
->updateStateBlock
->pIndexData
= pIndexData
;
3172 This
->updateStateBlock
->baseVertexIndex
= BaseVertexIndex
;
3174 /* Handle recording of state blocks */
3175 if (This
->isRecordingState
) {
3176 TRACE("Recording... not performing anything\n");
3180 if (NULL
!= pIndexData
) {
3181 IWineD3DIndexBuffer_AddRef(pIndexData
);
3183 if (NULL
!= oldIdxs
) {
3184 IWineD3DIndexBuffer_Release(oldIdxs
);
3189 static HRESULT WINAPI
IWineD3DDeviceImpl_GetIndices(IWineD3DDevice
*iface
, IWineD3DIndexBuffer
** ppIndexData
, UINT
* pBaseVertexIndex
) {
3190 IWineD3DDeviceImpl
*This
= (IWineD3DDeviceImpl
*)iface
;
3192 *ppIndexData
= This
->stateBlock
->pIndexData
;
3194 /* up ref count on ppindexdata */
3196 IWineD3DIndexBuffer_AddRef(*ppIndexData
);
3197 *pBaseVertexIndex
= This
->stateBlock
->baseVertexIndex
;
3198 TRACE("(%p) index data set to %p + %u\n", This
, ppIndexData
, This
->stateBlock
->baseVertexIndex
);
3200 TRACE("(%p) No index data set\n", This
);
3202 TRACE("Returning %p %d\n", *ppIndexData
, *pBaseVertexIndex
);
3208 * Get / Set Viewports
3210 static HRESULT WINAPI
IWineD3DDeviceImpl_SetViewport(IWineD3DDevice
*iface
, CONST WINED3DVIEWPORT
* pViewport
) {
3211 IWineD3DDeviceImpl
*This
= (IWineD3DDeviceImpl
*)iface
;
3213 TRACE("(%p)\n", This
);
3214 This
->updateStateBlock
->changed
.viewport
= TRUE
;
3215 This
->updateStateBlock
->set
.viewport
= TRUE
;
3216 memcpy(&This
->updateStateBlock
->viewport
, pViewport
, sizeof(WINED3DVIEWPORT
));
3218 /* Handle recording of state blocks */
3219 if (This
->isRecordingState
) {
3220 TRACE("Recording... not performing anything\n");
3223 This
->viewport_changed
= TRUE
;
3227 TRACE("(%p) : x=%ld, y=%ld, wid=%ld, hei=%ld, minz=%f, maxz=%f\n", This
,
3228 pViewport
->X
, pViewport
->Y
, pViewport
->Width
, pViewport
->Height
, pViewport
->MinZ
, pViewport
->MaxZ
);
3230 glDepthRange(pViewport
->MinZ
, pViewport
->MaxZ
);
3231 checkGLcall("glDepthRange");
3232 /* Note: GL requires lower left, DirectX supplies upper left */
3233 /* TODO: replace usage of renderTarget with context management */
3234 glViewport(pViewport
->X
,
3235 (((IWineD3DSurfaceImpl
*)This
->renderTarget
)->currentDesc
.Height
- (pViewport
->Y
+ pViewport
->Height
)),
3236 pViewport
->Width
, pViewport
->Height
);
3238 checkGLcall("glViewport");
3246 static HRESULT WINAPI
IWineD3DDeviceImpl_GetViewport(IWineD3DDevice
*iface
, WINED3DVIEWPORT
* pViewport
) {
3247 IWineD3DDeviceImpl
*This
= (IWineD3DDeviceImpl
*)iface
;
3248 TRACE("(%p)\n", This
);
3249 memcpy(pViewport
, &This
->stateBlock
->viewport
, sizeof(WINED3DVIEWPORT
));
3253 static void renderstate_stencil_twosided(
3254 IWineD3DDeviceImpl
*This
,
3261 GLint stencilPass
) {
3262 #if 0 /* Don't use OpenGL 2.0 calls for now */
3263 if(GL_EXTCALL(glStencilFuncSeparate
) && GL_EXTCALL(glStencilOpSeparate
)) {
3264 GL_EXTCALL(glStencilFuncSeparate(face
, func
, ref
, mask
));
3265 checkGLcall("glStencilFuncSeparate(...)");
3266 GL_EXTCALL(glStencilOpSeparate(face
, stencilFail
, depthFail
, stencilPass
));
3267 checkGLcall("glStencilOpSeparate(...)");
3271 if(GL_SUPPORT(EXT_STENCIL_TWO_SIDE
)) {
3272 glEnable(GL_STENCIL_TEST_TWO_SIDE_EXT
);
3273 checkGLcall("glEnable(GL_STENCIL_TEST_TWO_SIDE_EXT)");
3274 GL_EXTCALL(glActiveStencilFaceEXT(face
));
3275 checkGLcall("glActiveStencilFaceEXT(...)");
3276 glStencilFunc(func
, ref
, mask
);
3277 checkGLcall("glStencilFunc(...)");
3278 glStencilOp(stencilFail
, depthFail
, stencilPass
);
3279 checkGLcall("glStencilOp(...)");
3280 } else if(GL_SUPPORT(ATI_SEPARATE_STENCIL
)) {
3281 GL_EXTCALL(glStencilFuncSeparateATI(face
, func
, ref
, mask
));
3282 checkGLcall("glStencilFuncSeparateATI(...)");
3283 GL_EXTCALL(glStencilOpSeparateATI(face
, stencilFail
, depthFail
, stencilPass
));
3284 checkGLcall("glStencilOpSeparateATI(...)");
3286 ERR("Separate (two sided) stencil not supported on this version of opengl. Caps weren't honored?\n");
3290 static void renderstate_stencil(IWineD3DDeviceImpl
*This
, D3DRENDERSTATETYPE State
, DWORD Value
) {
3291 DWORD onesided_enable
= FALSE
;
3292 DWORD twosided_enable
= FALSE
;
3293 GLint func
= GL_ALWAYS
;
3294 GLint func_ccw
= GL_ALWAYS
;
3297 GLint stencilFail
= GL_KEEP
;
3298 GLint depthFail
= GL_KEEP
;
3299 GLint stencilPass
= GL_KEEP
;
3300 GLint stencilFail_ccw
= GL_KEEP
;
3301 GLint depthFail_ccw
= GL_KEEP
;
3302 GLint stencilPass_ccw
= GL_KEEP
;
3304 if( This
->stateBlock
->set
.renderState
[WINED3DRS_STENCILENABLE
] )
3305 onesided_enable
= This
->stateBlock
->renderState
[WINED3DRS_STENCILENABLE
];
3306 if( This
->stateBlock
->set
.renderState
[WINED3DRS_TWOSIDEDSTENCILMODE
] )
3307 twosided_enable
= This
->stateBlock
->renderState
[WINED3DRS_TWOSIDEDSTENCILMODE
];
3308 if( This
->stateBlock
->set
.renderState
[WINED3DRS_STENCILFUNC
] )
3309 func
= StencilFunc(This
->stateBlock
->renderState
[WINED3DRS_STENCILFUNC
]);
3310 if( This
->stateBlock
->set
.renderState
[WINED3DRS_CCW_STENCILFUNC
] )
3311 func_ccw
= StencilFunc(This
->stateBlock
->renderState
[WINED3DRS_CCW_STENCILFUNC
]);
3312 if( This
->stateBlock
->set
.renderState
[WINED3DRS_STENCILREF
] )
3313 ref
= This
->stateBlock
->renderState
[WINED3DRS_STENCILREF
];
3314 if( This
->stateBlock
->set
.renderState
[WINED3DRS_STENCILMASK
] )
3315 mask
= This
->stateBlock
->renderState
[WINED3DRS_STENCILMASK
];
3316 if( This
->stateBlock
->set
.renderState
[WINED3DRS_STENCILFAIL
] )
3317 stencilFail
= StencilOp(This
->stateBlock
->renderState
[WINED3DRS_STENCILFAIL
]);
3318 if( This
->stateBlock
->set
.renderState
[WINED3DRS_STENCILZFAIL
] )
3319 depthFail
= StencilOp(This
->stateBlock
->renderState
[WINED3DRS_STENCILZFAIL
]);
3320 if( This
->stateBlock
->set
.renderState
[WINED3DRS_STENCILPASS
] )
3321 stencilPass
= StencilOp(This
->stateBlock
->renderState
[WINED3DRS_STENCILPASS
]);
3322 if( This
->stateBlock
->set
.renderState
[WINED3DRS_CCW_STENCILFAIL
] )
3323 stencilFail_ccw
= StencilOp(This
->stateBlock
->renderState
[WINED3DRS_CCW_STENCILFAIL
]);
3324 if( This
->stateBlock
->set
.renderState
[WINED3DRS_CCW_STENCILZFAIL
] )
3325 depthFail_ccw
= StencilOp(This
->stateBlock
->renderState
[WINED3DRS_CCW_STENCILZFAIL
]);
3326 if( This
->stateBlock
->set
.renderState
[WINED3DRS_CCW_STENCILPASS
] )
3327 stencilPass_ccw
= StencilOp(This
->stateBlock
->renderState
[WINED3DRS_CCW_STENCILPASS
]);
3330 case WINED3DRS_STENCILENABLE
:
3331 onesided_enable
= Value
;
3333 case WINED3DRS_TWOSIDEDSTENCILMODE
:
3334 twosided_enable
= Value
;
3336 case WINED3DRS_STENCILFUNC
:
3337 func
= StencilFunc(Value
);
3339 case WINED3DRS_CCW_STENCILFUNC
:
3340 func_ccw
= StencilFunc(Value
);
3342 case WINED3DRS_STENCILREF
:
3345 case WINED3DRS_STENCILMASK
:
3348 case WINED3DRS_STENCILFAIL
:
3349 stencilFail
= StencilOp(Value
);
3351 case WINED3DRS_STENCILZFAIL
:
3352 depthFail
= StencilOp(Value
);
3354 case WINED3DRS_STENCILPASS
:
3355 stencilPass
= StencilOp(Value
);
3357 case WINED3DRS_CCW_STENCILFAIL
:
3358 stencilFail_ccw
= StencilOp(Value
);
3360 case WINED3DRS_CCW_STENCILZFAIL
:
3361 depthFail_ccw
= StencilOp(Value
);
3363 case WINED3DRS_CCW_STENCILPASS
:
3364 stencilPass_ccw
= StencilOp(Value
);
3367 ERR("This should not happen!");
3370 TRACE("(onesided %ld, twosided %ld, ref %x, mask %x, \
3371 GL_FRONT: func: %x, fail %x, zfail %x, zpass %x \
3372 GL_BACK: func: %x, fail %x, zfail %x, zpass %x )\n",
3373 onesided_enable
, twosided_enable
, ref
, mask
,
3374 func
, stencilFail
, depthFail
, stencilPass
,
3375 func_ccw
, stencilFail_ccw
, depthFail_ccw
, stencilPass_ccw
);
3377 if (twosided_enable
) {
3378 renderstate_stencil_twosided(This
, GL_FRONT
, func
, ref
, mask
, stencilFail
, depthFail
, stencilPass
);
3379 renderstate_stencil_twosided(This
, GL_BACK
, func_ccw
, ref
, mask
, stencilFail_ccw
, depthFail_ccw
, stencilPass_ccw
);
3381 if (onesided_enable
) {
3382 glEnable(GL_STENCIL_TEST
);
3383 checkGLcall("glEnable GL_STENCIL_TEST");
3384 glStencilFunc(func
, ref
, mask
);
3385 checkGLcall("glStencilFunc(...)");
3386 glStencilOp(stencilFail
, depthFail
, stencilPass
);
3387 checkGLcall("glStencilOp(...)");
3389 glDisable(GL_STENCIL_TEST
);
3390 checkGLcall("glDisable GL_STENCIL_TEST");
3396 * Get / Set Render States
3397 * TODO: Verify against dx9 definitions
3399 static HRESULT WINAPI
IWineD3DDeviceImpl_SetRenderState(IWineD3DDevice
*iface
, D3DRENDERSTATETYPE State
, DWORD Value
) {
3401 IWineD3DDeviceImpl
*This
= (IWineD3DDeviceImpl
*)iface
;
3402 DWORD OldValue
= This
->stateBlock
->renderState
[State
];
3404 /* Simple way of referring to either a DWORD or a 4 byte float */
3410 TRACE("(%p)->state = %s(%d), value = %ld\n", This
, debug_d3drenderstate(State
), State
, Value
);
3411 This
->updateStateBlock
->changed
.renderState
[State
] = TRUE
;
3412 This
->updateStateBlock
->set
.renderState
[State
] = TRUE
;
3413 This
->updateStateBlock
->renderState
[State
] = Value
;
3415 /* Handle recording of state blocks */
3416 if (This
->isRecordingState
) {
3417 TRACE("Recording... not performing anything\n");
3424 case WINED3DRS_FILLMODE
:
3425 switch ((D3DFILLMODE
) Value
) {
3426 case D3DFILL_POINT
: glPolygonMode(GL_FRONT_AND_BACK
, GL_POINT
); break;
3427 case D3DFILL_WIREFRAME
: glPolygonMode(GL_FRONT_AND_BACK
, GL_LINE
); break;
3428 case D3DFILL_SOLID
: glPolygonMode(GL_FRONT_AND_BACK
, GL_FILL
); break;
3430 FIXME("Unrecognized WINED3DRS_FILLMODE value %ld\n", Value
);
3432 checkGLcall("glPolygonMode (fillmode)");
3435 case WINED3DRS_LIGHTING
:
3437 glEnable(GL_LIGHTING
);
3438 checkGLcall("glEnable GL_LIGHTING");
3440 glDisable(GL_LIGHTING
);
3441 checkGLcall("glDisable GL_LIGHTING");
3445 case WINED3DRS_ZENABLE
:
3446 switch ((D3DZBUFFERTYPE
) Value
) {
3448 glDisable(GL_DEPTH_TEST
);
3449 checkGLcall("glDisable GL_DEPTH_TEST");
3452 glEnable(GL_DEPTH_TEST
);
3453 checkGLcall("glEnable GL_DEPTH_TEST");
3456 glEnable(GL_DEPTH_TEST
);
3457 checkGLcall("glEnable GL_DEPTH_TEST");
3458 FIXME("W buffer is not well handled\n");
3461 FIXME("Unrecognized D3DZBUFFERTYPE value %ld\n", Value
);
3465 case WINED3DRS_CULLMODE
:
3467 /* If we are culling "back faces with clockwise vertices" then
3468 set front faces to be counter clockwise and enable culling
3470 switch ((D3DCULL
) Value
) {
3472 glDisable(GL_CULL_FACE
);
3473 checkGLcall("glDisable GL_CULL_FACE");
3476 glEnable(GL_CULL_FACE
);
3477 checkGLcall("glEnable GL_CULL_FACE");
3478 if (This
->renderUpsideDown
) {
3480 checkGLcall("glFrontFace GL_CW");
3482 glFrontFace(GL_CCW
);
3483 checkGLcall("glFrontFace GL_CCW");
3485 glCullFace(GL_BACK
);
3488 glEnable(GL_CULL_FACE
);
3489 checkGLcall("glEnable GL_CULL_FACE");
3490 if (This
->renderUpsideDown
) {
3491 glFrontFace(GL_CCW
);
3492 checkGLcall("glFrontFace GL_CCW");
3495 checkGLcall("glFrontFace GL_CW");
3497 glCullFace(GL_BACK
);
3500 FIXME("Unrecognized/Unhandled D3DCULL value %ld\n", Value
);
3504 case WINED3DRS_SHADEMODE
:
3505 switch ((D3DSHADEMODE
) Value
) {
3507 glShadeModel(GL_FLAT
);
3508 checkGLcall("glShadeModel");
3510 case D3DSHADE_GOURAUD
:
3511 glShadeModel(GL_SMOOTH
);
3512 checkGLcall("glShadeModel");
3514 case D3DSHADE_PHONG
:
3515 FIXME("D3DSHADE_PHONG isn't supported\n");
3518 FIXME("Unrecognized/Unhandled D3DSHADEMODE value %ld\n", Value
);
3522 case WINED3DRS_DITHERENABLE
:
3524 glEnable(GL_DITHER
);
3525 checkGLcall("glEnable GL_DITHER");
3527 glDisable(GL_DITHER
);
3528 checkGLcall("glDisable GL_DITHER");
3532 case WINED3DRS_ZWRITEENABLE
:
3535 checkGLcall("glDepthMask");
3538 checkGLcall("glDepthMask");
3542 case WINED3DRS_ZFUNC
:
3544 int glParm
= GL_LESS
;
3546 switch ((D3DCMPFUNC
) Value
) {
3547 case D3DCMP_NEVER
: glParm
=GL_NEVER
; break;
3548 case D3DCMP_LESS
: glParm
=GL_LESS
; break;
3549 case D3DCMP_EQUAL
: glParm
=GL_EQUAL
; break;
3550 case D3DCMP_LESSEQUAL
: glParm
=GL_LEQUAL
; break;
3551 case D3DCMP_GREATER
: glParm
=GL_GREATER
; break;
3552 case D3DCMP_NOTEQUAL
: glParm
=GL_NOTEQUAL
; break;
3553 case D3DCMP_GREATEREQUAL
: glParm
=GL_GEQUAL
; break;
3554 case D3DCMP_ALWAYS
: glParm
=GL_ALWAYS
; break;
3556 FIXME("Unrecognized/Unhandled D3DCMPFUNC value %ld\n", Value
);
3558 glDepthFunc(glParm
);
3559 checkGLcall("glDepthFunc");
3563 case WINED3DRS_AMBIENT
:
3566 D3DCOLORTOGLFLOAT4(Value
, col
);
3567 TRACE("Setting ambient to (%f,%f,%f,%f)\n", col
[0], col
[1], col
[2], col
[3]);
3568 glLightModelfv(GL_LIGHT_MODEL_AMBIENT
, col
);
3569 checkGLcall("glLightModel for MODEL_AMBIENT");
3574 case WINED3DRS_ALPHABLENDENABLE
:
3577 checkGLcall("glEnable GL_BLEND");
3579 glDisable(GL_BLEND
);
3580 checkGLcall("glDisable GL_BLEND");
3584 case WINED3DRS_SRCBLEND
:
3585 case WINED3DRS_DESTBLEND
:
3587 int newVal
= GL_ZERO
;
3589 case D3DBLEND_ZERO
: newVal
= GL_ZERO
; break;
3590 case D3DBLEND_ONE
: newVal
= GL_ONE
; break;
3591 case D3DBLEND_SRCCOLOR
: newVal
= GL_SRC_COLOR
; break;
3592 case D3DBLEND_INVSRCCOLOR
: newVal
= GL_ONE_MINUS_SRC_COLOR
; break;
3593 case D3DBLEND_SRCALPHA
: newVal
= GL_SRC_ALPHA
; break;
3594 case D3DBLEND_INVSRCALPHA
: newVal
= GL_ONE_MINUS_SRC_ALPHA
; break;
3595 case D3DBLEND_DESTALPHA
: newVal
= GL_DST_ALPHA
; break;
3596 case D3DBLEND_INVDESTALPHA
: newVal
= GL_ONE_MINUS_DST_ALPHA
; break;
3597 case D3DBLEND_DESTCOLOR
: newVal
= GL_DST_COLOR
; break;
3598 case D3DBLEND_INVDESTCOLOR
: newVal
= GL_ONE_MINUS_DST_COLOR
; break;
3599 case D3DBLEND_SRCALPHASAT
: newVal
= GL_SRC_ALPHA_SATURATE
; break;
3601 case D3DBLEND_BOTHSRCALPHA
: newVal
= GL_SRC_ALPHA
;
3602 This
->srcBlend
= newVal
;
3603 This
->dstBlend
= newVal
;
3606 case D3DBLEND_BOTHINVSRCALPHA
: newVal
= GL_ONE_MINUS_SRC_ALPHA
;
3607 This
->srcBlend
= newVal
;
3608 This
->dstBlend
= newVal
;
3611 FIXME("Unrecognized src/dest blend value %ld (%d)\n", Value
, State
);
3614 if (State
== WINED3DRS_SRCBLEND
) This
->srcBlend
= newVal
;
3615 if (State
== WINED3DRS_DESTBLEND
) This
->dstBlend
= newVal
;
3616 TRACE("glBlendFunc src=%x, dst=%x\n", This
->srcBlend
, This
->dstBlend
);
3617 glBlendFunc(This
->srcBlend
, This
->dstBlend
);
3619 checkGLcall("glBlendFunc");
3623 case WINED3DRS_ALPHATESTENABLE
:
3624 case WINED3DRS_ALPHAFUNC
:
3625 case WINED3DRS_ALPHAREF
:
3626 case WINED3DRS_COLORKEYENABLE
:
3629 float ref
= GL_LESS
;
3630 BOOL enable_ckey
= FALSE
;
3632 IWineD3DSurfaceImpl
*surf
;
3634 /* Find out if the texture on the first stage has a ckey set */
3635 if(This
->stateBlock
->textures
[0]) {
3636 surf
= (IWineD3DSurfaceImpl
*) ((IWineD3DTextureImpl
*)This
->stateBlock
->textures
[0])->surfaces
[0];
3637 if(surf
->CKeyFlags
& DDSD_CKSRCBLT
) enable_ckey
= TRUE
;
3640 if (This
->stateBlock
->renderState
[WINED3DRS_ALPHATESTENABLE
] ||
3641 (This
->stateBlock
->renderState
[WINED3DRS_COLORKEYENABLE
] && enable_ckey
)) {
3642 glEnable(GL_ALPHA_TEST
);
3643 checkGLcall("glEnable GL_ALPHA_TEST");
3645 glDisable(GL_ALPHA_TEST
);
3646 checkGLcall("glDisable GL_ALPHA_TEST");
3647 /* Alpha test is disabled, don't bother setting the params - it will happen on the next
3653 if(This
->stateBlock
->renderState
[WINED3DRS_COLORKEYENABLE
] && enable_ckey
) {
3654 glParm
= GL_NOTEQUAL
;
3657 ref
= ((float) This
->stateBlock
->renderState
[WINED3DRS_ALPHAREF
]) / 255.0f
;
3659 switch ((D3DCMPFUNC
) This
->stateBlock
->renderState
[WINED3DRS_ALPHAFUNC
]) {
3660 case D3DCMP_NEVER
: glParm
= GL_NEVER
; break;
3661 case D3DCMP_LESS
: glParm
= GL_LESS
; break;
3662 case D3DCMP_EQUAL
: glParm
= GL_EQUAL
; break;
3663 case D3DCMP_LESSEQUAL
: glParm
= GL_LEQUAL
; break;
3664 case D3DCMP_GREATER
: glParm
= GL_GREATER
; break;
3665 case D3DCMP_NOTEQUAL
: glParm
= GL_NOTEQUAL
; break;
3666 case D3DCMP_GREATEREQUAL
: glParm
= GL_GEQUAL
; break;
3667 case D3DCMP_ALWAYS
: glParm
= GL_ALWAYS
; break;
3669 FIXME("Unrecognized/Unhandled D3DCMPFUNC value %ld\n", Value
);
3672 This
->alphafunc
= glParm
;
3673 glAlphaFunc(glParm
, ref
);
3674 checkGLcall("glAlphaFunc");
3678 case WINED3DRS_CLIPPLANEENABLE
:
3679 case WINED3DRS_CLIPPING
:
3681 /* Ensure we only do the changed clip planes */
3682 DWORD enable
= 0xFFFFFFFF;
3683 DWORD disable
= 0x00000000;
3685 /* If enabling / disabling all */
3686 if (State
== WINED3DRS_CLIPPING
) {
3688 enable
= This
->stateBlock
->renderState
[WINED3DRS_CLIPPLANEENABLE
];
3691 disable
= This
->stateBlock
->renderState
[WINED3DRS_CLIPPLANEENABLE
];
3695 enable
= Value
& ~OldValue
;
3696 disable
= ~Value
& OldValue
;
3699 if (enable
& D3DCLIPPLANE0
) { glEnable(GL_CLIP_PLANE0
); checkGLcall("glEnable(clip plane 0)"); }
3700 if (enable
& D3DCLIPPLANE1
) { glEnable(GL_CLIP_PLANE1
); checkGLcall("glEnable(clip plane 1)"); }
3701 if (enable
& D3DCLIPPLANE2
) { glEnable(GL_CLIP_PLANE2
); checkGLcall("glEnable(clip plane 2)"); }
3702 if (enable
& D3DCLIPPLANE3
) { glEnable(GL_CLIP_PLANE3
); checkGLcall("glEnable(clip plane 3)"); }
3703 if (enable
& D3DCLIPPLANE4
) { glEnable(GL_CLIP_PLANE4
); checkGLcall("glEnable(clip plane 4)"); }
3704 if (enable
& D3DCLIPPLANE5
) { glEnable(GL_CLIP_PLANE5
); checkGLcall("glEnable(clip plane 5)"); }
3706 if (disable
& D3DCLIPPLANE0
) { glDisable(GL_CLIP_PLANE0
); checkGLcall("glDisable(clip plane 0)"); }
3707 if (disable
& D3DCLIPPLANE1
) { glDisable(GL_CLIP_PLANE1
); checkGLcall("glDisable(clip plane 1)"); }
3708 if (disable
& D3DCLIPPLANE2
) { glDisable(GL_CLIP_PLANE2
); checkGLcall("glDisable(clip plane 2)"); }
3709 if (disable
& D3DCLIPPLANE3
) { glDisable(GL_CLIP_PLANE3
); checkGLcall("glDisable(clip plane 3)"); }
3710 if (disable
& D3DCLIPPLANE4
) { glDisable(GL_CLIP_PLANE4
); checkGLcall("glDisable(clip plane 4)"); }
3711 if (disable
& D3DCLIPPLANE5
) { glDisable(GL_CLIP_PLANE5
); checkGLcall("glDisable(clip plane 5)"); }
3713 /** update clipping status */
3715 This
->stateBlock
->clip_status
.ClipUnion
= 0;
3716 This
->stateBlock
->clip_status
.ClipIntersection
= 0xFFFFFFFF;
3718 This
->stateBlock
->clip_status
.ClipUnion
= 0;
3719 This
->stateBlock
->clip_status
.ClipIntersection
= 0;
3724 case WINED3DRS_BLENDOP
:
3726 int glParm
= GL_FUNC_ADD
;
3728 switch ((D3DBLENDOP
) Value
) {
3729 case D3DBLENDOP_ADD
: glParm
= GL_FUNC_ADD
; break;
3730 case D3DBLENDOP_SUBTRACT
: glParm
= GL_FUNC_SUBTRACT
; break;
3731 case D3DBLENDOP_REVSUBTRACT
: glParm
= GL_FUNC_REVERSE_SUBTRACT
; break;
3732 case D3DBLENDOP_MIN
: glParm
= GL_MIN
; break;
3733 case D3DBLENDOP_MAX
: glParm
= GL_MAX
; break;
3735 FIXME("Unrecognized/Unhandled D3DBLENDOP value %ld\n", Value
);
3738 if(GL_SUPPORT(ARB_IMAGING
)) {
3739 TRACE("glBlendEquation(%x)\n", glParm
);
3740 GL_EXTCALL(glBlendEquation(glParm
));
3741 checkGLcall("glBlendEquation");
3743 WARN("Unsupported in local OpenGL implementation: glBlendEquation\n");
3748 case WINED3DRS_TEXTUREFACTOR
:
3752 /* Note the texture color applies to all textures whereas
3753 GL_TEXTURE_ENV_COLOR applies to active only */
3755 D3DCOLORTOGLFLOAT4(Value
, col
);
3756 /* Set the default alpha blend color */
3757 if (GL_SUPPORT(ARB_IMAGING
)) {
3758 GL_EXTCALL(glBlendColor(col
[0], col
[1], col
[2], col
[3]));
3759 checkGLcall("glBlendColor");
3761 WARN("Unsupported in local OpenGL implementation: glBlendColor\n");
3764 if (!GL_SUPPORT(NV_REGISTER_COMBINERS
)) {
3765 /* And now the default texture color as well */
3766 for (i
= 0; i
< GL_LIMITS(texture_stages
); i
++) {
3767 /* Note the D3DRS value applies to all textures, but GL has one
3768 per texture, so apply it now ready to be used! */
3769 if (GL_SUPPORT(ARB_MULTITEXTURE
)) {
3770 GL_EXTCALL(glActiveTextureARB(GL_TEXTURE0_ARB
+ i
));
3771 checkGLcall("glActiveTextureARB");
3773 FIXME("Program using multiple concurrent textures which this opengl implementation doesn't support\n");
3776 glTexEnvfv(GL_TEXTURE_ENV
, GL_TEXTURE_ENV_COLOR
, &col
[0]);
3777 checkGLcall("glTexEnvfv(GL_TEXTURE_ENV, GL_TEXTURE_ENV_COLOR, color);");
3783 case WINED3DRS_SPECULARENABLE
:
3785 /* Originally this used glLightModeli(GL_LIGHT_MODEL_COLOR_CONTROL,GL_SEPARATE_SPECULAR_COLOR)
3786 and (GL_LIGHT_MODEL_COLOR_CONTROL,GL_SINGLE_COLOR) to swap between enabled/disabled
3787 specular color. This is wrong:
3788 Separate specular color means the specular colour is maintained separately, whereas
3789 single color means it is merged in. However in both cases they are being used to
3791 To disable specular color, set it explicitly to black and turn off GL_COLOR_SUM_EXT
3792 NOTE: If not supported don't give FIXMEs the impact is really minimal and very few people are
3796 * If register combiners are enabled, enabling / disabling GL_COLOR_SUM has no effect.
3797 * Instead, we need to setup the FinalCombiner properly.
3799 * The default setup for the FinalCombiner is:
3801 * <variable> <input> <mapping> <usage>
3802 * GL_VARIABLE_A_NV GL_FOG, GL_UNSIGNED_IDENTITY_NV GL_ALPHA
3803 * GL_VARIABLE_B_NV GL_SPARE0_PLUS_SECONDARY_COLOR_NV GL_UNSIGNED_IDENTITY_NV GL_RGB
3804 * GL_VARIABLE_C_NV GL_FOG GL_UNSIGNED_IDENTITY_NV GL_RGB
3805 * GL_VARIABLE_D_NV GL_ZERO GL_UNSIGNED_IDENTITY_NV GL_RGB
3806 * GL_VARIABLE_E_NV GL_ZERO GL_UNSIGNED_IDENTITY_NV GL_RGB
3807 * GL_VARIABLE_F_NV GL_ZERO GL_UNSIGNED_IDENTITY_NV GL_RGB
3808 * GL_VARIABLE_G_NV GL_SPARE0_NV GL_UNSIGNED_IDENTITY_NV GL_ALPHA
3810 * That's pretty much fine as it is, except for variable B, which needs to take
3811 * either GL_SPARE0_PLUS_SECONDARY_COLOR_NV or GL_SPARE0_NV, depending on
3812 * whether WINED3DRS_SPECULARENABLE is enabled or not.
3816 glMaterialfv(GL_FRONT_AND_BACK
, GL_SPECULAR
, (float*) &This
->updateStateBlock
->material
.Specular
);
3817 checkGLcall("glMaterialfv");
3818 if (GL_SUPPORT(EXT_SECONDARY_COLOR
)) {
3819 glEnable(GL_COLOR_SUM_EXT
);
3821 TRACE("Specular colors cannot be enabled in this version of opengl\n");
3823 checkGLcall("glEnable(GL_COLOR_SUM)");
3825 if (GL_SUPPORT(NV_REGISTER_COMBINERS
)) {
3826 GL_EXTCALL(glFinalCombinerInputNV(GL_VARIABLE_B_NV
, GL_SPARE0_PLUS_SECONDARY_COLOR_NV
, GL_UNSIGNED_IDENTITY_NV
, GL_RGB
));
3827 checkGLcall("glFinalCombinerInputNV()");
3830 float black
[4] = {0.0f
, 0.0f
, 0.0f
, 0.0f
};
3832 /* for the case of enabled lighting: */
3833 glMaterialfv(GL_FRONT_AND_BACK
, GL_SPECULAR
, &black
[0]);
3834 checkGLcall("glMaterialfv");
3836 /* for the case of disabled lighting: */
3837 if (GL_SUPPORT(EXT_SECONDARY_COLOR
)) {
3838 glDisable(GL_COLOR_SUM_EXT
);
3840 TRACE("Specular colors cannot be disabled in this version of opengl\n");
3842 checkGLcall("glDisable(GL_COLOR_SUM)");
3844 if (GL_SUPPORT(NV_REGISTER_COMBINERS
)) {
3845 GL_EXTCALL(glFinalCombinerInputNV(GL_VARIABLE_B_NV
, GL_SPARE0_NV
, GL_UNSIGNED_IDENTITY_NV
, GL_RGB
));
3846 checkGLcall("glFinalCombinerInputNV()");
3852 case WINED3DRS_STENCILENABLE
:
3853 case WINED3DRS_TWOSIDEDSTENCILMODE
:
3854 case WINED3DRS_STENCILFUNC
:
3855 case WINED3DRS_CCW_STENCILFUNC
:
3856 case WINED3DRS_STENCILREF
:
3857 case WINED3DRS_STENCILMASK
:
3858 case WINED3DRS_STENCILFAIL
:
3859 case WINED3DRS_STENCILZFAIL
:
3860 case WINED3DRS_STENCILPASS
:
3861 case WINED3DRS_CCW_STENCILFAIL
:
3862 case WINED3DRS_CCW_STENCILZFAIL
:
3863 case WINED3DRS_CCW_STENCILPASS
:
3864 renderstate_stencil(This
, State
, Value
);
3866 case WINED3DRS_STENCILWRITEMASK
:
3868 glStencilMask(Value
);
3869 TRACE("glStencilMask(%lu)\n", Value
);
3870 checkGLcall("glStencilMask");
3874 case WINED3DRS_FOGENABLE
:
3878 checkGLcall("glEnable GL_FOG");
3881 checkGLcall("glDisable GL_FOG");
3886 case WINED3DRS_RANGEFOGENABLE
:
3889 TRACE("Enabled RANGEFOG");
3891 TRACE("Disabled RANGEFOG");
3896 case WINED3DRS_FOGCOLOR
:
3899 D3DCOLORTOGLFLOAT4(Value
, col
);
3900 /* Set the default alpha blend color */
3901 glFogfv(GL_FOG_COLOR
, &col
[0]);
3902 checkGLcall("glFog GL_FOG_COLOR");
3906 case WINED3DRS_FOGTABLEMODE
:
3907 case WINED3DRS_FOGVERTEXMODE
:
3909 /* DX 7 sdk: "If both render states(vertex and table fog) are set to valid modes, the system will apply only pixel(=table) fog effects." */
3910 if(This
->stateBlock
->renderState
[WINED3DRS_FOGTABLEMODE
] == D3DFOG_NONE
) {
3911 glHint(GL_FOG_HINT
, GL_FASTEST
);
3912 checkGLcall("glHint(GL_FOG_HINT, GL_FASTEST)");
3913 switch (This
->stateBlock
->renderState
[WINED3DRS_FOGVERTEXMODE
]) {
3914 /* Processed vertices have their fog factor stored in the specular value. Fall too the none case.
3915 * If we are drawing untransformed vertices atm, d3ddevice_set_ortho will update the fog
3918 if(!This
->last_was_rhw
) {
3919 glFogi(GL_FOG_MODE
, GL_EXP
);
3920 checkGLcall("glFogi(GL_FOG_MODE, GL_EXP");
3921 if(GL_SUPPORT(EXT_FOG_COORD
)) {
3922 glFogi(GL_FOG_COORDINATE_SOURCE_EXT
, GL_FRAGMENT_DEPTH_EXT
);
3923 checkGLcall("glFogi(GL_FOG_COORDINATE_SOURCE_EXT, GL_FRAGMENT_DEPTH_EXT");
3924 IWineD3DDevice_SetRenderState(iface
, WINED3DRS_FOGSTART
, This
->stateBlock
->renderState
[WINED3DRS_FOGSTART
]);
3925 IWineD3DDevice_SetRenderState(iface
, WINED3DRS_FOGEND
, This
->stateBlock
->renderState
[WINED3DRS_FOGEND
]);
3931 if(!This
->last_was_rhw
) {
3932 glFogi(GL_FOG_MODE
, GL_EXP2
);
3933 checkGLcall("glFogi(GL_FOG_MODE, GL_EXP2");
3934 if(GL_SUPPORT(EXT_FOG_COORD
)) {
3935 glFogi(GL_FOG_COORDINATE_SOURCE_EXT
, GL_FRAGMENT_DEPTH_EXT
);
3936 checkGLcall("glFogi(GL_FOG_COORDINATE_SOURCE_EXT, GL_FRAGMENT_DEPTH_EXT");
3937 IWineD3DDevice_SetRenderState(iface
, WINED3DRS_FOGSTART
, This
->stateBlock
->renderState
[WINED3DRS_FOGSTART
]);
3938 IWineD3DDevice_SetRenderState(iface
, WINED3DRS_FOGEND
, This
->stateBlock
->renderState
[WINED3DRS_FOGEND
]);
3943 case D3DFOG_LINEAR
: {
3944 if(!This
->last_was_rhw
) {
3945 glFogi(GL_FOG_MODE
, GL_LINEAR
);
3946 checkGLcall("glFogi(GL_FOG_MODE, GL_LINEAR");
3947 if(GL_SUPPORT(EXT_FOG_COORD
)) {
3948 glFogi(GL_FOG_COORDINATE_SOURCE_EXT
, GL_FRAGMENT_DEPTH_EXT
);
3949 checkGLcall("glFogi(GL_FOG_COORDINATE_SOURCE_EXT, GL_FRAGMENT_DEPTH_EXT");
3950 IWineD3DDevice_SetRenderState(iface
, WINED3DRS_FOGSTART
, This
->stateBlock
->renderState
[WINED3DRS_FOGSTART
]);
3951 IWineD3DDevice_SetRenderState(iface
, WINED3DRS_FOGEND
, This
->stateBlock
->renderState
[WINED3DRS_FOGEND
]);
3957 /* Both are none? According to msdn the alpha channel of the specular
3958 * color contains a fog factor. Set it in drawStridedSlow.
3959 * Same happens with Vertexfog on transformed vertices
3961 if(GL_SUPPORT(EXT_FOG_COORD
)) {
3962 glFogi(GL_FOG_COORDINATE_SOURCE_EXT
, GL_FOG_COORDINATE_EXT
);
3963 checkGLcall("glFogi(GL_FOG_COORDINATE_SOURCE_EXT, GL_FOG_COORDINATE_EXT)\n");
3964 glFogi(GL_FOG_MODE
, GL_LINEAR
);
3965 checkGLcall("glFogi(GL_FOG_MODE, GL_LINEAR)");
3966 glFogf(GL_FOG_START
, (float) 0xff);
3967 checkGLcall("glFogfv GL_FOG_START");
3968 glFogf(GL_FOG_END
, 0.0);
3969 checkGLcall("glFogfv GL_FOG_END");
3971 /* Disable GL fog, handle this in software in drawStridedSlow */
3973 checkGLcall("glDisable(GL_FOG)");
3977 default: FIXME("Unexpected WINED3DRS_FOGVERTEXMODE %ld\n", This
->stateBlock
->renderState
[WINED3DRS_FOGVERTEXMODE
]);
3980 glHint(GL_FOG_HINT
, GL_NICEST
);
3981 checkGLcall("glHint(GL_FOG_HINT, GL_NICEST)");
3982 switch (This
->stateBlock
->renderState
[WINED3DRS_FOGTABLEMODE
]) {
3983 case D3DFOG_EXP
: glFogi(GL_FOG_MODE
, GL_EXP
);
3984 checkGLcall("glFogi(GL_FOG_MODE, GL_EXP");
3985 if(GL_SUPPORT(EXT_FOG_COORD
)) {
3986 glFogi(GL_FOG_COORDINATE_SOURCE_EXT
, GL_FRAGMENT_DEPTH_EXT
);
3987 checkGLcall("glFogi(GL_FOG_COORDINATE_SOURCE_EXT, GL_FRAGMENT_DEPTH_EXT");
3988 IWineD3DDevice_SetRenderState(iface
, WINED3DRS_FOGSTART
, This
->stateBlock
->renderState
[WINED3DRS_FOGSTART
]);
3989 IWineD3DDevice_SetRenderState(iface
, WINED3DRS_FOGEND
, This
->stateBlock
->renderState
[WINED3DRS_FOGEND
]);
3992 case D3DFOG_EXP2
: glFogi(GL_FOG_MODE
, GL_EXP2
);
3993 checkGLcall("glFogi(GL_FOG_MODE, GL_EXP2");
3994 if(GL_SUPPORT(EXT_FOG_COORD
)) {
3995 glFogi(GL_FOG_COORDINATE_SOURCE_EXT
, GL_FRAGMENT_DEPTH_EXT
);
3996 checkGLcall("glFogi(GL_FOG_COORDINATE_SOURCE_EXT, GL_FRAGMENT_DEPTH_EXT");
3997 IWineD3DDevice_SetRenderState(iface
, WINED3DRS_FOGSTART
, This
->stateBlock
->renderState
[WINED3DRS_FOGSTART
]);
3998 IWineD3DDevice_SetRenderState(iface
, WINED3DRS_FOGEND
, This
->stateBlock
->renderState
[WINED3DRS_FOGEND
]);
4001 case D3DFOG_LINEAR
: glFogi(GL_FOG_MODE
, GL_LINEAR
);
4002 checkGLcall("glFogi(GL_FOG_MODE, GL_LINEAR");
4003 if(GL_SUPPORT(EXT_FOG_COORD
)) {
4004 glFogi(GL_FOG_COORDINATE_SOURCE_EXT
, GL_FRAGMENT_DEPTH_EXT
);
4005 checkGLcall("glFogi(GL_FOG_COORDINATE_SOURCE_EXT, GL_FRAGMENT_DEPTH_EXT");
4006 IWineD3DDevice_SetRenderState(iface
, WINED3DRS_FOGSTART
, This
->stateBlock
->renderState
[WINED3DRS_FOGSTART
]);
4007 IWineD3DDevice_SetRenderState(iface
, WINED3DRS_FOGEND
, This
->stateBlock
->renderState
[WINED3DRS_FOGEND
]);
4010 case D3DFOG_NONE
: /* Won't happen */
4011 default: FIXME("Unexpected WINED3DRS_FOGTABLEMODE %ld\n", This
->stateBlock
->renderState
[WINED3DRS_FOGTABLEMODE
]);
4014 if (GL_SUPPORT(NV_FOG_DISTANCE
)) {
4015 glFogi(GL_FOG_DISTANCE_MODE_NV
, GL_EYE_PLANE_ABSOLUTE_NV
);
4020 case WINED3DRS_FOGSTART
:
4023 glFogfv(GL_FOG_START
, &tmpvalue
.f
);
4024 checkGLcall("glFogf(GL_FOG_START, (float) Value)");
4025 TRACE("Fog Start == %f\n", tmpvalue
.f
);
4029 case WINED3DRS_FOGEND
:
4032 glFogfv(GL_FOG_END
, &tmpvalue
.f
);
4033 checkGLcall("glFogf(GL_FOG_END, (float) Value)");
4034 TRACE("Fog End == %f\n", tmpvalue
.f
);
4038 case WINED3DRS_FOGDENSITY
:
4041 glFogfv(GL_FOG_DENSITY
, &tmpvalue
.f
);
4042 checkGLcall("glFogf(GL_FOG_DENSITY, (float) Value)");
4046 case WINED3DRS_VERTEXBLEND
:
4048 This
->updateStateBlock
->vertex_blend
= (D3DVERTEXBLENDFLAGS
) Value
;
4049 TRACE("Vertex Blending state to %ld\n", Value
);
4053 case WINED3DRS_TWEENFACTOR
:
4056 This
->updateStateBlock
->tween_factor
= tmpvalue
.f
;
4057 TRACE("Vertex Blending Tween Factor to %f\n", This
->updateStateBlock
->tween_factor
);
4061 case WINED3DRS_INDEXEDVERTEXBLENDENABLE
:
4063 TRACE("Indexed Vertex Blend Enable to %ul\n", (BOOL
) Value
);
4067 case WINED3DRS_COLORVERTEX
:
4068 case WINED3DRS_DIFFUSEMATERIALSOURCE
:
4069 case WINED3DRS_SPECULARMATERIALSOURCE
:
4070 case WINED3DRS_AMBIENTMATERIALSOURCE
:
4071 case WINED3DRS_EMISSIVEMATERIALSOURCE
:
4073 GLenum Parm
= GL_AMBIENT_AND_DIFFUSE
;
4075 if (This
->stateBlock
->renderState
[WINED3DRS_COLORVERTEX
]) {
4076 TRACE("diff %ld, amb %ld, emis %ld, spec %ld\n",
4077 This
->stateBlock
->renderState
[WINED3DRS_DIFFUSEMATERIALSOURCE
],
4078 This
->stateBlock
->renderState
[WINED3DRS_AMBIENTMATERIALSOURCE
],
4079 This
->stateBlock
->renderState
[WINED3DRS_EMISSIVEMATERIALSOURCE
],
4080 This
->stateBlock
->renderState
[WINED3DRS_SPECULARMATERIALSOURCE
]);
4082 if (This
->stateBlock
->renderState
[WINED3DRS_DIFFUSEMATERIALSOURCE
] == D3DMCS_COLOR1
) {
4083 if (This
->stateBlock
->renderState
[WINED3DRS_AMBIENTMATERIALSOURCE
] == D3DMCS_COLOR1
) {
4084 Parm
= GL_AMBIENT_AND_DIFFUSE
;
4088 } else if (This
->stateBlock
->renderState
[WINED3DRS_AMBIENTMATERIALSOURCE
] == D3DMCS_COLOR1
) {
4090 } else if (This
->stateBlock
->renderState
[WINED3DRS_EMISSIVEMATERIALSOURCE
] == D3DMCS_COLOR1
) {
4092 } else if (This
->stateBlock
->renderState
[WINED3DRS_SPECULARMATERIALSOURCE
] == D3DMCS_COLOR1
) {
4099 if (This
->tracking_color
!= DISABLED_TRACKING
) This
->tracking_color
= NEEDS_DISABLE
;
4101 This
->tracking_color
= NEEDS_TRACKING
;
4102 This
->tracking_parm
= Parm
;
4106 if (This
->tracking_color
!= DISABLED_TRACKING
) This
->tracking_color
= NEEDS_DISABLE
;
4111 case WINED3DRS_LINEPATTERN
:
4117 tmppattern
.d
= Value
;
4119 TRACE("Line pattern: repeat %d bits %x\n", tmppattern
.lp
.wRepeatFactor
, tmppattern
.lp
.wLinePattern
);
4121 if (tmppattern
.lp
.wRepeatFactor
) {
4122 glLineStipple(tmppattern
.lp
.wRepeatFactor
, tmppattern
.lp
.wLinePattern
);
4123 checkGLcall("glLineStipple(repeat, linepattern)");
4124 glEnable(GL_LINE_STIPPLE
);
4125 checkGLcall("glEnable(GL_LINE_STIPPLE);");
4127 glDisable(GL_LINE_STIPPLE
);
4128 checkGLcall("glDisable(GL_LINE_STIPPLE);");
4133 case WINED3DRS_ZBIAS
: /* D3D8 only */
4137 TRACE("ZBias value %f\n", tmpvalue
.f
);
4138 glPolygonOffset(0, -tmpvalue
.f
);
4139 checkGLcall("glPolygonOffset(0, -Value)");
4140 glEnable(GL_POLYGON_OFFSET_FILL
);
4141 checkGLcall("glEnable(GL_POLYGON_OFFSET_FILL);");
4142 glEnable(GL_POLYGON_OFFSET_LINE
);
4143 checkGLcall("glEnable(GL_POLYGON_OFFSET_LINE);");
4144 glEnable(GL_POLYGON_OFFSET_POINT
);
4145 checkGLcall("glEnable(GL_POLYGON_OFFSET_POINT);");
4147 glDisable(GL_POLYGON_OFFSET_FILL
);
4148 checkGLcall("glDisable(GL_POLYGON_OFFSET_FILL);");
4149 glDisable(GL_POLYGON_OFFSET_LINE
);
4150 checkGLcall("glDisable(GL_POLYGON_OFFSET_LINE);");
4151 glDisable(GL_POLYGON_OFFSET_POINT
);
4152 checkGLcall("glDisable(GL_POLYGON_OFFSET_POINT);");
4157 case WINED3DRS_NORMALIZENORMALS
:
4159 glEnable(GL_NORMALIZE
);
4160 checkGLcall("glEnable(GL_NORMALIZE);");
4162 glDisable(GL_NORMALIZE
);
4163 checkGLcall("glDisable(GL_NORMALIZE);");
4167 case WINED3DRS_POINTSIZE
:
4168 /* FIXME: check that pointSize isn't outside glGetFloatv( GL_POINT_SIZE_MAX_ARB, &maxSize ); or -ve */
4170 TRACE("Set point size to %f\n", tmpvalue
.f
);
4171 glPointSize(tmpvalue
.f
);
4172 checkGLcall("glPointSize(...);");
4175 case WINED3DRS_POINTSIZE_MIN
:
4176 if (GL_SUPPORT(EXT_POINT_PARAMETERS
)) {
4178 GL_EXTCALL(glPointParameterfEXT
)(GL_POINT_SIZE_MIN_EXT
, tmpvalue
.f
);
4179 checkGLcall("glPointParameterfEXT(...);");
4181 FIXME("WINED3DRS_POINTSIZE_MIN not supported on this opengl\n");
4185 case WINED3DRS_POINTSIZE_MAX
:
4186 if (GL_SUPPORT(EXT_POINT_PARAMETERS
)) {
4188 GL_EXTCALL(glPointParameterfEXT
)(GL_POINT_SIZE_MAX_EXT
, tmpvalue
.f
);
4189 checkGLcall("glPointParameterfEXT(...);");
4191 FIXME("WINED3DRS_POINTSIZE_MAX not supported on this opengl\n");
4195 case WINED3DRS_POINTSCALE_A
:
4196 case WINED3DRS_POINTSCALE_B
:
4197 case WINED3DRS_POINTSCALE_C
:
4198 case WINED3DRS_POINTSCALEENABLE
:
4201 * POINTSCALEENABLE controls how point size value is treated. If set to
4202 * true, the point size is scaled with respect to height of viewport.
4203 * When set to false point size is in pixels.
4205 * http://msdn.microsoft.com/library/en-us/directx9_c/point_sprites.asp
4208 /* Default values */
4209 GLfloat att
[3] = {1.0f
, 0.0f
, 0.0f
};
4212 * Minimum valid point size for OpenGL is 1.0f. For Direct3D it is 0.0f.
4213 * This means that OpenGL will clamp really small point sizes to 1.0f.
4214 * To correct for this we need to multiply by the scale factor when sizes
4215 * are less than 1.0f. scale_factor = 1.0f / point_size.
4217 GLfloat pointSize
= *((float*)&This
->stateBlock
->renderState
[WINED3DRS_POINTSIZE
]);
4218 if(pointSize
> 0.0f
) {
4219 GLfloat scaleFactor
;
4221 if(pointSize
< 1.0f
) {
4222 scaleFactor
= pointSize
* pointSize
;
4227 if(This
->stateBlock
->renderState
[WINED3DRS_POINTSCALEENABLE
]) {
4228 att
[0] = *((float*)&This
->stateBlock
->renderState
[WINED3DRS_POINTSCALE_A
]) /
4229 (This
->stateBlock
->viewport
.Height
* This
->stateBlock
->viewport
.Height
* scaleFactor
);
4230 att
[1] = *((float*)&This
->stateBlock
->renderState
[WINED3DRS_POINTSCALE_B
]) /
4231 (This
->stateBlock
->viewport
.Height
* This
->stateBlock
->viewport
.Height
* scaleFactor
);
4232 att
[2] = *((float*)&This
->stateBlock
->renderState
[WINED3DRS_POINTSCALE_C
]) /
4233 (This
->stateBlock
->viewport
.Height
* This
->stateBlock
->viewport
.Height
* scaleFactor
);
4237 if(GL_SUPPORT(ARB_POINT_PARAMETERS
)) {
4238 GL_EXTCALL(glPointParameterfvARB
)(GL_POINT_DISTANCE_ATTENUATION_ARB
, att
);
4239 checkGLcall("glPointParameterfvARB(GL_DISTANCE_ATTENUATION_ARB, ...");
4241 else if(GL_SUPPORT(EXT_POINT_PARAMETERS
)) {
4242 GL_EXTCALL(glPointParameterfvEXT
)(GL_DISTANCE_ATTENUATION_EXT
, att
);
4243 checkGLcall("glPointParameterfvEXT(GL_DISTANCE_ATTENUATION_EXT, ...");
4245 TRACE("POINT_PARAMETERS not supported in this version of opengl\n");
4249 case WINED3DRS_COLORWRITEENABLE
:
4251 TRACE("Color mask: r(%d) g(%d) b(%d) a(%d)\n",
4252 Value
& D3DCOLORWRITEENABLE_RED
? 1 : 0,
4253 Value
& D3DCOLORWRITEENABLE_GREEN
? 1 : 0,
4254 Value
& D3DCOLORWRITEENABLE_BLUE
? 1 : 0,
4255 Value
& D3DCOLORWRITEENABLE_ALPHA
? 1 : 0);
4256 glColorMask(Value
& D3DCOLORWRITEENABLE_RED
? GL_TRUE
: GL_FALSE
,
4257 Value
& D3DCOLORWRITEENABLE_GREEN
? GL_TRUE
: GL_FALSE
,
4258 Value
& D3DCOLORWRITEENABLE_BLUE
? GL_TRUE
: GL_FALSE
,
4259 Value
& D3DCOLORWRITEENABLE_ALPHA
? GL_TRUE
: GL_FALSE
);
4260 checkGLcall("glColorMask(...)");
4264 case WINED3DRS_LOCALVIEWER
:
4266 GLint state
= (Value
) ? 1 : 0;
4267 TRACE("Local Viewer Enable to %ul\n", (BOOL
) Value
);
4268 glLightModeli(GL_LIGHT_MODEL_LOCAL_VIEWER
, state
);
4272 case WINED3DRS_LASTPIXEL
:
4275 TRACE("Last Pixel Drawing Enabled\n");
4277 FIXME("Last Pixel Drawing Disabled, not handled yet\n");
4282 case WINED3DRS_SOFTWAREVERTEXPROCESSING
:
4285 TRACE("Software Processing Enabled\n");
4287 TRACE("Software Processing Disabled\n");
4292 /** not supported */
4293 case WINED3DRS_ZVISIBLE
:
4296 return WINED3DERR_INVALIDCALL
;
4298 case WINED3DRS_POINTSPRITEENABLE
:
4300 /* TODO: NV_POINT_SPRITE */
4301 if (!GL_SUPPORT(ARB_POINT_SPRITE
)) {
4302 TRACE("Point sprites not supported\n");
4307 * Point sprites are always enabled. Value controls texture coordinate
4308 * replacement mode. Must be set true for point sprites to use
4311 glEnable(GL_POINT_SPRITE_ARB
);
4312 checkGLcall("glEnable(GL_POINT_SPRITE_ARB)");
4315 glTexEnvf(GL_POINT_SPRITE_ARB
, GL_COORD_REPLACE_ARB
, TRUE
);
4316 checkGLcall("glTexEnvf(GL_POINT_SPRITE, GL_COORD_REPLACE, TRUE)");
4318 glTexEnvf(GL_POINT_SPRITE_ARB
, GL_COORD_REPLACE_ARB
, FALSE
);
4319 checkGLcall("glTexEnvf(GL_POINT_SPRITE, GL_COORD_REPLACE, FALSE)");
4323 case WINED3DRS_EDGEANTIALIAS
:
4326 glBlendFunc(GL_SRC_ALPHA
, GL_ONE_MINUS_SRC_ALPHA
);
4328 checkGLcall("glEnable(GL_BLEND)");
4329 glEnable(GL_LINE_SMOOTH
);
4330 checkGLcall("glEnable(GL_LINE_SMOOTH)");
4332 if(!This
->stateBlock
->renderState
[WINED3DRS_ALPHABLENDENABLE
]) {
4333 glDisable(GL_BLEND
);
4334 checkGLcall("glDisable(GL_BLEND)");
4336 glDisable(GL_LINE_SMOOTH
);
4337 checkGLcall("glDisable(GL_LINE_SMOOTH)");
4341 case WINED3DRS_WRAP0
:
4342 case WINED3DRS_WRAP1
:
4343 case WINED3DRS_WRAP2
:
4344 case WINED3DRS_WRAP3
:
4345 case WINED3DRS_WRAP4
:
4346 case WINED3DRS_WRAP5
:
4347 case WINED3DRS_WRAP6
:
4348 case WINED3DRS_WRAP7
:
4349 case WINED3DRS_WRAP8
:
4350 case WINED3DRS_WRAP9
:
4351 case WINED3DRS_WRAP10
:
4352 case WINED3DRS_WRAP11
:
4353 case WINED3DRS_WRAP12
:
4354 case WINED3DRS_WRAP13
:
4355 case WINED3DRS_WRAP14
:
4356 case WINED3DRS_WRAP15
:
4358 http://www.cosc.brocku.ca/Offerings/3P98/course/lectures/texture/
4359 http://msdn.microsoft.com/archive/default.asp?url=/archive/en-us/directx9_c/directx/graphics/programmingguide/FixedFunction/Textures/texturewrapping.asp
4360 http://www.gamedev.net/reference/programming/features/rendererdll3/page2.asp
4361 Descussion that ways to turn on WRAPing to solve an opengl conversion problem.
4362 http://www.flipcode.org/cgi-bin/fcmsg.cgi?thread_show=10248
4364 so far as I can tell, wrapping and texture-coordinate generate go hand in hand,
4366 TRACE("(%p)->(%s,%ld) Texture wraping not yet supported\n",This
, debug_d3drenderstate(State
), Value
);
4368 case WINED3DRS_MULTISAMPLEANTIALIAS
:
4370 if (!GL_SUPPORT(ARB_MULTISAMPLE
)) {
4371 TRACE("Multisample antialiasing not supported\n");
4376 glEnable(GL_MULTISAMPLE_ARB
);
4377 checkGLcall("glEnable(GL_MULTISAMPLE_ARB)");
4379 glDisable(GL_MULTISAMPLE_ARB
);
4380 checkGLcall("glDisable(GL_MULTISAMPLE_ARB)");
4384 case WINED3DRS_SCISSORTESTENABLE
:
4387 glEnable(GL_SCISSOR_TEST
);
4388 checkGLcall("glEnable(GL_SCISSOR_TEST)");
4390 glDisable(GL_SCISSOR_TEST
);
4391 checkGLcall("glDisable(GL_SCISSOR_TEST)");
4395 case WINED3DRS_SLOPESCALEDEPTHBIAS
:
4399 glEnable(GL_POLYGON_OFFSET_FILL
);
4400 checkGLcall("glEnable(GL_POLYGON_OFFSET_FILL)");
4401 glPolygonOffset(tmpvalue
.f
, *((float*)&This
->stateBlock
->renderState
[WINED3DRS_DEPTHBIAS
]));
4402 checkGLcall("glPolygonOffset(...)");
4404 glDisable(GL_POLYGON_OFFSET_FILL
);
4405 checkGLcall("glDisable(GL_POLYGON_OFFSET_FILL)");
4409 case WINED3DRS_ANTIALIASEDLINEENABLE
:
4412 glBlendFunc(GL_SRC_ALPHA
, GL_ONE_MINUS_SRC_ALPHA
);
4414 checkGLcall("glEnable(GL_BLEND)");
4415 glEnable(GL_LINE_SMOOTH
);
4416 checkGLcall("glEnable(GL_LINE_SMOOTH)");
4418 glDisable(GL_BLEND
);
4419 checkGLcall("glDisable(GL_BLEND)");
4420 glDisable(GL_LINE_SMOOTH
);
4421 checkGLcall("glDisable(GL_LINE_SMOOTH)");
4425 case WINED3DRS_DEPTHBIAS
:
4429 glEnable(GL_POLYGON_OFFSET_FILL
);
4430 checkGLcall("glEnable(GL_POLYGON_OFFSET_FILL)");
4431 glPolygonOffset(*((float*)&This
->stateBlock
->renderState
[WINED3DRS_SLOPESCALEDEPTHBIAS
]), tmpvalue
.f
);
4432 checkGLcall("glPolygonOffset(...)");
4434 glDisable(GL_POLYGON_OFFSET_FILL
);
4435 checkGLcall("glDisable(GL_POLYGON_OFFSET_FILL)");
4440 case WINED3DRS_TEXTUREPERSPECTIVE
:
4443 glHint(GL_PERSPECTIVE_CORRECTION_HINT
, GL_NICEST
);
4445 glHint(GL_PERSPECTIVE_CORRECTION_HINT
, GL_FASTEST
);
4449 case WINED3DRS_STIPPLEDALPHA
:
4452 ERR(" Stippled Alpha not supported yet.\n");
4455 case WINED3DRS_ANTIALIAS
:
4458 ERR(" Antialias not supported yet.\n");
4462 FIXME("(%p)->(%s,%ld) not handled yet\n", This
, debug_d3drenderstate(State
), Value
);
4470 static HRESULT WINAPI
IWineD3DDeviceImpl_GetRenderState(IWineD3DDevice
*iface
, D3DRENDERSTATETYPE State
, DWORD
*pValue
) {
4471 IWineD3DDeviceImpl
*This
= (IWineD3DDeviceImpl
*)iface
;
4472 TRACE("(%p) for State %d = %ld\n", This
, State
, This
->stateBlock
->renderState
[State
]);
4473 *pValue
= This
->stateBlock
->renderState
[State
];
4478 * Get / Set Sampler States
4479 * TODO: Verify against dx9 definitions
4482 static HRESULT WINAPI
IWineD3DDeviceImpl_SetSamplerState(IWineD3DDevice
*iface
, DWORD Sampler
, WINED3DSAMPLERSTATETYPE Type
, DWORD Value
) {
4483 IWineD3DDeviceImpl
*This
= (IWineD3DDeviceImpl
*)iface
;
4485 * SetSampler is designed to allow for more than the standard up to 8 textures
4486 * and Geforce has stopped supporting more than 6 standard textures in openGL.
4487 * So I have to use ARB for Gforce. (maybe if the sampler > 4 then use ARB?)
4489 * http://developer.nvidia.com/object/General_FAQ.html#t6
4491 * There are two new settings for GForce
4493 * GL_MAX_TEXTURE_IMAGE_UNITS_ARB
4494 * and the texture one:
4495 * GL_MAX_TEXTURE_COORDS_ARB.
4496 * Ok GForce say it's ok to use glTexParameter/glGetTexParameter(...).
4498 /** NOTE: States are appled in IWineD3DBaseTextre ApplyStateChanges and IWineD3DDevice SetupTextureStates**/
4499 if(Sampler
> GL_LIMITS(sampler_stages
) || Sampler
< 0 || Type
> WINED3D_HIGHEST_SAMPLER_STATE
|| Type
< 0) {
4500 FIXME("sampler %ld type %s(%u) is out of range [max_samplers=%d, highest_state=%d]\n",
4501 Sampler
, debug_d3dsamplerstate(Type
), Type
, GL_LIMITS(sampler_stages
), WINED3D_HIGHEST_SAMPLER_STATE
);
4502 return WINED3DERR_INVALIDCALL
;
4505 TRACE("(%p) : Sampler=%ld, Type=%s(%d), Value=%ld\n", This
, Sampler
,
4506 debug_d3dsamplerstate(Type
), Type
, Value
);
4507 This
->updateStateBlock
->samplerState
[Sampler
][Type
] = Value
;
4508 This
->updateStateBlock
->set
.samplerState
[Sampler
][Type
] = Value
;
4509 This
->updateStateBlock
->changed
.samplerState
[Sampler
][Type
] = Value
;
4511 /* Handle recording of state blocks */
4512 if (This
->isRecordingState
) {
4513 TRACE("Recording... not performing anything\n");
4520 static HRESULT WINAPI
IWineD3DDeviceImpl_GetSamplerState(IWineD3DDevice
*iface
, DWORD Sampler
, WINED3DSAMPLERSTATETYPE Type
, DWORD
* Value
) {
4521 IWineD3DDeviceImpl
*This
= (IWineD3DDeviceImpl
*)iface
;
4522 /** TODO: check that sampler is in range **/
4523 *Value
= This
->updateStateBlock
->samplerState
[Sampler
][Type
];
4524 TRACE("(%p) : Sampler %ld Type %u Returning %ld\n", This
, Sampler
, Type
, *Value
);
4529 static HRESULT WINAPI
IWineD3DDeviceImpl_SetScissorRect(IWineD3DDevice
*iface
, CONST RECT
* pRect
) {
4530 IWineD3DDeviceImpl
*This
= (IWineD3DDeviceImpl
*)iface
;
4533 /** FIXME: Windows uses a top,left origin openGL uses a bottom Right? **/
4534 TRACE("(%p)Setting new Scissor Rect to %ld:%ld-%ld:%ld\n", This
, pRect
->left
, pRect
->top
, pRect
->right
, pRect
->bottom
);
4535 glScissor(pRect
->left
, pRect
->top
, pRect
->right
- pRect
->left
, pRect
->bottom
- pRect
->top
);
4541 static HRESULT WINAPI
IWineD3DDeviceImpl_GetScissorRect(IWineD3DDevice
*iface
, RECT
* pRect
) {
4542 IWineD3DDeviceImpl
*This
= (IWineD3DDeviceImpl
*)iface
;
4543 GLint scissorBox
[4];
4546 /** FIXME: Windows uses a top,left origin openGL uses a bottom Right? **/
4547 glGetIntegerv(GL_SCISSOR_BOX
, scissorBox
);
4548 pRect
->left
= scissorBox
[0];
4549 pRect
->top
= scissorBox
[1];
4550 pRect
->right
= scissorBox
[0] + scissorBox
[2];
4551 pRect
->bottom
= scissorBox
[1] + scissorBox
[3];
4552 TRACE("(%p)Returning a Scissor Rect of %ld:%ld-%ld:%ld\n", This
, pRect
->left
, pRect
->top
, pRect
->right
, pRect
->bottom
);
4557 static HRESULT WINAPI
IWineD3DDeviceImpl_SetVertexDeclaration(IWineD3DDevice
* iface
, IWineD3DVertexDeclaration
* pDecl
) {
4558 IWineD3DDeviceImpl
*This
= (IWineD3DDeviceImpl
*) iface
;
4559 IWineD3DVertexDeclaration
*oldDecl
= This
->updateStateBlock
->vertexDecl
;
4561 TRACE("(%p) : pDecl=%p\n", This
, pDecl
);
4563 This
->updateStateBlock
->vertexDecl
= pDecl
;
4564 This
->updateStateBlock
->changed
.vertexDecl
= TRUE
;
4565 This
->updateStateBlock
->set
.vertexDecl
= TRUE
;
4567 if (This
->isRecordingState
) {
4568 TRACE("Recording... not performing anything\n");
4571 if (NULL
!= pDecl
) {
4572 IWineD3DVertexDeclaration_AddRef(pDecl
);
4574 if (NULL
!= oldDecl
) {
4575 IWineD3DVertexDeclaration_Release(oldDecl
);
4580 static HRESULT WINAPI
IWineD3DDeviceImpl_GetVertexDeclaration(IWineD3DDevice
* iface
, IWineD3DVertexDeclaration
** ppDecl
) {
4581 IWineD3DDeviceImpl
*This
= (IWineD3DDeviceImpl
*)iface
;
4583 TRACE("(%p) : ppDecl=%p\n", This
, ppDecl
);
4585 *ppDecl
= This
->stateBlock
->vertexDecl
;
4586 if (NULL
!= *ppDecl
) IWineD3DVertexDeclaration_AddRef(*ppDecl
);
4590 static HRESULT WINAPI
IWineD3DDeviceImpl_SetVertexShader(IWineD3DDevice
*iface
, IWineD3DVertexShader
* pShader
) {
4591 IWineD3DDeviceImpl
*This
= (IWineD3DDeviceImpl
*)iface
;
4592 IWineD3DVertexShader
* oldShader
= This
->updateStateBlock
->vertexShader
;
4594 This
->updateStateBlock
->vertexShader
= pShader
;
4595 This
->updateStateBlock
->changed
.vertexShader
= TRUE
;
4596 This
->updateStateBlock
->set
.vertexShader
= TRUE
;
4598 if (This
->isRecordingState
) {
4599 TRACE("Recording... not performing anything\n");
4602 if (NULL
!= pShader
) {
4603 IWineD3DVertexShader_AddRef(pShader
);
4605 if (NULL
!= oldShader
) {
4606 IWineD3DVertexShader_Release(oldShader
);
4609 TRACE("(%p) : setting pShader(%p)\n", This
, pShader
);
4611 * TODO: merge HAL shaders context switching from prototype
4616 static HRESULT WINAPI
IWineD3DDeviceImpl_GetVertexShader(IWineD3DDevice
*iface
, IWineD3DVertexShader
** ppShader
) {
4617 IWineD3DDeviceImpl
*This
= (IWineD3DDeviceImpl
*)iface
;
4619 if (NULL
== ppShader
) {
4620 return WINED3DERR_INVALIDCALL
;
4622 *ppShader
= This
->stateBlock
->vertexShader
;
4623 if( NULL
!= *ppShader
)
4624 IWineD3DVertexShader_AddRef(*ppShader
);
4626 TRACE("(%p) : returning %p\n", This
, *ppShader
);
4630 static HRESULT WINAPI
IWineD3DDeviceImpl_SetVertexShaderConstantB(
4631 IWineD3DDevice
*iface
,
4633 CONST BOOL
*srcData
,
4636 IWineD3DDeviceImpl
*This
= (IWineD3DDeviceImpl
*)iface
;
4637 int i
, cnt
= min(count
, MAX_CONST_B
- start
);
4639 TRACE("(iface %p, srcData %p, start %d, count %d)\n",
4640 iface
, srcData
, start
, count
);
4642 if (srcData
== NULL
|| cnt
< 0)
4643 return WINED3DERR_INVALIDCALL
;
4645 memcpy(&This
->updateStateBlock
->vertexShaderConstantB
[start
], srcData
, cnt
* sizeof(BOOL
));
4646 for (i
= 0; i
< cnt
; i
++)
4647 TRACE("Set BOOL constant %u to %s\n", start
+ i
, srcData
[i
]? "true":"false");
4649 for (i
= start
; i
< cnt
+ start
; ++i
) {
4650 This
->updateStateBlock
->changed
.vertexShaderConstantsB
[i
] = TRUE
;
4651 This
->updateStateBlock
->set
.vertexShaderConstantsB
[i
] = TRUE
;
4657 static HRESULT WINAPI
IWineD3DDeviceImpl_GetVertexShaderConstantB(
4658 IWineD3DDevice
*iface
,
4663 IWineD3DDeviceImpl
*This
= (IWineD3DDeviceImpl
*)iface
;
4664 int cnt
= min(count
, MAX_CONST_B
- start
);
4666 TRACE("(iface %p, dstData %p, start %d, count %d)\n",
4667 iface
, dstData
, start
, count
);
4669 if (dstData
== NULL
|| cnt
< 0)
4670 return WINED3DERR_INVALIDCALL
;
4672 memcpy(dstData
, &This
->stateBlock
->vertexShaderConstantB
[start
], cnt
* sizeof(BOOL
));
4676 static HRESULT WINAPI
IWineD3DDeviceImpl_SetVertexShaderConstantI(
4677 IWineD3DDevice
*iface
,
4682 IWineD3DDeviceImpl
*This
= (IWineD3DDeviceImpl
*)iface
;
4683 int i
, cnt
= min(count
, MAX_CONST_I
- start
);
4685 TRACE("(iface %p, srcData %p, start %d, count %d)\n",
4686 iface
, srcData
, start
, count
);
4688 if (srcData
== NULL
|| cnt
< 0)
4689 return WINED3DERR_INVALIDCALL
;
4691 memcpy(&This
->updateStateBlock
->vertexShaderConstantI
[start
* 4], srcData
, cnt
* sizeof(int) * 4);
4692 for (i
= 0; i
< cnt
; i
++)
4693 TRACE("Set INT constant %u to { %d, %d, %d, %d }\n", start
+ i
,
4694 srcData
[i
*4], srcData
[i
*4+1], srcData
[i
*4+2], srcData
[i
*4+3]);
4696 for (i
= start
; i
< cnt
+ start
; ++i
) {
4697 This
->updateStateBlock
->changed
.vertexShaderConstantsI
[i
] = TRUE
;
4698 This
->updateStateBlock
->set
.vertexShaderConstantsI
[i
] = TRUE
;
4704 static HRESULT WINAPI
IWineD3DDeviceImpl_GetVertexShaderConstantI(
4705 IWineD3DDevice
*iface
,
4710 IWineD3DDeviceImpl
*This
= (IWineD3DDeviceImpl
*)iface
;
4711 int cnt
= min(count
, MAX_CONST_I
- start
);
4713 TRACE("(iface %p, dstData %p, start %d, count %d)\n",
4714 iface
, dstData
, start
, count
);
4716 if (dstData
== NULL
|| cnt
< 0)
4717 return WINED3DERR_INVALIDCALL
;
4719 memcpy(dstData
, &This
->stateBlock
->vertexShaderConstantI
[start
* 4], cnt
* sizeof(int) * 4);
4723 static HRESULT WINAPI
IWineD3DDeviceImpl_SetVertexShaderConstantF(
4724 IWineD3DDevice
*iface
,
4726 CONST
float *srcData
,
4729 IWineD3DDeviceImpl
*This
= (IWineD3DDeviceImpl
*)iface
;
4730 int i
, cnt
= min(count
, GL_LIMITS(vshader_constantsF
) - start
);
4732 TRACE("(iface %p, srcData %p, start %d, count %d)\n",
4733 iface
, srcData
, start
, count
);
4735 if (srcData
== NULL
|| cnt
< 0)
4736 return WINED3DERR_INVALIDCALL
;
4738 memcpy(&This
->updateStateBlock
->vertexShaderConstantF
[start
* 4], srcData
, cnt
* sizeof(float) * 4);
4739 for (i
= 0; i
< cnt
; i
++)
4740 TRACE("Set FLOAT constant %u to { %f, %f, %f, %f }\n", start
+ i
,
4741 srcData
[i
*4], srcData
[i
*4+1], srcData
[i
*4+2], srcData
[i
*4+3]);
4743 for (i
= start
; i
< cnt
+ start
; ++i
) {
4744 This
->updateStateBlock
->changed
.vertexShaderConstantsF
[i
] = TRUE
;
4745 This
->updateStateBlock
->set
.vertexShaderConstantsF
[i
] = TRUE
;
4751 static HRESULT WINAPI
IWineD3DDeviceImpl_GetVertexShaderConstantF(
4752 IWineD3DDevice
*iface
,
4757 IWineD3DDeviceImpl
*This
= (IWineD3DDeviceImpl
*)iface
;
4758 int cnt
= min(count
, GL_LIMITS(vshader_constantsF
) - start
);
4760 TRACE("(iface %p, dstData %p, start %d, count %d)\n",
4761 iface
, dstData
, start
, count
);
4763 if (dstData
== NULL
|| cnt
< 0)
4764 return WINED3DERR_INVALIDCALL
;
4766 memcpy(dstData
, &This
->stateBlock
->vertexShaderConstantF
[start
* 4], cnt
* sizeof(float) * 4);
4770 static HRESULT WINAPI
IWineD3DDeviceImpl_SetPixelShader(IWineD3DDevice
*iface
, IWineD3DPixelShader
*pShader
) {
4771 IWineD3DDeviceImpl
*This
= (IWineD3DDeviceImpl
*)iface
;
4772 IWineD3DPixelShader
*oldShader
= This
->updateStateBlock
->pixelShader
;
4773 This
->updateStateBlock
->pixelShader
= pShader
;
4774 This
->updateStateBlock
->changed
.pixelShader
= TRUE
;
4775 This
->updateStateBlock
->set
.pixelShader
= TRUE
;
4777 /* Handle recording of state blocks */
4778 if (This
->isRecordingState
) {
4779 TRACE("Recording... not performing anything\n");
4782 if (NULL
!= pShader
) {
4783 IWineD3DPixelShader_AddRef(pShader
);
4785 if (NULL
!= oldShader
) {
4786 IWineD3DPixelShader_Release(oldShader
);
4789 TRACE("(%p) : setting pShader(%p)\n", This
, pShader
);
4791 * TODO: merge HAL shaders context switching from prototype
4796 static HRESULT WINAPI
IWineD3DDeviceImpl_GetPixelShader(IWineD3DDevice
*iface
, IWineD3DPixelShader
**ppShader
) {
4797 IWineD3DDeviceImpl
*This
= (IWineD3DDeviceImpl
*)iface
;
4799 if (NULL
== ppShader
) {
4800 WARN("(%p) : PShader is NULL, returning INVALIDCALL\n", This
);
4801 return WINED3DERR_INVALIDCALL
;
4804 *ppShader
= This
->stateBlock
->pixelShader
;
4805 if (NULL
!= *ppShader
) {
4806 IWineD3DPixelShader_AddRef(*ppShader
);
4808 TRACE("(%p) : returning %p\n", This
, *ppShader
);
4812 static HRESULT WINAPI
IWineD3DDeviceImpl_SetPixelShaderConstantB(
4813 IWineD3DDevice
*iface
,
4815 CONST BOOL
*srcData
,
4818 IWineD3DDeviceImpl
*This
= (IWineD3DDeviceImpl
*)iface
;
4819 int i
, cnt
= min(count
, MAX_CONST_B
- start
);
4821 TRACE("(iface %p, srcData %p, start %d, count %d)\n",
4822 iface
, srcData
, start
, count
);
4824 if (srcData
== NULL
|| cnt
< 0)
4825 return WINED3DERR_INVALIDCALL
;
4827 memcpy(&This
->updateStateBlock
->pixelShaderConstantB
[start
], srcData
, cnt
* sizeof(BOOL
));
4828 for (i
= 0; i
< cnt
; i
++)
4829 TRACE("Set BOOL constant %u to %s\n", start
+ i
, srcData
[i
]? "true":"false");
4831 for (i
= start
; i
< cnt
+ start
; ++i
) {
4832 This
->updateStateBlock
->changed
.pixelShaderConstantsB
[i
] = TRUE
;
4833 This
->updateStateBlock
->set
.pixelShaderConstantsB
[i
] = TRUE
;
4839 static HRESULT WINAPI
IWineD3DDeviceImpl_GetPixelShaderConstantB(
4840 IWineD3DDevice
*iface
,
4845 IWineD3DDeviceImpl
*This
= (IWineD3DDeviceImpl
*)iface
;
4846 int cnt
= min(count
, MAX_CONST_B
- start
);
4848 TRACE("(iface %p, dstData %p, start %d, count %d)\n",
4849 iface
, dstData
, start
, count
);
4851 if (dstData
== NULL
|| cnt
< 0)
4852 return WINED3DERR_INVALIDCALL
;
4854 memcpy(dstData
, &This
->stateBlock
->pixelShaderConstantB
[start
], cnt
* sizeof(BOOL
));
4858 static HRESULT WINAPI
IWineD3DDeviceImpl_SetPixelShaderConstantI(
4859 IWineD3DDevice
*iface
,
4864 IWineD3DDeviceImpl
*This
= (IWineD3DDeviceImpl
*)iface
;
4865 int i
, cnt
= min(count
, MAX_CONST_I
- start
);
4867 TRACE("(iface %p, srcData %p, start %d, count %d)\n",
4868 iface
, srcData
, start
, count
);
4870 if (srcData
== NULL
|| cnt
< 0)
4871 return WINED3DERR_INVALIDCALL
;
4873 memcpy(&This
->updateStateBlock
->pixelShaderConstantI
[start
* 4], srcData
, cnt
* sizeof(int) * 4);
4874 for (i
= 0; i
< cnt
; i
++)
4875 TRACE("Set INT constant %u to { %d, %d, %d, %d }\n", start
+ i
,
4876 srcData
[i
*4], srcData
[i
*4+1], srcData
[i
*4+2], srcData
[i
*4+3]);
4878 for (i
= start
; i
< cnt
+ start
; ++i
) {
4879 This
->updateStateBlock
->changed
.pixelShaderConstantsI
[i
] = TRUE
;
4880 This
->updateStateBlock
->set
.pixelShaderConstantsI
[i
] = TRUE
;
4886 static HRESULT WINAPI
IWineD3DDeviceImpl_GetPixelShaderConstantI(
4887 IWineD3DDevice
*iface
,
4892 IWineD3DDeviceImpl
*This
= (IWineD3DDeviceImpl
*)iface
;
4893 int cnt
= min(count
, MAX_CONST_I
- start
);
4895 TRACE("(iface %p, dstData %p, start %d, count %d)\n",
4896 iface
, dstData
, start
, count
);
4898 if (dstData
== NULL
|| cnt
< 0)
4899 return WINED3DERR_INVALIDCALL
;
4901 memcpy(dstData
, &This
->stateBlock
->pixelShaderConstantI
[start
* 4], cnt
* sizeof(int) * 4);
4905 static HRESULT WINAPI
IWineD3DDeviceImpl_SetPixelShaderConstantF(
4906 IWineD3DDevice
*iface
,
4908 CONST
float *srcData
,
4911 IWineD3DDeviceImpl
*This
= (IWineD3DDeviceImpl
*)iface
;
4912 int i
, cnt
= min(count
, GL_LIMITS(pshader_constantsF
) - start
);
4914 TRACE("(iface %p, srcData %p, start %d, count %d)\n",
4915 iface
, srcData
, start
, count
);
4917 if (srcData
== NULL
|| cnt
< 0)
4918 return WINED3DERR_INVALIDCALL
;
4920 memcpy(&This
->updateStateBlock
->pixelShaderConstantF
[start
* 4], srcData
, cnt
* sizeof(float) * 4);
4921 for (i
= 0; i
< cnt
; i
++)
4922 TRACE("Set FLOAT constant %u to { %f, %f, %f, %f }\n", start
+ i
,
4923 srcData
[i
*4], srcData
[i
*4+1], srcData
[i
*4+2], srcData
[i
*4+3]);
4925 for (i
= start
; i
< cnt
+ start
; ++i
) {
4926 This
->updateStateBlock
->changed
.pixelShaderConstantsF
[i
] = TRUE
;
4927 This
->updateStateBlock
->set
.pixelShaderConstantsF
[i
] = TRUE
;
4933 static HRESULT WINAPI
IWineD3DDeviceImpl_GetPixelShaderConstantF(
4934 IWineD3DDevice
*iface
,
4939 IWineD3DDeviceImpl
*This
= (IWineD3DDeviceImpl
*)iface
;
4940 int cnt
= min(count
, GL_LIMITS(pshader_constantsF
) - start
);
4942 TRACE("(iface %p, dstData %p, start %d, count %d)\n",
4943 iface
, dstData
, start
, count
);
4945 if (dstData
== NULL
|| cnt
< 0)
4946 return WINED3DERR_INVALIDCALL
;
4948 memcpy(dstData
, &This
->stateBlock
->pixelShaderConstantF
[start
* 4], cnt
* sizeof(float) * 4);
4952 #define copy_and_next(dest, src, size) memcpy(dest, src, size); dest += (size)
4954 process_vertices_strided(IWineD3DDeviceImpl
*This
, DWORD dwDestIndex
, DWORD dwCount
, WineDirect3DVertexStridedData
*lpStrideData
, DWORD SrcFVF
, IWineD3DVertexBufferImpl
*dest
, DWORD dwFlags
) {
4955 char *dest_ptr
, *dest_conv
= NULL
;
4957 DWORD DestFVF
= dest
->fvf
;
4959 D3DMATRIX mat
, proj_mat
, view_mat
, world_mat
;
4963 if (SrcFVF
& D3DFVF_NORMAL
) {
4964 WARN(" lighting state not saved yet... Some strange stuff may happen !\n");
4967 if ( (SrcFVF
& D3DFVF_POSITION_MASK
) != D3DFVF_XYZ
) {
4968 ERR("Source has no position mask\n");
4969 return WINED3DERR_INVALIDCALL
;
4972 /* We might access VBOs from this code, so hold the lock */
4975 if (dest
->resource
.allocatedMemory
== NULL
) {
4976 /* This may happen if we do direct locking into a vbo. Unlikely,
4977 * but theoretically possible(ddraw processvertices test)
4979 dest
->resource
.allocatedMemory
= HeapAlloc(GetProcessHeap(), 0, dest
->resource
.size
);
4980 if(!dest
->resource
.allocatedMemory
) {
4982 ERR("Out of memory\n");
4983 return E_OUTOFMEMORY
;
4987 GL_EXTCALL(glBindBufferARB(GL_ARRAY_BUFFER_ARB
, dest
->vbo
));
4988 checkGLcall("glBindBufferARB");
4989 src
= GL_EXTCALL(glMapBufferARB(GL_ARRAY_BUFFER_ARB
, GL_READ_ONLY_ARB
));
4991 memcpy(dest
->resource
.allocatedMemory
, src
, dest
->resource
.size
);
4993 GL_EXTCALL(glUnmapBufferARB(GL_ARRAY_BUFFER_ARB
));
4994 checkGLcall("glUnmapBufferARB");
4998 /* Get a pointer into the destination vbo(create one if none exists) and
4999 * write correct opengl data into it. It's cheap and allows us to run drawStridedFast
5001 if(!dest
->vbo
&& GL_SUPPORT(ARB_VERTEX_BUFFER_OBJECT
)) {
5006 GL_EXTCALL(glBindBufferARB(GL_ARRAY_BUFFER_ARB
, dest
->vbo
));
5007 dest_conv
= GL_EXTCALL(glMapBufferARB(GL_ARRAY_BUFFER_ARB
, GL_WRITE_ONLY_ARB
));
5009 ERR("glMapBuffer failed\n");
5010 /* Continue without storing converted vertices */
5015 * a) D3DRS_CLIPPING is enabled
5016 * b) WINED3DVOP_CLIP is passed
5018 if(This
->stateBlock
->renderState
[WINED3DRS_CLIPPING
]) {
5019 static BOOL warned
= FALSE
;
5021 * The clipping code is not quite correct. Some things need
5022 * to be checked against IDirect3DDevice3 (!), d3d8 and d3d9,
5023 * so disable clipping for now.
5024 * (The graphics in Half-Life are broken, and my processvertices
5025 * test crashes with IDirect3DDevice3)
5031 FIXME("Clipping is broken and disabled for now\n");
5033 } else doClip
= FALSE
;
5034 dest_ptr
= ((char *) dest
->resource
.allocatedMemory
) + dwDestIndex
* get_flexible_vertex_size(DestFVF
);
5036 dest_conv
= ((char *) dest_conv
) + dwDestIndex
* get_flexible_vertex_size(DestFVF
);
5039 IWineD3DDevice_GetTransform( (IWineD3DDevice
*) This
,
5042 IWineD3DDevice_GetTransform( (IWineD3DDevice
*) This
,
5043 WINED3DTS_PROJECTION
,
5045 IWineD3DDevice_GetTransform( (IWineD3DDevice
*) This
,
5046 WINED3DTS_WORLDMATRIX(0),
5049 TRACE("View mat:\n");
5050 TRACE("%f %f %f %f\n", view_mat
.u
.s
._11
, view_mat
.u
.s
._12
, view_mat
.u
.s
._13
, view_mat
.u
.s
._14
); \
5051 TRACE("%f %f %f %f\n", view_mat
.u
.s
._21
, view_mat
.u
.s
._22
, view_mat
.u
.s
._23
, view_mat
.u
.s
._24
); \
5052 TRACE("%f %f %f %f\n", view_mat
.u
.s
._31
, view_mat
.u
.s
._32
, view_mat
.u
.s
._33
, view_mat
.u
.s
._34
); \
5053 TRACE("%f %f %f %f\n", view_mat
.u
.s
._41
, view_mat
.u
.s
._42
, view_mat
.u
.s
._43
, view_mat
.u
.s
._44
); \
5055 TRACE("Proj mat:\n");
5056 TRACE("%f %f %f %f\n", proj_mat
.u
.s
._11
, proj_mat
.u
.s
._12
, proj_mat
.u
.s
._13
, proj_mat
.u
.s
._14
); \
5057 TRACE("%f %f %f %f\n", proj_mat
.u
.s
._21
, proj_mat
.u
.s
._22
, proj_mat
.u
.s
._23
, proj_mat
.u
.s
._24
); \
5058 TRACE("%f %f %f %f\n", proj_mat
.u
.s
._31
, proj_mat
.u
.s
._32
, proj_mat
.u
.s
._33
, proj_mat
.u
.s
._34
); \
5059 TRACE("%f %f %f %f\n", proj_mat
.u
.s
._41
, proj_mat
.u
.s
._42
, proj_mat
.u
.s
._43
, proj_mat
.u
.s
._44
); \
5061 TRACE("World mat:\n");
5062 TRACE("%f %f %f %f\n", world_mat
.u
.s
._11
, world_mat
.u
.s
._12
, world_mat
.u
.s
._13
, world_mat
.u
.s
._14
); \
5063 TRACE("%f %f %f %f\n", world_mat
.u
.s
._21
, world_mat
.u
.s
._22
, world_mat
.u
.s
._23
, world_mat
.u
.s
._24
); \
5064 TRACE("%f %f %f %f\n", world_mat
.u
.s
._31
, world_mat
.u
.s
._32
, world_mat
.u
.s
._33
, world_mat
.u
.s
._34
); \
5065 TRACE("%f %f %f %f\n", world_mat
.u
.s
._41
, world_mat
.u
.s
._42
, world_mat
.u
.s
._43
, world_mat
.u
.s
._44
); \
5067 /* Get the viewport */
5068 IWineD3DDevice_GetViewport( (IWineD3DDevice
*) This
, &vp
);
5069 TRACE("Viewport: X=%ld, Y=%ld, Width=%ld, Height=%ld, MinZ=%f, MaxZ=%f\n",
5070 vp
.X
, vp
.Y
, vp
.Width
, vp
.Height
, vp
.MinZ
, vp
.MaxZ
);
5072 multiply_matrix(&mat
,&view_mat
,&world_mat
);
5073 multiply_matrix(&mat
,&proj_mat
,&mat
);
5075 numTextures
= (DestFVF
& D3DFVF_TEXCOUNT_MASK
) >> D3DFVF_TEXCOUNT_SHIFT
;
5077 for (i
= 0; i
< dwCount
; i
+= 1) {
5078 unsigned int tex_index
;
5080 if ( ((DestFVF
& D3DFVF_POSITION_MASK
) == D3DFVF_XYZ
) ||
5081 ((DestFVF
& D3DFVF_POSITION_MASK
) == D3DFVF_XYZRHW
) ) {
5082 /* The position first */
5084 (float *) (((char *) lpStrideData
->u
.s
.position
.lpData
) + i
* lpStrideData
->u
.s
.position
.dwStride
);
5086 TRACE("In: ( %06.2f %06.2f %06.2f )\n", p
[0], p
[1], p
[2]);
5088 /* Multiplication with world, view and projection matrix */
5089 x
= (p
[0] * mat
.u
.s
._11
) + (p
[1] * mat
.u
.s
._21
) + (p
[2] * mat
.u
.s
._31
) + (1.0 * mat
.u
.s
._41
);
5090 y
= (p
[0] * mat
.u
.s
._12
) + (p
[1] * mat
.u
.s
._22
) + (p
[2] * mat
.u
.s
._32
) + (1.0 * mat
.u
.s
._42
);
5091 z
= (p
[0] * mat
.u
.s
._13
) + (p
[1] * mat
.u
.s
._23
) + (p
[2] * mat
.u
.s
._33
) + (1.0 * mat
.u
.s
._43
);
5092 rhw
= (p
[0] * mat
.u
.s
._14
) + (p
[1] * mat
.u
.s
._24
) + (p
[2] * mat
.u
.s
._34
) + (1.0 * mat
.u
.s
._44
);
5094 TRACE("x=%f y=%f z=%f rhw=%f\n", x
, y
, z
, rhw
);
5096 /* WARNING: The following things are taken from d3d7 and were not yet checked
5097 * against d3d8 or d3d9!
5100 /* Clipping conditions: From
5101 * http://msdn.microsoft.com/archive/default.asp?url=/archive/en-us/directx9_c/directx/graphics/programmingguide/fixedfunction/viewportsclipping/clippingvolumes.asp
5103 * A vertex is clipped if it does not match the following requirements
5107 * 0 < rhw ( Not in d3d7, but tested in d3d7)
5109 * If clipping is on is determined by the D3DVOP_CLIP flag in D3D7, and
5110 * by the D3DRS_CLIPPING in D3D9(according to the msdn, not checked)
5114 if( doClip
== FALSE
||
5115 ( (-rhw
-eps
< x
) && (-rhw
-eps
< y
) && ( -eps
< z
) &&
5116 (x
<= rhw
+ eps
) && (y
<= rhw
+ eps
) && (z
<= rhw
+ eps
) &&
5119 /* "Normal" viewport transformation (not clipped)
5120 * 1) The values are divided by rhw
5121 * 2) The y axis is negative, so multiply it with -1
5122 * 3) Screen coordinates go from -(Width/2) to +(Width/2) and
5123 * -(Height/2) to +(Height/2). The z range is MinZ to MaxZ
5124 * 4) Multiply x with Width/2 and add Width/2
5125 * 5) The same for the height
5126 * 6) Add the viewpoint X and Y to the 2D coordinates and
5127 * The minimum Z value to z
5128 * 7) rhw = 1 / rhw Reciprocal of Homogeneous W....
5130 * Well, basically it's simply a linear transformation into viewport
5142 z
*= vp
.MaxZ
- vp
.MinZ
;
5144 x
+= vp
.Width
/ 2 + vp
.X
;
5145 y
+= vp
.Height
/ 2 + vp
.Y
;
5150 /* That vertex got clipped
5151 * Contrary to OpenGL it is not dropped completely, it just
5152 * undergoes a different calculation.
5154 TRACE("Vertex got clipped\n");
5161 /* Msdn mentions that Direct3D9 keeps a list of clipped vertices
5162 * outside of the main vertex buffer memory. That needs some more
5167 TRACE("Writing (%f %f %f) %f\n", x
, y
, z
, rhw
);
5170 ( (float *) dest_ptr
)[0] = x
;
5171 ( (float *) dest_ptr
)[1] = y
;
5172 ( (float *) dest_ptr
)[2] = z
;
5173 ( (float *) dest_ptr
)[3] = rhw
; /* SIC, see ddraw test! */
5175 dest_ptr
+= 3 * sizeof(float);
5177 if((DestFVF
& D3DFVF_POSITION_MASK
) == D3DFVF_XYZRHW
) {
5178 dest_ptr
+= sizeof(float);
5183 ( (float *) dest_conv
)[0] = x
* w
;
5184 ( (float *) dest_conv
)[1] = y
* w
;
5185 ( (float *) dest_conv
)[2] = z
* w
;
5186 ( (float *) dest_conv
)[3] = w
;
5188 dest_conv
+= 3 * sizeof(float);
5190 if((DestFVF
& D3DFVF_POSITION_MASK
) == D3DFVF_XYZRHW
) {
5191 dest_conv
+= sizeof(float);
5195 if (DestFVF
& D3DFVF_PSIZE
) {
5196 dest_ptr
+= sizeof(DWORD
);
5197 if(dest_conv
) dest_conv
+= sizeof(DWORD
);
5199 if (DestFVF
& D3DFVF_NORMAL
) {
5201 (float *) (((float *) lpStrideData
->u
.s
.normal
.lpData
) + i
* lpStrideData
->u
.s
.normal
.dwStride
);
5202 /* AFAIK this should go into the lighting information */
5203 FIXME("Didn't expect the destination to have a normal\n");
5204 copy_and_next(dest_ptr
, normal
, 3 * sizeof(float));
5206 copy_and_next(dest_conv
, normal
, 3 * sizeof(float));
5210 if (DestFVF
& D3DFVF_DIFFUSE
) {
5212 (DWORD
*) (((char *) lpStrideData
->u
.s
.diffuse
.lpData
) + i
* lpStrideData
->u
.s
.diffuse
.dwStride
);
5214 static BOOL warned
= FALSE
;
5216 if(warned
== FALSE
) {
5217 ERR("No diffuse color in source, but destination has one\n");
5221 *( (DWORD
*) dest_ptr
) = 0xffffffff;
5222 dest_ptr
+= sizeof(DWORD
);
5225 *( (DWORD
*) dest_conv
) = 0xffffffff;
5226 dest_conv
+= sizeof(DWORD
);
5230 copy_and_next(dest_ptr
, color_d
, sizeof(DWORD
));
5232 *( (DWORD
*) dest_conv
) = (*color_d
& 0xff00ff00) ; /* Alpha + green */
5233 *( (DWORD
*) dest_conv
) |= (*color_d
& 0x00ff0000) >> 16; /* Red */
5234 *( (DWORD
*) dest_conv
) |= (*color_d
& 0xff0000ff) << 16; /* Blue */
5235 dest_conv
+= sizeof(DWORD
);
5240 if (DestFVF
& D3DFVF_SPECULAR
) {
5241 /* What's the color value in the feedback buffer? */
5243 (DWORD
*) (((char *) lpStrideData
->u
.s
.specular
.lpData
) + i
* lpStrideData
->u
.s
.specular
.dwStride
);
5245 static BOOL warned
= FALSE
;
5247 if(warned
== FALSE
) {
5248 ERR("No specular color in source, but destination has one\n");
5252 *( (DWORD
*) dest_ptr
) = 0xFF000000;
5253 dest_ptr
+= sizeof(DWORD
);
5256 *( (DWORD
*) dest_conv
) = 0xFF000000;
5257 dest_conv
+= sizeof(DWORD
);
5261 copy_and_next(dest_ptr
, color_s
, sizeof(DWORD
));
5263 *( (DWORD
*) dest_conv
) = (*color_s
& 0xff00ff00) ; /* Alpha + green */
5264 *( (DWORD
*) dest_conv
) |= (*color_s
& 0x00ff0000) >> 16; /* Red */
5265 *( (DWORD
*) dest_conv
) |= (*color_s
& 0xff0000ff) << 16; /* Blue */
5266 dest_conv
+= sizeof(DWORD
);
5271 for (tex_index
= 0; tex_index
< numTextures
; tex_index
++) {
5273 (float *) (((char *) lpStrideData
->u
.s
.texCoords
[tex_index
].lpData
) +
5274 i
* lpStrideData
->u
.s
.texCoords
[tex_index
].dwStride
);
5276 ERR("No source texture, but destination requests one\n");
5277 dest_ptr
+=GET_TEXCOORD_SIZE_FROM_FVF(DestFVF
, tex_index
) * sizeof(float);
5278 if(dest_conv
) dest_conv
+= GET_TEXCOORD_SIZE_FROM_FVF(DestFVF
, tex_index
) * sizeof(float);
5281 copy_and_next(dest_ptr
, tex_coord
, GET_TEXCOORD_SIZE_FROM_FVF(DestFVF
, tex_index
) * sizeof(float));
5283 copy_and_next(dest_conv
, tex_coord
, GET_TEXCOORD_SIZE_FROM_FVF(DestFVF
, tex_index
) * sizeof(float));
5290 GL_EXTCALL(glUnmapBufferARB(GL_ARRAY_BUFFER_ARB
));
5291 checkGLcall("glUnmapBufferARB(GL_ARRAY_BUFFER_ARB)");
5298 #undef copy_and_next
5300 static HRESULT WINAPI
IWineD3DDeviceImpl_ProcessVertices(IWineD3DDevice
*iface
, UINT SrcStartIndex
, UINT DestIndex
, UINT VertexCount
, IWineD3DVertexBuffer
* pDestBuffer
, IWineD3DVertexBuffer
* pVertexDecl
, DWORD Flags
) {
5301 IWineD3DDeviceImpl
*This
= (IWineD3DDeviceImpl
*)iface
;
5302 IWineD3DVertexBufferImpl
*SrcImpl
= (IWineD3DVertexBufferImpl
*) pVertexDecl
;
5303 WineDirect3DVertexStridedData strided
;
5304 TRACE("(%p)->(%d,%d,%d,%p,%p,%ld\n", This
, SrcStartIndex
, DestIndex
, VertexCount
, pDestBuffer
, pVertexDecl
, Flags
);
5306 /* We don't need the source vbo because this buffer is only used as
5307 * a source for ProcessVertices. Avoid wasting resources by converting the
5308 * buffer and loading the VBO
5311 TRACE("Releaseing the source vbo, it won't be needed\n");
5313 if(!SrcImpl
->resource
.allocatedMemory
) {
5314 /* Rescue the data from the buffer */
5316 SrcImpl
->resource
.allocatedMemory
= HeapAlloc(GetProcessHeap(), 0, SrcImpl
->resource
.size
);
5317 if(!SrcImpl
->resource
.allocatedMemory
) {
5318 ERR("Out of memory\n");
5319 return E_OUTOFMEMORY
;
5323 GL_EXTCALL(glBindBufferARB(GL_ARRAY_BUFFER_ARB
, SrcImpl
->vbo
));
5324 checkGLcall("glBindBufferARB");
5326 src
= GL_EXTCALL(glMapBufferARB(GL_ARRAY_BUFFER_ARB
, GL_READ_ONLY_ARB
));
5328 memcpy(SrcImpl
->resource
.allocatedMemory
, src
, SrcImpl
->resource
.size
);
5331 GL_EXTCALL(glUnmapBufferARB(GL_ARRAY_BUFFER_ARB
));
5332 checkGLcall("glUnmapBufferARB");
5337 GL_EXTCALL(glBindBufferARB(GL_ARRAY_BUFFER_ARB
, 0));
5338 checkGLcall("glBindBufferARB");
5339 GL_EXTCALL(glDeleteBuffersARB(1, &SrcImpl
->vbo
));
5340 checkGLcall("glDeleteBuffersARB");
5346 memset(&strided
, 0, sizeof(strided
));
5347 primitiveConvertFVFtoOffset(SrcImpl
->fvf
, get_flexible_vertex_size(SrcImpl
->fvf
), SrcImpl
->resource
.allocatedMemory
+ get_flexible_vertex_size(SrcImpl
->fvf
) * SrcStartIndex
, &strided
, 0);
5349 return process_vertices_strided(This
, DestIndex
, VertexCount
, &strided
, SrcImpl
->fvf
, (IWineD3DVertexBufferImpl
*) pDestBuffer
, Flags
);
5353 * Apply / Get / Set Texture Stage States
5354 * TODO: Verify against dx9 definitions
5357 /* NOTE: It's expected that this function is going to be called lots of times with the same stage active, so make it the callers responsibility to GLACTIVETEXTURE(Stage) for better state management. Set the correct Texture unit active before calling ApplyTextureStageState */
5358 static void WINAPI
IWineD3DDeviceImpl_ApplyTextureUnitState(IWineD3DDevice
*iface
, DWORD Stage
, WINED3DTEXTURESTAGESTATETYPE Type
) {
5359 IWineD3DDeviceImpl
*This
= (IWineD3DDeviceImpl
*)iface
;
5360 DWORD Value
= This
->updateStateBlock
->textureState
[Stage
][Type
];
5361 /* FIXME: Handle 3d textures? What if TSS value set before set texture? Need to reapply all values? */
5363 TRACE("(%p) : Stage=%ld, Type=%s(%d), Value=%ld\n", This
, Stage
, debug_d3dtexturestate(Type
), Type
, Value
);
5365 /* Check that the stage is within limits */
5366 if (Stage
>= GL_LIMITS(texture_stages
) || Stage
< 0) {
5367 TRACE("Attempt to access invalid texture rejected\n");
5374 case WINED3DTSS_ALPHAOP
:
5375 case WINED3DTSS_COLOROP
:
5376 /* nothing to do as moved to drawprim for now */
5378 case WINED3DTSS_ADDRESSW
:
5379 #if 0 /* I'm not sure what D3D does about ADDRESSW appearing twice */
5380 if (Value
< minLookup
[WINELOOKUP_WARPPARAM
] || Value
> maxLookup
[WINELOOKUP_WARPPARAM
]) {
5381 FIXME("Unrecognized or unsupported D3DTADDRESS_* value %ld, state %d\n", Value
, Type
);
5384 GLint wrapParm
= stateLookup
[WINELOOKUP_WARPPARAM
][Value
- minLookup
[WINELOOKUP_WARPPARAM
]];
5385 TRACE("Setting WRAP_R to %d for %x\n", wrapParm
, This
->stateBlock
->textureDimensions
[Stage
]);
5386 glTexParameteri(This
->stateBlock
->textureDimensions
[Stage
], GL_TEXTURE_WRAP_R
, wrapParm
);
5387 checkGLcall("glTexParameteri(..., GL_TEXTURE_WRAP_R, wrapParm)");
5390 case WINED3DTSS_TEXCOORDINDEX
:
5392 /* Values 0-7 are indexes into the FVF tex coords - See comments in DrawPrimitive */
5394 /* FIXME: From MSDN: The WINED3DTSS_TCI_* flags are mutually exclusive. If you include
5395 one flag, you can still specify an index value, which the system uses to
5396 determine the texture wrapping mode.
5397 eg. SetTextureStageState( 0, D3DTSS_TEXCOORDINDEX, D3DTSS_TCI_CAMERASPACEPOSITION | 1 );
5398 means use the vertex position (camera-space) as the input texture coordinates
5399 for this texture stage, and the wrap mode set in the WINED3DRS_WRAP1 render
5400 state. We do not (yet) support the D3DRENDERSTATE_WRAPx values, nor tie them up
5401 to the TEXCOORDINDEX value */
5404 * Be careful the value of the mask 0xF0000 come from d3d8types.h infos
5406 switch (Value
& 0xFFFF0000) {
5407 case D3DTSS_TCI_PASSTHRU
:
5408 /*Use the specified texture coordinates contained within the vertex format. This value resolves to zero.*/
5409 glDisable(GL_TEXTURE_GEN_S
);
5410 glDisable(GL_TEXTURE_GEN_T
);
5411 glDisable(GL_TEXTURE_GEN_R
);
5412 glDisable(GL_TEXTURE_GEN_Q
);
5413 checkGLcall("glDisable(GL_TEXTURE_GEN_S,T,R,Q)");
5416 case D3DTSS_TCI_CAMERASPACEPOSITION
:
5417 /* CameraSpacePosition means use the vertex position, transformed to camera space,
5418 as the input texture coordinates for this stage's texture transformation. This
5419 equates roughly to EYE_LINEAR */
5421 float s_plane
[] = { 1.0, 0.0, 0.0, 0.0 };
5422 float t_plane
[] = { 0.0, 1.0, 0.0, 0.0 };
5423 float r_plane
[] = { 0.0, 0.0, 1.0, 0.0 };
5424 float q_plane
[] = { 0.0, 0.0, 0.0, 1.0 };
5425 TRACE("WINED3DTSS_TCI_CAMERASPACEPOSITION - Set eye plane\n");
5427 glMatrixMode(GL_MODELVIEW
);
5430 glTexGenfv(GL_S
, GL_EYE_PLANE
, s_plane
);
5431 glTexGenfv(GL_T
, GL_EYE_PLANE
, t_plane
);
5432 glTexGenfv(GL_R
, GL_EYE_PLANE
, r_plane
);
5433 glTexGenfv(GL_Q
, GL_EYE_PLANE
, q_plane
);
5436 TRACE("WINED3DTSS_TCI_CAMERASPACEPOSITION - Set GL_TEXTURE_GEN_x and GL_x, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR\n");
5437 glEnable(GL_TEXTURE_GEN_S
);
5438 checkGLcall("glEnable(GL_TEXTURE_GEN_S);");
5439 glTexGeni(GL_S
, GL_TEXTURE_GEN_MODE
, GL_EYE_LINEAR
);
5440 checkGLcall("glTexGeni(GL_S, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR)");
5441 glEnable(GL_TEXTURE_GEN_T
);
5442 checkGLcall("glEnable(GL_TEXTURE_GEN_T);");
5443 glTexGeni(GL_T
, GL_TEXTURE_GEN_MODE
, GL_EYE_LINEAR
);
5444 checkGLcall("glTexGeni(GL_T, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR)");
5445 glEnable(GL_TEXTURE_GEN_R
);
5446 checkGLcall("glEnable(GL_TEXTURE_GEN_R);");
5447 glTexGeni(GL_R
, GL_TEXTURE_GEN_MODE
, GL_EYE_LINEAR
);
5448 checkGLcall("glTexGeni(GL_R, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR)");
5452 case D3DTSS_TCI_CAMERASPACENORMAL
:
5454 if (GL_SUPPORT(NV_TEXGEN_REFLECTION
)) {
5455 float s_plane
[] = { 1.0, 0.0, 0.0, 0.0 };
5456 float t_plane
[] = { 0.0, 1.0, 0.0, 0.0 };
5457 float r_plane
[] = { 0.0, 0.0, 1.0, 0.0 };
5458 float q_plane
[] = { 0.0, 0.0, 0.0, 1.0 };
5459 TRACE("WINED3DTSS_TCI_CAMERASPACENORMAL - Set eye plane\n");
5461 glMatrixMode(GL_MODELVIEW
);
5464 glTexGenfv(GL_S
, GL_EYE_PLANE
, s_plane
);
5465 glTexGenfv(GL_T
, GL_EYE_PLANE
, t_plane
);
5466 glTexGenfv(GL_R
, GL_EYE_PLANE
, r_plane
);
5467 glTexGenfv(GL_Q
, GL_EYE_PLANE
, q_plane
);
5470 glEnable(GL_TEXTURE_GEN_S
);
5471 checkGLcall("glEnable(GL_TEXTURE_GEN_S);");
5472 glTexGeni(GL_S
, GL_TEXTURE_GEN_MODE
, GL_NORMAL_MAP_NV
);
5473 checkGLcall("glTexGeni(GL_S, GL_TEXTURE_GEN_MODE, GL_NORMAL_MAP_NV)");
5474 glEnable(GL_TEXTURE_GEN_T
);
5475 checkGLcall("glEnable(GL_TEXTURE_GEN_T);");
5476 glTexGeni(GL_T
, GL_TEXTURE_GEN_MODE
, GL_NORMAL_MAP_NV
);
5477 checkGLcall("glTexGeni(GL_T, GL_TEXTURE_GEN_MODE, GL_NORMAL_MAP_NV)");
5478 glEnable(GL_TEXTURE_GEN_R
);
5479 checkGLcall("glEnable(GL_TEXTURE_GEN_R);");
5480 glTexGeni(GL_R
, GL_TEXTURE_GEN_MODE
, GL_NORMAL_MAP_NV
);
5481 checkGLcall("glTexGeni(GL_R, GL_TEXTURE_GEN_MODE, GL_NORMAL_MAP_NV)");
5486 case D3DTSS_TCI_CAMERASPACEREFLECTIONVECTOR
:
5488 if (GL_SUPPORT(NV_TEXGEN_REFLECTION
)) {
5489 float s_plane
[] = { 1.0, 0.0, 0.0, 0.0 };
5490 float t_plane
[] = { 0.0, 1.0, 0.0, 0.0 };
5491 float r_plane
[] = { 0.0, 0.0, 1.0, 0.0 };
5492 float q_plane
[] = { 0.0, 0.0, 0.0, 1.0 };
5493 TRACE("WINED3DTSS_TCI_CAMERASPACEREFLECTIONVECTOR - Set eye plane\n");
5495 glMatrixMode(GL_MODELVIEW
);
5498 glTexGenfv(GL_S
, GL_EYE_PLANE
, s_plane
);
5499 glTexGenfv(GL_T
, GL_EYE_PLANE
, t_plane
);
5500 glTexGenfv(GL_R
, GL_EYE_PLANE
, r_plane
);
5501 glTexGenfv(GL_Q
, GL_EYE_PLANE
, q_plane
);
5504 glEnable(GL_TEXTURE_GEN_S
);
5505 checkGLcall("glEnable(GL_TEXTURE_GEN_S);");
5506 glTexGeni(GL_S
, GL_TEXTURE_GEN_MODE
, GL_REFLECTION_MAP_NV
);
5507 checkGLcall("glTexGeni(GL_S, GL_TEXTURE_GEN_MODE, GL_REFLECTION_MAP_NV)");
5508 glEnable(GL_TEXTURE_GEN_T
);
5509 checkGLcall("glEnable(GL_TEXTURE_GEN_T);");
5510 glTexGeni(GL_T
, GL_TEXTURE_GEN_MODE
, GL_REFLECTION_MAP_NV
);
5511 checkGLcall("glTexGeni(GL_T, GL_TEXTURE_GEN_MODE, GL_REFLECTION_MAP_NV)");
5512 glEnable(GL_TEXTURE_GEN_R
);
5513 checkGLcall("glEnable(GL_TEXTURE_GEN_R);");
5514 glTexGeni(GL_R
, GL_TEXTURE_GEN_MODE
, GL_REFLECTION_MAP_NV
);
5515 checkGLcall("glTexGeni(GL_R, GL_TEXTURE_GEN_MODE, GL_REFLECTION_MAP_NV)");
5520 /* Unhandled types: */
5523 /* ? disable GL_TEXTURE_GEN_n ? */
5524 glDisable(GL_TEXTURE_GEN_S
);
5525 glDisable(GL_TEXTURE_GEN_T
);
5526 glDisable(GL_TEXTURE_GEN_R
);
5527 glDisable(GL_TEXTURE_GEN_Q
);
5528 FIXME("Unhandled WINED3DTSS_TEXCOORDINDEX %lx\n", Value
);
5535 case WINED3DTSS_TEXTURETRANSFORMFLAGS
:
5536 set_texture_matrix((float *)&This
->stateBlock
->transforms
[WINED3DTS_TEXTURE0
+ Stage
].u
.m
[0][0], Value
, (This
->stateBlock
->textureState
[Stage
][WINED3DTSS_TEXCOORDINDEX
] & 0xFFFF0000) != D3DTSS_TCI_PASSTHRU
);
5539 case WINED3DTSS_BUMPENVMAT00
:
5540 case WINED3DTSS_BUMPENVMAT01
:
5541 TRACE("BUMPENVMAT0%u Stage=%ld, Type=%d, Value =%ld\n", Type
- WINED3DTSS_BUMPENVMAT00
, Stage
, Type
, Value
);
5543 case WINED3DTSS_BUMPENVMAT10
:
5544 case WINED3DTSS_BUMPENVMAT11
:
5545 TRACE("BUMPENVMAT1%u Stage=%ld, Type=%d, Value =%ld\n", Type
- WINED3DTSS_BUMPENVMAT10
, Stage
, Type
, Value
);
5548 case WINED3DTSS_BUMPENVLSCALE
:
5549 TRACE("BUMPENVLSCALE Stage=%ld, Type=%d, Value =%ld\n", Stage
, Type
, Value
);
5552 case WINED3DTSS_BUMPENVLOFFSET
:
5553 TRACE("BUMPENVLOFFSET Stage=%ld, Type=%d, Value =%ld\n", Stage
, Type
, Value
);
5556 case WINED3DTSS_RESULTARG
:
5557 TRACE("RESULTARG Still a stub, Stage=%ld, Type=%d, Value =%ld\n", Stage
, Type
, Value
);
5561 /* Put back later: FIXME("(%p) : stub, Stage=%ld, Type=%d, Value =%ld\n", This, Stage, Type, Value); */
5562 TRACE("Still a stub, Stage=%ld, Type=%d, Value =%ld\n", Stage
, Type
, Value
);
5571 * Get / Set Texture Stage States
5572 * TODO: Verify against dx9 definitions
5574 static HRESULT WINAPI
IWineD3DDeviceImpl_SetTextureStageState(IWineD3DDevice
*iface
, DWORD Stage
, WINED3DTEXTURESTAGESTATETYPE Type
, DWORD Value
) {
5575 IWineD3DDeviceImpl
*This
= (IWineD3DDeviceImpl
*)iface
;
5577 /* FIXME: Handle 3d textures? What if TSS value set before set texture? Need to reapply all values? */
5579 TRACE("(%p) : Stage=%ld, Type=%s(%d), Value=%ld\n", This
, Stage
, debug_d3dtexturestate(Type
), Type
, Value
);
5581 /* Reject invalid texture units */
5582 if (Stage
>= GL_LIMITS(texture_stages
)) {
5583 TRACE("Attempt to access invalid texture rejected\n");
5584 return WINED3DERR_INVALIDCALL
;
5587 This
->updateStateBlock
->changed
.textureState
[Stage
][Type
] = TRUE
;
5588 This
->updateStateBlock
->set
.textureState
[Stage
][Type
] = TRUE
;
5589 This
->updateStateBlock
->textureState
[Stage
][Type
] = Value
;
5594 static HRESULT WINAPI
IWineD3DDeviceImpl_GetTextureStageState(IWineD3DDevice
*iface
, DWORD Stage
, WINED3DTEXTURESTAGESTATETYPE Type
, DWORD
* pValue
) {
5595 IWineD3DDeviceImpl
*This
= (IWineD3DDeviceImpl
*)iface
;
5596 TRACE("(%p) : requesting Stage %ld, Type %d getting %ld\n", This
, Stage
, Type
, This
->updateStateBlock
->textureState
[Stage
][Type
]);
5597 *pValue
= This
->updateStateBlock
->textureState
[Stage
][Type
];
5604 static HRESULT WINAPI
IWineD3DDeviceImpl_SetTexture(IWineD3DDevice
*iface
, DWORD Stage
, IWineD3DBaseTexture
* pTexture
) {
5606 IWineD3DDeviceImpl
*This
= (IWineD3DDeviceImpl
*)iface
;
5607 IWineD3DBaseTexture
*oldTexture
;
5609 oldTexture
= This
->updateStateBlock
->textures
[Stage
];
5610 TRACE("(%p) : Stage(%ld), Texture (%p)\n", This
, Stage
, pTexture
);
5612 #if 0 /* TODO: check so vertex textures */
5613 if (Stage
>= D3DVERTEXTEXTURESAMPLER
&& Stage
<= D3DVERTEXTEXTURESAMPLER3
){
5614 This
->updateStateBlock
->vertexTextures
[Stage
- D3DVERTEXTEXTURESAMPLER
] = pTexture
;
5619 /* Reject invalid texture units */
5620 if (Stage
>= GL_LIMITS(sampler_stages
) || Stage
< 0) {
5621 WARN("Attempt to access invalid texture rejected\n");
5622 return WINED3DERR_INVALIDCALL
;
5625 if(pTexture
!= NULL
) {
5626 /* SetTexture isn't allowed on textures in WINED3DPOOL_SCRATCH;
5628 if(((IWineD3DTextureImpl
*)pTexture
)->resource
.pool
== WINED3DPOOL_SCRATCH
) {
5629 WARN("(%p) Attempt to set scratch texture rejected\n", pTexture
);
5630 return WINED3DERR_INVALIDCALL
;
5634 oldTexture
= This
->updateStateBlock
->textures
[Stage
];
5635 TRACE("GL_LIMITS %d\n",GL_LIMITS(sampler_stages
));
5636 TRACE("(%p) : oldtexture(%p)\n", This
,oldTexture
);
5638 This
->updateStateBlock
->set
.textures
[Stage
] = TRUE
;
5639 This
->updateStateBlock
->changed
.textures
[Stage
] = TRUE
;
5640 TRACE("(%p) : setting new texture to %p\n", This
, pTexture
);
5641 This
->updateStateBlock
->textures
[Stage
] = pTexture
;
5643 /* Handle recording of state blocks */
5644 if (This
->isRecordingState
) {
5645 TRACE("Recording... not performing anything\n");
5649 /** NOTE: MSDN says that setTexture increases the reference count,
5650 * and the the application nust set the texture back to null (or have a leaky application),
5651 * This means we should pass the refcount up to the parent
5652 *******************************/
5653 if (NULL
!= This
->updateStateBlock
->textures
[Stage
]) {
5654 IWineD3DBaseTexture_AddRef(This
->updateStateBlock
->textures
[Stage
]);
5657 if (NULL
!= oldTexture
) {
5658 IWineD3DBaseTexture_Release(oldTexture
);
5661 /* Reset color keying */
5662 if(Stage
== 0 && This
->stateBlock
->renderState
[WINED3DRS_COLORKEYENABLE
]) {
5663 BOOL enable_ckey
= FALSE
;
5666 IWineD3DSurfaceImpl
*surf
= (IWineD3DSurfaceImpl
*) ((IWineD3DTextureImpl
*)pTexture
)->surfaces
[0];
5667 if(surf
->CKeyFlags
& DDSD_CKSRCBLT
) enable_ckey
= TRUE
;
5671 glAlphaFunc(GL_NOTEQUAL
, 0.0);
5672 checkGLcall("glAlphaFunc");
5679 static HRESULT WINAPI
IWineD3DDeviceImpl_GetTexture(IWineD3DDevice
*iface
, DWORD Stage
, IWineD3DBaseTexture
** ppTexture
) {
5680 IWineD3DDeviceImpl
*This
= (IWineD3DDeviceImpl
*)iface
;
5681 TRACE("(%p) : (%ld /* Stage */,%p /* ppTexture */)\n", This
, Stage
, ppTexture
);
5683 /* Reject invalid texture units */
5684 if (Stage
>= GL_LIMITS(sampler_stages
)) {
5685 TRACE("Attempt to access invalid texture rejected\n");
5686 return WINED3DERR_INVALIDCALL
;
5688 *ppTexture
=This
->updateStateBlock
->textures
[Stage
];
5690 IWineD3DBaseTexture_AddRef(*ppTexture
);
5692 return WINED3DERR_INVALIDCALL
;
5699 static HRESULT WINAPI
IWineD3DDeviceImpl_GetBackBuffer(IWineD3DDevice
*iface
, UINT iSwapChain
, UINT BackBuffer
, WINED3DBACKBUFFER_TYPE Type
,
5700 IWineD3DSurface
**ppBackBuffer
) {
5701 IWineD3DDeviceImpl
*This
= (IWineD3DDeviceImpl
*)iface
;
5702 IWineD3DSwapChain
*swapChain
;
5705 TRACE("(%p) : BackBuf %d Type %d SwapChain %d returning %p\n", This
, BackBuffer
, Type
, iSwapChain
, *ppBackBuffer
);
5707 hr
= IWineD3DDeviceImpl_GetSwapChain(iface
, iSwapChain
, &swapChain
);
5708 if (hr
== WINED3D_OK
) {
5709 hr
= IWineD3DSwapChain_GetBackBuffer(swapChain
, BackBuffer
, Type
, ppBackBuffer
);
5710 IWineD3DSwapChain_Release(swapChain
);
5712 *ppBackBuffer
= NULL
;
5717 static HRESULT WINAPI
IWineD3DDeviceImpl_GetDeviceCaps(IWineD3DDevice
*iface
, WINED3DCAPS
* pCaps
) {
5718 IWineD3DDeviceImpl
*This
= (IWineD3DDeviceImpl
*)iface
;
5719 WARN("(%p) : stub, calling idirect3d for now\n", This
);
5720 return IWineD3D_GetDeviceCaps(This
->wineD3D
, This
->adapterNo
, This
->devType
, pCaps
);
5723 static HRESULT WINAPI
IWineD3DDeviceImpl_GetDisplayMode(IWineD3DDevice
*iface
, UINT iSwapChain
, WINED3DDISPLAYMODE
* pMode
) {
5724 IWineD3DDeviceImpl
*This
= (IWineD3DDeviceImpl
*)iface
;
5725 IWineD3DSwapChain
*swapChain
;
5728 if(iSwapChain
> 0) {
5729 hr
= IWineD3DDeviceImpl_GetSwapChain(iface
, iSwapChain
, (IWineD3DSwapChain
**)&swapChain
);
5730 if (hr
== WINED3D_OK
) {
5731 hr
= IWineD3DSwapChain_GetDisplayMode(swapChain
, pMode
);
5732 IWineD3DSwapChain_Release(swapChain
);
5734 FIXME("(%p) Error getting display mode\n", This
);
5737 /* Don't read the real display mode,
5738 but return the stored mode instead. X11 can't change the color
5739 depth, and some apps are pretty angry if they SetDisplayMode from
5740 24 to 16 bpp and find out that GetDisplayMode still returns 24 bpp
5742 Also don't relay to the swapchain because with ddraw it's possible
5743 that there isn't a swapchain at all */
5744 pMode
->Width
= This
->ddraw_width
;
5745 pMode
->Height
= This
->ddraw_height
;
5746 pMode
->Format
= This
->ddraw_format
;
5747 pMode
->RefreshRate
= 0;
5754 static HRESULT WINAPI
IWineD3DDeviceImpl_SetHWND(IWineD3DDevice
*iface
, HWND hWnd
) {
5755 IWineD3DDeviceImpl
*This
= (IWineD3DDeviceImpl
*)iface
;
5756 TRACE("(%p)->(%p)\n", This
, hWnd
);
5758 This
->ddraw_window
= hWnd
;
5762 static HRESULT WINAPI
IWineD3DDeviceImpl_GetHWND(IWineD3DDevice
*iface
, HWND
*hWnd
) {
5763 IWineD3DDeviceImpl
*This
= (IWineD3DDeviceImpl
*)iface
;
5764 TRACE("(%p)->(%p)\n", This
, hWnd
);
5766 *hWnd
= This
->ddraw_window
;
5771 * Stateblock related functions
5774 static HRESULT WINAPI
IWineD3DDeviceImpl_BeginStateBlock(IWineD3DDevice
*iface
) {
5775 IWineD3DDeviceImpl
*This
= (IWineD3DDeviceImpl
*)iface
;
5776 IWineD3DStateBlockImpl
*object
;
5777 HRESULT temp_result
;
5779 TRACE("(%p)", This
);
5781 if (This
->isRecordingState
) {
5782 return WINED3DERR_INVALIDCALL
;
5785 object
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, sizeof(IWineD3DStateBlockImpl
));
5786 if (NULL
== object
) {
5787 FIXME("(%p)Error allocating memory for stateblock\n", This
);
5788 return E_OUTOFMEMORY
;
5790 TRACE("(%p) created object %p\n", This
, object
);
5791 object
->wineD3DDevice
= This
;
5792 /** FIXME: object->parent = parent; **/
5793 object
->parent
= NULL
;
5794 object
->blockType
= WINED3DSBT_ALL
;
5796 object
->lpVtbl
= &IWineD3DStateBlock_Vtbl
;
5798 temp_result
= allocate_shader_constants(object
);
5799 if (WINED3D_OK
!= temp_result
)
5802 IWineD3DStateBlock_Release((IWineD3DStateBlock
*)This
->updateStateBlock
);
5803 This
->updateStateBlock
= object
;
5804 This
->isRecordingState
= TRUE
;
5806 TRACE("(%p) recording stateblock %p\n",This
, object
);
5810 static HRESULT WINAPI
IWineD3DDeviceImpl_EndStateBlock(IWineD3DDevice
*iface
, IWineD3DStateBlock
** ppStateBlock
) {
5811 IWineD3DDeviceImpl
*This
= (IWineD3DDeviceImpl
*)iface
;
5813 if (!This
->isRecordingState
) {
5814 FIXME("(%p) not recording! returning error\n", This
);
5815 *ppStateBlock
= NULL
;
5816 return WINED3DERR_INVALIDCALL
;
5819 *ppStateBlock
= (IWineD3DStateBlock
*)This
->updateStateBlock
;
5820 This
->isRecordingState
= FALSE
;
5821 This
->updateStateBlock
= This
->stateBlock
;
5822 IWineD3DStateBlock_AddRef((IWineD3DStateBlock
*)This
->updateStateBlock
);
5823 /* IWineD3DStateBlock_AddRef(*ppStateBlock); don't need to do this, since we should really just release UpdateStateBlock first */
5824 TRACE("(%p) returning token (ptr to stateblock) of %p\n", This
, *ppStateBlock
);
5829 * Scene related functions
5831 static HRESULT WINAPI
IWineD3DDeviceImpl_BeginScene(IWineD3DDevice
*iface
) {
5832 /* At the moment we have no need for any functionality at the beginning
5834 IWineD3DDeviceImpl
*This
= (IWineD3DDeviceImpl
*)iface
;
5835 TRACE("(%p) : stub\n", This
);
5839 static HRESULT WINAPI
IWineD3DDeviceImpl_EndScene(IWineD3DDevice
*iface
) {
5840 IWineD3DDeviceImpl
*This
= (IWineD3DDeviceImpl
*)iface
;
5841 TRACE("(%p)\n", This
);
5843 /* We only have to do this if we need to read the, swapbuffers performs a flush for us */
5845 checkGLcall("glFlush");
5847 TRACE("End Scene\n");
5848 if(This
->renderTarget
!= NULL
) {
5850 /* If the container of the rendertarget is a texture then we need to save the data from the pbuffer */
5851 IUnknown
*targetContainer
= NULL
;
5852 if (WINED3D_OK
== IWineD3DSurface_GetContainer(This
->renderTarget
, &IID_IWineD3DBaseTexture
, (void **)&targetContainer
)
5853 || WINED3D_OK
== IWineD3DSurface_GetContainer(This
->renderTarget
, &IID_IWineD3DDevice
, (void **)&targetContainer
)) {
5854 TRACE("(%p) : Texture rendertarget %p\n", This
,This
->renderTarget
);
5855 /** always dirtify for now. we must find a better way to see that surface have been modified
5856 (Modifications should will only occur via draw-primitive, but we do need better locking
5857 switching to render-to-texture should remove the overhead though.
5859 IWineD3DSurface_SetPBufferState(This
->renderTarget
, TRUE
/* inPBuffer */, FALSE
/* inTexture */);
5860 IWineD3DSurface_AddDirtyRect(This
->renderTarget
, NULL
);
5861 IWineD3DSurface_PreLoad(This
->renderTarget
);
5862 IWineD3DSurface_SetPBufferState(This
->renderTarget
, FALSE
/* inPBuffer */, FALSE
/* inTexture */);
5863 IUnknown_Release(targetContainer
);
5866 This
->sceneEnded
= TRUE
;
5871 static HRESULT WINAPI
IWineD3DDeviceImpl_Present(IWineD3DDevice
*iface
,
5872 CONST RECT
* pSourceRect
, CONST RECT
* pDestRect
,
5873 HWND hDestWindowOverride
, CONST RGNDATA
* pDirtyRegion
) {
5874 IWineD3DDeviceImpl
*This
= (IWineD3DDeviceImpl
*)iface
;
5875 IWineD3DSwapChain
*swapChain
= NULL
;
5877 int swapchains
= IWineD3DDeviceImpl_GetNumberOfSwapChains(iface
);
5879 TRACE("(%p) Presenting the frame\n", This
);
5881 for(i
= 0 ; i
< swapchains
; i
++) {
5883 IWineD3DDeviceImpl_GetSwapChain(iface
, i
, (IWineD3DSwapChain
**)&swapChain
);
5884 TRACE("presentinng chain %d, %p\n", i
, swapChain
);
5885 IWineD3DSwapChain_Present(swapChain
, pSourceRect
, pDestRect
, hDestWindowOverride
, pDirtyRegion
, 0);
5886 IWineD3DSwapChain_Release(swapChain
);
5892 static HRESULT WINAPI
IWineD3DDeviceImpl_Clear(IWineD3DDevice
*iface
, DWORD Count
, CONST D3DRECT
* pRects
,
5893 DWORD Flags
, D3DCOLOR Color
, float Z
, DWORD Stencil
) {
5894 IWineD3DDeviceImpl
*This
= (IWineD3DDeviceImpl
*)iface
;
5896 /* TODO: From MSDN This method fails if you specify the D3DCLEAR_ZBUFFER or D3DCLEAR_STENCIL flags when the
5897 render target does not have an attached depth buffer. Similarly, if you specify the D3DCLEAR_STENCIL flag
5898 when the depth-buffer format does not contain stencil buffer information, this method fails. */
5899 GLbitfield glMask
= 0;
5900 GLboolean old_ztest
;
5901 GLfloat old_z_clear_value
;
5902 GLint old_stencil_clear_value
;
5903 GLfloat old_color_clear_value
[4];
5905 CONST D3DRECT
* curRect
;
5907 TRACE("(%p) Count (%ld), pRects (%p), Flags (%lx), Z (%f), Stencil (%ld)\n", This
,
5908 Count
, pRects
, Flags
, Z
, Stencil
);
5912 glEnable(GL_SCISSOR_TEST
);
5913 checkGLcall("glEnable GL_SCISSOR_TEST");
5915 if (Count
> 0 && pRects
) {
5921 /* Only set the values up once, as they are not changing */
5922 if (Flags
& D3DCLEAR_STENCIL
) {
5923 glGetIntegerv(GL_STENCIL_CLEAR_VALUE
, &old_stencil_clear_value
);
5924 glClearStencil(Stencil
);
5925 checkGLcall("glClearStencil");
5926 glMask
= glMask
| GL_STENCIL_BUFFER_BIT
;
5927 glStencilMask(0xFFFFFFFF);
5930 if (Flags
& D3DCLEAR_ZBUFFER
) {
5931 glGetBooleanv(GL_DEPTH_WRITEMASK
, &old_ztest
);
5932 glDepthMask(GL_TRUE
);
5933 glGetFloatv(GL_DEPTH_CLEAR_VALUE
, &old_z_clear_value
);
5935 checkGLcall("glClearDepth");
5936 glMask
= glMask
| GL_DEPTH_BUFFER_BIT
;
5939 if (Flags
& D3DCLEAR_TARGET
) {
5940 TRACE("Clearing screen with glClear to color %lx\n", Color
);
5941 glGetFloatv(GL_COLOR_CLEAR_VALUE
, old_color_clear_value
);
5942 glClearColor(D3DCOLOR_R(Color
),
5946 checkGLcall("glClearColor");
5948 /* Clear ALL colors! */
5949 glColorMask(GL_TRUE
, GL_TRUE
, GL_TRUE
, GL_TRUE
);
5950 glMask
= glMask
| GL_COLOR_BUFFER_BIT
;
5953 /* Now process each rect in turn */
5954 for (i
= 0; i
< Count
|| i
== 0; i
++) {
5957 /* Note gl uses lower left, width/height */
5958 TRACE("(%p) %p Rect=(%ld,%ld)->(%ld,%ld) glRect=(%ld,%ld), len=%ld, hei=%ld\n", This
, curRect
,
5959 curRect
->x1
, curRect
->y1
, curRect
->x2
, curRect
->y2
,
5960 curRect
->x1
, (((IWineD3DSurfaceImpl
*)This
->renderTarget
)->currentDesc
.Height
- curRect
->y2
),
5961 curRect
->x2
- curRect
->x1
, curRect
->y2
- curRect
->y1
);
5962 glScissor(curRect
->x1
, (((IWineD3DSurfaceImpl
*)This
->renderTarget
)->currentDesc
.Height
- curRect
->y2
),
5963 curRect
->x2
- curRect
->x1
, curRect
->y2
- curRect
->y1
);
5964 checkGLcall("glScissor");
5966 glScissor(This
->stateBlock
->viewport
.X
,
5967 (((IWineD3DSurfaceImpl
*)This
->renderTarget
)->currentDesc
.Height
-
5968 (This
->stateBlock
->viewport
.Y
+ This
->stateBlock
->viewport
.Height
)),
5969 This
->stateBlock
->viewport
.Width
,
5970 This
->stateBlock
->viewport
.Height
);
5971 checkGLcall("glScissor");
5974 /* Clear the selected rectangle (or full screen) */
5976 checkGLcall("glClear");
5978 /* Step to the next rectangle */
5979 if (curRect
) curRect
= curRect
+ sizeof(D3DRECT
);
5982 /* Restore the old values (why..?) */
5983 if (Flags
& D3DCLEAR_STENCIL
) {
5984 glClearStencil(old_stencil_clear_value
);
5985 glStencilMask(This
->stateBlock
->renderState
[WINED3DRS_STENCILWRITEMASK
]);
5987 if (Flags
& D3DCLEAR_ZBUFFER
) {
5988 glDepthMask(old_ztest
);
5989 glClearDepth(old_z_clear_value
);
5991 if (Flags
& D3DCLEAR_TARGET
) {
5992 glClearColor(old_color_clear_value
[0],
5993 old_color_clear_value
[1],
5994 old_color_clear_value
[2],
5995 old_color_clear_value
[3]);
5996 glColorMask(This
->stateBlock
->renderState
[WINED3DRS_COLORWRITEENABLE
] & D3DCOLORWRITEENABLE_RED
? GL_TRUE
: GL_FALSE
,
5997 This
->stateBlock
->renderState
[WINED3DRS_COLORWRITEENABLE
] & D3DCOLORWRITEENABLE_GREEN
? GL_TRUE
: GL_FALSE
,
5998 This
->stateBlock
->renderState
[WINED3DRS_COLORWRITEENABLE
] & D3DCOLORWRITEENABLE_BLUE
? GL_TRUE
: GL_FALSE
,
5999 This
->stateBlock
->renderState
[WINED3DRS_COLORWRITEENABLE
] & D3DCOLORWRITEENABLE_ALPHA
? GL_TRUE
: GL_FALSE
);
6002 glDisable(GL_SCISSOR_TEST
);
6003 checkGLcall("glDisable");
6012 static HRESULT WINAPI
IWineD3DDeviceImpl_DrawPrimitive(IWineD3DDevice
*iface
, D3DPRIMITIVETYPE PrimitiveType
, UINT StartVertex
,
6013 UINT PrimitiveCount
) {
6015 IWineD3DDeviceImpl
*This
= (IWineD3DDeviceImpl
*)iface
;
6016 This
->stateBlock
->streamIsUP
= FALSE
;
6018 TRACE("(%p) : Type=(%d,%s), Start=%d, Count=%d\n", This
, PrimitiveType
,
6019 debug_d3dprimitivetype(PrimitiveType
),
6020 StartVertex
, PrimitiveCount
);
6021 drawPrimitive(iface
, PrimitiveType
, PrimitiveCount
, StartVertex
, 0/* NumVertices */, -1 /* indxStart */,
6022 0 /* indxSize */, NULL
/* indxData */, 0 /* minIndex */, NULL
);
6028 /* TODO: baseVIndex needs to be provided from This->stateBlock->baseVertexIndex when called from d3d8 */
6029 static HRESULT WINAPI
IWineD3DDeviceImpl_DrawIndexedPrimitive(IWineD3DDevice
*iface
,
6030 D3DPRIMITIVETYPE PrimitiveType
,
6031 INT baseVIndex
, UINT minIndex
,
6032 UINT NumVertices
, UINT startIndex
, UINT primCount
) {
6034 IWineD3DDeviceImpl
*This
= (IWineD3DDeviceImpl
*)iface
;
6036 IWineD3DIndexBuffer
*pIB
;
6037 WINED3DINDEXBUFFER_DESC IdxBufDsc
;
6039 pIB
= This
->stateBlock
->pIndexData
;
6040 This
->stateBlock
->streamIsUP
= FALSE
;
6042 TRACE("(%p) : Type=(%d,%s), min=%d, CountV=%d, startIdx=%d, baseVidx=%d, countP=%d\n", This
,
6043 PrimitiveType
, debug_d3dprimitivetype(PrimitiveType
),
6044 minIndex
, NumVertices
, startIndex
, baseVIndex
, primCount
);
6046 IWineD3DIndexBuffer_GetDesc(pIB
, &IdxBufDsc
);
6047 if (IdxBufDsc
.Format
== WINED3DFMT_INDEX16
) {
6053 drawPrimitive(iface
, PrimitiveType
, primCount
, baseVIndex
, NumVertices
, startIndex
,
6054 idxStride
, ((IWineD3DIndexBufferImpl
*) pIB
)->resource
.allocatedMemory
, minIndex
, NULL
);
6059 static HRESULT WINAPI
IWineD3DDeviceImpl_DrawPrimitiveUP(IWineD3DDevice
*iface
, D3DPRIMITIVETYPE PrimitiveType
,
6060 UINT PrimitiveCount
, CONST
void* pVertexStreamZeroData
,
6061 UINT VertexStreamZeroStride
) {
6062 IWineD3DDeviceImpl
*This
= (IWineD3DDeviceImpl
*)iface
;
6064 TRACE("(%p) : Type=(%d,%s), pCount=%d, pVtxData=%p, Stride=%d\n", This
, PrimitiveType
,
6065 debug_d3dprimitivetype(PrimitiveType
),
6066 PrimitiveCount
, pVertexStreamZeroData
, VertexStreamZeroStride
);
6068 /* release the stream source */
6069 if (This
->stateBlock
->streamSource
[0] != NULL
) {
6070 IWineD3DVertexBuffer_Release(This
->stateBlock
->streamSource
[0]);
6073 /* Note in the following, it's not this type, but that's the purpose of streamIsUP */
6074 This
->stateBlock
->streamSource
[0] = (IWineD3DVertexBuffer
*)pVertexStreamZeroData
;
6075 This
->stateBlock
->streamStride
[0] = VertexStreamZeroStride
;
6076 This
->stateBlock
->streamIsUP
= TRUE
;
6078 drawPrimitive(iface
, PrimitiveType
, PrimitiveCount
, 0 /* start vertex */, 0 /* NumVertices */,
6079 0 /* indxStart*/, 0 /* indxSize*/, NULL
/* indxData */, 0 /* indxMin */, NULL
);
6081 /* MSDN specifies stream zero settings must be set to NULL */
6082 This
->stateBlock
->streamStride
[0] = 0;
6083 This
->stateBlock
->streamSource
[0] = NULL
;
6085 /*stream zero settings set to null at end, as per the msdn */
6089 static HRESULT WINAPI
IWineD3DDeviceImpl_DrawIndexedPrimitiveUP(IWineD3DDevice
*iface
, D3DPRIMITIVETYPE PrimitiveType
,
6090 UINT MinVertexIndex
, UINT NumVertices
,
6091 UINT PrimitiveCount
, CONST
void* pIndexData
,
6092 WINED3DFORMAT IndexDataFormat
,CONST
void* pVertexStreamZeroData
,
6093 UINT VertexStreamZeroStride
) {
6095 IWineD3DDeviceImpl
*This
= (IWineD3DDeviceImpl
*)iface
;
6097 TRACE("(%p) : Type=(%d,%s), MinVtxIdx=%d, NumVIdx=%d, PCount=%d, pidxdata=%p, IdxFmt=%d, pVtxdata=%p, stride=%d\n",
6098 This
, PrimitiveType
, debug_d3dprimitivetype(PrimitiveType
),
6099 MinVertexIndex
, NumVertices
, PrimitiveCount
, pIndexData
,
6100 IndexDataFormat
, pVertexStreamZeroData
, VertexStreamZeroStride
);
6102 if (IndexDataFormat
== WINED3DFMT_INDEX16
) {
6108 /* release the stream and index data */
6109 if (This
->stateBlock
->streamSource
[0] != NULL
) {
6110 IWineD3DVertexBuffer_Release(This
->stateBlock
->streamSource
[0]);
6112 if (This
->stateBlock
->pIndexData
) {
6113 IWineD3DIndexBuffer_Release(This
->stateBlock
->pIndexData
);
6116 /* Note in the following, it's not this type, but that's the purpose of streamIsUP */
6117 This
->stateBlock
->streamSource
[0] = (IWineD3DVertexBuffer
*)pVertexStreamZeroData
;
6118 This
->stateBlock
->streamIsUP
= TRUE
;
6119 This
->stateBlock
->streamStride
[0] = VertexStreamZeroStride
;
6121 drawPrimitive(iface
, PrimitiveType
, PrimitiveCount
, 0 /* vertexStart */, NumVertices
, 0 /* indxStart */, idxStride
, pIndexData
, MinVertexIndex
, NULL
);
6123 /* MSDN specifies stream zero settings and index buffer must be set to NULL */
6124 This
->stateBlock
->streamSource
[0] = NULL
;
6125 This
->stateBlock
->streamStride
[0] = 0;
6126 This
->stateBlock
->pIndexData
= NULL
;
6131 static HRESULT WINAPI
IWineD3DDeviceImpl_DrawPrimitiveStrided (IWineD3DDevice
*iface
, D3DPRIMITIVETYPE PrimitiveType
, UINT PrimitiveCount
, WineDirect3DVertexStridedData
*DrawPrimStrideData
) {
6133 drawPrimitive(iface
, PrimitiveType
, PrimitiveCount
, 0, 0, 0, 0, NULL
, 0, DrawPrimStrideData
);
6136 /* Yet another way to update a texture, some apps use this to load default textures instead of using surface/texture lock/unlock */
6137 static HRESULT WINAPI
IWineD3DDeviceImpl_UpdateTexture (IWineD3DDevice
*iface
, IWineD3DBaseTexture
*pSourceTexture
, IWineD3DBaseTexture
*pDestinationTexture
){
6138 IWineD3DDeviceImpl
*This
= (IWineD3DDeviceImpl
*)iface
;
6139 HRESULT hr
= WINED3D_OK
;
6140 WINED3DRESOURCETYPE sourceType
;
6141 WINED3DRESOURCETYPE destinationType
;
6144 /* TODO: think about moving the code into IWineD3DBaseTexture */
6146 TRACE("(%p) Source %p Destination %p\n", This
, pSourceTexture
, pDestinationTexture
);
6148 /* verify that the source and destination textures aren't NULL */
6149 if (NULL
== pSourceTexture
|| NULL
== pDestinationTexture
) {
6150 WARN("(%p) : source (%p) and destination (%p) textures must not be NULL, returning WINED3DERR_INVALIDCALL\n",
6151 This
, pSourceTexture
, pDestinationTexture
);
6152 hr
= WINED3DERR_INVALIDCALL
;
6155 if (pSourceTexture
== pDestinationTexture
) {
6156 WARN("(%p) : source (%p) and destination (%p) textures must be different, returning WINED3DERR_INVALIDCALL\n",
6157 This
, pSourceTexture
, pDestinationTexture
);
6158 hr
= WINED3DERR_INVALIDCALL
;
6160 /* Verify that the source and destination textures are the same type */
6161 sourceType
= IWineD3DBaseTexture_GetType(pSourceTexture
);
6162 destinationType
= IWineD3DBaseTexture_GetType(pDestinationTexture
);
6164 if (sourceType
!= destinationType
) {
6165 WARN("(%p) Sorce and destination types must match, returning WINED3DERR_INVALIDCALL\n",
6167 hr
= WINED3DERR_INVALIDCALL
;
6170 /* check that both textures have the identical numbers of levels */
6171 if (IWineD3DBaseTexture_GetLevelCount(pDestinationTexture
) != IWineD3DBaseTexture_GetLevelCount(pSourceTexture
)) {
6172 WARN("(%p) : source (%p) and destination (%p) textures must have identicle numbers of levels, returning WINED3DERR_INVALIDCALL\n", This
, pSourceTexture
, pDestinationTexture
);
6173 hr
= WINED3DERR_INVALIDCALL
;
6176 if (WINED3D_OK
== hr
) {
6178 /* Make sure that the destination texture is loaded */
6179 IWineD3DBaseTexture_PreLoad(pDestinationTexture
);
6181 /* Update every surface level of the texture */
6182 levels
= IWineD3DBaseTexture_GetLevelCount(pDestinationTexture
);
6184 switch (sourceType
) {
6185 case WINED3DRTYPE_TEXTURE
:
6187 IWineD3DSurface
*srcSurface
;
6188 IWineD3DSurface
*destSurface
;
6190 for (i
= 0 ; i
< levels
; ++i
) {
6191 IWineD3DTexture_GetSurfaceLevel((IWineD3DTexture
*)pSourceTexture
, i
, &srcSurface
);
6192 IWineD3DTexture_GetSurfaceLevel((IWineD3DTexture
*)pDestinationTexture
, i
, &destSurface
);
6193 hr
= IWineD3DDevice_UpdateSurface(iface
, srcSurface
, NULL
, destSurface
, NULL
);
6194 IWineD3DSurface_Release(srcSurface
);
6195 IWineD3DSurface_Release(destSurface
);
6196 if (WINED3D_OK
!= hr
) {
6197 WARN("(%p) : Call to update surface failed\n", This
);
6203 case WINED3DRTYPE_CUBETEXTURE
:
6205 IWineD3DSurface
*srcSurface
;
6206 IWineD3DSurface
*destSurface
;
6207 WINED3DCUBEMAP_FACES faceType
;
6209 for (i
= 0 ; i
< levels
; ++i
) {
6210 /* Update each cube face */
6211 for (faceType
= D3DCUBEMAP_FACE_POSITIVE_X
; faceType
<= D3DCUBEMAP_FACE_NEGATIVE_Z
; ++faceType
){
6212 hr
= IWineD3DCubeTexture_GetCubeMapSurface((IWineD3DCubeTexture
*)pSourceTexture
, faceType
, i
, &srcSurface
);
6213 if (WINED3D_OK
!= hr
) {
6214 FIXME("(%p) : Failed to get src cube surface facetype %d, level %d\n", This
, faceType
, i
);
6216 TRACE("Got srcSurface %p\n", srcSurface
);
6218 hr
= IWineD3DCubeTexture_GetCubeMapSurface((IWineD3DCubeTexture
*)pDestinationTexture
, faceType
, i
, &destSurface
);
6219 if (WINED3D_OK
!= hr
) {
6220 FIXME("(%p) : Failed to get src cube surface facetype %d, level %d\n", This
, faceType
, i
);
6222 TRACE("Got desrSurface %p\n", destSurface
);
6224 hr
= IWineD3DDevice_UpdateSurface(iface
, srcSurface
, NULL
, destSurface
, NULL
);
6225 IWineD3DSurface_Release(srcSurface
);
6226 IWineD3DSurface_Release(destSurface
);
6227 if (WINED3D_OK
!= hr
) {
6228 WARN("(%p) : Call to update surface failed\n", This
);
6235 #if 0 /* TODO: Add support for volume textures */
6236 case WINED3DRTYPE_VOLUMETEXTURE
:
6238 IWineD3DVolume srcVolume
= NULL
;
6239 IWineD3DSurface destVolume
= NULL
;
6241 for (i
= 0 ; i
< levels
; ++i
) {
6242 IWineD3DVolumeTexture_GetVolume((IWineD3DVolumeTexture
*)pSourceTexture
, i
, &srcVolume
);
6243 IWineD3DVolumeTexture_GetVolume((IWineD3DVolumeTexture
*)pDestinationTexture
, i
, &destVolume
);
6244 hr
= IWineD3DFoo_UpdateVolume(iface
, srcVolume
, NULL
, destVolume
, NULL
);
6245 IWineD3DVolume_Release(srcSurface
);
6246 IWineD3DVolume_Release(destSurface
);
6247 if (WINED3D_OK
!= hr
) {
6248 WARN("(%p) : Call to update volume failed\n", This
);
6256 FIXME("(%p) : Unsupported source and destination type\n", This
);
6257 hr
= WINED3DERR_INVALIDCALL
;
6264 static HRESULT WINAPI
IWineD3DDeviceImpl_StretchRect(IWineD3DDevice
*iface
, IWineD3DSurface
*pSourceSurface
,
6265 CONST RECT
* pSourceRect
, IWineD3DSurface
*pDestinationSurface
,
6266 CONST RECT
* pDestRect
, WINED3DTEXTUREFILTERTYPE Filter
) {
6267 IWineD3DDeviceImpl
*This
= (IWineD3DDeviceImpl
*)iface
;
6269 TRACE("(%p) : stub\n", This
);
6272 static HRESULT WINAPI
IWineD3DDeviceImpl_GetRenderTargetData(IWineD3DDevice
*iface
, IWineD3DSurface
*pRenderTarget
, IWineD3DSurface
*pSurface
) {
6273 IWineD3DDeviceImpl
*This
= (IWineD3DDeviceImpl
*)iface
;
6274 /** TODO: remove remove casts to IWineD3DSurfaceImpl *
6275 * NOTE It may be best to move the code into surface to occomplish this
6276 ****************************************/
6278 WINED3DSURFACE_DESC surfaceDesc
;
6279 unsigned int surfaceWidth
, surfaceHeight
;
6280 glDescriptor
*targetGlDescription
= NULL
;
6281 glDescriptor
*surfaceGlDescription
= NULL
;
6282 IWineD3DSwapChainImpl
*container
= NULL
;
6284 IWineD3DSurface_GetGlDesc(pRenderTarget
, &targetGlDescription
);
6285 IWineD3DSurface_GetGlDesc(pSurface
, &surfaceGlDescription
);
6286 memset(&surfaceDesc
, 0, sizeof(surfaceDesc
));
6288 surfaceDesc
.Width
= &surfaceWidth
;
6289 surfaceDesc
.Height
= &surfaceHeight
;
6290 IWineD3DSurface_GetDesc(pSurface
, &surfaceDesc
);
6291 /* check to see if it's the backbuffer or the frontbuffer being requested (to make sure the data is up to date)*/
6293 /* Ok, I may need to setup some kind of active swapchain reference on the device */
6294 IWineD3DSurface_GetContainer(pRenderTarget
, &IID_IWineD3DSwapChain
, (void **)&container
);
6296 /* TODO: opengl Context switching for swapchains etc... */
6297 if (NULL
!= container
|| pRenderTarget
== This
->renderTarget
|| pRenderTarget
== This
->depthStencilBuffer
) {
6298 if (NULL
!= container
&& (pRenderTarget
== container
->backBuffer
[0])) {
6299 glReadBuffer(GL_BACK
);
6300 vcheckGLcall("glReadBuffer(GL_BACK)");
6301 } else if ((NULL
!= container
&& (pRenderTarget
== container
->frontBuffer
)) || (pRenderTarget
== This
->renderTarget
)) {
6302 glReadBuffer(GL_FRONT
);
6303 vcheckGLcall("glReadBuffer(GL_FRONT)");
6304 } else if (pRenderTarget
== This
->depthStencilBuffer
) {
6305 FIXME("Reading of depthstencil not yet supported\n");
6308 glReadPixels(surfaceGlDescription
->target
,
6309 surfaceGlDescription
->level
,
6312 surfaceGlDescription
->glFormat
,
6313 surfaceGlDescription
->glType
,
6314 (void *)IWineD3DSurface_GetData(pSurface
));
6315 vcheckGLcall("glReadPixels(...)");
6316 if(NULL
!= container
){
6317 IWineD3DSwapChain_Release((IWineD3DSwapChain
*) container
);
6320 IWineD3DBaseTexture
*container
;
6321 GLenum textureDimensions
= GL_TEXTURE_2D
;
6323 if (WINED3D_OK
== IWineD3DSurface_GetContainer(pSurface
, &IID_IWineD3DBaseTexture
, (void **)&container
)) {
6324 textureDimensions
= IWineD3DBaseTexture_GetTextureDimensions(container
);
6325 IWineD3DBaseTexture_Release(container
);
6327 /* TODO: 2D -> Cube surface coppies etc.. */
6328 if (surfaceGlDescription
->target
!= textureDimensions
) {
6329 FIXME("(%p) : Texture dimension mismatch\n", This
);
6331 glEnable(textureDimensions
);
6332 vcheckGLcall("glEnable(GL_TEXTURE_...)");
6333 /* FIXME: this isn't correct, it need to add a dirty rect if nothing else... */
6334 glBindTexture(targetGlDescription
->target
, targetGlDescription
->textureName
);
6335 vcheckGLcall("glBindTexture");
6336 glGetTexImage(surfaceGlDescription
->target
,
6337 surfaceGlDescription
->level
,
6338 surfaceGlDescription
->glFormat
,
6339 surfaceGlDescription
->glType
,
6340 (void *)IWineD3DSurface_GetData(pSurface
));
6341 glDisable(textureDimensions
);
6342 vcheckGLcall("glDisable(GL_TEXTURE_...)");
6349 static HRESULT WINAPI
IWineD3DDeviceImpl_GetFrontBufferData(IWineD3DDevice
*iface
,UINT iSwapChain
, IWineD3DSurface
*pDestSurface
) {
6350 IWineD3DSwapChain
*swapChain
;
6352 hr
= IWineD3DDeviceImpl_GetSwapChain(iface
, iSwapChain
, (IWineD3DSwapChain
**)&swapChain
);
6353 if(hr
== WINED3D_OK
) {
6354 hr
= IWineD3DSwapChain_GetFrontBufferData(swapChain
, pDestSurface
);
6355 IWineD3DSwapChain_Release(swapChain
);
6360 static HRESULT WINAPI
IWineD3DDeviceImpl_ValidateDevice(IWineD3DDevice
*iface
, DWORD
* pNumPasses
) {
6361 IWineD3DDeviceImpl
*This
= (IWineD3DDeviceImpl
*)iface
;
6362 /* return a sensible default */
6364 /* TODO: If the window is minimized then validate device should return something other than WINED3D_OK */
6365 FIXME("(%p) : stub\n", This
);
6369 static HRESULT WINAPI
IWineD3DDeviceImpl_SetPaletteEntries(IWineD3DDevice
*iface
, UINT PaletteNumber
, CONST PALETTEENTRY
* pEntries
) {
6370 IWineD3DDeviceImpl
*This
= (IWineD3DDeviceImpl
*)iface
;
6372 TRACE("(%p) : PaletteNumber %u\n", This
, PaletteNumber
);
6373 if ( PaletteNumber
< 0 || PaletteNumber
>= MAX_PALETTES
) {
6374 WARN("(%p) : (%u) Out of range 0-%u, returning Invalid Call\n", This
, PaletteNumber
, MAX_PALETTES
);
6375 return WINED3DERR_INVALIDCALL
;
6377 for (j
= 0; j
< 256; ++j
) {
6378 This
->palettes
[PaletteNumber
][j
].peRed
= pEntries
[j
].peRed
;
6379 This
->palettes
[PaletteNumber
][j
].peGreen
= pEntries
[j
].peGreen
;
6380 This
->palettes
[PaletteNumber
][j
].peBlue
= pEntries
[j
].peBlue
;
6381 This
->palettes
[PaletteNumber
][j
].peFlags
= pEntries
[j
].peFlags
;
6383 TRACE("(%p) : returning\n", This
);
6387 static HRESULT WINAPI
IWineD3DDeviceImpl_GetPaletteEntries(IWineD3DDevice
*iface
, UINT PaletteNumber
, PALETTEENTRY
* pEntries
) {
6388 IWineD3DDeviceImpl
*This
= (IWineD3DDeviceImpl
*)iface
;
6390 TRACE("(%p) : PaletteNumber %u\n", This
, PaletteNumber
);
6391 if ( PaletteNumber
< 0 || PaletteNumber
>= MAX_PALETTES
) {
6392 WARN("(%p) : (%u) Out of range 0-%u, returning Invalid Call\n", This
, PaletteNumber
, MAX_PALETTES
);
6393 return WINED3DERR_INVALIDCALL
;
6395 for (j
= 0; j
< 256; ++j
) {
6396 pEntries
[j
].peRed
= This
->palettes
[PaletteNumber
][j
].peRed
;
6397 pEntries
[j
].peGreen
= This
->palettes
[PaletteNumber
][j
].peGreen
;
6398 pEntries
[j
].peBlue
= This
->palettes
[PaletteNumber
][j
].peBlue
;
6399 pEntries
[j
].peFlags
= This
->palettes
[PaletteNumber
][j
].peFlags
;
6401 TRACE("(%p) : returning\n", This
);
6405 static HRESULT WINAPI
IWineD3DDeviceImpl_SetCurrentTexturePalette(IWineD3DDevice
*iface
, UINT PaletteNumber
) {
6406 IWineD3DDeviceImpl
*This
= (IWineD3DDeviceImpl
*)iface
;
6407 TRACE("(%p) : PaletteNumber %u\n", This
, PaletteNumber
);
6408 if ( PaletteNumber
< 0 || PaletteNumber
>= MAX_PALETTES
) {
6409 WARN("(%p) : (%u) Out of range 0-%u, returning Invalid Call\n", This
, PaletteNumber
, MAX_PALETTES
);
6410 return WINED3DERR_INVALIDCALL
;
6412 /*TODO: stateblocks */
6413 This
->currentPalette
= PaletteNumber
;
6414 TRACE("(%p) : returning\n", This
);
6418 static HRESULT WINAPI
IWineD3DDeviceImpl_GetCurrentTexturePalette(IWineD3DDevice
*iface
, UINT
* PaletteNumber
) {
6419 IWineD3DDeviceImpl
*This
= (IWineD3DDeviceImpl
*)iface
;
6420 if (PaletteNumber
== NULL
) {
6421 WARN("(%p) : returning Invalid Call\n", This
);
6422 return WINED3DERR_INVALIDCALL
;
6424 /*TODO: stateblocks */
6425 *PaletteNumber
= This
->currentPalette
;
6426 TRACE("(%p) : returning %u\n", This
, *PaletteNumber
);
6430 static HRESULT WINAPI
IWineD3DDeviceImpl_SetSoftwareVertexProcessing(IWineD3DDevice
*iface
, BOOL bSoftware
) {
6431 IWineD3DDeviceImpl
*This
= (IWineD3DDeviceImpl
*)iface
;
6432 static BOOL showFixmes
= TRUE
;
6434 FIXME("(%p) : stub\n", This
);
6438 This
->softwareVertexProcessing
= bSoftware
;
6443 static BOOL WINAPI
IWineD3DDeviceImpl_GetSoftwareVertexProcessing(IWineD3DDevice
*iface
) {
6444 IWineD3DDeviceImpl
*This
= (IWineD3DDeviceImpl
*)iface
;
6445 static BOOL showFixmes
= TRUE
;
6447 FIXME("(%p) : stub\n", This
);
6450 return This
->softwareVertexProcessing
;
6454 static HRESULT WINAPI
IWineD3DDeviceImpl_GetRasterStatus(IWineD3DDevice
*iface
, UINT iSwapChain
, WINED3DRASTER_STATUS
* pRasterStatus
) {
6455 IWineD3DDeviceImpl
*This
= (IWineD3DDeviceImpl
*)iface
;
6456 IWineD3DSwapChain
*swapChain
;
6459 TRACE("(%p) : SwapChain %d returning %p\n", This
, iSwapChain
, pRasterStatus
);
6461 hr
= IWineD3DDeviceImpl_GetSwapChain(iface
, iSwapChain
, (IWineD3DSwapChain
**)&swapChain
);
6462 if(hr
== WINED3D_OK
){
6463 hr
= IWineD3DSwapChain_GetRasterStatus(swapChain
, pRasterStatus
);
6464 IWineD3DSwapChain_Release(swapChain
);
6466 FIXME("(%p) IWineD3DSwapChain_GetRasterStatus returned in error\n", This
);
6472 static HRESULT WINAPI
IWineD3DDeviceImpl_SetNPatchMode(IWineD3DDevice
*iface
, float nSegments
) {
6473 IWineD3DDeviceImpl
*This
= (IWineD3DDeviceImpl
*)iface
;
6474 static BOOL showfixmes
= TRUE
;
6475 if(nSegments
!= 0.0f
) {
6477 FIXME("(%p) : stub nSegments(%f)\n", This
, nSegments
);
6484 static float WINAPI
IWineD3DDeviceImpl_GetNPatchMode(IWineD3DDevice
*iface
) {
6485 IWineD3DDeviceImpl
*This
= (IWineD3DDeviceImpl
*)iface
;
6486 static BOOL showfixmes
= TRUE
;
6488 FIXME("(%p) : stub returning(%f)\n", This
, 0.0f
);
6494 static HRESULT WINAPI
IWineD3DDeviceImpl_UpdateSurface(IWineD3DDevice
*iface
, IWineD3DSurface
*pSourceSurface
, CONST RECT
* pSourceRect
, IWineD3DSurface
*pDestinationSurface
, CONST POINT
* pDestPoint
) {
6495 IWineD3DDeviceImpl
*This
= (IWineD3DDeviceImpl
*) iface
;
6496 /** TODO: remove casts to IWineD3DSurfaceImpl
6497 * NOTE: move code to surface to accomplish this
6498 ****************************************/
6499 IWineD3DSurfaceImpl
*pSrcSurface
= (IWineD3DSurfaceImpl
*)pSourceSurface
;
6500 int srcWidth
, srcHeight
;
6501 unsigned int srcSurfaceWidth
, srcSurfaceHeight
, destSurfaceWidth
, destSurfaceHeight
;
6502 WINED3DFORMAT destFormat
, srcFormat
;
6504 int destLeft
, destTop
;
6505 WINED3DPOOL srcPool
, destPool
;
6507 int rowoffset
= 0; /* how many bytes to add onto the end of a row to wraparound to the beginning of the next */
6508 glDescriptor
*glDescription
= NULL
;
6509 GLenum textureDimensions
= GL_TEXTURE_2D
;
6510 IWineD3DBaseTexture
*baseTexture
;
6512 WINED3DSURFACE_DESC winedesc
;
6514 TRACE("(%p) : Source (%p) Rect (%p) Destination (%p) Point(%p)\n", This
, pSourceSurface
, pSourceRect
, pDestinationSurface
, pDestPoint
);
6515 memset(&winedesc
, 0, sizeof(winedesc
));
6516 winedesc
.Width
= &srcSurfaceWidth
;
6517 winedesc
.Height
= &srcSurfaceHeight
;
6518 winedesc
.Pool
= &srcPool
;
6519 winedesc
.Format
= &srcFormat
;
6521 IWineD3DSurface_GetDesc(pSourceSurface
, &winedesc
);
6523 winedesc
.Width
= &destSurfaceWidth
;
6524 winedesc
.Height
= &destSurfaceHeight
;
6525 winedesc
.Pool
= &destPool
;
6526 winedesc
.Format
= &destFormat
;
6527 winedesc
.Size
= &destSize
;
6529 IWineD3DSurface_GetDesc(pDestinationSurface
, &winedesc
);
6531 if(srcPool
!= WINED3DPOOL_SYSTEMMEM
|| destPool
!= WINED3DPOOL_DEFAULT
){
6532 WARN("source %p must be SYSTEMMEM and dest %p must be DEFAULT, returning WINED3DERR_INVALIDCALL\n", pSourceSurface
, pDestinationSurface
);
6533 return WINED3DERR_INVALIDCALL
;
6536 if (destFormat
== WINED3DFMT_UNKNOWN
) {
6537 TRACE("(%p) : Converting destination surface from WINED3DFMT_UNKNOWN to the source format\n", This
);
6538 IWineD3DSurface_SetFormat(pDestinationSurface
, srcFormat
);
6540 /* Get the update surface description */
6541 IWineD3DSurface_GetDesc(pDestinationSurface
, &winedesc
);
6544 /* Make sure the surface is loaded and up to date */
6545 IWineD3DSurface_PreLoad(pDestinationSurface
);
6547 IWineD3DSurface_GetGlDesc(pDestinationSurface
, &glDescription
);
6551 /* this needs to be done in lines if the sourceRect != the sourceWidth */
6552 srcWidth
= pSourceRect
? pSourceRect
->right
- pSourceRect
->left
: srcSurfaceWidth
;
6553 srcHeight
= pSourceRect
? pSourceRect
->top
- pSourceRect
->bottom
: srcSurfaceHeight
;
6554 destLeft
= pDestPoint
? pDestPoint
->x
: 0;
6555 destTop
= pDestPoint
? pDestPoint
->y
: 0;
6558 /* This function doesn't support compressed textures
6559 the pitch is just bytesPerPixel * width */
6560 if(srcWidth
!= srcSurfaceWidth
|| (pSourceRect
!= NULL
&& pSourceRect
->left
!= 0) ){
6561 rowoffset
= (srcSurfaceWidth
- srcWidth
) * pSrcSurface
->bytesPerPixel
;
6562 offset
+= pSourceRect
->left
* pSrcSurface
->bytesPerPixel
;
6563 /* TODO: do we ever get 3bpp?, would a shift and an add be quicker than a mul (well maybe a cycle or two) */
6565 /* TODO DXT formats */
6567 if(pSourceRect
!= NULL
&& pSourceRect
->top
!= 0){
6568 offset
+= pSourceRect
->top
* srcWidth
* pSrcSurface
->bytesPerPixel
;
6570 TRACE("(%p) glTexSubImage2D, Level %d, left %d, top %d, width %d, height %d , ftm %d, type %d, memory %p\n"
6572 ,glDescription
->level
6577 ,glDescription
->glFormat
6578 ,glDescription
->glType
6579 ,IWineD3DSurface_GetData(pSourceSurface
)
6583 if (IWineD3DSurface_GetData(pSourceSurface
) == NULL
) {
6585 /* need to lock the surface to get the data */
6586 FIXME("Surfaces has no allocated memory, but should be an in memory only surface\n");
6589 /* TODO: Cube and volume support */
6591 /* not a whole row so we have to do it a line at a time */
6594 /* hopefully using pointer addtion will be quicker than using a point + j * rowoffset */
6595 unsigned char* data
=((unsigned char *)IWineD3DSurface_GetData(pSourceSurface
)) + offset
;
6597 for(j
= destTop
; j
< (srcHeight
+ destTop
) ; j
++){
6599 glTexSubImage2D(glDescription
->target
6600 ,glDescription
->level
6605 ,glDescription
->glFormat
6606 ,glDescription
->glType
6607 ,data
/* could be quicker using */
6612 } else { /* Full width, so just write out the whole texture */
6614 if (WINED3DFMT_DXT1
== destFormat
||
6615 WINED3DFMT_DXT2
== destFormat
||
6616 WINED3DFMT_DXT3
== destFormat
||
6617 WINED3DFMT_DXT4
== destFormat
||
6618 WINED3DFMT_DXT5
== destFormat
) {
6619 if (GL_SUPPORT(EXT_TEXTURE_COMPRESSION_S3TC
)) {
6620 if (destSurfaceHeight
!= srcHeight
|| destSurfaceWidth
!= srcWidth
) {
6621 /* FIXME: The easy way to do this is lock the destination, and copy the bits accross */
6622 FIXME("Updating part of a compressed texture is not supported at the moment\n");
6623 } if (destFormat
!= srcFormat
) {
6624 FIXME("Updating mixed format compressed texture is not curretly support\n");
6626 GL_EXTCALL(glCompressedTexImage2DARB
)(glDescription
->target
,
6627 glDescription
->level
,
6628 glDescription
->glFormatInternal
,
6633 IWineD3DSurface_GetData(pSourceSurface
));
6636 FIXME("Attempting to update a DXT compressed texture without hardware support\n");
6641 if (NP2_REPACK
== wined3d_settings
.nonpower2_mode
) {
6643 /* some applications cannot handle odd pitches returned by soft non-power2, so we have
6644 to repack the data from pow2Width/Height to expected Width,Height, this makes the
6645 data returned by GetData non-power2 width/height with hardware non-power2
6646 pow2Width/height are set to surface width height, repacking isn't needed so it
6647 doesn't matter which function gets called. */
6648 glTexSubImage2D(glDescription
->target
6649 ,glDescription
->level
6654 ,glDescription
->glFormat
6655 ,glDescription
->glType
6656 ,IWineD3DSurface_GetData(pSourceSurface
)
6660 /* not repacked, the data returned by IWineD3DSurface_GetData is pow2Width x pow2Height */
6661 glTexSubImage2D(glDescription
->target
6662 ,glDescription
->level
6665 ,((IWineD3DSurfaceImpl
*)pSourceSurface
)->pow2Width
6666 ,((IWineD3DSurfaceImpl
*)pSourceSurface
)->pow2Height
6667 ,glDescription
->glFormat
6668 ,glDescription
->glType
6669 ,IWineD3DSurface_GetData(pSourceSurface
)
6675 checkGLcall("glTexSubImage2D");
6677 /* I only need to look up baseTexture here, so it may be a good idea to hava a GL_TARGET ->
6678 * GL_DIMENSIONS lookup, or maybe store the dimensions on the surface (but that's making the
6679 * surface bigger than it needs to be hmm.. */
6680 if (WINED3D_OK
== IWineD3DSurface_GetContainer(pDestinationSurface
, &IID_IWineD3DBaseTexture
, (void **)&baseTexture
)) {
6681 textureDimensions
= IWineD3DBaseTexture_GetTextureDimensions(baseTexture
);
6682 IWineD3DBaseTexture_Release(baseTexture
);
6685 glDisable(textureDimensions
); /* This needs to be managed better.... */
6691 /* Used by DirectX 8 */
6692 static HRESULT WINAPI
IWineD3DDeviceImpl_CopyRects(IWineD3DDevice
*iface
,
6693 IWineD3DSurface
* pSourceSurface
, CONST RECT
* pSourceRectsArray
, UINT cRects
,
6694 IWineD3DSurface
* pDestinationSurface
, CONST POINT
* pDestPointsArray
) {
6696 IWineD3DDeviceImpl
*This
= (IWineD3DDeviceImpl
*)iface
;
6697 HRESULT hr
= WINED3D_OK
;
6698 WINED3DFORMAT srcFormat
, destFormat
;
6699 UINT srcWidth
, destWidth
;
6700 UINT srcHeight
, destHeight
;
6702 WINED3DSURFACE_DESC winedesc
;
6704 TRACE("(%p) pSrcSur=%p, pSourceRects=%p, cRects=%d, pDstSur=%p, pDestPtsArr=%p\n", This
,
6705 pSourceSurface
, pSourceRectsArray
, cRects
, pDestinationSurface
, pDestPointsArray
);
6708 /* Check that the source texture is in WINED3DPOOL_SYSTEMMEM and the destination texture is in WINED3DPOOL_DEFAULT */
6709 memset(&winedesc
, 0, sizeof(winedesc
));
6711 winedesc
.Format
= &srcFormat
;
6712 winedesc
.Width
= &srcWidth
;
6713 winedesc
.Height
= &srcHeight
;
6714 winedesc
.Size
= &srcSize
;
6715 IWineD3DSurface_GetDesc(pSourceSurface
, &winedesc
);
6717 winedesc
.Format
= &destFormat
;
6718 winedesc
.Width
= &destWidth
;
6719 winedesc
.Height
= &destHeight
;
6720 winedesc
.Size
= NULL
;
6721 IWineD3DSurface_GetDesc(pDestinationSurface
, &winedesc
);
6723 /* Check that the source and destination formats match */
6724 if (srcFormat
!= destFormat
&& WINED3DFMT_UNKNOWN
!= destFormat
) {
6725 WARN("(%p) source %p format must match the dest %p format, returning WINED3DERR_INVALIDCALL\n", This
, pSourceSurface
, pDestinationSurface
);
6726 return WINED3DERR_INVALIDCALL
;
6727 } else if (WINED3DFMT_UNKNOWN
== destFormat
) {
6728 TRACE("(%p) : Converting destination surface from WINED3DFMT_UNKNOWN to the source format\n", This
);
6729 IWineD3DSurface_SetFormat(pDestinationSurface
, srcFormat
);
6730 destFormat
= srcFormat
;
6733 /* Quick if complete copy ... */
6734 if (cRects
== 0 && pSourceRectsArray
== NULL
&& pDestPointsArray
== NULL
) {
6736 if (srcWidth
== destWidth
&& srcHeight
== destHeight
) {
6737 WINED3DLOCKED_RECT lrSrc
;
6738 WINED3DLOCKED_RECT lrDst
;
6739 IWineD3DSurface_LockRect(pSourceSurface
, &lrSrc
, NULL
, WINED3DLOCK_READONLY
);
6740 IWineD3DSurface_LockRect(pDestinationSurface
, &lrDst
, NULL
, 0L);
6741 TRACE("Locked src and dst, Direct copy as surfaces are equal, w=%d, h=%d\n", srcWidth
, srcHeight
);
6743 memcpy(lrDst
.pBits
, lrSrc
.pBits
, srcSize
);
6745 IWineD3DSurface_UnlockRect(pSourceSurface
);
6746 IWineD3DSurface_UnlockRect(pDestinationSurface
);
6747 TRACE("Unlocked src and dst\n");
6751 FIXME("Wanted to copy all surfaces but size not compatible, returning WINED3DERR_INVALIDCALL\n");
6752 hr
= WINED3DERR_INVALIDCALL
;
6757 if (NULL
!= pSourceRectsArray
&& NULL
!= pDestPointsArray
) {
6759 int bytesPerPixel
= ((IWineD3DSurfaceImpl
*) pSourceSurface
)->bytesPerPixel
;
6762 /* Copy rect by rect */
6763 for (i
= 0; i
< cRects
; ++i
) {
6764 CONST RECT
* r
= &pSourceRectsArray
[i
];
6765 CONST POINT
* p
= &pDestPointsArray
[i
];
6768 WINED3DLOCKED_RECT lrSrc
;
6769 WINED3DLOCKED_RECT lrDst
;
6772 TRACE("Copying rect %d (%ld,%ld),(%ld,%ld) -> (%ld,%ld)\n", i
, r
->left
, r
->top
, r
->right
, r
->bottom
, p
->x
, p
->y
);
6773 if (srcFormat
== WINED3DFMT_DXT1
) {
6774 copyperline
= ((r
->right
- r
->left
) * bytesPerPixel
) / 2; /* DXT1 is half byte per pixel */
6776 copyperline
= ((r
->right
- r
->left
) * bytesPerPixel
);
6779 IWineD3DSurface_LockRect(pSourceSurface
, &lrSrc
, r
, WINED3DLOCK_READONLY
);
6780 dest_rect
.left
= p
->x
;
6781 dest_rect
.top
= p
->y
;
6782 dest_rect
.right
= p
->x
+ (r
->right
- r
->left
);
6783 dest_rect
.bottom
= p
->y
+ (r
->bottom
- r
->top
);
6784 IWineD3DSurface_LockRect(pDestinationSurface
, &lrDst
, &dest_rect
, 0L);
6785 TRACE("Locked src and dst\n");
6787 /* Find where to start */
6788 for (j
= 0; j
< (r
->bottom
- r
->top
- 1); ++j
) {
6789 memcpy((char*) lrDst
.pBits
+ (j
* lrDst
.Pitch
), (char*) lrSrc
.pBits
+ (j
* lrSrc
.Pitch
), copyperline
);
6791 IWineD3DSurface_UnlockRect(pSourceSurface
);
6792 IWineD3DSurface_UnlockRect(pDestinationSurface
);
6793 TRACE("Unlocked src and dst\n");
6797 int bytesPerPixel
= ((IWineD3DSurfaceImpl
*) pSourceSurface
)->bytesPerPixel
;
6800 WINED3DLOCKED_RECT lrSrc
;
6801 WINED3DLOCKED_RECT lrDst
;
6804 for(i
=0; i
< cRects
; i
++) {
6805 CONST RECT
* r
= &pSourceRectsArray
[i
];
6807 TRACE("Copying rect %d (%ld,%ld),(%ld,%ld) -> (0, 0)\n", i
, r
->left
, r
->top
, r
->right
, r
->bottom
);
6808 if (srcFormat
== WINED3DFMT_DXT1
) {
6809 copyperline
= ((r
->right
- r
->left
) * bytesPerPixel
) / 2; /* DXT1 is half byte per pixel */
6811 copyperline
= ((r
->right
- r
->left
) * bytesPerPixel
);
6813 IWineD3DSurface_LockRect(pSourceSurface
, &lrSrc
, r
, WINED3DLOCK_READONLY
);
6816 dest_rect
.right
= r
->right
- r
->left
;
6817 dest_rect
.bottom
= r
->bottom
- r
->top
;
6818 IWineD3DSurface_LockRect(pDestinationSurface
, &lrDst
, &dest_rect
, 0L);
6819 TRACE("Locked src and dst\n");
6820 /* Find where to start */
6821 for (j
= 0; j
< (r
->bottom
- r
->top
- 1); ++j
) {
6822 memcpy((char*) lrDst
.pBits
+ (j
* lrDst
.Pitch
), (char*) lrSrc
.pBits
+ (j
* lrSrc
.Pitch
), copyperline
);
6824 IWineD3DSurface_UnlockRect(pSourceSurface
);
6825 IWineD3DSurface_UnlockRect(pDestinationSurface
);
6826 TRACE("Unlocked src and dst\n");
6834 /* Implementation details at http://developer.nvidia.com/attach/6494
6836 http://oss.sgi.com/projects/ogl-sample/registry/NV/evaluators.txt
6837 hmm.. no longer supported use
6838 OpenGL evaluators or tessellate surfaces within your application.
6841 /* http://msdn.microsoft.com/library/default.asp?url=/library/en-us/directx9_c/directx/graphics/reference/d3d/interfaces/idirect3ddevice9/DrawRectPatch.asp */
6842 static HRESULT WINAPI
IWineD3DDeviceImpl_DrawRectPatch(IWineD3DDevice
*iface
, UINT Handle
, CONST
float* pNumSegs
, CONST WINED3DRECTPATCH_INFO
* pRectPatchInfo
) {
6843 IWineD3DDeviceImpl
*This
= (IWineD3DDeviceImpl
*)iface
;
6844 TRACE("(%p) Handle(%d) noSegs(%p) rectpatch(%p)\n", This
, Handle
, pNumSegs
, pRectPatchInfo
);
6845 FIXME("(%p) : Stub\n", This
);
6850 /* http://msdn.microsoft.com/library/default.asp?url=/library/en-us/directx9_c/directx/graphics/reference/d3d/interfaces/idirect3ddevice9/DrawTriPatch.asp */
6851 static HRESULT WINAPI
IWineD3DDeviceImpl_DrawTriPatch(IWineD3DDevice
*iface
, UINT Handle
, CONST
float* pNumSegs
, CONST WINED3DTRIPATCH_INFO
* pTriPatchInfo
) {
6852 IWineD3DDeviceImpl
*This
= (IWineD3DDeviceImpl
*)iface
;
6853 TRACE("(%p) Handle(%d) noSegs(%p) tripatch(%p)\n", This
, Handle
, pNumSegs
, pTriPatchInfo
);
6854 FIXME("(%p) : Stub\n", This
);
6858 static HRESULT WINAPI
IWineD3DDeviceImpl_DeletePatch(IWineD3DDevice
*iface
, UINT Handle
) {
6859 IWineD3DDeviceImpl
*This
= (IWineD3DDeviceImpl
*)iface
;
6860 TRACE("(%p) Handle(%d)\n", This
, Handle
);
6861 FIXME("(%p) : Stub\n", This
);
6865 static HRESULT WINAPI
IWineD3DDeviceImpl_ColorFill(IWineD3DDevice
*iface
, IWineD3DSurface
*pSurface
, CONST D3DRECT
* pRect
, D3DCOLOR color
) {
6866 IWineD3DDeviceImpl
*This
= (IWineD3DDeviceImpl
*) iface
;
6867 IWineD3DSurfaceImpl
*surface
= (IWineD3DSurfaceImpl
*) pSurface
;
6869 TRACE("(%p) Colour fill Surface: %p rect: %p color: %ld\n", This
, pSurface
, pRect
, color
);
6871 if (surface
->resource
.pool
!= WINED3DPOOL_DEFAULT
&& surface
->resource
.pool
!= WINED3DPOOL_SYSTEMMEM
) {
6872 FIXME("call to colorfill with non WINED3DPOOL_DEFAULT or WINED3DPOOL_SYSTEMMEM surface\n");
6873 return WINED3DERR_INVALIDCALL
;
6876 /* Just forward this to the DirectDraw blitting engine */
6877 memset(&BltFx
, 0, sizeof(BltFx
));
6878 BltFx
.dwSize
= sizeof(BltFx
);
6879 BltFx
.u5
.dwFillColor
= color
;
6880 return IWineD3DSurface_Blt(pSurface
, (RECT
*) pRect
, NULL
, NULL
, DDBLT_COLORFILL
, &BltFx
);
6883 /* rendertarget and deptth stencil functions */
6884 static HRESULT WINAPI
IWineD3DDeviceImpl_GetRenderTarget(IWineD3DDevice
* iface
,DWORD RenderTargetIndex
, IWineD3DSurface
**ppRenderTarget
) {
6885 IWineD3DDeviceImpl
*This
= (IWineD3DDeviceImpl
*)iface
;
6887 /* FIXME: Implelent RenderTargetIndex >0 */
6888 if(RenderTargetIndex
> 0)
6889 FIXME("(%p) : RenderTargetIndex %ld >0 not currently supported\n", This
, RenderTargetIndex
);
6891 *ppRenderTarget
= This
->renderTarget
;
6892 TRACE("(%p) : RenderTarget %ld Index returning %p\n", This
, RenderTargetIndex
, *ppRenderTarget
);
6893 /* Note inc ref on returned surface */
6894 if(*ppRenderTarget
!= NULL
)
6895 IWineD3DSurface_AddRef(*ppRenderTarget
);
6899 static HRESULT WINAPI
IWineD3DDeviceImpl_SetFrontBackBuffers(IWineD3DDevice
*iface
, IWineD3DSurface
*Front
, IWineD3DSurface
*Back
) {
6900 IWineD3DDeviceImpl
*This
= (IWineD3DDeviceImpl
*)iface
;
6901 IWineD3DSurfaceImpl
*FrontImpl
= (IWineD3DSurfaceImpl
*) Front
;
6902 IWineD3DSurfaceImpl
*BackImpl
= (IWineD3DSurfaceImpl
*) Back
;
6903 IWineD3DSwapChainImpl
*Swapchain
;
6906 TRACE("(%p)->(%p,%p)\n", This
, FrontImpl
, BackImpl
);
6908 hr
= IWineD3DDevice_GetSwapChain(iface
, 0, (IWineD3DSwapChain
**) &Swapchain
);
6909 if(hr
!= WINED3D_OK
) {
6910 ERR("Can't get the swapchain\n");
6914 /* Make sure to release the swapchain */
6915 IWineD3DSwapChain_Release((IWineD3DSwapChain
*) Swapchain
);
6917 if(FrontImpl
&& !(FrontImpl
->resource
.usage
& WINED3DUSAGE_RENDERTARGET
) ) {
6918 ERR("Trying to set a front buffer which doesn't have WINED3DUSAGE_RENDERTARGET usage\n");
6919 return WINED3DERR_INVALIDCALL
;
6921 else if(BackImpl
&& !(BackImpl
->resource
.usage
& WINED3DUSAGE_RENDERTARGET
)) {
6922 ERR("Trying to set a back buffer which doesn't have WINED3DUSAGE_RENDERTARGET usage\n");
6923 return WINED3DERR_INVALIDCALL
;
6926 if(Swapchain
->frontBuffer
!= Front
) {
6927 TRACE("Changing the front buffer from %p to %p\n", Swapchain
->frontBuffer
, Front
);
6929 if(Swapchain
->frontBuffer
)
6930 IWineD3DSurface_SetContainer(Swapchain
->frontBuffer
, NULL
);
6931 Swapchain
->frontBuffer
= Front
;
6933 if(Swapchain
->frontBuffer
) {
6934 IWineD3DSurface_SetContainer(Swapchain
->frontBuffer
, (IWineD3DBase
*) Swapchain
);
6938 if(Back
&& !Swapchain
->backBuffer
) {
6939 /* We need memory for the back buffer array - only one back buffer this way */
6940 Swapchain
->backBuffer
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, sizeof(IWineD3DSurface
*));
6941 if(!Swapchain
->backBuffer
) {
6942 ERR("Out of memory\n");
6943 return E_OUTOFMEMORY
;
6947 if(Swapchain
->backBuffer
[0] != Back
) {
6948 TRACE("Changing the back buffer from %p to %p\n", Swapchain
->backBuffer
, Back
);
6950 if(!Swapchain
->backBuffer
[0]) {
6951 /* GL was told to draw to the front buffer at creation,
6954 glDrawBuffer(GL_BACK
);
6955 checkGLcall("glDrawBuffer(GL_BACK)");
6956 /* Set the backbuffer count to 1 because other code uses it to fing the back buffers */
6957 Swapchain
->presentParms
.BackBufferCount
= 1;
6959 /* That makes problems - disable for now */
6960 /* glDrawBuffer(GL_FRONT); */
6961 checkGLcall("glDrawBuffer(GL_FRONT)");
6962 /* We have lost our back buffer, set this to 0 to avoid confusing other code */
6963 Swapchain
->presentParms
.BackBufferCount
= 0;
6967 if(Swapchain
->backBuffer
[0])
6968 IWineD3DSurface_SetContainer(Swapchain
->backBuffer
[0], NULL
);
6969 Swapchain
->backBuffer
[0] = Back
;
6971 if(Swapchain
->backBuffer
[0]) {
6972 IWineD3DSurface_SetContainer(Swapchain
->backBuffer
[0], (IWineD3DBase
*) Swapchain
);
6974 HeapFree(GetProcessHeap(), 0, Swapchain
->backBuffer
);
6982 static HRESULT WINAPI
IWineD3DDeviceImpl_GetDepthStencilSurface(IWineD3DDevice
* iface
, IWineD3DSurface
**ppZStencilSurface
) {
6983 IWineD3DDeviceImpl
*This
= (IWineD3DDeviceImpl
*)iface
;
6984 *ppZStencilSurface
= This
->depthStencilBuffer
;
6985 TRACE("(%p) : zStencilSurface returning %p\n", This
, *ppZStencilSurface
);
6987 if(*ppZStencilSurface
!= NULL
) {
6988 /* Note inc ref on returned surface */
6989 IWineD3DSurface_AddRef(*ppZStencilSurface
);
6994 /* internal static helper functions */
6995 static HRESULT WINAPI
IWineD3DDeviceImpl_ActiveRender(IWineD3DDevice
* iface
,
6996 IWineD3DSurface
*RenderSurface
);
6998 static HRESULT WINAPI
IWineD3DDeviceImpl_SetRenderTarget(IWineD3DDevice
*iface
, DWORD RenderTargetIndex
, IWineD3DSurface
*pRenderTarget
) {
6999 IWineD3DDeviceImpl
*This
= (IWineD3DDeviceImpl
*)iface
;
7000 HRESULT hr
= WINED3D_OK
;
7001 WINED3DVIEWPORT viewport
;
7003 TRACE("(%p) Swapping rendertarget\n",This
);
7004 if (RenderTargetIndex
> 0) {
7005 FIXME("(%p) Render targets other than the first are not supported\n",This
);
7006 RenderTargetIndex
= 0;
7009 /* MSDN says that null disables the render target
7010 but a device must always be associated with a render target
7011 nope MSDN says that we return invalid call to a null rendertarget with an index of 0
7013 see http://msdn.microsoft.com/library/default.asp?url=/library/en-us/directx9_c/directx/graphics/programmingguide/AdvancedTopics/PixelPipe/MultipleRenderTarget.asp
7016 if (RenderTargetIndex
== 0 && pRenderTarget
== NULL
) {
7017 FIXME("Trying to set render target 0 to NULL\n");
7018 return WINED3DERR_INVALIDCALL
;
7020 /* TODO: replace Impl* usage with interface usage */
7021 if (!((IWineD3DSurfaceImpl
*)pRenderTarget
)->resource
.usage
& WINED3DUSAGE_RENDERTARGET
) {
7022 FIXME("(%p)Trying to set the render target to a surface(%p) that wasn't created with a usage of WINED3DUSAGE_RENDERTARGET\n",This
,pRenderTarget
);
7023 return WINED3DERR_INVALIDCALL
;
7025 /** TODO: check that the depth stencil format matches the render target, this is only done in debug
7026 * builds, but I think wine counts as a 'debug' build for now.
7027 ******************************/
7028 /* If we are trying to set what we already have, don't bother */
7029 if (pRenderTarget
== This
->renderTarget
) {
7030 TRACE("Trying to do a NOP SetRenderTarget operation\n");
7032 /* Otherwise, set the render target up */
7034 if (FALSE
== This
->sceneEnded
) {
7035 IWineD3DDevice_EndScene(iface
);
7037 TRACE("clearing renderer\n");
7038 /* IWineD3DDeviceImpl_CleanRender(iface); */
7039 /* OpenGL doesn't support 'sharing' of the stencilBuffer so we may incure an extra memory overhead
7040 depending on the renter target implementation being used.
7041 A shared context implementation will share all buffers between all rendertargets (including swapchains),
7042 implementations that use separate pbuffers for different swapchains or rendertargets will have to duplicate the
7043 stencil buffer and incure an extra memory overhead */
7044 hr
= IWineD3DDeviceImpl_ActiveRender(iface
, pRenderTarget
);
7047 if (SUCCEEDED(hr
)) {
7048 /* Finally, reset the viewport as the MSDN states. */
7049 /* TODO: Replace impl usage */
7050 viewport
.Height
= ((IWineD3DSurfaceImpl
*)This
->renderTarget
)->currentDesc
.Height
;
7051 viewport
.Width
= ((IWineD3DSurfaceImpl
*)This
->renderTarget
)->currentDesc
.Width
;
7054 viewport
.MaxZ
= 1.0f
;
7055 viewport
.MinZ
= 0.0f
;
7056 IWineD3DDeviceImpl_SetViewport(iface
, &viewport
);
7058 FIXME("Unknown error setting the render target\n");
7060 This
->sceneEnded
= FALSE
;
7064 static HRESULT WINAPI
IWineD3DDeviceImpl_SetDepthStencilSurface(IWineD3DDevice
*iface
, IWineD3DSurface
*pNewZStencil
) {
7065 IWineD3DDeviceImpl
*This
= (IWineD3DDeviceImpl
*)iface
;
7066 HRESULT hr
= WINED3D_OK
;
7067 IWineD3DSurface
*tmp
;
7069 TRACE("(%p) Swapping z-buffer\n",This
);
7071 if (pNewZStencil
== This
->stencilBufferTarget
) {
7072 TRACE("Trying to do a NOP SetRenderTarget operation\n");
7074 /** OpenGL doesn't support 'sharing' of the stencilBuffer so we may incure an extra memory overhead
7075 * depending on the renter target implementation being used.
7076 * A shared context implementation will share all buffers between all rendertargets (including swapchains),
7077 * implementations that use separate pbuffers for different swapchains or rendertargets will have to duplicate the
7078 * stencil buffer and incure an extra memory overhead
7079 ******************************************************/
7082 tmp
= This
->stencilBufferTarget
;
7083 This
->stencilBufferTarget
= pNewZStencil
;
7084 /* should we be calling the parent or the wined3d surface? */
7085 if (NULL
!= This
->stencilBufferTarget
) IWineD3DSurface_AddRef(This
->stencilBufferTarget
);
7086 if (NULL
!= tmp
) IWineD3DSurface_Release(tmp
);
7088 /** TODO: glEnable/glDisable on depth/stencil depending on
7089 * pNewZStencil is NULL and the depth/stencil is enabled in d3d
7090 **********************************************************/
7097 #ifdef GL_VERSION_1_3
7098 /* Internal functions not in DirectX */
7099 /** TODO: move this off to the opengl context manager
7100 *(the swapchain doesn't need to know anything about offscreen rendering!)
7101 ****************************************************/
7103 static HRESULT WINAPI
IWineD3DDeviceImpl_CleanRender(IWineD3DDevice
* iface
, IWineD3DSwapChainImpl
*swapchain
)
7105 IWineD3DDeviceImpl
*This
= (IWineD3DDeviceImpl
*)iface
;
7107 TRACE("(%p), %p\n", This
, swapchain
);
7109 if (swapchain
->win
!= swapchain
->drawable
) {
7110 /* Set everything back the way it ws */
7111 swapchain
->render_ctx
= swapchain
->glCtx
;
7112 swapchain
->drawable
= swapchain
->win
;
7117 /* TODO: move this off into a context manager so that GLX_ATI_render_texture and other types of surface can be used. */
7118 static HRESULT WINAPI
IWineD3DDeviceImpl_FindGLContext(IWineD3DDevice
*iface
, IWineD3DSurface
*pSurface
, glContext
**context
) {
7119 IWineD3DDeviceImpl
*This
= (IWineD3DDeviceImpl
*)iface
;
7122 unsigned int height
;
7123 WINED3DFORMAT format
;
7124 WINED3DSURFACE_DESC surfaceDesc
;
7125 memset(&surfaceDesc
, 0, sizeof(surfaceDesc
));
7126 surfaceDesc
.Width
= &width
;
7127 surfaceDesc
.Height
= &height
;
7128 surfaceDesc
.Format
= &format
;
7129 IWineD3DSurface_GetDesc(pSurface
, &surfaceDesc
);
7131 /* I need a get width/height function (and should do something with the format) */
7132 for (i
= 0; i
< CONTEXT_CACHE
; ++i
) {
7133 /** NOTE: the contextCache[i].pSurface == pSurface check ceates onepbuffer per surface
7134 ATI cards don't destroy pbuffers, but as soon as resource releasing callbacks are inplace
7135 the pSurface can be set to 0 allowing it to be reused from cache **/
7136 if (This
->contextCache
[i
].Width
== width
&& This
->contextCache
[i
].Height
== height
7137 && (pbuffer_per_surface
== FALSE
|| This
->contextCache
[i
].pSurface
== pSurface
|| This
->contextCache
[i
].pSurface
== NULL
)) {
7138 *context
= &This
->contextCache
[i
];
7141 if (This
->contextCache
[i
].Width
== 0) {
7142 This
->contextCache
[i
].pSurface
= pSurface
;
7143 This
->contextCache
[i
].Width
= width
;
7144 This
->contextCache
[i
].Height
= height
;
7145 *context
= &This
->contextCache
[i
];
7149 if (i
== CONTEXT_CACHE
) {
7150 int minUsage
= 0x7FFFFFFF; /* MAX_INT */
7151 glContext
*dropContext
= 0;
7152 for (i
= 0; i
< CONTEXT_CACHE
; i
++) {
7153 if (This
->contextCache
[i
].usedcount
< minUsage
) {
7154 dropContext
= &This
->contextCache
[i
];
7155 minUsage
= This
->contextCache
[i
].usedcount
;
7158 /* clean up the context (this doesn't work for ATI at the moment */
7160 glXDestroyContext(swapchain
->display
, dropContext
->context
);
7161 glXDestroyPbuffer(swapchain
->display
, dropContext
->drawable
);
7164 dropContext
->Width
= 0;
7165 dropContext
->pSurface
= pSurface
;
7166 *context
= dropContext
;
7168 if (++This
->contextCache
[i
].usedcount
== 0x7FFFFFFF /* MAX_INT */ - 1 ) {
7169 for (i
= 0; i
< CONTEXT_CACHE
; i
++) {
7170 This
->contextCache
[i
].usedcount
= max(0, This
->contextCache
[i
].usedcount
- (0x7FFFFFFF /* MAX_INT */ >> 1));
7174 if (*context
!= NULL
)
7177 return E_OUTOFMEMORY
;
7181 /** FIXME: This is currently used called whenever SetRenderTarget or SetStencilBuffer are called
7182 * the functionality needs splitting up so that we don't do more than we should do.
7183 * this only seems to impact performance a little.
7184 ******************************/
7185 static HRESULT WINAPI
IWineD3DDeviceImpl_ActiveRender(IWineD3DDevice
* iface
,
7186 IWineD3DSurface
*RenderSurface
) {
7187 HRESULT ret
= WINED3DERR_INVALIDCALL
;
7189 IWineD3DStateBlockImpl
*oldUpdateStateBlock
;
7192 * Currently only active for GLX >= 1.3
7193 * for others versions we'll have to use GLXPixmaps
7195 * normally we must test GLX_VERSION_1_3 but nvidia headers are not correct
7196 * as they implement GLX 1.3 but only define GLX_VERSION_1_2
7197 * so only check OpenGL version
7198 * ..........................
7199 * I don't believe that it is a problem with NVidia headers,
7200 * XFree only supports GLX1.2, nVidia (and ATI to some extent) provide 1.3 functions
7201 * in GLX 1.2, there is no mention of the correct way to tell if the extensions are provided.
7203 * Your application will report GLX version 1.2 on glXQueryVersion.
7204 * However, it is safe to call the GLX 1.3 functions as described below.
7206 #if defined(GL_VERSION_1_3)
7208 IWineD3DDeviceImpl
*This
= (IWineD3DDeviceImpl
*)iface
;
7209 IWineD3DSurface
*StencilSurface
= This
->stencilBufferTarget
;
7210 IWineD3DSurface
*tmp
;
7211 /** TODO: we only need to look up the configuration !IF! we are setting the target to a texture **/
7212 GLXFBConfig
* cfgs
= NULL
;
7216 IWineD3DSwapChain
*currentSwapchain
;
7217 IWineD3DSwapChainImpl
*swapchain
;
7218 /** TODO: get rid of Impl usage we should always create a zbuffer/stencil with our contexts if possible,
7219 * but switch them off if the StencilSurface is set to NULL
7220 ** *********************************************************/
7221 D3DFORMAT BackBufferFormat
= ((IWineD3DSurfaceImpl
*) RenderSurface
)->resource
.format
;
7222 D3DFORMAT StencilBufferFormat
= (NULL
!= StencilSurface
) ? ((IWineD3DSurfaceImpl
*) StencilSurface
)->resource
.format
: 0;
7225 if StencilSurface == NULL && zBufferTarget != NULL then switch the zbuffer off,
7226 it StencilSurface != NULL && zBufferTarget == NULL switch it on
7229 #define PUSH1(att) attribs[nAttribs++] = (att);
7230 #define PUSH2(att,value) attribs[nAttribs++] = (att); attribs[nAttribs++] = (value);
7232 /* PUSH2(GLX_BIND_TO_TEXTURE_RGBA_ATI, True); examples of this are few and far between (but I've got a nice working one!)*/
7234 /** TODO: remove the reff to Impl (context manager should fix this!) **/
7235 IWineD3DSwapChainImpl
*impSwapChain
;
7236 IWineD3DDevice_GetSwapChain(iface
, 0, (IWineD3DSwapChain
**)&impSwapChain
);
7237 if (NULL
== impSwapChain
) { /* NOTE: This should NEVER fail */
7238 ERR("(%p) Failed to get a the implicit swapchain\n", iface
);
7243 PUSH2(GLX_DRAWABLE_TYPE
, GLX_PBUFFER_BIT
);
7244 PUSH2(GLX_X_RENDERABLE
, TRUE
);
7245 PUSH2(GLX_DOUBLEBUFFER
, TRUE
);
7246 TRACE("calling makeglcfg\n");
7247 D3DFmtMakeGlCfg(BackBufferFormat
, StencilBufferFormat
, attribs
, &nAttribs
, FALSE
/* alternate */);
7250 TRACE("calling chooseFGConfig\n");
7251 cfgs
= glXChooseFBConfig(impSwapChain
->display
, DefaultScreen(impSwapChain
->display
),
7254 if (!cfgs
) { /* OK we didn't find the exact config, so use any reasonable match */
7255 /* TODO: fill in the 'requested' and 'current' depths, also make sure that's
7256 why we failed and only show this message once! */
7257 MESSAGE("Failed to find exact match, finding alternative but you may suffer performance issues, try changing xfree's depth to match the requested depth\n"); /**/
7259 PUSH2(GLX_DRAWABLE_TYPE
, GLX_PBUFFER_BIT
| GLX_WINDOW_BIT
);
7260 /* PUSH2(GLX_X_RENDERABLE, TRUE); */
7261 PUSH2(GLX_RENDER_TYPE
, GLX_RGBA_BIT
);
7262 PUSH2(GLX_DOUBLEBUFFER
, FALSE
);
7263 TRACE("calling makeglcfg\n");
7264 D3DFmtMakeGlCfg(BackBufferFormat
, StencilBufferFormat
, attribs
, &nAttribs
, TRUE
/* alternate */);
7266 cfgs
= glXChooseFBConfig(impSwapChain
->display
, DefaultScreen(impSwapChain
->display
),
7273 for (i
= 0; i
< nCfgs
; ++i
) {
7274 TRACE("for (%u,%s)/(%u,%s) found config[%d]@%p\n", BackBufferFormat
,
7275 debug_d3dformat(BackBufferFormat
), StencilBufferFormat
,
7276 debug_d3dformat(StencilBufferFormat
), i
, cfgs
[i
]);
7279 if (NULL
!= This
->renderTarget
) {
7281 vcheckGLcall("glFlush");
7282 /** This is only useful if the old render target was a swapchain,
7283 * we need to supercede this with a function that displays
7284 * the current buffer on the screen. This is easy to do in glx1.3 but
7285 * we need to do copy-write pixels in glx 1.2.
7286 ************************************************/
7287 glXSwapBuffers(impSwapChain
->display
, impSwapChain
->drawable
);
7289 printf("Hit Enter to get next frame ...\n");
7295 if (IWineD3DSurface_GetContainer(This
->renderTarget
, &IID_IWineD3DSwapChain
, (void **)¤tSwapchain
) != WINED3D_OK
) {
7296 /* the selected render target doesn't belong to a swapchain, so use the devices implicit swapchain */
7297 IWineD3DDevice_GetSwapChain(iface
, 0, ¤tSwapchain
);
7301 * TODO: remove the use of IWineD3DSwapChainImpl, a context manager will help since it will replace the
7302 * renderTarget = swapchain->backBuffer[i] bit and anything to do with *glContexts
7303 **********************************************************************/
7304 if (IWineD3DSurface_GetContainer(RenderSurface
, &IID_IWineD3DSwapChain
, (void **)&swapchain
) == WINED3D_OK
) {
7305 /* We also need to make sure that the lights &co are also in the context of the swapchains */
7306 /* FIXME: If the render target gets sent to the frontBuffer should be be presenting it raw? */
7307 TRACE("making swapchain active\n");
7308 if (RenderSurface
!= This
->renderTarget
) {
7309 BOOL backbuf
= FALSE
;
7312 for(i
= 0; i
< swapchain
->presentParms
.BackBufferCount
; i
++) {
7313 if(RenderSurface
== swapchain
->backBuffer
[i
]) {
7321 /* This could be flagged so that some operations work directly with the front buffer */
7322 FIXME("Attempting to set the renderTarget to the frontBuffer\n");
7324 if (glXMakeCurrent(swapchain
->display
, swapchain
->win
, swapchain
->glCtx
)
7326 TRACE("Error in setting current context: context %p drawable %ld !\n",
7327 impSwapChain
->glCtx
, impSwapChain
->win
);
7330 IWineD3DDeviceImpl_CleanRender(iface
, (IWineD3DSwapChainImpl
*)currentSwapchain
);
7332 checkGLcall("glXMakeContextCurrent");
7334 IWineD3DSwapChain_Release((IWineD3DSwapChain
*)swapchain
);
7336 else if (pbuffer_support
&& cfgs
!= NULL
/* && some test to make sure that opengl supports pbuffers */) {
7338 /** ********************************************************************
7339 * This is a quickly hacked out implementation of offscreen textures.
7340 * It will work in most cases but there may be problems if the client
7341 * modifies the texture directly, or expects the contents of the rendertarget
7344 * There are some real speed vs compatibility issues here:
7345 * we should really use a new context for every texture, but that eats ram.
7346 * we should also be restoring the texture to the pbuffer but that eats CPU
7347 * we can also 'reuse' the current pbuffer if the size is larger than the requested buffer,
7348 * but if this means reusing the display backbuffer then we need to make sure that
7349 * states are correctly preserved.
7350 * In many cases I would expect that we can 'skip' some functions, such as preserving states,
7351 * and gain a good performance increase at the cost of compatibility.
7352 * I would suggest that, when this is the case, a user configurable flag be made
7353 * available, allowing the user to choose the best emulated experience for them.
7354 *********************************************************************/
7356 XVisualInfo
*visinfo
;
7357 glContext
*newContext
;
7359 /* Here were using a shared context model */
7360 if (WINED3D_OK
!= IWineD3DDeviceImpl_FindGLContext(iface
, RenderSurface
, &newContext
)) {
7361 FIXME("(%p) : Failed to find a context for surface %p\n", iface
, RenderSurface
);
7364 /* If the context doesn't exist then create a new one */
7365 /* TODO: This should really be part of findGlContext */
7366 if (NULL
== newContext
->context
) {
7368 TRACE("making new buffer\n");
7370 PUSH2(GLX_PBUFFER_WIDTH
, newContext
->Width
);
7371 PUSH2(GLX_PBUFFER_HEIGHT
, newContext
->Height
);
7374 newContext
->drawable
= glXCreatePbuffer(impSwapChain
->display
, cfgs
[0], attribs
);
7376 /** ****************************************
7377 *GLX1.3 isn't supported by XFree 'yet' until that point ATI emulates pBuffers
7379 * In future releases, we may provide the calls glXCreateNewContext,
7380 * glXQueryDrawable and glXMakeContextCurrent.
7381 * so until then we have to use glXGetVisualFromFBConfig &co..
7382 ********************************************/
7385 visinfo
= glXGetVisualFromFBConfig(impSwapChain
->display
, cfgs
[0]);
7387 ERR("Error: couldn't get an RGBA, double-buffered visual\n");
7389 newContext
->context
= glXCreateContext(impSwapChain
->display
, visinfo
, impSwapChain
->glCtx
, GL_TRUE
);
7393 if (NULL
== newContext
|| NULL
== newContext
->context
) {
7394 ERR("(%p) : Failed to find a context for surface %p\n", iface
, RenderSurface
);
7396 /* Debug logging, (this function leaks), change to a TRACE when the leak is plugged */
7397 if (glXMakeCurrent(impSwapChain
->display
, newContext
->drawable
, newContext
->context
) == False
) {
7398 TRACE("Error in setting current context: context %p drawable %ld\n", newContext
->context
, newContext
->drawable
);
7401 /* Clean up the old context */
7402 IWineD3DDeviceImpl_CleanRender(iface
, (IWineD3DSwapChainImpl
*)currentSwapchain
);
7403 /* Set the current context of the swapchain to the new context */
7404 impSwapChain
->drawable
= newContext
->drawable
;
7405 impSwapChain
->render_ctx
= newContext
->context
;
7409 /* Disable recording, and apply the stateblock to the new context
7410 * FIXME: This is a bit of a hack, each context should know it's own state,
7411 * the directX current directX state should then be applied to the context */
7412 oldUpdateStateBlock
= This
->updateStateBlock
;
7413 oldRecording
= This
->isRecordingState
;
7414 This
->isRecordingState
= FALSE
;
7415 This
->updateStateBlock
= This
->stateBlock
;
7416 IWineD3DStateBlock_Apply((IWineD3DStateBlock
*)This
->stateBlock
);
7418 /* clean up the current rendertargets swapchain (if it belonged to one) */
7419 if (currentSwapchain
!= NULL
) {
7420 IWineD3DSwapChain_Release((IWineD3DSwapChain
*)currentSwapchain
);
7423 /* Were done with the opengl context management, setup the rendertargets */
7425 tmp
= This
->renderTarget
;
7426 This
->renderTarget
= RenderSurface
;
7427 IWineD3DSurface_AddRef(This
->renderTarget
);
7428 IWineD3DSurface_Release(tmp
);
7433 /* The surface must be rendered upside down to cancel the flip produce by glCopyTexImage */
7434 /* Check that the container is not a swapchain member */
7436 IWineD3DSwapChain
*tmpSwapChain
;
7437 if (WINED3D_OK
!= IWineD3DSurface_GetContainer(This
->renderTarget
, &IID_IWineD3DSwapChain
, (void **)&tmpSwapChain
)) {
7438 This
->renderUpsideDown
= TRUE
;
7440 This
->renderUpsideDown
= FALSE
;
7441 IWineD3DSwapChain_Release(tmpSwapChain
);
7443 /* Force updating the cull mode */
7444 TRACE("setting render state\n");
7445 IWineD3DDevice_GetRenderState(iface
, WINED3DRS_CULLMODE
, &value
);
7446 IWineD3DDevice_SetRenderState(iface
, WINED3DRS_CULLMODE
, value
);
7448 /* Force updating projection matrix */
7449 This
->last_was_rhw
= FALSE
;
7450 This
->proj_valid
= FALSE
;
7453 /* Restore recording state */
7454 This
->isRecordingState
= oldRecording
;
7455 This
->updateStateBlock
= oldUpdateStateBlock
;
7462 ERR("cannot get valides GLXFBConfig for (%u,%s)/(%u,%s)\n", BackBufferFormat
,
7463 debug_d3dformat(BackBufferFormat
), StencilBufferFormat
, debug_d3dformat(StencilBufferFormat
));
7468 if ( NULL
!= impSwapChain
) {
7469 IWineD3DSwapChain_Release((IWineD3DSwapChain
*)impSwapChain
);
7477 static HRESULT WINAPI
IWineD3DDeviceImpl_SetCursorProperties(IWineD3DDevice
* iface
, UINT XHotSpot
,
7478 UINT YHotSpot
, IWineD3DSurface
*pCursorBitmap
) {
7479 IWineD3DDeviceImpl
*This
= (IWineD3DDeviceImpl
*) iface
;
7480 /* TODO: the use of Impl is deprecated. */
7481 IWineD3DSurfaceImpl
* pSur
= (IWineD3DSurfaceImpl
*) pCursorBitmap
;
7483 TRACE("(%p) : Spot Pos(%u,%u)\n", This
, XHotSpot
, YHotSpot
);
7485 /* some basic validation checks */
7486 if(This
->cursorTexture
) {
7488 glDeleteTextures(1, &This
->cursorTexture
);
7490 This
->cursorTexture
= 0;
7494 /* MSDN: Cursor must be A8R8G8B8 */
7495 if (WINED3DFMT_A8R8G8B8
!= pSur
->resource
.format
) {
7496 ERR("(%p) : surface(%p) has an invalid format\n", This
, pCursorBitmap
);
7497 return WINED3DERR_INVALIDCALL
;
7500 /* MSDN: Cursor must be smaller than the display mode */
7501 if(pSur
->currentDesc
.Width
> This
->ddraw_width
||
7502 pSur
->currentDesc
.Height
> This
->ddraw_height
) {
7503 ERR("(%p) : Surface(%p) is %dx%d pixels, but screen res is %ldx%ld\n", This
, pSur
, pSur
->currentDesc
.Width
, pSur
->currentDesc
.Height
, This
->ddraw_width
, This
->ddraw_height
);
7504 return WINED3DERR_INVALIDCALL
;
7507 /* TODO: MSDN: Cursor sizes must be a power of 2 */
7508 /* This is to tell our texture code to load a SCRATCH surface. This allows us to use out
7509 * Texture and Blitting code to draw the cursor
7511 pSur
->Flags
|= SFLAG_FORCELOAD
;
7512 IWineD3DSurface_PreLoad(pCursorBitmap
);
7513 pSur
->Flags
&= ~SFLAG_FORCELOAD
;
7514 /* Do not store the surface's pointer because the application may release
7515 * it after setting the cursor image. Windows doesn't addref the set surface, so we can't
7516 * do this either without creating circular refcount dependencies. Copy out the gl texture instead.
7518 This
->cursorTexture
= pSur
->glDescription
.textureName
;
7519 This
->cursorWidth
= pSur
->currentDesc
.Width
;
7520 This
->cursorHeight
= pSur
->currentDesc
.Height
;
7521 pSur
->glDescription
.textureName
= 0; /* Prevent the texture from being changed or deleted */
7524 This
->xHotSpot
= XHotSpot
;
7525 This
->yHotSpot
= YHotSpot
;
7529 static void WINAPI
IWineD3DDeviceImpl_SetCursorPosition(IWineD3DDevice
* iface
, int XScreenSpace
, int YScreenSpace
, DWORD Flags
) {
7530 IWineD3DDeviceImpl
*This
= (IWineD3DDeviceImpl
*) iface
;
7531 TRACE("(%p) : SetPos to (%u,%u)\n", This
, XScreenSpace
, YScreenSpace
);
7533 This
->xScreenSpace
= XScreenSpace
;
7534 This
->yScreenSpace
= YScreenSpace
;
7540 static BOOL WINAPI
IWineD3DDeviceImpl_ShowCursor(IWineD3DDevice
* iface
, BOOL bShow
) {
7541 IWineD3DDeviceImpl
*This
= (IWineD3DDeviceImpl
*) iface
;
7542 TRACE("(%p) : visible(%d)\n", This
, bShow
);
7544 This
->bCursorVisible
= bShow
;
7549 static HRESULT WINAPI
IWineD3DDeviceImpl_TestCooperativeLevel(IWineD3DDevice
* iface
) {
7550 IWineD3DDeviceImpl
*This
= (IWineD3DDeviceImpl
*) iface
;
7551 TRACE("(%p) : state (%lu)\n", This
, This
->state
);
7552 /* TODO: Implement wrapping of the WndProc so that mimimize and maxamise can be monitored and the states adjusted. */
7553 switch (This
->state
) {
7556 case WINED3DERR_DEVICELOST
:
7558 ResourceList
*resourceList
= This
->resources
;
7559 while (NULL
!= resourceList
) {
7560 if (((IWineD3DResourceImpl
*)resourceList
->resource
)->resource
.pool
== WINED3DPOOL_DEFAULT
/* TODO: IWineD3DResource_GetPool(resourceList->resource)*/)
7561 return WINED3DERR_DEVICENOTRESET
;
7562 resourceList
= resourceList
->next
;
7564 return WINED3DERR_DEVICELOST
;
7566 case WINED3DERR_DRIVERINTERNALERROR
:
7567 return WINED3DERR_DRIVERINTERNALERROR
;
7571 return WINED3DERR_DRIVERINTERNALERROR
;
7575 static HRESULT WINAPI
IWineD3DDeviceImpl_EvictManagedResources(IWineD3DDevice
* iface
) {
7576 IWineD3DDeviceImpl
*This
= (IWineD3DDeviceImpl
*) iface
;
7577 /** FIXME: Resource tracking needs to be done,
7578 * The closes we can do to this is set the priorities of all managed textures low
7579 * and then reset them.
7580 ***********************************************************/
7581 FIXME("(%p) : stub\n", This
);
7585 static HRESULT WINAPI
IWineD3DDeviceImpl_Reset(IWineD3DDevice
* iface
, WINED3DPRESENT_PARAMETERS
* pPresentationParameters
) {
7586 IWineD3DDeviceImpl
*This
= (IWineD3DDeviceImpl
*) iface
;
7587 /** FIXME: Resource trascking needs to be done.
7588 * in effect this pulls all non only default
7589 * textures out of video memory and deletes all glTextures (glDeleteTextures)
7590 * and should clear down the context and set it up according to pPresentationParameters
7591 ***********************************************************/
7592 FIXME("(%p) : stub\n", This
);
7596 static HRESULT WINAPI
IWineD3DDeviceImpl_SetDialogBoxMode(IWineD3DDevice
*iface
, BOOL bEnableDialogs
) {
7597 IWineD3DDeviceImpl
*This
= (IWineD3DDeviceImpl
*)iface
;
7598 /** FIXME: always true at the moment **/
7599 if(bEnableDialogs
== FALSE
) {
7600 FIXME("(%p) Dialogs cannot be disabled yet\n", This
);
7606 static HRESULT WINAPI
IWineD3DDeviceImpl_GetCreationParameters(IWineD3DDevice
*iface
, WINED3DDEVICE_CREATION_PARAMETERS
*pParameters
) {
7607 IWineD3DDeviceImpl
*This
= (IWineD3DDeviceImpl
*) iface
;
7608 TRACE("(%p) : pParameters %p\n", This
, pParameters
);
7610 *pParameters
= This
->createParms
;
7614 static void WINAPI
IWineD3DDeviceImpl_SetGammaRamp(IWineD3DDevice
* iface
, UINT iSwapChain
, DWORD Flags
, CONST WINED3DGAMMARAMP
* pRamp
) {
7615 IWineD3DSwapChain
*swapchain
;
7616 HRESULT hrc
= WINED3D_OK
;
7618 TRACE("Relaying to swapchain\n");
7620 if ((hrc
= IWineD3DDeviceImpl_GetSwapChain(iface
, iSwapChain
, &swapchain
)) == WINED3D_OK
) {
7621 IWineD3DSwapChain_SetGammaRamp(swapchain
, Flags
, (WINED3DGAMMARAMP
*)pRamp
);
7622 IWineD3DSwapChain_Release(swapchain
);
7627 static void WINAPI
IWineD3DDeviceImpl_GetGammaRamp(IWineD3DDevice
*iface
, UINT iSwapChain
, WINED3DGAMMARAMP
* pRamp
) {
7628 IWineD3DSwapChain
*swapchain
;
7629 HRESULT hrc
= WINED3D_OK
;
7631 TRACE("Relaying to swapchain\n");
7633 if ((hrc
= IWineD3DDeviceImpl_GetSwapChain(iface
, iSwapChain
, &swapchain
)) == WINED3D_OK
) {
7634 hrc
=IWineD3DSwapChain_GetGammaRamp(swapchain
, pRamp
);
7635 IWineD3DSwapChain_Release(swapchain
);
7641 /** ********************************************************
7642 * Notification functions
7643 ** ********************************************************/
7644 /** This function must be called in the release of a resource when ref == 0,
7645 * the contents of resource must still be correct,
7646 * any handels to other resource held by the caller must be closed
7647 * (e.g. a texture should release all held surfaces because telling the device that it's been released.)
7648 *****************************************************/
7649 static void WINAPI
IWineD3DDeviceImpl_AddResource(IWineD3DDevice
*iface
, IWineD3DResource
*resource
){
7650 IWineD3DDeviceImpl
*This
= (IWineD3DDeviceImpl
*)iface
;
7651 ResourceList
* resourceList
;
7653 TRACE("(%p) : resource %p\n", This
, resource
);
7655 EnterCriticalSection(&resourceStoreCriticalSection
);
7657 /* add a new texture to the frot of the linked list */
7658 resourceList
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, sizeof(ResourceList
));
7659 resourceList
->resource
= resource
;
7661 /* Get the old head */
7662 resourceList
->next
= This
->resources
;
7664 This
->resources
= resourceList
;
7665 TRACE("Added resource %p with element %p pointing to %p\n", resource
, resourceList
, resourceList
->next
);
7668 LeaveCriticalSection(&resourceStoreCriticalSection
);
7673 static void WINAPI
IWineD3DDeviceImpl_RemoveResource(IWineD3DDevice
*iface
, IWineD3DResource
*resource
){
7674 IWineD3DDeviceImpl
*This
= (IWineD3DDeviceImpl
*)iface
;
7675 ResourceList
* resourceList
= NULL
;
7676 ResourceList
* previousResourceList
= NULL
;
7678 TRACE("(%p) : resource %p\n", This
, resource
);
7681 EnterCriticalSection(&resourceStoreCriticalSection
);
7683 resourceList
= This
->resources
;
7685 while (resourceList
!= NULL
) {
7686 if(resourceList
->resource
== resource
) break;
7687 previousResourceList
= resourceList
;
7688 resourceList
= resourceList
->next
;
7691 if (resourceList
== NULL
) {
7692 FIXME("Attempted to remove resource %p that hasn't been stored\n", resource
);
7694 LeaveCriticalSection(&resourceStoreCriticalSection
);
7698 TRACE("Found resource %p with element %p pointing to %p (previous %p)\n", resourceList
->resource
, resourceList
, resourceList
->next
, previousResourceList
);
7700 /* make sure we don't leave a hole in the list */
7701 if (previousResourceList
!= NULL
) {
7702 previousResourceList
->next
= resourceList
->next
;
7704 This
->resources
= resourceList
->next
;
7708 LeaveCriticalSection(&resourceStoreCriticalSection
);
7714 static void WINAPI
IWineD3DDeviceImpl_ResourceReleased(IWineD3DDevice
*iface
, IWineD3DResource
*resource
){
7715 IWineD3DDeviceImpl
*This
= (IWineD3DDeviceImpl
*) iface
;
7718 TRACE("(%p) : resource %p\n", This
, resource
);
7719 switch(IWineD3DResource_GetType(resource
)){
7720 case WINED3DRTYPE_SURFACE
:
7721 /* TODO: check front and back buffers, rendertargets etc.. possibly swapchains? */
7723 case WINED3DRTYPE_TEXTURE
:
7724 case WINED3DRTYPE_CUBETEXTURE
:
7725 case WINED3DRTYPE_VOLUMETEXTURE
:
7726 for (counter
= 0; counter
< GL_LIMITS(sampler_stages
); counter
++) {
7727 if (This
->stateBlock
!= NULL
&& This
->stateBlock
->textures
[counter
] == (IWineD3DBaseTexture
*)resource
) {
7728 WARN("Texture being released is still by a stateblock, Stage = %u Texture = %p\n", counter
, resource
);
7729 This
->stateBlock
->textures
[counter
] = NULL
;
7731 if (This
->updateStateBlock
!= This
->stateBlock
){
7732 if (This
->updateStateBlock
->textures
[counter
] == (IWineD3DBaseTexture
*)resource
) {
7733 WARN("Texture being released is still by a stateblock, Stage = %u Texture = %p\n", counter
, resource
);
7734 This
->updateStateBlock
->textures
[counter
] = NULL
;
7739 case WINED3DRTYPE_VOLUME
:
7740 /* TODO: nothing really? */
7742 case WINED3DRTYPE_VERTEXBUFFER
:
7743 /* MSDN: When an application no longer holds a references to this interface, the interface will automatically be freed. */
7746 TRACE("Cleaning up stream pointers\n");
7748 for(streamNumber
= 0; streamNumber
< MAX_STREAMS
; streamNumber
++){
7749 /* FINDOUT: should a warn be generated if were recording and updateStateBlock->streamSource is lost?
7750 FINDOUT: should changes.streamSource[StreamNumber] be set ?
7752 if (This
->updateStateBlock
!= NULL
) { /* ==NULL when device is being destroyed */
7753 if ((IWineD3DResource
*)This
->updateStateBlock
->streamSource
[streamNumber
] == resource
) {
7754 FIXME("Vertex buffer released whlst bound to a state block stream %d\n", streamNumber
);
7755 This
->updateStateBlock
->streamSource
[streamNumber
] = 0;
7756 /* Set changed flag? */
7759 if (This
->stateBlock
!= NULL
) { /* only happens if there is an error in the application, or on reset/release (because we don't manage internal tracking properly) */
7760 if ((IWineD3DResource
*)This
->stateBlock
->streamSource
[streamNumber
] == resource
) {
7761 TRACE("Vertex buffer released whlst bound to a state block stream %d\n", streamNumber
);
7762 This
->stateBlock
->streamSource
[streamNumber
] = 0;
7765 #if 0 /* TODO: Manage internal tracking properly so that 'this shouldn't happen' */
7766 else { /* This shouldn't happen */
7767 FIXME("Calling application has released the device before relasing all the resources bound to the device\n");
7774 case WINED3DRTYPE_INDEXBUFFER
:
7775 /* MSDN: When an application no longer holds a references to this interface, the interface will automatically be freed.*/
7776 if (This
->updateStateBlock
!= NULL
) { /* ==NULL when device is being destroyed */
7777 if (This
->updateStateBlock
->pIndexData
== (IWineD3DIndexBuffer
*)resource
) {
7778 This
->updateStateBlock
->pIndexData
= NULL
;
7781 if (This
->stateBlock
!= NULL
) { /* ==NULL when device is being destroyed */
7782 if (This
->stateBlock
->pIndexData
== (IWineD3DIndexBuffer
*)resource
) {
7783 This
->stateBlock
->pIndexData
= NULL
;
7789 FIXME("(%p) unknown resource type %p %u\n", This
, resource
, IWineD3DResource_GetType(resource
));
7794 /* Remove the resoruce from the resourceStore */
7795 IWineD3DDeviceImpl_RemoveResource(iface
, resource
);
7797 TRACE("Resource released\n");
7801 /**********************************************************
7802 * IWineD3DDevice VTbl follows
7803 **********************************************************/
7805 const IWineD3DDeviceVtbl IWineD3DDevice_Vtbl
=
7807 /*** IUnknown methods ***/
7808 IWineD3DDeviceImpl_QueryInterface
,
7809 IWineD3DDeviceImpl_AddRef
,
7810 IWineD3DDeviceImpl_Release
,
7811 /*** IWineD3DDevice methods ***/
7812 IWineD3DDeviceImpl_GetParent
,
7813 /*** Creation methods**/
7814 IWineD3DDeviceImpl_CreateVertexBuffer
,
7815 IWineD3DDeviceImpl_CreateIndexBuffer
,
7816 IWineD3DDeviceImpl_CreateStateBlock
,
7817 IWineD3DDeviceImpl_CreateSurface
,
7818 IWineD3DDeviceImpl_CreateTexture
,
7819 IWineD3DDeviceImpl_CreateVolumeTexture
,
7820 IWineD3DDeviceImpl_CreateVolume
,
7821 IWineD3DDeviceImpl_CreateCubeTexture
,
7822 IWineD3DDeviceImpl_CreateQuery
,
7823 IWineD3DDeviceImpl_CreateAdditionalSwapChain
,
7824 IWineD3DDeviceImpl_CreateVertexDeclaration
,
7825 IWineD3DDeviceImpl_CreateVertexShader
,
7826 IWineD3DDeviceImpl_CreatePixelShader
,
7827 IWineD3DDeviceImpl_CreatePalette
,
7828 /*** Odd functions **/
7829 IWineD3DDeviceImpl_Init3D
,
7830 IWineD3DDeviceImpl_Uninit3D
,
7831 IWineD3DDeviceImpl_EnumDisplayModes
,
7832 IWineD3DDeviceImpl_EvictManagedResources
,
7833 IWineD3DDeviceImpl_GetAvailableTextureMem
,
7834 IWineD3DDeviceImpl_GetBackBuffer
,
7835 IWineD3DDeviceImpl_GetCreationParameters
,
7836 IWineD3DDeviceImpl_GetDeviceCaps
,
7837 IWineD3DDeviceImpl_GetDirect3D
,
7838 IWineD3DDeviceImpl_GetDisplayMode
,
7839 IWineD3DDeviceImpl_SetDisplayMode
,
7840 IWineD3DDeviceImpl_GetHWND
,
7841 IWineD3DDeviceImpl_SetHWND
,
7842 IWineD3DDeviceImpl_GetNumberOfSwapChains
,
7843 IWineD3DDeviceImpl_GetRasterStatus
,
7844 IWineD3DDeviceImpl_GetSwapChain
,
7845 IWineD3DDeviceImpl_Reset
,
7846 IWineD3DDeviceImpl_SetDialogBoxMode
,
7847 IWineD3DDeviceImpl_SetCursorProperties
,
7848 IWineD3DDeviceImpl_SetCursorPosition
,
7849 IWineD3DDeviceImpl_ShowCursor
,
7850 IWineD3DDeviceImpl_TestCooperativeLevel
,
7851 /*** Getters and setters **/
7852 IWineD3DDeviceImpl_SetClipPlane
,
7853 IWineD3DDeviceImpl_GetClipPlane
,
7854 IWineD3DDeviceImpl_SetClipStatus
,
7855 IWineD3DDeviceImpl_GetClipStatus
,
7856 IWineD3DDeviceImpl_SetCurrentTexturePalette
,
7857 IWineD3DDeviceImpl_GetCurrentTexturePalette
,
7858 IWineD3DDeviceImpl_SetDepthStencilSurface
,
7859 IWineD3DDeviceImpl_GetDepthStencilSurface
,
7860 IWineD3DDeviceImpl_SetFVF
,
7861 IWineD3DDeviceImpl_GetFVF
,
7862 IWineD3DDeviceImpl_SetGammaRamp
,
7863 IWineD3DDeviceImpl_GetGammaRamp
,
7864 IWineD3DDeviceImpl_SetIndices
,
7865 IWineD3DDeviceImpl_GetIndices
,
7866 IWineD3DDeviceImpl_SetLight
,
7867 IWineD3DDeviceImpl_GetLight
,
7868 IWineD3DDeviceImpl_SetLightEnable
,
7869 IWineD3DDeviceImpl_GetLightEnable
,
7870 IWineD3DDeviceImpl_SetMaterial
,
7871 IWineD3DDeviceImpl_GetMaterial
,
7872 IWineD3DDeviceImpl_SetNPatchMode
,
7873 IWineD3DDeviceImpl_GetNPatchMode
,
7874 IWineD3DDeviceImpl_SetPaletteEntries
,
7875 IWineD3DDeviceImpl_GetPaletteEntries
,
7876 IWineD3DDeviceImpl_SetPixelShader
,
7877 IWineD3DDeviceImpl_GetPixelShader
,
7878 IWineD3DDeviceImpl_SetPixelShaderConstantB
,
7879 IWineD3DDeviceImpl_GetPixelShaderConstantB
,
7880 IWineD3DDeviceImpl_SetPixelShaderConstantI
,
7881 IWineD3DDeviceImpl_GetPixelShaderConstantI
,
7882 IWineD3DDeviceImpl_SetPixelShaderConstantF
,
7883 IWineD3DDeviceImpl_GetPixelShaderConstantF
,
7884 IWineD3DDeviceImpl_SetRenderState
,
7885 IWineD3DDeviceImpl_GetRenderState
,
7886 IWineD3DDeviceImpl_SetRenderTarget
,
7887 IWineD3DDeviceImpl_GetRenderTarget
,
7888 IWineD3DDeviceImpl_SetFrontBackBuffers
,
7889 IWineD3DDeviceImpl_SetSamplerState
,
7890 IWineD3DDeviceImpl_GetSamplerState
,
7891 IWineD3DDeviceImpl_SetScissorRect
,
7892 IWineD3DDeviceImpl_GetScissorRect
,
7893 IWineD3DDeviceImpl_SetSoftwareVertexProcessing
,
7894 IWineD3DDeviceImpl_GetSoftwareVertexProcessing
,
7895 IWineD3DDeviceImpl_SetStreamSource
,
7896 IWineD3DDeviceImpl_GetStreamSource
,
7897 IWineD3DDeviceImpl_SetStreamSourceFreq
,
7898 IWineD3DDeviceImpl_GetStreamSourceFreq
,
7899 IWineD3DDeviceImpl_SetTexture
,
7900 IWineD3DDeviceImpl_GetTexture
,
7901 IWineD3DDeviceImpl_SetTextureStageState
,
7902 IWineD3DDeviceImpl_GetTextureStageState
,
7903 IWineD3DDeviceImpl_SetTransform
,
7904 IWineD3DDeviceImpl_GetTransform
,
7905 IWineD3DDeviceImpl_SetVertexDeclaration
,
7906 IWineD3DDeviceImpl_GetVertexDeclaration
,
7907 IWineD3DDeviceImpl_SetVertexShader
,
7908 IWineD3DDeviceImpl_GetVertexShader
,
7909 IWineD3DDeviceImpl_SetVertexShaderConstantB
,
7910 IWineD3DDeviceImpl_GetVertexShaderConstantB
,
7911 IWineD3DDeviceImpl_SetVertexShaderConstantI
,
7912 IWineD3DDeviceImpl_GetVertexShaderConstantI
,
7913 IWineD3DDeviceImpl_SetVertexShaderConstantF
,
7914 IWineD3DDeviceImpl_GetVertexShaderConstantF
,
7915 IWineD3DDeviceImpl_SetViewport
,
7916 IWineD3DDeviceImpl_GetViewport
,
7917 IWineD3DDeviceImpl_MultiplyTransform
,
7918 IWineD3DDeviceImpl_ValidateDevice
,
7919 IWineD3DDeviceImpl_ProcessVertices
,
7920 /*** State block ***/
7921 IWineD3DDeviceImpl_BeginStateBlock
,
7922 IWineD3DDeviceImpl_EndStateBlock
,
7923 /*** Scene management ***/
7924 IWineD3DDeviceImpl_BeginScene
,
7925 IWineD3DDeviceImpl_EndScene
,
7926 IWineD3DDeviceImpl_Present
,
7927 IWineD3DDeviceImpl_Clear
,
7929 IWineD3DDeviceImpl_DrawPrimitive
,
7930 IWineD3DDeviceImpl_DrawIndexedPrimitive
,
7931 IWineD3DDeviceImpl_DrawPrimitiveUP
,
7932 IWineD3DDeviceImpl_DrawIndexedPrimitiveUP
,
7933 IWineD3DDeviceImpl_DrawPrimitiveStrided
,
7934 IWineD3DDeviceImpl_DrawRectPatch
,
7935 IWineD3DDeviceImpl_DrawTriPatch
,
7936 IWineD3DDeviceImpl_DeletePatch
,
7937 IWineD3DDeviceImpl_ColorFill
,
7938 IWineD3DDeviceImpl_UpdateTexture
,
7939 IWineD3DDeviceImpl_UpdateSurface
,
7940 IWineD3DDeviceImpl_CopyRects
,
7941 IWineD3DDeviceImpl_StretchRect
,
7942 IWineD3DDeviceImpl_GetRenderTargetData
,
7943 IWineD3DDeviceImpl_GetFrontBufferData
,
7944 /*** Internal use IWineD3DDevice methods ***/
7945 IWineD3DDeviceImpl_SetupTextureStates
,
7946 /*** object tracking ***/
7947 IWineD3DDeviceImpl_ResourceReleased
7951 const DWORD SavedPixelStates_R
[NUM_SAVEDPIXELSTATES_R
] = {
7952 WINED3DRS_ALPHABLENDENABLE
,
7953 WINED3DRS_ALPHAFUNC
,
7954 WINED3DRS_ALPHAREF
,
7955 WINED3DRS_ALPHATESTENABLE
,
7957 WINED3DRS_COLORWRITEENABLE
,
7958 WINED3DRS_DESTBLEND
,
7959 WINED3DRS_DITHERENABLE
,
7960 WINED3DRS_FILLMODE
,
7961 WINED3DRS_FOGDENSITY
,
7963 WINED3DRS_FOGSTART
,
7964 WINED3DRS_LASTPIXEL
,
7965 WINED3DRS_SHADEMODE
,
7966 WINED3DRS_SRCBLEND
,
7967 WINED3DRS_STENCILENABLE
,
7968 WINED3DRS_STENCILFAIL
,
7969 WINED3DRS_STENCILFUNC
,
7970 WINED3DRS_STENCILMASK
,
7971 WINED3DRS_STENCILPASS
,
7972 WINED3DRS_STENCILREF
,
7973 WINED3DRS_STENCILWRITEMASK
,
7974 WINED3DRS_STENCILZFAIL
,
7975 WINED3DRS_TEXTUREFACTOR
,
7986 WINED3DRS_ZWRITEENABLE
7989 const DWORD SavedPixelStates_T
[NUM_SAVEDPIXELSTATES_T
] = {
7990 WINED3DTSS_ADDRESSW
,
7991 WINED3DTSS_ALPHAARG0
,
7992 WINED3DTSS_ALPHAARG1
,
7993 WINED3DTSS_ALPHAARG2
,
7994 WINED3DTSS_ALPHAOP
,
7995 WINED3DTSS_BUMPENVLOFFSET
,
7996 WINED3DTSS_BUMPENVLSCALE
,
7997 WINED3DTSS_BUMPENVMAT00
,
7998 WINED3DTSS_BUMPENVMAT01
,
7999 WINED3DTSS_BUMPENVMAT10
,
8000 WINED3DTSS_BUMPENVMAT11
,
8001 WINED3DTSS_COLORARG0
,
8002 WINED3DTSS_COLORARG1
,
8003 WINED3DTSS_COLORARG2
,
8004 WINED3DTSS_COLOROP
,
8005 WINED3DTSS_RESULTARG
,
8006 WINED3DTSS_TEXCOORDINDEX
,
8007 WINED3DTSS_TEXTURETRANSFORMFLAGS
8010 const DWORD SavedPixelStates_S
[NUM_SAVEDPIXELSTATES_S
] = {
8011 WINED3DSAMP_ADDRESSU
,
8012 WINED3DSAMP_ADDRESSV
,
8013 WINED3DSAMP_ADDRESSW
,
8014 WINED3DSAMP_BORDERCOLOR
,
8015 WINED3DSAMP_MAGFILTER
,
8016 WINED3DSAMP_MINFILTER
,
8017 WINED3DSAMP_MIPFILTER
,
8018 WINED3DSAMP_MIPMAPLODBIAS
,
8019 WINED3DSAMP_MAXMIPLEVEL
,
8020 WINED3DSAMP_MAXANISOTROPY
,
8021 WINED3DSAMP_SRGBTEXTURE
,
8022 WINED3DSAMP_ELEMENTINDEX
8025 const DWORD SavedVertexStates_R
[NUM_SAVEDVERTEXSTATES_R
] = {
8027 WINED3DRS_AMBIENTMATERIALSOURCE
,
8028 WINED3DRS_CLIPPING
,
8029 WINED3DRS_CLIPPLANEENABLE
,
8030 WINED3DRS_COLORVERTEX
,
8031 WINED3DRS_DIFFUSEMATERIALSOURCE
,
8032 WINED3DRS_EMISSIVEMATERIALSOURCE
,
8033 WINED3DRS_FOGDENSITY
,
8035 WINED3DRS_FOGSTART
,
8036 WINED3DRS_FOGTABLEMODE
,
8037 WINED3DRS_FOGVERTEXMODE
,
8038 WINED3DRS_INDEXEDVERTEXBLENDENABLE
,
8039 WINED3DRS_LIGHTING
,
8040 WINED3DRS_LOCALVIEWER
,
8041 WINED3DRS_MULTISAMPLEANTIALIAS
,
8042 WINED3DRS_MULTISAMPLEMASK
,
8043 WINED3DRS_NORMALIZENORMALS
,
8044 WINED3DRS_PATCHEDGESTYLE
,
8045 WINED3DRS_POINTSCALE_A
,
8046 WINED3DRS_POINTSCALE_B
,
8047 WINED3DRS_POINTSCALE_C
,
8048 WINED3DRS_POINTSCALEENABLE
,
8049 WINED3DRS_POINTSIZE
,
8050 WINED3DRS_POINTSIZE_MAX
,
8051 WINED3DRS_POINTSIZE_MIN
,
8052 WINED3DRS_POINTSPRITEENABLE
,
8053 WINED3DRS_RANGEFOGENABLE
,
8054 WINED3DRS_SPECULARMATERIALSOURCE
,
8055 WINED3DRS_TWEENFACTOR
,
8056 WINED3DRS_VERTEXBLEND
8059 const DWORD SavedVertexStates_T
[NUM_SAVEDVERTEXSTATES_T
] = {
8060 WINED3DTSS_TEXCOORDINDEX
,
8061 WINED3DTSS_TEXTURETRANSFORMFLAGS
8064 const DWORD SavedVertexStates_S
[NUM_SAVEDVERTEXSTATES_S
] = {
8065 WINED3DSAMP_DMAPOFFSET