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 /* Memory tracking and object counting */
74 static unsigned int emulated_textureram = 64*1024*1024;
76 /* TODO: setup some flags in the regestry to enable, disable pbuffer support */
77 /* enable pbuffer support for offscreen textures */
78 BOOL pbuffer_support = FALSE;
79 /* allocate one pbuffer per surface */
80 BOOL pbuffer_per_surface = FALSE;
82 /* static function declarations */
83 static void WINAPI IWineD3DDeviceImpl_AddResource(IWineD3DDevice *iface, IWineD3DResource *resource);
85 static void WINAPI IWineD3DDeviceImpl_ApplyTextureUnitState(IWineD3DDevice *iface, DWORD Stage, WINED3DTEXTURESTAGESTATETYPE Type);
88 #define D3DMEMCHECK(object, ppResult) if(NULL == object) { *ppResult = NULL; WARN("Out of memory\n"); return WINED3DERR_OUTOFVIDEOMEMORY;}
90 #define D3DCREATEOBJECTINSTANCE(object, type) { \
91 object=HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(IWineD3D##type##Impl)); \
92 D3DMEMCHECK(object, pp##type); \
93 object->lpVtbl = &IWineD3D##type##_Vtbl; \
94 object->wineD3DDevice = This; \
95 object->parent = parent; \
97 *pp##type = (IWineD3D##type *) object; \
100 #define D3DCREATERESOURCEOBJECTINSTANCE(object, type, d3dtype, _size){ \
101 object=HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(IWineD3D##type##Impl)); \
102 D3DMEMCHECK(object, pp##type); \
103 object->lpVtbl = &IWineD3D##type##_Vtbl; \
104 object->resource.wineD3DDevice = This; \
105 object->resource.parent = parent; \
106 object->resource.resourceType = d3dtype; \
107 object->resource.ref = 1; \
108 object->resource.pool = Pool; \
109 object->resource.format = Format; \
110 object->resource.usage = Usage; \
111 object->resource.size = _size; \
112 /* Check that we have enough video ram left */ \
113 if (Pool == WINED3DPOOL_DEFAULT) { \
114 if (IWineD3DDevice_GetAvailableTextureMem(iface) <= _size) { \
115 WARN("Out of 'bogus' video memory\n"); \
116 HeapFree(GetProcessHeap(), 0, object); \
118 return WINED3DERR_OUTOFVIDEOMEMORY; \
120 globalChangeGlRam(_size); \
122 object->resource.allocatedMemory = (0 == _size ? NULL : Pool == WINED3DPOOL_DEFAULT ? NULL : HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, _size)); \
123 if (object->resource.allocatedMemory == NULL && _size != 0 && Pool != WINED3DPOOL_DEFAULT) { \
124 FIXME("Out of memory!\n"); \
125 HeapFree(GetProcessHeap(), 0, object); \
127 return WINED3DERR_OUTOFVIDEOMEMORY; \
129 *pp##type = (IWineD3D##type *) object; \
130 IWineD3DDeviceImpl_AddResource(iface, (IWineD3DResource *)object) ;\
131 TRACE("(%p) : Created resource %p\n", This, object); \
134 #define D3DINITIALIZEBASETEXTURE(_basetexture) { \
135 _basetexture.levels = Levels; \
136 _basetexture.filterType = (Usage & WINED3DUSAGE_AUTOGENMIPMAP) ? WINED3DTEXF_LINEAR : WINED3DTEXF_NONE; \
137 _basetexture.LOD = 0; \
138 _basetexture.dirty = TRUE; \
141 /**********************************************************
142 * Global variable / Constants follow
143 **********************************************************/
144 const float identity[16] = {1,0,0,0, 0,1,0,0, 0,0,1,0, 0,0,0,1}; /* When needed for comparisons */
146 /**********************************************************
147 * Utility functions follow
148 **********************************************************/
149 /* Convert the D3DLIGHT properties into equivalent gl lights */
150 static void setup_light(IWineD3DDevice *iface, LONG Index, PLIGHTINFOEL *lightInfo) {
153 float colRGBA[] = {0.0, 0.0, 0.0, 0.0};
154 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
156 /* Light settings are affected by the model view in OpenGL, the View transform in direct3d*/
157 glMatrixMode(GL_MODELVIEW);
159 glLoadMatrixf((float *)&This->stateBlock->transforms[D3DTS_VIEW].u.m[0][0]);
162 colRGBA[0] = lightInfo->OriginalParms.Diffuse.r;
163 colRGBA[1] = lightInfo->OriginalParms.Diffuse.g;
164 colRGBA[2] = lightInfo->OriginalParms.Diffuse.b;
165 colRGBA[3] = lightInfo->OriginalParms.Diffuse.a;
166 glLightfv(GL_LIGHT0+Index, GL_DIFFUSE, colRGBA);
167 checkGLcall("glLightfv");
170 colRGBA[0] = lightInfo->OriginalParms.Specular.r;
171 colRGBA[1] = lightInfo->OriginalParms.Specular.g;
172 colRGBA[2] = lightInfo->OriginalParms.Specular.b;
173 colRGBA[3] = lightInfo->OriginalParms.Specular.a;
174 glLightfv(GL_LIGHT0+Index, GL_SPECULAR, colRGBA);
175 checkGLcall("glLightfv");
178 colRGBA[0] = lightInfo->OriginalParms.Ambient.r;
179 colRGBA[1] = lightInfo->OriginalParms.Ambient.g;
180 colRGBA[2] = lightInfo->OriginalParms.Ambient.b;
181 colRGBA[3] = lightInfo->OriginalParms.Ambient.a;
182 glLightfv(GL_LIGHT0+Index, GL_AMBIENT, colRGBA);
183 checkGLcall("glLightfv");
185 /* Attenuation - Are these right? guessing... */
186 glLightf(GL_LIGHT0+Index, GL_CONSTANT_ATTENUATION, lightInfo->OriginalParms.Attenuation0);
187 checkGLcall("glLightf");
188 glLightf(GL_LIGHT0+Index, GL_LINEAR_ATTENUATION, lightInfo->OriginalParms.Attenuation1);
189 checkGLcall("glLightf");
191 if ((lightInfo->OriginalParms.Range *lightInfo->OriginalParms.Range) >= FLT_MIN) {
192 quad_att = 1.4/(lightInfo->OriginalParms.Range *lightInfo->OriginalParms.Range);
194 quad_att = 0; /* 0 or MAX? (0 seems to be ok) */
197 if (quad_att < lightInfo->OriginalParms.Attenuation2) quad_att = lightInfo->OriginalParms.Attenuation2;
198 glLightf(GL_LIGHT0+Index, GL_QUADRATIC_ATTENUATION, quad_att);
199 checkGLcall("glLightf");
201 switch (lightInfo->OriginalParms.Type) {
204 glLightfv(GL_LIGHT0+Index, GL_POSITION, &lightInfo->lightPosn[0]);
205 checkGLcall("glLightfv");
206 glLightf(GL_LIGHT0 + Index, GL_SPOT_CUTOFF, lightInfo->cutoff);
207 checkGLcall("glLightf");
213 glLightfv(GL_LIGHT0+Index, GL_POSITION, &lightInfo->lightPosn[0]);
214 checkGLcall("glLightfv");
216 glLightfv(GL_LIGHT0+Index, GL_SPOT_DIRECTION, &lightInfo->lightDirn[0]);
217 checkGLcall("glLightfv");
218 glLightf(GL_LIGHT0 + Index, GL_SPOT_EXPONENT, lightInfo->exponent);
219 checkGLcall("glLightf");
220 glLightf(GL_LIGHT0 + Index, GL_SPOT_CUTOFF, lightInfo->cutoff);
221 checkGLcall("glLightf");
225 case D3DLIGHT_DIRECTIONAL:
227 glLightfv(GL_LIGHT0+Index, GL_POSITION, &lightInfo->lightPosn[0]); /* Note gl uses w position of 0 for direction! */
228 checkGLcall("glLightfv");
229 glLightf(GL_LIGHT0+Index, GL_SPOT_CUTOFF, lightInfo->cutoff);
230 checkGLcall("glLightf");
231 glLightf(GL_LIGHT0+Index, GL_SPOT_EXPONENT, 0.0f);
232 checkGLcall("glLightf");
236 FIXME("Unrecognized light type %d\n", lightInfo->OriginalParms.Type);
239 /* Restore the modelview matrix */
243 /**********************************************************
244 * GLSL helper functions follow
245 **********************************************************/
247 /** Attach a GLSL pixel or vertex shader object to the shader program */
248 static void attach_glsl_shader(IWineD3DDevice *iface, IWineD3DBaseShader* shader) {
250 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
251 GLhandleARB shaderObj = ((IWineD3DBaseShaderImpl*)shader)->baseShader.prgId;
252 if (This->stateBlock->shaderPrgId != 0 && shaderObj != 0) {
253 TRACE_(d3d_shader)("Attaching GLSL shader object %u to program %u\n", shaderObj, This->stateBlock->shaderPrgId);
254 GL_EXTCALL(glAttachObjectARB(This->stateBlock->shaderPrgId, shaderObj));
255 checkGLcall("glAttachObjectARB");
259 /** Sets the GLSL program ID for the given pixel and vertex shader combination.
260 * It sets the programId on the current StateBlock (because it should be called
261 * inside of the DrawPrimitive() part of the render loop).
263 * If a program for the given combination does not exist, create one, and store
264 * the program in the list. If it creates a program, it will link the given
267 * We keep the shader programs around on a list because linking
268 * shader objects together is an expensive operation. It's much
269 * faster to loop through a list of pre-compiled & linked programs
270 * each time that the application sets a new pixel or vertex shader
271 * than it is to re-link them together at that time.
273 * The list will be deleted in IWineD3DDevice::Release().
275 void set_glsl_shader_program(IWineD3DDevice *iface) {
277 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
278 IWineD3DPixelShader *pshader = This->stateBlock->pixelShader;
279 IWineD3DVertexShader *vshader = This->stateBlock->vertexShader;
280 struct glsl_shader_prog_link *curLink = NULL;
281 struct glsl_shader_prog_link *newLink = NULL;
282 struct list *ptr = NULL;
283 GLhandleARB programId = 0;
285 ptr = list_head( &This->glsl_shader_progs );
287 /* At least one program exists - see if it matches our ps/vs combination */
288 curLink = LIST_ENTRY( ptr, struct glsl_shader_prog_link, entry );
289 if (vshader == curLink->vertexShader && pshader == curLink->pixelShader) {
290 /* Existing Program found, use it */
291 TRACE_(d3d_shader)("Found existing program (%u) for this vertex/pixel shader combination\n",
293 This->stateBlock->shaderPrgId = curLink->programId;
296 /* This isn't the entry we need - try the next one */
297 ptr = list_next( &This->glsl_shader_progs, ptr );
300 /* If we get to this point, then no matching program exists, so we create one */
301 programId = GL_EXTCALL(glCreateProgramObjectARB());
302 TRACE_(d3d_shader)("Created new GLSL shader program %u\n", programId);
303 This->stateBlock->shaderPrgId = programId;
305 /* Allocate a new link for the list of programs */
306 newLink = HeapAlloc(GetProcessHeap(), 0, sizeof(struct glsl_shader_prog_link));
307 newLink->programId = programId;
309 /* Attach GLSL vshader */
310 if (NULL != vshader && wined3d_settings.vs_selected_mode == SHADER_GLSL) {
312 int max_attribs = 16; /* TODO: Will this always be the case? It is at the moment... */
315 TRACE("Attaching vertex shader to GLSL program\n");
316 attach_glsl_shader(iface, (IWineD3DBaseShader*)vshader);
318 /* Bind vertex attributes to a corresponding index number to match
319 * the same index numbers as ARB_vertex_programs (makes loading
320 * vertex attributes simpler). With this method, we can use the
321 * exact same code to load the attributes later for both ARB and
324 * We have to do this here because we need to know the Program ID
325 * in order to make the bindings work, and it has to be done prior
326 * to linking the GLSL program. */
327 for (i = 0; i < max_attribs; ++i) {
328 snprintf(tmp_name, sizeof(tmp_name), "attrib%i", i);
329 GL_EXTCALL(glBindAttribLocationARB(programId, i, tmp_name));
331 checkGLcall("glBindAttribLocationARB");
332 newLink->vertexShader = vshader;
335 /* Attach GLSL pshader */
336 if (NULL != pshader && wined3d_settings.ps_selected_mode == SHADER_GLSL) {
337 TRACE("Attaching pixel shader to GLSL program\n");
338 attach_glsl_shader(iface, (IWineD3DBaseShader*)pshader);
339 newLink->pixelShader = pshader;
342 /* Link the program */
343 TRACE_(d3d_shader)("Linking GLSL shader program %u\n", programId);
344 GL_EXTCALL(glLinkProgramARB(programId));
345 print_glsl_info_log(&GLINFO_LOCATION, programId);
346 list_add_head( &This->glsl_shader_progs, &newLink->entry);
350 /** Detach the GLSL pixel or vertex shader object from the shader program */
351 static void detach_glsl_shader(IWineD3DDevice *iface, GLhandleARB shaderObj, GLhandleARB programId) {
353 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
355 if (shaderObj != 0 && programId != 0) {
356 TRACE_(d3d_shader)("Detaching GLSL shader object %u from program %u\n", shaderObj, programId);
357 GL_EXTCALL(glDetachObjectARB(programId, shaderObj));
358 checkGLcall("glDetachObjectARB");
362 /** Delete a GLSL shader program */
363 static void delete_glsl_shader_program(IWineD3DDevice *iface, GLhandleARB obj) {
365 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
368 TRACE_(d3d_shader)("Deleting GLSL shader program %u\n", obj);
369 GL_EXTCALL(glDeleteObjectARB(obj));
370 checkGLcall("glDeleteObjectARB");
374 /** Delete the list of linked programs this shader is associated with.
375 * Also at this point, check to see if there are any objects left attached
376 * to each GLSL program. If not, delete the GLSL program object.
377 * This will be run when a device is released. */
378 static void delete_glsl_shader_list(IWineD3DDevice* iface) {
380 struct list *ptr = NULL;
381 struct glsl_shader_prog_link *curLink = NULL;
382 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
386 GLhandleARB objList[2]; /* There should never be more than 2 objects attached
387 (one pixel shader and one vertex shader at most) */
389 ptr = list_head( &This->glsl_shader_progs );
391 /* First, get the current item,
392 * save the link to the next pointer,
393 * detach and delete shader objects,
394 * then de-allocate the list item's memory */
395 curLink = LIST_ENTRY( ptr, struct glsl_shader_prog_link, entry );
396 ptr = list_next( &This->glsl_shader_progs, ptr );
398 /* See if this object is still attached to the program - it may have been detached already */
399 GL_EXTCALL(glGetAttachedObjectsARB(curLink->programId, 2, &numAttached, objList));
400 TRACE_(d3d_shader)("%i GLSL objects are currently attached to program %u\n", numAttached, curLink->programId);
401 for (i = 0; i < numAttached; i++) {
402 detach_glsl_shader(iface, objList[i], curLink->programId);
405 delete_glsl_shader_program(iface, curLink->programId);
407 /* Free the memory for this list item */
408 HeapFree(GetProcessHeap(), 0, curLink);
413 /* Apply the current values to the specified texture stage */
414 static void WINAPI IWineD3DDeviceImpl_SetupTextureStates(IWineD3DDevice *iface, DWORD Sampler, DWORD texture_idx, DWORD Flags) {
415 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
423 /* In addition, IDirect3DDevice9::SetSamplerState will now be used for filtering, tiling,
424 clamping, MIPLOD, etc. This will work for up to 16 samplers.
427 if (Sampler >= GL_LIMITS(sampler_stages)) {
428 FIXME("Trying to set the state of more samplers %ld than are supported %d by this openGL implementation\n", Sampler, GL_LIMITS(sampler_stages));
431 VTRACE(("Activating appropriate texture state %ld\n", Sampler));
432 if (GL_SUPPORT(ARB_MULTITEXTURE)) {
434 GL_EXTCALL(glActiveTextureARB(GL_TEXTURE0_ARB + texture_idx));
435 checkGLcall("glActiveTextureARB");
437 /* Could we use bindTexture and then apply the states instead of GLACTIVETEXTURE */
438 } else if (Sampler > 0) {
439 FIXME("Program using multiple concurrent textures which this opengl implementation doesn't support\n");
443 /* TODO: change this to a lookup table
444 LOOKUP_TEXTURE_STATES lists all texture states that should be applied.
445 LOOKUP_CONTEXT_SATES list all context applicable states that can be applied
446 etc.... it's a lot cleaner, quicker and possibly easier to maintain than running a switch and setting a skip flag...
447 especially when there are a number of groups of states. */
449 TRACE("-----------------------> Updating the texture at Sampler %ld to have new texture state information\n", Sampler);
451 /* 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 */
452 #define APPLY_STATE(_state) IWineD3DDeviceImpl_ApplyTextureUnitState(iface, Sampler, _state)
453 /* these are the only two supported states that need to be applied */
454 APPLY_STATE(WINED3DTSS_TEXCOORDINDEX);
455 APPLY_STATE(WINED3DTSS_TEXTURETRANSFORMFLAGS);
456 #if 0 /* not supported at the moment */
457 APPLY_STATE(WINED3DTSS_BUMPENVMAT00);
458 APPLY_STATE(WINED3DTSS_BUMPENVMAT01);
459 APPLY_STATE(WINED3DTSS_BUMPENVMAT10);
460 APPLY_STATE(WINED3DTSS_BUMPENVMAT11);
461 APPLY_STATE(WINED3DTSS_BUMPENVLSCALE);
462 APPLY_STATE(WINED3DTSS_BUMPENVLOFFSET);
463 APPLY_STATE(WINED3DTSS_RESULTARG);
464 APPLY_STATE(WINED3DTSS_CONSTANT);
466 /* a quick sanity check in case someone forgot to update this function */
467 if (WINED3D_HIGHEST_TEXTURE_STATE > WINED3DTSS_CONSTANT) {
468 FIXME("(%p) : There are more texture states than expected, update device.c to match\n", This);
472 /* apply any sampler states that always need applying */
473 if (GL_SUPPORT(EXT_TEXTURE_LOD_BIAS)) {
474 tmpvalue.d = This->stateBlock->samplerState[Sampler][WINED3DSAMP_MIPMAPLODBIAS];
475 glTexEnvf(GL_TEXTURE_FILTER_CONTROL_EXT,
476 GL_TEXTURE_LOD_BIAS_EXT,
478 checkGLcall("glTexEnvi GL_TEXTURE_LOD_BIAS_EXT ...");
481 /* Note the D3DRS value applies to all textures, but GL has one
482 * per texture, so apply it now ready to be used!
484 D3DCOLORTOGLFLOAT4(This->stateBlock->renderState[WINED3DRS_TEXTUREFACTOR], col);
485 /* Set the default alpha blend color */
486 if (GL_SUPPORT(ARB_IMAGING)) {
487 GL_EXTCALL(glBlendColor(col[0], col[1], col[2], col[3]));
488 checkGLcall("glBlendColor");
490 WARN("Unsupported in local OpenGL implementation: glBlendColor\n");
493 D3DCOLORTOGLFLOAT4(This->stateBlock->renderState[WINED3DRS_TEXTUREFACTOR], col);
494 glTexEnvfv(GL_TEXTURE_ENV, GL_TEXTURE_ENV_COLOR, &col[0]);
495 checkGLcall("glTexEnvfv(GL_TEXTURE_ENV, GL_TEXTURE_ENV_COLOR, color);");
497 /* TODO: NV_POINT_SPRITE */
498 if (GL_SUPPORT(ARB_POINT_SPRITE)) {
499 if (This->stateBlock->renderState[WINED3DRS_POINTSPRITEENABLE] != FALSE) {
500 /* Doesn't work with GL_POINT_SMOOTH on on my ATI 9600, but then ATI drivers are buggered! */
501 glDisable(GL_POINT_SMOOTH);
503 /* Centre the texture on the vertex */
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);
507 VTRACE(("glTexEnvf( GL_POINT_SPRITE_ARB, GL_COORD_REPLACE_ARB, GL_TRUE)\n"));
508 glTexEnvf( GL_POINT_SPRITE_ARB, GL_COORD_REPLACE_ARB, GL_TRUE);
509 checkGLcall("glTexEnvf(...)");
510 VTRACE(("glEnable( GL_POINT_SPRITE_ARB )\n"));
511 glEnable( GL_POINT_SPRITE_ARB );
512 checkGLcall("glEnable(...)");
514 VTRACE(("glDisable( GL_POINT_SPRITE_ARB )\n"));
515 glDisable( GL_POINT_SPRITE_ARB );
516 checkGLcall("glEnable(...)");
520 TRACE("-----------------------> Updated the texture at Sampler %ld to have new texture state information\n", Sampler);
523 /**********************************************************
524 * IUnknown parts follows
525 **********************************************************/
527 static HRESULT WINAPI IWineD3DDeviceImpl_QueryInterface(IWineD3DDevice *iface,REFIID riid,LPVOID *ppobj)
529 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
531 TRACE("(%p)->(%s,%p)\n",This,debugstr_guid(riid),ppobj);
532 if (IsEqualGUID(riid, &IID_IUnknown)
533 || IsEqualGUID(riid, &IID_IWineD3DBase)
534 || IsEqualGUID(riid, &IID_IWineD3DDevice)) {
535 IUnknown_AddRef(iface);
540 return E_NOINTERFACE;
543 static ULONG WINAPI IWineD3DDeviceImpl_AddRef(IWineD3DDevice *iface) {
544 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
545 ULONG refCount = InterlockedIncrement(&This->ref);
547 TRACE("(%p) : AddRef increasing from %ld\n", This, refCount - 1);
551 static ULONG WINAPI IWineD3DDeviceImpl_Release(IWineD3DDevice *iface) {
552 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
553 ULONG refCount = InterlockedDecrement(&This->ref);
555 TRACE("(%p) : Releasing from %ld\n", This, refCount + 1);
558 /* TODO: Clean up all the surfaces and textures! */
559 /* NOTE: You must release the parent if the object was created via a callback
560 ** ***************************/
562 /* Delete any GLSL shader programs that may exist */
563 if (wined3d_settings.vs_selected_mode == SHADER_GLSL ||
564 wined3d_settings.ps_selected_mode == SHADER_GLSL)
565 delete_glsl_shader_list(iface);
567 /* Release the update stateblock */
568 if(IWineD3DStateBlock_Release((IWineD3DStateBlock *)This->updateStateBlock) > 0){
569 if(This->updateStateBlock != This->stateBlock)
570 FIXME("(%p) Something's still holding the Update stateblock\n",This);
572 This->updateStateBlock = NULL;
573 { /* because were not doing proper internal refcounts releasing the primary state block
574 causes recursion with the extra checks in ResourceReleased, to avoid this we have
575 to set this->stateBlock = NULL; first */
576 IWineD3DStateBlock *stateBlock = (IWineD3DStateBlock *)This->stateBlock;
577 This->stateBlock = NULL;
579 /* Release the stateblock */
580 if(IWineD3DStateBlock_Release(stateBlock) > 0){
581 FIXME("(%p) Something's still holding the Update stateblock\n",This);
585 if (This->resources != NULL ) {
586 FIXME("(%p) Device released with resources still bound, acceptable but unexpected\n", This);
587 dumpResources(This->resources);
591 IWineD3D_Release(This->wineD3D);
592 This->wineD3D = NULL;
593 HeapFree(GetProcessHeap(), 0, This);
594 TRACE("Freed device %p\n", This);
600 /**********************************************************
601 * IWineD3DDevice implementation follows
602 **********************************************************/
603 static HRESULT WINAPI IWineD3DDeviceImpl_GetParent(IWineD3DDevice *iface, IUnknown **pParent) {
604 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
605 *pParent = This->parent;
606 IUnknown_AddRef(This->parent);
610 static void CreateVBO(IWineD3DVertexBufferImpl *object) {
611 IWineD3DDeviceImpl *This = object->resource.wineD3DDevice; /* Needed for GL_EXTCALL */
612 GLenum error, glUsage;
613 DWORD vboUsage = object->resource.usage;
614 TRACE("Creating an OpenGL vertex buffer object for IWineD3DVertexBuffer %p\n", object);
617 /* Make sure that the gl error is cleared. Do not use checkGLcall
618 * here because checkGLcall just prints a fixme and continues. However,
619 * if an error during VBO creation occurs we can fall back to non-vbo operation
620 * with full functionality(but performance loss)
622 while(glGetError() != GL_NO_ERROR);
624 /* Basically the FVF parameter passed to CreateVertexBuffer is no good
625 * It is the FVF set with IWineD3DDevice::SetFVF or the Vertex Declaration set with
626 * IWineD3DDevice::SetVertexDeclaration that decides how the vertices in the buffer
627 * look like. This means that on each DrawPrimitive call the vertex buffer has to be verified
628 * to check if the rhw and color values are in the correct format.
631 GL_EXTCALL(glGenBuffersARB(1, &object->vbo));
632 error = glGetError();
633 if(object->vbo == 0 || error != GL_NO_ERROR) {
634 WARN("Failed to create a VBO with error %d\n", error);
638 GL_EXTCALL(glBindBufferARB(GL_ARRAY_BUFFER_ARB, object->vbo));
639 error = glGetError();
640 if(error != GL_NO_ERROR) {
641 WARN("Failed to bind the VBO, error %d\n", error);
645 /* Transformed vertices are horribly inflexible. If the app specifies an
646 * vertex buffer with transformed vertices in default pool without DYNAMIC
647 * usage assume DYNAMIC usage and print a warning. The app will have to update
648 * the vertices regularily for them to be useful
650 if(((object->fvf & D3DFVF_POSITION_MASK) == D3DFVF_XYZRHW) &&
651 !(vboUsage & WINED3DUSAGE_DYNAMIC)) {
652 WARN("Application creates a vertex buffer holding transformed vertices which doesn't specify dynamic usage\n");
653 vboUsage |= WINED3DUSAGE_DYNAMIC;
656 /* Don't use static, because dx apps tend to update the buffer
657 * quite often even if they specify 0 usage
659 switch(vboUsage & (D3DUSAGE_WRITEONLY | D3DUSAGE_DYNAMIC) ) {
660 case D3DUSAGE_WRITEONLY | D3DUSAGE_DYNAMIC:
661 TRACE("Gl usage = GL_STREAM_DRAW\n");
662 glUsage = GL_STREAM_DRAW_ARB;
664 case D3DUSAGE_WRITEONLY:
665 TRACE("Gl usage = GL_STATIC_DRAW\n");
666 glUsage = GL_DYNAMIC_DRAW_ARB;
668 case D3DUSAGE_DYNAMIC:
669 TRACE("Gl usage = GL_STREAM_COPY\n");
670 glUsage = GL_STREAM_COPY_ARB;
673 TRACE("Gl usage = GL_STATIC_COPY\n");
674 glUsage = GL_DYNAMIC_COPY_ARB;
678 /* Reserve memory for the buffer. The amount of data won't change
679 * so we are safe with calling glBufferData once with a NULL ptr and
680 * calling glBufferSubData on updates
682 GL_EXTCALL(glBufferDataARB(GL_ARRAY_BUFFER_ARB, object->resource.size, NULL, glUsage));
683 error = glGetError();
684 if(error != GL_NO_ERROR) {
685 WARN("glBufferDataARB failed with error %d\n", error);
693 /* Clean up all vbo init, but continue because we can work without a vbo :-) */
694 FIXME("Failed to create a vertex buffer object. Continuing, but performance issues can occur\n");
695 if(object->vbo) GL_EXTCALL(glDeleteBuffersARB(1, &object->vbo));
701 static HRESULT WINAPI IWineD3DDeviceImpl_CreateVertexBuffer(IWineD3DDevice *iface, UINT Size, DWORD Usage,
702 DWORD FVF, WINED3DPOOL Pool, IWineD3DVertexBuffer** ppVertexBuffer, HANDLE *sharedHandle,
704 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
705 IWineD3DVertexBufferImpl *object;
706 WINED3DFORMAT Format = WINED3DFMT_VERTEXDATA; /* Dummy format for now */
707 int dxVersion = ( (IWineD3DImpl *) This->wineD3D)->dxVersion;
709 D3DCREATERESOURCEOBJECTINSTANCE(object, VertexBuffer, WINED3DRTYPE_VERTEXBUFFER, Size)
711 TRACE("(%p) : Size=%d, Usage=%ld, FVF=%lx, Pool=%d - Memory@%p, Iface@%p\n", This, Size, Usage, FVF, Pool, object->resource.allocatedMemory, object);
712 *ppVertexBuffer = (IWineD3DVertexBuffer *)object;
714 if(Size == 0) return WINED3DERR_INVALIDCALL;
716 if (Pool == WINED3DPOOL_DEFAULT ) { /* Allocate some system memory for now */
717 object->resource.allocatedMemory = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, object->resource.size);
721 /* Observations show that drawStridedSlow is faster on dynamic VBs than converting +
722 * drawStridedFast (half-life 2).
724 * Basically converting the vertices in the buffer is quite expensive, and observations
725 * show that drawStridedSlow is faster than converting + uploading + drawStridedFast.
726 * Therefore do not create a VBO for WINED3DUSAGE_DYNAMIC buffers.
728 * Direct3D7 has another problem: Its vertexbuffer api doesn't offer a way to specify
729 * the range of vertices beeing locked, so each lock will require the whole buffer to be transformed.
730 * Moreover geometry data in dx7 is quite simple, so drawStridedSlow isn't a big hit. A plus
731 * is that the vertex buffers fvf can be trusted in dx7. So only create non-converted vbos for
733 * There is a IDirect3DVertexBuffer7::Optimize call after which the buffer can't be locked any
734 * more. In this call we can convert dx7 buffers too.
736 conv = ((FVF & D3DFVF_POSITION_MASK) == D3DFVF_XYZRHW ) || (FVF & (D3DFVF_DIFFUSE | D3DFVF_SPECULAR));
737 if( GL_SUPPORT(ARB_VERTEX_BUFFER_OBJECT) && Pool != WINED3DPOOL_SYSTEMMEM && !(Usage & WINED3DUSAGE_DYNAMIC) &&
738 (dxVersion > 7 || !conv) ) {
741 /* DX7 buffers can be locked directly into the VBO(no conversion, see above */
742 if(dxVersion == 7 && object->vbo) {
743 HeapFree(GetProcessHeap(), 0, object->resource.allocatedMemory);
744 object->resource.allocatedMemory = NULL;
751 static HRESULT WINAPI IWineD3DDeviceImpl_CreateIndexBuffer(IWineD3DDevice *iface, UINT Length, DWORD Usage,
752 WINED3DFORMAT Format, WINED3DPOOL Pool, IWineD3DIndexBuffer** ppIndexBuffer,
753 HANDLE *sharedHandle, IUnknown *parent) {
754 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
755 IWineD3DIndexBufferImpl *object;
756 TRACE("(%p) Creating index buffer\n", This);
758 /* Allocate the storage for the device */
759 D3DCREATERESOURCEOBJECTINSTANCE(object,IndexBuffer,WINED3DRTYPE_INDEXBUFFER, Length)
762 if (Pool == WINED3DPOOL_DEFAULT ) { /* Allocate some system memory for now */
763 object->resource.allocatedMemory = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,object->resource.size);
766 TRACE("(%p) : Len=%d, Use=%lx, Format=(%u,%s), Pool=%d - Memory@%p, Iface@%p\n", This, Length, Usage, Format,
767 debug_d3dformat(Format), Pool, object, object->resource.allocatedMemory);
768 *ppIndexBuffer = (IWineD3DIndexBuffer *) object;
773 static HRESULT WINAPI IWineD3DDeviceImpl_CreateStateBlock(IWineD3DDevice* iface, WINED3DSTATEBLOCKTYPE Type, IWineD3DStateBlock** ppStateBlock, IUnknown *parent) {
775 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
776 IWineD3DStateBlockImpl *object;
779 D3DCREATEOBJECTINSTANCE(object, StateBlock)
780 object->blockType = Type;
782 /* Special case - Used during initialization to produce a placeholder stateblock
783 so other functions called can update a state block */
784 if (Type == WINED3DSBT_INIT) {
785 /* Don't bother increasing the reference count otherwise a device will never
786 be freed due to circular dependencies */
790 /* Otherwise, might as well set the whole state block to the appropriate values */
791 if ( This->stateBlock != NULL) {
792 memcpy(object, This->stateBlock, sizeof(IWineD3DStateBlockImpl));
794 memset(object->streamFreq, 1, sizeof(object->streamFreq));
797 /* Reset the ref and type after kludging it */
798 object->wineD3DDevice = This;
800 object->blockType = Type;
802 TRACE("Updating changed flags appropriate for type %d\n", Type);
804 if (Type == WINED3DSBT_ALL) {
806 TRACE("ALL => Pretend everything has changed\n");
807 memset(&object->changed, TRUE, sizeof(This->stateBlock->changed));
808 } else if (Type == WINED3DSBT_PIXELSTATE) {
810 TRACE("PIXELSTATE => Pretend all pixel shates have changed\n");
811 memset(&object->changed, FALSE, sizeof(This->stateBlock->changed));
813 object->changed.pixelShader = TRUE;
815 /* Pixel Shader Constants */
816 for (i = 0; i < MAX_PSHADER_CONSTANTS; ++i) {
817 object->changed.pixelShaderConstantsF[i] = TRUE;
818 object->changed.pixelShaderConstantsB[i] = TRUE;
819 object->changed.pixelShaderConstantsI[i] = TRUE;
821 for (i = 0; i < NUM_SAVEDPIXELSTATES_R; i++) {
822 object->changed.renderState[SavedPixelStates_R[i]] = TRUE;
824 for (j = 0; j < GL_LIMITS(texture_stages); j++) {
825 for (i = 0; i < NUM_SAVEDPIXELSTATES_T; i++) {
826 object->changed.textureState[j][SavedPixelStates_T[i]] = TRUE;
829 for (j = 0 ; j < 16; j++) {
830 for (i =0; i < NUM_SAVEDPIXELSTATES_S;i++) {
832 object->changed.samplerState[j][SavedPixelStates_S[i]] = TRUE;
836 } else if (Type == WINED3DSBT_VERTEXSTATE) {
838 TRACE("VERTEXSTATE => Pretend all vertex shates have changed\n");
839 memset(&object->changed, FALSE, sizeof(This->stateBlock->changed));
841 object->changed.vertexShader = TRUE;
843 /* Vertex Shader Constants */
844 for (i = 0; i < MAX_VSHADER_CONSTANTS; ++i) {
845 object->changed.vertexShaderConstantsF[i] = TRUE;
846 object->changed.vertexShaderConstantsB[i] = TRUE;
847 object->changed.vertexShaderConstantsI[i] = TRUE;
849 for (i = 0; i < NUM_SAVEDVERTEXSTATES_R; i++) {
850 object->changed.renderState[SavedVertexStates_R[i]] = TRUE;
852 for (j = 0; j < GL_LIMITS(texture_stages); j++) {
853 for (i = 0; i < NUM_SAVEDVERTEXSTATES_T; i++) {
854 object->changed.textureState[j][SavedVertexStates_T[i]] = TRUE;
857 for (j = 0 ; j < 16; j++){
858 for (i =0; i < NUM_SAVEDVERTEXSTATES_S;i++) {
859 object->changed.samplerState[j][SavedVertexStates_S[i]] = TRUE;
863 /* Duplicate light chain */
865 PLIGHTINFOEL *src = NULL;
866 PLIGHTINFOEL *dst = NULL;
867 PLIGHTINFOEL *newEl = NULL;
868 src = This->stateBlock->lights;
869 object->lights = NULL;
873 newEl = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(PLIGHTINFOEL));
874 if (newEl == NULL) return WINED3DERR_OUTOFVIDEOMEMORY;
875 memcpy(newEl, src, sizeof(PLIGHTINFOEL));
877 newEl->changed = TRUE;
878 newEl->enabledChanged = TRUE;
880 object->lights = newEl;
891 FIXME("Unrecognized state block type %d\n", Type);
894 TRACE("(%p) returning token (ptr to stateblock) of %p\n", This, object);
899 /* ************************************
901 [in] Render targets are not lockable unless the application specifies TRUE for Lockable. Note that lockable render targets reduce performance on some graphics hardware.
904 [in] Set this flag to TRUE to enable z-buffer discarding, and FALSE otherwise.
906 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.
908 ******************************** */
910 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) {
911 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
912 IWineD3DSurfaceImpl *object; /*NOTE: impl ref allowed since this is a create function */
913 unsigned int pow2Width, pow2Height;
914 unsigned int Size = 1;
915 const PixelFormatDesc *tableEntry = getFormatDescEntry(Format);
916 TRACE("(%p) Create surface\n",This);
918 /** FIXME: Check ranges on the inputs are valid
921 * [in] Quality level. The valid range is between zero and one less than the level
922 * returned by pQualityLevels used by IDirect3D9::CheckDeviceMultiSampleType.
923 * Passing a larger value returns the error WINED3DERR_INVALIDCALL. The MultisampleQuality
924 * values of paired render targets, depth stencil surfaces, and the MultiSample type
926 *******************************/
931 * [in] Set this flag to TRUE to enable z-buffer discarding, and FALSE otherwise.
933 * If this flag is set, the contents of the depth stencil buffer will be
934 * invalid after calling either IDirect3DDevice9::Present or * IDirect3DDevice9::SetDepthStencilSurface
935 * with a different depth surface.
937 *This flag has the same behavior as the constant, D3DPRESENTFLAG_DISCARD_DEPTHSTENCIL, in D3DPRESENTFLAG.
938 ***************************/
940 if(MultisampleQuality < 0) {
941 FIXME("Invalid multisample level %ld\n", MultisampleQuality);
942 return WINED3DERR_INVALIDCALL; /* TODO: Check that this is the case! */
945 if(MultisampleQuality > 0) {
946 FIXME("MultisampleQuality set to %ld, substituting 0\n", MultisampleQuality);
947 MultisampleQuality=0;
950 /** FIXME: Check that the format is supported
952 *******************************/
954 /* Non-power2 support */
956 /* Find the nearest pow2 match */
957 pow2Width = pow2Height = 1;
958 while (pow2Width < Width) pow2Width <<= 1;
959 while (pow2Height < Height) pow2Height <<= 1;
961 if (pow2Width > Width || pow2Height > Height) {
962 /** TODO: add support for non power two compressed textures (OpenGL 2 provices support for * non-power-two textures gratis) **/
963 if (Format == WINED3DFMT_DXT1 || Format == WINED3DFMT_DXT2 || Format == WINED3DFMT_DXT3
964 || Format == WINED3DFMT_DXT4 || Format == WINED3DFMT_DXT5) {
965 FIXME("(%p) Compressed non-power-two textures are not supported w(%d) h(%d)\n",
966 This, Width, Height);
967 return WINED3DERR_NOTAVAILABLE;
971 /** DXTn mipmaps use the same number of 'levels' down to eg. 8x1, but since
972 * it is based around 4x4 pixel blocks it requires padding, so allocate enough
974 *********************************/
975 if (WINED3DFMT_UNKNOWN == Format) {
977 } else if (Format == WINED3DFMT_DXT1) {
978 /* DXT1 is half byte per pixel */
979 Size = ((max(pow2Width,4) * tableEntry->bpp) * max(pow2Height,4)) >> 1;
981 } else if (Format == WINED3DFMT_DXT2 || Format == WINED3DFMT_DXT3 ||
982 Format == WINED3DFMT_DXT4 || Format == WINED3DFMT_DXT5) {
983 Size = ((max(pow2Width,4) * tableEntry->bpp) * max(pow2Height,4));
985 Size = (pow2Width * tableEntry->bpp) * pow2Height;
988 /** Create and initialise the surface resource **/
989 D3DCREATERESOURCEOBJECTINSTANCE(object,Surface,WINED3DRTYPE_SURFACE, Size)
990 /* "Standalone" surface */
991 IWineD3DSurface_SetContainer((IWineD3DSurface *)object, NULL);
993 object->currentDesc.Width = Width;
994 object->currentDesc.Height = Height;
995 object->currentDesc.MultiSampleType = MultiSample;
996 object->currentDesc.MultiSampleQuality = MultisampleQuality;
998 /* Setup some glformat defaults */
999 object->glDescription.glFormat = tableEntry->glFormat;
1000 object->glDescription.glFormatInternal = tableEntry->glInternal;
1001 object->glDescription.glType = tableEntry->glType;
1003 object->glDescription.textureName = 0;
1004 object->glDescription.level = Level;
1005 object->glDescription.target = GL_TEXTURE_2D;
1008 object->pow2Width = pow2Width;
1009 object->pow2Height = pow2Height;
1012 object->Flags = 0; /* We start without flags set */
1013 object->Flags |= (pow2Width != Width || pow2Height != Height) ? SFLAG_NONPOW2 : 0;
1014 object->Flags |= Discard ? SFLAG_DISCARD : 0;
1015 object->Flags |= (WINED3DFMT_D16_LOCKABLE == Format) ? SFLAG_LOCKABLE : 0;
1016 object->Flags |= Lockable ? SFLAG_LOCKABLE : 0;
1019 if (WINED3DFMT_UNKNOWN != Format) {
1020 object->bytesPerPixel = tableEntry->bpp;
1021 object->pow2Size = (pow2Width * object->bytesPerPixel) * pow2Height;
1023 object->bytesPerPixel = 0;
1024 object->pow2Size = 0;
1027 /** TODO: change this into a texture transform matrix so that it's processed in hardware **/
1029 TRACE("Pool %d %d %d %d",Pool, WINED3DPOOL_DEFAULT, WINED3DPOOL_MANAGED, WINED3DPOOL_SYSTEMMEM);
1031 /** Quick lockable sanity check TODO: remove this after surfaces, usage and locablility have been debugged properly
1032 * this function is too deap to need to care about things like this.
1033 * Levels need to be checked too, and possibly Type wince they all affect what can be done.
1034 * ****************************************/
1036 case WINED3DPOOL_SCRATCH:
1037 if(Lockable == FALSE)
1038 FIXME("Create suface called with a pool of SCRATCH and a Lockable of FALSE \
1039 which are mutually exclusive, setting lockable to true\n");
1042 case WINED3DPOOL_SYSTEMMEM:
1043 if(Lockable == FALSE) FIXME("Create surface called with a pool of SYSTEMMEM and a Lockable of FALSE, \
1044 this is acceptable but unexpected (I can't know how the surface can be usable!)\n");
1045 case WINED3DPOOL_MANAGED:
1046 if(Usage == WINED3DUSAGE_DYNAMIC) FIXME("Create surface called with a pool of MANAGED and a \
1047 Usage of DYNAMIC which are mutually exclusive, not doing \
1048 anything just telling you.\n");
1050 case WINED3DPOOL_DEFAULT: /*TODO: Create offscreen plain can cause this check to fail..., find out if it should */
1051 if(!(Usage & WINED3DUSAGE_DYNAMIC) && !(Usage & WINED3DUSAGE_RENDERTARGET)
1052 && !(Usage && WINED3DUSAGE_DEPTHSTENCIL ) && Lockable)
1053 WARN("Creating a surface with a POOL of DEFAULT with Lockable true, that doesn't specify DYNAMIC usage.\n");
1056 FIXME("(%p) Unknown pool %d\n", This, Pool);
1060 if (Usage & WINED3DUSAGE_RENDERTARGET && Pool != WINED3DPOOL_DEFAULT) {
1061 FIXME("Trying to create a render target that isn't in the default pool\n");
1064 /* mark the texture as dirty so that it get's loaded first time around*/
1065 IWineD3DSurface_AddDirtyRect(*ppSurface, NULL);
1066 TRACE("(%p) : w(%d) h(%d) fmt(%d,%s) lockable(%d) surf@%p, surfmem@%p, %d bytes\n",
1067 This, Width, Height, Format, debug_d3dformat(Format),
1068 (WINED3DFMT_D16_LOCKABLE == Format), *ppSurface, object->resource.allocatedMemory, object->resource.size);
1070 /* Store the DirectDraw primary surface. This is the first rendertarget surface created */
1071 if( (Usage & WINED3DUSAGE_RENDERTARGET) && (!This->ddraw_primary) )
1072 This->ddraw_primary = (IWineD3DSurface *) object;
1074 /* Look at the implementation and set the correct Vtable */
1076 case SURFACE_OPENGL:
1077 /* Nothing to do, it's set already */
1081 object->lpVtbl = &IWineGDISurface_Vtbl;
1085 /* To be sure to catch this */
1086 ERR("Unknown requested surface implementation %d!\n", Impl);
1087 IWineD3DSurface_Release((IWineD3DSurface *) object);
1088 return WINED3DERR_INVALIDCALL;
1091 /* Call the private setup routine */
1092 return IWineD3DSurface_PrivateSetup( (IWineD3DSurface *) object );
1096 static HRESULT WINAPI IWineD3DDeviceImpl_CreateTexture(IWineD3DDevice *iface, UINT Width, UINT Height, UINT Levels,
1097 DWORD Usage, WINED3DFORMAT Format, WINED3DPOOL Pool,
1098 IWineD3DTexture** ppTexture, HANDLE* pSharedHandle, IUnknown *parent,
1099 D3DCB_CREATESURFACEFN D3DCB_CreateSurface) {
1101 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
1102 IWineD3DTextureImpl *object;
1107 unsigned int pow2Width = Width;
1108 unsigned int pow2Height = Height;
1111 TRACE("(%p), Width(%d) Height(%d) Levels(%d) Usage(%ld) ....\n", This, Width, Height, Levels, Usage);
1113 /* TODO: It should only be possible to create textures for formats
1114 that are reported as supported */
1115 if (WINED3DFMT_UNKNOWN >= Format) {
1116 WARN("(%p) : Texture cannot be created with a format of D3DFMT_UNKNOWN\n", This);
1117 return WINED3DERR_INVALIDCALL;
1120 D3DCREATERESOURCEOBJECTINSTANCE(object, Texture, WINED3DRTYPE_TEXTURE, 0);
1121 D3DINITIALIZEBASETEXTURE(object->baseTexture);
1122 object->width = Width;
1123 object->height = Height;
1125 /** Non-power2 support **/
1126 /* Find the nearest pow2 match */
1127 pow2Width = pow2Height = 1;
1128 while (pow2Width < Width) pow2Width <<= 1;
1129 while (pow2Height < Height) pow2Height <<= 1;
1131 /** FIXME: add support for real non-power-two if it's provided by the video card **/
1132 /* Precalculated scaling for 'faked' non power of two texture coords */
1133 object->pow2scalingFactorX = (((float)Width) / ((float)pow2Width));
1134 object->pow2scalingFactorY = (((float)Height) / ((float)pow2Height));
1135 TRACE(" xf(%f) yf(%f)\n", object->pow2scalingFactorX, object->pow2scalingFactorY);
1137 /* Calculate levels for mip mapping */
1139 TRACE("calculating levels %d\n", object->baseTexture.levels);
1140 object->baseTexture.levels++;
1143 while (tmpW > 1 || tmpH > 1) {
1144 tmpW = max(1, tmpW >> 1);
1145 tmpH = max(1, tmpH >> 1);
1146 object->baseTexture.levels++;
1148 TRACE("Calculated levels = %d\n", object->baseTexture.levels);
1151 /* Generate all the surfaces */
1154 for (i = 0; i < object->baseTexture.levels; i++)
1156 /* use the callback to create the texture surface */
1157 hr = D3DCB_CreateSurface(This->parent, tmpW, tmpH, Format, Usage, Pool, i, &object->surfaces[i],NULL);
1158 if (hr!= WINED3D_OK || ( (IWineD3DSurfaceImpl *) object->surfaces[i])->Flags & SFLAG_OVERSIZE) {
1159 FIXME("Failed to create surface %p\n", object);
1161 object->surfaces[i] = NULL;
1162 IWineD3DTexture_Release((IWineD3DTexture *)object);
1168 IWineD3DSurface_SetContainer(object->surfaces[i], (IWineD3DBase *)object);
1169 TRACE("Created surface level %d @ %p\n", i, object->surfaces[i]);
1170 /* calculate the next mipmap level */
1171 tmpW = max(1, tmpW >> 1);
1172 tmpH = max(1, tmpH >> 1);
1175 TRACE("(%p) : Created texture %p\n", This, object);
1179 static HRESULT WINAPI IWineD3DDeviceImpl_CreateVolumeTexture(IWineD3DDevice *iface,
1180 UINT Width, UINT Height, UINT Depth,
1181 UINT Levels, DWORD Usage,
1182 WINED3DFORMAT Format, WINED3DPOOL Pool,
1183 IWineD3DVolumeTexture **ppVolumeTexture,
1184 HANDLE *pSharedHandle, IUnknown *parent,
1185 D3DCB_CREATEVOLUMEFN D3DCB_CreateVolume) {
1187 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
1188 IWineD3DVolumeTextureImpl *object;
1194 /* TODO: It should only be possible to create textures for formats
1195 that are reported as supported */
1196 if (WINED3DFMT_UNKNOWN >= Format) {
1197 WARN("(%p) : Texture cannot be created with a format of D3DFMT_UNKNOWN\n", This);
1198 return WINED3DERR_INVALIDCALL;
1201 D3DCREATERESOURCEOBJECTINSTANCE(object, VolumeTexture, WINED3DRTYPE_VOLUMETEXTURE, 0);
1202 D3DINITIALIZEBASETEXTURE(object->baseTexture);
1204 TRACE("(%p) : W(%d) H(%d) D(%d), Lvl(%d) Usage(%ld), Fmt(%u,%s), Pool(%s)\n", This, Width, Height,
1205 Depth, Levels, Usage, Format, debug_d3dformat(Format), debug_d3dpool(Pool));
1207 object->width = Width;
1208 object->height = Height;
1209 object->depth = Depth;
1211 /* Calculate levels for mip mapping */
1213 object->baseTexture.levels++;
1217 while (tmpW > 1 || tmpH > 1 || tmpD > 1) {
1218 tmpW = max(1, tmpW >> 1);
1219 tmpH = max(1, tmpH >> 1);
1220 tmpD = max(1, tmpD >> 1);
1221 object->baseTexture.levels++;
1223 TRACE("Calculated levels = %d\n", object->baseTexture.levels);
1226 /* Generate all the surfaces */
1231 for (i = 0; i < object->baseTexture.levels; i++)
1233 /* Create the volume */
1234 D3DCB_CreateVolume(This->parent, Width, Height, Depth, Format, Pool, Usage,
1235 (IWineD3DVolume **)&object->volumes[i], pSharedHandle);
1237 /* Set it's container to this object */
1238 IWineD3DVolume_SetContainer(object->volumes[i], (IWineD3DBase *)object);
1240 /* calcualte the next mipmap level */
1241 tmpW = max(1, tmpW >> 1);
1242 tmpH = max(1, tmpH >> 1);
1243 tmpD = max(1, tmpD >> 1);
1246 *ppVolumeTexture = (IWineD3DVolumeTexture *) object;
1247 TRACE("(%p) : Created volume texture %p\n", This, object);
1251 static HRESULT WINAPI IWineD3DDeviceImpl_CreateVolume(IWineD3DDevice *iface,
1252 UINT Width, UINT Height, UINT Depth,
1254 WINED3DFORMAT Format, WINED3DPOOL Pool,
1255 IWineD3DVolume** ppVolume,
1256 HANDLE* pSharedHandle, IUnknown *parent) {
1258 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
1259 IWineD3DVolumeImpl *object; /** NOTE: impl ref allowed since this is a create function **/
1260 const PixelFormatDesc *formatDesc = getFormatDescEntry(Format);
1262 D3DCREATERESOURCEOBJECTINSTANCE(object, Volume, WINED3DRTYPE_VOLUME, ((Width * formatDesc->bpp) * Height * Depth))
1264 TRACE("(%p) : W(%d) H(%d) D(%d), Usage(%ld), Fmt(%u,%s), Pool(%s)\n", This, Width, Height,
1265 Depth, Usage, Format, debug_d3dformat(Format), debug_d3dpool(Pool));
1267 object->currentDesc.Width = Width;
1268 object->currentDesc.Height = Height;
1269 object->currentDesc.Depth = Depth;
1270 object->bytesPerPixel = formatDesc->bpp;
1272 /** Note: Volume textures cannot be dxtn, hence no need to check here **/
1273 object->lockable = TRUE;
1274 object->locked = FALSE;
1275 memset(&object->lockedBox, 0, sizeof(WINED3DBOX));
1276 object->dirty = TRUE;
1278 return IWineD3DVolume_AddDirtyBox((IWineD3DVolume *) object, NULL);
1281 static HRESULT WINAPI IWineD3DDeviceImpl_CreateCubeTexture(IWineD3DDevice *iface, UINT EdgeLength,
1282 UINT Levels, DWORD Usage,
1283 WINED3DFORMAT Format, WINED3DPOOL Pool,
1284 IWineD3DCubeTexture **ppCubeTexture,
1285 HANDLE *pSharedHandle, IUnknown *parent,
1286 D3DCB_CREATESURFACEFN D3DCB_CreateSurface) {
1288 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
1289 IWineD3DCubeTextureImpl *object; /** NOTE: impl ref allowed since this is a create function **/
1293 unsigned int pow2EdgeLength = EdgeLength;
1295 /* TODO: It should only be possible to create textures for formats
1296 that are reported as supported */
1297 if (WINED3DFMT_UNKNOWN >= Format) {
1298 WARN("(%p) : Texture cannot be created with a format of D3DFMT_UNKNOWN\n", This);
1299 return WINED3DERR_INVALIDCALL;
1302 D3DCREATERESOURCEOBJECTINSTANCE(object, CubeTexture, WINED3DRTYPE_CUBETEXTURE, 0);
1303 D3DINITIALIZEBASETEXTURE(object->baseTexture);
1305 TRACE("(%p) Create Cube Texture\n", This);
1307 /** Non-power2 support **/
1309 /* Find the nearest pow2 match */
1311 while (pow2EdgeLength < EdgeLength) pow2EdgeLength <<= 1;
1313 object->edgeLength = EdgeLength;
1314 /* TODO: support for native non-power 2 */
1315 /* Precalculated scaling for 'faked' non power of two texture coords */
1316 object->pow2scalingFactor = ((float)EdgeLength) / ((float)pow2EdgeLength);
1318 /* Calculate levels for mip mapping */
1320 object->baseTexture.levels++;
1323 tmpW = max(1, tmpW >> 1);
1324 object->baseTexture.levels++;
1326 TRACE("Calculated levels = %d\n", object->baseTexture.levels);
1329 /* Generate all the surfaces */
1331 for (i = 0; i < object->baseTexture.levels; i++) {
1333 /* Create the 6 faces */
1334 for (j = 0; j < 6; j++) {
1336 hr=D3DCB_CreateSurface(This->parent, tmpW, tmpW, Format, Usage, Pool,
1337 i /* Level */, &object->surfaces[j][i],pSharedHandle);
1339 if(hr!= WINED3D_OK) {
1343 for (l = 0; l < j; l++) {
1344 IWineD3DSurface_Release(object->surfaces[j][i]);
1346 for (k = 0; k < i; k++) {
1347 for (l = 0; l < 6; l++) {
1348 IWineD3DSurface_Release(object->surfaces[l][j]);
1352 FIXME("(%p) Failed to create surface\n",object);
1353 HeapFree(GetProcessHeap(),0,object);
1354 *ppCubeTexture = NULL;
1357 IWineD3DSurface_SetContainer(object->surfaces[j][i], (IWineD3DBase *)object);
1358 TRACE("Created surface level %d @ %p,\n", i, object->surfaces[j][i]);
1360 tmpW = max(1, tmpW >> 1);
1363 TRACE("(%p) : Created Cube Texture %p\n", This, object);
1364 *ppCubeTexture = (IWineD3DCubeTexture *) object;
1368 static HRESULT WINAPI IWineD3DDeviceImpl_CreateQuery(IWineD3DDevice *iface, WINED3DQUERYTYPE Type, IWineD3DQuery **ppQuery, IUnknown* parent) {
1369 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
1370 IWineD3DQueryImpl *object; /*NOTE: impl ref allowed since this is a create function */
1372 if (NULL == ppQuery) {
1373 /* Just a check to see if we support this type of query */
1374 HRESULT hr = WINED3DERR_NOTAVAILABLE;
1376 case WINED3DQUERYTYPE_OCCLUSION:
1377 TRACE("(%p) occlusion query\n", This);
1378 if (GL_SUPPORT(ARB_OCCLUSION_QUERY) || GL_SUPPORT(NV_OCCLUSION_QUERY))
1381 WARN("Unsupported in local OpenGL implementation: ARB_OCCLUSION_QUERY/NV_OCCLUSION_QUERY\n");
1383 case WINED3DQUERYTYPE_VCACHE:
1384 case WINED3DQUERYTYPE_RESOURCEMANAGER:
1385 case WINED3DQUERYTYPE_VERTEXSTATS:
1386 case WINED3DQUERYTYPE_EVENT:
1387 case WINED3DQUERYTYPE_TIMESTAMP:
1388 case WINED3DQUERYTYPE_TIMESTAMPDISJOINT:
1389 case WINED3DQUERYTYPE_TIMESTAMPFREQ:
1390 case WINED3DQUERYTYPE_PIPELINETIMINGS:
1391 case WINED3DQUERYTYPE_INTERFACETIMINGS:
1392 case WINED3DQUERYTYPE_VERTEXTIMINGS:
1393 case WINED3DQUERYTYPE_PIXELTIMINGS:
1394 case WINED3DQUERYTYPE_BANDWIDTHTIMINGS:
1395 case WINED3DQUERYTYPE_CACHEUTILIZATION:
1397 FIXME("(%p) Unhandled query type %d\n", This, Type);
1402 D3DCREATEOBJECTINSTANCE(object, Query)
1403 object->type = Type;
1404 /* allocated the 'extended' data based on the type of query requested */
1406 case D3DQUERYTYPE_OCCLUSION:
1407 if(GL_SUPPORT(ARB_OCCLUSION_QUERY) || GL_SUPPORT(NV_OCCLUSION_QUERY)) {
1408 TRACE("(%p) Allocating data for an occlusion query\n", This);
1409 object->extendedData = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(WineQueryOcclusionData));
1412 case D3DQUERYTYPE_VCACHE:
1413 case D3DQUERYTYPE_RESOURCEMANAGER:
1414 case D3DQUERYTYPE_VERTEXSTATS:
1415 case D3DQUERYTYPE_EVENT:
1416 case D3DQUERYTYPE_TIMESTAMP:
1417 case D3DQUERYTYPE_TIMESTAMPDISJOINT:
1418 case D3DQUERYTYPE_TIMESTAMPFREQ:
1419 case D3DQUERYTYPE_PIPELINETIMINGS:
1420 case D3DQUERYTYPE_INTERFACETIMINGS:
1421 case D3DQUERYTYPE_VERTEXTIMINGS:
1422 case D3DQUERYTYPE_PIXELTIMINGS:
1423 case D3DQUERYTYPE_BANDWIDTHTIMINGS:
1424 case D3DQUERYTYPE_CACHEUTILIZATION:
1426 object->extendedData = 0;
1427 FIXME("(%p) Unhandled query type %d\n",This , Type);
1429 TRACE("(%p) : Created Query %p\n", This, object);
1433 /* example at http://www.fairyengine.com/articles/dxmultiviews.htm */
1434 static HRESULT WINAPI IWineD3DDeviceImpl_CreateAdditionalSwapChain(IWineD3DDevice* iface, WINED3DPRESENT_PARAMETERS* pPresentationParameters, IWineD3DSwapChain** ppSwapChain,
1436 D3DCB_CREATERENDERTARGETFN D3DCB_CreateRenderTarget,
1437 D3DCB_CREATEDEPTHSTENCILSURFACEFN D3DCB_CreateDepthStencil) {
1438 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
1441 IWineD3DSwapChainImpl *object; /** NOTE: impl ref allowed since this is a create function **/
1443 XVisualInfo template;
1444 GLXContext oldContext;
1445 Drawable oldDrawable;
1446 HRESULT hr = WINED3D_OK;
1448 TRACE("(%p) : Created Aditional Swap Chain\n", This);
1450 /** FIXME: Test under windows to find out what the life cycle of a swap chain is,
1451 * does a device hold a reference to a swap chain giving them a lifetime of the device
1452 * or does the swap chain notify the device of its destruction.
1453 *******************************/
1455 /* Check the params */
1456 if(*pPresentationParameters->BackBufferCount > D3DPRESENT_BACK_BUFFER_MAX) {
1457 ERR("App requested %d back buffers, this is not supported for now\n", *pPresentationParameters->BackBufferCount);
1458 return WINED3DERR_INVALIDCALL;
1459 } else if (*pPresentationParameters->BackBufferCount > 1) {
1460 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");
1463 D3DCREATEOBJECTINSTANCE(object, SwapChain)
1465 /*********************
1466 * Lookup the window Handle and the relating X window handle
1467 ********************/
1469 /* Setup hwnd we are using, plus which display this equates to */
1470 object->win_handle = *(pPresentationParameters->hDeviceWindow);
1471 if (!object->win_handle) {
1472 object->win_handle = This->createParms.hFocusWindow;
1475 object->win_handle = GetAncestor(object->win_handle, GA_ROOT);
1476 if ( !( object->win = (Window)GetPropA(object->win_handle, "__wine_x11_whole_window") ) ) {
1477 ERR("Can't get drawable (window), HWND:%p doesn't have the property __wine_x11_whole_window\n", object->win_handle);
1478 return WINED3DERR_NOTAVAILABLE;
1480 hDc = GetDC(object->win_handle);
1481 object->display = get_display(hDc);
1482 ReleaseDC(object->win_handle, hDc);
1483 TRACE("Using a display of %p %p\n", object->display, hDc);
1485 if (NULL == object->display || NULL == hDc) {
1486 WARN("Failed to get a display and HDc for Window %p\n", object->win_handle);
1487 return WINED3DERR_NOTAVAILABLE;
1490 if (object->win == 0) {
1491 WARN("Failed to get a valid XVisuial ID for the window %p\n", object->win_handle);
1492 return WINED3DERR_NOTAVAILABLE;
1495 * Create an opengl context for the display visual
1496 * NOTE: the visual is chosen as the window is created and the glcontext cannot
1497 * use different properties after that point in time. FIXME: How to handle when requested format
1498 * doesn't match actual visual? Cannot choose one here - code removed as it ONLY works if the one
1499 * it chooses is identical to the one already being used!
1500 **********************************/
1502 /** FIXME: Handle stencil appropriately via EnableAutoDepthStencil / AutoDepthStencilFormat **/
1505 /* Create a new context for this swapchain */
1506 template.visualid = (VisualID)GetPropA(GetDesktopWindow(), "__wine_x11_visual_id");
1507 /* TODO: change this to find a similar visual, but one with a stencil/zbuffer buffer that matches the request
1508 (or the best possible if none is requested) */
1509 TRACE("Found x visual ID : %ld\n", template.visualid);
1511 object->visInfo = XGetVisualInfo(object->display, VisualIDMask, &template, &num);
1512 if (NULL == object->visInfo) {
1513 ERR("cannot really get XVisual\n");
1515 return WINED3DERR_NOTAVAILABLE;
1518 /* Write out some debug info about the visual/s */
1519 TRACE("Using x visual ID : %ld\n", template.visualid);
1520 TRACE(" visual info: %p\n", object->visInfo);
1521 TRACE(" num items : %d\n", num);
1522 for (n = 0;n < num; n++) {
1523 TRACE("=====item=====: %d\n", n + 1);
1524 TRACE(" visualid : %ld\n", object->visInfo[n].visualid);
1525 TRACE(" screen : %d\n", object->visInfo[n].screen);
1526 TRACE(" depth : %u\n", object->visInfo[n].depth);
1527 TRACE(" class : %d\n", object->visInfo[n].class);
1528 TRACE(" red_mask : %ld\n", object->visInfo[n].red_mask);
1529 TRACE(" green_mask : %ld\n", object->visInfo[n].green_mask);
1530 TRACE(" blue_mask : %ld\n", object->visInfo[n].blue_mask);
1531 TRACE(" colormap_size : %d\n", object->visInfo[n].colormap_size);
1532 TRACE(" bits_per_rgb : %d\n", object->visInfo[n].bits_per_rgb);
1533 /* log some extra glx info */
1534 glXGetConfig(object->display, object->visInfo, GLX_AUX_BUFFERS, &value);
1535 TRACE(" gl_aux_buffers : %d\n", value);
1536 glXGetConfig(object->display, object->visInfo, GLX_BUFFER_SIZE ,&value);
1537 TRACE(" gl_buffer_size : %d\n", value);
1538 glXGetConfig(object->display, object->visInfo, GLX_RED_SIZE, &value);
1539 TRACE(" gl_red_size : %d\n", value);
1540 glXGetConfig(object->display, object->visInfo, GLX_GREEN_SIZE, &value);
1541 TRACE(" gl_green_size : %d\n", value);
1542 glXGetConfig(object->display, object->visInfo, GLX_BLUE_SIZE, &value);
1543 TRACE(" gl_blue_size : %d\n", value);
1544 glXGetConfig(object->display, object->visInfo, GLX_ALPHA_SIZE, &value);
1545 TRACE(" gl_alpha_size : %d\n", value);
1546 glXGetConfig(object->display, object->visInfo, GLX_DEPTH_SIZE ,&value);
1547 TRACE(" gl_depth_size : %d\n", value);
1548 glXGetConfig(object->display, object->visInfo, GLX_STENCIL_SIZE, &value);
1549 TRACE(" gl_stencil_size : %d\n", value);
1551 /* Now choose a simila visual ID*/
1553 #ifdef USE_CONTEXT_MANAGER
1555 /** TODO: use a context mamager **/
1559 IWineD3DSwapChain *implSwapChain;
1560 if (WINED3D_OK != IWineD3DDevice_GetSwapChain(iface, 0, &implSwapChain)) {
1561 /* The first time around we create the context that is shared with all other swapchains and render targets */
1562 object->glCtx = glXCreateContext(object->display, object->visInfo, NULL, GL_TRUE);
1563 TRACE("Creating implicit context for vis %p, hwnd %p\n", object->display, object->visInfo);
1566 TRACE("Creating context for vis %p, hwnd %p\n", object->display, object->visInfo);
1567 /* TODO: don't use Impl structures outside of create functions! (a context manager will replace the ->glCtx) */
1568 /* and create a new context with the implicit swapchains context as the shared context */
1569 object->glCtx = glXCreateContext(object->display, object->visInfo, ((IWineD3DSwapChainImpl *)implSwapChain)->glCtx, GL_TRUE);
1570 IWineD3DSwapChain_Release(implSwapChain);
1575 XFree(object->visInfo);
1576 object->visInfo = NULL;
1580 if (!object->glCtx) {
1581 ERR("Failed to create GLX context\n");
1582 return WINED3DERR_NOTAVAILABLE;
1584 TRACE("Context created (HWND=%p, glContext=%p, Window=%ld, VisInfo=%p)\n",
1585 object->win_handle, object->glCtx, object->win, object->visInfo);
1588 /*********************
1589 * Windowed / Fullscreen
1590 *******************/
1593 * TODO: MSDN says that we are only allowed one fullscreen swapchain per device,
1594 * so we should really check to see if there is a fullscreen swapchain already
1595 * I think Windows and X have different ideas about fullscreen, does a single head count as full screen?
1596 **************************************/
1598 if (!*(pPresentationParameters->Windowed)) {
1604 /* Get info on the current display setup */
1605 hdc = CreateDCA("DISPLAY", NULL, NULL, NULL);
1606 bpp = GetDeviceCaps(hdc, BITSPIXEL);
1609 /* Change the display settings */
1610 memset(&devmode, 0, sizeof(DEVMODEW));
1611 devmode.dmFields = DM_BITSPERPEL | DM_PELSWIDTH | DM_PELSHEIGHT;
1612 devmode.dmBitsPerPel = (bpp >= 24) ? 32 : bpp; /* Stupid XVidMode cannot change bpp */
1613 devmode.dmPelsWidth = *(pPresentationParameters->BackBufferWidth);
1614 devmode.dmPelsHeight = *(pPresentationParameters->BackBufferHeight);
1615 MultiByteToWideChar(CP_ACP, 0, "Gamers CG", -1, devmode.dmDeviceName, CCHDEVICENAME);
1616 ChangeDisplaySettingsExW(devmode.dmDeviceName, &devmode, object->win_handle, CDS_FULLSCREEN, NULL);
1618 /* Make popup window */
1619 SetWindowLongA(object->win_handle, GWL_STYLE, WS_POPUP);
1620 SetWindowPos(object->win_handle, HWND_TOP, 0, 0,
1621 *(pPresentationParameters->BackBufferWidth),
1622 *(pPresentationParameters->BackBufferHeight), SWP_SHOWWINDOW | SWP_FRAMECHANGED);
1624 /* For GetDisplayMode */
1625 This->ddraw_width = devmode.dmPelsWidth;
1626 This->ddraw_height = devmode.dmPelsHeight;
1627 This->ddraw_format = *(pPresentationParameters->BackBufferFormat);
1631 /** MSDN: If Windowed is TRUE and either of the BackBufferWidth/Height values is zero,
1632 * then the corresponding dimension of the client area of the hDeviceWindow
1633 * (or the focus window, if hDeviceWindow is NULL) is taken.
1634 **********************/
1636 if (*(pPresentationParameters->Windowed) &&
1637 ((*(pPresentationParameters->BackBufferWidth) == 0) ||
1638 (*(pPresentationParameters->BackBufferHeight) == 0))) {
1641 GetClientRect(object->win_handle, &Rect);
1643 if (*(pPresentationParameters->BackBufferWidth) == 0) {
1644 *(pPresentationParameters->BackBufferWidth) = Rect.right;
1645 TRACE("Updating width to %d\n", *(pPresentationParameters->BackBufferWidth));
1647 if (*(pPresentationParameters->BackBufferHeight) == 0) {
1648 *(pPresentationParameters->BackBufferHeight) = Rect.bottom;
1649 TRACE("Updating height to %d\n", *(pPresentationParameters->BackBufferHeight));
1653 /*********************
1654 * finish off parameter initialization
1655 *******************/
1657 /* Put the correct figures in the presentation parameters */
1658 TRACE("Coppying accross presentaion paraneters\n");
1659 object->presentParms.BackBufferWidth = *(pPresentationParameters->BackBufferWidth);
1660 object->presentParms.BackBufferHeight = *(pPresentationParameters->BackBufferHeight);
1661 object->presentParms.BackBufferFormat = *(pPresentationParameters->BackBufferFormat);
1662 object->presentParms.BackBufferCount = *(pPresentationParameters->BackBufferCount);
1663 object->presentParms.MultiSampleType = *(pPresentationParameters->MultiSampleType);
1664 object->presentParms.MultiSampleQuality = NULL == pPresentationParameters->MultiSampleQuality ? 0 : *(pPresentationParameters->MultiSampleQuality);
1665 object->presentParms.SwapEffect = *(pPresentationParameters->SwapEffect);
1666 object->presentParms.hDeviceWindow = *(pPresentationParameters->hDeviceWindow);
1667 object->presentParms.Windowed = *(pPresentationParameters->Windowed);
1668 object->presentParms.EnableAutoDepthStencil = *(pPresentationParameters->EnableAutoDepthStencil);
1669 object->presentParms.AutoDepthStencilFormat = *(pPresentationParameters->AutoDepthStencilFormat);
1670 object->presentParms.Flags = *(pPresentationParameters->Flags);
1671 object->presentParms.FullScreen_RefreshRateInHz = *(pPresentationParameters->FullScreen_RefreshRateInHz);
1672 object->presentParms.PresentationInterval = *(pPresentationParameters->PresentationInterval);
1675 /*********************
1676 * Create the back, front and stencil buffers
1677 *******************/
1679 TRACE("calling rendertarget CB\n");
1680 hr = D3DCB_CreateRenderTarget((IUnknown *) This->parent,
1681 object->presentParms.BackBufferWidth,
1682 object->presentParms.BackBufferHeight,
1683 object->presentParms.BackBufferFormat,
1684 object->presentParms.MultiSampleType,
1685 object->presentParms.MultiSampleQuality,
1686 TRUE /* Lockable */,
1687 &object->frontBuffer,
1688 NULL /* pShared (always null)*/);
1689 if (object->frontBuffer != NULL)
1690 IWineD3DSurface_SetContainer(object->frontBuffer, (IWineD3DBase *)object);
1692 if(object->presentParms.BackBufferCount > 0) {
1695 object->backBuffer = HeapAlloc(GetProcessHeap(), 0, sizeof(IWineD3DSurface *) * object->presentParms.BackBufferCount);
1696 if(!object->backBuffer) {
1697 ERR("Out of memory\n");
1699 if (object->frontBuffer) {
1700 IUnknown *bufferParent;
1701 IWineD3DSurface_GetParent(object->frontBuffer, &bufferParent);
1702 IUnknown_Release(bufferParent); /* once for the get parent */
1703 if (IUnknown_Release(bufferParent) > 0) {
1704 FIXME("(%p) Something's still holding the front buffer\n",This);
1707 HeapFree(GetProcessHeap(), 0, object);
1708 return E_OUTOFMEMORY;
1711 for(i = 0; i < object->presentParms.BackBufferCount; i++) {
1712 TRACE("calling rendertarget CB\n");
1713 hr = D3DCB_CreateRenderTarget((IUnknown *) This->parent,
1714 object->presentParms.BackBufferWidth,
1715 object->presentParms.BackBufferHeight,
1716 object->presentParms.BackBufferFormat,
1717 object->presentParms.MultiSampleType,
1718 object->presentParms.MultiSampleQuality,
1719 TRUE /* Lockable */,
1720 &object->backBuffer[i],
1721 NULL /* pShared (always null)*/);
1722 if(hr == WINED3D_OK && object->backBuffer[i]) {
1723 IWineD3DSurface_SetContainer(object->backBuffer[i], (IWineD3DBase *)object);
1729 object->backBuffer = NULL;
1732 if (object->backBuffer != NULL) {
1734 glDrawBuffer(GL_BACK);
1735 checkGLcall("glDrawBuffer(GL_BACK)");
1738 /* Single buffering - draw to front buffer */
1740 glDrawBuffer(GL_FRONT);
1741 checkGLcall("glDrawBuffer(GL_FRONT)");
1745 /* Under directX swapchains share the depth stencil, so only create one depth-stencil */
1746 if (pPresentationParameters->EnableAutoDepthStencil && hr == WINED3D_OK) {
1747 TRACE("Creating depth stencil buffer\n");
1748 if (This->depthStencilBuffer == NULL ) {
1749 hr = D3DCB_CreateDepthStencil((IUnknown *) This->parent,
1750 object->presentParms.BackBufferWidth,
1751 object->presentParms.BackBufferHeight,
1752 object->presentParms.AutoDepthStencilFormat,
1753 object->presentParms.MultiSampleType,
1754 object->presentParms.MultiSampleQuality,
1755 FALSE /* FIXME: Discard */,
1756 &This->depthStencilBuffer,
1757 NULL /* pShared (always null)*/ );
1758 if (This->depthStencilBuffer != NULL)
1759 IWineD3DSurface_SetContainer(This->depthStencilBuffer, 0);
1762 /** TODO: A check on width, height and multisample types
1763 *(since the zbuffer must be at least as large as the render target and have the same multisample parameters)
1764 ****************************/
1765 object->wantsDepthStencilBuffer = TRUE;
1767 object->wantsDepthStencilBuffer = FALSE;
1770 TRACE("FrontBuf @ %p, BackBuf @ %p, DepthStencil %d\n",object->frontBuffer, object->backBuffer ? object->backBuffer[0] : NULL, object->wantsDepthStencilBuffer);
1773 /*********************
1774 * init the default renderTarget management
1775 *******************/
1776 object->drawable = object->win;
1777 object->render_ctx = object->glCtx;
1779 if (hr == WINED3D_OK) {
1780 /*********************
1781 * Setup some defaults and clear down the buffers
1782 *******************/
1784 /** save current context and drawable **/
1785 oldContext = glXGetCurrentContext();
1786 oldDrawable = glXGetCurrentDrawable();
1788 TRACE("Activating context (display %p context %p drawable %ld)!\n", object->display, object->glCtx, object->win);
1789 if (glXMakeCurrent(object->display, object->win, object->glCtx) == False) {
1790 ERR("Error in setting current context (display %p context %p drawable %ld)!\n", object->display, object->glCtx, object->win);
1792 checkGLcall("glXMakeCurrent");
1794 TRACE("Setting up the screen\n");
1795 /* Clear the screen */
1796 glClearColor(1.0, 0.0, 0.0, 0.0);
1797 checkGLcall("glClearColor");
1800 glClearStencil(0xffff);
1802 checkGLcall("glClear");
1804 glColor3f(1.0, 1.0, 1.0);
1805 checkGLcall("glColor3f");
1807 glEnable(GL_LIGHTING);
1808 checkGLcall("glEnable");
1810 glLightModeli(GL_LIGHT_MODEL_LOCAL_VIEWER, GL_TRUE);
1811 checkGLcall("glLightModeli(GL_LIGHT_MODEL_LOCAL_VIEWER, GL_TRUE);");
1813 glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE_EXT);
1814 checkGLcall("glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE_EXT);");
1816 glLightModeli(GL_LIGHT_MODEL_COLOR_CONTROL, GL_SEPARATE_SPECULAR_COLOR);
1817 checkGLcall("glLightModeli(GL_LIGHT_MODEL_COLOR_CONTROL, GL_SEPARATE_SPECULAR_COLOR);");
1819 /* switch back to the original context (if there was one)*/
1820 if (This->swapchains) {
1821 /** TODO: restore the context and drawable **/
1822 glXMakeCurrent(object->display, oldDrawable, oldContext);
1827 TRACE("Set swapchain to %p\n", object);
1828 } else { /* something went wrong so clean up */
1829 IUnknown* bufferParent;
1830 if (object->frontBuffer) {
1832 IWineD3DSurface_GetParent(object->frontBuffer, &bufferParent);
1833 IUnknown_Release(bufferParent); /* once for the get parent */
1834 if (IUnknown_Release(bufferParent) > 0) {
1835 FIXME("(%p) Something's still holding the front buffer\n",This);
1838 if (object->backBuffer) {
1840 for(i = 0; i < object->presentParms.BackBufferCount; i++) {
1841 if(object->backBuffer[i]) {
1842 IWineD3DSurface_GetParent(object->backBuffer[i], &bufferParent);
1843 IUnknown_Release(bufferParent); /* once for the get parent */
1844 if (IUnknown_Release(bufferParent) > 0) {
1845 FIXME("(%p) Something's still holding the back buffer\n",This);
1849 HeapFree(GetProcessHeap(), 0, object->backBuffer);
1850 object->backBuffer = NULL;
1852 /* NOTE: don't clean up the depthstencil buffer because it belongs to the device */
1853 /* Clean up the context */
1854 /* check that we are the current context first (we shouldn't be though!) */
1855 if (object->glCtx != 0) {
1856 if(glXGetCurrentContext() == object->glCtx) {
1857 glXMakeCurrent(object->display, None, NULL);
1859 glXDestroyContext(object->display, object->glCtx);
1861 HeapFree(GetProcessHeap(), 0, object);
1868 /** NOTE: These are ahead of the other getters and setters to save using a forward declaration **/
1869 static UINT WINAPI IWineD3DDeviceImpl_GetNumberOfSwapChains(IWineD3DDevice *iface) {
1870 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
1871 TRACE("(%p)\n", This);
1873 return This->NumberOfSwapChains;
1876 static HRESULT WINAPI IWineD3DDeviceImpl_GetSwapChain(IWineD3DDevice *iface, UINT iSwapChain, IWineD3DSwapChain **pSwapChain) {
1877 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
1878 TRACE("(%p) : swapchain %d\n", This, iSwapChain);
1880 if(iSwapChain < This->NumberOfSwapChains) {
1881 *pSwapChain = This->swapchains[iSwapChain];
1882 IWineD3DSwapChain_AddRef(*pSwapChain);
1883 TRACE("(%p) returning %p\n", This, *pSwapChain);
1886 TRACE("Swapchain out of range\n");
1888 return WINED3DERR_INVALIDCALL;
1893 * Vertex Declaration
1895 static HRESULT WINAPI IWineD3DDeviceImpl_CreateVertexDeclaration(IWineD3DDevice* iface, CONST VOID* pDeclaration, IWineD3DVertexDeclaration** ppVertexDeclaration, IUnknown *parent) {
1896 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
1897 IWineD3DVertexDeclarationImpl *object = NULL;
1898 HRESULT hr = WINED3D_OK;
1899 TRACE("(%p) : directXVersion=%u, pFunction=%p, ppDecl=%p\n", This, ((IWineD3DImpl *)This->wineD3D)->dxVersion, pDeclaration, ppVertexDeclaration);
1900 D3DCREATEOBJECTINSTANCE(object, VertexDeclaration)
1903 hr = IWineD3DVertexDeclaration_SetDeclaration((IWineD3DVertexDeclaration *)object, (void *)pDeclaration);
1908 /* http://msdn.microsoft.com/archive/default.asp?url=/archive/en-us/directx9_c/directx/graphics/programmingguide/programmable/vertexshaders/vscreate.asp */
1909 static HRESULT WINAPI IWineD3DDeviceImpl_CreateVertexShader(IWineD3DDevice *iface, CONST DWORD *pDeclaration, CONST DWORD *pFunction, IWineD3DVertexShader **ppVertexShader, IUnknown *parent) {
1910 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
1911 IWineD3DVertexShaderImpl *object; /* NOTE: impl usage is ok, this is a create */
1912 HRESULT hr = WINED3D_OK;
1913 D3DCREATEOBJECTINSTANCE(object, VertexShader)
1914 object->baseShader.shader_ins = IWineD3DVertexShaderImpl_shader_ins;
1916 TRACE("(%p) : Created Vertex shader %p\n", This, *ppVertexShader);
1918 /* If a vertex declaration has been passed, save it to the vertex shader, this affects d3d8 only. */
1919 /* Further it needs to be set before calling SetFunction as SetFunction needs the declaration. */
1920 if (pDeclaration != NULL) {
1921 IWineD3DVertexDeclaration *vertexDeclaration;
1922 hr = IWineD3DDevice_CreateVertexDeclaration(iface, pDeclaration, &vertexDeclaration ,NULL);
1923 if (WINED3D_OK == hr) {
1924 TRACE("(%p) : Setting vertex declaration to %p\n", This, vertexDeclaration);
1925 object->vertexDeclaration = vertexDeclaration;
1927 FIXME("(%p) : Failed to set the declaration, returning WINED3DERR_INVALIDCALL\n", iface);
1928 IWineD3DVertexShader_Release(*ppVertexShader);
1929 return WINED3DERR_INVALIDCALL;
1933 hr = IWineD3DVertexShader_SetFunction(*ppVertexShader, pFunction);
1935 if (WINED3D_OK != hr) {
1936 FIXME("(%p) : Failed to set the function, returning WINED3DERR_INVALIDCALL\n", iface);
1937 IWineD3DVertexShader_Release(*ppVertexShader);
1938 return WINED3DERR_INVALIDCALL;
1941 #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. */
1942 if(Usage == WINED3DUSAGE_SOFTWAREVERTEXPROCESSING) {
1953 static HRESULT WINAPI IWineD3DDeviceImpl_CreatePixelShader(IWineD3DDevice *iface, CONST DWORD *pFunction, IWineD3DPixelShader **ppPixelShader, IUnknown *parent) {
1954 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
1955 IWineD3DPixelShaderImpl *object; /* NOTE: impl allowed, this is a create */
1956 HRESULT hr = WINED3D_OK;
1958 D3DCREATEOBJECTINSTANCE(object, PixelShader)
1959 object->baseShader.shader_ins = IWineD3DPixelShaderImpl_shader_ins;
1960 hr = IWineD3DPixelShader_SetFunction(*ppPixelShader, pFunction);
1961 if (WINED3D_OK == hr) {
1962 TRACE("(%p) : Created Pixel shader %p\n", This, *ppPixelShader);
1964 WARN("(%p) : Failed to create pixel shader\n", This);
1970 static HRESULT WINAPI IWineD3DDeviceImpl_CreatePalette(IWineD3DDevice *iface, DWORD Flags, PALETTEENTRY *PalEnt, IWineD3DPalette **Palette, IUnknown *Parent) {
1971 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *) iface;
1972 IWineD3DPaletteImpl *object;
1974 TRACE("(%p)->(%lx, %p, %p, %p)\n", This, Flags, PalEnt, Palette, Parent);
1976 /* Create the new object */
1977 object = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(IWineD3DPaletteImpl));
1979 ERR("Out of memory when allocating memory for a IWineD3DPalette implementation\n");
1980 return E_OUTOFMEMORY;
1983 object->lpVtbl = &IWineD3DPalette_Vtbl;
1985 object->Flags = Flags;
1986 object->parent = Parent;
1987 object->wineD3DDevice = This;
1988 object->palNumEntries = IWineD3DPaletteImpl_Size(Flags);
1990 object->hpal = CreatePalette((const LOGPALETTE*)&(object->palVersion));
1993 HeapFree( GetProcessHeap(), 0, object);
1994 return E_OUTOFMEMORY;
1997 hr = IWineD3DPalette_SetEntries((IWineD3DPalette *) object, 0, 0, IWineD3DPaletteImpl_Size(Flags), PalEnt);
1999 IWineD3DPalette_Release((IWineD3DPalette *) object);
2003 *Palette = (IWineD3DPalette *) object;
2008 static HRESULT WINAPI IWineD3DDeviceImpl_Init3D(IWineD3DDevice *iface, WINED3DPRESENT_PARAMETERS* pPresentationParameters, D3DCB_CREATEADDITIONALSWAPCHAIN D3DCB_CreateAdditionalSwapChain) {
2009 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *) iface;
2010 IWineD3DSwapChainImpl *swapchain;
2012 TRACE("(%p)->(%p,%p)\n", This, pPresentationParameters, D3DCB_CreateAdditionalSwapChain);
2013 if(This->d3d_initialized) return WINED3DERR_INVALIDCALL;
2015 /* TODO: Test if OpenGL is compiled in and loaded */
2017 /* Setup the implicit swapchain */
2018 TRACE("Creating implicit swapchain\n");
2019 if (D3D_OK != D3DCB_CreateAdditionalSwapChain((IUnknown *) This->parent, pPresentationParameters, (IWineD3DSwapChain **)&swapchain) || swapchain == NULL) {
2020 WARN("Failed to create implicit swapchain\n");
2021 return WINED3DERR_INVALIDCALL;
2024 This->NumberOfSwapChains = 1;
2025 This->swapchains = HeapAlloc(GetProcessHeap(), 0, This->NumberOfSwapChains * sizeof(IWineD3DSwapChain *));
2026 if(!This->swapchains) {
2027 ERR("Out of memory!\n");
2028 IWineD3DSwapChain_Release( (IWineD3DSwapChain *) swapchain);
2029 return E_OUTOFMEMORY;
2031 This->swapchains[0] = (IWineD3DSwapChain *) swapchain;
2033 if(swapchain->backBuffer && swapchain->backBuffer[0]) {
2034 TRACE("Setting rendertarget to %p\n", swapchain->backBuffer);
2035 This->renderTarget = swapchain->backBuffer[0];
2038 TRACE("Setting rendertarget to %p\n", swapchain->frontBuffer);
2039 This->renderTarget = swapchain->frontBuffer;
2041 IWineD3DSurface_AddRef(This->renderTarget);
2042 /* Depth Stencil support */
2043 This->stencilBufferTarget = This->depthStencilBuffer;
2044 if (NULL != This->stencilBufferTarget) {
2045 IWineD3DSurface_AddRef(This->stencilBufferTarget);
2048 /* Set up some starting GL setup */
2051 * Initialize openGL extension related variables
2052 * with Default values
2055 ((IWineD3DImpl *) This->wineD3D)->isGLInfoValid = IWineD3DImpl_FillGLCaps( &((IWineD3DImpl *) This->wineD3D)->gl_info, swapchain->display);
2056 /* Setup all the devices defaults */
2057 IWineD3DStateBlock_InitStartupStateBlock((IWineD3DStateBlock *)This->stateBlock);
2059 IWineD3DImpl_CheckGraphicsMemory();
2063 /* Initialize our list of GLSL programs */
2064 list_init(&This->glsl_shader_progs);
2066 { /* Set a default viewport */
2070 vp.Width = *(pPresentationParameters->BackBufferWidth);
2071 vp.Height = *(pPresentationParameters->BackBufferHeight);
2074 IWineD3DDevice_SetViewport((IWineD3DDevice *)This, &vp);
2077 /* Initialize the current view state */
2078 This->modelview_valid = 1;
2079 This->proj_valid = 0;
2080 This->view_ident = 1;
2081 This->last_was_rhw = 0;
2082 glGetIntegerv(GL_MAX_LIGHTS, &This->maxConcurrentLights);
2083 TRACE("(%p) All defaults now set up, leaving Init3D with %p\n", This, This);
2085 /* Clear the screen */
2086 IWineD3DDevice_Clear((IWineD3DDevice *) This, 0, NULL, D3DCLEAR_STENCIL|D3DCLEAR_ZBUFFER|D3DCLEAR_TARGET, 0x00, 1.0, 0);
2088 This->d3d_initialized = TRUE;
2092 static HRESULT WINAPI IWineD3DDeviceImpl_Uninit3D(IWineD3DDevice *iface) {
2093 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *) iface;
2095 IUnknown* stencilBufferParent;
2096 IUnknown* swapChainParent;
2098 TRACE("(%p)\n", This);
2100 if(!This->d3d_initialized) return WINED3DERR_INVALIDCALL;
2102 for(sampler = 0; sampler < GL_LIMITS(sampler_stages); ++sampler) {
2103 IWineD3DDevice_SetTexture(iface, sampler, NULL);
2106 /* Release the buffers (with sanity checks)*/
2107 TRACE("Releasing the depth stencil buffer at %p\n", This->stencilBufferTarget);
2108 if(This->stencilBufferTarget != NULL && (IWineD3DSurface_Release(This->stencilBufferTarget) >0)){
2109 if(This->depthStencilBuffer != This->stencilBufferTarget)
2110 FIXME("(%p) Something's still holding the depthStencilBuffer\n",This);
2112 This->stencilBufferTarget = NULL;
2114 TRACE("Releasing the render target at %p\n", This->renderTarget);
2115 if(IWineD3DSurface_Release(This->renderTarget) >0){
2116 /* This check is a bit silly, itshould be in swapchain_release FIXME("(%p) Something's still holding the renderTarget\n",This); */
2118 TRACE("Setting rendertarget to NULL\n");
2119 This->renderTarget = NULL;
2121 IWineD3DSurface_GetParent(This->depthStencilBuffer, &stencilBufferParent);
2122 IUnknown_Release(stencilBufferParent); /* once for the get parent */
2123 if(IUnknown_Release(stencilBufferParent) >0){ /* the second time for when it was created */
2124 FIXME("(%p) Something's still holding the depthStencilBuffer\n",This);
2126 This->depthStencilBuffer = NULL;
2128 for(i=0; i < This->NumberOfSwapChains; i++) {
2129 TRACE("Releasing the implicit swapchain %d\n", i);
2130 /* Swapchain 0 is special because it's created in startup with a hanging parent, so we have to release its parent now */
2131 IWineD3DSwapChain_GetParent(This->swapchains[i], &swapChainParent);
2132 IUnknown_Release(swapChainParent); /* once for the get parent */
2133 if (IUnknown_Release(swapChainParent) > 0) { /* the second time for when it was created */
2134 FIXME("(%p) Something's still holding the implicit swapchain\n", This);
2138 HeapFree(GetProcessHeap(), 0, This->swapchains);
2139 This->swapchains = NULL;
2140 This->NumberOfSwapChains = 0;
2142 This->d3d_initialized = FALSE;
2146 static HRESULT WINAPI IWineD3DDeviceImpl_EnumDisplayModes(IWineD3DDevice *iface, DWORD Flags, UINT Width, UINT Height, WINED3DFORMAT pixelformat, LPVOID context, D3DCB_ENUMDISPLAYMODESCALLBACK callback) {
2147 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2151 const PixelFormatDesc *formatDesc = getFormatDescEntry(pixelformat);
2153 TRACE("(%p)->(%lx,%d,%d,%d,%p,%p)\n", This, Flags, Width, Height, pixelformat, context, callback);
2155 for (i = 0; EnumDisplaySettingsExW(NULL, i, &DevModeW, 0); i++) {
2156 /* Ignore some modes if a description was passed */
2157 if ( (Width > 0) && (Width != DevModeW.dmPelsWidth)) continue;
2158 if ( (Height > 0) && (Height != DevModeW.dmPelsHeight)) continue;
2159 if ( (pixelformat != WINED3DFMT_UNKNOWN) && ( formatDesc->bpp != DevModeW.dmBitsPerPel) ) continue;
2161 TRACE("Enumerating %ldx%ld@%s\n", DevModeW.dmPelsWidth, DevModeW.dmPelsHeight, debug_d3dformat(pixelformat_for_depth(DevModeW.dmBitsPerPel)));
2163 if (callback((IUnknown *) This, (UINT) DevModeW.dmPelsWidth, (UINT) DevModeW.dmPelsHeight, pixelformat_for_depth(DevModeW.dmBitsPerPel), 60.0, context) == DDENUMRET_CANCEL)
2170 static HRESULT WINAPI IWineD3DDeviceImpl_SetDisplayMode(IWineD3DDevice *iface, UINT iSwapChain, WINED3DDISPLAYMODE* pMode) {
2172 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2174 const PixelFormatDesc *formatDesc = getFormatDescEntry(pMode->Format);
2176 TRACE("(%p)->(%d,%p) Mode=%dx%dx@%d, %s\n", This, iSwapChain, pMode, pMode->Width, pMode->Height, pMode->RefreshRate, debug_d3dformat(pMode->Format));
2178 /* Resize the screen even without a window:
2179 * The app could have unset it with SetCooperativeLevel, but not called
2180 * RestoreDisplayMode first. Then the release will call RestoreDisplayMode,
2181 * but we don't have any hwnd
2184 devmode.dmFields = DM_BITSPERPEL | DM_PELSWIDTH | DM_PELSHEIGHT;
2185 devmode.dmBitsPerPel = formatDesc->bpp * 8;
2186 if(devmode.dmBitsPerPel == 24) devmode.dmBitsPerPel = 32;
2187 devmode.dmPelsWidth = pMode->Width;
2188 devmode.dmPelsHeight = pMode->Height;
2190 devmode.dmDisplayFrequency = pMode->RefreshRate;
2191 if (pMode->RefreshRate != 0) {
2192 devmode.dmFields |= DM_DISPLAYFREQUENCY;
2195 /* Only change the mode if necessary */
2196 if( (This->ddraw_width == pMode->Width) &&
2197 (This->ddraw_height == pMode->Height) &&
2198 (This->ddraw_format == pMode->Format) &&
2199 (pMode->RefreshRate == 0) ) {
2203 ret = ChangeDisplaySettingsExW(NULL, &devmode, NULL, CDS_FULLSCREEN, NULL);
2204 if (ret != DISP_CHANGE_SUCCESSFUL) {
2205 if(devmode.dmDisplayFrequency != 0) {
2206 WARN("ChangeDisplaySettingsExW failed, trying without the refresh rate\n");
2207 devmode.dmFields &= ~DM_DISPLAYFREQUENCY;
2208 devmode.dmDisplayFrequency = 0;
2209 ret = ChangeDisplaySettingsExW(NULL, &devmode, NULL, CDS_FULLSCREEN, NULL) != DISP_CHANGE_SUCCESSFUL;
2211 if(ret != DISP_CHANGE_SUCCESSFUL) {
2212 return DDERR_INVALIDMODE;
2216 /* Store the new values */
2217 This->ddraw_width = pMode->Width;
2218 This->ddraw_height = pMode->Height;
2219 This->ddraw_format = pMode->Format;
2221 /* Only do this with a window of course */
2222 if(This->ddraw_window)
2223 MoveWindow(This->ddraw_window, 0, 0, pMode->Width, pMode->Height, TRUE);
2228 static HRESULT WINAPI IWineD3DDeviceImpl_EnumZBufferFormats(IWineD3DDevice *iface, D3DCB_ENUMPIXELFORMATS Callback, void *Context) {
2229 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *) iface;
2232 WINED3DFORMAT FormatList[] = {
2239 WINED3DFMT_UNKNOWN /* Terminate the list */
2242 TRACE("(%p)->(%p,%p)\n", This, Callback, Context);
2244 while(FormatList[i] != WINED3DFMT_UNKNOWN) {
2245 TRACE("Enumerating %s\n", debug_d3dformat(FormatList[i]));
2246 ret = Callback((IUnknown *) This, FormatList[i], Context);
2247 if(ret != DDENUMRET_OK) {
2248 TRACE("Enumeration cancelled by Application\n");
2254 TRACE("End of Enumeration\n");
2259 static HRESULT WINAPI IWineD3DDeviceImpl_EnumTextureFormats(IWineD3DDevice *iface, D3DCB_ENUMPIXELFORMATS Callback, void *Context) {
2260 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *) iface;
2265 * WINED3DFMT_A1R5G5B5 needs to be the first 16 bit format, as some dumb apps depend on this
2267 * Do not enumerate RGBA pixel formats: "some games choose the first 16 bit texture format
2268 * with alpha they find enumerated, others the last one. And both want to have the ARGB one."
2269 * But WineD3D doesn't support RGBA formats anyway...
2272 WINED3DFORMAT FormatList[] = {
2274 WINED3DFMT_A8R8G8B8,
2275 WINED3DFMT_X8R8G8B8,
2279 WINED3DFMT_A1R5G5B5,
2280 WINED3DFMT_A4R4G4B4,
2282 WINED3DFMT_X1R5G5B5,
2290 /* Terminate the list */
2294 TRACE("(%p)->(%p,%p)\n", This, Callback, Context);
2296 while(FormatList[i] != WINED3DFMT_UNKNOWN) {
2297 TRACE("Enumerating %s\n", debug_d3dformat(FormatList[i]));
2298 ret = Callback((IUnknown *) This, FormatList[i], Context);
2299 if(ret != DDENUMRET_OK) {
2300 TRACE("Enumeration cancelled by Application\n");
2306 TRACE("End of Enumeration\n");
2311 static HRESULT WINAPI IWineD3DDeviceImpl_GetDirect3D(IWineD3DDevice *iface, IWineD3D **ppD3D) {
2312 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2313 *ppD3D= This->wineD3D;
2314 TRACE("(%p) : wineD3D returning %p\n", This, *ppD3D);
2315 IWineD3D_AddRef(*ppD3D);
2319 static UINT WINAPI IWineD3DDeviceImpl_GetAvailableTextureMem(IWineD3DDevice *iface) {
2320 /** NOTE: There's a probably a hack-around for this one by putting as many pbuffers, VBO's (or whatever)
2321 * Into the video ram as possible and seeing how many fit
2322 * you can also get the correct initial value from via X and ATI's driver
2323 *******************/
2324 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2325 static BOOL showfixmes = TRUE;
2327 FIXME("(%p) : stub, emulating %dMB for now, returning %dMB\n", This, (emulated_textureram/(1024*1024)),
2328 ((emulated_textureram - wineD3DGlobalStatistics->glsurfaceram) / (1024*1024)));
2331 TRACE("(%p) : emulating %dMB for now, returning %dMB\n", This, (emulated_textureram/(1024*1024)),
2332 ((emulated_textureram - wineD3DGlobalStatistics->glsurfaceram) / (1024*1024)));
2333 /* videomemory is simulated videomemory + AGP memory left */
2334 return (emulated_textureram - wineD3DGlobalStatistics->glsurfaceram);
2342 static HRESULT WINAPI IWineD3DDeviceImpl_SetFVF(IWineD3DDevice *iface, DWORD fvf) {
2343 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2344 HRESULT hr = WINED3D_OK;
2346 /* Update the current state block */
2347 This->updateStateBlock->fvf = fvf;
2348 This->updateStateBlock->changed.fvf = TRUE;
2349 This->updateStateBlock->set.fvf = TRUE;
2351 TRACE("(%p) : FVF Shader FVF set to %lx\n", This, fvf);
2356 static HRESULT WINAPI IWineD3DDeviceImpl_GetFVF(IWineD3DDevice *iface, DWORD *pfvf) {
2357 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2358 TRACE("(%p) : GetFVF returning %lx\n", This, This->stateBlock->fvf);
2359 *pfvf = This->stateBlock->fvf;
2364 * Get / Set Stream Source
2366 static HRESULT WINAPI IWineD3DDeviceImpl_SetStreamSource(IWineD3DDevice *iface, UINT StreamNumber,IWineD3DVertexBuffer* pStreamData, UINT OffsetInBytes, UINT Stride) {
2367 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2368 IWineD3DVertexBuffer *oldSrc;
2370 /**TODO: instance and index data, see
2371 http://msdn.microsoft.com/library/default.asp?url=/library/en-us/directx9_c/directx/graphics/programmingguide/advancedtopics/DrawingMultipleInstances.asp
2373 http://msdn.microsoft.com/library/default.asp?url=/library/en-us/directx9_c/directx/graphics/reference/d3d/interfaces/idirect3ddevice9/SetStreamSourceFreq.asp
2376 /* D3d9 only, but shouldn't hurt d3d8 */
2379 streamFlags = StreamNumber &(D3DSTREAMSOURCE_INDEXEDDATA | D3DSTREAMSOURCE_INSTANCEDATA);
2381 if (streamFlags & D3DSTREAMSOURCE_INDEXEDDATA) {
2382 FIXME("stream index data not supported\n");
2384 if (streamFlags & D3DSTREAMSOURCE_INDEXEDDATA) {
2385 FIXME("stream instance data not supported\n");
2389 StreamNumber&= ~(D3DSTREAMSOURCE_INDEXEDDATA | D3DSTREAMSOURCE_INSTANCEDATA);
2391 if (StreamNumber >= MAX_STREAMS) {
2392 WARN("Stream out of range %d\n", StreamNumber);
2393 return WINED3DERR_INVALIDCALL;
2396 oldSrc = This->stateBlock->streamSource[StreamNumber];
2397 TRACE("(%p) : StreamNo: %d, OldStream (%p), NewStream (%p), NewStride %d\n", This, StreamNumber, oldSrc, pStreamData, Stride);
2399 This->updateStateBlock->changed.streamSource[StreamNumber] = TRUE;
2400 This->updateStateBlock->set.streamSource[StreamNumber] = TRUE;
2401 This->updateStateBlock->streamStride[StreamNumber] = Stride;
2402 This->updateStateBlock->streamSource[StreamNumber] = pStreamData;
2403 This->updateStateBlock->streamOffset[StreamNumber] = OffsetInBytes;
2404 This->updateStateBlock->streamFlags[StreamNumber] = streamFlags;
2406 /* Handle recording of state blocks */
2407 if (This->isRecordingState) {
2408 TRACE("Recording... not performing anything\n");
2412 /* Same stream object: no action */
2413 if (oldSrc == pStreamData)
2416 /* Need to do a getParent and pass the reffs up */
2417 /* MSDN says ..... When an application no longer holds a references to this interface, the interface will automatically be freed.
2418 which suggests that we shouldn't be ref counting? and do need a _release on the stream source to reset the stream source
2419 so for now, just count internally */
2420 if (pStreamData != NULL) {
2421 IWineD3DVertexBufferImpl *vbImpl = (IWineD3DVertexBufferImpl *) pStreamData;
2422 if( (vbImpl->Flags & VBFLAG_STREAM) && vbImpl->stream != StreamNumber) {
2423 WARN("Assigning a Vertex Buffer to stream %d which is already assigned to stream %d\n", StreamNumber, vbImpl->stream);
2425 vbImpl->stream = StreamNumber;
2426 vbImpl->Flags |= VBFLAG_STREAM;
2427 IWineD3DVertexBuffer_AddRef(pStreamData);
2429 if (oldSrc != NULL) {
2430 ((IWineD3DVertexBufferImpl *) oldSrc)->Flags &= ~VBFLAG_STREAM;
2431 IWineD3DVertexBuffer_Release(oldSrc);
2437 static HRESULT WINAPI IWineD3DDeviceImpl_GetStreamSource(IWineD3DDevice *iface, UINT StreamNumber,IWineD3DVertexBuffer** pStream, UINT *pOffset, UINT* pStride) {
2438 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2441 TRACE("(%p) : StreamNo: %d, Stream (%p), Stride %d\n", This, StreamNumber,
2442 This->stateBlock->streamSource[StreamNumber], This->stateBlock->streamStride[StreamNumber]);
2445 streamFlags = StreamNumber &(D3DSTREAMSOURCE_INDEXEDDATA | D3DSTREAMSOURCE_INSTANCEDATA);
2447 if (streamFlags & D3DSTREAMSOURCE_INDEXEDDATA) {
2448 FIXME("stream index data not supported\n");
2450 if (streamFlags & D3DSTREAMSOURCE_INDEXEDDATA) {
2451 FIXME("stream instance data not supported\n");
2455 StreamNumber&= ~(D3DSTREAMSOURCE_INDEXEDDATA | D3DSTREAMSOURCE_INSTANCEDATA);
2457 if (StreamNumber >= MAX_STREAMS) {
2458 WARN("Stream out of range %d\n", StreamNumber);
2459 return WINED3DERR_INVALIDCALL;
2461 *pStream = This->stateBlock->streamSource[StreamNumber];
2462 *pStride = This->stateBlock->streamStride[StreamNumber];
2463 *pOffset = This->stateBlock->streamOffset[StreamNumber];
2465 if (*pStream == NULL) {
2466 FIXME("Attempting to get an empty stream %d, returning WINED3DERR_INVALIDCALL\n", StreamNumber);
2467 return WINED3DERR_INVALIDCALL;
2470 IWineD3DVertexBuffer_AddRef(*pStream); /* We have created a new reference to the VB */
2474 /*Should be quite easy, just an extension of vertexdata
2476 http://msdn.microsoft.com/archive/default.asp?url=/archive/en-us/directx9_c_Summer_04/directx/graphics/programmingguide/advancedtopics/DrawingMultipleInstances.asp
2478 The divider is a bit odd though
2480 VertexOffset = StartVertex / Divider * StreamStride +
2481 VertexIndex / Divider * StreamStride + StreamOffset
2484 static HRESULT WINAPI IWineD3DDeviceImpl_SetStreamSourceFreq(IWineD3DDevice *iface, UINT StreamNumber, UINT Divider) {
2485 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2487 TRACE("(%p) StreamNumber(%d), Divider(%d)\n", This, StreamNumber, Divider);
2488 This->updateStateBlock->streamFlags[StreamNumber] = Divider & (D3DSTREAMSOURCE_INSTANCEDATA | D3DSTREAMSOURCE_INDEXEDDATA );
2490 This->updateStateBlock->changed.streamFreq[StreamNumber] = TRUE;
2491 This->updateStateBlock->set.streamFreq[StreamNumber] = TRUE;
2492 This->updateStateBlock->streamFreq[StreamNumber] = Divider & 0x7FFFFF;
2494 if (This->updateStateBlock->streamFlags[StreamNumber] || This->updateStateBlock->streamFreq[StreamNumber] != 1) {
2495 FIXME("Stream indexing not fully supported\n");
2501 static HRESULT WINAPI IWineD3DDeviceImpl_GetStreamSourceFreq(IWineD3DDevice *iface, UINT StreamNumber, UINT* Divider) {
2502 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2504 TRACE("(%p) StreamNumber(%d), Divider(%p)\n", This, StreamNumber, Divider);
2505 *Divider = This->updateStateBlock->streamFreq[StreamNumber] | This->updateStateBlock->streamFlags[StreamNumber];
2507 TRACE("(%p) : returning %d\n", This, *Divider);
2513 * Get / Set & Multiply Transform
2515 static HRESULT WINAPI IWineD3DDeviceImpl_SetTransform(IWineD3DDevice *iface, D3DTRANSFORMSTATETYPE d3dts, CONST D3DMATRIX* lpmatrix) {
2516 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2518 /* Most of this routine, comments included copied from ddraw tree initially: */
2519 TRACE("(%p) : Transform State=%d\n", This, d3dts);
2521 /* Handle recording of state blocks */
2522 if (This->isRecordingState) {
2523 TRACE("Recording... not performing anything\n");
2524 This->updateStateBlock->changed.transform[d3dts] = TRUE;
2525 This->updateStateBlock->set.transform[d3dts] = TRUE;
2526 memcpy(&This->updateStateBlock->transforms[d3dts], lpmatrix, sizeof(D3DMATRIX));
2531 * If the new matrix is the same as the current one,
2532 * we cut off any further processing. this seems to be a reasonable
2533 * optimization because as was noticed, some apps (warcraft3 for example)
2534 * tend towards setting the same matrix repeatedly for some reason.
2536 * From here on we assume that the new matrix is different, wherever it matters.
2538 if (!memcmp(&This->stateBlock->transforms[d3dts].u.m[0][0], lpmatrix, sizeof(D3DMATRIX))) {
2539 TRACE("The app is setting the same matrix over again\n");
2542 conv_mat(lpmatrix, &This->stateBlock->transforms[d3dts].u.m[0][0]);
2546 ScreenCoord = ProjectionMat * ViewMat * WorldMat * ObjectCoord
2547 where ViewMat = Camera space, WorldMat = world space.
2549 In OpenGL, camera and world space is combined into GL_MODELVIEW
2550 matrix. The Projection matrix stay projection matrix.
2553 /* Capture the times we can just ignore the change for now */
2554 if (d3dts == D3DTS_WORLDMATRIX(0)) {
2555 This->modelview_valid = FALSE;
2558 } else if (d3dts == D3DTS_PROJECTION) {
2559 This->proj_valid = FALSE;
2562 } else if (d3dts >= D3DTS_WORLDMATRIX(1) && d3dts <= D3DTS_WORLDMATRIX(255)) {
2563 /* Indexed Vertex Blending Matrices 256 -> 511 */
2564 /* Use arb_vertex_blend or NV_VERTEX_WEIGHTING? */
2565 FIXME("D3DTS_WORLDMATRIX(1..255) not handled\n");
2569 /* Now we really are going to have to change a matrix */
2572 if (d3dts >= D3DTS_TEXTURE0 && d3dts <= D3DTS_TEXTURE7) { /* handle texture matrices */
2573 /* This is now set with the texture unit states, it may be a good idea to flag the change though! */
2574 } else if (d3dts == D3DTS_VIEW) { /* handle the VIEW matrice */
2577 /* If we are changing the View matrix, reset the light and clipping planes to the new view
2578 * NOTE: We have to reset the positions even if the light/plane is not currently
2579 * enabled, since the call to enable it will not reset the position.
2580 * NOTE2: Apparently texture transforms do NOT need reapplying
2583 PLIGHTINFOEL *lightChain = NULL;
2584 This->modelview_valid = FALSE;
2585 This->view_ident = !memcmp(lpmatrix, identity, 16 * sizeof(float));
2587 glMatrixMode(GL_MODELVIEW);
2588 checkGLcall("glMatrixMode(GL_MODELVIEW)");
2590 glLoadMatrixf((float *)lpmatrix);
2591 checkGLcall("glLoadMatrixf(...)");
2594 lightChain = This->stateBlock->lights;
2595 while (lightChain && lightChain->glIndex != -1) {
2596 glLightfv(GL_LIGHT0 + lightChain->glIndex, GL_POSITION, lightChain->lightPosn);
2597 checkGLcall("glLightfv posn");
2598 glLightfv(GL_LIGHT0 + lightChain->glIndex, GL_SPOT_DIRECTION, lightChain->lightDirn);
2599 checkGLcall("glLightfv dirn");
2600 lightChain = lightChain->next;
2603 /* Reset Clipping Planes if clipping is enabled */
2604 for (k = 0; k < GL_LIMITS(clipplanes); k++) {
2605 glClipPlane(GL_CLIP_PLANE0 + k, This->stateBlock->clipplane[k]);
2606 checkGLcall("glClipPlane");
2610 } else { /* What was requested!?? */
2611 WARN("invalid matrix specified: %i\n", d3dts);
2614 /* Release lock, all done */
2619 static HRESULT WINAPI IWineD3DDeviceImpl_GetTransform(IWineD3DDevice *iface, D3DTRANSFORMSTATETYPE State, D3DMATRIX* pMatrix) {
2620 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2621 TRACE("(%p) : for Transform State %d\n", This, State);
2622 memcpy(pMatrix, &This->stateBlock->transforms[State], sizeof(D3DMATRIX));
2626 static HRESULT WINAPI IWineD3DDeviceImpl_MultiplyTransform(IWineD3DDevice *iface, D3DTRANSFORMSTATETYPE State, CONST D3DMATRIX* pMatrix) {
2627 D3DMATRIX *mat = NULL;
2630 /* Note: Using 'updateStateBlock' rather than 'stateblock' in the code
2631 * below means it will be recorded in a state block change, but it
2632 * works regardless where it is recorded.
2633 * If this is found to be wrong, change to StateBlock.
2635 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2636 TRACE("(%p) : For state %u\n", This, State);
2638 if (State < HIGHEST_TRANSFORMSTATE)
2640 mat = &This->updateStateBlock->transforms[State];
2642 FIXME("Unhandled transform state!!\n");
2645 multiply_matrix(&temp, mat, (D3DMATRIX *) pMatrix);
2647 /* Apply change via set transform - will reapply to eg. lights this way */
2648 return IWineD3DDeviceImpl_SetTransform(iface, State, &temp);
2653 * WARNING: This code relies on the fact that D3DLIGHT8 == D3DLIGHT9
2655 /* Note lights are real special cases. Although the device caps state only eg. 8 are supported,
2656 you can reference any indexes you want as long as that number max are enabled at any
2657 one point in time! Therefore since the indexes can be anything, we need a linked list of them.
2658 However, this causes stateblock problems. When capturing the state block, I duplicate the list,
2659 but when recording, just build a chain pretty much of commands to be replayed. */
2661 static HRESULT WINAPI IWineD3DDeviceImpl_SetLight(IWineD3DDevice *iface, DWORD Index, CONST WINED3DLIGHT* pLight) {
2663 PLIGHTINFOEL *object, *temp;
2665 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2666 TRACE("(%p) : Idx(%ld), pLight(%p)\n", This, Index, pLight);
2668 /* If recording state block, just add to end of lights chain */
2669 if (This->isRecordingState) {
2670 object = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(PLIGHTINFOEL));
2671 if (NULL == object) {
2672 return WINED3DERR_OUTOFVIDEOMEMORY;
2674 memcpy(&object->OriginalParms, pLight, sizeof(D3DLIGHT9));
2675 object->OriginalIndex = Index;
2676 object->glIndex = -1;
2677 object->changed = TRUE;
2679 /* Add to the END of the chain of lights changes to be replayed */
2680 if (This->updateStateBlock->lights == NULL) {
2681 This->updateStateBlock->lights = object;
2683 temp = This->updateStateBlock->lights;
2684 while (temp->next != NULL) temp=temp->next;
2685 temp->next = object;
2687 TRACE("Recording... not performing anything more\n");
2691 /* Ok, not recording any longer so do real work */
2692 object = This->stateBlock->lights;
2693 while (object != NULL && object->OriginalIndex != Index) object = object->next;
2695 /* If we didn't find it in the list of lights, time to add it */
2696 if (object == NULL) {
2697 PLIGHTINFOEL *insertAt,*prevPos;
2699 object = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(PLIGHTINFOEL));
2700 if (NULL == object) {
2701 return WINED3DERR_OUTOFVIDEOMEMORY;
2703 object->OriginalIndex = Index;
2704 object->glIndex = -1;
2706 /* Add it to the front of list with the idea that lights will be changed as needed
2707 BUT after any lights currently assigned GL indexes */
2708 insertAt = This->stateBlock->lights;
2710 while (insertAt != NULL && insertAt->glIndex != -1) {
2712 insertAt = insertAt->next;
2715 if (insertAt == NULL && prevPos == NULL) { /* Start of list */
2716 This->stateBlock->lights = object;
2717 } else if (insertAt == NULL) { /* End of list */
2718 prevPos->next = object;
2719 object->prev = prevPos;
2720 } else { /* Middle of chain */
2721 if (prevPos == NULL) {
2722 This->stateBlock->lights = object;
2724 prevPos->next = object;
2726 object->prev = prevPos;
2727 object->next = insertAt;
2728 insertAt->prev = object;
2732 /* Initialize the object */
2733 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,
2734 pLight->Diffuse.r, pLight->Diffuse.g, pLight->Diffuse.b, pLight->Diffuse.a,
2735 pLight->Specular.r, pLight->Specular.g, pLight->Specular.b, pLight->Specular.a,
2736 pLight->Ambient.r, pLight->Ambient.g, pLight->Ambient.b, pLight->Ambient.a);
2737 TRACE("... Pos(%f,%f,%f), Dirn(%f,%f,%f)\n", pLight->Position.x, pLight->Position.y, pLight->Position.z,
2738 pLight->Direction.x, pLight->Direction.y, pLight->Direction.z);
2739 TRACE("... Range(%f), Falloff(%f), Theta(%f), Phi(%f)\n", pLight->Range, pLight->Falloff, pLight->Theta, pLight->Phi);
2741 /* Save away the information */
2742 memcpy(&object->OriginalParms, pLight, sizeof(D3DLIGHT9));
2744 switch (pLight->Type) {
2745 case D3DLIGHT_POINT:
2747 object->lightPosn[0] = pLight->Position.x;
2748 object->lightPosn[1] = pLight->Position.y;
2749 object->lightPosn[2] = pLight->Position.z;
2750 object->lightPosn[3] = 1.0f;
2751 object->cutoff = 180.0f;
2755 case D3DLIGHT_DIRECTIONAL:
2757 object->lightPosn[0] = -pLight->Direction.x;
2758 object->lightPosn[1] = -pLight->Direction.y;
2759 object->lightPosn[2] = -pLight->Direction.z;
2760 object->lightPosn[3] = 0.0;
2761 object->exponent = 0.0f;
2762 object->cutoff = 180.0f;
2767 object->lightPosn[0] = pLight->Position.x;
2768 object->lightPosn[1] = pLight->Position.y;
2769 object->lightPosn[2] = pLight->Position.z;
2770 object->lightPosn[3] = 1.0;
2773 object->lightDirn[0] = pLight->Direction.x;
2774 object->lightDirn[1] = pLight->Direction.y;
2775 object->lightDirn[2] = pLight->Direction.z;
2776 object->lightDirn[3] = 1.0;
2779 * opengl-ish and d3d-ish spot lights use too different models for the
2780 * light "intensity" as a function of the angle towards the main light direction,
2781 * so we only can approximate very roughly.
2782 * however spot lights are rather rarely used in games (if ever used at all).
2783 * furthermore if still used, probably nobody pays attention to such details.
2785 if (pLight->Falloff == 0) {
2788 rho = pLight->Theta + (pLight->Phi - pLight->Theta)/(2*pLight->Falloff);
2790 if (rho < 0.0001) rho = 0.0001f;
2791 object->exponent = -0.3/log(cos(rho/2));
2792 object->cutoff = pLight->Phi*90/M_PI;
2798 FIXME("Unrecognized light type %d\n", pLight->Type);
2801 /* Update the live definitions if the light is currently assigned a glIndex */
2802 if (object->glIndex != -1) {
2803 setup_light(iface, object->glIndex, object);
2808 static HRESULT WINAPI IWineD3DDeviceImpl_GetLight(IWineD3DDevice *iface, DWORD Index, WINED3DLIGHT* pLight) {
2809 PLIGHTINFOEL *lightInfo = NULL;
2810 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2811 TRACE("(%p) : Idx(%ld), pLight(%p)\n", This, Index, pLight);
2813 /* Locate the light in the live lights */
2814 lightInfo = This->stateBlock->lights;
2815 while (lightInfo != NULL && lightInfo->OriginalIndex != Index) lightInfo = lightInfo->next;
2817 if (lightInfo == NULL) {
2818 TRACE("Light information requested but light not defined\n");
2819 return WINED3DERR_INVALIDCALL;
2822 memcpy(pLight, &lightInfo->OriginalParms, sizeof(D3DLIGHT9));
2827 * Get / Set Light Enable
2828 * (Note for consistency, renamed d3dx function by adding the 'set' prefix)
2830 static HRESULT WINAPI IWineD3DDeviceImpl_SetLightEnable(IWineD3DDevice *iface, DWORD Index, BOOL Enable) {
2831 PLIGHTINFOEL *lightInfo = NULL;
2832 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2833 TRACE("(%p) : Idx(%ld), enable? %d\n", This, Index, Enable);
2835 /* If recording state block, just add to end of lights chain with changedEnable set to true */
2836 if (This->isRecordingState) {
2837 lightInfo = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(PLIGHTINFOEL));
2838 if (NULL == lightInfo) {
2839 return WINED3DERR_OUTOFVIDEOMEMORY;
2841 lightInfo->OriginalIndex = Index;
2842 lightInfo->glIndex = -1;
2843 lightInfo->enabledChanged = TRUE;
2845 /* Add to the END of the chain of lights changes to be replayed */
2846 if (This->updateStateBlock->lights == NULL) {
2847 This->updateStateBlock->lights = lightInfo;
2849 PLIGHTINFOEL *temp = This->updateStateBlock->lights;
2850 while (temp->next != NULL) temp=temp->next;
2851 temp->next = lightInfo;
2853 TRACE("Recording... not performing anything more\n");
2857 /* Not recording... So, locate the light in the live lights */
2858 lightInfo = This->stateBlock->lights;
2859 while (lightInfo != NULL && lightInfo->OriginalIndex != Index) lightInfo = lightInfo->next;
2861 /* Special case - enabling an undefined light creates one with a strict set of parms! */
2862 if (lightInfo == NULL) {
2864 TRACE("Light enabled requested but light not defined, so defining one!\n");
2865 IWineD3DDeviceImpl_SetLight(iface, Index, &WINED3D_default_light);
2867 /* Search for it again! Should be fairly quick as near head of list */
2868 lightInfo = This->stateBlock->lights;
2869 while (lightInfo != NULL && lightInfo->OriginalIndex != Index) lightInfo = lightInfo->next;
2870 if (lightInfo == NULL) {
2871 FIXME("Adding default lights has failed dismally\n");
2872 return WINED3DERR_INVALIDCALL;
2876 /* OK, we now have a light... */
2877 if (Enable == FALSE) {
2879 /* If we are disabling it, check it was enabled, and
2880 still only do something if it has assigned a glIndex (which it should have!) */
2881 if ((lightInfo->lightEnabled) && (lightInfo->glIndex != -1)) {
2882 TRACE("Disabling light set up at gl idx %ld\n", lightInfo->glIndex);
2884 glDisable(GL_LIGHT0 + lightInfo->glIndex);
2885 checkGLcall("glDisable GL_LIGHT0+Index");
2888 TRACE("Nothing to do as light was not enabled\n");
2890 lightInfo->lightEnabled = FALSE;
2893 /* We are enabling it. If it is enabled, it's really simple */
2894 if (lightInfo->lightEnabled) {
2896 TRACE("Nothing to do as light was enabled\n");
2898 /* If it already has a glIndex, it's still simple */
2899 } else if (lightInfo->glIndex != -1) {
2900 TRACE("Reusing light as already set up at gl idx %ld\n", lightInfo->glIndex);
2901 lightInfo->lightEnabled = TRUE;
2903 glEnable(GL_LIGHT0 + lightInfo->glIndex);
2904 checkGLcall("glEnable GL_LIGHT0+Index already setup");
2907 /* Otherwise got to find space - lights are ordered gl indexes first */
2909 PLIGHTINFOEL *bsf = NULL;
2910 PLIGHTINFOEL *pos = This->stateBlock->lights;
2911 PLIGHTINFOEL *prev = NULL;
2915 /* Try to minimize changes as much as possible */
2916 while (pos != NULL && pos->glIndex != -1 && Index < This->maxConcurrentLights) {
2918 /* Try to remember which index can be replaced if necessary */
2919 if (bsf==NULL && pos->lightEnabled == FALSE) {
2920 /* Found a light we can replace, save as best replacement */
2924 /* Step to next space */
2930 /* If we have too many active lights, fail the call */
2931 if ((Index == This->maxConcurrentLights) && (bsf == NULL)) {
2932 FIXME("Program requests too many concurrent lights\n");
2933 return WINED3DERR_INVALIDCALL;
2935 /* If we have allocated all lights, but not all are enabled,
2936 reuse one which is not enabled */
2937 } else if (Index == This->maxConcurrentLights) {
2938 /* use bsf - Simply swap the new light and the BSF one */
2939 PLIGHTINFOEL *bsfNext = bsf->next;
2940 PLIGHTINFOEL *bsfPrev = bsf->prev;
2943 if (lightInfo->next != NULL) lightInfo->next->prev = bsf;
2944 if (bsf->prev != NULL) {
2945 bsf->prev->next = lightInfo;
2947 This->stateBlock->lights = lightInfo;
2950 /* If not side by side, lots of chains to update */
2951 if (bsf->next != lightInfo) {
2952 lightInfo->prev->next = bsf;
2953 bsf->next->prev = lightInfo;
2954 bsf->next = lightInfo->next;
2955 bsf->prev = lightInfo->prev;
2956 lightInfo->next = bsfNext;
2957 lightInfo->prev = bsfPrev;
2961 bsf->prev = lightInfo;
2962 bsf->next = lightInfo->next;
2963 lightInfo->next = bsf;
2964 lightInfo->prev = bsfPrev;
2969 glIndex = bsf->glIndex;
2971 lightInfo->glIndex = glIndex;
2972 lightInfo->lightEnabled = TRUE;
2974 /* Finally set up the light in gl itself */
2975 TRACE("Replacing light which was set up at gl idx %ld\n", lightInfo->glIndex);
2977 setup_light(iface, glIndex, lightInfo);
2978 glEnable(GL_LIGHT0 + glIndex);
2979 checkGLcall("glEnable GL_LIGHT0 new setup");
2982 /* If we reached the end of the allocated lights, with space in the
2983 gl lights, setup a new light */
2984 } else if (pos->glIndex == -1) {
2986 /* We reached the end of the allocated gl lights, so already
2987 know the index of the next one! */
2989 lightInfo->glIndex = glIndex;
2990 lightInfo->lightEnabled = TRUE;
2992 /* In an ideal world, it's already in the right place */
2993 if (lightInfo->prev == NULL || lightInfo->prev->glIndex!=-1) {
2994 /* No need to move it */
2996 /* Remove this light from the list */
2997 lightInfo->prev->next = lightInfo->next;
2998 if (lightInfo->next != NULL) {
2999 lightInfo->next->prev = lightInfo->prev;
3002 /* Add in at appropriate place (inbetween prev and pos) */
3003 lightInfo->prev = prev;
3004 lightInfo->next = pos;
3006 This->stateBlock->lights = lightInfo;
3008 prev->next = lightInfo;
3011 pos->prev = lightInfo;
3015 /* Finally set up the light in gl itself */
3016 TRACE("Defining new light at gl idx %ld\n", lightInfo->glIndex);
3018 setup_light(iface, glIndex, lightInfo);
3019 glEnable(GL_LIGHT0 + glIndex);
3020 checkGLcall("glEnable GL_LIGHT0 new setup");
3029 static HRESULT WINAPI IWineD3DDeviceImpl_GetLightEnable(IWineD3DDevice *iface, DWORD Index,BOOL* pEnable) {
3031 PLIGHTINFOEL *lightInfo = NULL;
3032 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3033 TRACE("(%p) : for idx(%ld)\n", This, Index);
3035 /* Locate the light in the live lights */
3036 lightInfo = This->stateBlock->lights;
3037 while (lightInfo != NULL && lightInfo->OriginalIndex != Index) lightInfo = lightInfo->next;
3039 if (lightInfo == NULL) {
3040 TRACE("Light enabled state requested but light not defined\n");
3041 return WINED3DERR_INVALIDCALL;
3043 *pEnable = lightInfo->lightEnabled;
3048 * Get / Set Clip Planes
3050 static HRESULT WINAPI IWineD3DDeviceImpl_SetClipPlane(IWineD3DDevice *iface, DWORD Index, CONST float *pPlane) {
3051 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3052 TRACE("(%p) : for idx %ld, %p\n", This, Index, pPlane);
3054 /* Validate Index */
3055 if (Index >= GL_LIMITS(clipplanes)) {
3056 TRACE("Application has requested clipplane this device doesn't support\n");
3057 return WINED3DERR_INVALIDCALL;
3060 This->updateStateBlock->changed.clipplane[Index] = TRUE;
3061 This->updateStateBlock->set.clipplane[Index] = TRUE;
3062 This->updateStateBlock->clipplane[Index][0] = pPlane[0];
3063 This->updateStateBlock->clipplane[Index][1] = pPlane[1];
3064 This->updateStateBlock->clipplane[Index][2] = pPlane[2];
3065 This->updateStateBlock->clipplane[Index][3] = pPlane[3];
3067 /* Handle recording of state blocks */
3068 if (This->isRecordingState) {
3069 TRACE("Recording... not performing anything\n");
3077 /* Clip Plane settings are affected by the model view in OpenGL, the View transform in direct3d */
3078 glMatrixMode(GL_MODELVIEW);
3080 glLoadMatrixf((float *) &This->stateBlock->transforms[D3DTS_VIEW].u.m[0][0]);
3082 TRACE("Clipplane [%f,%f,%f,%f]\n",
3083 This->updateStateBlock->clipplane[Index][0],
3084 This->updateStateBlock->clipplane[Index][1],
3085 This->updateStateBlock->clipplane[Index][2],
3086 This->updateStateBlock->clipplane[Index][3]);
3087 glClipPlane(GL_CLIP_PLANE0 + Index, This->updateStateBlock->clipplane[Index]);
3088 checkGLcall("glClipPlane");
3096 static HRESULT WINAPI IWineD3DDeviceImpl_GetClipPlane(IWineD3DDevice *iface, DWORD Index, float *pPlane) {
3097 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3098 TRACE("(%p) : for idx %ld\n", This, Index);
3100 /* Validate Index */
3101 if (Index >= GL_LIMITS(clipplanes)) {
3102 TRACE("Application has requested clipplane this device doesn't support\n");
3103 return WINED3DERR_INVALIDCALL;
3106 pPlane[0] = This->stateBlock->clipplane[Index][0];
3107 pPlane[1] = This->stateBlock->clipplane[Index][1];
3108 pPlane[2] = This->stateBlock->clipplane[Index][2];
3109 pPlane[3] = This->stateBlock->clipplane[Index][3];
3114 * Get / Set Clip Plane Status
3115 * WARNING: This code relies on the fact that D3DCLIPSTATUS8 == D3DCLIPSTATUS9
3117 static HRESULT WINAPI IWineD3DDeviceImpl_SetClipStatus(IWineD3DDevice *iface, CONST WINED3DCLIPSTATUS* pClipStatus) {
3118 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3119 FIXME("(%p) : stub\n", This);
3120 if (NULL == pClipStatus) {
3121 return WINED3DERR_INVALIDCALL;
3123 This->updateStateBlock->clip_status.ClipUnion = pClipStatus->ClipUnion;
3124 This->updateStateBlock->clip_status.ClipIntersection = pClipStatus->ClipIntersection;
3128 static HRESULT WINAPI IWineD3DDeviceImpl_GetClipStatus(IWineD3DDevice *iface, WINED3DCLIPSTATUS* pClipStatus) {
3129 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3130 FIXME("(%p) : stub\n", This);
3131 if (NULL == pClipStatus) {
3132 return WINED3DERR_INVALIDCALL;
3134 pClipStatus->ClipUnion = This->updateStateBlock->clip_status.ClipUnion;
3135 pClipStatus->ClipIntersection = This->updateStateBlock->clip_status.ClipIntersection;
3140 * Get / Set Material
3141 * WARNING: This code relies on the fact that D3DMATERIAL8 == D3DMATERIAL9
3143 static HRESULT WINAPI IWineD3DDeviceImpl_SetMaterial(IWineD3DDevice *iface, CONST WINED3DMATERIAL* pMaterial) {
3144 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3146 This->updateStateBlock->changed.material = TRUE;
3147 This->updateStateBlock->set.material = TRUE;
3148 memcpy(&This->updateStateBlock->material, pMaterial, sizeof(WINED3DMATERIAL));
3150 /* Handle recording of state blocks */
3151 if (This->isRecordingState) {
3152 TRACE("Recording... not performing anything\n");
3157 TRACE("(%p) : Diffuse (%f,%f,%f,%f)\n", This, pMaterial->Diffuse.r, pMaterial->Diffuse.g,
3158 pMaterial->Diffuse.b, pMaterial->Diffuse.a);
3159 TRACE("(%p) : Ambient (%f,%f,%f,%f)\n", This, pMaterial->Ambient.r, pMaterial->Ambient.g,
3160 pMaterial->Ambient.b, pMaterial->Ambient.a);
3161 TRACE("(%p) : Specular (%f,%f,%f,%f)\n", This, pMaterial->Specular.r, pMaterial->Specular.g,
3162 pMaterial->Specular.b, pMaterial->Specular.a);
3163 TRACE("(%p) : Emissive (%f,%f,%f,%f)\n", This, pMaterial->Emissive.r, pMaterial->Emissive.g,
3164 pMaterial->Emissive.b, pMaterial->Emissive.a);
3165 TRACE("(%p) : Power (%f)\n", This, pMaterial->Power);
3167 glMaterialfv(GL_FRONT_AND_BACK, GL_AMBIENT, (float*) &This->updateStateBlock->material.Ambient);
3168 checkGLcall("glMaterialfv(GL_AMBIENT)");
3169 glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, (float*) &This->updateStateBlock->material.Diffuse);
3170 checkGLcall("glMaterialfv(GL_DIFFUSE)");
3172 /* Only change material color if specular is enabled, otherwise it is set to black */
3173 if (This->stateBlock->renderState[WINED3DRS_SPECULARENABLE]) {
3174 glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, (float*) &This->updateStateBlock->material.Specular);
3175 checkGLcall("glMaterialfv(GL_SPECULAR");
3177 float black[4] = {0.0f, 0.0f, 0.0f, 0.0f};
3178 glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, &black[0]);
3179 checkGLcall("glMaterialfv(GL_SPECULAR");
3181 glMaterialfv(GL_FRONT_AND_BACK, GL_EMISSION, (float*) &This->updateStateBlock->material.Emissive);
3182 checkGLcall("glMaterialfv(GL_EMISSION)");
3183 glMaterialf(GL_FRONT_AND_BACK, GL_SHININESS, This->updateStateBlock->material.Power);
3184 checkGLcall("glMaterialf(GL_SHININESS");
3190 static HRESULT WINAPI IWineD3DDeviceImpl_GetMaterial(IWineD3DDevice *iface, WINED3DMATERIAL* pMaterial) {
3191 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3192 memcpy(pMaterial, &This->updateStateBlock->material, sizeof (WINED3DMATERIAL));
3193 TRACE("(%p) : Diffuse (%f,%f,%f,%f)\n", This, pMaterial->Diffuse.r, pMaterial->Diffuse.g,
3194 pMaterial->Diffuse.b, pMaterial->Diffuse.a);
3195 TRACE("(%p) : Ambient (%f,%f,%f,%f)\n", This, pMaterial->Ambient.r, pMaterial->Ambient.g,
3196 pMaterial->Ambient.b, pMaterial->Ambient.a);
3197 TRACE("(%p) : Specular (%f,%f,%f,%f)\n", This, pMaterial->Specular.r, pMaterial->Specular.g,
3198 pMaterial->Specular.b, pMaterial->Specular.a);
3199 TRACE("(%p) : Emissive (%f,%f,%f,%f)\n", This, pMaterial->Emissive.r, pMaterial->Emissive.g,
3200 pMaterial->Emissive.b, pMaterial->Emissive.a);
3201 TRACE("(%p) : Power (%f)\n", This, pMaterial->Power);
3209 static HRESULT WINAPI IWineD3DDeviceImpl_SetIndices(IWineD3DDevice *iface, IWineD3DIndexBuffer* pIndexData,
3210 UINT BaseVertexIndex) {
3211 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3212 IWineD3DIndexBuffer *oldIdxs;
3214 TRACE("(%p) : Setting to %p, base %d\n", This, pIndexData, BaseVertexIndex);
3215 oldIdxs = This->updateStateBlock->pIndexData;
3217 This->updateStateBlock->changed.indices = TRUE;
3218 This->updateStateBlock->set.indices = TRUE;
3219 This->updateStateBlock->pIndexData = pIndexData;
3220 This->updateStateBlock->baseVertexIndex = BaseVertexIndex;
3222 /* Handle recording of state blocks */
3223 if (This->isRecordingState) {
3224 TRACE("Recording... not performing anything\n");
3228 if (NULL != pIndexData) {
3229 IWineD3DIndexBuffer_AddRef(pIndexData);
3231 if (NULL != oldIdxs) {
3232 IWineD3DIndexBuffer_Release(oldIdxs);
3237 static HRESULT WINAPI IWineD3DDeviceImpl_GetIndices(IWineD3DDevice *iface, IWineD3DIndexBuffer** ppIndexData, UINT* pBaseVertexIndex) {
3238 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3240 *ppIndexData = This->stateBlock->pIndexData;
3242 /* up ref count on ppindexdata */
3244 IWineD3DIndexBuffer_AddRef(*ppIndexData);
3245 *pBaseVertexIndex = This->stateBlock->baseVertexIndex;
3246 TRACE("(%p) index data set to %p + %u\n", This, ppIndexData, This->stateBlock->baseVertexIndex);
3248 TRACE("(%p) No index data set\n", This);
3250 TRACE("Returning %p %d\n", *ppIndexData, *pBaseVertexIndex);
3256 * Get / Set Viewports
3258 static HRESULT WINAPI IWineD3DDeviceImpl_SetViewport(IWineD3DDevice *iface, CONST WINED3DVIEWPORT* pViewport) {
3259 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3261 TRACE("(%p)\n", This);
3262 This->updateStateBlock->changed.viewport = TRUE;
3263 This->updateStateBlock->set.viewport = TRUE;
3264 memcpy(&This->updateStateBlock->viewport, pViewport, sizeof(WINED3DVIEWPORT));
3266 /* Handle recording of state blocks */
3267 if (This->isRecordingState) {
3268 TRACE("Recording... not performing anything\n");
3271 This->viewport_changed = TRUE;
3275 TRACE("(%p) : x=%ld, y=%ld, wid=%ld, hei=%ld, minz=%f, maxz=%f\n", This,
3276 pViewport->X, pViewport->Y, pViewport->Width, pViewport->Height, pViewport->MinZ, pViewport->MaxZ);
3278 glDepthRange(pViewport->MinZ, pViewport->MaxZ);
3279 checkGLcall("glDepthRange");
3280 /* Note: GL requires lower left, DirectX supplies upper left */
3281 /* TODO: replace usage of renderTarget with context management */
3282 glViewport(pViewport->X,
3283 (((IWineD3DSurfaceImpl *)This->renderTarget)->currentDesc.Height - (pViewport->Y + pViewport->Height)),
3284 pViewport->Width, pViewport->Height);
3286 checkGLcall("glViewport");
3294 static HRESULT WINAPI IWineD3DDeviceImpl_GetViewport(IWineD3DDevice *iface, WINED3DVIEWPORT* pViewport) {
3295 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3296 TRACE("(%p)\n", This);
3297 memcpy(pViewport, &This->stateBlock->viewport, sizeof(WINED3DVIEWPORT));
3301 static void renderstate_stencil_twosided(
3302 IWineD3DDeviceImpl *This,
3309 GLint stencilPass ) {
3310 #if 0 /* Don't use OpenGL 2.0 calls for now */
3311 if(GL_EXTCALL(glStencilFuncSeparate) && GL_EXTCALL(glStencilOpSeparate)) {
3312 GL_EXTCALL(glStencilFuncSeparate(face, func, ref, mask));
3313 checkGLcall("glStencilFuncSeparate(...)");
3314 GL_EXTCALL(glStencilOpSeparate(face, stencilFail, depthFail, stencilPass));
3315 checkGLcall("glStencilOpSeparate(...)");
3319 if(GL_SUPPORT(EXT_STENCIL_TWO_SIDE)) {
3320 glEnable(GL_STENCIL_TEST_TWO_SIDE_EXT);
3321 checkGLcall("glEnable(GL_STENCIL_TEST_TWO_SIDE_EXT)");
3322 GL_EXTCALL(glActiveStencilFaceEXT(face));
3323 checkGLcall("glActiveStencilFaceEXT(...)");
3324 glStencilFunc(func, ref, mask);
3325 checkGLcall("glStencilFunc(...)");
3326 glStencilOp(stencilFail, depthFail, stencilPass);
3327 checkGLcall("glStencilOp(...)");
3328 } else if(GL_SUPPORT(ATI_SEPARATE_STENCIL)) {
3329 GL_EXTCALL(glStencilFuncSeparateATI(face, func, ref, mask));
3330 checkGLcall("glStencilFuncSeparateATI(...)");
3331 GL_EXTCALL(glStencilOpSeparateATI(face, stencilFail, depthFail, stencilPass));
3332 checkGLcall("glStencilOpSeparateATI(...)");
3334 ERR("Separate (two sided) stencil not supported on this version of opengl. Caps weren't honored?\n");
3338 static void renderstate_stencil(IWineD3DDeviceImpl *This, D3DRENDERSTATETYPE State, DWORD Value) {
3339 DWORD onesided_enable = FALSE;
3340 DWORD twosided_enable = FALSE;
3341 GLint func = GL_ALWAYS;
3342 GLint func_ccw = GL_ALWAYS;
3345 GLint stencilFail = GL_KEEP;
3346 GLint depthFail = GL_KEEP;
3347 GLint stencilPass = GL_KEEP;
3348 GLint stencilFail_ccw = GL_KEEP;
3349 GLint depthFail_ccw = GL_KEEP;
3350 GLint stencilPass_ccw = GL_KEEP;
3352 if( This->stateBlock->set.renderState[WINED3DRS_STENCILENABLE] )
3353 onesided_enable = This->stateBlock->renderState[WINED3DRS_STENCILENABLE];
3354 if( This->stateBlock->set.renderState[WINED3DRS_TWOSIDEDSTENCILMODE] )
3355 twosided_enable = This->stateBlock->renderState[WINED3DRS_TWOSIDEDSTENCILMODE];
3356 if( This->stateBlock->set.renderState[WINED3DRS_STENCILFUNC] )
3357 func = StencilFunc(This->stateBlock->renderState[WINED3DRS_STENCILFUNC]);
3358 if( This->stateBlock->set.renderState[WINED3DRS_CCW_STENCILFUNC] )
3359 func_ccw = StencilFunc(This->stateBlock->renderState[WINED3DRS_CCW_STENCILFUNC]);
3360 if( This->stateBlock->set.renderState[WINED3DRS_STENCILREF] )
3361 ref = This->stateBlock->renderState[WINED3DRS_STENCILREF];
3362 if( This->stateBlock->set.renderState[WINED3DRS_STENCILMASK] )
3363 mask = This->stateBlock->renderState[WINED3DRS_STENCILMASK];
3364 if( This->stateBlock->set.renderState[WINED3DRS_STENCILFAIL] )
3365 stencilFail = StencilOp(This->stateBlock->renderState[WINED3DRS_STENCILFAIL]);
3366 if( This->stateBlock->set.renderState[WINED3DRS_STENCILZFAIL] )
3367 depthFail = StencilOp(This->stateBlock->renderState[WINED3DRS_STENCILZFAIL]);
3368 if( This->stateBlock->set.renderState[WINED3DRS_STENCILPASS] )
3369 stencilPass = StencilOp(This->stateBlock->renderState[WINED3DRS_STENCILPASS]);
3370 if( This->stateBlock->set.renderState[WINED3DRS_CCW_STENCILFAIL] )
3371 stencilFail_ccw = StencilOp(This->stateBlock->renderState[WINED3DRS_CCW_STENCILFAIL]);
3372 if( This->stateBlock->set.renderState[WINED3DRS_CCW_STENCILZFAIL] )
3373 depthFail_ccw = StencilOp(This->stateBlock->renderState[WINED3DRS_CCW_STENCILZFAIL]);
3374 if( This->stateBlock->set.renderState[WINED3DRS_CCW_STENCILPASS] )
3375 stencilPass_ccw = StencilOp(This->stateBlock->renderState[WINED3DRS_CCW_STENCILPASS]);
3378 case WINED3DRS_STENCILENABLE :
3379 onesided_enable = Value;
3381 case WINED3DRS_TWOSIDEDSTENCILMODE :
3382 twosided_enable = Value;
3384 case WINED3DRS_STENCILFUNC :
3385 func = StencilFunc(Value);
3387 case WINED3DRS_CCW_STENCILFUNC :
3388 func_ccw = StencilFunc(Value);
3390 case WINED3DRS_STENCILREF :
3393 case WINED3DRS_STENCILMASK :
3396 case WINED3DRS_STENCILFAIL :
3397 stencilFail = StencilOp(Value);
3399 case WINED3DRS_STENCILZFAIL :
3400 depthFail = StencilOp(Value);
3402 case WINED3DRS_STENCILPASS :
3403 stencilPass = StencilOp(Value);
3405 case WINED3DRS_CCW_STENCILFAIL :
3406 stencilFail_ccw = StencilOp(Value);
3408 case WINED3DRS_CCW_STENCILZFAIL :
3409 depthFail_ccw = StencilOp(Value);
3411 case WINED3DRS_CCW_STENCILPASS :
3412 stencilPass_ccw = StencilOp(Value);
3415 ERR("This should not happen!");
3418 TRACE("(onesided %ld, twosided %ld, ref %x, mask %x, \
3419 GL_FRONT: func: %x, fail %x, zfail %x, zpass %x \
3420 GL_BACK: func: %x, fail %x, zfail %x, zpass %x )\n",
3421 onesided_enable, twosided_enable, ref, mask,
3422 func, stencilFail, depthFail, stencilPass,
3423 func_ccw, stencilFail_ccw, depthFail_ccw, stencilPass_ccw);
3425 if (twosided_enable) {
3426 renderstate_stencil_twosided(This, GL_FRONT, func, ref, mask, stencilFail, depthFail, stencilPass);
3427 renderstate_stencil_twosided(This, GL_BACK, func_ccw, ref, mask, stencilFail_ccw, depthFail_ccw, stencilPass_ccw);
3429 if (onesided_enable) {
3430 glEnable(GL_STENCIL_TEST);
3431 checkGLcall("glEnable GL_STENCIL_TEST");
3432 glStencilFunc(func, ref, mask);
3433 checkGLcall("glStencilFunc(...)");
3434 glStencilOp(stencilFail, depthFail, stencilPass);
3435 checkGLcall("glStencilOp(...)");
3437 glDisable(GL_STENCIL_TEST);
3438 checkGLcall("glDisable GL_STENCIL_TEST");
3444 * Get / Set Render States
3445 * TODO: Verify against dx9 definitions
3447 static HRESULT WINAPI IWineD3DDeviceImpl_SetRenderState(IWineD3DDevice *iface, D3DRENDERSTATETYPE State, DWORD Value) {
3449 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3450 DWORD OldValue = This->stateBlock->renderState[State];
3452 /* Simple way of referring to either a DWORD or a 4 byte float */
3458 TRACE("(%p)->state = %s(%d), value = %ld\n", This, debug_d3drenderstate(State), State, Value);
3459 This->updateStateBlock->changed.renderState[State] = TRUE;
3460 This->updateStateBlock->set.renderState[State] = TRUE;
3461 This->updateStateBlock->renderState[State] = Value;
3463 /* Handle recording of state blocks */
3464 if (This->isRecordingState) {
3465 TRACE("Recording... not performing anything\n");
3472 case WINED3DRS_FILLMODE :
3473 switch ((D3DFILLMODE) Value) {
3474 case D3DFILL_POINT : glPolygonMode(GL_FRONT_AND_BACK, GL_POINT); break;
3475 case D3DFILL_WIREFRAME : glPolygonMode(GL_FRONT_AND_BACK, GL_LINE); break;
3476 case D3DFILL_SOLID : glPolygonMode(GL_FRONT_AND_BACK, GL_FILL); break;
3478 FIXME("Unrecognized WINED3DRS_FILLMODE value %ld\n", Value);
3480 checkGLcall("glPolygonMode (fillmode)");
3483 case WINED3DRS_LIGHTING :
3485 glEnable(GL_LIGHTING);
3486 checkGLcall("glEnable GL_LIGHTING");
3488 glDisable(GL_LIGHTING);
3489 checkGLcall("glDisable GL_LIGHTING");
3493 case WINED3DRS_ZENABLE :
3494 switch ((D3DZBUFFERTYPE) Value) {
3496 glDisable(GL_DEPTH_TEST);
3497 checkGLcall("glDisable GL_DEPTH_TEST");
3500 glEnable(GL_DEPTH_TEST);
3501 checkGLcall("glEnable GL_DEPTH_TEST");
3504 glEnable(GL_DEPTH_TEST);
3505 checkGLcall("glEnable GL_DEPTH_TEST");
3506 FIXME("W buffer is not well handled\n");
3509 FIXME("Unrecognized D3DZBUFFERTYPE value %ld\n", Value);
3513 case WINED3DRS_CULLMODE :
3515 /* If we are culling "back faces with clockwise vertices" then
3516 set front faces to be counter clockwise and enable culling
3518 switch ((D3DCULL) Value) {
3520 glDisable(GL_CULL_FACE);
3521 checkGLcall("glDisable GL_CULL_FACE");
3524 glEnable(GL_CULL_FACE);
3525 checkGLcall("glEnable GL_CULL_FACE");
3526 if (This->renderUpsideDown) {
3528 checkGLcall("glFrontFace GL_CW");
3530 glFrontFace(GL_CCW);
3531 checkGLcall("glFrontFace GL_CCW");
3533 glCullFace(GL_BACK);
3536 glEnable(GL_CULL_FACE);
3537 checkGLcall("glEnable GL_CULL_FACE");
3538 if (This->renderUpsideDown) {
3539 glFrontFace(GL_CCW);
3540 checkGLcall("glFrontFace GL_CCW");
3543 checkGLcall("glFrontFace GL_CW");
3545 glCullFace(GL_BACK);
3548 FIXME("Unrecognized/Unhandled D3DCULL value %ld\n", Value);
3552 case WINED3DRS_SHADEMODE :
3553 switch ((D3DSHADEMODE) Value) {
3555 glShadeModel(GL_FLAT);
3556 checkGLcall("glShadeModel");
3558 case D3DSHADE_GOURAUD:
3559 glShadeModel(GL_SMOOTH);
3560 checkGLcall("glShadeModel");
3562 case D3DSHADE_PHONG:
3563 FIXME("D3DSHADE_PHONG isn't supported?\n");
3566 return WINED3DERR_INVALIDCALL;
3568 FIXME("Unrecognized/Unhandled D3DSHADEMODE value %ld\n", Value);
3572 case WINED3DRS_DITHERENABLE :
3574 glEnable(GL_DITHER);
3575 checkGLcall("glEnable GL_DITHER");
3577 glDisable(GL_DITHER);
3578 checkGLcall("glDisable GL_DITHER");
3582 case WINED3DRS_ZWRITEENABLE :
3585 checkGLcall("glDepthMask");
3588 checkGLcall("glDepthMask");
3592 case WINED3DRS_ZFUNC :
3594 int glParm = GL_LESS;
3596 switch ((D3DCMPFUNC) Value) {
3597 case D3DCMP_NEVER: glParm=GL_NEVER; break;
3598 case D3DCMP_LESS: glParm=GL_LESS; break;
3599 case D3DCMP_EQUAL: glParm=GL_EQUAL; break;
3600 case D3DCMP_LESSEQUAL: glParm=GL_LEQUAL; break;
3601 case D3DCMP_GREATER: glParm=GL_GREATER; break;
3602 case D3DCMP_NOTEQUAL: glParm=GL_NOTEQUAL; break;
3603 case D3DCMP_GREATEREQUAL: glParm=GL_GEQUAL; break;
3604 case D3DCMP_ALWAYS: glParm=GL_ALWAYS; break;
3606 FIXME("Unrecognized/Unhandled D3DCMPFUNC value %ld\n", Value);
3608 glDepthFunc(glParm);
3609 checkGLcall("glDepthFunc");
3613 case WINED3DRS_AMBIENT :
3616 D3DCOLORTOGLFLOAT4(Value, col);
3617 TRACE("Setting ambient to (%f,%f,%f,%f)\n", col[0], col[1], col[2], col[3]);
3618 glLightModelfv(GL_LIGHT_MODEL_AMBIENT, col);
3619 checkGLcall("glLightModel for MODEL_AMBIENT");
3624 case WINED3DRS_ALPHABLENDENABLE :
3627 checkGLcall("glEnable GL_BLEND");
3629 glDisable(GL_BLEND);
3630 checkGLcall("glDisable GL_BLEND");
3634 case WINED3DRS_SRCBLEND :
3635 case WINED3DRS_DESTBLEND :
3637 int newVal = GL_ZERO;
3639 case D3DBLEND_ZERO : newVal = GL_ZERO; break;
3640 case D3DBLEND_ONE : newVal = GL_ONE; break;
3641 case D3DBLEND_SRCCOLOR : newVal = GL_SRC_COLOR; break;
3642 case D3DBLEND_INVSRCCOLOR : newVal = GL_ONE_MINUS_SRC_COLOR; break;
3643 case D3DBLEND_SRCALPHA : newVal = GL_SRC_ALPHA; break;
3644 case D3DBLEND_INVSRCALPHA : newVal = GL_ONE_MINUS_SRC_ALPHA; break;
3645 case D3DBLEND_DESTALPHA : newVal = GL_DST_ALPHA; break;
3646 case D3DBLEND_INVDESTALPHA : newVal = GL_ONE_MINUS_DST_ALPHA; break;
3647 case D3DBLEND_DESTCOLOR : newVal = GL_DST_COLOR; break;
3648 case D3DBLEND_INVDESTCOLOR : newVal = GL_ONE_MINUS_DST_COLOR; break;
3649 case D3DBLEND_SRCALPHASAT : newVal = GL_SRC_ALPHA_SATURATE; break;
3651 case D3DBLEND_BOTHSRCALPHA : newVal = GL_SRC_ALPHA;
3652 This->srcBlend = newVal;
3653 This->dstBlend = newVal;
3656 case D3DBLEND_BOTHINVSRCALPHA : newVal = GL_ONE_MINUS_SRC_ALPHA;
3657 This->srcBlend = newVal;
3658 This->dstBlend = newVal;
3661 FIXME("Unrecognized src/dest blend value %ld (%d)\n", Value, State);
3664 if (State == WINED3DRS_SRCBLEND) This->srcBlend = newVal;
3665 if (State == WINED3DRS_DESTBLEND) This->dstBlend = newVal;
3666 TRACE("glBlendFunc src=%x, dst=%x\n", This->srcBlend, This->dstBlend);
3667 glBlendFunc(This->srcBlend, This->dstBlend);
3669 checkGLcall("glBlendFunc");
3673 case WINED3DRS_ALPHATESTENABLE :
3674 case WINED3DRS_ALPHAFUNC :
3675 case WINED3DRS_ALPHAREF :
3676 case WINED3DRS_COLORKEYENABLE :
3679 float ref = GL_LESS;
3680 BOOL enable_ckey = FALSE;
3682 IWineD3DSurfaceImpl *surf;
3684 /* Find out if the texture on the first stage has a ckey set */
3685 if(This->stateBlock->textures[0]) {
3686 surf = (IWineD3DSurfaceImpl *) ((IWineD3DTextureImpl *)This->stateBlock->textures[0])->surfaces[0];
3687 if(surf->CKeyFlags & DDSD_CKSRCBLT) enable_ckey = TRUE;
3690 if (This->stateBlock->renderState[WINED3DRS_ALPHATESTENABLE] ||
3691 (This->stateBlock->renderState[WINED3DRS_COLORKEYENABLE] && enable_ckey)) {
3692 glEnable(GL_ALPHA_TEST);
3693 checkGLcall("glEnable GL_ALPHA_TEST");
3695 glDisable(GL_ALPHA_TEST);
3696 checkGLcall("glDisable GL_ALPHA_TEST");
3697 /* Alpha test is disabled, don't bother setting the params - it will happen on the next
3703 if(This->stateBlock->renderState[WINED3DRS_COLORKEYENABLE] && enable_ckey) {
3704 glParm = GL_NOTEQUAL;
3707 ref = ((float) This->stateBlock->renderState[WINED3DRS_ALPHAREF]) / 255.0f;
3709 switch ((D3DCMPFUNC) This->stateBlock->renderState[WINED3DRS_ALPHAFUNC]) {
3710 case D3DCMP_NEVER: glParm = GL_NEVER; break;
3711 case D3DCMP_LESS: glParm = GL_LESS; break;
3712 case D3DCMP_EQUAL: glParm = GL_EQUAL; break;
3713 case D3DCMP_LESSEQUAL: glParm = GL_LEQUAL; break;
3714 case D3DCMP_GREATER: glParm = GL_GREATER; break;
3715 case D3DCMP_NOTEQUAL: glParm = GL_NOTEQUAL; break;
3716 case D3DCMP_GREATEREQUAL: glParm = GL_GEQUAL; break;
3717 case D3DCMP_ALWAYS: glParm = GL_ALWAYS; break;
3719 FIXME("Unrecognized/Unhandled D3DCMPFUNC value %ld\n", Value);
3722 This->alphafunc = glParm;
3723 glAlphaFunc(glParm, ref);
3724 checkGLcall("glAlphaFunc");
3728 case WINED3DRS_CLIPPLANEENABLE :
3729 case WINED3DRS_CLIPPING :
3731 /* Ensure we only do the changed clip planes */
3732 DWORD enable = 0xFFFFFFFF;
3733 DWORD disable = 0x00000000;
3735 /* If enabling / disabling all */
3736 if (State == WINED3DRS_CLIPPING) {
3738 enable = This->stateBlock->renderState[WINED3DRS_CLIPPLANEENABLE];
3741 disable = This->stateBlock->renderState[WINED3DRS_CLIPPLANEENABLE];
3745 enable = Value & ~OldValue;
3746 disable = ~Value & OldValue;
3749 if (enable & D3DCLIPPLANE0) { glEnable(GL_CLIP_PLANE0); checkGLcall("glEnable(clip plane 0)"); }
3750 if (enable & D3DCLIPPLANE1) { glEnable(GL_CLIP_PLANE1); checkGLcall("glEnable(clip plane 1)"); }
3751 if (enable & D3DCLIPPLANE2) { glEnable(GL_CLIP_PLANE2); checkGLcall("glEnable(clip plane 2)"); }
3752 if (enable & D3DCLIPPLANE3) { glEnable(GL_CLIP_PLANE3); checkGLcall("glEnable(clip plane 3)"); }
3753 if (enable & D3DCLIPPLANE4) { glEnable(GL_CLIP_PLANE4); checkGLcall("glEnable(clip plane 4)"); }
3754 if (enable & D3DCLIPPLANE5) { glEnable(GL_CLIP_PLANE5); checkGLcall("glEnable(clip plane 5)"); }
3756 if (disable & D3DCLIPPLANE0) { glDisable(GL_CLIP_PLANE0); checkGLcall("glDisable(clip plane 0)"); }
3757 if (disable & D3DCLIPPLANE1) { glDisable(GL_CLIP_PLANE1); checkGLcall("glDisable(clip plane 1)"); }
3758 if (disable & D3DCLIPPLANE2) { glDisable(GL_CLIP_PLANE2); checkGLcall("glDisable(clip plane 2)"); }
3759 if (disable & D3DCLIPPLANE3) { glDisable(GL_CLIP_PLANE3); checkGLcall("glDisable(clip plane 3)"); }
3760 if (disable & D3DCLIPPLANE4) { glDisable(GL_CLIP_PLANE4); checkGLcall("glDisable(clip plane 4)"); }
3761 if (disable & D3DCLIPPLANE5) { glDisable(GL_CLIP_PLANE5); checkGLcall("glDisable(clip plane 5)"); }
3763 /** update clipping status */
3765 This->stateBlock->clip_status.ClipUnion = 0;
3766 This->stateBlock->clip_status.ClipIntersection = 0xFFFFFFFF;
3768 This->stateBlock->clip_status.ClipUnion = 0;
3769 This->stateBlock->clip_status.ClipIntersection = 0;
3774 case WINED3DRS_BLENDOP :
3776 int glParm = GL_FUNC_ADD;
3778 switch ((D3DBLENDOP) Value) {
3779 case D3DBLENDOP_ADD : glParm = GL_FUNC_ADD; break;
3780 case D3DBLENDOP_SUBTRACT : glParm = GL_FUNC_SUBTRACT; break;
3781 case D3DBLENDOP_REVSUBTRACT : glParm = GL_FUNC_REVERSE_SUBTRACT; break;
3782 case D3DBLENDOP_MIN : glParm = GL_MIN; break;
3783 case D3DBLENDOP_MAX : glParm = GL_MAX; break;
3785 FIXME("Unrecognized/Unhandled D3DBLENDOP value %ld\n", Value);
3788 if(GL_SUPPORT(ARB_IMAGING)) {
3789 TRACE("glBlendEquation(%x)\n", glParm);
3790 GL_EXTCALL(glBlendEquation(glParm));
3791 checkGLcall("glBlendEquation");
3793 WARN("Unsupported in local OpenGL implementation: glBlendEquation\n");
3798 case WINED3DRS_TEXTUREFACTOR :
3802 /* Note the texture color applies to all textures whereas
3803 GL_TEXTURE_ENV_COLOR applies to active only */
3805 D3DCOLORTOGLFLOAT4(Value, col);
3806 /* Set the default alpha blend color */
3807 if (GL_SUPPORT(ARB_IMAGING)) {
3808 GL_EXTCALL(glBlendColor(col[0], col[1], col[2], col[3]));
3809 checkGLcall("glBlendColor");
3811 WARN("Unsupported in local OpenGL implementation: glBlendColor\n");
3814 if (!GL_SUPPORT(NV_REGISTER_COMBINERS)) {
3815 /* And now the default texture color as well */
3816 for (i = 0; i < GL_LIMITS(texture_stages); i++) {
3817 /* Note the D3DRS value applies to all textures, but GL has one
3818 per texture, so apply it now ready to be used! */
3819 if (GL_SUPPORT(ARB_MULTITEXTURE)) {
3820 GL_EXTCALL(glActiveTextureARB(GL_TEXTURE0_ARB + i));
3821 checkGLcall("glActiveTextureARB");
3823 FIXME("Program using multiple concurrent textures which this opengl implementation doesn't support\n");
3826 glTexEnvfv(GL_TEXTURE_ENV, GL_TEXTURE_ENV_COLOR, &col[0]);
3827 checkGLcall("glTexEnvfv(GL_TEXTURE_ENV, GL_TEXTURE_ENV_COLOR, color);");
3833 case WINED3DRS_SPECULARENABLE :
3835 /* Originally this used glLightModeli(GL_LIGHT_MODEL_COLOR_CONTROL,GL_SEPARATE_SPECULAR_COLOR)
3836 and (GL_LIGHT_MODEL_COLOR_CONTROL,GL_SINGLE_COLOR) to swap between enabled/disabled
3837 specular color. This is wrong:
3838 Separate specular color means the specular colour is maintained separately, whereas
3839 single color means it is merged in. However in both cases they are being used to
3841 To disable specular color, set it explicitly to black and turn off GL_COLOR_SUM_EXT
3842 NOTE: If not supported don't give FIXMEs the impact is really minimal and very few people are
3846 * If register combiners are enabled, enabling / disabling GL_COLOR_SUM has no effect.
3847 * Instead, we need to setup the FinalCombiner properly.
3849 * The default setup for the FinalCombiner is:
3851 * <variable> <input> <mapping> <usage>
3852 * GL_VARIABLE_A_NV GL_FOG, GL_UNSIGNED_IDENTITY_NV GL_ALPHA
3853 * GL_VARIABLE_B_NV GL_SPARE0_PLUS_SECONDARY_COLOR_NV GL_UNSIGNED_IDENTITY_NV GL_RGB
3854 * GL_VARIABLE_C_NV GL_FOG GL_UNSIGNED_IDENTITY_NV GL_RGB
3855 * GL_VARIABLE_D_NV GL_ZERO GL_UNSIGNED_IDENTITY_NV GL_RGB
3856 * GL_VARIABLE_E_NV GL_ZERO GL_UNSIGNED_IDENTITY_NV GL_RGB
3857 * GL_VARIABLE_F_NV GL_ZERO GL_UNSIGNED_IDENTITY_NV GL_RGB
3858 * GL_VARIABLE_G_NV GL_SPARE0_NV GL_UNSIGNED_IDENTITY_NV GL_ALPHA
3860 * That's pretty much fine as it is, except for variable B, which needs to take
3861 * either GL_SPARE0_PLUS_SECONDARY_COLOR_NV or GL_SPARE0_NV, depending on
3862 * whether WINED3DRS_SPECULARENABLE is enabled or not.
3866 glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, (float*) &This->updateStateBlock->material.Specular);
3867 checkGLcall("glMaterialfv");
3868 if (GL_SUPPORT(EXT_SECONDARY_COLOR)) {
3869 glEnable(GL_COLOR_SUM_EXT);
3871 TRACE("Specular colors cannot be enabled in this version of opengl\n");
3873 checkGLcall("glEnable(GL_COLOR_SUM)");
3875 if (GL_SUPPORT(NV_REGISTER_COMBINERS)) {
3876 GL_EXTCALL(glFinalCombinerInputNV(GL_VARIABLE_B_NV, GL_SPARE0_PLUS_SECONDARY_COLOR_NV, GL_UNSIGNED_IDENTITY_NV, GL_RGB));
3877 checkGLcall("glFinalCombinerInputNV()");
3880 float black[4] = {0.0f, 0.0f, 0.0f, 0.0f};
3882 /* for the case of enabled lighting: */
3883 glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, &black[0]);
3884 checkGLcall("glMaterialfv");
3886 /* for the case of disabled lighting: */
3887 if (GL_SUPPORT(EXT_SECONDARY_COLOR)) {
3888 glDisable(GL_COLOR_SUM_EXT);
3890 TRACE("Specular colors cannot be disabled in this version of opengl\n");
3892 checkGLcall("glDisable(GL_COLOR_SUM)");
3894 if (GL_SUPPORT(NV_REGISTER_COMBINERS)) {
3895 GL_EXTCALL(glFinalCombinerInputNV(GL_VARIABLE_B_NV, GL_SPARE0_NV, GL_UNSIGNED_IDENTITY_NV, GL_RGB));
3896 checkGLcall("glFinalCombinerInputNV()");
3902 case WINED3DRS_STENCILENABLE :
3903 case WINED3DRS_TWOSIDEDSTENCILMODE :
3904 case WINED3DRS_STENCILFUNC :
3905 case WINED3DRS_CCW_STENCILFUNC :
3906 case WINED3DRS_STENCILREF :
3907 case WINED3DRS_STENCILMASK :
3908 case WINED3DRS_STENCILFAIL :
3909 case WINED3DRS_STENCILZFAIL :
3910 case WINED3DRS_STENCILPASS :
3911 case WINED3DRS_CCW_STENCILFAIL :
3912 case WINED3DRS_CCW_STENCILZFAIL :
3913 case WINED3DRS_CCW_STENCILPASS :
3914 renderstate_stencil(This, State, Value);
3916 case WINED3DRS_STENCILWRITEMASK :
3918 glStencilMask(Value);
3919 TRACE("glStencilMask(%lu)\n", Value);
3920 checkGLcall("glStencilMask");
3924 case WINED3DRS_FOGENABLE :
3928 checkGLcall("glEnable GL_FOG");
3931 checkGLcall("glDisable GL_FOG");
3936 case WINED3DRS_RANGEFOGENABLE :
3939 TRACE("Enabled RANGEFOG");
3941 TRACE("Disabled RANGEFOG");
3946 case WINED3DRS_FOGCOLOR :
3949 D3DCOLORTOGLFLOAT4(Value, col);
3950 /* Set the default alpha blend color */
3951 glFogfv(GL_FOG_COLOR, &col[0]);
3952 checkGLcall("glFog GL_FOG_COLOR");
3956 case WINED3DRS_FOGTABLEMODE :
3957 case WINED3DRS_FOGVERTEXMODE :
3959 /* 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." */
3960 if(This->stateBlock->renderState[WINED3DRS_FOGTABLEMODE] == D3DFOG_NONE) {
3961 glHint(GL_FOG_HINT, GL_FASTEST);
3962 checkGLcall("glHint(GL_FOG_HINT, GL_FASTEST)");
3963 switch (This->stateBlock->renderState[WINED3DRS_FOGVERTEXMODE]) {
3964 /* Processed vertices have their fog factor stored in the specular value. Fall too the none case.
3965 * If we are drawing untransformed vertices atm, d3ddevice_set_ortho will update the fog
3968 if(!This->last_was_rhw) {
3969 glFogi(GL_FOG_MODE, GL_EXP);
3970 checkGLcall("glFogi(GL_FOG_MODE, GL_EXP");
3971 if(GL_SUPPORT(EXT_FOG_COORD)) {
3972 glFogi(GL_FOG_COORDINATE_SOURCE_EXT, GL_FRAGMENT_DEPTH_EXT);
3973 checkGLcall("glFogi(GL_FOG_COORDINATE_SOURCE_EXT, GL_FRAGMENT_DEPTH_EXT");
3974 IWineD3DDevice_SetRenderState(iface, WINED3DRS_FOGSTART, This->stateBlock->renderState[WINED3DRS_FOGSTART]);
3975 IWineD3DDevice_SetRenderState(iface, WINED3DRS_FOGEND, This->stateBlock->renderState[WINED3DRS_FOGEND]);
3981 if(!This->last_was_rhw) {
3982 glFogi(GL_FOG_MODE, GL_EXP2);
3983 checkGLcall("glFogi(GL_FOG_MODE, GL_EXP2");
3984 if(GL_SUPPORT(EXT_FOG_COORD)) {
3985 glFogi(GL_FOG_COORDINATE_SOURCE_EXT, GL_FRAGMENT_DEPTH_EXT);
3986 checkGLcall("glFogi(GL_FOG_COORDINATE_SOURCE_EXT, GL_FRAGMENT_DEPTH_EXT");
3987 IWineD3DDevice_SetRenderState(iface, WINED3DRS_FOGSTART, This->stateBlock->renderState[WINED3DRS_FOGSTART]);
3988 IWineD3DDevice_SetRenderState(iface, WINED3DRS_FOGEND, This->stateBlock->renderState[WINED3DRS_FOGEND]);
3993 case D3DFOG_LINEAR: {
3994 if(!This->last_was_rhw) {
3995 glFogi(GL_FOG_MODE, GL_LINEAR);
3996 checkGLcall("glFogi(GL_FOG_MODE, GL_LINEAR");
3997 if(GL_SUPPORT(EXT_FOG_COORD)) {
3998 glFogi(GL_FOG_COORDINATE_SOURCE_EXT, GL_FRAGMENT_DEPTH_EXT);
3999 checkGLcall("glFogi(GL_FOG_COORDINATE_SOURCE_EXT, GL_FRAGMENT_DEPTH_EXT");
4000 IWineD3DDevice_SetRenderState(iface, WINED3DRS_FOGSTART, This->stateBlock->renderState[WINED3DRS_FOGSTART]);
4001 IWineD3DDevice_SetRenderState(iface, WINED3DRS_FOGEND, This->stateBlock->renderState[WINED3DRS_FOGEND]);
4007 /* Both are none? According to msdn the alpha channel of the specular
4008 * color contains a fog factor. Set it in drawStridedSlow.
4009 * Same happens with Vertexfog on transformed vertices
4011 if(GL_SUPPORT(EXT_FOG_COORD)) {
4012 glFogi(GL_FOG_COORDINATE_SOURCE_EXT, GL_FOG_COORDINATE_EXT);
4013 checkGLcall("glFogi(GL_FOG_COORDINATE_SOURCE_EXT, GL_FOG_COORDINATE_EXT)\n");
4014 glFogi(GL_FOG_MODE, GL_LINEAR);
4015 checkGLcall("glFogi(GL_FOG_MODE, GL_LINEAR)");
4016 glFogf(GL_FOG_START, (float) 0xff);
4017 checkGLcall("glFogfv GL_FOG_START");
4018 glFogf(GL_FOG_END, 0.0);
4019 checkGLcall("glFogfv GL_FOG_END");
4021 /* Disable GL fog, handle this in software in drawStridedSlow */
4023 checkGLcall("glDisable(GL_FOG)");
4027 default: FIXME("Unexpected WINED3DRS_FOGVERTEXMODE %ld\n", This->stateBlock->renderState[WINED3DRS_FOGVERTEXMODE]);
4030 glHint(GL_FOG_HINT, GL_NICEST);
4031 checkGLcall("glHint(GL_FOG_HINT, GL_NICEST)");
4032 switch (This->stateBlock->renderState[WINED3DRS_FOGTABLEMODE]) {
4033 case D3DFOG_EXP: glFogi(GL_FOG_MODE, GL_EXP);
4034 checkGLcall("glFogi(GL_FOG_MODE, GL_EXP");
4035 if(GL_SUPPORT(EXT_FOG_COORD)) {
4036 glFogi(GL_FOG_COORDINATE_SOURCE_EXT, GL_FRAGMENT_DEPTH_EXT);
4037 checkGLcall("glFogi(GL_FOG_COORDINATE_SOURCE_EXT, GL_FRAGMENT_DEPTH_EXT");
4038 IWineD3DDevice_SetRenderState(iface, WINED3DRS_FOGSTART, This->stateBlock->renderState[WINED3DRS_FOGSTART]);
4039 IWineD3DDevice_SetRenderState(iface, WINED3DRS_FOGEND, This->stateBlock->renderState[WINED3DRS_FOGEND]);
4042 case D3DFOG_EXP2: glFogi(GL_FOG_MODE, GL_EXP2);
4043 checkGLcall("glFogi(GL_FOG_MODE, GL_EXP2");
4044 if(GL_SUPPORT(EXT_FOG_COORD)) {
4045 glFogi(GL_FOG_COORDINATE_SOURCE_EXT, GL_FRAGMENT_DEPTH_EXT);
4046 checkGLcall("glFogi(GL_FOG_COORDINATE_SOURCE_EXT, GL_FRAGMENT_DEPTH_EXT");
4047 IWineD3DDevice_SetRenderState(iface, WINED3DRS_FOGSTART, This->stateBlock->renderState[WINED3DRS_FOGSTART]);
4048 IWineD3DDevice_SetRenderState(iface, WINED3DRS_FOGEND, This->stateBlock->renderState[WINED3DRS_FOGEND]);
4051 case D3DFOG_LINEAR: glFogi(GL_FOG_MODE, GL_LINEAR);
4052 checkGLcall("glFogi(GL_FOG_MODE, GL_LINEAR");
4053 if(GL_SUPPORT(EXT_FOG_COORD)) {
4054 glFogi(GL_FOG_COORDINATE_SOURCE_EXT, GL_FRAGMENT_DEPTH_EXT);
4055 checkGLcall("glFogi(GL_FOG_COORDINATE_SOURCE_EXT, GL_FRAGMENT_DEPTH_EXT");
4056 IWineD3DDevice_SetRenderState(iface, WINED3DRS_FOGSTART, This->stateBlock->renderState[WINED3DRS_FOGSTART]);
4057 IWineD3DDevice_SetRenderState(iface, WINED3DRS_FOGEND, This->stateBlock->renderState[WINED3DRS_FOGEND]);
4060 case D3DFOG_NONE: /* Won't happen */
4061 default: FIXME("Unexpected WINED3DRS_FOGTABLEMODE %ld\n", This->stateBlock->renderState[WINED3DRS_FOGTABLEMODE]);
4064 if (GL_SUPPORT(NV_FOG_DISTANCE)) {
4065 glFogi(GL_FOG_DISTANCE_MODE_NV, GL_EYE_PLANE_ABSOLUTE_NV);
4070 case WINED3DRS_FOGSTART :
4073 glFogfv(GL_FOG_START, &tmpvalue.f);
4074 checkGLcall("glFogf(GL_FOG_START, (float) Value)");
4075 TRACE("Fog Start == %f\n", tmpvalue.f);
4079 case WINED3DRS_FOGEND :
4082 glFogfv(GL_FOG_END, &tmpvalue.f);
4083 checkGLcall("glFogf(GL_FOG_END, (float) Value)");
4084 TRACE("Fog End == %f\n", tmpvalue.f);
4088 case WINED3DRS_FOGDENSITY :
4091 glFogfv(GL_FOG_DENSITY, &tmpvalue.f);
4092 checkGLcall("glFogf(GL_FOG_DENSITY, (float) Value)");
4096 case WINED3DRS_VERTEXBLEND :
4098 This->updateStateBlock->vertex_blend = (D3DVERTEXBLENDFLAGS) Value;
4099 TRACE("Vertex Blending state to %ld\n", Value);
4103 case WINED3DRS_TWEENFACTOR :
4106 This->updateStateBlock->tween_factor = tmpvalue.f;
4107 TRACE("Vertex Blending Tween Factor to %f\n", This->updateStateBlock->tween_factor);
4111 case WINED3DRS_INDEXEDVERTEXBLENDENABLE :
4113 TRACE("Indexed Vertex Blend Enable to %ul\n", (BOOL) Value);
4117 case WINED3DRS_COLORVERTEX :
4118 case WINED3DRS_DIFFUSEMATERIALSOURCE :
4119 case WINED3DRS_SPECULARMATERIALSOURCE :
4120 case WINED3DRS_AMBIENTMATERIALSOURCE :
4121 case WINED3DRS_EMISSIVEMATERIALSOURCE :
4123 GLenum Parm = GL_AMBIENT_AND_DIFFUSE;
4125 if (This->stateBlock->renderState[WINED3DRS_COLORVERTEX]) {
4126 TRACE("diff %ld, amb %ld, emis %ld, spec %ld\n",
4127 This->stateBlock->renderState[WINED3DRS_DIFFUSEMATERIALSOURCE],
4128 This->stateBlock->renderState[WINED3DRS_AMBIENTMATERIALSOURCE],
4129 This->stateBlock->renderState[WINED3DRS_EMISSIVEMATERIALSOURCE],
4130 This->stateBlock->renderState[WINED3DRS_SPECULARMATERIALSOURCE]);
4132 if (This->stateBlock->renderState[WINED3DRS_DIFFUSEMATERIALSOURCE] == D3DMCS_COLOR1) {
4133 if (This->stateBlock->renderState[WINED3DRS_AMBIENTMATERIALSOURCE] == D3DMCS_COLOR1) {
4134 Parm = GL_AMBIENT_AND_DIFFUSE;
4138 } else if (This->stateBlock->renderState[WINED3DRS_AMBIENTMATERIALSOURCE] == D3DMCS_COLOR1) {
4140 } else if (This->stateBlock->renderState[WINED3DRS_EMISSIVEMATERIALSOURCE] == D3DMCS_COLOR1) {
4142 } else if (This->stateBlock->renderState[WINED3DRS_SPECULARMATERIALSOURCE] == D3DMCS_COLOR1) {
4149 if (This->tracking_color != DISABLED_TRACKING) This->tracking_color = NEEDS_DISABLE;
4151 This->tracking_color = NEEDS_TRACKING;
4152 This->tracking_parm = Parm;
4156 if (This->tracking_color != DISABLED_TRACKING) This->tracking_color = NEEDS_DISABLE;
4161 case WINED3DRS_LINEPATTERN :
4167 tmppattern.d = Value;
4169 TRACE("Line pattern: repeat %d bits %x\n", tmppattern.lp.wRepeatFactor, tmppattern.lp.wLinePattern);
4171 if (tmppattern.lp.wRepeatFactor) {
4172 glLineStipple(tmppattern.lp.wRepeatFactor, tmppattern.lp.wLinePattern);
4173 checkGLcall("glLineStipple(repeat, linepattern)");
4174 glEnable(GL_LINE_STIPPLE);
4175 checkGLcall("glEnable(GL_LINE_STIPPLE);");
4177 glDisable(GL_LINE_STIPPLE);
4178 checkGLcall("glDisable(GL_LINE_STIPPLE);");
4183 case WINED3DRS_ZBIAS : /* D3D8 only */
4187 TRACE("ZBias value %f\n", tmpvalue.f);
4188 glPolygonOffset(0, -tmpvalue.f);
4189 checkGLcall("glPolygonOffset(0, -Value)");
4190 glEnable(GL_POLYGON_OFFSET_FILL);
4191 checkGLcall("glEnable(GL_POLYGON_OFFSET_FILL);");
4192 glEnable(GL_POLYGON_OFFSET_LINE);
4193 checkGLcall("glEnable(GL_POLYGON_OFFSET_LINE);");
4194 glEnable(GL_POLYGON_OFFSET_POINT);
4195 checkGLcall("glEnable(GL_POLYGON_OFFSET_POINT);");
4197 glDisable(GL_POLYGON_OFFSET_FILL);
4198 checkGLcall("glDisable(GL_POLYGON_OFFSET_FILL);");
4199 glDisable(GL_POLYGON_OFFSET_LINE);
4200 checkGLcall("glDisable(GL_POLYGON_OFFSET_LINE);");
4201 glDisable(GL_POLYGON_OFFSET_POINT);
4202 checkGLcall("glDisable(GL_POLYGON_OFFSET_POINT);");
4207 case WINED3DRS_NORMALIZENORMALS :
4209 glEnable(GL_NORMALIZE);
4210 checkGLcall("glEnable(GL_NORMALIZE);");
4212 glDisable(GL_NORMALIZE);
4213 checkGLcall("glDisable(GL_NORMALIZE);");
4217 case WINED3DRS_POINTSIZE :
4218 /* FIXME: check that pointSize isn't outside glGetFloatv( GL_POINT_SIZE_MAX_ARB, &maxSize ); or -ve */
4220 TRACE("Set point size to %f\n", tmpvalue.f);
4221 glPointSize(tmpvalue.f);
4222 checkGLcall("glPointSize(...);");
4225 case WINED3DRS_POINTSIZE_MIN :
4226 if (GL_SUPPORT(EXT_POINT_PARAMETERS)) {
4228 GL_EXTCALL(glPointParameterfEXT)(GL_POINT_SIZE_MIN_EXT, tmpvalue.f);
4229 checkGLcall("glPointParameterfEXT(...);");
4231 FIXME("WINED3DRS_POINTSIZE_MIN not supported on this opengl\n");
4235 case WINED3DRS_POINTSIZE_MAX :
4236 if (GL_SUPPORT(EXT_POINT_PARAMETERS)) {
4238 GL_EXTCALL(glPointParameterfEXT)(GL_POINT_SIZE_MAX_EXT, tmpvalue.f);
4239 checkGLcall("glPointParameterfEXT(...);");
4241 FIXME("WINED3DRS_POINTSIZE_MAX not supported on this opengl\n");
4245 case WINED3DRS_POINTSCALE_A :
4246 case WINED3DRS_POINTSCALE_B :
4247 case WINED3DRS_POINTSCALE_C :
4248 case WINED3DRS_POINTSCALEENABLE :
4251 * POINTSCALEENABLE controls how point size value is treated. If set to
4252 * true, the point size is scaled with respect to height of viewport.
4253 * When set to false point size is in pixels.
4255 * http://msdn.microsoft.com/library/en-us/directx9_c/point_sprites.asp
4258 /* Default values */
4259 GLfloat att[3] = {1.0f, 0.0f, 0.0f};
4262 * Minimum valid point size for OpenGL is 1.0f. For Direct3D it is 0.0f.
4263 * This means that OpenGL will clamp really small point sizes to 1.0f.
4264 * To correct for this we need to multiply by the scale factor when sizes
4265 * are less than 1.0f. scale_factor = 1.0f / point_size.
4267 GLfloat pointSize = *((float*)&This->stateBlock->renderState[WINED3DRS_POINTSIZE]);
4268 if(pointSize > 0.0f) {
4269 GLfloat scaleFactor;
4271 if(pointSize < 1.0f) {
4272 scaleFactor = pointSize * pointSize;
4277 if(This->stateBlock->renderState[WINED3DRS_POINTSCALEENABLE]) {
4278 att[0] = *((float*)&This->stateBlock->renderState[WINED3DRS_POINTSCALE_A]) /
4279 (This->stateBlock->viewport.Height * This->stateBlock->viewport.Height * scaleFactor);
4280 att[1] = *((float*)&This->stateBlock->renderState[WINED3DRS_POINTSCALE_B]) /
4281 (This->stateBlock->viewport.Height * This->stateBlock->viewport.Height * scaleFactor);
4282 att[2] = *((float*)&This->stateBlock->renderState[WINED3DRS_POINTSCALE_C]) /
4283 (This->stateBlock->viewport.Height * This->stateBlock->viewport.Height * scaleFactor);
4287 if(GL_SUPPORT(ARB_POINT_PARAMETERS)) {
4288 GL_EXTCALL(glPointParameterfvARB)(GL_POINT_DISTANCE_ATTENUATION_ARB, att);
4289 checkGLcall("glPointParameterfvARB(GL_DISTANCE_ATTENUATION_ARB, ...");
4291 else if(GL_SUPPORT(EXT_POINT_PARAMETERS)) {
4292 GL_EXTCALL(glPointParameterfvEXT)(GL_DISTANCE_ATTENUATION_EXT, att);
4293 checkGLcall("glPointParameterfvEXT(GL_DISTANCE_ATTENUATION_EXT, ...");
4295 TRACE("POINT_PARAMETERS not supported in this version of opengl\n");
4299 case WINED3DRS_COLORWRITEENABLE :
4301 TRACE("Color mask: r(%d) g(%d) b(%d) a(%d)\n",
4302 Value & D3DCOLORWRITEENABLE_RED ? 1 : 0,
4303 Value & D3DCOLORWRITEENABLE_GREEN ? 1 : 0,
4304 Value & D3DCOLORWRITEENABLE_BLUE ? 1 : 0,
4305 Value & D3DCOLORWRITEENABLE_ALPHA ? 1 : 0);
4306 glColorMask(Value & D3DCOLORWRITEENABLE_RED ? GL_TRUE : GL_FALSE,
4307 Value & D3DCOLORWRITEENABLE_GREEN ? GL_TRUE : GL_FALSE,
4308 Value & D3DCOLORWRITEENABLE_BLUE ? GL_TRUE : GL_FALSE,
4309 Value & D3DCOLORWRITEENABLE_ALPHA ? GL_TRUE : GL_FALSE);
4310 checkGLcall("glColorMask(...)");
4314 case WINED3DRS_LOCALVIEWER :
4316 GLint state = (Value) ? 1 : 0;
4317 TRACE("Local Viewer Enable to %ul\n", (BOOL) Value);
4318 glLightModeli(GL_LIGHT_MODEL_LOCAL_VIEWER, state);
4322 case WINED3DRS_LASTPIXEL :
4325 TRACE("Last Pixel Drawing Enabled\n");
4327 FIXME("Last Pixel Drawing Disabled, not handled yet\n");
4332 case WINED3DRS_SOFTWAREVERTEXPROCESSING :
4335 TRACE("Software Processing Enabled\n");
4337 TRACE("Software Processing Disabled\n");
4342 /** not supported */
4343 case WINED3DRS_ZVISIBLE :
4346 return WINED3DERR_INVALIDCALL;
4348 case WINED3DRS_POINTSPRITEENABLE :
4350 /* TODO: NV_POINT_SPRITE */
4351 if (!GL_SUPPORT(ARB_POINT_SPRITE)) {
4352 TRACE("Point sprites not supported\n");
4357 * Point sprites are always enabled. Value controls texture coordinate
4358 * replacement mode. Must be set true for point sprites to use
4361 glEnable(GL_POINT_SPRITE_ARB);
4362 checkGLcall("glEnable(GL_POINT_SPRITE_ARB)");
4365 glTexEnvf(GL_POINT_SPRITE_ARB, GL_COORD_REPLACE_ARB, TRUE);
4366 checkGLcall("glTexEnvf(GL_POINT_SPRITE, GL_COORD_REPLACE, TRUE)");
4368 glTexEnvf(GL_POINT_SPRITE_ARB, GL_COORD_REPLACE_ARB, FALSE);
4369 checkGLcall("glTexEnvf(GL_POINT_SPRITE, GL_COORD_REPLACE, FALSE)");
4373 case WINED3DRS_EDGEANTIALIAS :
4376 glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
4378 checkGLcall("glEnable(GL_BLEND)");
4379 glEnable(GL_LINE_SMOOTH);
4380 checkGLcall("glEnable(GL_LINE_SMOOTH)");
4382 if(!This->stateBlock->renderState[WINED3DRS_ALPHABLENDENABLE]) {
4383 glDisable(GL_BLEND);
4384 checkGLcall("glDisable(GL_BLEND)");
4386 glDisable(GL_LINE_SMOOTH);
4387 checkGLcall("glDisable(GL_LINE_SMOOTH)");
4391 case WINED3DRS_WRAP0 :
4392 case WINED3DRS_WRAP1 :
4393 case WINED3DRS_WRAP2 :
4394 case WINED3DRS_WRAP3 :
4395 case WINED3DRS_WRAP4 :
4396 case WINED3DRS_WRAP5 :
4397 case WINED3DRS_WRAP6 :
4398 case WINED3DRS_WRAP7 :
4399 case WINED3DRS_WRAP8 :
4400 case WINED3DRS_WRAP9 :
4401 case WINED3DRS_WRAP10 :
4402 case WINED3DRS_WRAP11 :
4403 case WINED3DRS_WRAP12 :
4404 case WINED3DRS_WRAP13 :
4405 case WINED3DRS_WRAP14 :
4406 case WINED3DRS_WRAP15 :
4408 http://www.cosc.brocku.ca/Offerings/3P98/course/lectures/texture/
4409 http://msdn.microsoft.com/archive/default.asp?url=/archive/en-us/directx9_c/directx/graphics/programmingguide/FixedFunction/Textures/texturewrapping.asp
4410 http://www.gamedev.net/reference/programming/features/rendererdll3/page2.asp
4411 Descussion that ways to turn on WRAPing to solve an opengl conversion problem.
4412 http://www.flipcode.org/cgi-bin/fcmsg.cgi?thread_show=10248
4414 so far as I can tell, wrapping and texture-coordinate generate go hand in hand,
4416 TRACE("(%p)->(%s,%ld) Texture wraping not yet supported\n",This, debug_d3drenderstate(State), Value);
4418 case WINED3DRS_MULTISAMPLEANTIALIAS :
4420 if (!GL_SUPPORT(ARB_MULTISAMPLE)) {
4421 TRACE("Multisample antialiasing not supported\n");
4426 glEnable(GL_MULTISAMPLE_ARB);
4427 checkGLcall("glEnable(GL_MULTISAMPLE_ARB)");
4429 glDisable(GL_MULTISAMPLE_ARB);
4430 checkGLcall("glDisable(GL_MULTISAMPLE_ARB)");
4434 case WINED3DRS_SCISSORTESTENABLE :
4437 glEnable(GL_SCISSOR_TEST);
4438 checkGLcall("glEnable(GL_SCISSOR_TEST)");
4440 glDisable(GL_SCISSOR_TEST);
4441 checkGLcall("glDisable(GL_SCISSOR_TEST)");
4445 case WINED3DRS_SLOPESCALEDEPTHBIAS :
4449 glEnable(GL_POLYGON_OFFSET_FILL);
4450 checkGLcall("glEnable(GL_POLYGON_OFFSET_FILL)");
4451 glPolygonOffset(tmpvalue.f, *((float*)&This->stateBlock->renderState[WINED3DRS_DEPTHBIAS]));
4452 checkGLcall("glPolygonOffset(...)");
4454 glDisable(GL_POLYGON_OFFSET_FILL);
4455 checkGLcall("glDisable(GL_POLYGON_OFFSET_FILL)");
4459 case WINED3DRS_ANTIALIASEDLINEENABLE :
4462 glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
4464 checkGLcall("glEnable(GL_BLEND)");
4465 glEnable(GL_LINE_SMOOTH);
4466 checkGLcall("glEnable(GL_LINE_SMOOTH)");
4468 glDisable(GL_BLEND);
4469 checkGLcall("glDisable(GL_BLEND)");
4470 glDisable(GL_LINE_SMOOTH);
4471 checkGLcall("glDisable(GL_LINE_SMOOTH)");
4475 case WINED3DRS_DEPTHBIAS :
4479 glEnable(GL_POLYGON_OFFSET_FILL);
4480 checkGLcall("glEnable(GL_POLYGON_OFFSET_FILL)");
4481 glPolygonOffset(*((float*)&This->stateBlock->renderState[WINED3DRS_SLOPESCALEDEPTHBIAS]), tmpvalue.f);
4482 checkGLcall("glPolygonOffset(...)");
4484 glDisable(GL_POLYGON_OFFSET_FILL);
4485 checkGLcall("glDisable(GL_POLYGON_OFFSET_FILL)");
4490 case WINED3DRS_TEXTUREPERSPECTIVE :
4493 glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST);
4495 glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_FASTEST);
4499 case WINED3DRS_STIPPLEDALPHA :
4502 ERR(" Stippled Alpha not supported yet.\n");
4505 case WINED3DRS_ANTIALIAS :
4508 ERR(" Antialias not supported yet.\n");
4512 FIXME("(%p)->(%s,%ld) not handled yet\n", This, debug_d3drenderstate(State), Value);
4520 static HRESULT WINAPI IWineD3DDeviceImpl_GetRenderState(IWineD3DDevice *iface, D3DRENDERSTATETYPE State, DWORD *pValue) {
4521 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4522 TRACE("(%p) for State %d = %ld\n", This, State, This->stateBlock->renderState[State]);
4523 *pValue = This->stateBlock->renderState[State];
4528 * Get / Set Sampler States
4529 * TODO: Verify against dx9 definitions
4532 static HRESULT WINAPI IWineD3DDeviceImpl_SetSamplerState(IWineD3DDevice *iface, DWORD Sampler, WINED3DSAMPLERSTATETYPE Type, DWORD Value) {
4533 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4535 * SetSampler is designed to allow for more than the standard up to 8 textures
4536 * and Geforce has stopped supporting more than 6 standard textures in openGL.
4537 * So I have to use ARB for Gforce. (maybe if the sampler > 4 then use ARB?)
4539 * http://developer.nvidia.com/object/General_FAQ.html#t6
4541 * There are two new settings for GForce
4543 * GL_MAX_TEXTURE_IMAGE_UNITS_ARB
4544 * and the texture one:
4545 * GL_MAX_TEXTURE_COORDS_ARB.
4546 * Ok GForce say it's ok to use glTexParameter/glGetTexParameter(...).
4548 /** NOTE: States are appled in IWineD3DBaseTextre ApplyStateChanges and IWineD3DDevice SetupTextureStates**/
4549 if(Sampler > GL_LIMITS(sampler_stages) || Sampler < 0 || Type > WINED3D_HIGHEST_SAMPLER_STATE || Type < 0) {
4550 FIXME("sampler %ld type %s(%u) is out of range [max_samplers=%d, highest_state=%d]\n",
4551 Sampler, debug_d3dsamplerstate(Type), Type, GL_LIMITS(sampler_stages), WINED3D_HIGHEST_SAMPLER_STATE);
4552 return WINED3DERR_INVALIDCALL;
4555 TRACE("(%p) : Sampler=%ld, Type=%s(%d), Value=%ld\n", This, Sampler,
4556 debug_d3dsamplerstate(Type), Type, Value);
4557 This->updateStateBlock->samplerState[Sampler][Type] = Value;
4558 This->updateStateBlock->set.samplerState[Sampler][Type] = Value;
4559 This->updateStateBlock->changed.samplerState[Sampler][Type] = Value;
4561 /* Handle recording of state blocks */
4562 if (This->isRecordingState) {
4563 TRACE("Recording... not performing anything\n");
4570 static HRESULT WINAPI IWineD3DDeviceImpl_GetSamplerState(IWineD3DDevice *iface, DWORD Sampler, WINED3DSAMPLERSTATETYPE Type, DWORD* Value) {
4571 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4572 /** TODO: check that sampler is in range **/
4573 *Value = This->updateStateBlock->samplerState[Sampler][Type];
4574 TRACE("(%p) : Sampler %ld Type %u Returning %ld\n", This, Sampler, Type, *Value);
4579 static HRESULT WINAPI IWineD3DDeviceImpl_SetScissorRect(IWineD3DDevice *iface, CONST RECT* pRect) {
4580 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4583 /** FIXME: Windows uses a top,left origin openGL uses a bottom Right? **/
4584 TRACE("(%p)Setting new Scissor Rect to %ld:%ld-%ld:%ld\n", This, pRect->left, pRect->top, pRect->right, pRect->bottom);
4585 glScissor(pRect->left, pRect->top, pRect->right - pRect->left, pRect->bottom - pRect->top);
4591 static HRESULT WINAPI IWineD3DDeviceImpl_GetScissorRect(IWineD3DDevice *iface, RECT* pRect) {
4592 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4593 GLint scissorBox[4];
4596 /** FIXME: Windows uses a top,left origin openGL uses a bottom Right? **/
4597 glGetIntegerv(GL_SCISSOR_BOX, scissorBox);
4598 pRect->left = scissorBox[0];
4599 pRect->top = scissorBox[1];
4600 pRect->right = scissorBox[0] + scissorBox[2];
4601 pRect->bottom = scissorBox[1] + scissorBox[3];
4602 TRACE("(%p)Returning a Scissor Rect of %ld:%ld-%ld:%ld\n", This, pRect->left, pRect->top, pRect->right, pRect->bottom);
4607 static HRESULT WINAPI IWineD3DDeviceImpl_SetVertexDeclaration(IWineD3DDevice* iface, IWineD3DVertexDeclaration* pDecl) {
4608 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *) iface;
4609 IWineD3DVertexDeclaration *oldDecl = This->updateStateBlock->vertexDecl;
4611 TRACE("(%p) : pDecl=%p\n", This, pDecl);
4613 This->updateStateBlock->vertexDecl = pDecl;
4614 This->updateStateBlock->changed.vertexDecl = TRUE;
4615 This->updateStateBlock->set.vertexDecl = TRUE;
4617 if (This->isRecordingState) {
4618 TRACE("Recording... not performing anything\n");
4621 if (NULL != pDecl) {
4622 IWineD3DVertexDeclaration_AddRef(pDecl);
4624 if (NULL != oldDecl) {
4625 IWineD3DVertexDeclaration_Release(oldDecl);
4630 static HRESULT WINAPI IWineD3DDeviceImpl_GetVertexDeclaration(IWineD3DDevice* iface, IWineD3DVertexDeclaration** ppDecl) {
4631 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4633 TRACE("(%p) : ppDecl=%p\n", This, ppDecl);
4635 *ppDecl = This->stateBlock->vertexDecl;
4636 if (NULL != *ppDecl) IWineD3DVertexDeclaration_AddRef(*ppDecl);
4640 static HRESULT WINAPI IWineD3DDeviceImpl_SetVertexShader(IWineD3DDevice *iface, IWineD3DVertexShader* pShader) {
4641 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4642 IWineD3DVertexShader* oldShader = This->updateStateBlock->vertexShader;
4644 This->updateStateBlock->vertexShader = pShader;
4645 This->updateStateBlock->changed.vertexShader = TRUE;
4646 This->updateStateBlock->set.vertexShader = TRUE;
4648 if (This->isRecordingState) {
4649 TRACE("Recording... not performing anything\n");
4652 if (NULL != pShader) {
4653 IWineD3DVertexShader_AddRef(pShader);
4655 if (NULL != oldShader) {
4656 IWineD3DVertexShader_Release(oldShader);
4659 TRACE("(%p) : setting pShader(%p)\n", This, pShader);
4661 * TODO: merge HAL shaders context switching from prototype
4666 static HRESULT WINAPI IWineD3DDeviceImpl_GetVertexShader(IWineD3DDevice *iface, IWineD3DVertexShader** ppShader) {
4667 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4669 if (NULL == ppShader) {
4670 return WINED3DERR_INVALIDCALL;
4672 *ppShader = This->stateBlock->vertexShader;
4673 if( NULL != *ppShader)
4674 IWineD3DVertexShader_AddRef(*ppShader);
4676 TRACE("(%p) : returning %p\n", This, *ppShader);
4680 static HRESULT WINAPI IWineD3DDeviceImpl_SetVertexShaderConstantB(
4681 IWineD3DDevice *iface,
4683 CONST BOOL *srcData,
4686 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4687 int i, cnt = min(count, MAX_VSHADER_CONSTANTS - start);
4689 TRACE("(iface %p, srcData %p, start %d, count %d)\n",
4690 iface, srcData, start, count);
4692 if (srcData == NULL || cnt < 0)
4693 return WINED3DERR_INVALIDCALL;
4695 memcpy(&This->updateStateBlock->vertexShaderConstantB[start], srcData, cnt * sizeof(BOOL));
4696 for (i = 0; i < cnt; i++)
4697 TRACE("Set BOOL constant %u to %s\n", i, srcData[i]? "true":"false");
4699 for (i = start; i < cnt + start; ++i) {
4700 This->updateStateBlock->changed.vertexShaderConstantsB[i] = TRUE;
4701 This->updateStateBlock->set.vertexShaderConstantsB[i] = TRUE;
4707 static HRESULT WINAPI IWineD3DDeviceImpl_GetVertexShaderConstantB(
4708 IWineD3DDevice *iface,
4713 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4714 int cnt = min(count, MAX_VSHADER_CONSTANTS - start);
4716 TRACE("(iface %p, dstData %p, start %d, count %d)\n",
4717 iface, dstData, start, count);
4719 if (dstData == NULL || cnt < 0)
4720 return WINED3DERR_INVALIDCALL;
4722 memcpy(dstData, &This->updateStateBlock->vertexShaderConstantB[start], cnt * sizeof(BOOL));
4726 static HRESULT WINAPI IWineD3DDeviceImpl_SetVertexShaderConstantI(
4727 IWineD3DDevice *iface,
4732 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4733 int i, cnt = min(count, MAX_VSHADER_CONSTANTS - start);
4735 TRACE("(iface %p, srcData %p, start %d, count %d)\n",
4736 iface, srcData, start, count);
4738 if (srcData == NULL || cnt < 0)
4739 return WINED3DERR_INVALIDCALL;
4741 memcpy(&This->updateStateBlock->vertexShaderConstantI[start * 4], srcData, cnt * sizeof(int) * 4);
4742 for (i = 0; i < cnt; i++)
4743 TRACE("Set INT constant %u to { %d, %d, %d, %d }\n", i,
4744 srcData[i*4], srcData[i*4+1], srcData[i*4+2], srcData[i*4+3]);
4746 for (i = start; i < cnt + start; ++i) {
4747 This->updateStateBlock->changed.vertexShaderConstantsI[i] = TRUE;
4748 This->updateStateBlock->set.vertexShaderConstantsI[i] = TRUE;
4754 static HRESULT WINAPI IWineD3DDeviceImpl_GetVertexShaderConstantI(
4755 IWineD3DDevice *iface,
4760 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4761 int cnt = min(count, MAX_VSHADER_CONSTANTS - start);
4763 TRACE("(iface %p, dstData %p, start %d, count %d)\n",
4764 iface, dstData, start, count);
4766 if (dstData == NULL || cnt < 0)
4767 return WINED3DERR_INVALIDCALL;
4769 memcpy(dstData, &This->updateStateBlock->vertexShaderConstantI[start * 4], cnt * sizeof(int) * 4);
4773 static HRESULT WINAPI IWineD3DDeviceImpl_SetVertexShaderConstantF(
4774 IWineD3DDevice *iface,
4776 CONST float *srcData,
4779 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4780 int i, cnt = min(count, MAX_VSHADER_CONSTANTS - start);
4782 TRACE("(iface %p, srcData %p, start %d, count %d)\n",
4783 iface, srcData, start, count);
4785 if (srcData == NULL || cnt < 0)
4786 return WINED3DERR_INVALIDCALL;
4788 memcpy(&This->updateStateBlock->vertexShaderConstantF[start * 4], srcData, cnt * sizeof(float) * 4);
4789 for (i = 0; i < cnt; i++)
4790 TRACE("Set FLOAT constant %u to { %f, %f, %f, %f }\n", i,
4791 srcData[i*4], srcData[i*4+1], srcData[i*4+2], srcData[i*4+3]);
4793 for (i = start; i < cnt + start; ++i) {
4794 This->updateStateBlock->changed.vertexShaderConstantsF[i] = TRUE;
4795 This->updateStateBlock->set.vertexShaderConstantsF[i] = TRUE;
4801 static HRESULT WINAPI IWineD3DDeviceImpl_GetVertexShaderConstantF(
4802 IWineD3DDevice *iface,
4807 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4808 int cnt = min(count, MAX_VSHADER_CONSTANTS - start);
4810 TRACE("(iface %p, dstData %p, start %d, count %d)\n",
4811 iface, dstData, start, count);
4813 if (dstData == NULL || cnt < 0)
4814 return WINED3DERR_INVALIDCALL;
4816 memcpy(dstData, &This->updateStateBlock->vertexShaderConstantF[start * 4], cnt * sizeof(float) * 4);
4820 static HRESULT WINAPI IWineD3DDeviceImpl_SetPixelShader(IWineD3DDevice *iface, IWineD3DPixelShader *pShader) {
4821 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4822 IWineD3DPixelShader *oldShader = This->updateStateBlock->pixelShader;
4823 This->updateStateBlock->pixelShader = pShader;
4824 This->updateStateBlock->changed.pixelShader = TRUE;
4825 This->updateStateBlock->set.pixelShader = TRUE;
4827 /* Handle recording of state blocks */
4828 if (This->isRecordingState) {
4829 TRACE("Recording... not performing anything\n");
4832 if (NULL != pShader) {
4833 IWineD3DPixelShader_AddRef(pShader);
4835 if (NULL != oldShader) {
4836 IWineD3DPixelShader_Release(oldShader);
4839 TRACE("(%p) : setting pShader(%p)\n", This, pShader);
4841 * TODO: merge HAL shaders context switching from prototype
4846 static HRESULT WINAPI IWineD3DDeviceImpl_GetPixelShader(IWineD3DDevice *iface, IWineD3DPixelShader **ppShader) {
4847 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4849 if (NULL == ppShader) {
4850 WARN("(%p) : PShader is NULL, returning INVALIDCALL\n", This);
4851 return WINED3DERR_INVALIDCALL;
4854 *ppShader = This->stateBlock->pixelShader;
4855 if (NULL != *ppShader) {
4856 IWineD3DPixelShader_AddRef(*ppShader);
4858 TRACE("(%p) : returning %p\n", This, *ppShader);
4862 static HRESULT WINAPI IWineD3DDeviceImpl_SetPixelShaderConstantB(
4863 IWineD3DDevice *iface,
4865 CONST BOOL *srcData,
4868 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4869 int i, cnt = min(count, MAX_PSHADER_CONSTANTS - start);
4871 TRACE("(iface %p, srcData %p, start %d, count %d)\n",
4872 iface, srcData, start, count);
4874 if (srcData == NULL || cnt < 0)
4875 return WINED3DERR_INVALIDCALL;
4877 memcpy(&This->updateStateBlock->pixelShaderConstantB[start], srcData, cnt * sizeof(BOOL));
4878 for (i = 0; i < cnt; i++)
4879 TRACE("Set BOOL constant %u to %s\n", i, srcData[i]? "true":"false");
4881 for (i = start; i < cnt + start; ++i) {
4882 This->updateStateBlock->changed.pixelShaderConstantsB[i] = TRUE;
4883 This->updateStateBlock->set.pixelShaderConstantsB[i] = TRUE;
4889 static HRESULT WINAPI IWineD3DDeviceImpl_GetPixelShaderConstantB(
4890 IWineD3DDevice *iface,
4895 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4896 int cnt = min(count, MAX_PSHADER_CONSTANTS - start);
4898 TRACE("(iface %p, dstData %p, start %d, count %d)\n",
4899 iface, dstData, start, count);
4901 if (dstData == NULL || cnt < 0)
4902 return WINED3DERR_INVALIDCALL;
4904 memcpy(dstData, &This->updateStateBlock->pixelShaderConstantB[start], cnt * sizeof(BOOL));
4908 static HRESULT WINAPI IWineD3DDeviceImpl_SetPixelShaderConstantI(
4909 IWineD3DDevice *iface,
4914 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4915 int i, cnt = min(count, MAX_PSHADER_CONSTANTS - start);
4917 TRACE("(iface %p, srcData %p, start %d, count %d)\n",
4918 iface, srcData, start, count);
4920 if (srcData == NULL || cnt < 0)
4921 return WINED3DERR_INVALIDCALL;
4923 memcpy(&This->updateStateBlock->pixelShaderConstantI[start * 4], srcData, cnt * sizeof(int) * 4);
4924 for (i = 0; i < cnt; i++)
4925 TRACE("Set INT constant %u to { %d, %d, %d, %d }\n", i,
4926 srcData[i*4], srcData[i*4+1], srcData[i*4+2], srcData[i*4+3]);
4928 for (i = start; i < cnt + start; ++i) {
4929 This->updateStateBlock->changed.pixelShaderConstantsI[i] = TRUE;
4930 This->updateStateBlock->set.pixelShaderConstantsI[i] = TRUE;
4936 static HRESULT WINAPI IWineD3DDeviceImpl_GetPixelShaderConstantI(
4937 IWineD3DDevice *iface,
4942 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4943 int cnt = min(count, MAX_PSHADER_CONSTANTS - start);
4945 TRACE("(iface %p, dstData %p, start %d, count %d)\n",
4946 iface, dstData, start, count);
4948 if (dstData == NULL || cnt < 0)
4949 return WINED3DERR_INVALIDCALL;
4951 memcpy(dstData, &This->updateStateBlock->pixelShaderConstantI[start * 4], cnt * sizeof(int) * 4);
4955 static HRESULT WINAPI IWineD3DDeviceImpl_SetPixelShaderConstantF(
4956 IWineD3DDevice *iface,
4958 CONST float *srcData,
4961 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4962 int i, cnt = min(count, MAX_PSHADER_CONSTANTS - start);
4964 TRACE("(iface %p, srcData %p, start %d, count %d)\n",
4965 iface, srcData, start, count);
4967 if (srcData == NULL || cnt < 0)
4968 return WINED3DERR_INVALIDCALL;
4970 memcpy(&This->updateStateBlock->pixelShaderConstantF[start * 4], srcData, cnt * sizeof(float) * 4);
4971 for (i = 0; i < cnt; i++)
4972 TRACE("Set FLOAT constant %u to { %f, %f, %f, %f }\n", i,
4973 srcData[i*4], srcData[i*4+1], srcData[i*4+2], srcData[i*4+3]);
4975 for (i = start; i < cnt + start; ++i) {
4976 This->updateStateBlock->changed.pixelShaderConstantsF[i] = TRUE;
4977 This->updateStateBlock->set.pixelShaderConstantsF[i] = TRUE;
4983 static HRESULT WINAPI IWineD3DDeviceImpl_GetPixelShaderConstantF(
4984 IWineD3DDevice *iface,
4989 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4990 int cnt = min(count, MAX_PSHADER_CONSTANTS - start);
4992 TRACE("(iface %p, dstData %p, start %d, count %d)\n",
4993 iface, dstData, start, count);
4995 if (dstData == NULL || cnt < 0)
4996 return WINED3DERR_INVALIDCALL;
4998 memcpy(dstData, &This->updateStateBlock->pixelShaderConstantF[start * 4], cnt * sizeof(float) * 4);
5002 #define copy_and_next(dest, src, size) memcpy(dest, src, size); dest += (size)
5004 process_vertices_strided(IWineD3DDeviceImpl *This, DWORD dwDestIndex, DWORD dwCount, WineDirect3DVertexStridedData *lpStrideData, DWORD SrcFVF, IWineD3DVertexBufferImpl *dest, DWORD dwFlags) {
5005 char *dest_ptr, *dest_conv = NULL;
5007 DWORD DestFVF = dest->fvf;
5009 D3DMATRIX mat, proj_mat, view_mat, world_mat;
5013 if (SrcFVF & D3DFVF_NORMAL) {
5014 WARN(" lighting state not saved yet... Some strange stuff may happen !\n");
5017 if ( (SrcFVF & D3DFVF_POSITION_MASK) != D3DFVF_XYZ) {
5018 ERR("Source has no position mask\n");
5019 return WINED3DERR_INVALIDCALL;
5022 /* We might access VBOs from this code, so hold the lock */
5025 if (dest->resource.allocatedMemory == NULL) {
5026 /* This may happen if we do direct locking into a vbo. Unlikely,
5027 * but theoretically possible(ddraw processvertices test)
5029 dest->resource.allocatedMemory = HeapAlloc(GetProcessHeap(), 0, dest->resource.size);
5030 if(!dest->resource.allocatedMemory) {
5032 ERR("Out of memory\n");
5033 return E_OUTOFMEMORY;
5037 GL_EXTCALL(glBindBufferARB(GL_ARRAY_BUFFER_ARB, dest->vbo));
5038 checkGLcall("glBindBufferARB");
5039 src = GL_EXTCALL(glMapBufferARB(GL_ARRAY_BUFFER_ARB, GL_READ_ONLY_ARB));
5041 memcpy(dest->resource.allocatedMemory, src, dest->resource.size);
5043 GL_EXTCALL(glUnmapBufferARB(GL_ARRAY_BUFFER_ARB));
5044 checkGLcall("glUnmapBufferARB");
5048 /* Get a pointer into the destination vbo(create one if none exists) and
5049 * write correct opengl data into it. It's cheap and allows us to run drawStridedFast
5051 if(!dest->vbo && GL_SUPPORT(ARB_VERTEX_BUFFER_OBJECT)) {
5056 GL_EXTCALL(glBindBufferARB(GL_ARRAY_BUFFER_ARB, dest->vbo));
5057 dest_conv = GL_EXTCALL(glMapBufferARB(GL_ARRAY_BUFFER_ARB, GL_WRITE_ONLY_ARB));
5059 ERR("glMapBuffer failed\n");
5060 /* Continue without storing converted vertices */
5065 * a) D3DRS_CLIPPING is enabled
5066 * b) WINED3DVOP_CLIP is passed
5068 if(This->stateBlock->renderState[WINED3DRS_CLIPPING]) {
5069 static BOOL warned = FALSE;
5071 * The clipping code is not quite correct. Some things need
5072 * to be checked against IDirect3DDevice3 (!), d3d8 and d3d9,
5073 * so disable clipping for now.
5074 * (The graphics in Half-Life are broken, and my processvertices
5075 * test crashes with IDirect3DDevice3)
5081 FIXME("Clipping is broken and disabled for now\n");
5083 } else doClip = FALSE;
5084 dest_ptr = ((char *) dest->resource.allocatedMemory) + dwDestIndex * get_flexible_vertex_size(DestFVF);
5086 dest_conv = ((char *) dest_conv) + dwDestIndex * get_flexible_vertex_size(DestFVF);
5089 IWineD3DDevice_GetTransform( (IWineD3DDevice *) This,
5092 IWineD3DDevice_GetTransform( (IWineD3DDevice *) This,
5095 IWineD3DDevice_GetTransform( (IWineD3DDevice *) This,
5096 D3DTS_WORLDMATRIX(0),
5099 TRACE("View mat:\n");
5100 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); \
5101 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); \
5102 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); \
5103 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); \
5105 TRACE("Proj mat:\n");
5106 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); \
5107 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); \
5108 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); \
5109 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); \
5111 TRACE("World mat:\n");
5112 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); \
5113 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); \
5114 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); \
5115 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); \
5117 /* Get the viewport */
5118 IWineD3DDevice_GetViewport( (IWineD3DDevice *) This, &vp);
5119 TRACE("Viewport: X=%ld, Y=%ld, Width=%ld, Height=%ld, MinZ=%f, MaxZ=%f\n",
5120 vp.X, vp.Y, vp.Width, vp.Height, vp.MinZ, vp.MaxZ);
5122 multiply_matrix(&mat,&view_mat,&world_mat);
5123 multiply_matrix(&mat,&proj_mat,&mat);
5125 numTextures = (DestFVF & D3DFVF_TEXCOUNT_MASK) >> D3DFVF_TEXCOUNT_SHIFT;
5127 for (i = 0; i < dwCount; i+= 1) {
5128 unsigned int tex_index;
5130 if ( ((DestFVF & D3DFVF_POSITION_MASK) == D3DFVF_XYZ ) ||
5131 ((DestFVF & D3DFVF_POSITION_MASK) == D3DFVF_XYZRHW ) ) {
5132 /* The position first */
5134 (float *) (((char *) lpStrideData->u.s.position.lpData) + i * lpStrideData->u.s.position.dwStride);
5136 TRACE("In: ( %06.2f %06.2f %06.2f )\n", p[0], p[1], p[2]);
5138 /* Multiplication with world, view and projection matrix */
5139 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);
5140 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);
5141 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);
5142 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);
5144 TRACE("x=%f y=%f z=%f rhw=%f\n", x, y, z, rhw);
5146 /* WARNING: The following things are taken from d3d7 and were not yet checked
5147 * against d3d8 or d3d9!
5150 /* Clipping conditions: From
5151 * http://msdn.microsoft.com/archive/default.asp?url=/archive/en-us/directx9_c/directx/graphics/programmingguide/fixedfunction/viewportsclipping/clippingvolumes.asp
5153 * A vertex is clipped if it does not match the following requirements
5157 * 0 < rhw ( Not in d3d7, but tested in d3d7)
5159 * If clipping is on is determined by the D3DVOP_CLIP flag in D3D7, and
5160 * by the D3DRS_CLIPPING in D3D9(according to the msdn, not checked)
5164 if( doClip == FALSE ||
5165 ( (-rhw -eps < x) && (-rhw -eps < y) && ( -eps < z) &&
5166 (x <= rhw + eps) && (y <= rhw + eps ) && (z <= rhw + eps) &&
5169 /* "Normal" viewport transformation (not clipped)
5170 * 1) The values are divided by rhw
5171 * 2) The y axis is negative, so multiply it with -1
5172 * 3) Screen coordinates go from -(Width/2) to +(Width/2) and
5173 * -(Height/2) to +(Height/2). The z range is MinZ to MaxZ
5174 * 4) Multiply x with Width/2 and add Width/2
5175 * 5) The same for the height
5176 * 6) Add the viewpoint X and Y to the 2D coordinates and
5177 * The minimum Z value to z
5178 * 7) rhw = 1 / rhw Reciprocal of Homogeneous W....
5180 * Well, basically it's simply a linear transformation into viewport
5192 z *= vp.MaxZ - vp.MinZ;
5194 x += vp.Width / 2 + vp.X;
5195 y += vp.Height / 2 + vp.Y;
5200 /* That vertex got clipped
5201 * Contrary to OpenGL it is not dropped completely, it just
5202 * undergoes a different calculation.
5204 TRACE("Vertex got clipped\n");
5211 /* Msdn mentions that Direct3D9 keeps a list of clipped vertices
5212 * outside of the main vertex buffer memory. That needs some more
5217 TRACE("Writing (%f %f %f) %f\n", x, y, z, rhw);
5220 ( (float *) dest_ptr)[0] = x;
5221 ( (float *) dest_ptr)[1] = y;
5222 ( (float *) dest_ptr)[2] = z;
5223 ( (float *) dest_ptr)[3] = rhw; /* SIC, see ddraw test! */
5225 dest_ptr += 3 * sizeof(float);
5227 if((DestFVF & D3DFVF_POSITION_MASK) == D3DFVF_XYZRHW) {
5228 dest_ptr += sizeof(float);
5233 ( (float *) dest_conv)[0] = x * w;
5234 ( (float *) dest_conv)[1] = y * w;
5235 ( (float *) dest_conv)[2] = z * w;
5236 ( (float *) dest_conv)[3] = w;
5238 dest_conv += 3 * sizeof(float);
5240 if((DestFVF & D3DFVF_POSITION_MASK) == D3DFVF_XYZRHW) {
5241 dest_conv += sizeof(float);
5245 if (DestFVF & D3DFVF_PSIZE) {
5246 dest_ptr += sizeof(DWORD);
5247 if(dest_conv) dest_conv += sizeof(DWORD);
5249 if (DestFVF & D3DFVF_NORMAL) {
5251 (float *) (((float *) lpStrideData->u.s.normal.lpData) + i * lpStrideData->u.s.normal.dwStride);
5252 /* AFAIK this should go into the lighting information */
5253 FIXME("Didn't expect the destination to have a normal\n");
5254 copy_and_next(dest_ptr, normal, 3 * sizeof(float));
5256 copy_and_next(dest_conv, normal, 3 * sizeof(float));
5260 if (DestFVF & D3DFVF_DIFFUSE) {
5262 (DWORD *) (((char *) lpStrideData->u.s.diffuse.lpData) + i * lpStrideData->u.s.diffuse.dwStride);
5264 static BOOL warned = FALSE;
5266 if(warned == FALSE) {
5267 ERR("No diffuse color in source, but destination has one\n");
5271 *( (DWORD *) dest_ptr) = 0xffffffff;
5272 dest_ptr += sizeof(DWORD);
5275 *( (DWORD *) dest_conv) = 0xffffffff;
5276 dest_conv += sizeof(DWORD);
5280 copy_and_next(dest_ptr, color_d, sizeof(DWORD));
5282 *( (DWORD *) dest_conv) = (*color_d & 0xff00ff00) ; /* Alpha + green */
5283 *( (DWORD *) dest_conv) |= (*color_d & 0x00ff0000) >> 16; /* Red */
5284 *( (DWORD *) dest_conv) |= (*color_d & 0xff0000ff) << 16; /* Blue */
5285 dest_conv += sizeof(DWORD);
5290 if (DestFVF & D3DFVF_SPECULAR) {
5291 /* What's the color value in the feedback buffer? */
5293 (DWORD *) (((char *) lpStrideData->u.s.specular.lpData) + i * lpStrideData->u.s.specular.dwStride);
5295 static BOOL warned = FALSE;
5297 if(warned == FALSE) {
5298 ERR("No specular color in source, but destination has one\n");
5302 *( (DWORD *) dest_ptr) = 0xFF000000;
5303 dest_ptr += sizeof(DWORD);
5306 *( (DWORD *) dest_conv) = 0xFF000000;
5307 dest_conv += sizeof(DWORD);
5311 copy_and_next(dest_ptr, color_s, sizeof(DWORD));
5313 *( (DWORD *) dest_conv) = (*color_s & 0xff00ff00) ; /* Alpha + green */
5314 *( (DWORD *) dest_conv) |= (*color_s & 0x00ff0000) >> 16; /* Red */
5315 *( (DWORD *) dest_conv) |= (*color_s & 0xff0000ff) << 16; /* Blue */
5316 dest_conv += sizeof(DWORD);
5321 for (tex_index = 0; tex_index < numTextures; tex_index++) {
5323 (float *) (((char *) lpStrideData->u.s.texCoords[tex_index].lpData) +
5324 i * lpStrideData->u.s.texCoords[tex_index].dwStride);
5326 ERR("No source texture, but destination requests one\n");
5327 dest_ptr+=GET_TEXCOORD_SIZE_FROM_FVF(DestFVF, tex_index) * sizeof(float);
5328 if(dest_conv) dest_conv += GET_TEXCOORD_SIZE_FROM_FVF(DestFVF, tex_index) * sizeof(float);
5331 copy_and_next(dest_ptr, tex_coord, GET_TEXCOORD_SIZE_FROM_FVF(DestFVF, tex_index) * sizeof(float));
5333 copy_and_next(dest_conv, tex_coord, GET_TEXCOORD_SIZE_FROM_FVF(DestFVF, tex_index) * sizeof(float));
5340 GL_EXTCALL(glUnmapBufferARB(GL_ARRAY_BUFFER_ARB));
5341 checkGLcall("glUnmapBufferARB(GL_ARRAY_BUFFER_ARB)");
5348 #undef copy_and_next
5350 static HRESULT WINAPI IWineD3DDeviceImpl_ProcessVertices(IWineD3DDevice *iface, UINT SrcStartIndex, UINT DestIndex, UINT VertexCount, IWineD3DVertexBuffer* pDestBuffer, IWineD3DVertexBuffer* pVertexDecl, DWORD Flags) {
5351 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5352 IWineD3DVertexBufferImpl *SrcImpl = (IWineD3DVertexBufferImpl *) pVertexDecl;
5353 WineDirect3DVertexStridedData strided;
5354 TRACE("(%p)->(%d,%d,%d,%p,%p,%ld\n", This, SrcStartIndex, DestIndex, VertexCount, pDestBuffer, pVertexDecl, Flags);
5356 /* We don't need the source vbo because this buffer is only used as
5357 * a source for ProcessVertices. Avoid wasting resources by converting the
5358 * buffer and loading the VBO
5361 TRACE("Releaseing the source vbo, it won't be needed\n");
5363 if(!SrcImpl->resource.allocatedMemory) {
5364 /* Rescue the data from the buffer */
5366 SrcImpl->resource.allocatedMemory = HeapAlloc(GetProcessHeap(), 0, SrcImpl->resource.size);
5367 if(!SrcImpl->resource.allocatedMemory) {
5368 ERR("Out of memory\n");
5369 return E_OUTOFMEMORY;
5373 GL_EXTCALL(glBindBufferARB(GL_ARRAY_BUFFER_ARB, SrcImpl->vbo));
5374 checkGLcall("glBindBufferARB");
5376 src = GL_EXTCALL(glMapBufferARB(GL_ARRAY_BUFFER_ARB, GL_READ_ONLY_ARB));
5378 memcpy(SrcImpl->resource.allocatedMemory, src, SrcImpl->resource.size);
5381 GL_EXTCALL(glUnmapBufferARB(GL_ARRAY_BUFFER_ARB));
5382 checkGLcall("glUnmapBufferARB");
5387 GL_EXTCALL(glBindBufferARB(GL_ARRAY_BUFFER_ARB, 0));
5388 checkGLcall("glBindBufferARB");
5389 GL_EXTCALL(glDeleteBuffersARB(1, &SrcImpl->vbo));
5390 checkGLcall("glDeleteBuffersARB");
5396 memset(&strided, 0, sizeof(strided));
5397 primitiveConvertFVFtoOffset(SrcImpl->fvf, get_flexible_vertex_size(SrcImpl->fvf), SrcImpl->resource.allocatedMemory + get_flexible_vertex_size(SrcImpl->fvf) * SrcStartIndex, &strided, 0);
5399 return process_vertices_strided(This, DestIndex, VertexCount, &strided, SrcImpl->fvf, (IWineD3DVertexBufferImpl *) pDestBuffer, Flags);
5403 * Apply / Get / Set Texture Stage States
5404 * TODO: Verify against dx9 definitions
5407 /* 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 */
5408 static void WINAPI IWineD3DDeviceImpl_ApplyTextureUnitState(IWineD3DDevice *iface, DWORD Stage, WINED3DTEXTURESTAGESTATETYPE Type) {
5409 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5410 DWORD Value = This->updateStateBlock->textureState[Stage][Type];
5411 /* FIXME: Handle 3d textures? What if TSS value set before set texture? Need to reapply all values? */
5413 TRACE("(%p) : Stage=%ld, Type=%s(%d), Value=%ld\n", This, Stage, debug_d3dtexturestate(Type), Type, Value);
5415 /* Check that the stage is within limits */
5416 if (Stage >= GL_LIMITS(texture_stages) || Stage < 0) {
5417 TRACE("Attempt to access invalid texture rejected\n");
5424 case WINED3DTSS_ALPHAOP :
5425 case WINED3DTSS_COLOROP :
5426 /* nothing to do as moved to drawprim for now */
5428 case WINED3DTSS_ADDRESSW :
5429 #if 0 /* I'm not sure what D3D does about ADDRESSW appearing twice */
5430 if (Value < minLookup[WINELOOKUP_WARPPARAM] || Value > maxLookup[WINELOOKUP_WARPPARAM]) {
5431 FIXME("Unrecognized or unsupported D3DTADDRESS_* value %ld, state %d\n", Value, Type);
5434 GLint wrapParm = stateLookup[WINELOOKUP_WARPPARAM][Value - minLookup[WINELOOKUP_WARPPARAM]];
5435 TRACE("Setting WRAP_R to %d for %x\n", wrapParm, This->stateBlock->textureDimensions[Stage]);
5436 glTexParameteri(This->stateBlock->textureDimensions[Stage], GL_TEXTURE_WRAP_R, wrapParm);
5437 checkGLcall("glTexParameteri(..., GL_TEXTURE_WRAP_R, wrapParm)");
5440 case WINED3DTSS_TEXCOORDINDEX :
5442 /* Values 0-7 are indexes into the FVF tex coords - See comments in DrawPrimitive */
5444 /* FIXME: From MSDN: The WINED3DTSS_TCI_* flags are mutually exclusive. If you include
5445 one flag, you can still specify an index value, which the system uses to
5446 determine the texture wrapping mode.
5447 eg. SetTextureStageState( 0, D3DTSS_TEXCOORDINDEX, D3DTSS_TCI_CAMERASPACEPOSITION | 1 );
5448 means use the vertex position (camera-space) as the input texture coordinates
5449 for this texture stage, and the wrap mode set in the WINED3DRS_WRAP1 render
5450 state. We do not (yet) support the D3DRENDERSTATE_WRAPx values, nor tie them up
5451 to the TEXCOORDINDEX value */
5454 * Be careful the value of the mask 0xF0000 come from d3d8types.h infos
5456 switch (Value & 0xFFFF0000) {
5457 case D3DTSS_TCI_PASSTHRU:
5458 /*Use the specified texture coordinates contained within the vertex format. This value resolves to zero.*/
5459 glDisable(GL_TEXTURE_GEN_S);
5460 glDisable(GL_TEXTURE_GEN_T);
5461 glDisable(GL_TEXTURE_GEN_R);
5462 glDisable(GL_TEXTURE_GEN_Q);
5463 checkGLcall("glDisable(GL_TEXTURE_GEN_S,T,R,Q)");
5466 case D3DTSS_TCI_CAMERASPACEPOSITION:
5467 /* CameraSpacePosition means use the vertex position, transformed to camera space,
5468 as the input texture coordinates for this stage's texture transformation. This
5469 equates roughly to EYE_LINEAR */
5471 float s_plane[] = { 1.0, 0.0, 0.0, 0.0 };
5472 float t_plane[] = { 0.0, 1.0, 0.0, 0.0 };
5473 float r_plane[] = { 0.0, 0.0, 1.0, 0.0 };
5474 float q_plane[] = { 0.0, 0.0, 0.0, 1.0 };
5475 TRACE("WINED3DTSS_TCI_CAMERASPACEPOSITION - Set eye plane\n");
5477 glMatrixMode(GL_MODELVIEW);
5480 glTexGenfv(GL_S, GL_EYE_PLANE, s_plane);
5481 glTexGenfv(GL_T, GL_EYE_PLANE, t_plane);
5482 glTexGenfv(GL_R, GL_EYE_PLANE, r_plane);
5483 glTexGenfv(GL_Q, GL_EYE_PLANE, q_plane);
5486 TRACE("WINED3DTSS_TCI_CAMERASPACEPOSITION - Set GL_TEXTURE_GEN_x and GL_x, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR\n");
5487 glEnable(GL_TEXTURE_GEN_S);
5488 checkGLcall("glEnable(GL_TEXTURE_GEN_S);");
5489 glTexGeni(GL_S, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR);
5490 checkGLcall("glTexGeni(GL_S, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR)");
5491 glEnable(GL_TEXTURE_GEN_T);
5492 checkGLcall("glEnable(GL_TEXTURE_GEN_T);");
5493 glTexGeni(GL_T, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR);
5494 checkGLcall("glTexGeni(GL_T, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR)");
5495 glEnable(GL_TEXTURE_GEN_R);
5496 checkGLcall("glEnable(GL_TEXTURE_GEN_R);");
5497 glTexGeni(GL_R, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR);
5498 checkGLcall("glTexGeni(GL_R, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR)");
5502 case D3DTSS_TCI_CAMERASPACENORMAL:
5504 if (GL_SUPPORT(NV_TEXGEN_REFLECTION)) {
5505 float s_plane[] = { 1.0, 0.0, 0.0, 0.0 };
5506 float t_plane[] = { 0.0, 1.0, 0.0, 0.0 };
5507 float r_plane[] = { 0.0, 0.0, 1.0, 0.0 };
5508 float q_plane[] = { 0.0, 0.0, 0.0, 1.0 };
5509 TRACE("WINED3DTSS_TCI_CAMERASPACENORMAL - Set eye plane\n");
5511 glMatrixMode(GL_MODELVIEW);
5514 glTexGenfv(GL_S, GL_EYE_PLANE, s_plane);
5515 glTexGenfv(GL_T, GL_EYE_PLANE, t_plane);
5516 glTexGenfv(GL_R, GL_EYE_PLANE, r_plane);
5517 glTexGenfv(GL_Q, GL_EYE_PLANE, q_plane);
5520 glEnable(GL_TEXTURE_GEN_S);
5521 checkGLcall("glEnable(GL_TEXTURE_GEN_S);");
5522 glTexGeni(GL_S, GL_TEXTURE_GEN_MODE, GL_NORMAL_MAP_NV);
5523 checkGLcall("glTexGeni(GL_S, GL_TEXTURE_GEN_MODE, GL_NORMAL_MAP_NV)");
5524 glEnable(GL_TEXTURE_GEN_T);
5525 checkGLcall("glEnable(GL_TEXTURE_GEN_T);");
5526 glTexGeni(GL_T, GL_TEXTURE_GEN_MODE, GL_NORMAL_MAP_NV);
5527 checkGLcall("glTexGeni(GL_T, GL_TEXTURE_GEN_MODE, GL_NORMAL_MAP_NV)");
5528 glEnable(GL_TEXTURE_GEN_R);
5529 checkGLcall("glEnable(GL_TEXTURE_GEN_R);");
5530 glTexGeni(GL_R, GL_TEXTURE_GEN_MODE, GL_NORMAL_MAP_NV);
5531 checkGLcall("glTexGeni(GL_R, GL_TEXTURE_GEN_MODE, GL_NORMAL_MAP_NV)");
5536 case D3DTSS_TCI_CAMERASPACEREFLECTIONVECTOR:
5538 if (GL_SUPPORT(NV_TEXGEN_REFLECTION)) {
5539 float s_plane[] = { 1.0, 0.0, 0.0, 0.0 };
5540 float t_plane[] = { 0.0, 1.0, 0.0, 0.0 };
5541 float r_plane[] = { 0.0, 0.0, 1.0, 0.0 };
5542 float q_plane[] = { 0.0, 0.0, 0.0, 1.0 };
5543 TRACE("WINED3DTSS_TCI_CAMERASPACEREFLECTIONVECTOR - Set eye plane\n");
5545 glMatrixMode(GL_MODELVIEW);
5548 glTexGenfv(GL_S, GL_EYE_PLANE, s_plane);
5549 glTexGenfv(GL_T, GL_EYE_PLANE, t_plane);
5550 glTexGenfv(GL_R, GL_EYE_PLANE, r_plane);
5551 glTexGenfv(GL_Q, GL_EYE_PLANE, q_plane);
5554 glEnable(GL_TEXTURE_GEN_S);
5555 checkGLcall("glEnable(GL_TEXTURE_GEN_S);");
5556 glTexGeni(GL_S, GL_TEXTURE_GEN_MODE, GL_REFLECTION_MAP_NV);
5557 checkGLcall("glTexGeni(GL_S, GL_TEXTURE_GEN_MODE, GL_REFLECTION_MAP_NV)");
5558 glEnable(GL_TEXTURE_GEN_T);
5559 checkGLcall("glEnable(GL_TEXTURE_GEN_T);");
5560 glTexGeni(GL_T, GL_TEXTURE_GEN_MODE, GL_REFLECTION_MAP_NV);
5561 checkGLcall("glTexGeni(GL_T, GL_TEXTURE_GEN_MODE, GL_REFLECTION_MAP_NV)");
5562 glEnable(GL_TEXTURE_GEN_R);
5563 checkGLcall("glEnable(GL_TEXTURE_GEN_R);");
5564 glTexGeni(GL_R, GL_TEXTURE_GEN_MODE, GL_REFLECTION_MAP_NV);
5565 checkGLcall("glTexGeni(GL_R, GL_TEXTURE_GEN_MODE, GL_REFLECTION_MAP_NV)");
5570 /* Unhandled types: */
5573 /* ? disable GL_TEXTURE_GEN_n ? */
5574 glDisable(GL_TEXTURE_GEN_S);
5575 glDisable(GL_TEXTURE_GEN_T);
5576 glDisable(GL_TEXTURE_GEN_R);
5577 glDisable(GL_TEXTURE_GEN_Q);
5578 FIXME("Unhandled WINED3DTSS_TEXCOORDINDEX %lx\n", Value);
5585 case WINED3DTSS_TEXTURETRANSFORMFLAGS :
5586 set_texture_matrix((float *)&This->stateBlock->transforms[D3DTS_TEXTURE0 + Stage].u.m[0][0], Value, (This->stateBlock->textureState[Stage][WINED3DTSS_TEXCOORDINDEX] & 0xFFFF0000) != D3DTSS_TCI_PASSTHRU);
5589 case WINED3DTSS_BUMPENVMAT00 :
5590 case WINED3DTSS_BUMPENVMAT01 :
5591 TRACE("BUMPENVMAT0%u Stage=%ld, Type=%d, Value =%ld\n", Type - WINED3DTSS_BUMPENVMAT00, Stage, Type, Value);
5593 case WINED3DTSS_BUMPENVMAT10 :
5594 case WINED3DTSS_BUMPENVMAT11 :
5595 TRACE("BUMPENVMAT1%u Stage=%ld, Type=%d, Value =%ld\n", Type - WINED3DTSS_BUMPENVMAT10, Stage, Type, Value);
5598 case WINED3DTSS_BUMPENVLSCALE :
5599 TRACE("BUMPENVLSCALE Stage=%ld, Type=%d, Value =%ld\n", Stage, Type, Value);
5602 case WINED3DTSS_BUMPENVLOFFSET :
5603 TRACE("BUMPENVLOFFSET Stage=%ld, Type=%d, Value =%ld\n", Stage, Type, Value);
5606 case WINED3DTSS_RESULTARG :
5607 TRACE("RESULTARG Still a stub, Stage=%ld, Type=%d, Value =%ld\n", Stage, Type, Value);
5611 /* Put back later: FIXME("(%p) : stub, Stage=%ld, Type=%d, Value =%ld\n", This, Stage, Type, Value); */
5612 TRACE("Still a stub, Stage=%ld, Type=%d, Value =%ld\n", Stage, Type, Value);
5621 * Get / Set Texture Stage States
5622 * TODO: Verify against dx9 definitions
5624 static HRESULT WINAPI IWineD3DDeviceImpl_SetTextureStageState(IWineD3DDevice *iface, DWORD Stage, WINED3DTEXTURESTAGESTATETYPE Type, DWORD Value) {
5625 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5627 /* FIXME: Handle 3d textures? What if TSS value set before set texture? Need to reapply all values? */
5629 TRACE("(%p) : Stage=%ld, Type=%s(%d), Value=%ld\n", This, Stage, debug_d3dtexturestate(Type), Type, Value);
5631 /* Reject invalid texture units */
5632 if (Stage >= GL_LIMITS(texture_stages)) {
5633 TRACE("Attempt to access invalid texture rejected\n");
5634 return WINED3DERR_INVALIDCALL;
5637 This->updateStateBlock->changed.textureState[Stage][Type] = TRUE;
5638 This->updateStateBlock->set.textureState[Stage][Type] = TRUE;
5639 This->updateStateBlock->textureState[Stage][Type] = Value;
5644 static HRESULT WINAPI IWineD3DDeviceImpl_GetTextureStageState(IWineD3DDevice *iface, DWORD Stage, WINED3DTEXTURESTAGESTATETYPE Type, DWORD* pValue) {
5645 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5646 TRACE("(%p) : requesting Stage %ld, Type %d getting %ld\n", This, Stage, Type, This->updateStateBlock->textureState[Stage][Type]);
5647 *pValue = This->updateStateBlock->textureState[Stage][Type];
5654 static HRESULT WINAPI IWineD3DDeviceImpl_SetTexture(IWineD3DDevice *iface, DWORD Stage, IWineD3DBaseTexture* pTexture) {
5656 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5657 IWineD3DBaseTexture *oldTexture;
5659 oldTexture = This->updateStateBlock->textures[Stage];
5660 TRACE("(%p) : Stage(%ld), Texture (%p)\n", This, Stage, pTexture);
5662 #if 0 /* TODO: check so vertex textures */
5663 if (Stage >= D3DVERTEXTEXTURESAMPLER && Stage <= D3DVERTEXTEXTURESAMPLER3){
5664 This->updateStateBlock->vertexTextures[Stage - D3DVERTEXTEXTURESAMPLER] = pTexture;
5669 /* Reject invalid texture units */
5670 if (Stage >= GL_LIMITS(sampler_stages) || Stage < 0) {
5671 WARN("Attempt to access invalid texture rejected\n");
5672 return WINED3DERR_INVALIDCALL;
5675 if(pTexture != NULL) {
5676 /* SetTexture isn't allowed on textures in WINED3DPOOL_SCRATCH;
5678 if(((IWineD3DTextureImpl*)pTexture)->resource.pool == WINED3DPOOL_SCRATCH) {
5679 WARN("(%p) Attempt to set scratch texture rejected\n", pTexture);
5680 return WINED3DERR_INVALIDCALL;
5684 oldTexture = This->updateStateBlock->textures[Stage];
5685 TRACE("GL_LIMITS %d\n",GL_LIMITS(sampler_stages));
5686 TRACE("(%p) : oldtexture(%p)\n", This,oldTexture);
5688 This->updateStateBlock->set.textures[Stage] = TRUE;
5689 This->updateStateBlock->changed.textures[Stage] = TRUE;
5690 TRACE("(%p) : setting new texture to %p\n", This, pTexture);
5691 This->updateStateBlock->textures[Stage] = pTexture;
5693 /* Handle recording of state blocks */
5694 if (This->isRecordingState) {
5695 TRACE("Recording... not performing anything\n");
5699 /** NOTE: MSDN says that setTexture increases the reference count,
5700 * and the the application nust set the texture back to null (or have a leaky application),
5701 * This means we should pass the refcount up to the parent
5702 *******************************/
5703 if (NULL != This->updateStateBlock->textures[Stage]) {
5704 IWineD3DBaseTexture_AddRef(This->updateStateBlock->textures[Stage]);
5707 if (NULL != oldTexture) {
5708 IWineD3DBaseTexture_Release(oldTexture);
5711 /* Reset color keying */
5712 if(Stage == 0 && This->stateBlock->renderState[WINED3DRS_COLORKEYENABLE]) {
5713 BOOL enable_ckey = FALSE;
5716 IWineD3DSurfaceImpl *surf = (IWineD3DSurfaceImpl *) ((IWineD3DTextureImpl *)pTexture)->surfaces[0];
5717 if(surf->CKeyFlags & DDSD_CKSRCBLT) enable_ckey = TRUE;
5721 glAlphaFunc(GL_NOTEQUAL, 0.0);
5722 checkGLcall("glAlphaFunc");
5729 static HRESULT WINAPI IWineD3DDeviceImpl_GetTexture(IWineD3DDevice *iface, DWORD Stage, IWineD3DBaseTexture** ppTexture) {
5730 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5731 TRACE("(%p) : (%ld /* Stage */,%p /* ppTexture */)\n", This, Stage, ppTexture);
5733 /* Reject invalid texture units */
5734 if (Stage >= GL_LIMITS(sampler_stages)) {
5735 TRACE("Attempt to access invalid texture rejected\n");
5736 return WINED3DERR_INVALIDCALL;
5738 *ppTexture=This->updateStateBlock->textures[Stage];
5740 IWineD3DBaseTexture_AddRef(*ppTexture);
5742 return WINED3DERR_INVALIDCALL;
5749 static HRESULT WINAPI IWineD3DDeviceImpl_GetBackBuffer(IWineD3DDevice *iface, UINT iSwapChain, UINT BackBuffer, WINED3DBACKBUFFER_TYPE Type,
5750 IWineD3DSurface **ppBackBuffer) {
5751 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5752 IWineD3DSwapChain *swapChain;
5755 TRACE("(%p) : BackBuf %d Type %d SwapChain %d returning %p\n", This, BackBuffer, Type, iSwapChain, *ppBackBuffer);
5757 hr = IWineD3DDeviceImpl_GetSwapChain(iface, iSwapChain, &swapChain);
5758 if (hr == WINED3D_OK) {
5759 hr = IWineD3DSwapChain_GetBackBuffer(swapChain, BackBuffer, Type, ppBackBuffer);
5760 IWineD3DSwapChain_Release(swapChain);
5762 *ppBackBuffer = NULL;
5767 static HRESULT WINAPI IWineD3DDeviceImpl_GetDeviceCaps(IWineD3DDevice *iface, WINED3DCAPS* pCaps) {
5768 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5769 WARN("(%p) : stub, calling idirect3d for now\n", This);
5770 return IWineD3D_GetDeviceCaps(This->wineD3D, This->adapterNo, This->devType, pCaps);
5773 static HRESULT WINAPI IWineD3DDeviceImpl_GetDisplayMode(IWineD3DDevice *iface, UINT iSwapChain, WINED3DDISPLAYMODE* pMode) {
5774 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5775 IWineD3DSwapChain *swapChain;
5778 if(iSwapChain > 0) {
5779 hr = IWineD3DDeviceImpl_GetSwapChain(iface, iSwapChain, (IWineD3DSwapChain **)&swapChain);
5780 if (hr == WINED3D_OK) {
5781 hr = IWineD3DSwapChain_GetDisplayMode(swapChain, pMode);
5782 IWineD3DSwapChain_Release(swapChain);
5784 FIXME("(%p) Error getting display mode\n", This);
5787 /* Don't read the real display mode,
5788 but return the stored mode instead. X11 can't change the color
5789 depth, and some apps are pretty angry if they SetDisplayMode from
5790 24 to 16 bpp and find out that GetDisplayMode still returns 24 bpp
5792 Also don't relay to the swapchain because with ddraw it's possible
5793 that there isn't a swapchain at all */
5794 pMode->Width = This->ddraw_width;
5795 pMode->Height = This->ddraw_height;
5796 pMode->Format = This->ddraw_format;
5797 pMode->RefreshRate = 0;
5804 static HRESULT WINAPI IWineD3DDeviceImpl_SetHWND(IWineD3DDevice *iface, HWND hWnd) {
5805 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5806 TRACE("(%p)->(%p)\n", This, hWnd);
5808 This->ddraw_window = hWnd;
5812 static HRESULT WINAPI IWineD3DDeviceImpl_GetHWND(IWineD3DDevice *iface, HWND *hWnd) {
5813 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5814 TRACE("(%p)->(%p)\n", This, hWnd);
5816 *hWnd = This->ddraw_window;
5821 * Stateblock related functions
5824 static HRESULT WINAPI IWineD3DDeviceImpl_BeginStateBlock(IWineD3DDevice *iface) {
5825 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5826 IWineD3DStateBlockImpl *object;
5827 TRACE("(%p)", This);
5829 if (This->isRecordingState) {
5830 return WINED3DERR_INVALIDCALL;
5833 object = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(IWineD3DStateBlockImpl));
5834 if (NULL == object ) {
5835 FIXME("(%p)Error allocating memory for stateblock\n", This);
5836 return E_OUTOFMEMORY;
5838 TRACE("(%p) creted object %p\n", This, object);
5839 object->wineD3DDevice= This;
5840 /** FIXME: object->parent = parent; **/
5841 object->parent = NULL;
5842 object->blockType = WINED3DSBT_ALL;
5844 object->lpVtbl = &IWineD3DStateBlock_Vtbl;
5846 IWineD3DStateBlock_Release((IWineD3DStateBlock*)This->updateStateBlock);
5847 This->updateStateBlock = object;
5848 This->isRecordingState = TRUE;
5850 TRACE("(%p) recording stateblock %p\n",This , object);
5854 static HRESULT WINAPI IWineD3DDeviceImpl_EndStateBlock(IWineD3DDevice *iface, IWineD3DStateBlock** ppStateBlock) {
5855 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5857 if (!This->isRecordingState) {
5858 FIXME("(%p) not recording! returning error\n", This);
5859 *ppStateBlock = NULL;
5860 return WINED3DERR_INVALIDCALL;
5863 *ppStateBlock = (IWineD3DStateBlock*)This->updateStateBlock;
5864 This->isRecordingState = FALSE;
5865 This->updateStateBlock = This->stateBlock;
5866 IWineD3DStateBlock_AddRef((IWineD3DStateBlock*)This->updateStateBlock);
5867 /* IWineD3DStateBlock_AddRef(*ppStateBlock); don't need to do this, since we should really just release UpdateStateBlock first */
5868 TRACE("(%p) returning token (ptr to stateblock) of %p\n", This, *ppStateBlock);
5873 * Scene related functions
5875 static HRESULT WINAPI IWineD3DDeviceImpl_BeginScene(IWineD3DDevice *iface) {
5876 /* At the moment we have no need for any functionality at the beginning
5878 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5879 TRACE("(%p) : stub\n", This);
5883 static HRESULT WINAPI IWineD3DDeviceImpl_EndScene(IWineD3DDevice *iface) {
5884 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5885 TRACE("(%p)\n", This);
5887 /* We only have to do this if we need to read the, swapbuffers performs a flush for us */
5889 checkGLcall("glFlush");
5891 TRACE("End Scene\n");
5892 if(This->renderTarget != NULL) {
5894 /* If the container of the rendertarget is a texture then we need to save the data from the pbuffer */
5895 IUnknown *targetContainer = NULL;
5896 if (WINED3D_OK == IWineD3DSurface_GetContainer(This->renderTarget, &IID_IWineD3DBaseTexture, (void **)&targetContainer)
5897 || WINED3D_OK == IWineD3DSurface_GetContainer(This->renderTarget, &IID_IWineD3DDevice, (void **)&targetContainer)) {
5898 TRACE("(%p) : Texture rendertarget %p\n", This ,This->renderTarget);
5899 /** always dirtify for now. we must find a better way to see that surface have been modified
5900 (Modifications should will only occur via draw-primitive, but we do need better locking
5901 switching to render-to-texture should remove the overhead though.
5903 IWineD3DSurface_SetPBufferState(This->renderTarget, TRUE /* inPBuffer */, FALSE /* inTexture */);
5904 IWineD3DSurface_AddDirtyRect(This->renderTarget, NULL);
5905 IWineD3DSurface_PreLoad(This->renderTarget);
5906 IWineD3DSurface_SetPBufferState(This->renderTarget, FALSE /* inPBuffer */, FALSE /* inTexture */);
5907 IUnknown_Release(targetContainer);
5910 This->sceneEnded = TRUE;
5915 static HRESULT WINAPI IWineD3DDeviceImpl_Present(IWineD3DDevice *iface,
5916 CONST RECT* pSourceRect, CONST RECT* pDestRect,
5917 HWND hDestWindowOverride, CONST RGNDATA* pDirtyRegion) {
5918 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5919 IWineD3DSwapChain *swapChain = NULL;
5921 int swapchains = IWineD3DDeviceImpl_GetNumberOfSwapChains(iface);
5923 TRACE("(%p) Presenting the frame\n", This);
5925 for(i = 0 ; i < swapchains ; i ++) {
5927 IWineD3DDeviceImpl_GetSwapChain(iface, i , (IWineD3DSwapChain **)&swapChain);
5928 TRACE("presentinng chain %d, %p\n", i, swapChain);
5929 IWineD3DSwapChain_Present(swapChain, pSourceRect, pDestRect, hDestWindowOverride, pDirtyRegion, 0);
5930 IWineD3DSwapChain_Release(swapChain);
5936 static HRESULT WINAPI IWineD3DDeviceImpl_Clear(IWineD3DDevice *iface, DWORD Count, CONST D3DRECT* pRects,
5937 DWORD Flags, D3DCOLOR Color, float Z, DWORD Stencil) {
5938 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5940 /* TODO: From MSDN This method fails if you specify the D3DCLEAR_ZBUFFER or D3DCLEAR_STENCIL flags when the
5941 render target does not have an attached depth buffer. Similarly, if you specify the D3DCLEAR_STENCIL flag
5942 when the depth-buffer format does not contain stencil buffer information, this method fails. */
5943 GLbitfield glMask = 0;
5944 GLboolean old_ztest;
5945 GLfloat old_z_clear_value;
5946 GLint old_stencil_clear_value;
5947 GLfloat old_color_clear_value[4];
5949 CONST D3DRECT* curRect;
5951 TRACE("(%p) Count (%ld), pRects (%p), Flags (%lx), Z (%f), Stencil (%ld)\n", This,
5952 Count, pRects, Flags, Z, Stencil);
5956 glEnable(GL_SCISSOR_TEST);
5957 checkGLcall("glEnable GL_SCISSOR_TEST");
5959 if (Count > 0 && pRects) {
5965 /* Only set the values up once, as they are not changing */
5966 if (Flags & D3DCLEAR_STENCIL) {
5967 glGetIntegerv(GL_STENCIL_CLEAR_VALUE, &old_stencil_clear_value);
5968 glClearStencil(Stencil);
5969 checkGLcall("glClearStencil");
5970 glMask = glMask | GL_STENCIL_BUFFER_BIT;
5971 glStencilMask(0xFFFFFFFF);
5974 if (Flags & D3DCLEAR_ZBUFFER) {
5975 glGetBooleanv(GL_DEPTH_WRITEMASK, &old_ztest);
5976 glDepthMask(GL_TRUE);
5977 glGetFloatv(GL_DEPTH_CLEAR_VALUE, &old_z_clear_value);
5979 checkGLcall("glClearDepth");
5980 glMask = glMask | GL_DEPTH_BUFFER_BIT;
5983 if (Flags & D3DCLEAR_TARGET) {
5984 TRACE("Clearing screen with glClear to color %lx\n", Color);
5985 glGetFloatv(GL_COLOR_CLEAR_VALUE, old_color_clear_value);
5986 glClearColor(D3DCOLOR_R(Color),
5990 checkGLcall("glClearColor");
5992 /* Clear ALL colors! */
5993 glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
5994 glMask = glMask | GL_COLOR_BUFFER_BIT;
5997 /* Now process each rect in turn */
5998 for (i = 0; i < Count || i == 0; i++) {
6001 /* Note gl uses lower left, width/height */
6002 TRACE("(%p) %p Rect=(%ld,%ld)->(%ld,%ld) glRect=(%ld,%ld), len=%ld, hei=%ld\n", This, curRect,
6003 curRect->x1, curRect->y1, curRect->x2, curRect->y2,
6004 curRect->x1, (((IWineD3DSurfaceImpl *)This->renderTarget)->currentDesc.Height - curRect->y2),
6005 curRect->x2 - curRect->x1, curRect->y2 - curRect->y1);
6006 glScissor(curRect->x1, (((IWineD3DSurfaceImpl *)This->renderTarget)->currentDesc.Height - curRect->y2),
6007 curRect->x2 - curRect->x1, curRect->y2 - curRect->y1);
6008 checkGLcall("glScissor");
6010 glScissor(This->stateBlock->viewport.X,
6011 (((IWineD3DSurfaceImpl *)This->renderTarget)->currentDesc.Height -
6012 (This->stateBlock->viewport.Y + This->stateBlock->viewport.Height)),
6013 This->stateBlock->viewport.Width,
6014 This->stateBlock->viewport.Height);
6015 checkGLcall("glScissor");
6018 /* Clear the selected rectangle (or full screen) */
6020 checkGLcall("glClear");
6022 /* Step to the next rectangle */
6023 if (curRect) curRect = curRect + sizeof(D3DRECT);
6026 /* Restore the old values (why..?) */
6027 if (Flags & D3DCLEAR_STENCIL) {
6028 glClearStencil(old_stencil_clear_value);
6029 glStencilMask(This->stateBlock->renderState[WINED3DRS_STENCILWRITEMASK]);
6031 if (Flags & D3DCLEAR_ZBUFFER) {
6032 glDepthMask(old_ztest);
6033 glClearDepth(old_z_clear_value);
6035 if (Flags & D3DCLEAR_TARGET) {
6036 glClearColor(old_color_clear_value[0],
6037 old_color_clear_value[1],
6038 old_color_clear_value[2],
6039 old_color_clear_value[3]);
6040 glColorMask(This->stateBlock->renderState[WINED3DRS_COLORWRITEENABLE] & D3DCOLORWRITEENABLE_RED ? GL_TRUE : GL_FALSE,
6041 This->stateBlock->renderState[WINED3DRS_COLORWRITEENABLE] & D3DCOLORWRITEENABLE_GREEN ? GL_TRUE : GL_FALSE,
6042 This->stateBlock->renderState[WINED3DRS_COLORWRITEENABLE] & D3DCOLORWRITEENABLE_BLUE ? GL_TRUE : GL_FALSE,
6043 This->stateBlock->renderState[WINED3DRS_COLORWRITEENABLE] & D3DCOLORWRITEENABLE_ALPHA ? GL_TRUE : GL_FALSE);
6046 glDisable(GL_SCISSOR_TEST);
6047 checkGLcall("glDisable");
6056 static HRESULT WINAPI IWineD3DDeviceImpl_DrawPrimitive(IWineD3DDevice *iface, D3DPRIMITIVETYPE PrimitiveType, UINT StartVertex,
6057 UINT PrimitiveCount) {
6059 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
6060 This->stateBlock->streamIsUP = FALSE;
6062 TRACE("(%p) : Type=(%d,%s), Start=%d, Count=%d\n", This, PrimitiveType,
6063 debug_d3dprimitivetype(PrimitiveType),
6064 StartVertex, PrimitiveCount);
6065 drawPrimitive(iface, PrimitiveType, PrimitiveCount, StartVertex, 0/* NumVertices */, -1 /* indxStart */,
6066 0 /* indxSize */, NULL /* indxData */, 0 /* minIndex */, NULL);
6072 /* TODO: baseVIndex needs to be provided from This->stateBlock->baseVertexIndex when called from d3d8 */
6073 static HRESULT WINAPI IWineD3DDeviceImpl_DrawIndexedPrimitive(IWineD3DDevice *iface,
6074 D3DPRIMITIVETYPE PrimitiveType,
6075 INT baseVIndex, UINT minIndex,
6076 UINT NumVertices, UINT startIndex, UINT primCount) {
6078 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
6080 IWineD3DIndexBuffer *pIB;
6081 WINED3DINDEXBUFFER_DESC IdxBufDsc;
6083 pIB = This->stateBlock->pIndexData;
6084 This->stateBlock->streamIsUP = FALSE;
6086 TRACE("(%p) : Type=(%d,%s), min=%d, CountV=%d, startIdx=%d, baseVidx=%d, countP=%d\n", This,
6087 PrimitiveType, debug_d3dprimitivetype(PrimitiveType),
6088 minIndex, NumVertices, startIndex, baseVIndex, primCount);
6090 IWineD3DIndexBuffer_GetDesc(pIB, &IdxBufDsc);
6091 if (IdxBufDsc.Format == WINED3DFMT_INDEX16) {
6097 drawPrimitive(iface, PrimitiveType, primCount, baseVIndex, NumVertices, startIndex,
6098 idxStride, ((IWineD3DIndexBufferImpl *) pIB)->resource.allocatedMemory, minIndex, NULL);
6103 static HRESULT WINAPI IWineD3DDeviceImpl_DrawPrimitiveUP(IWineD3DDevice *iface, D3DPRIMITIVETYPE PrimitiveType,
6104 UINT PrimitiveCount, CONST void* pVertexStreamZeroData,
6105 UINT VertexStreamZeroStride) {
6106 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
6108 TRACE("(%p) : Type=(%d,%s), pCount=%d, pVtxData=%p, Stride=%d\n", This, PrimitiveType,
6109 debug_d3dprimitivetype(PrimitiveType),
6110 PrimitiveCount, pVertexStreamZeroData, VertexStreamZeroStride);
6112 /* release the stream source */
6113 if (This->stateBlock->streamSource[0] != NULL) {
6114 IWineD3DVertexBuffer_Release(This->stateBlock->streamSource[0]);
6117 /* Note in the following, it's not this type, but that's the purpose of streamIsUP */
6118 This->stateBlock->streamSource[0] = (IWineD3DVertexBuffer *)pVertexStreamZeroData;
6119 This->stateBlock->streamStride[0] = VertexStreamZeroStride;
6120 This->stateBlock->streamIsUP = TRUE;
6122 drawPrimitive(iface, PrimitiveType, PrimitiveCount, 0 /* start vertex */, 0 /* NumVertices */,
6123 0 /* indxStart*/, 0 /* indxSize*/, NULL /* indxData */, 0 /* indxMin */, NULL);
6125 /* MSDN specifies stream zero settings must be set to NULL */
6126 This->stateBlock->streamStride[0] = 0;
6127 This->stateBlock->streamSource[0] = NULL;
6129 /*stream zero settings set to null at end, as per the msdn */
6133 static HRESULT WINAPI IWineD3DDeviceImpl_DrawIndexedPrimitiveUP(IWineD3DDevice *iface, D3DPRIMITIVETYPE PrimitiveType,
6134 UINT MinVertexIndex, UINT NumVertices,
6135 UINT PrimitiveCount, CONST void* pIndexData,
6136 WINED3DFORMAT IndexDataFormat,CONST void* pVertexStreamZeroData,
6137 UINT VertexStreamZeroStride) {
6139 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
6141 TRACE("(%p) : Type=(%d,%s), MinVtxIdx=%d, NumVIdx=%d, PCount=%d, pidxdata=%p, IdxFmt=%d, pVtxdata=%p, stride=%d\n",
6142 This, PrimitiveType, debug_d3dprimitivetype(PrimitiveType),
6143 MinVertexIndex, NumVertices, PrimitiveCount, pIndexData,
6144 IndexDataFormat, pVertexStreamZeroData, VertexStreamZeroStride);
6146 if (IndexDataFormat == WINED3DFMT_INDEX16) {
6152 /* release the stream and index data */
6153 if (This->stateBlock->streamSource[0] != NULL) {
6154 IWineD3DVertexBuffer_Release(This->stateBlock->streamSource[0]);
6156 if (This->stateBlock->pIndexData) {
6157 IWineD3DIndexBuffer_Release(This->stateBlock->pIndexData);
6160 /* Note in the following, it's not this type, but that's the purpose of streamIsUP */
6161 This->stateBlock->streamSource[0] = (IWineD3DVertexBuffer *)pVertexStreamZeroData;
6162 This->stateBlock->streamIsUP = TRUE;
6163 This->stateBlock->streamStride[0] = VertexStreamZeroStride;
6165 drawPrimitive(iface, PrimitiveType, PrimitiveCount, 0 /* vertexStart */, NumVertices, 0 /* indxStart */, idxStride, pIndexData, MinVertexIndex, NULL);
6167 /* MSDN specifies stream zero settings and index buffer must be set to NULL */
6168 This->stateBlock->streamSource[0] = NULL;
6169 This->stateBlock->streamStride[0] = 0;
6170 This->stateBlock->pIndexData = NULL;
6175 static HRESULT WINAPI IWineD3DDeviceImpl_DrawPrimitiveStrided (IWineD3DDevice *iface, D3DPRIMITIVETYPE PrimitiveType, UINT PrimitiveCount, WineDirect3DVertexStridedData *DrawPrimStrideData) {
6177 drawPrimitive(iface, PrimitiveType, PrimitiveCount, 0, 0, 0, 0, NULL, 0, DrawPrimStrideData);
6180 /* Yet another way to update a texture, some apps use this to load default textures instead of using surface/texture lock/unlock */
6181 static HRESULT WINAPI IWineD3DDeviceImpl_UpdateTexture (IWineD3DDevice *iface, IWineD3DBaseTexture *pSourceTexture, IWineD3DBaseTexture *pDestinationTexture){
6182 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
6183 HRESULT hr = WINED3D_OK;
6184 WINED3DRESOURCETYPE sourceType;
6185 WINED3DRESOURCETYPE destinationType;
6188 /* TODO: think about moving the code into IWineD3DBaseTexture */
6190 TRACE("(%p) Source %p Destination %p\n", This, pSourceTexture, pDestinationTexture);
6192 /* verify that the source and destination textures aren't NULL */
6193 if (NULL == pSourceTexture || NULL == pDestinationTexture) {
6194 WARN("(%p) : source (%p) and destination (%p) textures must not be NULL, returning WINED3DERR_INVALIDCALL\n",
6195 This, pSourceTexture, pDestinationTexture);
6196 hr = WINED3DERR_INVALIDCALL;
6199 if (pSourceTexture == pDestinationTexture) {
6200 WARN("(%p) : source (%p) and destination (%p) textures must be different, returning WINED3DERR_INVALIDCALL\n",
6201 This, pSourceTexture, pDestinationTexture);
6202 hr = WINED3DERR_INVALIDCALL;
6204 /* Verify that the source and destination textures are the same type */
6205 sourceType = IWineD3DBaseTexture_GetType(pSourceTexture);
6206 destinationType = IWineD3DBaseTexture_GetType(pDestinationTexture);
6208 if (sourceType != destinationType) {
6209 WARN("(%p) Sorce and destination types must match, returning WINED3DERR_INVALIDCALL\n",
6211 hr = WINED3DERR_INVALIDCALL;
6214 /* check that both textures have the identical numbers of levels */
6215 if (IWineD3DBaseTexture_GetLevelCount(pDestinationTexture) != IWineD3DBaseTexture_GetLevelCount(pSourceTexture)) {
6216 WARN("(%p) : source (%p) and destination (%p) textures must have identicle numbers of levels, returning WINED3DERR_INVALIDCALL\n", This, pSourceTexture, pDestinationTexture);
6217 hr = WINED3DERR_INVALIDCALL;
6220 if (WINED3D_OK == hr) {
6222 /* Make sure that the destination texture is loaded */
6223 IWineD3DBaseTexture_PreLoad(pDestinationTexture);
6225 /* Update every surface level of the texture */
6226 levels = IWineD3DBaseTexture_GetLevelCount(pDestinationTexture);
6228 switch (sourceType) {
6229 case WINED3DRTYPE_TEXTURE:
6231 IWineD3DSurface *srcSurface;
6232 IWineD3DSurface *destSurface;
6234 for (i = 0 ; i < levels ; ++i) {
6235 IWineD3DTexture_GetSurfaceLevel((IWineD3DTexture *)pSourceTexture, i, &srcSurface);
6236 IWineD3DTexture_GetSurfaceLevel((IWineD3DTexture *)pDestinationTexture, i, &destSurface);
6237 hr = IWineD3DDevice_UpdateSurface(iface, srcSurface, NULL, destSurface, NULL);
6238 IWineD3DSurface_Release(srcSurface);
6239 IWineD3DSurface_Release(destSurface);
6240 if (WINED3D_OK != hr) {
6241 WARN("(%p) : Call to update surface failed\n", This);
6247 case WINED3DRTYPE_CUBETEXTURE:
6249 IWineD3DSurface *srcSurface;
6250 IWineD3DSurface *destSurface;
6251 WINED3DCUBEMAP_FACES faceType;
6253 for (i = 0 ; i < levels ; ++i) {
6254 /* Update each cube face */
6255 for (faceType = D3DCUBEMAP_FACE_POSITIVE_X; faceType <= D3DCUBEMAP_FACE_NEGATIVE_Z; ++faceType){
6256 hr = IWineD3DCubeTexture_GetCubeMapSurface((IWineD3DCubeTexture *)pSourceTexture, faceType, i, &srcSurface);
6257 if (WINED3D_OK != hr) {
6258 FIXME("(%p) : Failed to get src cube surface facetype %d, level %d\n", This, faceType, i);
6260 TRACE("Got srcSurface %p\n", srcSurface);
6262 hr = IWineD3DCubeTexture_GetCubeMapSurface((IWineD3DCubeTexture *)pDestinationTexture, faceType, i, &destSurface);
6263 if (WINED3D_OK != hr) {
6264 FIXME("(%p) : Failed to get src cube surface facetype %d, level %d\n", This, faceType, i);
6266 TRACE("Got desrSurface %p\n", destSurface);
6268 hr = IWineD3DDevice_UpdateSurface(iface, srcSurface, NULL, destSurface, NULL);
6269 IWineD3DSurface_Release(srcSurface);
6270 IWineD3DSurface_Release(destSurface);
6271 if (WINED3D_OK != hr) {
6272 WARN("(%p) : Call to update surface failed\n", This);
6279 #if 0 /* TODO: Add support for volume textures */
6280 case WINED3DRTYPE_VOLUMETEXTURE:
6282 IWineD3DVolume srcVolume = NULL;
6283 IWineD3DSurface destVolume = NULL;
6285 for (i = 0 ; i < levels ; ++i) {
6286 IWineD3DVolumeTexture_GetVolume((IWineD3DVolumeTexture *)pSourceTexture, i, &srcVolume);
6287 IWineD3DVolumeTexture_GetVolume((IWineD3DVolumeTexture *)pDestinationTexture, i, &destVolume);
6288 hr = IWineD3DFoo_UpdateVolume(iface, srcVolume, NULL, destVolume, NULL);
6289 IWineD3DVolume_Release(srcSurface);
6290 IWineD3DVolume_Release(destSurface);
6291 if (WINED3D_OK != hr) {
6292 WARN("(%p) : Call to update volume failed\n", This);
6300 FIXME("(%p) : Unsupported source and destination type\n", This);
6301 hr = WINED3DERR_INVALIDCALL;
6308 static HRESULT WINAPI IWineD3DDeviceImpl_StretchRect(IWineD3DDevice *iface, IWineD3DSurface *pSourceSurface,
6309 CONST RECT* pSourceRect, IWineD3DSurface *pDestinationSurface,
6310 CONST RECT* pDestRect, WINED3DTEXTUREFILTERTYPE Filter) {
6311 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
6313 TRACE("(%p) : stub\n", This);
6316 static HRESULT WINAPI IWineD3DDeviceImpl_GetRenderTargetData(IWineD3DDevice *iface, IWineD3DSurface *pRenderTarget, IWineD3DSurface *pSurface) {
6317 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
6318 /** TODO: remove remove casts to IWineD3DSurfaceImpl *
6319 * NOTE It may be best to move the code into surface to occomplish this
6320 ****************************************/
6322 WINED3DSURFACE_DESC surfaceDesc;
6323 unsigned int surfaceWidth, surfaceHeight;
6324 glDescriptor *targetGlDescription = NULL;
6325 glDescriptor *surfaceGlDescription = NULL;
6326 IWineD3DSwapChainImpl *container = NULL;
6328 IWineD3DSurface_GetGlDesc(pRenderTarget, &targetGlDescription);
6329 IWineD3DSurface_GetGlDesc(pSurface, &surfaceGlDescription);
6330 memset(&surfaceDesc, 0, sizeof(surfaceDesc));
6332 surfaceDesc.Width = &surfaceWidth;
6333 surfaceDesc.Height = &surfaceHeight;
6334 IWineD3DSurface_GetDesc(pSurface, &surfaceDesc);
6335 /* check to see if it's the backbuffer or the frontbuffer being requested (to make sure the data is up to date)*/
6337 /* Ok, I may need to setup some kind of active swapchain reference on the device */
6338 IWineD3DSurface_GetContainer(pRenderTarget, &IID_IWineD3DSwapChain, (void **)&container);
6340 /* TODO: opengl Context switching for swapchains etc... */
6341 if (NULL != container || pRenderTarget == This->renderTarget || pRenderTarget == This->depthStencilBuffer) {
6342 if (NULL != container && (pRenderTarget == container->backBuffer[0])) {
6343 glReadBuffer(GL_BACK);
6344 vcheckGLcall("glReadBuffer(GL_BACK)");
6345 } else if ((NULL != container && (pRenderTarget == container->frontBuffer)) || (pRenderTarget == This->renderTarget)) {
6346 glReadBuffer(GL_FRONT);
6347 vcheckGLcall("glReadBuffer(GL_FRONT)");
6348 } else if (pRenderTarget == This->depthStencilBuffer) {
6349 FIXME("Reading of depthstencil not yet supported\n");
6352 glReadPixels(surfaceGlDescription->target,
6353 surfaceGlDescription->level,
6356 surfaceGlDescription->glFormat,
6357 surfaceGlDescription->glType,
6358 (void *)IWineD3DSurface_GetData(pSurface));
6359 vcheckGLcall("glReadPixels(...)");
6360 if(NULL != container ){
6361 IWineD3DSwapChain_Release((IWineD3DSwapChain*) container);
6364 IWineD3DBaseTexture *container;
6365 GLenum textureDimensions = GL_TEXTURE_2D;
6367 if (WINED3D_OK == IWineD3DSurface_GetContainer(pSurface, &IID_IWineD3DBaseTexture, (void **)&container)) {
6368 textureDimensions = IWineD3DBaseTexture_GetTextureDimensions(container);
6369 IWineD3DBaseTexture_Release(container);
6371 /* TODO: 2D -> Cube surface coppies etc.. */
6372 if (surfaceGlDescription->target != textureDimensions) {
6373 FIXME("(%p) : Texture dimension mismatch\n", This);
6375 glEnable(textureDimensions);
6376 vcheckGLcall("glEnable(GL_TEXTURE_...)");
6377 /* FIXME: this isn't correct, it need to add a dirty rect if nothing else... */
6378 glBindTexture(targetGlDescription->target, targetGlDescription->textureName);
6379 vcheckGLcall("glBindTexture");
6380 glGetTexImage(surfaceGlDescription->target,
6381 surfaceGlDescription->level,
6382 surfaceGlDescription->glFormat,
6383 surfaceGlDescription->glType,
6384 (void *)IWineD3DSurface_GetData(pSurface));
6385 glDisable(textureDimensions);
6386 vcheckGLcall("glDisable(GL_TEXTURE_...)");
6393 static HRESULT WINAPI IWineD3DDeviceImpl_GetFrontBufferData(IWineD3DDevice *iface,UINT iSwapChain, IWineD3DSurface *pDestSurface) {
6394 IWineD3DSwapChain *swapChain;
6396 hr = IWineD3DDeviceImpl_GetSwapChain(iface, iSwapChain, (IWineD3DSwapChain **)&swapChain);
6397 if(hr == WINED3D_OK) {
6398 hr = IWineD3DSwapChain_GetFrontBufferData(swapChain, pDestSurface);
6399 IWineD3DSwapChain_Release(swapChain);
6404 static HRESULT WINAPI IWineD3DDeviceImpl_ValidateDevice(IWineD3DDevice *iface, DWORD* pNumPasses) {
6405 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
6406 /* return a sensible default */
6408 /* TODO: If the window is minimized then validate device should return something other than WINED3D_OK */
6409 FIXME("(%p) : stub\n", This);
6413 static HRESULT WINAPI IWineD3DDeviceImpl_SetPaletteEntries(IWineD3DDevice *iface, UINT PaletteNumber, CONST PALETTEENTRY* pEntries) {
6414 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
6416 TRACE("(%p) : PaletteNumber %u\n", This, PaletteNumber);
6417 if ( PaletteNumber < 0 || PaletteNumber >= MAX_PALETTES) {
6418 WARN("(%p) : (%u) Out of range 0-%u, returning Invalid Call\n", This, PaletteNumber, MAX_PALETTES);
6419 return WINED3DERR_INVALIDCALL;
6421 for (j = 0; j < 256; ++j) {
6422 This->palettes[PaletteNumber][j].peRed = pEntries[j].peRed;
6423 This->palettes[PaletteNumber][j].peGreen = pEntries[j].peGreen;
6424 This->palettes[PaletteNumber][j].peBlue = pEntries[j].peBlue;
6425 This->palettes[PaletteNumber][j].peFlags = pEntries[j].peFlags;
6427 TRACE("(%p) : returning\n", This);
6431 static HRESULT WINAPI IWineD3DDeviceImpl_GetPaletteEntries(IWineD3DDevice *iface, UINT PaletteNumber, PALETTEENTRY* pEntries) {
6432 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
6434 TRACE("(%p) : PaletteNumber %u\n", This, PaletteNumber);
6435 if ( PaletteNumber < 0 || PaletteNumber >= MAX_PALETTES) {
6436 WARN("(%p) : (%u) Out of range 0-%u, returning Invalid Call\n", This, PaletteNumber, MAX_PALETTES);
6437 return WINED3DERR_INVALIDCALL;
6439 for (j = 0; j < 256; ++j) {
6440 pEntries[j].peRed = This->palettes[PaletteNumber][j].peRed;
6441 pEntries[j].peGreen = This->palettes[PaletteNumber][j].peGreen;
6442 pEntries[j].peBlue = This->palettes[PaletteNumber][j].peBlue;
6443 pEntries[j].peFlags = This->palettes[PaletteNumber][j].peFlags;
6445 TRACE("(%p) : returning\n", This);
6449 static HRESULT WINAPI IWineD3DDeviceImpl_SetCurrentTexturePalette(IWineD3DDevice *iface, UINT PaletteNumber) {
6450 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
6451 TRACE("(%p) : PaletteNumber %u\n", This, PaletteNumber);
6452 if ( PaletteNumber < 0 || PaletteNumber >= MAX_PALETTES) {
6453 WARN("(%p) : (%u) Out of range 0-%u, returning Invalid Call\n", This, PaletteNumber, MAX_PALETTES);
6454 return WINED3DERR_INVALIDCALL;
6456 /*TODO: stateblocks */
6457 This->currentPalette = PaletteNumber;
6458 TRACE("(%p) : returning\n", This);
6462 static HRESULT WINAPI IWineD3DDeviceImpl_GetCurrentTexturePalette(IWineD3DDevice *iface, UINT* PaletteNumber) {
6463 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
6464 if (PaletteNumber == NULL) {
6465 WARN("(%p) : returning Invalid Call\n", This);
6466 return WINED3DERR_INVALIDCALL;
6468 /*TODO: stateblocks */
6469 *PaletteNumber = This->currentPalette;
6470 TRACE("(%p) : returning %u\n", This, *PaletteNumber);
6474 static HRESULT WINAPI IWineD3DDeviceImpl_SetSoftwareVertexProcessing(IWineD3DDevice *iface, BOOL bSoftware) {
6475 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
6476 static BOOL showFixmes = TRUE;
6478 FIXME("(%p) : stub\n", This);
6482 This->softwareVertexProcessing = bSoftware;
6487 static BOOL WINAPI IWineD3DDeviceImpl_GetSoftwareVertexProcessing(IWineD3DDevice *iface) {
6488 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
6489 static BOOL showFixmes = TRUE;
6491 FIXME("(%p) : stub\n", This);
6494 return This->softwareVertexProcessing;
6498 static HRESULT WINAPI IWineD3DDeviceImpl_GetRasterStatus(IWineD3DDevice *iface, UINT iSwapChain, WINED3DRASTER_STATUS* pRasterStatus) {
6499 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
6500 IWineD3DSwapChain *swapChain;
6503 TRACE("(%p) : SwapChain %d returning %p\n", This, iSwapChain, pRasterStatus);
6505 hr = IWineD3DDeviceImpl_GetSwapChain(iface, iSwapChain, (IWineD3DSwapChain **)&swapChain);
6506 if(hr == WINED3D_OK){
6507 hr = IWineD3DSwapChain_GetRasterStatus(swapChain, pRasterStatus);
6508 IWineD3DSwapChain_Release(swapChain);
6510 FIXME("(%p) IWineD3DSwapChain_GetRasterStatus returned in error\n", This);
6516 static HRESULT WINAPI IWineD3DDeviceImpl_SetNPatchMode(IWineD3DDevice *iface, float nSegments) {
6517 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
6518 static BOOL showfixmes = TRUE;
6519 if(nSegments != 0.0f) {
6521 FIXME("(%p) : stub nSegments(%f)\n", This, nSegments);
6528 static float WINAPI IWineD3DDeviceImpl_GetNPatchMode(IWineD3DDevice *iface) {
6529 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
6530 static BOOL showfixmes = TRUE;
6532 FIXME("(%p) : stub returning(%f)\n", This, 0.0f);
6538 static HRESULT WINAPI IWineD3DDeviceImpl_UpdateSurface(IWineD3DDevice *iface, IWineD3DSurface *pSourceSurface, CONST RECT* pSourceRect, IWineD3DSurface *pDestinationSurface, CONST POINT* pDestPoint) {
6539 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *) iface;
6540 /** TODO: remove casts to IWineD3DSurfaceImpl
6541 * NOTE: move code to surface to accomplish this
6542 ****************************************/
6543 IWineD3DSurfaceImpl *pSrcSurface = (IWineD3DSurfaceImpl *)pSourceSurface;
6544 int srcWidth, srcHeight;
6545 unsigned int srcSurfaceWidth, srcSurfaceHeight, destSurfaceWidth, destSurfaceHeight;
6546 WINED3DFORMAT destFormat, srcFormat;
6548 int destLeft, destTop;
6549 WINED3DPOOL srcPool, destPool;
6551 int rowoffset = 0; /* how many bytes to add onto the end of a row to wraparound to the beginning of the next */
6552 glDescriptor *glDescription = NULL;
6553 GLenum textureDimensions = GL_TEXTURE_2D;
6554 IWineD3DBaseTexture *baseTexture;
6556 WINED3DSURFACE_DESC winedesc;
6558 TRACE("(%p) : Source (%p) Rect (%p) Destination (%p) Point(%p)\n", This, pSourceSurface, pSourceRect, pDestinationSurface, pDestPoint);
6559 memset(&winedesc, 0, sizeof(winedesc));
6560 winedesc.Width = &srcSurfaceWidth;
6561 winedesc.Height = &srcSurfaceHeight;
6562 winedesc.Pool = &srcPool;
6563 winedesc.Format = &srcFormat;
6565 IWineD3DSurface_GetDesc(pSourceSurface, &winedesc);
6567 winedesc.Width = &destSurfaceWidth;
6568 winedesc.Height = &destSurfaceHeight;
6569 winedesc.Pool = &destPool;
6570 winedesc.Format = &destFormat;
6571 winedesc.Size = &destSize;
6573 IWineD3DSurface_GetDesc(pDestinationSurface, &winedesc);
6575 if(srcPool != WINED3DPOOL_SYSTEMMEM || destPool != WINED3DPOOL_DEFAULT){
6576 WARN("source %p must be SYSTEMMEM and dest %p must be DEFAULT, returning WINED3DERR_INVALIDCALL\n", pSourceSurface, pDestinationSurface);
6577 return WINED3DERR_INVALIDCALL;
6580 if (destFormat == WINED3DFMT_UNKNOWN) {
6581 TRACE("(%p) : Converting destination surface from WINED3DFMT_UNKNOWN to the source format\n", This);
6582 IWineD3DSurface_SetFormat(pDestinationSurface, srcFormat);
6584 /* Get the update surface description */
6585 IWineD3DSurface_GetDesc(pDestinationSurface, &winedesc);
6588 /* Make sure the surface is loaded and up to date */
6589 IWineD3DSurface_PreLoad(pDestinationSurface);
6591 IWineD3DSurface_GetGlDesc(pDestinationSurface, &glDescription);
6595 /* this needs to be done in lines if the sourceRect != the sourceWidth */
6596 srcWidth = pSourceRect ? pSourceRect->right - pSourceRect->left : srcSurfaceWidth;
6597 srcHeight = pSourceRect ? pSourceRect->top - pSourceRect->bottom : srcSurfaceHeight;
6598 destLeft = pDestPoint ? pDestPoint->x : 0;
6599 destTop = pDestPoint ? pDestPoint->y : 0;
6602 /* This function doesn't support compressed textures
6603 the pitch is just bytesPerPixel * width */
6604 if(srcWidth != srcSurfaceWidth || (pSourceRect != NULL && pSourceRect->left != 0) ){
6605 rowoffset = (srcSurfaceWidth - srcWidth) * pSrcSurface->bytesPerPixel;
6606 offset += pSourceRect->left * pSrcSurface->bytesPerPixel;
6607 /* TODO: do we ever get 3bpp?, would a shift and an add be quicker than a mul (well maybe a cycle or two) */
6609 /* TODO DXT formats */
6611 if(pSourceRect != NULL && pSourceRect->top != 0){
6612 offset += pSourceRect->top * srcWidth * pSrcSurface->bytesPerPixel;
6614 TRACE("(%p) glTexSubImage2D, Level %d, left %d, top %d, width %d, height %d , ftm %d, type %d, memory %p\n"
6616 ,glDescription->level
6621 ,glDescription->glFormat
6622 ,glDescription->glType
6623 ,IWineD3DSurface_GetData(pSourceSurface)
6627 if (IWineD3DSurface_GetData(pSourceSurface) == NULL) {
6629 /* need to lock the surface to get the data */
6630 FIXME("Surfaces has no allocated memory, but should be an in memory only surface\n");
6633 /* TODO: Cube and volume support */
6635 /* not a whole row so we have to do it a line at a time */
6638 /* hopefully using pointer addtion will be quicker than using a point + j * rowoffset */
6639 unsigned char* data =((unsigned char *)IWineD3DSurface_GetData(pSourceSurface)) + offset;
6641 for(j = destTop ; j < (srcHeight + destTop) ; j++){
6643 glTexSubImage2D(glDescription->target
6644 ,glDescription->level
6649 ,glDescription->glFormat
6650 ,glDescription->glType
6651 ,data /* could be quicker using */
6656 } else { /* Full width, so just write out the whole texture */
6658 if (WINED3DFMT_DXT1 == destFormat ||
6659 WINED3DFMT_DXT2 == destFormat ||
6660 WINED3DFMT_DXT3 == destFormat ||
6661 WINED3DFMT_DXT4 == destFormat ||
6662 WINED3DFMT_DXT5 == destFormat) {
6663 if (GL_SUPPORT(EXT_TEXTURE_COMPRESSION_S3TC)) {
6664 if (destSurfaceHeight != srcHeight || destSurfaceWidth != srcWidth) {
6665 /* FIXME: The easy way to do this is lock the destination, and copy the bits accross */
6666 FIXME("Updating part of a compressed texture is not supported at the moment\n");
6667 } if (destFormat != srcFormat) {
6668 FIXME("Updating mixed format compressed texture is not curretly support\n");
6670 GL_EXTCALL(glCompressedTexImage2DARB)(glDescription->target,
6671 glDescription->level,
6672 glDescription->glFormatInternal,
6677 IWineD3DSurface_GetData(pSourceSurface));
6680 FIXME("Attempting to update a DXT compressed texture without hardware support\n");
6685 if (NP2_REPACK == wined3d_settings.nonpower2_mode) {
6687 /* some applications cannot handle odd pitches returned by soft non-power2, so we have
6688 to repack the data from pow2Width/Height to expected Width,Height, this makes the
6689 data returned by GetData non-power2 width/height with hardware non-power2
6690 pow2Width/height are set to surface width height, repacking isn't needed so it
6691 doesn't matter which function gets called. */
6692 glTexSubImage2D(glDescription->target
6693 ,glDescription->level
6698 ,glDescription->glFormat
6699 ,glDescription->glType
6700 ,IWineD3DSurface_GetData(pSourceSurface)
6704 /* not repacked, the data returned by IWineD3DSurface_GetData is pow2Width x pow2Height */
6705 glTexSubImage2D(glDescription->target
6706 ,glDescription->level
6709 ,((IWineD3DSurfaceImpl *)pSourceSurface)->pow2Width
6710 ,((IWineD3DSurfaceImpl *)pSourceSurface)->pow2Height
6711 ,glDescription->glFormat
6712 ,glDescription->glType
6713 ,IWineD3DSurface_GetData(pSourceSurface)
6719 checkGLcall("glTexSubImage2D");
6721 /* I only need to look up baseTexture here, so it may be a good idea to hava a GL_TARGET ->
6722 * GL_DIMENSIONS lookup, or maybe store the dimensions on the surface (but that's making the
6723 * surface bigger than it needs to be hmm.. */
6724 if (WINED3D_OK == IWineD3DSurface_GetContainer(pDestinationSurface, &IID_IWineD3DBaseTexture, (void **)&baseTexture)) {
6725 textureDimensions = IWineD3DBaseTexture_GetTextureDimensions(baseTexture);
6726 IWineD3DBaseTexture_Release(baseTexture);
6729 glDisable(textureDimensions); /* This needs to be managed better.... */
6735 /* Used by DirectX 8 */
6736 static HRESULT WINAPI IWineD3DDeviceImpl_CopyRects(IWineD3DDevice *iface,
6737 IWineD3DSurface* pSourceSurface, CONST RECT* pSourceRectsArray, UINT cRects,
6738 IWineD3DSurface* pDestinationSurface, CONST POINT* pDestPointsArray) {
6740 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
6741 HRESULT hr = WINED3D_OK;
6742 WINED3DFORMAT srcFormat, destFormat;
6743 UINT srcWidth, destWidth;
6744 UINT srcHeight, destHeight;
6746 WINED3DSURFACE_DESC winedesc;
6748 TRACE("(%p) pSrcSur=%p, pSourceRects=%p, cRects=%d, pDstSur=%p, pDestPtsArr=%p\n", This,
6749 pSourceSurface, pSourceRectsArray, cRects, pDestinationSurface, pDestPointsArray);
6752 /* Check that the source texture is in WINED3DPOOL_SYSTEMMEM and the destination texture is in WINED3DPOOL_DEFAULT */
6753 memset(&winedesc, 0, sizeof(winedesc));
6755 winedesc.Format = &srcFormat;
6756 winedesc.Width = &srcWidth;
6757 winedesc.Height = &srcHeight;
6758 winedesc.Size = &srcSize;
6759 IWineD3DSurface_GetDesc(pSourceSurface, &winedesc);
6761 winedesc.Format = &destFormat;
6762 winedesc.Width = &destWidth;
6763 winedesc.Height = &destHeight;
6764 winedesc.Size = NULL;
6765 IWineD3DSurface_GetDesc(pDestinationSurface, &winedesc);
6767 /* Check that the source and destination formats match */
6768 if (srcFormat != destFormat && WINED3DFMT_UNKNOWN != destFormat) {
6769 WARN("(%p) source %p format must match the dest %p format, returning WINED3DERR_INVALIDCALL\n", This, pSourceSurface, pDestinationSurface);
6770 return WINED3DERR_INVALIDCALL;
6771 } else if (WINED3DFMT_UNKNOWN == destFormat) {
6772 TRACE("(%p) : Converting destination surface from WINED3DFMT_UNKNOWN to the source format\n", This);
6773 IWineD3DSurface_SetFormat(pDestinationSurface, srcFormat);
6774 destFormat = srcFormat;
6777 /* Quick if complete copy ... */
6778 if (cRects == 0 && pSourceRectsArray == NULL && pDestPointsArray == NULL) {
6780 if (srcWidth == destWidth && srcHeight == destHeight) {
6781 WINED3DLOCKED_RECT lrSrc;
6782 WINED3DLOCKED_RECT lrDst;
6783 IWineD3DSurface_LockRect(pSourceSurface, &lrSrc, NULL, WINED3DLOCK_READONLY);
6784 IWineD3DSurface_LockRect(pDestinationSurface, &lrDst, NULL, 0L);
6785 TRACE("Locked src and dst, Direct copy as surfaces are equal, w=%d, h=%d\n", srcWidth, srcHeight);
6787 memcpy(lrDst.pBits, lrSrc.pBits, srcSize);
6789 IWineD3DSurface_UnlockRect(pSourceSurface);
6790 IWineD3DSurface_UnlockRect(pDestinationSurface);
6791 TRACE("Unlocked src and dst\n");
6795 FIXME("Wanted to copy all surfaces but size not compatible, returning WINED3DERR_INVALIDCALL\n");
6796 hr = WINED3DERR_INVALIDCALL;
6801 if (NULL != pSourceRectsArray && NULL != pDestPointsArray) {
6803 int bytesPerPixel = ((IWineD3DSurfaceImpl *) pSourceSurface)->bytesPerPixel;
6806 /* Copy rect by rect */
6807 for (i = 0; i < cRects; ++i) {
6808 CONST RECT* r = &pSourceRectsArray[i];
6809 CONST POINT* p = &pDestPointsArray[i];
6812 WINED3DLOCKED_RECT lrSrc;
6813 WINED3DLOCKED_RECT lrDst;
6816 TRACE("Copying rect %d (%ld,%ld),(%ld,%ld) -> (%ld,%ld)\n", i, r->left, r->top, r->right, r->bottom, p->x, p->y);
6817 if (srcFormat == WINED3DFMT_DXT1) {
6818 copyperline = ((r->right - r->left) * bytesPerPixel) / 2; /* DXT1 is half byte per pixel */
6820 copyperline = ((r->right - r->left) * bytesPerPixel);
6823 IWineD3DSurface_LockRect(pSourceSurface, &lrSrc, r, WINED3DLOCK_READONLY);
6824 dest_rect.left = p->x;
6825 dest_rect.top = p->y;
6826 dest_rect.right = p->x + (r->right - r->left);
6827 dest_rect.bottom= p->y + (r->bottom - r->top);
6828 IWineD3DSurface_LockRect(pDestinationSurface, &lrDst, &dest_rect, 0L);
6829 TRACE("Locked src and dst\n");
6831 /* Find where to start */
6832 for (j = 0; j < (r->bottom - r->top - 1); ++j) {
6833 memcpy((char*) lrDst.pBits + (j * lrDst.Pitch), (char*) lrSrc.pBits + (j * lrSrc.Pitch), copyperline);
6835 IWineD3DSurface_UnlockRect(pSourceSurface);
6836 IWineD3DSurface_UnlockRect(pDestinationSurface);
6837 TRACE("Unlocked src and dst\n");
6840 FIXME("Wanted to copy partial surfaces not implemented, returning WINED3DERR_INVALIDCALL\n");
6841 hr = WINED3DERR_INVALIDCALL;
6848 /* Implementation details at http://developer.nvidia.com/attach/6494
6850 http://oss.sgi.com/projects/ogl-sample/registry/NV/evaluators.txt
6851 hmm.. no longer supported use
6852 OpenGL evaluators or tessellate surfaces within your application.
6855 /* http://msdn.microsoft.com/library/default.asp?url=/library/en-us/directx9_c/directx/graphics/reference/d3d/interfaces/idirect3ddevice9/DrawRectPatch.asp */
6856 static HRESULT WINAPI IWineD3DDeviceImpl_DrawRectPatch(IWineD3DDevice *iface, UINT Handle, CONST float* pNumSegs, CONST WINED3DRECTPATCH_INFO* pRectPatchInfo) {
6857 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
6858 TRACE("(%p) Handle(%d) noSegs(%p) rectpatch(%p)\n", This, Handle, pNumSegs, pRectPatchInfo);
6859 FIXME("(%p) : Stub\n", This);
6864 /* http://msdn.microsoft.com/library/default.asp?url=/library/en-us/directx9_c/directx/graphics/reference/d3d/interfaces/idirect3ddevice9/DrawTriPatch.asp */
6865 static HRESULT WINAPI IWineD3DDeviceImpl_DrawTriPatch(IWineD3DDevice *iface, UINT Handle, CONST float* pNumSegs, CONST WINED3DTRIPATCH_INFO* pTriPatchInfo) {
6866 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
6867 TRACE("(%p) Handle(%d) noSegs(%p) tripatch(%p)\n", This, Handle, pNumSegs, pTriPatchInfo);
6868 FIXME("(%p) : Stub\n", This);
6872 static HRESULT WINAPI IWineD3DDeviceImpl_DeletePatch(IWineD3DDevice *iface, UINT Handle) {
6873 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
6874 TRACE("(%p) Handle(%d)\n", This, Handle);
6875 FIXME("(%p) : Stub\n", This);
6879 static HRESULT WINAPI IWineD3DDeviceImpl_ColorFill(IWineD3DDevice *iface, IWineD3DSurface *pSurface, CONST D3DRECT* pRect, D3DCOLOR color) {
6880 /* I couldn't find a 'really' quick way of doing this in openGl so here goes
6881 fill a surface with a block of color! */
6882 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
6883 /* TODO: get rid of the use of IWineD3DSurfaceImpl, move code into surface.c */
6884 IWineD3DSurfaceImpl *surface = (IWineD3DSurfaceImpl *)pSurface;
6885 IWineD3DSwapChainImpl *container = NULL;
6886 BOOL isRenderTarget = FALSE;
6887 unsigned int width, height;
6888 unsigned int top, left;
6891 TRACE("(%p) Colour fill Surface: %p rect: %p color: %ld\n", This, pSurface, pRect, color);
6893 if (surface->resource.pool != WINED3DPOOL_DEFAULT && surface->resource.pool != WINED3DPOOL_SYSTEMMEM) {
6894 FIXME("call to colorfill with non WINED3DPOOL_DEFAULT or WINED3DPOOL_SYSTEMMEM surface\n");
6895 return WINED3DERR_INVALIDCALL;
6898 /* TODO: get rid of IWineD3DSwapChainImpl reference, a 'context' manager may help with this */
6899 if (WINED3D_OK == IWineD3DSurface_GetContainer(pSurface, &IID_IWineD3DSwapChain, (void **)&container) || pSurface == This->renderTarget) {
6900 if (WINED3DUSAGE_RENDERTARGET & surface->resource.usage) {
6901 /* TODO: make sure we set everything back to the way it was, and context management!
6902 glGetIntegerv(GL_READ_BUFFER, &prev_read);
6903 vcheckGLcall("glIntegerv");
6904 glGetIntegerv(GL_PACK_SWAP_BYTES, &prev_store);
6905 vcheckGLcall("glIntegerv");
6907 TRACE("Color fill to render targets may cause some graphics issues\n");
6908 if (pSurface == container->frontBuffer) {
6909 glDrawBuffer(GL_FRONT);
6911 glDrawBuffer(GL_BACK);
6914 if (WINED3DUSAGE_DEPTHSTENCIL & surface->resource.usage) {
6915 FIXME("colouring of depth_stencil? %p buffers is not yet supported? %ld\n", surface, surface->resource.usage);
6917 FIXME("(%p) : Regression %ld %p %p\n", This, surface->resource.usage, pSurface, This->renderTarget);
6919 if (container != NULL) {
6920 IWineD3DSwapChain_Release((IWineD3DSwapChain *)container);
6922 /* we can use GL_STENCIL_INDEX etc...*/
6925 if (container != NULL) {
6926 IWineD3DSwapChain_Release((IWineD3DSwapChain *)container);
6928 isRenderTarget = TRUE;
6930 /* TODO: drawing to GL_FRONT and GL_BACK */
6931 /* TODO: see if things can be speeded up by using the correct
6932 * colour model of the target texture from the start (16 bit graphics on 32 X are slow anyway!) */
6933 if (pRect == NULL) {
6936 width = surface->currentDesc.Width;
6937 height = surface->currentDesc.Height;
6941 width = pRect->x2 - left;
6942 height = pRect->y2 - top;
6945 data = HeapAlloc(GetProcessHeap(), 0, 4 * width);
6946 /* Create a 'line' of color color, in the correct format for the surface */
6947 for (u = 0 ; u < width ; u ++) {
6952 if (isRenderTarget == FALSE) {
6953 glDescriptor *glDesc;
6954 IWineD3DSurface_PreLoad(pSurface);
6956 /* draw a block of the coloured line on the sufrace */
6957 IWineD3DSurface_GetGlDesc(pSurface, &glDesc);
6958 for (v = 0 ; v< height;v++) {
6959 glTexSubImage2D(glDesc->target
6960 ,glDesc->level /* level */
6970 checkGLcall("glTexSubImage2D");
6972 glDisable(glDesc->target);
6974 /** FIXME: Using GLClear may be faster **/
6975 glRasterPos2i(left, top);
6976 glPixelZoom((float)width ,(float)height);
6977 glDrawPixels(1, 1, GL_RGBA, GL_UNSIGNED_BYTE, data);
6978 checkGLcall("glDrawPixels");
6980 HeapFree(GetProcessHeap(), 0, data);
6986 /* rendertarget and deptth stencil functions */
6987 static HRESULT WINAPI IWineD3DDeviceImpl_GetRenderTarget(IWineD3DDevice* iface,DWORD RenderTargetIndex, IWineD3DSurface **ppRenderTarget) {
6988 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
6990 /* FIXME: Implelent RenderTargetIndex >0 */
6991 if(RenderTargetIndex > 0)
6992 FIXME("(%p) : RenderTargetIndex %ld >0 not currently supported\n", This, RenderTargetIndex);
6994 *ppRenderTarget = This->renderTarget;
6995 TRACE("(%p) : RenderTarget %ld Index returning %p\n", This, RenderTargetIndex, *ppRenderTarget);
6996 /* Note inc ref on returned surface */
6997 if(*ppRenderTarget != NULL)
6998 IWineD3DSurface_AddRef(*ppRenderTarget);
7002 static HRESULT WINAPI IWineD3DDeviceImpl_SetFrontBackBuffers(IWineD3DDevice *iface, IWineD3DSurface *Front, IWineD3DSurface *Back) {
7003 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
7004 IWineD3DSurfaceImpl *FrontImpl = (IWineD3DSurfaceImpl *) Front;
7005 IWineD3DSurfaceImpl *BackImpl = (IWineD3DSurfaceImpl *) Back;
7006 IWineD3DSwapChainImpl *Swapchain;
7009 TRACE("(%p)->(%p,%p)\n", This, FrontImpl, BackImpl);
7011 hr = IWineD3DDevice_GetSwapChain(iface, 0, (IWineD3DSwapChain **) &Swapchain);
7012 if(hr != WINED3D_OK) {
7013 ERR("Can't get the swapchain\n");
7017 /* Make sure to release the swapchain */
7018 IWineD3DSwapChain_Release((IWineD3DSwapChain *) Swapchain);
7020 if(FrontImpl && !(FrontImpl->resource.usage & WINED3DUSAGE_RENDERTARGET) ) {
7021 ERR("Trying to set a front buffer which doesn't have WINED3DUSAGE_RENDERTARGET usage\n");
7022 return WINED3DERR_INVALIDCALL;
7024 else if(BackImpl && !(BackImpl->resource.usage & WINED3DUSAGE_RENDERTARGET)) {
7025 ERR("Trying to set a back buffer which doesn't have WINED3DUSAGE_RENDERTARGET usage\n");
7026 return WINED3DERR_INVALIDCALL;
7029 if(Swapchain->frontBuffer != Front) {
7030 TRACE("Changing the front buffer from %p to %p\n", Swapchain->frontBuffer, Front);
7032 if(Swapchain->frontBuffer)
7033 IWineD3DSurface_SetContainer(Swapchain->frontBuffer, NULL);
7034 Swapchain->frontBuffer = Front;
7036 if(Swapchain->frontBuffer) {
7037 IWineD3DSurface_SetContainer(Swapchain->frontBuffer, (IWineD3DBase *) Swapchain);
7041 if(Back && !Swapchain->backBuffer) {
7042 /* We need memory for the back buffer array - only one back buffer this way */
7043 Swapchain->backBuffer = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(IWineD3DSurface *));
7044 if(!Swapchain->backBuffer) {
7045 ERR("Out of memory\n");
7046 return E_OUTOFMEMORY;
7050 if(Swapchain->backBuffer[0] != Back) {
7051 TRACE("Changing the back buffer from %p to %p\n", Swapchain->backBuffer, Back);
7053 if(!Swapchain->backBuffer[0]) {
7054 /* GL was told to draw to the front buffer at creation,
7057 glDrawBuffer(GL_BACK);
7058 checkGLcall("glDrawBuffer(GL_BACK)");
7059 /* Set the backbuffer count to 1 because other code uses it to fing the back buffers */
7060 Swapchain->presentParms.BackBufferCount = 1;
7062 /* That makes problems - disable for now */
7063 /* glDrawBuffer(GL_FRONT); */
7064 checkGLcall("glDrawBuffer(GL_FRONT)");
7065 /* We have lost our back buffer, set this to 0 to avoid confusing other code */
7066 Swapchain->presentParms.BackBufferCount = 0;
7070 if(Swapchain->backBuffer[0])
7071 IWineD3DSurface_SetContainer(Swapchain->backBuffer[0], NULL);
7072 Swapchain->backBuffer[0] = Back;
7074 if(Swapchain->backBuffer[0]) {
7075 IWineD3DSurface_SetContainer(Swapchain->backBuffer[0], (IWineD3DBase *) Swapchain);
7077 HeapFree(GetProcessHeap(), 0, Swapchain->backBuffer);
7085 static HRESULT WINAPI IWineD3DDeviceImpl_GetDepthStencilSurface(IWineD3DDevice* iface, IWineD3DSurface **ppZStencilSurface) {
7086 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
7087 *ppZStencilSurface = This->depthStencilBuffer;
7088 TRACE("(%p) : zStencilSurface returning %p\n", This, *ppZStencilSurface);
7090 if(*ppZStencilSurface != NULL) {
7091 /* Note inc ref on returned surface */
7092 IWineD3DSurface_AddRef(*ppZStencilSurface);
7097 /* internal static helper functions */
7098 static HRESULT WINAPI IWineD3DDeviceImpl_ActiveRender(IWineD3DDevice* iface,
7099 IWineD3DSurface *RenderSurface);
7101 static HRESULT WINAPI IWineD3DDeviceImpl_SetRenderTarget(IWineD3DDevice *iface, DWORD RenderTargetIndex, IWineD3DSurface *pRenderTarget) {
7102 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
7103 HRESULT hr = WINED3D_OK;
7104 WINED3DVIEWPORT viewport;
7106 TRACE("(%p) Swapping rendertarget\n",This);
7107 if (RenderTargetIndex > 0) {
7108 FIXME("(%p) Render targets other than the first are not supported\n",This);
7109 RenderTargetIndex = 0;
7112 /* MSDN says that null disables the render target
7113 but a device must always be associated with a render target
7114 nope MSDN says that we return invalid call to a null rendertarget with an index of 0
7116 see http://msdn.microsoft.com/library/default.asp?url=/library/en-us/directx9_c/directx/graphics/programmingguide/AdvancedTopics/PixelPipe/MultipleRenderTarget.asp
7119 if (RenderTargetIndex == 0 && pRenderTarget == NULL) {
7120 FIXME("Trying to set render target 0 to NULL\n");
7121 return WINED3DERR_INVALIDCALL;
7123 /* TODO: replace Impl* usage with interface usage */
7124 if (!((IWineD3DSurfaceImpl *)pRenderTarget)->resource.usage & WINED3DUSAGE_RENDERTARGET) {
7125 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);
7126 return WINED3DERR_INVALIDCALL;
7128 /** TODO: check that the depth stencil format matches the render target, this is only done in debug
7129 * builds, but I think wine counts as a 'debug' build for now.
7130 ******************************/
7131 /* If we are trying to set what we already have, don't bother */
7132 if (pRenderTarget == This->renderTarget) {
7133 TRACE("Trying to do a NOP SetRenderTarget operation\n");
7135 /* Otherwise, set the render target up */
7137 if (FALSE == This->sceneEnded) {
7138 IWineD3DDevice_EndScene(iface);
7140 TRACE("clearing renderer\n");
7141 /* IWineD3DDeviceImpl_CleanRender(iface); */
7142 /* OpenGL doesn't support 'sharing' of the stencilBuffer so we may incure an extra memory overhead
7143 depending on the renter target implementation being used.
7144 A shared context implementation will share all buffers between all rendertargets (including swapchains),
7145 implementations that use separate pbuffers for different swapchains or rendertargets will have to duplicate the
7146 stencil buffer and incure an extra memory overhead */
7147 hr = IWineD3DDeviceImpl_ActiveRender(iface, pRenderTarget);
7150 if (SUCCEEDED(hr)) {
7151 /* Finally, reset the viewport as the MSDN states. */
7152 /* TODO: Replace impl usage */
7153 viewport.Height = ((IWineD3DSurfaceImpl *)This->renderTarget)->currentDesc.Height;
7154 viewport.Width = ((IWineD3DSurfaceImpl *)This->renderTarget)->currentDesc.Width;
7157 viewport.MaxZ = 1.0f;
7158 viewport.MinZ = 0.0f;
7159 IWineD3DDeviceImpl_SetViewport(iface, &viewport);
7161 FIXME("Unknown error setting the render target\n");
7163 This->sceneEnded = FALSE;
7167 static HRESULT WINAPI IWineD3DDeviceImpl_SetDepthStencilSurface(IWineD3DDevice *iface, IWineD3DSurface *pNewZStencil) {
7168 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
7169 HRESULT hr = WINED3D_OK;
7170 IWineD3DSurface *tmp;
7172 TRACE("(%p) Swapping z-buffer\n",This);
7174 if (pNewZStencil == This->stencilBufferTarget) {
7175 TRACE("Trying to do a NOP SetRenderTarget operation\n");
7177 /** OpenGL doesn't support 'sharing' of the stencilBuffer so we may incure an extra memory overhead
7178 * depending on the renter target implementation being used.
7179 * A shared context implementation will share all buffers between all rendertargets (including swapchains),
7180 * implementations that use separate pbuffers for different swapchains or rendertargets will have to duplicate the
7181 * stencil buffer and incure an extra memory overhead
7182 ******************************************************/
7185 tmp = This->stencilBufferTarget;
7186 This->stencilBufferTarget = pNewZStencil;
7187 /* should we be calling the parent or the wined3d surface? */
7188 if (NULL != This->stencilBufferTarget) IWineD3DSurface_AddRef(This->stencilBufferTarget);
7189 if (NULL != tmp) IWineD3DSurface_Release(tmp);
7191 /** TODO: glEnable/glDisable on depth/stencil depending on
7192 * pNewZStencil is NULL and the depth/stencil is enabled in d3d
7193 **********************************************************/
7200 #ifdef GL_VERSION_1_3
7201 /* Internal functions not in DirectX */
7202 /** TODO: move this off to the opengl context manager
7203 *(the swapchain doesn't need to know anything about offscreen rendering!)
7204 ****************************************************/
7206 static HRESULT WINAPI IWineD3DDeviceImpl_CleanRender(IWineD3DDevice* iface, IWineD3DSwapChainImpl *swapchain)
7208 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
7210 TRACE("(%p), %p\n", This, swapchain);
7212 if (swapchain->win != swapchain->drawable) {
7213 /* Set everything back the way it ws */
7214 swapchain->render_ctx = swapchain->glCtx;
7215 swapchain->drawable = swapchain->win;
7220 /* TODO: move this off into a context manager so that GLX_ATI_render_texture and other types of surface can be used. */
7221 static HRESULT WINAPI IWineD3DDeviceImpl_FindGLContext(IWineD3DDevice *iface, IWineD3DSurface *pSurface, glContext **context) {
7222 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
7225 unsigned int height;
7226 WINED3DFORMAT format;
7227 WINED3DSURFACE_DESC surfaceDesc;
7228 memset(&surfaceDesc, 0, sizeof(surfaceDesc));
7229 surfaceDesc.Width = &width;
7230 surfaceDesc.Height = &height;
7231 surfaceDesc.Format = &format;
7232 IWineD3DSurface_GetDesc(pSurface, &surfaceDesc);
7234 /* I need a get width/height function (and should do something with the format) */
7235 for (i = 0; i < CONTEXT_CACHE; ++i) {
7236 /** NOTE: the contextCache[i].pSurface == pSurface check ceates onepbuffer per surface
7237 ATI cards don't destroy pbuffers, but as soon as resource releasing callbacks are inplace
7238 the pSurface can be set to 0 allowing it to be reused from cache **/
7239 if (This->contextCache[i].Width == width && This->contextCache[i].Height == height
7240 && (pbuffer_per_surface == FALSE || This->contextCache[i].pSurface == pSurface || This->contextCache[i].pSurface == NULL)) {
7241 *context = &This->contextCache[i];
7244 if (This->contextCache[i].Width == 0) {
7245 This->contextCache[i].pSurface = pSurface;
7246 This->contextCache[i].Width = width;
7247 This->contextCache[i].Height = height;
7248 *context = &This->contextCache[i];
7252 if (i == CONTEXT_CACHE) {
7253 int minUsage = 0x7FFFFFFF; /* MAX_INT */
7254 glContext *dropContext = 0;
7255 for (i = 0; i < CONTEXT_CACHE; i++) {
7256 if (This->contextCache[i].usedcount < minUsage) {
7257 dropContext = &This->contextCache[i];
7258 minUsage = This->contextCache[i].usedcount;
7261 /* clean up the context (this doesn't work for ATI at the moment */
7263 glXDestroyContext(swapchain->display, dropContext->context);
7264 glXDestroyPbuffer(swapchain->display, dropContext->drawable);
7267 dropContext->Width = 0;
7268 dropContext->pSurface = pSurface;
7269 *context = dropContext;
7271 if (++This->contextCache[i].usedcount == 0x7FFFFFFF /* MAX_INT */ - 1 ) {
7272 for (i = 0; i < CONTEXT_CACHE; i++) {
7273 This->contextCache[i].usedcount = max(0, This->contextCache[i].usedcount - (0x7FFFFFFF /* MAX_INT */ >> 1));
7277 if (*context != NULL)
7280 return E_OUTOFMEMORY;
7284 /** FIXME: This is currently used called whenever SetRenderTarget or SetStencilBuffer are called
7285 * the functionality needs splitting up so that we don't do more than we should do.
7286 * this only seems to impact performance a little.
7287 ******************************/
7288 static HRESULT WINAPI IWineD3DDeviceImpl_ActiveRender(IWineD3DDevice* iface,
7289 IWineD3DSurface *RenderSurface) {
7290 HRESULT ret = WINED3DERR_INVALIDCALL;
7293 * Currently only active for GLX >= 1.3
7294 * for others versions we'll have to use GLXPixmaps
7296 * normally we must test GLX_VERSION_1_3 but nvidia headers are not correct
7297 * as they implement GLX 1.3 but only define GLX_VERSION_1_2
7298 * so only check OpenGL version
7299 * ..........................
7300 * I don't believe that it is a problem with NVidia headers,
7301 * XFree only supports GLX1.2, nVidia (and ATI to some extent) provide 1.3 functions
7302 * in GLX 1.2, there is no mention of the correct way to tell if the extensions are provided.
7304 * Your application will report GLX version 1.2 on glXQueryVersion.
7305 * However, it is safe to call the GLX 1.3 functions as described below.
7307 #if defined(GL_VERSION_1_3)
7309 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
7310 IWineD3DSurface *StencilSurface = This->stencilBufferTarget;
7311 IWineD3DSurface *tmp;
7312 /** TODO: we only need to look up the configuration !IF! we are setting the target to a texture **/
7313 GLXFBConfig* cfgs = NULL;
7317 IWineD3DSwapChain *currentSwapchain;
7318 IWineD3DSwapChainImpl *swapchain;
7319 /** TODO: get rid of Impl usage we should always create a zbuffer/stencil with our contexts if possible,
7320 * but switch them off if the StencilSurface is set to NULL
7321 ** *********************************************************/
7322 D3DFORMAT BackBufferFormat = ((IWineD3DSurfaceImpl *) RenderSurface)->resource.format;
7323 D3DFORMAT StencilBufferFormat = (NULL != StencilSurface) ? ((IWineD3DSurfaceImpl *) StencilSurface)->resource.format : 0;
7326 if StencilSurface == NULL && zBufferTarget != NULL then switch the zbuffer off,
7327 it StencilSurface != NULL && zBufferTarget == NULL switch it on
7330 #define PUSH1(att) attribs[nAttribs++] = (att);
7331 #define PUSH2(att,value) attribs[nAttribs++] = (att); attribs[nAttribs++] = (value);
7333 /* PUSH2(GLX_BIND_TO_TEXTURE_RGBA_ATI, True); examples of this are few and far between (but I've got a nice working one!)*/
7335 /** TODO: remove the reff to Impl (context manager should fix this!) **/
7336 IWineD3DSwapChainImpl *impSwapChain;
7337 IWineD3DDevice_GetSwapChain(iface, 0, (IWineD3DSwapChain **)&impSwapChain);
7338 if (NULL == impSwapChain) { /* NOTE: This should NEVER fail */
7339 ERR("(%p) Failed to get a the implicit swapchain\n", iface);
7344 PUSH2(GLX_DRAWABLE_TYPE, GLX_PBUFFER_BIT);
7345 PUSH2(GLX_X_RENDERABLE, TRUE);
7346 PUSH2(GLX_DOUBLEBUFFER, TRUE);
7347 TRACE("calling makeglcfg\n");
7348 D3DFmtMakeGlCfg(BackBufferFormat, StencilBufferFormat, attribs, &nAttribs, FALSE /* alternate */);
7351 TRACE("calling chooseFGConfig\n");
7352 cfgs = glXChooseFBConfig(impSwapChain->display, DefaultScreen(impSwapChain->display),
7355 if (!cfgs) { /* OK we didn't find the exact config, so use any reasonable match */
7356 /* TODO: fill in the 'requested' and 'current' depths, also make sure that's
7357 why we failed and only show this message once! */
7358 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"); /**/
7360 PUSH2(GLX_DRAWABLE_TYPE, GLX_PBUFFER_BIT | GLX_WINDOW_BIT);
7361 /* PUSH2(GLX_X_RENDERABLE, TRUE); */
7362 PUSH2(GLX_RENDER_TYPE, GLX_RGBA_BIT);
7363 PUSH2(GLX_DOUBLEBUFFER, FALSE);
7364 TRACE("calling makeglcfg\n");
7365 D3DFmtMakeGlCfg(BackBufferFormat, StencilBufferFormat, attribs, &nAttribs, TRUE /* alternate */);
7367 cfgs = glXChooseFBConfig(impSwapChain->display, DefaultScreen(impSwapChain->display),
7374 for (i = 0; i < nCfgs; ++i) {
7375 TRACE("for (%u,%s)/(%u,%s) found config[%d]@%p\n", BackBufferFormat,
7376 debug_d3dformat(BackBufferFormat), StencilBufferFormat,
7377 debug_d3dformat(StencilBufferFormat), i, cfgs[i]);
7380 if (NULL != This->renderTarget) {
7382 vcheckGLcall("glFlush");
7383 /** This is only useful if the old render target was a swapchain,
7384 * we need to supercede this with a function that displays
7385 * the current buffer on the screen. This is easy to do in glx1.3 but
7386 * we need to do copy-write pixels in glx 1.2.
7387 ************************************************/
7388 glXSwapBuffers(impSwapChain->display, impSwapChain->drawable);
7390 printf("Hit Enter to get next frame ...\n");
7396 if (IWineD3DSurface_GetContainer(This->renderTarget, &IID_IWineD3DSwapChain, (void **)¤tSwapchain) != WINED3D_OK) {
7397 /* the selected render target doesn't belong to a swapchain, so use the devices implicit swapchain */
7398 IWineD3DDevice_GetSwapChain(iface, 0, ¤tSwapchain);
7402 * TODO: remove the use of IWineD3DSwapChainImpl, a context manager will help since it will replace the
7403 * renderTarget = swapchain->backBuffer[i] bit and anything to do with *glContexts
7404 **********************************************************************/
7405 if (IWineD3DSurface_GetContainer(RenderSurface, &IID_IWineD3DSwapChain, (void **)&swapchain) == WINED3D_OK) {
7406 /* We also need to make sure that the lights &co are also in the context of the swapchains */
7407 /* FIXME: If the render target gets sent to the frontBuffer should be be presenting it raw? */
7408 TRACE("making swapchain active\n");
7409 if (RenderSurface != This->renderTarget) {
7410 BOOL backbuf = FALSE;
7413 for(i = 0; i < swapchain->presentParms.BackBufferCount; i++) {
7414 if(RenderSurface == swapchain->backBuffer[i]) {
7422 /* This could be flagged so that some operations work directly with the front buffer */
7423 FIXME("Attempting to set the renderTarget to the frontBuffer\n");
7425 if (glXMakeCurrent(swapchain->display, swapchain->win, swapchain->glCtx)
7427 TRACE("Error in setting current context: context %p drawable %ld !\n",
7428 impSwapChain->glCtx, impSwapChain->win);
7431 IWineD3DDeviceImpl_CleanRender(iface, (IWineD3DSwapChainImpl *)currentSwapchain);
7433 checkGLcall("glXMakeContextCurrent");
7435 IWineD3DSwapChain_Release((IWineD3DSwapChain *)swapchain);
7437 else if (pbuffer_support && cfgs != NULL /* && some test to make sure that opengl supports pbuffers */) {
7439 /** ********************************************************************
7440 * This is a quickly hacked out implementation of offscreen textures.
7441 * It will work in most cases but there may be problems if the client
7442 * modifies the texture directly, or expects the contents of the rendertarget
7445 * There are some real speed vs compatibility issues here:
7446 * we should really use a new context for every texture, but that eats ram.
7447 * we should also be restoring the texture to the pbuffer but that eats CPU
7448 * we can also 'reuse' the current pbuffer if the size is larger than the requested buffer,
7449 * but if this means reusing the display backbuffer then we need to make sure that
7450 * states are correctly preserved.
7451 * In many cases I would expect that we can 'skip' some functions, such as preserving states,
7452 * and gain a good performance increase at the cost of compatibility.
7453 * I would suggest that, when this is the case, a user configurable flag be made
7454 * available, allowing the user to choose the best emulated experience for them.
7455 *********************************************************************/
7457 XVisualInfo *visinfo;
7458 glContext *newContext;
7460 /* Here were using a shared context model */
7461 if (WINED3D_OK != IWineD3DDeviceImpl_FindGLContext(iface, RenderSurface, &newContext)) {
7462 FIXME("(%p) : Failed to find a context for surface %p\n", iface, RenderSurface);
7465 /* If the context doesn't exist then create a new one */
7466 /* TODO: This should really be part of findGlContext */
7467 if (NULL == newContext->context) {
7469 TRACE("making new buffer\n");
7471 PUSH2(GLX_PBUFFER_WIDTH, newContext->Width);
7472 PUSH2(GLX_PBUFFER_HEIGHT, newContext->Height);
7475 newContext->drawable = glXCreatePbuffer(impSwapChain->display, cfgs[0], attribs);
7477 /** ****************************************
7478 *GLX1.3 isn't supported by XFree 'yet' until that point ATI emulates pBuffers
7480 * In future releases, we may provide the calls glXCreateNewContext,
7481 * glXQueryDrawable and glXMakeContextCurrent.
7482 * so until then we have to use glXGetVisualFromFBConfig &co..
7483 ********************************************/
7486 visinfo = glXGetVisualFromFBConfig(impSwapChain->display, cfgs[0]);
7488 ERR("Error: couldn't get an RGBA, double-buffered visual\n");
7490 newContext->context = glXCreateContext(impSwapChain->display, visinfo, impSwapChain->glCtx, GL_TRUE);
7494 if (NULL == newContext || NULL == newContext->context) {
7495 ERR("(%p) : Failed to find a context for surface %p\n", iface, RenderSurface);
7497 /* Debug logging, (this function leaks), change to a TRACE when the leak is plugged */
7498 if (glXMakeCurrent(impSwapChain->display, newContext->drawable, newContext->context) == False) {
7499 TRACE("Error in setting current context: context %p drawable %ld\n", newContext->context, newContext->drawable);
7502 /* Clean up the old context */
7503 IWineD3DDeviceImpl_CleanRender(iface, (IWineD3DSwapChainImpl *)currentSwapchain);
7504 /* Set the current context of the swapchain to the new context */
7505 impSwapChain->drawable = newContext->drawable;
7506 impSwapChain->render_ctx = newContext->context;
7510 #if 1 /* Apply the stateblock to the new context
7511 FIXME: This is a bit of a hack, each context should know it's own state,
7512 the directX current directX state should then be applied to the context */
7515 IWineD3DStateBlockImpl *oldUpdateStateBlock;
7516 oldUpdateStateBlock = This->updateStateBlock;
7517 oldRecording= This->isRecordingState;
7518 This->isRecordingState = FALSE;
7519 This->updateStateBlock = This->stateBlock;
7520 IWineD3DStateBlock_Apply((IWineD3DStateBlock *)This->stateBlock);
7522 This->isRecordingState = oldRecording;
7523 This->updateStateBlock = oldUpdateStateBlock;
7528 /* clean up the current rendertargets swapchain (if it belonged to one) */
7529 if (currentSwapchain != NULL) {
7530 IWineD3DSwapChain_Release((IWineD3DSwapChain *)currentSwapchain);
7533 /* Were done with the opengl context management, setup the rendertargets */
7535 tmp = This->renderTarget;
7536 This->renderTarget = RenderSurface;
7537 IWineD3DSurface_AddRef(This->renderTarget);
7538 IWineD3DSurface_Release(tmp);
7544 /* The surface must be rendered upside down to cancel the flip produce by glCopyTexImage */
7545 /* Check that the container is not a swapchain member */
7547 IWineD3DSwapChain *tmpSwapChain;
7548 if (WINED3D_OK != IWineD3DSurface_GetContainer(This->renderTarget, &IID_IWineD3DSwapChain, (void **)&tmpSwapChain)) {
7549 This->renderUpsideDown = TRUE;
7551 This->renderUpsideDown = FALSE;
7552 IWineD3DSwapChain_Release(tmpSwapChain);
7554 /* Force updating the cull mode */
7555 TRACE("setting render state\n");
7556 IWineD3DDevice_GetRenderState(iface, WINED3DRS_CULLMODE, &value);
7557 IWineD3DDevice_SetRenderState(iface, WINED3DRS_CULLMODE, value);
7559 /* Force updating projection matrix */
7560 This->last_was_rhw = FALSE;
7561 This->proj_valid = FALSE;
7569 ERR("cannot get valides GLXFBConfig for (%u,%s)/(%u,%s)\n", BackBufferFormat,
7570 debug_d3dformat(BackBufferFormat), StencilBufferFormat, debug_d3dformat(StencilBufferFormat));
7575 if ( NULL != impSwapChain) {
7576 IWineD3DSwapChain_Release((IWineD3DSwapChain *)impSwapChain);
7584 static HRESULT WINAPI IWineD3DDeviceImpl_SetCursorProperties(IWineD3DDevice* iface, UINT XHotSpot,
7585 UINT YHotSpot, IWineD3DSurface *pCursorBitmap) {
7586 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *) iface;
7587 /* TODO: the use of Impl is deprecated. */
7588 /* some basic validation checks */
7589 IWineD3DSurfaceImpl * pSur = (IWineD3DSurfaceImpl *) pCursorBitmap;
7591 TRACE("(%p) : Spot Pos(%u,%u)\n", This, XHotSpot, YHotSpot);
7593 if (WINED3DFMT_A8R8G8B8 != pSur->resource.format) {
7594 ERR("(%p) : surface(%p) has an invalid format\n", This, pCursorBitmap);
7595 return WINED3DERR_INVALIDCALL;
7597 if (32 != pSur->currentDesc.Height || 32 != pSur->currentDesc.Width) {
7598 ERR("(%p) : surface(%p) has an invalid size\n", This, pCursorBitmap);
7599 return WINED3DERR_INVALIDCALL;
7601 /* TODO: make the cursor 'real' */
7603 This->xHotSpot = XHotSpot;
7604 This->yHotSpot = YHotSpot;
7609 static void WINAPI IWineD3DDeviceImpl_SetCursorPosition(IWineD3DDevice* iface, int XScreenSpace, int YScreenSpace, DWORD Flags) {
7610 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *) iface;
7611 TRACE("(%p) : SetPos to (%u,%u)\n", This, XScreenSpace, YScreenSpace);
7613 This->xScreenSpace = XScreenSpace;
7614 This->yScreenSpace = YScreenSpace;
7620 static BOOL WINAPI IWineD3DDeviceImpl_ShowCursor(IWineD3DDevice* iface, BOOL bShow) {
7621 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *) iface;
7622 TRACE("(%p) : visible(%d)\n", This, bShow);
7624 This->bCursorVisible = bShow;
7629 static HRESULT WINAPI IWineD3DDeviceImpl_TestCooperativeLevel(IWineD3DDevice* iface) {
7630 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *) iface;
7631 TRACE("(%p) : state (%lu)\n", This, This->state);
7632 /* TODO: Implement wrapping of the WndProc so that mimimize and maxamise can be monitored and the states adjusted. */
7633 switch (This->state) {
7636 case WINED3DERR_DEVICELOST:
7638 ResourceList *resourceList = This->resources;
7639 while (NULL != resourceList) {
7640 if (((IWineD3DResourceImpl *)resourceList->resource)->resource.pool == WINED3DPOOL_DEFAULT /* TODO: IWineD3DResource_GetPool(resourceList->resource)*/)
7641 return WINED3DERR_DEVICENOTRESET;
7642 resourceList = resourceList->next;
7644 return WINED3DERR_DEVICELOST;
7646 case WINED3DERR_DRIVERINTERNALERROR:
7647 return WINED3DERR_DRIVERINTERNALERROR;
7651 return WINED3DERR_DRIVERINTERNALERROR;
7655 static HRESULT WINAPI IWineD3DDeviceImpl_EvictManagedResources(IWineD3DDevice* iface) {
7656 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *) iface;
7657 /** FIXME: Resource tracking needs to be done,
7658 * The closes we can do to this is set the priorities of all managed textures low
7659 * and then reset them.
7660 ***********************************************************/
7661 FIXME("(%p) : stub\n", This);
7665 static HRESULT WINAPI IWineD3DDeviceImpl_Reset(IWineD3DDevice* iface, WINED3DPRESENT_PARAMETERS* pPresentationParameters) {
7666 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *) iface;
7667 /** FIXME: Resource trascking needs to be done.
7668 * in effect this pulls all non only default
7669 * textures out of video memory and deletes all glTextures (glDeleteTextures)
7670 * and should clear down the context and set it up according to pPresentationParameters
7671 ***********************************************************/
7672 FIXME("(%p) : stub\n", This);
7676 static HRESULT WINAPI IWineD3DDeviceImpl_SetDialogBoxMode(IWineD3DDevice *iface, BOOL bEnableDialogs) {
7677 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
7678 /** FIXME: always true at the moment **/
7679 if(bEnableDialogs == FALSE) {
7680 FIXME("(%p) Dialogs cannot be disabled yet\n", This);
7686 static HRESULT WINAPI IWineD3DDeviceImpl_GetCreationParameters(IWineD3DDevice *iface, WINED3DDEVICE_CREATION_PARAMETERS *pParameters) {
7687 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *) iface;
7688 TRACE("(%p) : pParameters %p\n", This, pParameters);
7690 *pParameters = This->createParms;
7694 static void WINAPI IWineD3DDeviceImpl_SetGammaRamp(IWineD3DDevice * iface, UINT iSwapChain, DWORD Flags, CONST WINED3DGAMMARAMP* pRamp) {
7695 IWineD3DSwapChain *swapchain;
7696 HRESULT hrc = WINED3D_OK;
7698 TRACE("Relaying to swapchain\n");
7700 if ((hrc = IWineD3DDeviceImpl_GetSwapChain(iface, iSwapChain, &swapchain)) == WINED3D_OK) {
7701 IWineD3DSwapChain_SetGammaRamp(swapchain, Flags, (WINED3DGAMMARAMP *)pRamp);
7702 IWineD3DSwapChain_Release(swapchain);
7707 static void WINAPI IWineD3DDeviceImpl_GetGammaRamp(IWineD3DDevice *iface, UINT iSwapChain, WINED3DGAMMARAMP* pRamp) {
7708 IWineD3DSwapChain *swapchain;
7709 HRESULT hrc = WINED3D_OK;
7711 TRACE("Relaying to swapchain\n");
7713 if ((hrc = IWineD3DDeviceImpl_GetSwapChain(iface, iSwapChain, &swapchain)) == WINED3D_OK) {
7714 hrc =IWineD3DSwapChain_GetGammaRamp(swapchain, pRamp);
7715 IWineD3DSwapChain_Release(swapchain);
7721 /** ********************************************************
7722 * Notification functions
7723 ** ********************************************************/
7724 /** This function must be called in the release of a resource when ref == 0,
7725 * the contents of resource must still be correct,
7726 * any handels to other resource held by the caller must be closed
7727 * (e.g. a texture should release all held surfaces because telling the device that it's been released.)
7728 *****************************************************/
7729 static void WINAPI IWineD3DDeviceImpl_AddResource(IWineD3DDevice *iface, IWineD3DResource *resource){
7730 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
7731 ResourceList* resourceList;
7733 TRACE("(%p) : resource %p\n", This, resource);
7735 EnterCriticalSection(&resourceStoreCriticalSection);
7737 /* add a new texture to the frot of the linked list */
7738 resourceList = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(ResourceList));
7739 resourceList->resource = resource;
7741 /* Get the old head */
7742 resourceList->next = This->resources;
7744 This->resources = resourceList;
7745 TRACE("Added resource %p with element %p pointing to %p\n", resource, resourceList, resourceList->next);
7748 LeaveCriticalSection(&resourceStoreCriticalSection);
7753 static void WINAPI IWineD3DDeviceImpl_RemoveResource(IWineD3DDevice *iface, IWineD3DResource *resource){
7754 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
7755 ResourceList* resourceList = NULL;
7756 ResourceList* previousResourceList = NULL;
7758 TRACE("(%p) : resource %p\n", This, resource);
7761 EnterCriticalSection(&resourceStoreCriticalSection);
7763 resourceList = This->resources;
7765 while (resourceList != NULL) {
7766 if(resourceList->resource == resource) break;
7767 previousResourceList = resourceList;
7768 resourceList = resourceList->next;
7771 if (resourceList == NULL) {
7772 FIXME("Attempted to remove resource %p that hasn't been stored\n", resource);
7774 LeaveCriticalSection(&resourceStoreCriticalSection);
7778 TRACE("Found resource %p with element %p pointing to %p (previous %p)\n", resourceList->resource, resourceList, resourceList->next, previousResourceList);
7780 /* make sure we don't leave a hole in the list */
7781 if (previousResourceList != NULL) {
7782 previousResourceList->next = resourceList->next;
7784 This->resources = resourceList->next;
7788 LeaveCriticalSection(&resourceStoreCriticalSection);
7794 static void WINAPI IWineD3DDeviceImpl_ResourceReleased(IWineD3DDevice *iface, IWineD3DResource *resource){
7795 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *) iface;
7798 TRACE("(%p) : resource %p\n", This, resource);
7799 switch(IWineD3DResource_GetType(resource)){
7800 case WINED3DRTYPE_SURFACE:
7801 /* TODO: check front and back buffers, rendertargets etc.. possibly swapchains? */
7803 case WINED3DRTYPE_TEXTURE:
7804 case WINED3DRTYPE_CUBETEXTURE:
7805 case WINED3DRTYPE_VOLUMETEXTURE:
7806 for (counter = 0; counter < GL_LIMITS(sampler_stages); counter++) {
7807 if (This->stateBlock != NULL && This->stateBlock->textures[counter] == (IWineD3DBaseTexture *)resource) {
7808 WARN("Texture being released is still by a stateblock, Stage = %u Texture = %p\n", counter, resource);
7809 This->stateBlock->textures[counter] = NULL;
7811 if (This->updateStateBlock != This->stateBlock ){
7812 if (This->updateStateBlock->textures[counter] == (IWineD3DBaseTexture *)resource) {
7813 WARN("Texture being released is still by a stateblock, Stage = %u Texture = %p\n", counter, resource);
7814 This->updateStateBlock->textures[counter] = NULL;
7819 case WINED3DRTYPE_VOLUME:
7820 /* TODO: nothing really? */
7822 case WINED3DRTYPE_VERTEXBUFFER:
7823 /* MSDN: When an application no longer holds a references to this interface, the interface will automatically be freed. */
7826 TRACE("Cleaning up stream pointers\n");
7828 for(streamNumber = 0; streamNumber < MAX_STREAMS; streamNumber ++){
7829 /* FINDOUT: should a warn be generated if were recording and updateStateBlock->streamSource is lost?
7830 FINDOUT: should changes.streamSource[StreamNumber] be set ?
7832 if (This->updateStateBlock != NULL ) { /* ==NULL when device is being destroyed */
7833 if ((IWineD3DResource *)This->updateStateBlock->streamSource[streamNumber] == resource) {
7834 FIXME("Vertex buffer released whlst bound to a state block stream %d\n", streamNumber);
7835 This->updateStateBlock->streamSource[streamNumber] = 0;
7836 /* Set changed flag? */
7839 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) */
7840 if ((IWineD3DResource *)This->stateBlock->streamSource[streamNumber] == resource) {
7841 TRACE("Vertex buffer released whlst bound to a state block stream %d\n", streamNumber);
7842 This->stateBlock->streamSource[streamNumber] = 0;
7845 #if 0 /* TODO: Manage internal tracking properly so that 'this shouldn't happen' */
7846 else { /* This shouldn't happen */
7847 FIXME("Calling application has released the device before relasing all the resources bound to the device\n");
7854 case WINED3DRTYPE_INDEXBUFFER:
7855 /* MSDN: When an application no longer holds a references to this interface, the interface will automatically be freed.*/
7856 if (This->updateStateBlock != NULL ) { /* ==NULL when device is being destroyed */
7857 if (This->updateStateBlock->pIndexData == (IWineD3DIndexBuffer *)resource) {
7858 This->updateStateBlock->pIndexData = NULL;
7861 if (This->stateBlock != NULL ) { /* ==NULL when device is being destroyed */
7862 if (This->stateBlock->pIndexData == (IWineD3DIndexBuffer *)resource) {
7863 This->stateBlock->pIndexData = NULL;
7869 FIXME("(%p) unknown resource type %p %u\n", This, resource, IWineD3DResource_GetType(resource));
7874 /* Remove the resoruce from the resourceStore */
7875 IWineD3DDeviceImpl_RemoveResource(iface, resource);
7877 TRACE("Resource released\n");
7881 /**********************************************************
7882 * IWineD3DDevice VTbl follows
7883 **********************************************************/
7885 const IWineD3DDeviceVtbl IWineD3DDevice_Vtbl =
7887 /*** IUnknown methods ***/
7888 IWineD3DDeviceImpl_QueryInterface,
7889 IWineD3DDeviceImpl_AddRef,
7890 IWineD3DDeviceImpl_Release,
7891 /*** IWineD3DDevice methods ***/
7892 IWineD3DDeviceImpl_GetParent,
7893 /*** Creation methods**/
7894 IWineD3DDeviceImpl_CreateVertexBuffer,
7895 IWineD3DDeviceImpl_CreateIndexBuffer,
7896 IWineD3DDeviceImpl_CreateStateBlock,
7897 IWineD3DDeviceImpl_CreateSurface,
7898 IWineD3DDeviceImpl_CreateTexture,
7899 IWineD3DDeviceImpl_CreateVolumeTexture,
7900 IWineD3DDeviceImpl_CreateVolume,
7901 IWineD3DDeviceImpl_CreateCubeTexture,
7902 IWineD3DDeviceImpl_CreateQuery,
7903 IWineD3DDeviceImpl_CreateAdditionalSwapChain,
7904 IWineD3DDeviceImpl_CreateVertexDeclaration,
7905 IWineD3DDeviceImpl_CreateVertexShader,
7906 IWineD3DDeviceImpl_CreatePixelShader,
7907 IWineD3DDeviceImpl_CreatePalette,
7908 /*** Odd functions **/
7909 IWineD3DDeviceImpl_Init3D,
7910 IWineD3DDeviceImpl_Uninit3D,
7911 IWineD3DDeviceImpl_EnumDisplayModes,
7912 IWineD3DDeviceImpl_EvictManagedResources,
7913 IWineD3DDeviceImpl_GetAvailableTextureMem,
7914 IWineD3DDeviceImpl_GetBackBuffer,
7915 IWineD3DDeviceImpl_GetCreationParameters,
7916 IWineD3DDeviceImpl_GetDeviceCaps,
7917 IWineD3DDeviceImpl_GetDirect3D,
7918 IWineD3DDeviceImpl_GetDisplayMode,
7919 IWineD3DDeviceImpl_SetDisplayMode,
7920 IWineD3DDeviceImpl_GetHWND,
7921 IWineD3DDeviceImpl_SetHWND,
7922 IWineD3DDeviceImpl_GetNumberOfSwapChains,
7923 IWineD3DDeviceImpl_GetRasterStatus,
7924 IWineD3DDeviceImpl_GetSwapChain,
7925 IWineD3DDeviceImpl_Reset,
7926 IWineD3DDeviceImpl_SetDialogBoxMode,
7927 IWineD3DDeviceImpl_SetCursorProperties,
7928 IWineD3DDeviceImpl_SetCursorPosition,
7929 IWineD3DDeviceImpl_ShowCursor,
7930 IWineD3DDeviceImpl_TestCooperativeLevel,
7931 IWineD3DDeviceImpl_EnumZBufferFormats,
7932 IWineD3DDeviceImpl_EnumTextureFormats,
7933 /*** Getters and setters **/
7934 IWineD3DDeviceImpl_SetClipPlane,
7935 IWineD3DDeviceImpl_GetClipPlane,
7936 IWineD3DDeviceImpl_SetClipStatus,
7937 IWineD3DDeviceImpl_GetClipStatus,
7938 IWineD3DDeviceImpl_SetCurrentTexturePalette,
7939 IWineD3DDeviceImpl_GetCurrentTexturePalette,
7940 IWineD3DDeviceImpl_SetDepthStencilSurface,
7941 IWineD3DDeviceImpl_GetDepthStencilSurface,
7942 IWineD3DDeviceImpl_SetFVF,
7943 IWineD3DDeviceImpl_GetFVF,
7944 IWineD3DDeviceImpl_SetGammaRamp,
7945 IWineD3DDeviceImpl_GetGammaRamp,
7946 IWineD3DDeviceImpl_SetIndices,
7947 IWineD3DDeviceImpl_GetIndices,
7948 IWineD3DDeviceImpl_SetLight,
7949 IWineD3DDeviceImpl_GetLight,
7950 IWineD3DDeviceImpl_SetLightEnable,
7951 IWineD3DDeviceImpl_GetLightEnable,
7952 IWineD3DDeviceImpl_SetMaterial,
7953 IWineD3DDeviceImpl_GetMaterial,
7954 IWineD3DDeviceImpl_SetNPatchMode,
7955 IWineD3DDeviceImpl_GetNPatchMode,
7956 IWineD3DDeviceImpl_SetPaletteEntries,
7957 IWineD3DDeviceImpl_GetPaletteEntries,
7958 IWineD3DDeviceImpl_SetPixelShader,
7959 IWineD3DDeviceImpl_GetPixelShader,
7960 IWineD3DDeviceImpl_SetPixelShaderConstantB,
7961 IWineD3DDeviceImpl_GetPixelShaderConstantB,
7962 IWineD3DDeviceImpl_SetPixelShaderConstantI,
7963 IWineD3DDeviceImpl_GetPixelShaderConstantI,
7964 IWineD3DDeviceImpl_SetPixelShaderConstantF,
7965 IWineD3DDeviceImpl_GetPixelShaderConstantF,
7966 IWineD3DDeviceImpl_SetRenderState,
7967 IWineD3DDeviceImpl_GetRenderState,
7968 IWineD3DDeviceImpl_SetRenderTarget,
7969 IWineD3DDeviceImpl_GetRenderTarget,
7970 IWineD3DDeviceImpl_SetFrontBackBuffers,
7971 IWineD3DDeviceImpl_SetSamplerState,
7972 IWineD3DDeviceImpl_GetSamplerState,
7973 IWineD3DDeviceImpl_SetScissorRect,
7974 IWineD3DDeviceImpl_GetScissorRect,
7975 IWineD3DDeviceImpl_SetSoftwareVertexProcessing,
7976 IWineD3DDeviceImpl_GetSoftwareVertexProcessing,
7977 IWineD3DDeviceImpl_SetStreamSource,
7978 IWineD3DDeviceImpl_GetStreamSource,
7979 IWineD3DDeviceImpl_SetStreamSourceFreq,
7980 IWineD3DDeviceImpl_GetStreamSourceFreq,
7981 IWineD3DDeviceImpl_SetTexture,
7982 IWineD3DDeviceImpl_GetTexture,
7983 IWineD3DDeviceImpl_SetTextureStageState,
7984 IWineD3DDeviceImpl_GetTextureStageState,
7985 IWineD3DDeviceImpl_SetTransform,
7986 IWineD3DDeviceImpl_GetTransform,
7987 IWineD3DDeviceImpl_SetVertexDeclaration,
7988 IWineD3DDeviceImpl_GetVertexDeclaration,
7989 IWineD3DDeviceImpl_SetVertexShader,
7990 IWineD3DDeviceImpl_GetVertexShader,
7991 IWineD3DDeviceImpl_SetVertexShaderConstantB,
7992 IWineD3DDeviceImpl_GetVertexShaderConstantB,
7993 IWineD3DDeviceImpl_SetVertexShaderConstantI,
7994 IWineD3DDeviceImpl_GetVertexShaderConstantI,
7995 IWineD3DDeviceImpl_SetVertexShaderConstantF,
7996 IWineD3DDeviceImpl_GetVertexShaderConstantF,
7997 IWineD3DDeviceImpl_SetViewport,
7998 IWineD3DDeviceImpl_GetViewport,
7999 IWineD3DDeviceImpl_MultiplyTransform,
8000 IWineD3DDeviceImpl_ValidateDevice,
8001 IWineD3DDeviceImpl_ProcessVertices,
8002 /*** State block ***/
8003 IWineD3DDeviceImpl_BeginStateBlock,
8004 IWineD3DDeviceImpl_EndStateBlock,
8005 /*** Scene management ***/
8006 IWineD3DDeviceImpl_BeginScene,
8007 IWineD3DDeviceImpl_EndScene,
8008 IWineD3DDeviceImpl_Present,
8009 IWineD3DDeviceImpl_Clear,
8011 IWineD3DDeviceImpl_DrawPrimitive,
8012 IWineD3DDeviceImpl_DrawIndexedPrimitive,
8013 IWineD3DDeviceImpl_DrawPrimitiveUP,
8014 IWineD3DDeviceImpl_DrawIndexedPrimitiveUP,
8015 IWineD3DDeviceImpl_DrawPrimitiveStrided,
8016 IWineD3DDeviceImpl_DrawRectPatch,
8017 IWineD3DDeviceImpl_DrawTriPatch,
8018 IWineD3DDeviceImpl_DeletePatch,
8019 IWineD3DDeviceImpl_ColorFill,
8020 IWineD3DDeviceImpl_UpdateTexture,
8021 IWineD3DDeviceImpl_UpdateSurface,
8022 IWineD3DDeviceImpl_CopyRects,
8023 IWineD3DDeviceImpl_StretchRect,
8024 IWineD3DDeviceImpl_GetRenderTargetData,
8025 IWineD3DDeviceImpl_GetFrontBufferData,
8026 /*** Internal use IWineD3DDevice methods ***/
8027 IWineD3DDeviceImpl_SetupTextureStates,
8028 /*** object tracking ***/
8029 IWineD3DDeviceImpl_ResourceReleased
8033 const DWORD SavedPixelStates_R[NUM_SAVEDPIXELSTATES_R] = {
8034 WINED3DRS_ALPHABLENDENABLE ,
8035 WINED3DRS_ALPHAFUNC ,
8036 WINED3DRS_ALPHAREF ,
8037 WINED3DRS_ALPHATESTENABLE ,
8039 WINED3DRS_COLORWRITEENABLE ,
8040 WINED3DRS_DESTBLEND ,
8041 WINED3DRS_DITHERENABLE ,
8042 WINED3DRS_FILLMODE ,
8043 WINED3DRS_FOGDENSITY ,
8045 WINED3DRS_FOGSTART ,
8046 WINED3DRS_LASTPIXEL ,
8047 WINED3DRS_SHADEMODE ,
8048 WINED3DRS_SRCBLEND ,
8049 WINED3DRS_STENCILENABLE ,
8050 WINED3DRS_STENCILFAIL ,
8051 WINED3DRS_STENCILFUNC ,
8052 WINED3DRS_STENCILMASK ,
8053 WINED3DRS_STENCILPASS ,
8054 WINED3DRS_STENCILREF ,
8055 WINED3DRS_STENCILWRITEMASK ,
8056 WINED3DRS_STENCILZFAIL ,
8057 WINED3DRS_TEXTUREFACTOR ,
8068 WINED3DRS_ZWRITEENABLE
8071 const DWORD SavedPixelStates_T[NUM_SAVEDPIXELSTATES_T] = {
8072 WINED3DTSS_ADDRESSW ,
8073 WINED3DTSS_ALPHAARG0 ,
8074 WINED3DTSS_ALPHAARG1 ,
8075 WINED3DTSS_ALPHAARG2 ,
8076 WINED3DTSS_ALPHAOP ,
8077 WINED3DTSS_BUMPENVLOFFSET ,
8078 WINED3DTSS_BUMPENVLSCALE ,
8079 WINED3DTSS_BUMPENVMAT00 ,
8080 WINED3DTSS_BUMPENVMAT01 ,
8081 WINED3DTSS_BUMPENVMAT10 ,
8082 WINED3DTSS_BUMPENVMAT11 ,
8083 WINED3DTSS_COLORARG0 ,
8084 WINED3DTSS_COLORARG1 ,
8085 WINED3DTSS_COLORARG2 ,
8086 WINED3DTSS_COLOROP ,
8087 WINED3DTSS_RESULTARG ,
8088 WINED3DTSS_TEXCOORDINDEX ,
8089 WINED3DTSS_TEXTURETRANSFORMFLAGS
8092 const DWORD SavedPixelStates_S[NUM_SAVEDPIXELSTATES_S] = {
8093 WINED3DSAMP_ADDRESSU ,
8094 WINED3DSAMP_ADDRESSV ,
8095 WINED3DSAMP_ADDRESSW ,
8096 WINED3DSAMP_BORDERCOLOR ,
8097 WINED3DSAMP_MAGFILTER ,
8098 WINED3DSAMP_MINFILTER ,
8099 WINED3DSAMP_MIPFILTER ,
8100 WINED3DSAMP_MIPMAPLODBIAS ,
8101 WINED3DSAMP_MAXMIPLEVEL ,
8102 WINED3DSAMP_MAXANISOTROPY ,
8103 WINED3DSAMP_SRGBTEXTURE ,
8104 WINED3DSAMP_ELEMENTINDEX
8107 const DWORD SavedVertexStates_R[NUM_SAVEDVERTEXSTATES_R] = {
8109 WINED3DRS_AMBIENTMATERIALSOURCE ,
8110 WINED3DRS_CLIPPING ,
8111 WINED3DRS_CLIPPLANEENABLE ,
8112 WINED3DRS_COLORVERTEX ,
8113 WINED3DRS_DIFFUSEMATERIALSOURCE ,
8114 WINED3DRS_EMISSIVEMATERIALSOURCE ,
8115 WINED3DRS_FOGDENSITY ,
8117 WINED3DRS_FOGSTART ,
8118 WINED3DRS_FOGTABLEMODE ,
8119 WINED3DRS_FOGVERTEXMODE ,
8120 WINED3DRS_INDEXEDVERTEXBLENDENABLE ,
8121 WINED3DRS_LIGHTING ,
8122 WINED3DRS_LOCALVIEWER ,
8123 WINED3DRS_MULTISAMPLEANTIALIAS ,
8124 WINED3DRS_MULTISAMPLEMASK ,
8125 WINED3DRS_NORMALIZENORMALS ,
8126 WINED3DRS_PATCHEDGESTYLE ,
8127 WINED3DRS_POINTSCALE_A ,
8128 WINED3DRS_POINTSCALE_B ,
8129 WINED3DRS_POINTSCALE_C ,
8130 WINED3DRS_POINTSCALEENABLE ,
8131 WINED3DRS_POINTSIZE ,
8132 WINED3DRS_POINTSIZE_MAX ,
8133 WINED3DRS_POINTSIZE_MIN ,
8134 WINED3DRS_POINTSPRITEENABLE ,
8135 WINED3DRS_RANGEFOGENABLE ,
8136 WINED3DRS_SPECULARMATERIALSOURCE ,
8137 WINED3DRS_TWEENFACTOR ,
8138 WINED3DRS_VERTEXBLEND
8141 const DWORD SavedVertexStates_T[NUM_SAVEDVERTEXSTATES_T] = {
8142 WINED3DTSS_TEXCOORDINDEX ,
8143 WINED3DTSS_TEXTURETRANSFORMFLAGS
8146 const DWORD SavedVertexStates_S[NUM_SAVEDVERTEXSTATES_S] = {
8147 WINED3DSAMP_DMAPOFFSET