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 if (NULL == vshader && NULL == pshader) {
286 /* No pixel or vertex shader specified */
287 This->stateBlock->shaderPrgId = 0;
291 ptr = list_head( &This->glsl_shader_progs );
293 /* At least one program exists - see if it matches our ps/vs combination */
294 curLink = LIST_ENTRY( ptr, struct glsl_shader_prog_link, entry );
295 if (vshader == curLink->vertexShader && pshader == curLink->pixelShader) {
296 /* Existing Program found, use it */
297 TRACE_(d3d_shader)("Found existing program (%u) for this vertex/pixel shader combination\n",
299 This->stateBlock->shaderPrgId = curLink->programId;
302 /* This isn't the entry we need - try the next one */
303 ptr = list_next( &This->glsl_shader_progs, ptr );
306 /* If we get to this point, then no matching program exists, so we create one */
307 programId = GL_EXTCALL(glCreateProgramObjectARB());
308 TRACE_(d3d_shader)("Created new GLSL shader program %u\n", programId);
309 This->stateBlock->shaderPrgId = programId;
311 /* Allocate a new link for the list of programs */
312 newLink = HeapAlloc(GetProcessHeap(), 0, sizeof(struct glsl_shader_prog_link));
313 newLink->programId = programId;
315 /* Attach GLSL vshader */
316 if (NULL != vshader && wined3d_settings.vs_selected_mode == SHADER_GLSL) {
318 int max_attribs = 16; /* TODO: Will this always be the case? It is at the moment... */
321 TRACE("Attaching vertex shader to GLSL program\n");
322 attach_glsl_shader(iface, (IWineD3DBaseShader*)vshader);
324 /* Bind vertex attributes to a corresponding index number to match
325 * the same index numbers as ARB_vertex_programs (makes loading
326 * vertex attributes simpler). With this method, we can use the
327 * exact same code to load the attributes later for both ARB and
330 * We have to do this here because we need to know the Program ID
331 * in order to make the bindings work, and it has to be done prior
332 * to linking the GLSL program. */
333 for (i = 0; i < max_attribs; ++i) {
334 snprintf(tmp_name, sizeof(tmp_name), "attrib%i", i);
335 GL_EXTCALL(glBindAttribLocationARB(programId, i, tmp_name));
337 checkGLcall("glBindAttribLocationARB");
338 newLink->vertexShader = vshader;
341 /* Attach GLSL pshader */
342 if (NULL != pshader && wined3d_settings.ps_selected_mode == SHADER_GLSL) {
343 TRACE("Attaching pixel shader to GLSL program\n");
344 attach_glsl_shader(iface, (IWineD3DBaseShader*)pshader);
345 newLink->pixelShader = pshader;
348 /* Link the program */
349 TRACE_(d3d_shader)("Linking GLSL shader program %u\n", programId);
350 GL_EXTCALL(glLinkProgramARB(programId));
351 print_glsl_info_log(&GLINFO_LOCATION, programId);
352 list_add_head( &This->glsl_shader_progs, &newLink->entry);
356 /** Detach the GLSL pixel or vertex shader object from the shader program */
357 static void detach_glsl_shader(IWineD3DDevice *iface, GLhandleARB shaderObj, GLhandleARB programId) {
359 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
361 if (shaderObj != 0 && programId != 0) {
362 TRACE_(d3d_shader)("Detaching GLSL shader object %u from program %u\n", shaderObj, programId);
363 GL_EXTCALL(glDetachObjectARB(programId, shaderObj));
364 checkGLcall("glDetachObjectARB");
368 /** Delete a GLSL shader program */
369 static void delete_glsl_shader_program(IWineD3DDevice *iface, GLhandleARB obj) {
371 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
374 TRACE_(d3d_shader)("Deleting GLSL shader program %u\n", obj);
375 GL_EXTCALL(glDeleteObjectARB(obj));
376 checkGLcall("glDeleteObjectARB");
380 /** Delete the list of linked programs this shader is associated with.
381 * Also at this point, check to see if there are any objects left attached
382 * to each GLSL program. If not, delete the GLSL program object.
383 * This will be run when a device is released. */
384 static void delete_glsl_shader_list(IWineD3DDevice* iface) {
386 struct list *ptr = NULL;
387 struct glsl_shader_prog_link *curLink = NULL;
388 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
392 GLhandleARB objList[2]; /* There should never be more than 2 objects attached
393 (one pixel shader and one vertex shader at most) */
395 ptr = list_head( &This->glsl_shader_progs );
397 /* First, get the current item,
398 * save the link to the next pointer,
399 * detach and delete shader objects,
400 * then de-allocate the list item's memory */
401 curLink = LIST_ENTRY( ptr, struct glsl_shader_prog_link, entry );
402 ptr = list_next( &This->glsl_shader_progs, ptr );
404 /* See if this object is still attached to the program - it may have been detached already */
405 GL_EXTCALL(glGetAttachedObjectsARB(curLink->programId, 2, &numAttached, objList));
406 TRACE_(d3d_shader)("%i GLSL objects are currently attached to program %u\n", numAttached, curLink->programId);
407 for (i = 0; i < numAttached; i++) {
408 detach_glsl_shader(iface, objList[i], curLink->programId);
411 delete_glsl_shader_program(iface, curLink->programId);
413 /* Free the memory for this list item */
414 HeapFree(GetProcessHeap(), 0, curLink);
419 /* Apply the current values to the specified texture stage */
420 static void WINAPI IWineD3DDeviceImpl_SetupTextureStates(IWineD3DDevice *iface, DWORD Sampler, DWORD texture_idx, DWORD Flags) {
421 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
429 /* In addition, IDirect3DDevice9::SetSamplerState will now be used for filtering, tiling,
430 clamping, MIPLOD, etc. This will work for up to 16 samplers.
433 if (Sampler >= GL_LIMITS(sampler_stages)) {
434 FIXME("Trying to set the state of more samplers %ld than are supported %d by this openGL implementation\n", Sampler, GL_LIMITS(sampler_stages));
437 VTRACE(("Activating appropriate texture state %ld\n", Sampler));
438 if (GL_SUPPORT(ARB_MULTITEXTURE)) {
440 GL_EXTCALL(glActiveTextureARB(GL_TEXTURE0_ARB + texture_idx));
441 checkGLcall("glActiveTextureARB");
443 /* Could we use bindTexture and then apply the states instead of GLACTIVETEXTURE */
444 } else if (Sampler > 0) {
445 FIXME("Program using multiple concurrent textures which this opengl implementation doesn't support\n");
449 /* TODO: change this to a lookup table
450 LOOKUP_TEXTURE_STATES lists all texture states that should be applied.
451 LOOKUP_CONTEXT_SATES list all context applicable states that can be applied
452 etc.... it's a lot cleaner, quicker and possibly easier to maintain than running a switch and setting a skip flag...
453 especially when there are a number of groups of states. */
455 TRACE("-----------------------> Updating the texture at Sampler %ld to have new texture state information\n", Sampler);
457 /* 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 */
458 #define APPLY_STATE(_state) IWineD3DDeviceImpl_ApplyTextureUnitState(iface, Sampler, _state)
459 /* these are the only two supported states that need to be applied */
460 APPLY_STATE(WINED3DTSS_TEXCOORDINDEX);
461 APPLY_STATE(WINED3DTSS_TEXTURETRANSFORMFLAGS);
462 #if 0 /* not supported at the moment */
463 APPLY_STATE(WINED3DTSS_BUMPENVMAT00);
464 APPLY_STATE(WINED3DTSS_BUMPENVMAT01);
465 APPLY_STATE(WINED3DTSS_BUMPENVMAT10);
466 APPLY_STATE(WINED3DTSS_BUMPENVMAT11);
467 APPLY_STATE(WINED3DTSS_BUMPENVLSCALE);
468 APPLY_STATE(WINED3DTSS_BUMPENVLOFFSET);
469 APPLY_STATE(WINED3DTSS_RESULTARG);
470 APPLY_STATE(WINED3DTSS_CONSTANT);
472 /* a quick sanity check in case someone forgot to update this function */
473 if (WINED3D_HIGHEST_TEXTURE_STATE > WINED3DTSS_CONSTANT) {
474 FIXME("(%p) : There are more texture states than expected, update device.c to match\n", This);
478 /* apply any sampler states that always need applying */
479 if (GL_SUPPORT(EXT_TEXTURE_LOD_BIAS)) {
480 tmpvalue.d = This->stateBlock->samplerState[Sampler][WINED3DSAMP_MIPMAPLODBIAS];
481 glTexEnvf(GL_TEXTURE_FILTER_CONTROL_EXT,
482 GL_TEXTURE_LOD_BIAS_EXT,
484 checkGLcall("glTexEnvi GL_TEXTURE_LOD_BIAS_EXT ...");
487 /* Note the D3DRS value applies to all textures, but GL has one
488 * per texture, so apply it now ready to be used!
490 D3DCOLORTOGLFLOAT4(This->stateBlock->renderState[WINED3DRS_TEXTUREFACTOR], col);
491 /* Set the default alpha blend color */
492 if (GL_SUPPORT(ARB_IMAGING)) {
493 GL_EXTCALL(glBlendColor(col[0], col[1], col[2], col[3]));
494 checkGLcall("glBlendColor");
496 WARN("Unsupported in local OpenGL implementation: glBlendColor\n");
499 D3DCOLORTOGLFLOAT4(This->stateBlock->renderState[WINED3DRS_TEXTUREFACTOR], col);
500 glTexEnvfv(GL_TEXTURE_ENV, GL_TEXTURE_ENV_COLOR, &col[0]);
501 checkGLcall("glTexEnvfv(GL_TEXTURE_ENV, GL_TEXTURE_ENV_COLOR, color);");
503 /* TODO: NV_POINT_SPRITE */
504 if (GL_SUPPORT(ARB_POINT_SPRITE)) {
505 if (This->stateBlock->renderState[WINED3DRS_POINTSPRITEENABLE] != FALSE) {
506 /* Doesn't work with GL_POINT_SMOOTH on on my ATI 9600, but then ATI drivers are buggered! */
507 glDisable(GL_POINT_SMOOTH);
509 /* Centre the texture on the vertex */
510 VTRACE(("glTexEnvf( GL_POINT_SPRITE_ARB, GL_COORD_REPLACE_ARB, GL_TRUE)\n"));
511 glTexEnvf( GL_POINT_SPRITE_ARB, GL_COORD_REPLACE_ARB, GL_TRUE);
513 VTRACE(("glTexEnvf( GL_POINT_SPRITE_ARB, GL_COORD_REPLACE_ARB, GL_TRUE)\n"));
514 glTexEnvf( GL_POINT_SPRITE_ARB, GL_COORD_REPLACE_ARB, GL_TRUE);
515 checkGLcall("glTexEnvf(...)");
516 VTRACE(("glEnable( GL_POINT_SPRITE_ARB )\n"));
517 glEnable( GL_POINT_SPRITE_ARB );
518 checkGLcall("glEnable(...)");
520 VTRACE(("glDisable( GL_POINT_SPRITE_ARB )\n"));
521 glDisable( GL_POINT_SPRITE_ARB );
522 checkGLcall("glEnable(...)");
526 TRACE("-----------------------> Updated the texture at Sampler %ld to have new texture state information\n", Sampler);
529 /**********************************************************
530 * IUnknown parts follows
531 **********************************************************/
533 static HRESULT WINAPI IWineD3DDeviceImpl_QueryInterface(IWineD3DDevice *iface,REFIID riid,LPVOID *ppobj)
535 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
537 TRACE("(%p)->(%s,%p)\n",This,debugstr_guid(riid),ppobj);
538 if (IsEqualGUID(riid, &IID_IUnknown)
539 || IsEqualGUID(riid, &IID_IWineD3DBase)
540 || IsEqualGUID(riid, &IID_IWineD3DDevice)) {
541 IUnknown_AddRef(iface);
546 return E_NOINTERFACE;
549 static ULONG WINAPI IWineD3DDeviceImpl_AddRef(IWineD3DDevice *iface) {
550 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
551 ULONG refCount = InterlockedIncrement(&This->ref);
553 TRACE("(%p) : AddRef increasing from %ld\n", This, refCount - 1);
557 static ULONG WINAPI IWineD3DDeviceImpl_Release(IWineD3DDevice *iface) {
558 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
559 ULONG refCount = InterlockedDecrement(&This->ref);
561 TRACE("(%p) : Releasing from %ld\n", This, refCount + 1);
564 /* TODO: Clean up all the surfaces and textures! */
565 /* NOTE: You must release the parent if the object was created via a callback
566 ** ***************************/
568 /* Delete any GLSL shader programs that may exist */
569 if (wined3d_settings.vs_selected_mode == SHADER_GLSL ||
570 wined3d_settings.ps_selected_mode == SHADER_GLSL)
571 delete_glsl_shader_list(iface);
573 /* Release the update stateblock */
574 if(IWineD3DStateBlock_Release((IWineD3DStateBlock *)This->updateStateBlock) > 0){
575 if(This->updateStateBlock != This->stateBlock)
576 FIXME("(%p) Something's still holding the Update stateblock\n",This);
578 This->updateStateBlock = NULL;
579 { /* because were not doing proper internal refcounts releasing the primary state block
580 causes recursion with the extra checks in ResourceReleased, to avoid this we have
581 to set this->stateBlock = NULL; first */
582 IWineD3DStateBlock *stateBlock = (IWineD3DStateBlock *)This->stateBlock;
583 This->stateBlock = NULL;
585 /* Release the stateblock */
586 if(IWineD3DStateBlock_Release(stateBlock) > 0){
587 FIXME("(%p) Something's still holding the Update stateblock\n",This);
591 if (This->resources != NULL ) {
592 FIXME("(%p) Device released with resources still bound, acceptable but unexpected\n", This);
593 dumpResources(This->resources);
597 IWineD3D_Release(This->wineD3D);
598 This->wineD3D = NULL;
599 HeapFree(GetProcessHeap(), 0, This);
600 TRACE("Freed device %p\n", This);
606 /**********************************************************
607 * IWineD3DDevice implementation follows
608 **********************************************************/
609 static HRESULT WINAPI IWineD3DDeviceImpl_GetParent(IWineD3DDevice *iface, IUnknown **pParent) {
610 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
611 *pParent = This->parent;
612 IUnknown_AddRef(This->parent);
616 static void CreateVBO(IWineD3DVertexBufferImpl *object) {
617 IWineD3DDeviceImpl *This = object->resource.wineD3DDevice; /* Needed for GL_EXTCALL */
618 GLenum error, glUsage;
619 DWORD vboUsage = object->resource.usage;
620 TRACE("Creating an OpenGL vertex buffer object for IWineD3DVertexBuffer %p\n", object);
623 /* Make sure that the gl error is cleared. Do not use checkGLcall
624 * here because checkGLcall just prints a fixme and continues. However,
625 * if an error during VBO creation occurs we can fall back to non-vbo operation
626 * with full functionality(but performance loss)
628 while(glGetError() != GL_NO_ERROR);
630 /* Basically the FVF parameter passed to CreateVertexBuffer is no good
631 * It is the FVF set with IWineD3DDevice::SetFVF or the Vertex Declaration set with
632 * IWineD3DDevice::SetVertexDeclaration that decides how the vertices in the buffer
633 * look like. This means that on each DrawPrimitive call the vertex buffer has to be verified
634 * to check if the rhw and color values are in the correct format.
637 GL_EXTCALL(glGenBuffersARB(1, &object->vbo));
638 error = glGetError();
639 if(object->vbo == 0 || error != GL_NO_ERROR) {
640 WARN("Failed to create a VBO with error %d\n", error);
644 GL_EXTCALL(glBindBufferARB(GL_ARRAY_BUFFER_ARB, object->vbo));
645 error = glGetError();
646 if(error != GL_NO_ERROR) {
647 WARN("Failed to bind the VBO, error %d\n", error);
651 /* Transformed vertices are horribly inflexible. If the app specifies an
652 * vertex buffer with transformed vertices in default pool without DYNAMIC
653 * usage assume DYNAMIC usage and print a warning. The app will have to update
654 * the vertices regularily for them to be useful
656 if(((object->fvf & D3DFVF_POSITION_MASK) == D3DFVF_XYZRHW) &&
657 !(vboUsage & WINED3DUSAGE_DYNAMIC)) {
658 WARN("Application creates a vertex buffer holding transformed vertices which doesn't specify dynamic usage\n");
659 vboUsage |= WINED3DUSAGE_DYNAMIC;
662 /* Don't use static, because dx apps tend to update the buffer
663 * quite often even if they specify 0 usage
665 switch(vboUsage & (D3DUSAGE_WRITEONLY | D3DUSAGE_DYNAMIC) ) {
666 case D3DUSAGE_WRITEONLY | D3DUSAGE_DYNAMIC:
667 TRACE("Gl usage = GL_STREAM_DRAW\n");
668 glUsage = GL_STREAM_DRAW_ARB;
670 case D3DUSAGE_WRITEONLY:
671 TRACE("Gl usage = GL_STATIC_DRAW\n");
672 glUsage = GL_DYNAMIC_DRAW_ARB;
674 case D3DUSAGE_DYNAMIC:
675 TRACE("Gl usage = GL_STREAM_COPY\n");
676 glUsage = GL_STREAM_COPY_ARB;
679 TRACE("Gl usage = GL_STATIC_COPY\n");
680 glUsage = GL_DYNAMIC_COPY_ARB;
684 /* Reserve memory for the buffer. The amount of data won't change
685 * so we are safe with calling glBufferData once with a NULL ptr and
686 * calling glBufferSubData on updates
688 GL_EXTCALL(glBufferDataARB(GL_ARRAY_BUFFER_ARB, object->resource.size, NULL, glUsage));
689 error = glGetError();
690 if(error != GL_NO_ERROR) {
691 WARN("glBufferDataARB failed with error %d\n", error);
699 /* Clean up all vbo init, but continue because we can work without a vbo :-) */
700 FIXME("Failed to create a vertex buffer object. Continuing, but performance issues can occur\n");
701 if(object->vbo) GL_EXTCALL(glDeleteBuffersARB(1, &object->vbo));
707 static HRESULT WINAPI IWineD3DDeviceImpl_CreateVertexBuffer(IWineD3DDevice *iface, UINT Size, DWORD Usage,
708 DWORD FVF, WINED3DPOOL Pool, IWineD3DVertexBuffer** ppVertexBuffer, HANDLE *sharedHandle,
710 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
711 IWineD3DVertexBufferImpl *object;
712 WINED3DFORMAT Format = WINED3DFMT_VERTEXDATA; /* Dummy format for now */
713 int dxVersion = ( (IWineD3DImpl *) This->wineD3D)->dxVersion;
715 D3DCREATERESOURCEOBJECTINSTANCE(object, VertexBuffer, WINED3DRTYPE_VERTEXBUFFER, Size)
717 TRACE("(%p) : Size=%d, Usage=%ld, FVF=%lx, Pool=%d - Memory@%p, Iface@%p\n", This, Size, Usage, FVF, Pool, object->resource.allocatedMemory, object);
718 *ppVertexBuffer = (IWineD3DVertexBuffer *)object;
720 if(Size == 0) return WINED3DERR_INVALIDCALL;
722 if (Pool == WINED3DPOOL_DEFAULT ) { /* Allocate some system memory for now */
723 object->resource.allocatedMemory = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, object->resource.size);
727 /* Observations show that drawStridedSlow is faster on dynamic VBs than converting +
728 * drawStridedFast (half-life 2).
730 * Basically converting the vertices in the buffer is quite expensive, and observations
731 * show that drawStridedSlow is faster than converting + uploading + drawStridedFast.
732 * Therefore do not create a VBO for WINED3DUSAGE_DYNAMIC buffers.
734 * Direct3D7 has another problem: Its vertexbuffer api doesn't offer a way to specify
735 * the range of vertices beeing locked, so each lock will require the whole buffer to be transformed.
736 * Moreover geometry data in dx7 is quite simple, so drawStridedSlow isn't a big hit. A plus
737 * is that the vertex buffers fvf can be trusted in dx7. So only create non-converted vbos for
739 * There is a IDirect3DVertexBuffer7::Optimize call after which the buffer can't be locked any
740 * more. In this call we can convert dx7 buffers too.
742 conv = ((FVF & D3DFVF_POSITION_MASK) == D3DFVF_XYZRHW ) || (FVF & (D3DFVF_DIFFUSE | D3DFVF_SPECULAR));
743 if( GL_SUPPORT(ARB_VERTEX_BUFFER_OBJECT) && Pool != WINED3DPOOL_SYSTEMMEM && !(Usage & WINED3DUSAGE_DYNAMIC) &&
744 (dxVersion > 7 || !conv) ) {
747 /* DX7 buffers can be locked directly into the VBO(no conversion, see above */
748 if(dxVersion == 7 && object->vbo) {
749 HeapFree(GetProcessHeap(), 0, object->resource.allocatedMemory);
750 object->resource.allocatedMemory = NULL;
757 static HRESULT WINAPI IWineD3DDeviceImpl_CreateIndexBuffer(IWineD3DDevice *iface, UINT Length, DWORD Usage,
758 WINED3DFORMAT Format, WINED3DPOOL Pool, IWineD3DIndexBuffer** ppIndexBuffer,
759 HANDLE *sharedHandle, IUnknown *parent) {
760 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
761 IWineD3DIndexBufferImpl *object;
762 TRACE("(%p) Creating index buffer\n", This);
764 /* Allocate the storage for the device */
765 D3DCREATERESOURCEOBJECTINSTANCE(object,IndexBuffer,WINED3DRTYPE_INDEXBUFFER, Length)
768 if (Pool == WINED3DPOOL_DEFAULT ) { /* Allocate some system memory for now */
769 object->resource.allocatedMemory = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,object->resource.size);
772 TRACE("(%p) : Len=%d, Use=%lx, Format=(%u,%s), Pool=%d - Memory@%p, Iface@%p\n", This, Length, Usage, Format,
773 debug_d3dformat(Format), Pool, object, object->resource.allocatedMemory);
774 *ppIndexBuffer = (IWineD3DIndexBuffer *) object;
779 static HRESULT WINAPI IWineD3DDeviceImpl_CreateStateBlock(IWineD3DDevice* iface, WINED3DSTATEBLOCKTYPE Type, IWineD3DStateBlock** ppStateBlock, IUnknown *parent) {
781 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
782 IWineD3DStateBlockImpl *object;
785 D3DCREATEOBJECTINSTANCE(object, StateBlock)
786 object->blockType = Type;
788 /* Special case - Used during initialization to produce a placeholder stateblock
789 so other functions called can update a state block */
790 if (Type == WINED3DSBT_INIT) {
791 /* Don't bother increasing the reference count otherwise a device will never
792 be freed due to circular dependencies */
796 /* Otherwise, might as well set the whole state block to the appropriate values */
797 if ( This->stateBlock != NULL) {
798 memcpy(object, This->stateBlock, sizeof(IWineD3DStateBlockImpl));
800 memset(object->streamFreq, 1, sizeof(object->streamFreq));
803 /* Reset the ref and type after kludging it */
804 object->wineD3DDevice = This;
806 object->blockType = Type;
808 TRACE("Updating changed flags appropriate for type %d\n", Type);
810 if (Type == WINED3DSBT_ALL) {
812 TRACE("ALL => Pretend everything has changed\n");
813 memset(&object->changed, TRUE, sizeof(This->stateBlock->changed));
814 } else if (Type == WINED3DSBT_PIXELSTATE) {
816 TRACE("PIXELSTATE => Pretend all pixel shates have changed\n");
817 memset(&object->changed, FALSE, sizeof(This->stateBlock->changed));
819 object->changed.pixelShader = TRUE;
821 /* Pixel Shader Constants */
822 for (i = 0; i < MAX_PSHADER_CONSTANTS; ++i) {
823 object->changed.pixelShaderConstantsF[i] = TRUE;
824 object->changed.pixelShaderConstantsB[i] = TRUE;
825 object->changed.pixelShaderConstantsI[i] = TRUE;
827 for (i = 0; i < NUM_SAVEDPIXELSTATES_R; i++) {
828 object->changed.renderState[SavedPixelStates_R[i]] = TRUE;
830 for (j = 0; j < GL_LIMITS(texture_stages); j++) {
831 for (i = 0; i < NUM_SAVEDPIXELSTATES_T; i++) {
832 object->changed.textureState[j][SavedPixelStates_T[i]] = TRUE;
835 for (j = 0 ; j < 16; j++) {
836 for (i =0; i < NUM_SAVEDPIXELSTATES_S;i++) {
838 object->changed.samplerState[j][SavedPixelStates_S[i]] = TRUE;
842 } else if (Type == WINED3DSBT_VERTEXSTATE) {
844 TRACE("VERTEXSTATE => Pretend all vertex shates have changed\n");
845 memset(&object->changed, FALSE, sizeof(This->stateBlock->changed));
847 object->changed.vertexShader = TRUE;
849 /* Vertex Shader Constants */
850 for (i = 0; i < MAX_VSHADER_CONSTANTS; ++i) {
851 object->changed.vertexShaderConstantsF[i] = TRUE;
852 object->changed.vertexShaderConstantsB[i] = TRUE;
853 object->changed.vertexShaderConstantsI[i] = TRUE;
855 for (i = 0; i < NUM_SAVEDVERTEXSTATES_R; i++) {
856 object->changed.renderState[SavedVertexStates_R[i]] = TRUE;
858 for (j = 0; j < GL_LIMITS(texture_stages); j++) {
859 for (i = 0; i < NUM_SAVEDVERTEXSTATES_T; i++) {
860 object->changed.textureState[j][SavedVertexStates_T[i]] = TRUE;
863 for (j = 0 ; j < 16; j++){
864 for (i =0; i < NUM_SAVEDVERTEXSTATES_S;i++) {
865 object->changed.samplerState[j][SavedVertexStates_S[i]] = TRUE;
869 /* Duplicate light chain */
871 PLIGHTINFOEL *src = NULL;
872 PLIGHTINFOEL *dst = NULL;
873 PLIGHTINFOEL *newEl = NULL;
874 src = This->stateBlock->lights;
875 object->lights = NULL;
879 newEl = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(PLIGHTINFOEL));
880 if (newEl == NULL) return WINED3DERR_OUTOFVIDEOMEMORY;
881 memcpy(newEl, src, sizeof(PLIGHTINFOEL));
883 newEl->changed = TRUE;
884 newEl->enabledChanged = TRUE;
886 object->lights = newEl;
897 FIXME("Unrecognized state block type %d\n", Type);
900 TRACE("(%p) returning token (ptr to stateblock) of %p\n", This, object);
905 /* ************************************
907 [in] Render targets are not lockable unless the application specifies TRUE for Lockable. Note that lockable render targets reduce performance on some graphics hardware.
910 [in] Set this flag to TRUE to enable z-buffer discarding, and FALSE otherwise.
912 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.
914 ******************************** */
916 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) {
917 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
918 IWineD3DSurfaceImpl *object; /*NOTE: impl ref allowed since this is a create function */
919 unsigned int pow2Width, pow2Height;
920 unsigned int Size = 1;
921 const PixelFormatDesc *tableEntry = getFormatDescEntry(Format);
922 TRACE("(%p) Create surface\n",This);
924 /** FIXME: Check ranges on the inputs are valid
927 * [in] Quality level. The valid range is between zero and one less than the level
928 * returned by pQualityLevels used by IDirect3D9::CheckDeviceMultiSampleType.
929 * Passing a larger value returns the error WINED3DERR_INVALIDCALL. The MultisampleQuality
930 * values of paired render targets, depth stencil surfaces, and the MultiSample type
932 *******************************/
937 * [in] Set this flag to TRUE to enable z-buffer discarding, and FALSE otherwise.
939 * If this flag is set, the contents of the depth stencil buffer will be
940 * invalid after calling either IDirect3DDevice9::Present or * IDirect3DDevice9::SetDepthStencilSurface
941 * with a different depth surface.
943 *This flag has the same behavior as the constant, D3DPRESENTFLAG_DISCARD_DEPTHSTENCIL, in D3DPRESENTFLAG.
944 ***************************/
946 if(MultisampleQuality < 0) {
947 FIXME("Invalid multisample level %ld\n", MultisampleQuality);
948 return WINED3DERR_INVALIDCALL; /* TODO: Check that this is the case! */
951 if(MultisampleQuality > 0) {
952 FIXME("MultisampleQuality set to %ld, substituting 0\n", MultisampleQuality);
953 MultisampleQuality=0;
956 /** FIXME: Check that the format is supported
958 *******************************/
960 /* Non-power2 support */
962 /* Find the nearest pow2 match */
963 pow2Width = pow2Height = 1;
964 while (pow2Width < Width) pow2Width <<= 1;
965 while (pow2Height < Height) pow2Height <<= 1;
967 if (pow2Width > Width || pow2Height > Height) {
968 /** TODO: add support for non power two compressed textures (OpenGL 2 provices support for * non-power-two textures gratis) **/
969 if (Format == WINED3DFMT_DXT1 || Format == WINED3DFMT_DXT2 || Format == WINED3DFMT_DXT3
970 || Format == WINED3DFMT_DXT4 || Format == WINED3DFMT_DXT5) {
971 FIXME("(%p) Compressed non-power-two textures are not supported w(%d) h(%d)\n",
972 This, Width, Height);
973 return WINED3DERR_NOTAVAILABLE;
977 /** DXTn mipmaps use the same number of 'levels' down to eg. 8x1, but since
978 * it is based around 4x4 pixel blocks it requires padding, so allocate enough
980 *********************************/
981 if (WINED3DFMT_UNKNOWN == Format) {
983 } else if (Format == WINED3DFMT_DXT1) {
984 /* DXT1 is half byte per pixel */
985 Size = ((max(pow2Width,4) * tableEntry->bpp) * max(pow2Height,4)) >> 1;
987 } else if (Format == WINED3DFMT_DXT2 || Format == WINED3DFMT_DXT3 ||
988 Format == WINED3DFMT_DXT4 || Format == WINED3DFMT_DXT5) {
989 Size = ((max(pow2Width,4) * tableEntry->bpp) * max(pow2Height,4));
991 Size = (pow2Width * tableEntry->bpp) * pow2Height;
994 /** Create and initialise the surface resource **/
995 D3DCREATERESOURCEOBJECTINSTANCE(object,Surface,WINED3DRTYPE_SURFACE, Size)
996 /* "Standalone" surface */
997 IWineD3DSurface_SetContainer((IWineD3DSurface *)object, NULL);
999 object->currentDesc.Width = Width;
1000 object->currentDesc.Height = Height;
1001 object->currentDesc.MultiSampleType = MultiSample;
1002 object->currentDesc.MultiSampleQuality = MultisampleQuality;
1004 /* Setup some glformat defaults */
1005 object->glDescription.glFormat = tableEntry->glFormat;
1006 object->glDescription.glFormatInternal = tableEntry->glInternal;
1007 object->glDescription.glType = tableEntry->glType;
1009 object->glDescription.textureName = 0;
1010 object->glDescription.level = Level;
1011 object->glDescription.target = GL_TEXTURE_2D;
1014 object->pow2Width = pow2Width;
1015 object->pow2Height = pow2Height;
1018 object->Flags = 0; /* We start without flags set */
1019 object->Flags |= (pow2Width != Width || pow2Height != Height) ? SFLAG_NONPOW2 : 0;
1020 object->Flags |= Discard ? SFLAG_DISCARD : 0;
1021 object->Flags |= (WINED3DFMT_D16_LOCKABLE == Format) ? SFLAG_LOCKABLE : 0;
1022 object->Flags |= Lockable ? SFLAG_LOCKABLE : 0;
1025 if (WINED3DFMT_UNKNOWN != Format) {
1026 object->bytesPerPixel = tableEntry->bpp;
1027 object->pow2Size = (pow2Width * object->bytesPerPixel) * pow2Height;
1029 object->bytesPerPixel = 0;
1030 object->pow2Size = 0;
1033 /** TODO: change this into a texture transform matrix so that it's processed in hardware **/
1035 TRACE("Pool %d %d %d %d",Pool, WINED3DPOOL_DEFAULT, WINED3DPOOL_MANAGED, WINED3DPOOL_SYSTEMMEM);
1037 /** Quick lockable sanity check TODO: remove this after surfaces, usage and locablility have been debugged properly
1038 * this function is too deap to need to care about things like this.
1039 * Levels need to be checked too, and possibly Type wince they all affect what can be done.
1040 * ****************************************/
1042 case WINED3DPOOL_SCRATCH:
1043 if(Lockable == FALSE)
1044 FIXME("Create suface called with a pool of SCRATCH and a Lockable of FALSE \
1045 which are mutually exclusive, setting lockable to true\n");
1048 case WINED3DPOOL_SYSTEMMEM:
1049 if(Lockable == FALSE) FIXME("Create surface called with a pool of SYSTEMMEM and a Lockable of FALSE, \
1050 this is acceptable but unexpected (I can't know how the surface can be usable!)\n");
1051 case WINED3DPOOL_MANAGED:
1052 if(Usage == WINED3DUSAGE_DYNAMIC) FIXME("Create surface called with a pool of MANAGED and a \
1053 Usage of DYNAMIC which are mutually exclusive, not doing \
1054 anything just telling you.\n");
1056 case WINED3DPOOL_DEFAULT: /*TODO: Create offscreen plain can cause this check to fail..., find out if it should */
1057 if(!(Usage & WINED3DUSAGE_DYNAMIC) && !(Usage & WINED3DUSAGE_RENDERTARGET)
1058 && !(Usage && WINED3DUSAGE_DEPTHSTENCIL ) && Lockable)
1059 WARN("Creating a surface with a POOL of DEFAULT with Lockable true, that doesn't specify DYNAMIC usage.\n");
1062 FIXME("(%p) Unknown pool %d\n", This, Pool);
1066 if (Usage & WINED3DUSAGE_RENDERTARGET && Pool != WINED3DPOOL_DEFAULT) {
1067 FIXME("Trying to create a render target that isn't in the default pool\n");
1070 /* mark the texture as dirty so that it get's loaded first time around*/
1071 IWineD3DSurface_AddDirtyRect(*ppSurface, NULL);
1072 TRACE("(%p) : w(%d) h(%d) fmt(%d,%s) lockable(%d) surf@%p, surfmem@%p, %d bytes\n",
1073 This, Width, Height, Format, debug_d3dformat(Format),
1074 (WINED3DFMT_D16_LOCKABLE == Format), *ppSurface, object->resource.allocatedMemory, object->resource.size);
1076 /* Store the DirectDraw primary surface. This is the first rendertarget surface created */
1077 if( (Usage & WINED3DUSAGE_RENDERTARGET) && (!This->ddraw_primary) )
1078 This->ddraw_primary = (IWineD3DSurface *) object;
1080 /* Look at the implementation and set the correct Vtable */
1082 case SURFACE_OPENGL:
1083 /* Nothing to do, it's set already */
1087 object->lpVtbl = &IWineGDISurface_Vtbl;
1091 /* To be sure to catch this */
1092 ERR("Unknown requested surface implementation %d!\n", Impl);
1093 IWineD3DSurface_Release((IWineD3DSurface *) object);
1094 return WINED3DERR_INVALIDCALL;
1097 /* Call the private setup routine */
1098 return IWineD3DSurface_PrivateSetup( (IWineD3DSurface *) object );
1102 static HRESULT WINAPI IWineD3DDeviceImpl_CreateTexture(IWineD3DDevice *iface, UINT Width, UINT Height, UINT Levels,
1103 DWORD Usage, WINED3DFORMAT Format, WINED3DPOOL Pool,
1104 IWineD3DTexture** ppTexture, HANDLE* pSharedHandle, IUnknown *parent,
1105 D3DCB_CREATESURFACEFN D3DCB_CreateSurface) {
1107 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
1108 IWineD3DTextureImpl *object;
1113 unsigned int pow2Width = Width;
1114 unsigned int pow2Height = Height;
1117 TRACE("(%p), Width(%d) Height(%d) Levels(%d) Usage(%ld) ....\n", This, Width, Height, Levels, Usage);
1119 /* TODO: It should only be possible to create textures for formats
1120 that are reported as supported */
1121 if (WINED3DFMT_UNKNOWN >= Format) {
1122 WARN("(%p) : Texture cannot be created with a format of D3DFMT_UNKNOWN\n", This);
1123 return WINED3DERR_INVALIDCALL;
1126 D3DCREATERESOURCEOBJECTINSTANCE(object, Texture, WINED3DRTYPE_TEXTURE, 0);
1127 D3DINITIALIZEBASETEXTURE(object->baseTexture);
1128 object->width = Width;
1129 object->height = Height;
1131 /** Non-power2 support **/
1132 /* Find the nearest pow2 match */
1133 pow2Width = pow2Height = 1;
1134 while (pow2Width < Width) pow2Width <<= 1;
1135 while (pow2Height < Height) pow2Height <<= 1;
1137 /** FIXME: add support for real non-power-two if it's provided by the video card **/
1138 /* Precalculated scaling for 'faked' non power of two texture coords */
1139 object->pow2scalingFactorX = (((float)Width) / ((float)pow2Width));
1140 object->pow2scalingFactorY = (((float)Height) / ((float)pow2Height));
1141 TRACE(" xf(%f) yf(%f)\n", object->pow2scalingFactorX, object->pow2scalingFactorY);
1143 /* Calculate levels for mip mapping */
1145 TRACE("calculating levels %d\n", object->baseTexture.levels);
1146 object->baseTexture.levels++;
1149 while (tmpW > 1 || tmpH > 1) {
1150 tmpW = max(1, tmpW >> 1);
1151 tmpH = max(1, tmpH >> 1);
1152 object->baseTexture.levels++;
1154 TRACE("Calculated levels = %d\n", object->baseTexture.levels);
1157 /* Generate all the surfaces */
1160 for (i = 0; i < object->baseTexture.levels; i++)
1162 /* use the callback to create the texture surface */
1163 hr = D3DCB_CreateSurface(This->parent, tmpW, tmpH, Format, Usage, Pool, i, &object->surfaces[i],NULL);
1164 if (hr!= WINED3D_OK || ( (IWineD3DSurfaceImpl *) object->surfaces[i])->Flags & SFLAG_OVERSIZE) {
1165 FIXME("Failed to create surface %p\n", object);
1167 object->surfaces[i] = NULL;
1168 IWineD3DTexture_Release((IWineD3DTexture *)object);
1174 IWineD3DSurface_SetContainer(object->surfaces[i], (IWineD3DBase *)object);
1175 TRACE("Created surface level %d @ %p\n", i, object->surfaces[i]);
1176 /* calculate the next mipmap level */
1177 tmpW = max(1, tmpW >> 1);
1178 tmpH = max(1, tmpH >> 1);
1181 TRACE("(%p) : Created texture %p\n", This, object);
1185 static HRESULT WINAPI IWineD3DDeviceImpl_CreateVolumeTexture(IWineD3DDevice *iface,
1186 UINT Width, UINT Height, UINT Depth,
1187 UINT Levels, DWORD Usage,
1188 WINED3DFORMAT Format, WINED3DPOOL Pool,
1189 IWineD3DVolumeTexture **ppVolumeTexture,
1190 HANDLE *pSharedHandle, IUnknown *parent,
1191 D3DCB_CREATEVOLUMEFN D3DCB_CreateVolume) {
1193 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
1194 IWineD3DVolumeTextureImpl *object;
1200 /* TODO: It should only be possible to create textures for formats
1201 that are reported as supported */
1202 if (WINED3DFMT_UNKNOWN >= Format) {
1203 WARN("(%p) : Texture cannot be created with a format of D3DFMT_UNKNOWN\n", This);
1204 return WINED3DERR_INVALIDCALL;
1207 D3DCREATERESOURCEOBJECTINSTANCE(object, VolumeTexture, WINED3DRTYPE_VOLUMETEXTURE, 0);
1208 D3DINITIALIZEBASETEXTURE(object->baseTexture);
1210 TRACE("(%p) : W(%d) H(%d) D(%d), Lvl(%d) Usage(%ld), Fmt(%u,%s), Pool(%s)\n", This, Width, Height,
1211 Depth, Levels, Usage, Format, debug_d3dformat(Format), debug_d3dpool(Pool));
1213 object->width = Width;
1214 object->height = Height;
1215 object->depth = Depth;
1217 /* Calculate levels for mip mapping */
1219 object->baseTexture.levels++;
1223 while (tmpW > 1 || tmpH > 1 || tmpD > 1) {
1224 tmpW = max(1, tmpW >> 1);
1225 tmpH = max(1, tmpH >> 1);
1226 tmpD = max(1, tmpD >> 1);
1227 object->baseTexture.levels++;
1229 TRACE("Calculated levels = %d\n", object->baseTexture.levels);
1232 /* Generate all the surfaces */
1237 for (i = 0; i < object->baseTexture.levels; i++)
1239 /* Create the volume */
1240 D3DCB_CreateVolume(This->parent, Width, Height, Depth, Format, Pool, Usage,
1241 (IWineD3DVolume **)&object->volumes[i], pSharedHandle);
1243 /* Set it's container to this object */
1244 IWineD3DVolume_SetContainer(object->volumes[i], (IWineD3DBase *)object);
1246 /* calcualte the next mipmap level */
1247 tmpW = max(1, tmpW >> 1);
1248 tmpH = max(1, tmpH >> 1);
1249 tmpD = max(1, tmpD >> 1);
1252 *ppVolumeTexture = (IWineD3DVolumeTexture *) object;
1253 TRACE("(%p) : Created volume texture %p\n", This, object);
1257 static HRESULT WINAPI IWineD3DDeviceImpl_CreateVolume(IWineD3DDevice *iface,
1258 UINT Width, UINT Height, UINT Depth,
1260 WINED3DFORMAT Format, WINED3DPOOL Pool,
1261 IWineD3DVolume** ppVolume,
1262 HANDLE* pSharedHandle, IUnknown *parent) {
1264 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
1265 IWineD3DVolumeImpl *object; /** NOTE: impl ref allowed since this is a create function **/
1266 const PixelFormatDesc *formatDesc = getFormatDescEntry(Format);
1268 D3DCREATERESOURCEOBJECTINSTANCE(object, Volume, WINED3DRTYPE_VOLUME, ((Width * formatDesc->bpp) * Height * Depth))
1270 TRACE("(%p) : W(%d) H(%d) D(%d), Usage(%ld), Fmt(%u,%s), Pool(%s)\n", This, Width, Height,
1271 Depth, Usage, Format, debug_d3dformat(Format), debug_d3dpool(Pool));
1273 object->currentDesc.Width = Width;
1274 object->currentDesc.Height = Height;
1275 object->currentDesc.Depth = Depth;
1276 object->bytesPerPixel = formatDesc->bpp;
1278 /** Note: Volume textures cannot be dxtn, hence no need to check here **/
1279 object->lockable = TRUE;
1280 object->locked = FALSE;
1281 memset(&object->lockedBox, 0, sizeof(WINED3DBOX));
1282 object->dirty = TRUE;
1284 return IWineD3DVolume_AddDirtyBox((IWineD3DVolume *) object, NULL);
1287 static HRESULT WINAPI IWineD3DDeviceImpl_CreateCubeTexture(IWineD3DDevice *iface, UINT EdgeLength,
1288 UINT Levels, DWORD Usage,
1289 WINED3DFORMAT Format, WINED3DPOOL Pool,
1290 IWineD3DCubeTexture **ppCubeTexture,
1291 HANDLE *pSharedHandle, IUnknown *parent,
1292 D3DCB_CREATESURFACEFN D3DCB_CreateSurface) {
1294 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
1295 IWineD3DCubeTextureImpl *object; /** NOTE: impl ref allowed since this is a create function **/
1299 unsigned int pow2EdgeLength = EdgeLength;
1301 /* TODO: It should only be possible to create textures for formats
1302 that are reported as supported */
1303 if (WINED3DFMT_UNKNOWN >= Format) {
1304 WARN("(%p) : Texture cannot be created with a format of D3DFMT_UNKNOWN\n", This);
1305 return WINED3DERR_INVALIDCALL;
1308 D3DCREATERESOURCEOBJECTINSTANCE(object, CubeTexture, WINED3DRTYPE_CUBETEXTURE, 0);
1309 D3DINITIALIZEBASETEXTURE(object->baseTexture);
1311 TRACE("(%p) Create Cube Texture\n", This);
1313 /** Non-power2 support **/
1315 /* Find the nearest pow2 match */
1317 while (pow2EdgeLength < EdgeLength) pow2EdgeLength <<= 1;
1319 object->edgeLength = EdgeLength;
1320 /* TODO: support for native non-power 2 */
1321 /* Precalculated scaling for 'faked' non power of two texture coords */
1322 object->pow2scalingFactor = ((float)EdgeLength) / ((float)pow2EdgeLength);
1324 /* Calculate levels for mip mapping */
1326 object->baseTexture.levels++;
1329 tmpW = max(1, tmpW >> 1);
1330 object->baseTexture.levels++;
1332 TRACE("Calculated levels = %d\n", object->baseTexture.levels);
1335 /* Generate all the surfaces */
1337 for (i = 0; i < object->baseTexture.levels; i++) {
1339 /* Create the 6 faces */
1340 for (j = 0; j < 6; j++) {
1342 hr=D3DCB_CreateSurface(This->parent, tmpW, tmpW, Format, Usage, Pool,
1343 i /* Level */, &object->surfaces[j][i],pSharedHandle);
1345 if(hr!= WINED3D_OK) {
1349 for (l = 0; l < j; l++) {
1350 IWineD3DSurface_Release(object->surfaces[j][i]);
1352 for (k = 0; k < i; k++) {
1353 for (l = 0; l < 6; l++) {
1354 IWineD3DSurface_Release(object->surfaces[l][j]);
1358 FIXME("(%p) Failed to create surface\n",object);
1359 HeapFree(GetProcessHeap(),0,object);
1360 *ppCubeTexture = NULL;
1363 IWineD3DSurface_SetContainer(object->surfaces[j][i], (IWineD3DBase *)object);
1364 TRACE("Created surface level %d @ %p,\n", i, object->surfaces[j][i]);
1366 tmpW = max(1, tmpW >> 1);
1369 TRACE("(%p) : Created Cube Texture %p\n", This, object);
1370 *ppCubeTexture = (IWineD3DCubeTexture *) object;
1374 static HRESULT WINAPI IWineD3DDeviceImpl_CreateQuery(IWineD3DDevice *iface, WINED3DQUERYTYPE Type, IWineD3DQuery **ppQuery, IUnknown* parent) {
1375 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
1376 IWineD3DQueryImpl *object; /*NOTE: impl ref allowed since this is a create function */
1378 if (NULL == ppQuery) {
1379 /* Just a check to see if we support this type of query */
1380 HRESULT hr = WINED3DERR_NOTAVAILABLE;
1382 case WINED3DQUERYTYPE_OCCLUSION:
1383 TRACE("(%p) occlusion query\n", This);
1384 if (GL_SUPPORT(ARB_OCCLUSION_QUERY) || GL_SUPPORT(NV_OCCLUSION_QUERY))
1387 WARN("Unsupported in local OpenGL implementation: ARB_OCCLUSION_QUERY/NV_OCCLUSION_QUERY\n");
1389 case WINED3DQUERYTYPE_VCACHE:
1390 case WINED3DQUERYTYPE_RESOURCEMANAGER:
1391 case WINED3DQUERYTYPE_VERTEXSTATS:
1392 case WINED3DQUERYTYPE_EVENT:
1393 case WINED3DQUERYTYPE_TIMESTAMP:
1394 case WINED3DQUERYTYPE_TIMESTAMPDISJOINT:
1395 case WINED3DQUERYTYPE_TIMESTAMPFREQ:
1396 case WINED3DQUERYTYPE_PIPELINETIMINGS:
1397 case WINED3DQUERYTYPE_INTERFACETIMINGS:
1398 case WINED3DQUERYTYPE_VERTEXTIMINGS:
1399 case WINED3DQUERYTYPE_PIXELTIMINGS:
1400 case WINED3DQUERYTYPE_BANDWIDTHTIMINGS:
1401 case WINED3DQUERYTYPE_CACHEUTILIZATION:
1403 FIXME("(%p) Unhandled query type %d\n", This, Type);
1408 D3DCREATEOBJECTINSTANCE(object, Query)
1409 object->type = Type;
1410 /* allocated the 'extended' data based on the type of query requested */
1412 case D3DQUERYTYPE_OCCLUSION:
1413 if(GL_SUPPORT(ARB_OCCLUSION_QUERY) || GL_SUPPORT(NV_OCCLUSION_QUERY)) {
1414 TRACE("(%p) Allocating data for an occlusion query\n", This);
1415 object->extendedData = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(WineQueryOcclusionData));
1418 case D3DQUERYTYPE_VCACHE:
1419 case D3DQUERYTYPE_RESOURCEMANAGER:
1420 case D3DQUERYTYPE_VERTEXSTATS:
1421 case D3DQUERYTYPE_EVENT:
1422 case D3DQUERYTYPE_TIMESTAMP:
1423 case D3DQUERYTYPE_TIMESTAMPDISJOINT:
1424 case D3DQUERYTYPE_TIMESTAMPFREQ:
1425 case D3DQUERYTYPE_PIPELINETIMINGS:
1426 case D3DQUERYTYPE_INTERFACETIMINGS:
1427 case D3DQUERYTYPE_VERTEXTIMINGS:
1428 case D3DQUERYTYPE_PIXELTIMINGS:
1429 case D3DQUERYTYPE_BANDWIDTHTIMINGS:
1430 case D3DQUERYTYPE_CACHEUTILIZATION:
1432 object->extendedData = 0;
1433 FIXME("(%p) Unhandled query type %d\n",This , Type);
1435 TRACE("(%p) : Created Query %p\n", This, object);
1439 /* example at http://www.fairyengine.com/articles/dxmultiviews.htm */
1440 static HRESULT WINAPI IWineD3DDeviceImpl_CreateAdditionalSwapChain(IWineD3DDevice* iface, WINED3DPRESENT_PARAMETERS* pPresentationParameters, IWineD3DSwapChain** ppSwapChain,
1442 D3DCB_CREATERENDERTARGETFN D3DCB_CreateRenderTarget,
1443 D3DCB_CREATEDEPTHSTENCILSURFACEFN D3DCB_CreateDepthStencil) {
1444 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
1447 IWineD3DSwapChainImpl *object; /** NOTE: impl ref allowed since this is a create function **/
1449 XVisualInfo template;
1450 GLXContext oldContext;
1451 Drawable oldDrawable;
1452 HRESULT hr = WINED3D_OK;
1454 TRACE("(%p) : Created Aditional Swap Chain\n", This);
1456 /** FIXME: Test under windows to find out what the life cycle of a swap chain is,
1457 * does a device hold a reference to a swap chain giving them a lifetime of the device
1458 * or does the swap chain notify the device of its destruction.
1459 *******************************/
1461 /* Check the params */
1462 if(*pPresentationParameters->BackBufferCount > D3DPRESENT_BACK_BUFFER_MAX) {
1463 ERR("App requested %d back buffers, this is not supported for now\n", *pPresentationParameters->BackBufferCount);
1464 return WINED3DERR_INVALIDCALL;
1465 } else if (*pPresentationParameters->BackBufferCount > 1) {
1466 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");
1469 D3DCREATEOBJECTINSTANCE(object, SwapChain)
1471 /*********************
1472 * Lookup the window Handle and the relating X window handle
1473 ********************/
1475 /* Setup hwnd we are using, plus which display this equates to */
1476 object->win_handle = *(pPresentationParameters->hDeviceWindow);
1477 if (!object->win_handle) {
1478 object->win_handle = This->createParms.hFocusWindow;
1481 object->win_handle = GetAncestor(object->win_handle, GA_ROOT);
1482 if ( !( object->win = (Window)GetPropA(object->win_handle, "__wine_x11_whole_window") ) ) {
1483 ERR("Can't get drawable (window), HWND:%p doesn't have the property __wine_x11_whole_window\n", object->win_handle);
1484 return WINED3DERR_NOTAVAILABLE;
1486 hDc = GetDC(object->win_handle);
1487 object->display = get_display(hDc);
1488 ReleaseDC(object->win_handle, hDc);
1489 TRACE("Using a display of %p %p\n", object->display, hDc);
1491 if (NULL == object->display || NULL == hDc) {
1492 WARN("Failed to get a display and HDc for Window %p\n", object->win_handle);
1493 return WINED3DERR_NOTAVAILABLE;
1496 if (object->win == 0) {
1497 WARN("Failed to get a valid XVisuial ID for the window %p\n", object->win_handle);
1498 return WINED3DERR_NOTAVAILABLE;
1501 * Create an opengl context for the display visual
1502 * NOTE: the visual is chosen as the window is created and the glcontext cannot
1503 * use different properties after that point in time. FIXME: How to handle when requested format
1504 * doesn't match actual visual? Cannot choose one here - code removed as it ONLY works if the one
1505 * it chooses is identical to the one already being used!
1506 **********************************/
1508 /** FIXME: Handle stencil appropriately via EnableAutoDepthStencil / AutoDepthStencilFormat **/
1511 /* Create a new context for this swapchain */
1512 template.visualid = (VisualID)GetPropA(GetDesktopWindow(), "__wine_x11_visual_id");
1513 /* TODO: change this to find a similar visual, but one with a stencil/zbuffer buffer that matches the request
1514 (or the best possible if none is requested) */
1515 TRACE("Found x visual ID : %ld\n", template.visualid);
1517 object->visInfo = XGetVisualInfo(object->display, VisualIDMask, &template, &num);
1518 if (NULL == object->visInfo) {
1519 ERR("cannot really get XVisual\n");
1521 return WINED3DERR_NOTAVAILABLE;
1524 /* Write out some debug info about the visual/s */
1525 TRACE("Using x visual ID : %ld\n", template.visualid);
1526 TRACE(" visual info: %p\n", object->visInfo);
1527 TRACE(" num items : %d\n", num);
1528 for (n = 0;n < num; n++) {
1529 TRACE("=====item=====: %d\n", n + 1);
1530 TRACE(" visualid : %ld\n", object->visInfo[n].visualid);
1531 TRACE(" screen : %d\n", object->visInfo[n].screen);
1532 TRACE(" depth : %u\n", object->visInfo[n].depth);
1533 TRACE(" class : %d\n", object->visInfo[n].class);
1534 TRACE(" red_mask : %ld\n", object->visInfo[n].red_mask);
1535 TRACE(" green_mask : %ld\n", object->visInfo[n].green_mask);
1536 TRACE(" blue_mask : %ld\n", object->visInfo[n].blue_mask);
1537 TRACE(" colormap_size : %d\n", object->visInfo[n].colormap_size);
1538 TRACE(" bits_per_rgb : %d\n", object->visInfo[n].bits_per_rgb);
1539 /* log some extra glx info */
1540 glXGetConfig(object->display, object->visInfo, GLX_AUX_BUFFERS, &value);
1541 TRACE(" gl_aux_buffers : %d\n", value);
1542 glXGetConfig(object->display, object->visInfo, GLX_BUFFER_SIZE ,&value);
1543 TRACE(" gl_buffer_size : %d\n", value);
1544 glXGetConfig(object->display, object->visInfo, GLX_RED_SIZE, &value);
1545 TRACE(" gl_red_size : %d\n", value);
1546 glXGetConfig(object->display, object->visInfo, GLX_GREEN_SIZE, &value);
1547 TRACE(" gl_green_size : %d\n", value);
1548 glXGetConfig(object->display, object->visInfo, GLX_BLUE_SIZE, &value);
1549 TRACE(" gl_blue_size : %d\n", value);
1550 glXGetConfig(object->display, object->visInfo, GLX_ALPHA_SIZE, &value);
1551 TRACE(" gl_alpha_size : %d\n", value);
1552 glXGetConfig(object->display, object->visInfo, GLX_DEPTH_SIZE ,&value);
1553 TRACE(" gl_depth_size : %d\n", value);
1554 glXGetConfig(object->display, object->visInfo, GLX_STENCIL_SIZE, &value);
1555 TRACE(" gl_stencil_size : %d\n", value);
1557 /* Now choose a simila visual ID*/
1559 #ifdef USE_CONTEXT_MANAGER
1561 /** TODO: use a context mamager **/
1565 IWineD3DSwapChain *implSwapChain;
1566 if (WINED3D_OK != IWineD3DDevice_GetSwapChain(iface, 0, &implSwapChain)) {
1567 /* The first time around we create the context that is shared with all other swapchains and render targets */
1568 object->glCtx = glXCreateContext(object->display, object->visInfo, NULL, GL_TRUE);
1569 TRACE("Creating implicit context for vis %p, hwnd %p\n", object->display, object->visInfo);
1572 TRACE("Creating context for vis %p, hwnd %p\n", object->display, object->visInfo);
1573 /* TODO: don't use Impl structures outside of create functions! (a context manager will replace the ->glCtx) */
1574 /* and create a new context with the implicit swapchains context as the shared context */
1575 object->glCtx = glXCreateContext(object->display, object->visInfo, ((IWineD3DSwapChainImpl *)implSwapChain)->glCtx, GL_TRUE);
1576 IWineD3DSwapChain_Release(implSwapChain);
1581 XFree(object->visInfo);
1582 object->visInfo = NULL;
1586 if (!object->glCtx) {
1587 ERR("Failed to create GLX context\n");
1588 return WINED3DERR_NOTAVAILABLE;
1590 TRACE("Context created (HWND=%p, glContext=%p, Window=%ld, VisInfo=%p)\n",
1591 object->win_handle, object->glCtx, object->win, object->visInfo);
1594 /*********************
1595 * Windowed / Fullscreen
1596 *******************/
1599 * TODO: MSDN says that we are only allowed one fullscreen swapchain per device,
1600 * so we should really check to see if there is a fullscreen swapchain already
1601 * I think Windows and X have different ideas about fullscreen, does a single head count as full screen?
1602 **************************************/
1604 if (!*(pPresentationParameters->Windowed)) {
1610 /* Get info on the current display setup */
1611 hdc = CreateDCA("DISPLAY", NULL, NULL, NULL);
1612 bpp = GetDeviceCaps(hdc, BITSPIXEL);
1615 /* Change the display settings */
1616 memset(&devmode, 0, sizeof(DEVMODEW));
1617 devmode.dmFields = DM_BITSPERPEL | DM_PELSWIDTH | DM_PELSHEIGHT;
1618 devmode.dmBitsPerPel = (bpp >= 24) ? 32 : bpp; /* Stupid XVidMode cannot change bpp */
1619 devmode.dmPelsWidth = *(pPresentationParameters->BackBufferWidth);
1620 devmode.dmPelsHeight = *(pPresentationParameters->BackBufferHeight);
1621 MultiByteToWideChar(CP_ACP, 0, "Gamers CG", -1, devmode.dmDeviceName, CCHDEVICENAME);
1622 ChangeDisplaySettingsExW(devmode.dmDeviceName, &devmode, object->win_handle, CDS_FULLSCREEN, NULL);
1624 /* Make popup window */
1625 SetWindowLongA(object->win_handle, GWL_STYLE, WS_POPUP);
1626 SetWindowPos(object->win_handle, HWND_TOP, 0, 0,
1627 *(pPresentationParameters->BackBufferWidth),
1628 *(pPresentationParameters->BackBufferHeight), SWP_SHOWWINDOW | SWP_FRAMECHANGED);
1630 /* For GetDisplayMode */
1631 This->ddraw_width = devmode.dmPelsWidth;
1632 This->ddraw_height = devmode.dmPelsHeight;
1633 This->ddraw_format = *(pPresentationParameters->BackBufferFormat);
1637 /** MSDN: If Windowed is TRUE and either of the BackBufferWidth/Height values is zero,
1638 * then the corresponding dimension of the client area of the hDeviceWindow
1639 * (or the focus window, if hDeviceWindow is NULL) is taken.
1640 **********************/
1642 if (*(pPresentationParameters->Windowed) &&
1643 ((*(pPresentationParameters->BackBufferWidth) == 0) ||
1644 (*(pPresentationParameters->BackBufferHeight) == 0))) {
1647 GetClientRect(object->win_handle, &Rect);
1649 if (*(pPresentationParameters->BackBufferWidth) == 0) {
1650 *(pPresentationParameters->BackBufferWidth) = Rect.right;
1651 TRACE("Updating width to %d\n", *(pPresentationParameters->BackBufferWidth));
1653 if (*(pPresentationParameters->BackBufferHeight) == 0) {
1654 *(pPresentationParameters->BackBufferHeight) = Rect.bottom;
1655 TRACE("Updating height to %d\n", *(pPresentationParameters->BackBufferHeight));
1659 /*********************
1660 * finish off parameter initialization
1661 *******************/
1663 /* Put the correct figures in the presentation parameters */
1664 TRACE("Coppying accross presentaion paraneters\n");
1665 object->presentParms.BackBufferWidth = *(pPresentationParameters->BackBufferWidth);
1666 object->presentParms.BackBufferHeight = *(pPresentationParameters->BackBufferHeight);
1667 object->presentParms.BackBufferFormat = *(pPresentationParameters->BackBufferFormat);
1668 object->presentParms.BackBufferCount = *(pPresentationParameters->BackBufferCount);
1669 object->presentParms.MultiSampleType = *(pPresentationParameters->MultiSampleType);
1670 object->presentParms.MultiSampleQuality = NULL == pPresentationParameters->MultiSampleQuality ? 0 : *(pPresentationParameters->MultiSampleQuality);
1671 object->presentParms.SwapEffect = *(pPresentationParameters->SwapEffect);
1672 object->presentParms.hDeviceWindow = *(pPresentationParameters->hDeviceWindow);
1673 object->presentParms.Windowed = *(pPresentationParameters->Windowed);
1674 object->presentParms.EnableAutoDepthStencil = *(pPresentationParameters->EnableAutoDepthStencil);
1675 object->presentParms.AutoDepthStencilFormat = *(pPresentationParameters->AutoDepthStencilFormat);
1676 object->presentParms.Flags = *(pPresentationParameters->Flags);
1677 object->presentParms.FullScreen_RefreshRateInHz = *(pPresentationParameters->FullScreen_RefreshRateInHz);
1678 object->presentParms.PresentationInterval = *(pPresentationParameters->PresentationInterval);
1681 /*********************
1682 * Create the back, front and stencil buffers
1683 *******************/
1685 TRACE("calling rendertarget CB\n");
1686 hr = D3DCB_CreateRenderTarget((IUnknown *) This->parent,
1687 object->presentParms.BackBufferWidth,
1688 object->presentParms.BackBufferHeight,
1689 object->presentParms.BackBufferFormat,
1690 object->presentParms.MultiSampleType,
1691 object->presentParms.MultiSampleQuality,
1692 TRUE /* Lockable */,
1693 &object->frontBuffer,
1694 NULL /* pShared (always null)*/);
1695 if (object->frontBuffer != NULL)
1696 IWineD3DSurface_SetContainer(object->frontBuffer, (IWineD3DBase *)object);
1698 if(object->presentParms.BackBufferCount > 0) {
1701 object->backBuffer = HeapAlloc(GetProcessHeap(), 0, sizeof(IWineD3DSurface *) * object->presentParms.BackBufferCount);
1702 if(!object->backBuffer) {
1703 ERR("Out of memory\n");
1705 if (object->frontBuffer) {
1706 IUnknown *bufferParent;
1707 IWineD3DSurface_GetParent(object->frontBuffer, &bufferParent);
1708 IUnknown_Release(bufferParent); /* once for the get parent */
1709 if (IUnknown_Release(bufferParent) > 0) {
1710 FIXME("(%p) Something's still holding the front buffer\n",This);
1713 HeapFree(GetProcessHeap(), 0, object);
1714 return E_OUTOFMEMORY;
1717 for(i = 0; i < object->presentParms.BackBufferCount; i++) {
1718 TRACE("calling rendertarget CB\n");
1719 hr = D3DCB_CreateRenderTarget((IUnknown *) This->parent,
1720 object->presentParms.BackBufferWidth,
1721 object->presentParms.BackBufferHeight,
1722 object->presentParms.BackBufferFormat,
1723 object->presentParms.MultiSampleType,
1724 object->presentParms.MultiSampleQuality,
1725 TRUE /* Lockable */,
1726 &object->backBuffer[i],
1727 NULL /* pShared (always null)*/);
1728 if(hr == WINED3D_OK && object->backBuffer[i]) {
1729 IWineD3DSurface_SetContainer(object->backBuffer[i], (IWineD3DBase *)object);
1735 object->backBuffer = NULL;
1738 if (object->backBuffer != NULL) {
1740 glDrawBuffer(GL_BACK);
1741 checkGLcall("glDrawBuffer(GL_BACK)");
1744 /* Single buffering - draw to front buffer */
1746 glDrawBuffer(GL_FRONT);
1747 checkGLcall("glDrawBuffer(GL_FRONT)");
1751 /* Under directX swapchains share the depth stencil, so only create one depth-stencil */
1752 if (pPresentationParameters->EnableAutoDepthStencil && hr == WINED3D_OK) {
1753 TRACE("Creating depth stencil buffer\n");
1754 if (This->depthStencilBuffer == NULL ) {
1755 hr = D3DCB_CreateDepthStencil((IUnknown *) This->parent,
1756 object->presentParms.BackBufferWidth,
1757 object->presentParms.BackBufferHeight,
1758 object->presentParms.AutoDepthStencilFormat,
1759 object->presentParms.MultiSampleType,
1760 object->presentParms.MultiSampleQuality,
1761 FALSE /* FIXME: Discard */,
1762 &This->depthStencilBuffer,
1763 NULL /* pShared (always null)*/ );
1764 if (This->depthStencilBuffer != NULL)
1765 IWineD3DSurface_SetContainer(This->depthStencilBuffer, 0);
1768 /** TODO: A check on width, height and multisample types
1769 *(since the zbuffer must be at least as large as the render target and have the same multisample parameters)
1770 ****************************/
1771 object->wantsDepthStencilBuffer = TRUE;
1773 object->wantsDepthStencilBuffer = FALSE;
1776 TRACE("FrontBuf @ %p, BackBuf @ %p, DepthStencil %d\n",object->frontBuffer, object->backBuffer ? object->backBuffer[0] : NULL, object->wantsDepthStencilBuffer);
1779 /*********************
1780 * init the default renderTarget management
1781 *******************/
1782 object->drawable = object->win;
1783 object->render_ctx = object->glCtx;
1785 if (hr == WINED3D_OK) {
1786 /*********************
1787 * Setup some defaults and clear down the buffers
1788 *******************/
1790 /** save current context and drawable **/
1791 oldContext = glXGetCurrentContext();
1792 oldDrawable = glXGetCurrentDrawable();
1794 TRACE("Activating context (display %p context %p drawable %ld)!\n", object->display, object->glCtx, object->win);
1795 if (glXMakeCurrent(object->display, object->win, object->glCtx) == False) {
1796 ERR("Error in setting current context (display %p context %p drawable %ld)!\n", object->display, object->glCtx, object->win);
1798 checkGLcall("glXMakeCurrent");
1800 TRACE("Setting up the screen\n");
1801 /* Clear the screen */
1802 glClearColor(1.0, 0.0, 0.0, 0.0);
1803 checkGLcall("glClearColor");
1806 glClearStencil(0xffff);
1808 checkGLcall("glClear");
1810 glColor3f(1.0, 1.0, 1.0);
1811 checkGLcall("glColor3f");
1813 glEnable(GL_LIGHTING);
1814 checkGLcall("glEnable");
1816 glLightModeli(GL_LIGHT_MODEL_LOCAL_VIEWER, GL_TRUE);
1817 checkGLcall("glLightModeli(GL_LIGHT_MODEL_LOCAL_VIEWER, GL_TRUE);");
1819 glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE_EXT);
1820 checkGLcall("glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE_EXT);");
1822 glLightModeli(GL_LIGHT_MODEL_COLOR_CONTROL, GL_SEPARATE_SPECULAR_COLOR);
1823 checkGLcall("glLightModeli(GL_LIGHT_MODEL_COLOR_CONTROL, GL_SEPARATE_SPECULAR_COLOR);");
1825 /* switch back to the original context (if there was one)*/
1826 if (This->swapchains) {
1827 /** TODO: restore the context and drawable **/
1828 glXMakeCurrent(object->display, oldDrawable, oldContext);
1833 TRACE("Set swapchain to %p\n", object);
1834 } else { /* something went wrong so clean up */
1835 IUnknown* bufferParent;
1836 if (object->frontBuffer) {
1838 IWineD3DSurface_GetParent(object->frontBuffer, &bufferParent);
1839 IUnknown_Release(bufferParent); /* once for the get parent */
1840 if (IUnknown_Release(bufferParent) > 0) {
1841 FIXME("(%p) Something's still holding the front buffer\n",This);
1844 if (object->backBuffer) {
1846 for(i = 0; i < object->presentParms.BackBufferCount; i++) {
1847 if(object->backBuffer[i]) {
1848 IWineD3DSurface_GetParent(object->backBuffer[i], &bufferParent);
1849 IUnknown_Release(bufferParent); /* once for the get parent */
1850 if (IUnknown_Release(bufferParent) > 0) {
1851 FIXME("(%p) Something's still holding the back buffer\n",This);
1855 HeapFree(GetProcessHeap(), 0, object->backBuffer);
1856 object->backBuffer = NULL;
1858 /* NOTE: don't clean up the depthstencil buffer because it belongs to the device */
1859 /* Clean up the context */
1860 /* check that we are the current context first (we shouldn't be though!) */
1861 if (object->glCtx != 0) {
1862 if(glXGetCurrentContext() == object->glCtx) {
1863 glXMakeCurrent(object->display, None, NULL);
1865 glXDestroyContext(object->display, object->glCtx);
1867 HeapFree(GetProcessHeap(), 0, object);
1874 /** NOTE: These are ahead of the other getters and setters to save using a forward declaration **/
1875 static UINT WINAPI IWineD3DDeviceImpl_GetNumberOfSwapChains(IWineD3DDevice *iface) {
1876 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
1877 TRACE("(%p)\n", This);
1879 return This->NumberOfSwapChains;
1882 static HRESULT WINAPI IWineD3DDeviceImpl_GetSwapChain(IWineD3DDevice *iface, UINT iSwapChain, IWineD3DSwapChain **pSwapChain) {
1883 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
1884 TRACE("(%p) : swapchain %d\n", This, iSwapChain);
1886 if(iSwapChain < This->NumberOfSwapChains) {
1887 *pSwapChain = This->swapchains[iSwapChain];
1888 IWineD3DSwapChain_AddRef(*pSwapChain);
1889 TRACE("(%p) returning %p\n", This, *pSwapChain);
1892 TRACE("Swapchain out of range\n");
1894 return WINED3DERR_INVALIDCALL;
1899 * Vertex Declaration
1901 static HRESULT WINAPI IWineD3DDeviceImpl_CreateVertexDeclaration(IWineD3DDevice* iface, CONST VOID* pDeclaration, IWineD3DVertexDeclaration** ppVertexDeclaration, IUnknown *parent) {
1902 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
1903 IWineD3DVertexDeclarationImpl *object = NULL;
1904 HRESULT hr = WINED3D_OK;
1905 TRACE("(%p) : directXVersion=%u, pFunction=%p, ppDecl=%p\n", This, ((IWineD3DImpl *)This->wineD3D)->dxVersion, pDeclaration, ppVertexDeclaration);
1906 D3DCREATEOBJECTINSTANCE(object, VertexDeclaration)
1909 hr = IWineD3DVertexDeclaration_SetDeclaration((IWineD3DVertexDeclaration *)object, (void *)pDeclaration);
1914 /* http://msdn.microsoft.com/archive/default.asp?url=/archive/en-us/directx9_c/directx/graphics/programmingguide/programmable/vertexshaders/vscreate.asp */
1915 static HRESULT WINAPI IWineD3DDeviceImpl_CreateVertexShader(IWineD3DDevice *iface, CONST DWORD *pDeclaration, CONST DWORD *pFunction, IWineD3DVertexShader **ppVertexShader, IUnknown *parent) {
1916 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
1917 IWineD3DVertexShaderImpl *object; /* NOTE: impl usage is ok, this is a create */
1918 HRESULT hr = WINED3D_OK;
1919 D3DCREATEOBJECTINSTANCE(object, VertexShader)
1920 object->baseShader.shader_ins = IWineD3DVertexShaderImpl_shader_ins;
1922 TRACE("(%p) : Created Vertex shader %p\n", This, *ppVertexShader);
1924 /* If a vertex declaration has been passed, save it to the vertex shader, this affects d3d8 only. */
1925 /* Further it needs to be set before calling SetFunction as SetFunction needs the declaration. */
1926 if (pDeclaration != NULL) {
1927 IWineD3DVertexDeclaration *vertexDeclaration;
1928 hr = IWineD3DDevice_CreateVertexDeclaration(iface, pDeclaration, &vertexDeclaration ,NULL);
1929 if (WINED3D_OK == hr) {
1930 TRACE("(%p) : Setting vertex declaration to %p\n", This, vertexDeclaration);
1931 object->vertexDeclaration = vertexDeclaration;
1933 FIXME("(%p) : Failed to set the declaration, returning WINED3DERR_INVALIDCALL\n", iface);
1934 IWineD3DVertexShader_Release(*ppVertexShader);
1935 return WINED3DERR_INVALIDCALL;
1939 hr = IWineD3DVertexShader_SetFunction(*ppVertexShader, pFunction);
1941 if (WINED3D_OK != hr) {
1942 FIXME("(%p) : Failed to set the function, returning WINED3DERR_INVALIDCALL\n", iface);
1943 IWineD3DVertexShader_Release(*ppVertexShader);
1944 return WINED3DERR_INVALIDCALL;
1947 #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. */
1948 if(Usage == WINED3DUSAGE_SOFTWAREVERTEXPROCESSING) {
1959 static HRESULT WINAPI IWineD3DDeviceImpl_CreatePixelShader(IWineD3DDevice *iface, CONST DWORD *pFunction, IWineD3DPixelShader **ppPixelShader, IUnknown *parent) {
1960 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
1961 IWineD3DPixelShaderImpl *object; /* NOTE: impl allowed, this is a create */
1962 HRESULT hr = WINED3D_OK;
1964 D3DCREATEOBJECTINSTANCE(object, PixelShader)
1965 object->baseShader.shader_ins = IWineD3DPixelShaderImpl_shader_ins;
1966 hr = IWineD3DPixelShader_SetFunction(*ppPixelShader, pFunction);
1967 if (WINED3D_OK == hr) {
1968 TRACE("(%p) : Created Pixel shader %p\n", This, *ppPixelShader);
1970 WARN("(%p) : Failed to create pixel shader\n", This);
1976 static HRESULT WINAPI IWineD3DDeviceImpl_CreatePalette(IWineD3DDevice *iface, DWORD Flags, PALETTEENTRY *PalEnt, IWineD3DPalette **Palette, IUnknown *Parent) {
1977 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *) iface;
1978 IWineD3DPaletteImpl *object;
1980 TRACE("(%p)->(%lx, %p, %p, %p)\n", This, Flags, PalEnt, Palette, Parent);
1982 /* Create the new object */
1983 object = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(IWineD3DPaletteImpl));
1985 ERR("Out of memory when allocating memory for a IWineD3DPalette implementation\n");
1986 return E_OUTOFMEMORY;
1989 object->lpVtbl = &IWineD3DPalette_Vtbl;
1991 object->Flags = Flags;
1992 object->parent = Parent;
1993 object->wineD3DDevice = This;
1994 object->palNumEntries = IWineD3DPaletteImpl_Size(Flags);
1996 object->hpal = CreatePalette((const LOGPALETTE*)&(object->palVersion));
1999 HeapFree( GetProcessHeap(), 0, object);
2000 return E_OUTOFMEMORY;
2003 hr = IWineD3DPalette_SetEntries((IWineD3DPalette *) object, 0, 0, IWineD3DPaletteImpl_Size(Flags), PalEnt);
2005 IWineD3DPalette_Release((IWineD3DPalette *) object);
2009 *Palette = (IWineD3DPalette *) object;
2014 static HRESULT WINAPI IWineD3DDeviceImpl_Init3D(IWineD3DDevice *iface, WINED3DPRESENT_PARAMETERS* pPresentationParameters, D3DCB_CREATEADDITIONALSWAPCHAIN D3DCB_CreateAdditionalSwapChain) {
2015 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *) iface;
2016 IWineD3DSwapChainImpl *swapchain;
2018 TRACE("(%p)->(%p,%p)\n", This, pPresentationParameters, D3DCB_CreateAdditionalSwapChain);
2019 if(This->d3d_initialized) return WINED3DERR_INVALIDCALL;
2021 /* TODO: Test if OpenGL is compiled in and loaded */
2023 /* Setup the implicit swapchain */
2024 TRACE("Creating implicit swapchain\n");
2025 if (D3D_OK != D3DCB_CreateAdditionalSwapChain((IUnknown *) This->parent, pPresentationParameters, (IWineD3DSwapChain **)&swapchain) || swapchain == NULL) {
2026 WARN("Failed to create implicit swapchain\n");
2027 return WINED3DERR_INVALIDCALL;
2030 This->NumberOfSwapChains = 1;
2031 This->swapchains = HeapAlloc(GetProcessHeap(), 0, This->NumberOfSwapChains * sizeof(IWineD3DSwapChain *));
2032 if(!This->swapchains) {
2033 ERR("Out of memory!\n");
2034 IWineD3DSwapChain_Release( (IWineD3DSwapChain *) swapchain);
2035 return E_OUTOFMEMORY;
2037 This->swapchains[0] = (IWineD3DSwapChain *) swapchain;
2039 if(swapchain->backBuffer && swapchain->backBuffer[0]) {
2040 TRACE("Setting rendertarget to %p\n", swapchain->backBuffer);
2041 This->renderTarget = swapchain->backBuffer[0];
2044 TRACE("Setting rendertarget to %p\n", swapchain->frontBuffer);
2045 This->renderTarget = swapchain->frontBuffer;
2047 IWineD3DSurface_AddRef(This->renderTarget);
2048 /* Depth Stencil support */
2049 This->stencilBufferTarget = This->depthStencilBuffer;
2050 if (NULL != This->stencilBufferTarget) {
2051 IWineD3DSurface_AddRef(This->stencilBufferTarget);
2054 /* Set up some starting GL setup */
2057 * Initialize openGL extension related variables
2058 * with Default values
2061 ((IWineD3DImpl *) This->wineD3D)->isGLInfoValid = IWineD3DImpl_FillGLCaps( &((IWineD3DImpl *) This->wineD3D)->gl_info, swapchain->display);
2062 /* Setup all the devices defaults */
2063 IWineD3DStateBlock_InitStartupStateBlock((IWineD3DStateBlock *)This->stateBlock);
2065 IWineD3DImpl_CheckGraphicsMemory();
2069 /* Initialize our list of GLSL programs */
2070 list_init(&This->glsl_shader_progs);
2072 { /* Set a default viewport */
2076 vp.Width = *(pPresentationParameters->BackBufferWidth);
2077 vp.Height = *(pPresentationParameters->BackBufferHeight);
2080 IWineD3DDevice_SetViewport((IWineD3DDevice *)This, &vp);
2083 /* Initialize the current view state */
2084 This->modelview_valid = 1;
2085 This->proj_valid = 0;
2086 This->view_ident = 1;
2087 This->last_was_rhw = 0;
2088 glGetIntegerv(GL_MAX_LIGHTS, &This->maxConcurrentLights);
2089 TRACE("(%p) All defaults now set up, leaving Init3D with %p\n", This, This);
2091 /* Clear the screen */
2092 IWineD3DDevice_Clear((IWineD3DDevice *) This, 0, NULL, D3DCLEAR_STENCIL|D3DCLEAR_ZBUFFER|D3DCLEAR_TARGET, 0x00, 1.0, 0);
2094 This->d3d_initialized = TRUE;
2098 static HRESULT WINAPI IWineD3DDeviceImpl_Uninit3D(IWineD3DDevice *iface) {
2099 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *) iface;
2101 IUnknown* stencilBufferParent;
2102 IUnknown* swapChainParent;
2104 TRACE("(%p)\n", This);
2106 if(!This->d3d_initialized) return WINED3DERR_INVALIDCALL;
2108 for(sampler = 0; sampler < GL_LIMITS(sampler_stages); ++sampler) {
2109 IWineD3DDevice_SetTexture(iface, sampler, NULL);
2112 /* Release the buffers (with sanity checks)*/
2113 TRACE("Releasing the depth stencil buffer at %p\n", This->stencilBufferTarget);
2114 if(This->stencilBufferTarget != NULL && (IWineD3DSurface_Release(This->stencilBufferTarget) >0)){
2115 if(This->depthStencilBuffer != This->stencilBufferTarget)
2116 FIXME("(%p) Something's still holding the depthStencilBuffer\n",This);
2118 This->stencilBufferTarget = NULL;
2120 TRACE("Releasing the render target at %p\n", This->renderTarget);
2121 if(IWineD3DSurface_Release(This->renderTarget) >0){
2122 /* This check is a bit silly, itshould be in swapchain_release FIXME("(%p) Something's still holding the renderTarget\n",This); */
2124 TRACE("Setting rendertarget to NULL\n");
2125 This->renderTarget = NULL;
2127 IWineD3DSurface_GetParent(This->depthStencilBuffer, &stencilBufferParent);
2128 IUnknown_Release(stencilBufferParent); /* once for the get parent */
2129 if(IUnknown_Release(stencilBufferParent) >0){ /* the second time for when it was created */
2130 FIXME("(%p) Something's still holding the depthStencilBuffer\n",This);
2132 This->depthStencilBuffer = NULL;
2134 for(i=0; i < This->NumberOfSwapChains; i++) {
2135 TRACE("Releasing the implicit swapchain %d\n", i);
2136 /* Swapchain 0 is special because it's created in startup with a hanging parent, so we have to release its parent now */
2137 IWineD3DSwapChain_GetParent(This->swapchains[i], &swapChainParent);
2138 IUnknown_Release(swapChainParent); /* once for the get parent */
2139 if (IUnknown_Release(swapChainParent) > 0) { /* the second time for when it was created */
2140 FIXME("(%p) Something's still holding the implicit swapchain\n", This);
2144 HeapFree(GetProcessHeap(), 0, This->swapchains);
2145 This->swapchains = NULL;
2146 This->NumberOfSwapChains = 0;
2148 This->d3d_initialized = FALSE;
2152 static HRESULT WINAPI IWineD3DDeviceImpl_EnumDisplayModes(IWineD3DDevice *iface, DWORD Flags, UINT Width, UINT Height, WINED3DFORMAT pixelformat, LPVOID context, D3DCB_ENUMDISPLAYMODESCALLBACK callback) {
2153 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2157 const PixelFormatDesc *formatDesc = getFormatDescEntry(pixelformat);
2159 TRACE("(%p)->(%lx,%d,%d,%d,%p,%p)\n", This, Flags, Width, Height, pixelformat, context, callback);
2161 for (i = 0; EnumDisplaySettingsExW(NULL, i, &DevModeW, 0); i++) {
2162 /* Ignore some modes if a description was passed */
2163 if ( (Width > 0) && (Width != DevModeW.dmPelsWidth)) continue;
2164 if ( (Height > 0) && (Height != DevModeW.dmPelsHeight)) continue;
2165 if ( (pixelformat != WINED3DFMT_UNKNOWN) && ( formatDesc->bpp != DevModeW.dmBitsPerPel) ) continue;
2167 TRACE("Enumerating %ldx%ld@%s\n", DevModeW.dmPelsWidth, DevModeW.dmPelsHeight, debug_d3dformat(pixelformat_for_depth(DevModeW.dmBitsPerPel)));
2169 if (callback((IUnknown *) This, (UINT) DevModeW.dmPelsWidth, (UINT) DevModeW.dmPelsHeight, pixelformat_for_depth(DevModeW.dmBitsPerPel), 60.0, context) == DDENUMRET_CANCEL)
2176 static HRESULT WINAPI IWineD3DDeviceImpl_SetDisplayMode(IWineD3DDevice *iface, UINT iSwapChain, WINED3DDISPLAYMODE* pMode) {
2178 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2180 const PixelFormatDesc *formatDesc = getFormatDescEntry(pMode->Format);
2182 TRACE("(%p)->(%d,%p) Mode=%dx%dx@%d, %s\n", This, iSwapChain, pMode, pMode->Width, pMode->Height, pMode->RefreshRate, debug_d3dformat(pMode->Format));
2184 /* Resize the screen even without a window:
2185 * The app could have unset it with SetCooperativeLevel, but not called
2186 * RestoreDisplayMode first. Then the release will call RestoreDisplayMode,
2187 * but we don't have any hwnd
2190 devmode.dmFields = DM_BITSPERPEL | DM_PELSWIDTH | DM_PELSHEIGHT;
2191 devmode.dmBitsPerPel = formatDesc->bpp * 8;
2192 if(devmode.dmBitsPerPel == 24) devmode.dmBitsPerPel = 32;
2193 devmode.dmPelsWidth = pMode->Width;
2194 devmode.dmPelsHeight = pMode->Height;
2196 devmode.dmDisplayFrequency = pMode->RefreshRate;
2197 if (pMode->RefreshRate != 0) {
2198 devmode.dmFields |= DM_DISPLAYFREQUENCY;
2201 /* Only change the mode if necessary */
2202 if( (This->ddraw_width == pMode->Width) &&
2203 (This->ddraw_height == pMode->Height) &&
2204 (This->ddraw_format == pMode->Format) &&
2205 (pMode->RefreshRate == 0) ) {
2209 ret = ChangeDisplaySettingsExW(NULL, &devmode, NULL, CDS_FULLSCREEN, NULL);
2210 if (ret != DISP_CHANGE_SUCCESSFUL) {
2211 if(devmode.dmDisplayFrequency != 0) {
2212 WARN("ChangeDisplaySettingsExW failed, trying without the refresh rate\n");
2213 devmode.dmFields &= ~DM_DISPLAYFREQUENCY;
2214 devmode.dmDisplayFrequency = 0;
2215 ret = ChangeDisplaySettingsExW(NULL, &devmode, NULL, CDS_FULLSCREEN, NULL) != DISP_CHANGE_SUCCESSFUL;
2217 if(ret != DISP_CHANGE_SUCCESSFUL) {
2218 return DDERR_INVALIDMODE;
2222 /* Store the new values */
2223 This->ddraw_width = pMode->Width;
2224 This->ddraw_height = pMode->Height;
2225 This->ddraw_format = pMode->Format;
2227 /* Only do this with a window of course */
2228 if(This->ddraw_window)
2229 MoveWindow(This->ddraw_window, 0, 0, pMode->Width, pMode->Height, TRUE);
2234 static HRESULT WINAPI IWineD3DDeviceImpl_EnumZBufferFormats(IWineD3DDevice *iface, D3DCB_ENUMPIXELFORMATS Callback, void *Context) {
2235 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *) iface;
2238 WINED3DFORMAT FormatList[] = {
2245 WINED3DFMT_UNKNOWN /* Terminate the list */
2248 TRACE("(%p)->(%p,%p)\n", This, Callback, Context);
2250 while(FormatList[i] != WINED3DFMT_UNKNOWN) {
2251 TRACE("Enumerating %s\n", debug_d3dformat(FormatList[i]));
2252 ret = Callback((IUnknown *) This, FormatList[i], Context);
2253 if(ret != DDENUMRET_OK) {
2254 TRACE("Enumeration cancelled by Application\n");
2260 TRACE("End of Enumeration\n");
2265 static HRESULT WINAPI IWineD3DDeviceImpl_EnumTextureFormats(IWineD3DDevice *iface, D3DCB_ENUMPIXELFORMATS Callback, void *Context) {
2266 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *) iface;
2271 * WINED3DFMT_A1R5G5B5 needs to be the first 16 bit format, as some dumb apps depend on this
2273 * Do not enumerate RGBA pixel formats: "some games choose the first 16 bit texture format
2274 * with alpha they find enumerated, others the last one. And both want to have the ARGB one."
2275 * But WineD3D doesn't support RGBA formats anyway...
2278 WINED3DFORMAT FormatList[] = {
2280 WINED3DFMT_A8R8G8B8,
2281 WINED3DFMT_X8R8G8B8,
2285 WINED3DFMT_A1R5G5B5,
2286 WINED3DFMT_A4R4G4B4,
2288 WINED3DFMT_X1R5G5B5,
2296 /* Terminate the list */
2300 TRACE("(%p)->(%p,%p)\n", This, Callback, Context);
2302 while(FormatList[i] != WINED3DFMT_UNKNOWN) {
2303 TRACE("Enumerating %s\n", debug_d3dformat(FormatList[i]));
2304 ret = Callback((IUnknown *) This, FormatList[i], Context);
2305 if(ret != DDENUMRET_OK) {
2306 TRACE("Enumeration cancelled by Application\n");
2312 TRACE("End of Enumeration\n");
2317 static HRESULT WINAPI IWineD3DDeviceImpl_GetDirect3D(IWineD3DDevice *iface, IWineD3D **ppD3D) {
2318 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2319 *ppD3D= This->wineD3D;
2320 TRACE("(%p) : wineD3D returning %p\n", This, *ppD3D);
2321 IWineD3D_AddRef(*ppD3D);
2325 static UINT WINAPI IWineD3DDeviceImpl_GetAvailableTextureMem(IWineD3DDevice *iface) {
2326 /** NOTE: There's a probably a hack-around for this one by putting as many pbuffers, VBO's (or whatever)
2327 * Into the video ram as possible and seeing how many fit
2328 * you can also get the correct initial value from via X and ATI's driver
2329 *******************/
2330 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2331 static BOOL showfixmes = TRUE;
2333 FIXME("(%p) : stub, emulating %dMB for now, returning %dMB\n", This, (emulated_textureram/(1024*1024)),
2334 ((emulated_textureram - wineD3DGlobalStatistics->glsurfaceram) / (1024*1024)));
2337 TRACE("(%p) : emulating %dMB for now, returning %dMB\n", This, (emulated_textureram/(1024*1024)),
2338 ((emulated_textureram - wineD3DGlobalStatistics->glsurfaceram) / (1024*1024)));
2339 /* videomemory is simulated videomemory + AGP memory left */
2340 return (emulated_textureram - wineD3DGlobalStatistics->glsurfaceram);
2348 static HRESULT WINAPI IWineD3DDeviceImpl_SetFVF(IWineD3DDevice *iface, DWORD fvf) {
2349 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2350 HRESULT hr = WINED3D_OK;
2352 /* Update the current state block */
2353 This->updateStateBlock->fvf = fvf;
2354 This->updateStateBlock->changed.fvf = TRUE;
2355 This->updateStateBlock->set.fvf = TRUE;
2357 TRACE("(%p) : FVF Shader FVF set to %lx\n", This, fvf);
2360 /* clear down the vertex declaration
2361 NOTE: Axis and Allies doesn't work properly otherwise
2362 (may be a stateblock problem though!)
2364 hr = IWineD3DDevice_SetVertexDeclaration(iface, NULL);
2371 static HRESULT WINAPI IWineD3DDeviceImpl_GetFVF(IWineD3DDevice *iface, DWORD *pfvf) {
2372 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2373 TRACE("(%p) : GetFVF returning %lx\n", This, This->stateBlock->fvf);
2374 *pfvf = This->stateBlock->fvf;
2379 * Get / Set Stream Source
2381 static HRESULT WINAPI IWineD3DDeviceImpl_SetStreamSource(IWineD3DDevice *iface, UINT StreamNumber,IWineD3DVertexBuffer* pStreamData, UINT OffsetInBytes, UINT Stride) {
2382 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2383 IWineD3DVertexBuffer *oldSrc;
2385 /**TODO: instance and index data, see
2386 http://msdn.microsoft.com/library/default.asp?url=/library/en-us/directx9_c/directx/graphics/programmingguide/advancedtopics/DrawingMultipleInstances.asp
2388 http://msdn.microsoft.com/library/default.asp?url=/library/en-us/directx9_c/directx/graphics/reference/d3d/interfaces/idirect3ddevice9/SetStreamSourceFreq.asp
2391 /* D3d9 only, but shouldn't hurt d3d8 */
2394 streamFlags = StreamNumber &(D3DSTREAMSOURCE_INDEXEDDATA | D3DSTREAMSOURCE_INSTANCEDATA);
2396 if (streamFlags & D3DSTREAMSOURCE_INDEXEDDATA) {
2397 FIXME("stream index data not supported\n");
2399 if (streamFlags & D3DSTREAMSOURCE_INDEXEDDATA) {
2400 FIXME("stream instance data not supported\n");
2404 StreamNumber&= ~(D3DSTREAMSOURCE_INDEXEDDATA | D3DSTREAMSOURCE_INSTANCEDATA);
2406 if (StreamNumber >= MAX_STREAMS) {
2407 WARN("Stream out of range %d\n", StreamNumber);
2408 return WINED3DERR_INVALIDCALL;
2411 oldSrc = This->stateBlock->streamSource[StreamNumber];
2412 TRACE("(%p) : StreamNo: %d, OldStream (%p), NewStream (%p), NewStride %d\n", This, StreamNumber, oldSrc, pStreamData, Stride);
2414 This->updateStateBlock->changed.streamSource[StreamNumber] = TRUE;
2415 This->updateStateBlock->set.streamSource[StreamNumber] = TRUE;
2416 This->updateStateBlock->streamStride[StreamNumber] = Stride;
2417 This->updateStateBlock->streamSource[StreamNumber] = pStreamData;
2418 This->updateStateBlock->streamOffset[StreamNumber] = OffsetInBytes;
2419 This->updateStateBlock->streamFlags[StreamNumber] = streamFlags;
2421 /* Handle recording of state blocks */
2422 if (This->isRecordingState) {
2423 TRACE("Recording... not performing anything\n");
2427 /* Not recording... */
2428 /* Need to do a getParent and pass the reffs up */
2429 /* MSDN says ..... When an application no longer holds a references to this interface, the interface will automatically be freed.
2430 which suggests that we shouldn't be ref counting? and do need a _release on the stream source to reset the stream source
2431 so for now, just count internally */
2432 if (pStreamData != NULL) {
2433 IWineD3DVertexBufferImpl *vbImpl = (IWineD3DVertexBufferImpl *) pStreamData;
2434 if( (vbImpl->Flags & VBFLAG_STREAM) && vbImpl->stream != StreamNumber) {
2435 WARN("Assigning a Vertex Buffer to stream %d which is already assigned to stream %d\n", StreamNumber, vbImpl->stream);
2437 vbImpl->stream = StreamNumber;
2438 vbImpl->Flags |= VBFLAG_STREAM;
2439 IWineD3DVertexBuffer_AddRef(pStreamData);
2441 if (oldSrc != NULL) {
2442 ((IWineD3DVertexBufferImpl *) oldSrc)->Flags &= ~VBFLAG_STREAM;
2443 IWineD3DVertexBuffer_Release(oldSrc);
2449 static HRESULT WINAPI IWineD3DDeviceImpl_GetStreamSource(IWineD3DDevice *iface, UINT StreamNumber,IWineD3DVertexBuffer** pStream, UINT *pOffset, UINT* pStride) {
2450 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2453 TRACE("(%p) : StreamNo: %d, Stream (%p), Stride %d\n", This, StreamNumber,
2454 This->stateBlock->streamSource[StreamNumber], This->stateBlock->streamStride[StreamNumber]);
2457 streamFlags = StreamNumber &(D3DSTREAMSOURCE_INDEXEDDATA | D3DSTREAMSOURCE_INSTANCEDATA);
2459 if (streamFlags & D3DSTREAMSOURCE_INDEXEDDATA) {
2460 FIXME("stream index data not supported\n");
2462 if (streamFlags & D3DSTREAMSOURCE_INDEXEDDATA) {
2463 FIXME("stream instance data not supported\n");
2467 StreamNumber&= ~(D3DSTREAMSOURCE_INDEXEDDATA | D3DSTREAMSOURCE_INSTANCEDATA);
2469 if (StreamNumber >= MAX_STREAMS) {
2470 WARN("Stream out of range %d\n", StreamNumber);
2471 return WINED3DERR_INVALIDCALL;
2473 *pStream = This->stateBlock->streamSource[StreamNumber];
2474 *pStride = This->stateBlock->streamStride[StreamNumber];
2475 *pOffset = This->stateBlock->streamOffset[StreamNumber];
2477 if (*pStream == NULL) {
2478 FIXME("Attempting to get an empty stream %d, returning WINED3DERR_INVALIDCALL\n", StreamNumber);
2479 return WINED3DERR_INVALIDCALL;
2482 IWineD3DVertexBuffer_AddRef(*pStream); /* We have created a new reference to the VB */
2486 /*Should be quite easy, just an extension of vertexdata
2488 http://msdn.microsoft.com/archive/default.asp?url=/archive/en-us/directx9_c_Summer_04/directx/graphics/programmingguide/advancedtopics/DrawingMultipleInstances.asp
2490 The divider is a bit odd though
2492 VertexOffset = StartVertex / Divider * StreamStride +
2493 VertexIndex / Divider * StreamStride + StreamOffset
2496 static HRESULT WINAPI IWineD3DDeviceImpl_SetStreamSourceFreq(IWineD3DDevice *iface, UINT StreamNumber, UINT Divider) {
2497 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2499 TRACE("(%p) StreamNumber(%d), Divider(%d)\n", This, StreamNumber, Divider);
2500 This->updateStateBlock->streamFlags[StreamNumber] = Divider & (D3DSTREAMSOURCE_INSTANCEDATA | D3DSTREAMSOURCE_INDEXEDDATA );
2502 This->updateStateBlock->changed.streamFreq[StreamNumber] = TRUE;
2503 This->updateStateBlock->set.streamFreq[StreamNumber] = TRUE;
2504 This->updateStateBlock->streamFreq[StreamNumber] = Divider & 0x7FFFFF;
2506 if (This->updateStateBlock->streamFlags[StreamNumber] || This->updateStateBlock->streamFreq[StreamNumber] != 1) {
2507 FIXME("Stream indexing not fully supported\n");
2513 static HRESULT WINAPI IWineD3DDeviceImpl_GetStreamSourceFreq(IWineD3DDevice *iface, UINT StreamNumber, UINT* Divider) {
2514 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2516 TRACE("(%p) StreamNumber(%d), Divider(%p)\n", This, StreamNumber, Divider);
2517 *Divider = This->updateStateBlock->streamFreq[StreamNumber] | This->updateStateBlock->streamFlags[StreamNumber];
2519 TRACE("(%p) : returning %d\n", This, *Divider);
2525 * Get / Set & Multiply Transform
2527 static HRESULT WINAPI IWineD3DDeviceImpl_SetTransform(IWineD3DDevice *iface, D3DTRANSFORMSTATETYPE d3dts, CONST D3DMATRIX* lpmatrix) {
2528 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2530 /* Most of this routine, comments included copied from ddraw tree initially: */
2531 TRACE("(%p) : Transform State=%d\n", This, d3dts);
2533 /* Handle recording of state blocks */
2534 if (This->isRecordingState) {
2535 TRACE("Recording... not performing anything\n");
2536 This->updateStateBlock->changed.transform[d3dts] = TRUE;
2537 This->updateStateBlock->set.transform[d3dts] = TRUE;
2538 memcpy(&This->updateStateBlock->transforms[d3dts], lpmatrix, sizeof(D3DMATRIX));
2543 * If the new matrix is the same as the current one,
2544 * we cut off any further processing. this seems to be a reasonable
2545 * optimization because as was noticed, some apps (warcraft3 for example)
2546 * tend towards setting the same matrix repeatedly for some reason.
2548 * From here on we assume that the new matrix is different, wherever it matters.
2550 if (!memcmp(&This->stateBlock->transforms[d3dts].u.m[0][0], lpmatrix, sizeof(D3DMATRIX))) {
2551 TRACE("The app is setting the same matrix over again\n");
2554 conv_mat(lpmatrix, &This->stateBlock->transforms[d3dts].u.m[0][0]);
2558 ScreenCoord = ProjectionMat * ViewMat * WorldMat * ObjectCoord
2559 where ViewMat = Camera space, WorldMat = world space.
2561 In OpenGL, camera and world space is combined into GL_MODELVIEW
2562 matrix. The Projection matrix stay projection matrix.
2565 /* Capture the times we can just ignore the change for now */
2566 if (d3dts == D3DTS_WORLDMATRIX(0)) {
2567 This->modelview_valid = FALSE;
2570 } else if (d3dts == D3DTS_PROJECTION) {
2571 This->proj_valid = FALSE;
2574 } else if (d3dts >= D3DTS_WORLDMATRIX(1) && d3dts <= D3DTS_WORLDMATRIX(255)) {
2575 /* Indexed Vertex Blending Matrices 256 -> 511 */
2576 /* Use arb_vertex_blend or NV_VERTEX_WEIGHTING? */
2577 FIXME("D3DTS_WORLDMATRIX(1..255) not handled\n");
2581 /* Now we really are going to have to change a matrix */
2584 if (d3dts >= D3DTS_TEXTURE0 && d3dts <= D3DTS_TEXTURE7) { /* handle texture matrices */
2585 /* This is now set with the texture unit states, it may be a good idea to flag the change though! */
2586 } else if (d3dts == D3DTS_VIEW) { /* handle the VIEW matrice */
2589 /* If we are changing the View matrix, reset the light and clipping planes to the new view
2590 * NOTE: We have to reset the positions even if the light/plane is not currently
2591 * enabled, since the call to enable it will not reset the position.
2592 * NOTE2: Apparently texture transforms do NOT need reapplying
2595 PLIGHTINFOEL *lightChain = NULL;
2596 This->modelview_valid = FALSE;
2597 This->view_ident = !memcmp(lpmatrix, identity, 16 * sizeof(float));
2599 glMatrixMode(GL_MODELVIEW);
2600 checkGLcall("glMatrixMode(GL_MODELVIEW)");
2602 glLoadMatrixf((float *)lpmatrix);
2603 checkGLcall("glLoadMatrixf(...)");
2606 lightChain = This->stateBlock->lights;
2607 while (lightChain && lightChain->glIndex != -1) {
2608 glLightfv(GL_LIGHT0 + lightChain->glIndex, GL_POSITION, lightChain->lightPosn);
2609 checkGLcall("glLightfv posn");
2610 glLightfv(GL_LIGHT0 + lightChain->glIndex, GL_SPOT_DIRECTION, lightChain->lightDirn);
2611 checkGLcall("glLightfv dirn");
2612 lightChain = lightChain->next;
2615 /* Reset Clipping Planes if clipping is enabled */
2616 for (k = 0; k < GL_LIMITS(clipplanes); k++) {
2617 glClipPlane(GL_CLIP_PLANE0 + k, This->stateBlock->clipplane[k]);
2618 checkGLcall("glClipPlane");
2622 } else { /* What was requested!?? */
2623 WARN("invalid matrix specified: %i\n", d3dts);
2626 /* Release lock, all done */
2631 static HRESULT WINAPI IWineD3DDeviceImpl_GetTransform(IWineD3DDevice *iface, D3DTRANSFORMSTATETYPE State, D3DMATRIX* pMatrix) {
2632 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2633 TRACE("(%p) : for Transform State %d\n", This, State);
2634 memcpy(pMatrix, &This->stateBlock->transforms[State], sizeof(D3DMATRIX));
2638 static HRESULT WINAPI IWineD3DDeviceImpl_MultiplyTransform(IWineD3DDevice *iface, D3DTRANSFORMSTATETYPE State, CONST D3DMATRIX* pMatrix) {
2639 D3DMATRIX *mat = NULL;
2642 /* Note: Using 'updateStateBlock' rather than 'stateblock' in the code
2643 * below means it will be recorded in a state block change, but it
2644 * works regardless where it is recorded.
2645 * If this is found to be wrong, change to StateBlock.
2647 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2648 TRACE("(%p) : For state %u\n", This, State);
2650 if (State < HIGHEST_TRANSFORMSTATE)
2652 mat = &This->updateStateBlock->transforms[State];
2654 FIXME("Unhandled transform state!!\n");
2657 multiply_matrix(&temp, mat, (D3DMATRIX *) pMatrix);
2659 /* Apply change via set transform - will reapply to eg. lights this way */
2660 return IWineD3DDeviceImpl_SetTransform(iface, State, &temp);
2665 * WARNING: This code relies on the fact that D3DLIGHT8 == D3DLIGHT9
2667 /* Note lights are real special cases. Although the device caps state only eg. 8 are supported,
2668 you can reference any indexes you want as long as that number max are enabled at any
2669 one point in time! Therefore since the indexes can be anything, we need a linked list of them.
2670 However, this causes stateblock problems. When capturing the state block, I duplicate the list,
2671 but when recording, just build a chain pretty much of commands to be replayed. */
2673 static HRESULT WINAPI IWineD3DDeviceImpl_SetLight(IWineD3DDevice *iface, DWORD Index, CONST WINED3DLIGHT* pLight) {
2675 PLIGHTINFOEL *object, *temp;
2677 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2678 TRACE("(%p) : Idx(%ld), pLight(%p)\n", This, Index, pLight);
2680 /* If recording state block, just add to end of lights chain */
2681 if (This->isRecordingState) {
2682 object = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(PLIGHTINFOEL));
2683 if (NULL == object) {
2684 return WINED3DERR_OUTOFVIDEOMEMORY;
2686 memcpy(&object->OriginalParms, pLight, sizeof(D3DLIGHT9));
2687 object->OriginalIndex = Index;
2688 object->glIndex = -1;
2689 object->changed = TRUE;
2691 /* Add to the END of the chain of lights changes to be replayed */
2692 if (This->updateStateBlock->lights == NULL) {
2693 This->updateStateBlock->lights = object;
2695 temp = This->updateStateBlock->lights;
2696 while (temp->next != NULL) temp=temp->next;
2697 temp->next = object;
2699 TRACE("Recording... not performing anything more\n");
2703 /* Ok, not recording any longer so do real work */
2704 object = This->stateBlock->lights;
2705 while (object != NULL && object->OriginalIndex != Index) object = object->next;
2707 /* If we didn't find it in the list of lights, time to add it */
2708 if (object == NULL) {
2709 PLIGHTINFOEL *insertAt,*prevPos;
2711 object = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(PLIGHTINFOEL));
2712 if (NULL == object) {
2713 return WINED3DERR_OUTOFVIDEOMEMORY;
2715 object->OriginalIndex = Index;
2716 object->glIndex = -1;
2718 /* Add it to the front of list with the idea that lights will be changed as needed
2719 BUT after any lights currently assigned GL indexes */
2720 insertAt = This->stateBlock->lights;
2722 while (insertAt != NULL && insertAt->glIndex != -1) {
2724 insertAt = insertAt->next;
2727 if (insertAt == NULL && prevPos == NULL) { /* Start of list */
2728 This->stateBlock->lights = object;
2729 } else if (insertAt == NULL) { /* End of list */
2730 prevPos->next = object;
2731 object->prev = prevPos;
2732 } else { /* Middle of chain */
2733 if (prevPos == NULL) {
2734 This->stateBlock->lights = object;
2736 prevPos->next = object;
2738 object->prev = prevPos;
2739 object->next = insertAt;
2740 insertAt->prev = object;
2744 /* Initialize the object */
2745 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,
2746 pLight->Diffuse.r, pLight->Diffuse.g, pLight->Diffuse.b, pLight->Diffuse.a,
2747 pLight->Specular.r, pLight->Specular.g, pLight->Specular.b, pLight->Specular.a,
2748 pLight->Ambient.r, pLight->Ambient.g, pLight->Ambient.b, pLight->Ambient.a);
2749 TRACE("... Pos(%f,%f,%f), Dirn(%f,%f,%f)\n", pLight->Position.x, pLight->Position.y, pLight->Position.z,
2750 pLight->Direction.x, pLight->Direction.y, pLight->Direction.z);
2751 TRACE("... Range(%f), Falloff(%f), Theta(%f), Phi(%f)\n", pLight->Range, pLight->Falloff, pLight->Theta, pLight->Phi);
2753 /* Save away the information */
2754 memcpy(&object->OriginalParms, pLight, sizeof(D3DLIGHT9));
2756 switch (pLight->Type) {
2757 case D3DLIGHT_POINT:
2759 object->lightPosn[0] = pLight->Position.x;
2760 object->lightPosn[1] = pLight->Position.y;
2761 object->lightPosn[2] = pLight->Position.z;
2762 object->lightPosn[3] = 1.0f;
2763 object->cutoff = 180.0f;
2767 case D3DLIGHT_DIRECTIONAL:
2769 object->lightPosn[0] = -pLight->Direction.x;
2770 object->lightPosn[1] = -pLight->Direction.y;
2771 object->lightPosn[2] = -pLight->Direction.z;
2772 object->lightPosn[3] = 0.0;
2773 object->exponent = 0.0f;
2774 object->cutoff = 180.0f;
2779 object->lightPosn[0] = pLight->Position.x;
2780 object->lightPosn[1] = pLight->Position.y;
2781 object->lightPosn[2] = pLight->Position.z;
2782 object->lightPosn[3] = 1.0;
2785 object->lightDirn[0] = pLight->Direction.x;
2786 object->lightDirn[1] = pLight->Direction.y;
2787 object->lightDirn[2] = pLight->Direction.z;
2788 object->lightDirn[3] = 1.0;
2791 * opengl-ish and d3d-ish spot lights use too different models for the
2792 * light "intensity" as a function of the angle towards the main light direction,
2793 * so we only can approximate very roughly.
2794 * however spot lights are rather rarely used in games (if ever used at all).
2795 * furthermore if still used, probably nobody pays attention to such details.
2797 if (pLight->Falloff == 0) {
2800 rho = pLight->Theta + (pLight->Phi - pLight->Theta)/(2*pLight->Falloff);
2802 if (rho < 0.0001) rho = 0.0001f;
2803 object->exponent = -0.3/log(cos(rho/2));
2804 object->cutoff = pLight->Phi*90/M_PI;
2810 FIXME("Unrecognized light type %d\n", pLight->Type);
2813 /* Update the live definitions if the light is currently assigned a glIndex */
2814 if (object->glIndex != -1) {
2815 setup_light(iface, object->glIndex, object);
2820 static HRESULT WINAPI IWineD3DDeviceImpl_GetLight(IWineD3DDevice *iface, DWORD Index, WINED3DLIGHT* pLight) {
2821 PLIGHTINFOEL *lightInfo = NULL;
2822 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2823 TRACE("(%p) : Idx(%ld), pLight(%p)\n", This, Index, pLight);
2825 /* Locate the light in the live lights */
2826 lightInfo = This->stateBlock->lights;
2827 while (lightInfo != NULL && lightInfo->OriginalIndex != Index) lightInfo = lightInfo->next;
2829 if (lightInfo == NULL) {
2830 TRACE("Light information requested but light not defined\n");
2831 return WINED3DERR_INVALIDCALL;
2834 memcpy(pLight, &lightInfo->OriginalParms, sizeof(D3DLIGHT9));
2839 * Get / Set Light Enable
2840 * (Note for consistency, renamed d3dx function by adding the 'set' prefix)
2842 static HRESULT WINAPI IWineD3DDeviceImpl_SetLightEnable(IWineD3DDevice *iface, DWORD Index, BOOL Enable) {
2843 PLIGHTINFOEL *lightInfo = NULL;
2844 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2845 TRACE("(%p) : Idx(%ld), enable? %d\n", This, Index, Enable);
2847 /* If recording state block, just add to end of lights chain with changedEnable set to true */
2848 if (This->isRecordingState) {
2849 lightInfo = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(PLIGHTINFOEL));
2850 if (NULL == lightInfo) {
2851 return WINED3DERR_OUTOFVIDEOMEMORY;
2853 lightInfo->OriginalIndex = Index;
2854 lightInfo->glIndex = -1;
2855 lightInfo->enabledChanged = TRUE;
2857 /* Add to the END of the chain of lights changes to be replayed */
2858 if (This->updateStateBlock->lights == NULL) {
2859 This->updateStateBlock->lights = lightInfo;
2861 PLIGHTINFOEL *temp = This->updateStateBlock->lights;
2862 while (temp->next != NULL) temp=temp->next;
2863 temp->next = lightInfo;
2865 TRACE("Recording... not performing anything more\n");
2869 /* Not recording... So, locate the light in the live lights */
2870 lightInfo = This->stateBlock->lights;
2871 while (lightInfo != NULL && lightInfo->OriginalIndex != Index) lightInfo = lightInfo->next;
2873 /* Special case - enabling an undefined light creates one with a strict set of parms! */
2874 if (lightInfo == NULL) {
2876 TRACE("Light enabled requested but light not defined, so defining one!\n");
2877 IWineD3DDeviceImpl_SetLight(iface, Index, &WINED3D_default_light);
2879 /* Search for it again! Should be fairly quick as near head of list */
2880 lightInfo = This->stateBlock->lights;
2881 while (lightInfo != NULL && lightInfo->OriginalIndex != Index) lightInfo = lightInfo->next;
2882 if (lightInfo == NULL) {
2883 FIXME("Adding default lights has failed dismally\n");
2884 return WINED3DERR_INVALIDCALL;
2888 /* OK, we now have a light... */
2889 if (Enable == FALSE) {
2891 /* If we are disabling it, check it was enabled, and
2892 still only do something if it has assigned a glIndex (which it should have!) */
2893 if ((lightInfo->lightEnabled) && (lightInfo->glIndex != -1)) {
2894 TRACE("Disabling light set up at gl idx %ld\n", lightInfo->glIndex);
2896 glDisable(GL_LIGHT0 + lightInfo->glIndex);
2897 checkGLcall("glDisable GL_LIGHT0+Index");
2900 TRACE("Nothing to do as light was not enabled\n");
2902 lightInfo->lightEnabled = FALSE;
2905 /* We are enabling it. If it is enabled, it's really simple */
2906 if (lightInfo->lightEnabled) {
2908 TRACE("Nothing to do as light was enabled\n");
2910 /* If it already has a glIndex, it's still simple */
2911 } else if (lightInfo->glIndex != -1) {
2912 TRACE("Reusing light as already set up at gl idx %ld\n", lightInfo->glIndex);
2913 lightInfo->lightEnabled = TRUE;
2915 glEnable(GL_LIGHT0 + lightInfo->glIndex);
2916 checkGLcall("glEnable GL_LIGHT0+Index already setup");
2919 /* Otherwise got to find space - lights are ordered gl indexes first */
2921 PLIGHTINFOEL *bsf = NULL;
2922 PLIGHTINFOEL *pos = This->stateBlock->lights;
2923 PLIGHTINFOEL *prev = NULL;
2927 /* Try to minimize changes as much as possible */
2928 while (pos != NULL && pos->glIndex != -1 && Index < This->maxConcurrentLights) {
2930 /* Try to remember which index can be replaced if necessary */
2931 if (bsf==NULL && pos->lightEnabled == FALSE) {
2932 /* Found a light we can replace, save as best replacement */
2936 /* Step to next space */
2942 /* If we have too many active lights, fail the call */
2943 if ((Index == This->maxConcurrentLights) && (bsf == NULL)) {
2944 FIXME("Program requests too many concurrent lights\n");
2945 return WINED3DERR_INVALIDCALL;
2947 /* If we have allocated all lights, but not all are enabled,
2948 reuse one which is not enabled */
2949 } else if (Index == This->maxConcurrentLights) {
2950 /* use bsf - Simply swap the new light and the BSF one */
2951 PLIGHTINFOEL *bsfNext = bsf->next;
2952 PLIGHTINFOEL *bsfPrev = bsf->prev;
2955 if (lightInfo->next != NULL) lightInfo->next->prev = bsf;
2956 if (bsf->prev != NULL) {
2957 bsf->prev->next = lightInfo;
2959 This->stateBlock->lights = lightInfo;
2962 /* If not side by side, lots of chains to update */
2963 if (bsf->next != lightInfo) {
2964 lightInfo->prev->next = bsf;
2965 bsf->next->prev = lightInfo;
2966 bsf->next = lightInfo->next;
2967 bsf->prev = lightInfo->prev;
2968 lightInfo->next = bsfNext;
2969 lightInfo->prev = bsfPrev;
2973 bsf->prev = lightInfo;
2974 bsf->next = lightInfo->next;
2975 lightInfo->next = bsf;
2976 lightInfo->prev = bsfPrev;
2981 glIndex = bsf->glIndex;
2983 lightInfo->glIndex = glIndex;
2984 lightInfo->lightEnabled = TRUE;
2986 /* Finally set up the light in gl itself */
2987 TRACE("Replacing light which was set up at gl idx %ld\n", lightInfo->glIndex);
2989 setup_light(iface, glIndex, lightInfo);
2990 glEnable(GL_LIGHT0 + glIndex);
2991 checkGLcall("glEnable GL_LIGHT0 new setup");
2994 /* If we reached the end of the allocated lights, with space in the
2995 gl lights, setup a new light */
2996 } else if (pos->glIndex == -1) {
2998 /* We reached the end of the allocated gl lights, so already
2999 know the index of the next one! */
3001 lightInfo->glIndex = glIndex;
3002 lightInfo->lightEnabled = TRUE;
3004 /* In an ideal world, it's already in the right place */
3005 if (lightInfo->prev == NULL || lightInfo->prev->glIndex!=-1) {
3006 /* No need to move it */
3008 /* Remove this light from the list */
3009 lightInfo->prev->next = lightInfo->next;
3010 if (lightInfo->next != NULL) {
3011 lightInfo->next->prev = lightInfo->prev;
3014 /* Add in at appropriate place (inbetween prev and pos) */
3015 lightInfo->prev = prev;
3016 lightInfo->next = pos;
3018 This->stateBlock->lights = lightInfo;
3020 prev->next = lightInfo;
3023 pos->prev = lightInfo;
3027 /* Finally set up the light in gl itself */
3028 TRACE("Defining new light at gl idx %ld\n", lightInfo->glIndex);
3030 setup_light(iface, glIndex, lightInfo);
3031 glEnable(GL_LIGHT0 + glIndex);
3032 checkGLcall("glEnable GL_LIGHT0 new setup");
3041 static HRESULT WINAPI IWineD3DDeviceImpl_GetLightEnable(IWineD3DDevice *iface, DWORD Index,BOOL* pEnable) {
3043 PLIGHTINFOEL *lightInfo = NULL;
3044 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3045 TRACE("(%p) : for idx(%ld)\n", This, Index);
3047 /* Locate the light in the live lights */
3048 lightInfo = This->stateBlock->lights;
3049 while (lightInfo != NULL && lightInfo->OriginalIndex != Index) lightInfo = lightInfo->next;
3051 if (lightInfo == NULL) {
3052 TRACE("Light enabled state requested but light not defined\n");
3053 return WINED3DERR_INVALIDCALL;
3055 *pEnable = lightInfo->lightEnabled;
3060 * Get / Set Clip Planes
3062 static HRESULT WINAPI IWineD3DDeviceImpl_SetClipPlane(IWineD3DDevice *iface, DWORD Index, CONST float *pPlane) {
3063 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3064 TRACE("(%p) : for idx %ld, %p\n", This, Index, pPlane);
3066 /* Validate Index */
3067 if (Index >= GL_LIMITS(clipplanes)) {
3068 TRACE("Application has requested clipplane this device doesn't support\n");
3069 return WINED3DERR_INVALIDCALL;
3072 This->updateStateBlock->changed.clipplane[Index] = TRUE;
3073 This->updateStateBlock->set.clipplane[Index] = TRUE;
3074 This->updateStateBlock->clipplane[Index][0] = pPlane[0];
3075 This->updateStateBlock->clipplane[Index][1] = pPlane[1];
3076 This->updateStateBlock->clipplane[Index][2] = pPlane[2];
3077 This->updateStateBlock->clipplane[Index][3] = pPlane[3];
3079 /* Handle recording of state blocks */
3080 if (This->isRecordingState) {
3081 TRACE("Recording... not performing anything\n");
3089 /* Clip Plane settings are affected by the model view in OpenGL, the View transform in direct3d */
3090 glMatrixMode(GL_MODELVIEW);
3092 glLoadMatrixf((float *) &This->stateBlock->transforms[D3DTS_VIEW].u.m[0][0]);
3094 TRACE("Clipplane [%f,%f,%f,%f]\n",
3095 This->updateStateBlock->clipplane[Index][0],
3096 This->updateStateBlock->clipplane[Index][1],
3097 This->updateStateBlock->clipplane[Index][2],
3098 This->updateStateBlock->clipplane[Index][3]);
3099 glClipPlane(GL_CLIP_PLANE0 + Index, This->updateStateBlock->clipplane[Index]);
3100 checkGLcall("glClipPlane");
3108 static HRESULT WINAPI IWineD3DDeviceImpl_GetClipPlane(IWineD3DDevice *iface, DWORD Index, float *pPlane) {
3109 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3110 TRACE("(%p) : for idx %ld\n", This, Index);
3112 /* Validate Index */
3113 if (Index >= GL_LIMITS(clipplanes)) {
3114 TRACE("Application has requested clipplane this device doesn't support\n");
3115 return WINED3DERR_INVALIDCALL;
3118 pPlane[0] = This->stateBlock->clipplane[Index][0];
3119 pPlane[1] = This->stateBlock->clipplane[Index][1];
3120 pPlane[2] = This->stateBlock->clipplane[Index][2];
3121 pPlane[3] = This->stateBlock->clipplane[Index][3];
3126 * Get / Set Clip Plane Status
3127 * WARNING: This code relies on the fact that D3DCLIPSTATUS8 == D3DCLIPSTATUS9
3129 static HRESULT WINAPI IWineD3DDeviceImpl_SetClipStatus(IWineD3DDevice *iface, CONST WINED3DCLIPSTATUS* pClipStatus) {
3130 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3131 FIXME("(%p) : stub\n", This);
3132 if (NULL == pClipStatus) {
3133 return WINED3DERR_INVALIDCALL;
3135 This->updateStateBlock->clip_status.ClipUnion = pClipStatus->ClipUnion;
3136 This->updateStateBlock->clip_status.ClipIntersection = pClipStatus->ClipIntersection;
3140 static HRESULT WINAPI IWineD3DDeviceImpl_GetClipStatus(IWineD3DDevice *iface, WINED3DCLIPSTATUS* pClipStatus) {
3141 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3142 FIXME("(%p) : stub\n", This);
3143 if (NULL == pClipStatus) {
3144 return WINED3DERR_INVALIDCALL;
3146 pClipStatus->ClipUnion = This->updateStateBlock->clip_status.ClipUnion;
3147 pClipStatus->ClipIntersection = This->updateStateBlock->clip_status.ClipIntersection;
3152 * Get / Set Material
3153 * WARNING: This code relies on the fact that D3DMATERIAL8 == D3DMATERIAL9
3155 static HRESULT WINAPI IWineD3DDeviceImpl_SetMaterial(IWineD3DDevice *iface, CONST WINED3DMATERIAL* pMaterial) {
3156 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3158 This->updateStateBlock->changed.material = TRUE;
3159 This->updateStateBlock->set.material = TRUE;
3160 memcpy(&This->updateStateBlock->material, pMaterial, sizeof(WINED3DMATERIAL));
3162 /* Handle recording of state blocks */
3163 if (This->isRecordingState) {
3164 TRACE("Recording... not performing anything\n");
3169 TRACE("(%p) : Diffuse (%f,%f,%f,%f)\n", This, pMaterial->Diffuse.r, pMaterial->Diffuse.g,
3170 pMaterial->Diffuse.b, pMaterial->Diffuse.a);
3171 TRACE("(%p) : Ambient (%f,%f,%f,%f)\n", This, pMaterial->Ambient.r, pMaterial->Ambient.g,
3172 pMaterial->Ambient.b, pMaterial->Ambient.a);
3173 TRACE("(%p) : Specular (%f,%f,%f,%f)\n", This, pMaterial->Specular.r, pMaterial->Specular.g,
3174 pMaterial->Specular.b, pMaterial->Specular.a);
3175 TRACE("(%p) : Emissive (%f,%f,%f,%f)\n", This, pMaterial->Emissive.r, pMaterial->Emissive.g,
3176 pMaterial->Emissive.b, pMaterial->Emissive.a);
3177 TRACE("(%p) : Power (%f)\n", This, pMaterial->Power);
3179 glMaterialfv(GL_FRONT_AND_BACK, GL_AMBIENT, (float*) &This->updateStateBlock->material.Ambient);
3180 checkGLcall("glMaterialfv(GL_AMBIENT)");
3181 glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, (float*) &This->updateStateBlock->material.Diffuse);
3182 checkGLcall("glMaterialfv(GL_DIFFUSE)");
3184 /* Only change material color if specular is enabled, otherwise it is set to black */
3185 if (This->stateBlock->renderState[WINED3DRS_SPECULARENABLE]) {
3186 glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, (float*) &This->updateStateBlock->material.Specular);
3187 checkGLcall("glMaterialfv(GL_SPECULAR");
3189 float black[4] = {0.0f, 0.0f, 0.0f, 0.0f};
3190 glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, &black[0]);
3191 checkGLcall("glMaterialfv(GL_SPECULAR");
3193 glMaterialfv(GL_FRONT_AND_BACK, GL_EMISSION, (float*) &This->updateStateBlock->material.Emissive);
3194 checkGLcall("glMaterialfv(GL_EMISSION)");
3195 glMaterialf(GL_FRONT_AND_BACK, GL_SHININESS, This->updateStateBlock->material.Power);
3196 checkGLcall("glMaterialf(GL_SHININESS");
3202 static HRESULT WINAPI IWineD3DDeviceImpl_GetMaterial(IWineD3DDevice *iface, WINED3DMATERIAL* pMaterial) {
3203 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3204 memcpy(pMaterial, &This->updateStateBlock->material, sizeof (WINED3DMATERIAL));
3205 TRACE("(%p) : Diffuse (%f,%f,%f,%f)\n", This, pMaterial->Diffuse.r, pMaterial->Diffuse.g,
3206 pMaterial->Diffuse.b, pMaterial->Diffuse.a);
3207 TRACE("(%p) : Ambient (%f,%f,%f,%f)\n", This, pMaterial->Ambient.r, pMaterial->Ambient.g,
3208 pMaterial->Ambient.b, pMaterial->Ambient.a);
3209 TRACE("(%p) : Specular (%f,%f,%f,%f)\n", This, pMaterial->Specular.r, pMaterial->Specular.g,
3210 pMaterial->Specular.b, pMaterial->Specular.a);
3211 TRACE("(%p) : Emissive (%f,%f,%f,%f)\n", This, pMaterial->Emissive.r, pMaterial->Emissive.g,
3212 pMaterial->Emissive.b, pMaterial->Emissive.a);
3213 TRACE("(%p) : Power (%f)\n", This, pMaterial->Power);
3221 static HRESULT WINAPI IWineD3DDeviceImpl_SetIndices(IWineD3DDevice *iface, IWineD3DIndexBuffer* pIndexData,
3222 UINT BaseVertexIndex) {
3223 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3224 IWineD3DIndexBuffer *oldIdxs;
3226 TRACE("(%p) : Setting to %p, base %d\n", This, pIndexData, BaseVertexIndex);
3227 oldIdxs = This->updateStateBlock->pIndexData;
3229 This->updateStateBlock->changed.indices = TRUE;
3230 This->updateStateBlock->set.indices = TRUE;
3231 This->updateStateBlock->pIndexData = pIndexData;
3232 This->updateStateBlock->baseVertexIndex = BaseVertexIndex;
3234 /* Handle recording of state blocks */
3235 if (This->isRecordingState) {
3236 TRACE("Recording... not performing anything\n");
3240 if (NULL != pIndexData) {
3241 IWineD3DIndexBuffer_AddRef(pIndexData);
3243 if (NULL != oldIdxs) {
3244 IWineD3DIndexBuffer_Release(oldIdxs);
3249 static HRESULT WINAPI IWineD3DDeviceImpl_GetIndices(IWineD3DDevice *iface, IWineD3DIndexBuffer** ppIndexData, UINT* pBaseVertexIndex) {
3250 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3252 *ppIndexData = This->stateBlock->pIndexData;
3254 /* up ref count on ppindexdata */
3256 IWineD3DIndexBuffer_AddRef(*ppIndexData);
3257 *pBaseVertexIndex = This->stateBlock->baseVertexIndex;
3258 TRACE("(%p) index data set to %p + %u\n", This, ppIndexData, This->stateBlock->baseVertexIndex);
3260 TRACE("(%p) No index data set\n", This);
3262 TRACE("Returning %p %d\n", *ppIndexData, *pBaseVertexIndex);
3268 * Get / Set Viewports
3270 static HRESULT WINAPI IWineD3DDeviceImpl_SetViewport(IWineD3DDevice *iface, CONST WINED3DVIEWPORT* pViewport) {
3271 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3273 TRACE("(%p)\n", This);
3274 This->updateStateBlock->changed.viewport = TRUE;
3275 This->updateStateBlock->set.viewport = TRUE;
3276 memcpy(&This->updateStateBlock->viewport, pViewport, sizeof(WINED3DVIEWPORT));
3278 /* Handle recording of state blocks */
3279 if (This->isRecordingState) {
3280 TRACE("Recording... not performing anything\n");
3283 This->viewport_changed = TRUE;
3287 TRACE("(%p) : x=%ld, y=%ld, wid=%ld, hei=%ld, minz=%f, maxz=%f\n", This,
3288 pViewport->X, pViewport->Y, pViewport->Width, pViewport->Height, pViewport->MinZ, pViewport->MaxZ);
3290 glDepthRange(pViewport->MinZ, pViewport->MaxZ);
3291 checkGLcall("glDepthRange");
3292 /* Note: GL requires lower left, DirectX supplies upper left */
3293 /* TODO: replace usage of renderTarget with context management */
3294 glViewport(pViewport->X,
3295 (((IWineD3DSurfaceImpl *)This->renderTarget)->currentDesc.Height - (pViewport->Y + pViewport->Height)),
3296 pViewport->Width, pViewport->Height);
3298 checkGLcall("glViewport");
3306 static HRESULT WINAPI IWineD3DDeviceImpl_GetViewport(IWineD3DDevice *iface, WINED3DVIEWPORT* pViewport) {
3307 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3308 TRACE("(%p)\n", This);
3309 memcpy(pViewport, &This->stateBlock->viewport, sizeof(WINED3DVIEWPORT));
3313 static void renderstate_stencil_twosided(
3314 IWineD3DDeviceImpl *This,
3321 GLint stencilPass ) {
3322 #if 0 /* Don't use OpenGL 2.0 calls for now */
3323 if(GL_EXTCALL(glStencilFuncSeparate) && GL_EXTCALL(glStencilOpSeparate)) {
3324 GL_EXTCALL(glStencilFuncSeparate(face, func, ref, mask));
3325 checkGLcall("glStencilFuncSeparate(...)");
3326 GL_EXTCALL(glStencilOpSeparate(face, stencilFail, depthFail, stencilPass));
3327 checkGLcall("glStencilOpSeparate(...)");
3331 if(GL_SUPPORT(EXT_STENCIL_TWO_SIDE)) {
3332 glEnable(GL_STENCIL_TEST_TWO_SIDE_EXT);
3333 checkGLcall("glEnable(GL_STENCIL_TEST_TWO_SIDE_EXT)");
3334 GL_EXTCALL(glActiveStencilFaceEXT(face));
3335 checkGLcall("glActiveStencilFaceEXT(...)");
3336 glStencilFunc(func, ref, mask);
3337 checkGLcall("glStencilFunc(...)");
3338 glStencilOp(stencilFail, depthFail, stencilPass);
3339 checkGLcall("glStencilOp(...)");
3340 } else if(GL_SUPPORT(ATI_SEPARATE_STENCIL)) {
3341 GL_EXTCALL(glStencilFuncSeparateATI(face, func, ref, mask));
3342 checkGLcall("glStencilFuncSeparateATI(...)");
3343 GL_EXTCALL(glStencilOpSeparateATI(face, stencilFail, depthFail, stencilPass));
3344 checkGLcall("glStencilOpSeparateATI(...)");
3346 ERR("Separate (two sided) stencil not supported on this version of opengl. Caps weren't honored?\n");
3350 static void renderstate_stencil(IWineD3DDeviceImpl *This, D3DRENDERSTATETYPE State, DWORD Value) {
3351 DWORD onesided_enable = FALSE;
3352 DWORD twosided_enable = FALSE;
3353 GLint func = GL_ALWAYS;
3354 GLint func_ccw = GL_ALWAYS;
3357 GLint stencilFail = GL_KEEP;
3358 GLint depthFail = GL_KEEP;
3359 GLint stencilPass = GL_KEEP;
3360 GLint stencilFail_ccw = GL_KEEP;
3361 GLint depthFail_ccw = GL_KEEP;
3362 GLint stencilPass_ccw = GL_KEEP;
3364 if( This->stateBlock->set.renderState[WINED3DRS_STENCILENABLE] )
3365 onesided_enable = This->stateBlock->renderState[WINED3DRS_STENCILENABLE];
3366 if( This->stateBlock->set.renderState[WINED3DRS_TWOSIDEDSTENCILMODE] )
3367 twosided_enable = This->stateBlock->renderState[WINED3DRS_TWOSIDEDSTENCILMODE];
3368 if( This->stateBlock->set.renderState[WINED3DRS_STENCILFUNC] )
3369 func = StencilFunc(This->stateBlock->renderState[WINED3DRS_STENCILFUNC]);
3370 if( This->stateBlock->set.renderState[WINED3DRS_CCW_STENCILFUNC] )
3371 func_ccw = StencilFunc(This->stateBlock->renderState[WINED3DRS_CCW_STENCILFUNC]);
3372 if( This->stateBlock->set.renderState[WINED3DRS_STENCILREF] )
3373 ref = This->stateBlock->renderState[WINED3DRS_STENCILREF];
3374 if( This->stateBlock->set.renderState[WINED3DRS_STENCILMASK] )
3375 mask = This->stateBlock->renderState[WINED3DRS_STENCILMASK];
3376 if( This->stateBlock->set.renderState[WINED3DRS_STENCILFAIL] )
3377 stencilFail = StencilOp(This->stateBlock->renderState[WINED3DRS_STENCILFAIL]);
3378 if( This->stateBlock->set.renderState[WINED3DRS_STENCILZFAIL] )
3379 depthFail = StencilOp(This->stateBlock->renderState[WINED3DRS_STENCILZFAIL]);
3380 if( This->stateBlock->set.renderState[WINED3DRS_STENCILPASS] )
3381 stencilPass = StencilOp(This->stateBlock->renderState[WINED3DRS_STENCILPASS]);
3382 if( This->stateBlock->set.renderState[WINED3DRS_CCW_STENCILFAIL] )
3383 stencilFail_ccw = StencilOp(This->stateBlock->renderState[WINED3DRS_CCW_STENCILFAIL]);
3384 if( This->stateBlock->set.renderState[WINED3DRS_CCW_STENCILZFAIL] )
3385 depthFail_ccw = StencilOp(This->stateBlock->renderState[WINED3DRS_CCW_STENCILZFAIL]);
3386 if( This->stateBlock->set.renderState[WINED3DRS_CCW_STENCILPASS] )
3387 stencilPass_ccw = StencilOp(This->stateBlock->renderState[WINED3DRS_CCW_STENCILPASS]);
3390 case WINED3DRS_STENCILENABLE :
3391 onesided_enable = Value;
3393 case WINED3DRS_TWOSIDEDSTENCILMODE :
3394 twosided_enable = Value;
3396 case WINED3DRS_STENCILFUNC :
3397 func = StencilFunc(Value);
3399 case WINED3DRS_CCW_STENCILFUNC :
3400 func_ccw = StencilFunc(Value);
3402 case WINED3DRS_STENCILREF :
3405 case WINED3DRS_STENCILMASK :
3408 case WINED3DRS_STENCILFAIL :
3409 stencilFail = StencilOp(Value);
3411 case WINED3DRS_STENCILZFAIL :
3412 depthFail = StencilOp(Value);
3414 case WINED3DRS_STENCILPASS :
3415 stencilPass = StencilOp(Value);
3417 case WINED3DRS_CCW_STENCILFAIL :
3418 stencilFail_ccw = StencilOp(Value);
3420 case WINED3DRS_CCW_STENCILZFAIL :
3421 depthFail_ccw = StencilOp(Value);
3423 case WINED3DRS_CCW_STENCILPASS :
3424 stencilPass_ccw = StencilOp(Value);
3427 ERR("This should not happen!");
3430 TRACE("(onesided %ld, twosided %ld, ref %x, mask %x, \
3431 GL_FRONT: func: %x, fail %x, zfail %x, zpass %x \
3432 GL_BACK: func: %x, fail %x, zfail %x, zpass %x )\n",
3433 onesided_enable, twosided_enable, ref, mask,
3434 func, stencilFail, depthFail, stencilPass,
3435 func_ccw, stencilFail_ccw, depthFail_ccw, stencilPass_ccw);
3437 if (twosided_enable) {
3438 renderstate_stencil_twosided(This, GL_FRONT, func, ref, mask, stencilFail, depthFail, stencilPass);
3439 renderstate_stencil_twosided(This, GL_BACK, func_ccw, ref, mask, stencilFail_ccw, depthFail_ccw, stencilPass_ccw);
3441 if (onesided_enable) {
3442 glEnable(GL_STENCIL_TEST);
3443 checkGLcall("glEnable GL_STENCIL_TEST");
3444 glStencilFunc(func, ref, mask);
3445 checkGLcall("glStencilFunc(...)");
3446 glStencilOp(stencilFail, depthFail, stencilPass);
3447 checkGLcall("glStencilOp(...)");
3449 glDisable(GL_STENCIL_TEST);
3450 checkGLcall("glDisable GL_STENCIL_TEST");
3456 * Get / Set Render States
3457 * TODO: Verify against dx9 definitions
3459 static HRESULT WINAPI IWineD3DDeviceImpl_SetRenderState(IWineD3DDevice *iface, D3DRENDERSTATETYPE State, DWORD Value) {
3461 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3462 DWORD OldValue = This->stateBlock->renderState[State];
3464 /* Simple way of referring to either a DWORD or a 4 byte float */
3470 TRACE("(%p)->state = %s(%d), value = %ld\n", This, debug_d3drenderstate(State), State, Value);
3471 This->updateStateBlock->changed.renderState[State] = TRUE;
3472 This->updateStateBlock->set.renderState[State] = TRUE;
3473 This->updateStateBlock->renderState[State] = Value;
3475 /* Handle recording of state blocks */
3476 if (This->isRecordingState) {
3477 TRACE("Recording... not performing anything\n");
3484 case WINED3DRS_FILLMODE :
3485 switch ((D3DFILLMODE) Value) {
3486 case D3DFILL_POINT : glPolygonMode(GL_FRONT_AND_BACK, GL_POINT); break;
3487 case D3DFILL_WIREFRAME : glPolygonMode(GL_FRONT_AND_BACK, GL_LINE); break;
3488 case D3DFILL_SOLID : glPolygonMode(GL_FRONT_AND_BACK, GL_FILL); break;
3490 FIXME("Unrecognized WINED3DRS_FILLMODE value %ld\n", Value);
3492 checkGLcall("glPolygonMode (fillmode)");
3495 case WINED3DRS_LIGHTING :
3497 glEnable(GL_LIGHTING);
3498 checkGLcall("glEnable GL_LIGHTING");
3500 glDisable(GL_LIGHTING);
3501 checkGLcall("glDisable GL_LIGHTING");
3505 case WINED3DRS_ZENABLE :
3506 switch ((D3DZBUFFERTYPE) Value) {
3508 glDisable(GL_DEPTH_TEST);
3509 checkGLcall("glDisable GL_DEPTH_TEST");
3512 glEnable(GL_DEPTH_TEST);
3513 checkGLcall("glEnable GL_DEPTH_TEST");
3516 glEnable(GL_DEPTH_TEST);
3517 checkGLcall("glEnable GL_DEPTH_TEST");
3518 FIXME("W buffer is not well handled\n");
3521 FIXME("Unrecognized D3DZBUFFERTYPE value %ld\n", Value);
3525 case WINED3DRS_CULLMODE :
3527 /* If we are culling "back faces with clockwise vertices" then
3528 set front faces to be counter clockwise and enable culling
3530 switch ((D3DCULL) Value) {
3532 glDisable(GL_CULL_FACE);
3533 checkGLcall("glDisable GL_CULL_FACE");
3536 glEnable(GL_CULL_FACE);
3537 checkGLcall("glEnable GL_CULL_FACE");
3538 if (This->renderUpsideDown) {
3540 checkGLcall("glFrontFace GL_CW");
3542 glFrontFace(GL_CCW);
3543 checkGLcall("glFrontFace GL_CCW");
3545 glCullFace(GL_BACK);
3548 glEnable(GL_CULL_FACE);
3549 checkGLcall("glEnable GL_CULL_FACE");
3550 if (This->renderUpsideDown) {
3551 glFrontFace(GL_CCW);
3552 checkGLcall("glFrontFace GL_CCW");
3555 checkGLcall("glFrontFace GL_CW");
3557 glCullFace(GL_BACK);
3560 FIXME("Unrecognized/Unhandled D3DCULL value %ld\n", Value);
3564 case WINED3DRS_SHADEMODE :
3565 switch ((D3DSHADEMODE) Value) {
3567 glShadeModel(GL_FLAT);
3568 checkGLcall("glShadeModel");
3570 case D3DSHADE_GOURAUD:
3571 glShadeModel(GL_SMOOTH);
3572 checkGLcall("glShadeModel");
3574 case D3DSHADE_PHONG:
3575 FIXME("D3DSHADE_PHONG isn't supported?\n");
3578 return WINED3DERR_INVALIDCALL;
3580 FIXME("Unrecognized/Unhandled D3DSHADEMODE value %ld\n", Value);
3584 case WINED3DRS_DITHERENABLE :
3586 glEnable(GL_DITHER);
3587 checkGLcall("glEnable GL_DITHER");
3589 glDisable(GL_DITHER);
3590 checkGLcall("glDisable GL_DITHER");
3594 case WINED3DRS_ZWRITEENABLE :
3597 checkGLcall("glDepthMask");
3600 checkGLcall("glDepthMask");
3604 case WINED3DRS_ZFUNC :
3606 int glParm = GL_LESS;
3608 switch ((D3DCMPFUNC) Value) {
3609 case D3DCMP_NEVER: glParm=GL_NEVER; break;
3610 case D3DCMP_LESS: glParm=GL_LESS; break;
3611 case D3DCMP_EQUAL: glParm=GL_EQUAL; break;
3612 case D3DCMP_LESSEQUAL: glParm=GL_LEQUAL; break;
3613 case D3DCMP_GREATER: glParm=GL_GREATER; break;
3614 case D3DCMP_NOTEQUAL: glParm=GL_NOTEQUAL; break;
3615 case D3DCMP_GREATEREQUAL: glParm=GL_GEQUAL; break;
3616 case D3DCMP_ALWAYS: glParm=GL_ALWAYS; break;
3618 FIXME("Unrecognized/Unhandled D3DCMPFUNC value %ld\n", Value);
3620 glDepthFunc(glParm);
3621 checkGLcall("glDepthFunc");
3625 case WINED3DRS_AMBIENT :
3628 D3DCOLORTOGLFLOAT4(Value, col);
3629 TRACE("Setting ambient to (%f,%f,%f,%f)\n", col[0], col[1], col[2], col[3]);
3630 glLightModelfv(GL_LIGHT_MODEL_AMBIENT, col);
3631 checkGLcall("glLightModel for MODEL_AMBIENT");
3636 case WINED3DRS_ALPHABLENDENABLE :
3639 checkGLcall("glEnable GL_BLEND");
3641 glDisable(GL_BLEND);
3642 checkGLcall("glDisable GL_BLEND");
3646 case WINED3DRS_SRCBLEND :
3647 case WINED3DRS_DESTBLEND :
3649 int newVal = GL_ZERO;
3651 case D3DBLEND_ZERO : newVal = GL_ZERO; break;
3652 case D3DBLEND_ONE : newVal = GL_ONE; break;
3653 case D3DBLEND_SRCCOLOR : newVal = GL_SRC_COLOR; break;
3654 case D3DBLEND_INVSRCCOLOR : newVal = GL_ONE_MINUS_SRC_COLOR; break;
3655 case D3DBLEND_SRCALPHA : newVal = GL_SRC_ALPHA; break;
3656 case D3DBLEND_INVSRCALPHA : newVal = GL_ONE_MINUS_SRC_ALPHA; break;
3657 case D3DBLEND_DESTALPHA : newVal = GL_DST_ALPHA; break;
3658 case D3DBLEND_INVDESTALPHA : newVal = GL_ONE_MINUS_DST_ALPHA; break;
3659 case D3DBLEND_DESTCOLOR : newVal = GL_DST_COLOR; break;
3660 case D3DBLEND_INVDESTCOLOR : newVal = GL_ONE_MINUS_DST_COLOR; break;
3661 case D3DBLEND_SRCALPHASAT : newVal = GL_SRC_ALPHA_SATURATE; break;
3663 case D3DBLEND_BOTHSRCALPHA : newVal = GL_SRC_ALPHA;
3664 This->srcBlend = newVal;
3665 This->dstBlend = newVal;
3668 case D3DBLEND_BOTHINVSRCALPHA : newVal = GL_ONE_MINUS_SRC_ALPHA;
3669 This->srcBlend = newVal;
3670 This->dstBlend = newVal;
3673 FIXME("Unrecognized src/dest blend value %ld (%d)\n", Value, State);
3676 if (State == WINED3DRS_SRCBLEND) This->srcBlend = newVal;
3677 if (State == WINED3DRS_DESTBLEND) This->dstBlend = newVal;
3678 TRACE("glBlendFunc src=%x, dst=%x\n", This->srcBlend, This->dstBlend);
3679 glBlendFunc(This->srcBlend, This->dstBlend);
3681 checkGLcall("glBlendFunc");
3685 case WINED3DRS_ALPHATESTENABLE :
3686 case WINED3DRS_ALPHAFUNC :
3687 case WINED3DRS_ALPHAREF :
3688 case WINED3DRS_COLORKEYENABLE :
3691 float ref = GL_LESS;
3692 BOOL enable_ckey = FALSE;
3694 IWineD3DSurfaceImpl *surf;
3696 /* Find out if the texture on the first stage has a ckey set */
3697 if(This->stateBlock->textures[0]) {
3698 surf = (IWineD3DSurfaceImpl *) ((IWineD3DTextureImpl *)This->stateBlock->textures[0])->surfaces[0];
3699 if(surf->CKeyFlags & DDSD_CKSRCBLT) enable_ckey = TRUE;
3702 if (This->stateBlock->renderState[WINED3DRS_ALPHATESTENABLE] ||
3703 (This->stateBlock->renderState[WINED3DRS_COLORKEYENABLE] && enable_ckey)) {
3704 glEnable(GL_ALPHA_TEST);
3705 checkGLcall("glEnable GL_ALPHA_TEST");
3707 glDisable(GL_ALPHA_TEST);
3708 checkGLcall("glDisable GL_ALPHA_TEST");
3709 /* Alpha test is disabled, don't bother setting the params - it will happen on the next
3715 if(This->stateBlock->renderState[WINED3DRS_COLORKEYENABLE] && enable_ckey) {
3716 glParm = GL_NOTEQUAL;
3719 ref = ((float) This->stateBlock->renderState[WINED3DRS_ALPHAREF]) / 255.0f;
3721 switch ((D3DCMPFUNC) This->stateBlock->renderState[WINED3DRS_ALPHAFUNC]) {
3722 case D3DCMP_NEVER: glParm = GL_NEVER; break;
3723 case D3DCMP_LESS: glParm = GL_LESS; break;
3724 case D3DCMP_EQUAL: glParm = GL_EQUAL; break;
3725 case D3DCMP_LESSEQUAL: glParm = GL_LEQUAL; break;
3726 case D3DCMP_GREATER: glParm = GL_GREATER; break;
3727 case D3DCMP_NOTEQUAL: glParm = GL_NOTEQUAL; break;
3728 case D3DCMP_GREATEREQUAL: glParm = GL_GEQUAL; break;
3729 case D3DCMP_ALWAYS: glParm = GL_ALWAYS; break;
3731 FIXME("Unrecognized/Unhandled D3DCMPFUNC value %ld\n", Value);
3734 This->alphafunc = glParm;
3735 glAlphaFunc(glParm, ref);
3736 checkGLcall("glAlphaFunc");
3740 case WINED3DRS_CLIPPLANEENABLE :
3741 case WINED3DRS_CLIPPING :
3743 /* Ensure we only do the changed clip planes */
3744 DWORD enable = 0xFFFFFFFF;
3745 DWORD disable = 0x00000000;
3747 /* If enabling / disabling all */
3748 if (State == WINED3DRS_CLIPPING) {
3750 enable = This->stateBlock->renderState[WINED3DRS_CLIPPLANEENABLE];
3753 disable = This->stateBlock->renderState[WINED3DRS_CLIPPLANEENABLE];
3757 enable = Value & ~OldValue;
3758 disable = ~Value & OldValue;
3761 if (enable & D3DCLIPPLANE0) { glEnable(GL_CLIP_PLANE0); checkGLcall("glEnable(clip plane 0)"); }
3762 if (enable & D3DCLIPPLANE1) { glEnable(GL_CLIP_PLANE1); checkGLcall("glEnable(clip plane 1)"); }
3763 if (enable & D3DCLIPPLANE2) { glEnable(GL_CLIP_PLANE2); checkGLcall("glEnable(clip plane 2)"); }
3764 if (enable & D3DCLIPPLANE3) { glEnable(GL_CLIP_PLANE3); checkGLcall("glEnable(clip plane 3)"); }
3765 if (enable & D3DCLIPPLANE4) { glEnable(GL_CLIP_PLANE4); checkGLcall("glEnable(clip plane 4)"); }
3766 if (enable & D3DCLIPPLANE5) { glEnable(GL_CLIP_PLANE5); checkGLcall("glEnable(clip plane 5)"); }
3768 if (disable & D3DCLIPPLANE0) { glDisable(GL_CLIP_PLANE0); checkGLcall("glDisable(clip plane 0)"); }
3769 if (disable & D3DCLIPPLANE1) { glDisable(GL_CLIP_PLANE1); checkGLcall("glDisable(clip plane 1)"); }
3770 if (disable & D3DCLIPPLANE2) { glDisable(GL_CLIP_PLANE2); checkGLcall("glDisable(clip plane 2)"); }
3771 if (disable & D3DCLIPPLANE3) { glDisable(GL_CLIP_PLANE3); checkGLcall("glDisable(clip plane 3)"); }
3772 if (disable & D3DCLIPPLANE4) { glDisable(GL_CLIP_PLANE4); checkGLcall("glDisable(clip plane 4)"); }
3773 if (disable & D3DCLIPPLANE5) { glDisable(GL_CLIP_PLANE5); checkGLcall("glDisable(clip plane 5)"); }
3775 /** update clipping status */
3777 This->stateBlock->clip_status.ClipUnion = 0;
3778 This->stateBlock->clip_status.ClipIntersection = 0xFFFFFFFF;
3780 This->stateBlock->clip_status.ClipUnion = 0;
3781 This->stateBlock->clip_status.ClipIntersection = 0;
3786 case WINED3DRS_BLENDOP :
3788 int glParm = GL_FUNC_ADD;
3790 switch ((D3DBLENDOP) Value) {
3791 case D3DBLENDOP_ADD : glParm = GL_FUNC_ADD; break;
3792 case D3DBLENDOP_SUBTRACT : glParm = GL_FUNC_SUBTRACT; break;
3793 case D3DBLENDOP_REVSUBTRACT : glParm = GL_FUNC_REVERSE_SUBTRACT; break;
3794 case D3DBLENDOP_MIN : glParm = GL_MIN; break;
3795 case D3DBLENDOP_MAX : glParm = GL_MAX; break;
3797 FIXME("Unrecognized/Unhandled D3DBLENDOP value %ld\n", Value);
3800 if(GL_SUPPORT(ARB_IMAGING)) {
3801 TRACE("glBlendEquation(%x)\n", glParm);
3802 GL_EXTCALL(glBlendEquation(glParm));
3803 checkGLcall("glBlendEquation");
3805 WARN("Unsupported in local OpenGL implementation: glBlendEquation\n");
3810 case WINED3DRS_TEXTUREFACTOR :
3814 /* Note the texture color applies to all textures whereas
3815 GL_TEXTURE_ENV_COLOR applies to active only */
3817 D3DCOLORTOGLFLOAT4(Value, col);
3818 /* Set the default alpha blend color */
3819 if (GL_SUPPORT(ARB_IMAGING)) {
3820 GL_EXTCALL(glBlendColor(col[0], col[1], col[2], col[3]));
3821 checkGLcall("glBlendColor");
3823 WARN("Unsupported in local OpenGL implementation: glBlendColor\n");
3826 if (!GL_SUPPORT(NV_REGISTER_COMBINERS)) {
3827 /* And now the default texture color as well */
3828 for (i = 0; i < GL_LIMITS(texture_stages); i++) {
3829 /* Note the D3DRS value applies to all textures, but GL has one
3830 per texture, so apply it now ready to be used! */
3831 if (GL_SUPPORT(ARB_MULTITEXTURE)) {
3832 GL_EXTCALL(glActiveTextureARB(GL_TEXTURE0_ARB + i));
3833 checkGLcall("glActiveTextureARB");
3835 FIXME("Program using multiple concurrent textures which this opengl implementation doesn't support\n");
3838 glTexEnvfv(GL_TEXTURE_ENV, GL_TEXTURE_ENV_COLOR, &col[0]);
3839 checkGLcall("glTexEnvfv(GL_TEXTURE_ENV, GL_TEXTURE_ENV_COLOR, color);");
3845 case WINED3DRS_SPECULARENABLE :
3847 /* Originally this used glLightModeli(GL_LIGHT_MODEL_COLOR_CONTROL,GL_SEPARATE_SPECULAR_COLOR)
3848 and (GL_LIGHT_MODEL_COLOR_CONTROL,GL_SINGLE_COLOR) to swap between enabled/disabled
3849 specular color. This is wrong:
3850 Separate specular color means the specular colour is maintained separately, whereas
3851 single color means it is merged in. However in both cases they are being used to
3853 To disable specular color, set it explicitly to black and turn off GL_COLOR_SUM_EXT
3854 NOTE: If not supported don't give FIXMEs the impact is really minimal and very few people are
3858 glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, (float*) &This->updateStateBlock->material.Specular);
3859 checkGLcall("glMaterialfv");
3860 if (GL_SUPPORT(EXT_SECONDARY_COLOR)) {
3861 glEnable(GL_COLOR_SUM_EXT);
3863 TRACE("Specular colors cannot be enabled in this version of opengl\n");
3865 checkGLcall("glEnable(GL_COLOR_SUM)");
3867 float black[4] = {0.0f, 0.0f, 0.0f, 0.0f};
3869 /* for the case of enabled lighting: */
3870 glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, &black[0]);
3871 checkGLcall("glMaterialfv");
3873 /* for the case of disabled lighting: */
3874 if (GL_SUPPORT(EXT_SECONDARY_COLOR)) {
3875 glDisable(GL_COLOR_SUM_EXT);
3877 TRACE("Specular colors cannot be disabled in this version of opengl\n");
3879 checkGLcall("glDisable(GL_COLOR_SUM)");
3884 case WINED3DRS_STENCILENABLE :
3885 case WINED3DRS_TWOSIDEDSTENCILMODE :
3886 case WINED3DRS_STENCILFUNC :
3887 case WINED3DRS_CCW_STENCILFUNC :
3888 case WINED3DRS_STENCILREF :
3889 case WINED3DRS_STENCILMASK :
3890 case WINED3DRS_STENCILFAIL :
3891 case WINED3DRS_STENCILZFAIL :
3892 case WINED3DRS_STENCILPASS :
3893 case WINED3DRS_CCW_STENCILFAIL :
3894 case WINED3DRS_CCW_STENCILZFAIL :
3895 case WINED3DRS_CCW_STENCILPASS :
3896 renderstate_stencil(This, State, Value);
3898 case WINED3DRS_STENCILWRITEMASK :
3900 glStencilMask(Value);
3901 TRACE("glStencilMask(%lu)\n", Value);
3902 checkGLcall("glStencilMask");
3906 case WINED3DRS_FOGENABLE :
3910 checkGLcall("glEnable GL_FOG");
3913 checkGLcall("glDisable GL_FOG");
3918 case WINED3DRS_RANGEFOGENABLE :
3921 TRACE("Enabled RANGEFOG");
3923 TRACE("Disabled RANGEFOG");
3928 case WINED3DRS_FOGCOLOR :
3931 D3DCOLORTOGLFLOAT4(Value, col);
3932 /* Set the default alpha blend color */
3933 glFogfv(GL_FOG_COLOR, &col[0]);
3934 checkGLcall("glFog GL_FOG_COLOR");
3938 case WINED3DRS_FOGTABLEMODE :
3939 case WINED3DRS_FOGVERTEXMODE :
3941 /* 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." */
3942 if(This->stateBlock->renderState[WINED3DRS_FOGTABLEMODE] == D3DFOG_NONE) {
3943 glHint(GL_FOG_HINT, GL_FASTEST);
3944 checkGLcall("glHint(GL_FOG_HINT, GL_FASTEST)");
3945 switch (This->stateBlock->renderState[WINED3DRS_FOGVERTEXMODE]) {
3946 /* Processed vertices have their fog factor stored in the specular value. Fall too the none case.
3947 * If we are drawing untransformed vertices atm, d3ddevice_set_ortho will update the fog
3950 if(!This->last_was_rhw) {
3951 glFogi(GL_FOG_MODE, GL_EXP);
3952 checkGLcall("glFogi(GL_FOG_MODE, GL_EXP");
3953 if(GL_SUPPORT(EXT_FOG_COORD)) {
3954 glFogi(GL_FOG_COORDINATE_SOURCE_EXT, GL_FRAGMENT_DEPTH_EXT);
3955 checkGLcall("glFogi(GL_FOG_COORDINATE_SOURCE_EXT, GL_FRAGMENT_DEPTH_EXT");
3956 IWineD3DDevice_SetRenderState(iface, WINED3DRS_FOGSTART, This->stateBlock->renderState[WINED3DRS_FOGSTART]);
3957 IWineD3DDevice_SetRenderState(iface, WINED3DRS_FOGEND, This->stateBlock->renderState[WINED3DRS_FOGEND]);
3963 if(!This->last_was_rhw) {
3964 glFogi(GL_FOG_MODE, GL_EXP2);
3965 checkGLcall("glFogi(GL_FOG_MODE, GL_EXP2");
3966 if(GL_SUPPORT(EXT_FOG_COORD)) {
3967 glFogi(GL_FOG_COORDINATE_SOURCE_EXT, GL_FRAGMENT_DEPTH_EXT);
3968 checkGLcall("glFogi(GL_FOG_COORDINATE_SOURCE_EXT, GL_FRAGMENT_DEPTH_EXT");
3969 IWineD3DDevice_SetRenderState(iface, WINED3DRS_FOGSTART, This->stateBlock->renderState[WINED3DRS_FOGSTART]);
3970 IWineD3DDevice_SetRenderState(iface, WINED3DRS_FOGEND, This->stateBlock->renderState[WINED3DRS_FOGEND]);
3975 case D3DFOG_LINEAR: {
3976 if(!This->last_was_rhw) {
3977 glFogi(GL_FOG_MODE, GL_LINEAR);
3978 checkGLcall("glFogi(GL_FOG_MODE, GL_LINEAR");
3979 if(GL_SUPPORT(EXT_FOG_COORD)) {
3980 glFogi(GL_FOG_COORDINATE_SOURCE_EXT, GL_FRAGMENT_DEPTH_EXT);
3981 checkGLcall("glFogi(GL_FOG_COORDINATE_SOURCE_EXT, GL_FRAGMENT_DEPTH_EXT");
3982 IWineD3DDevice_SetRenderState(iface, WINED3DRS_FOGSTART, This->stateBlock->renderState[WINED3DRS_FOGSTART]);
3983 IWineD3DDevice_SetRenderState(iface, WINED3DRS_FOGEND, This->stateBlock->renderState[WINED3DRS_FOGEND]);
3989 /* Both are none? According to msdn the alpha channel of the specular
3990 * color contains a fog factor. Set it in drawStridedSlow.
3991 * Same happens with Vertexfog on transformed vertices
3993 if(GL_SUPPORT(EXT_FOG_COORD)) {
3994 glFogi(GL_FOG_COORDINATE_SOURCE_EXT, GL_FOG_COORDINATE_EXT);
3995 checkGLcall("glFogi(GL_FOG_COORDINATE_SOURCE_EXT, GL_FOG_COORDINATE_EXT)\n");
3996 glFogi(GL_FOG_MODE, GL_LINEAR);
3997 checkGLcall("glFogi(GL_FOG_MODE, GL_LINEAR)");
3998 glFogf(GL_FOG_START, (float) 0xff);
3999 checkGLcall("glFogfv GL_FOG_START");
4000 glFogf(GL_FOG_END, 0.0);
4001 checkGLcall("glFogfv GL_FOG_END");
4003 /* Disable GL fog, handle this in software in drawStridedSlow */
4005 checkGLcall("glDisable(GL_FOG)");
4009 default: FIXME("Unexpected WINED3DRS_FOGVERTEXMODE %ld\n", This->stateBlock->renderState[WINED3DRS_FOGVERTEXMODE]);
4012 glHint(GL_FOG_HINT, GL_NICEST);
4013 checkGLcall("glHint(GL_FOG_HINT, GL_NICEST)");
4014 switch (This->stateBlock->renderState[WINED3DRS_FOGTABLEMODE]) {
4015 case D3DFOG_EXP: glFogi(GL_FOG_MODE, GL_EXP);
4016 checkGLcall("glFogi(GL_FOG_MODE, GL_EXP");
4017 if(GL_SUPPORT(EXT_FOG_COORD)) {
4018 glFogi(GL_FOG_COORDINATE_SOURCE_EXT, GL_FRAGMENT_DEPTH_EXT);
4019 checkGLcall("glFogi(GL_FOG_COORDINATE_SOURCE_EXT, GL_FRAGMENT_DEPTH_EXT");
4020 IWineD3DDevice_SetRenderState(iface, WINED3DRS_FOGSTART, This->stateBlock->renderState[WINED3DRS_FOGSTART]);
4021 IWineD3DDevice_SetRenderState(iface, WINED3DRS_FOGEND, This->stateBlock->renderState[WINED3DRS_FOGEND]);
4024 case D3DFOG_EXP2: glFogi(GL_FOG_MODE, GL_EXP2);
4025 checkGLcall("glFogi(GL_FOG_MODE, GL_EXP2");
4026 if(GL_SUPPORT(EXT_FOG_COORD)) {
4027 glFogi(GL_FOG_COORDINATE_SOURCE_EXT, GL_FRAGMENT_DEPTH_EXT);
4028 checkGLcall("glFogi(GL_FOG_COORDINATE_SOURCE_EXT, GL_FRAGMENT_DEPTH_EXT");
4029 IWineD3DDevice_SetRenderState(iface, WINED3DRS_FOGSTART, This->stateBlock->renderState[WINED3DRS_FOGSTART]);
4030 IWineD3DDevice_SetRenderState(iface, WINED3DRS_FOGEND, This->stateBlock->renderState[WINED3DRS_FOGEND]);
4033 case D3DFOG_LINEAR: glFogi(GL_FOG_MODE, GL_LINEAR);
4034 checkGLcall("glFogi(GL_FOG_MODE, GL_LINEAR");
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_NONE: /* Won't happen */
4043 default: FIXME("Unexpected WINED3DRS_FOGTABLEMODE %ld\n", This->stateBlock->renderState[WINED3DRS_FOGTABLEMODE]);
4046 if (GL_SUPPORT(NV_FOG_DISTANCE)) {
4047 glFogi(GL_FOG_DISTANCE_MODE_NV, GL_EYE_PLANE_ABSOLUTE_NV);
4052 case WINED3DRS_FOGSTART :
4055 glFogfv(GL_FOG_START, &tmpvalue.f);
4056 checkGLcall("glFogf(GL_FOG_START, (float) Value)");
4057 TRACE("Fog Start == %f\n", tmpvalue.f);
4061 case WINED3DRS_FOGEND :
4064 glFogfv(GL_FOG_END, &tmpvalue.f);
4065 checkGLcall("glFogf(GL_FOG_END, (float) Value)");
4066 TRACE("Fog End == %f\n", tmpvalue.f);
4070 case WINED3DRS_FOGDENSITY :
4073 glFogfv(GL_FOG_DENSITY, &tmpvalue.f);
4074 checkGLcall("glFogf(GL_FOG_DENSITY, (float) Value)");
4078 case WINED3DRS_VERTEXBLEND :
4080 This->updateStateBlock->vertex_blend = (D3DVERTEXBLENDFLAGS) Value;
4081 TRACE("Vertex Blending state to %ld\n", Value);
4085 case WINED3DRS_TWEENFACTOR :
4088 This->updateStateBlock->tween_factor = tmpvalue.f;
4089 TRACE("Vertex Blending Tween Factor to %f\n", This->updateStateBlock->tween_factor);
4093 case WINED3DRS_INDEXEDVERTEXBLENDENABLE :
4095 TRACE("Indexed Vertex Blend Enable to %ul\n", (BOOL) Value);
4099 case WINED3DRS_COLORVERTEX :
4100 case WINED3DRS_DIFFUSEMATERIALSOURCE :
4101 case WINED3DRS_SPECULARMATERIALSOURCE :
4102 case WINED3DRS_AMBIENTMATERIALSOURCE :
4103 case WINED3DRS_EMISSIVEMATERIALSOURCE :
4105 GLenum Parm = GL_AMBIENT_AND_DIFFUSE;
4107 if (This->stateBlock->renderState[WINED3DRS_COLORVERTEX]) {
4108 TRACE("diff %ld, amb %ld, emis %ld, spec %ld\n",
4109 This->stateBlock->renderState[WINED3DRS_DIFFUSEMATERIALSOURCE],
4110 This->stateBlock->renderState[WINED3DRS_AMBIENTMATERIALSOURCE],
4111 This->stateBlock->renderState[WINED3DRS_EMISSIVEMATERIALSOURCE],
4112 This->stateBlock->renderState[WINED3DRS_SPECULARMATERIALSOURCE]);
4114 if (This->stateBlock->renderState[WINED3DRS_DIFFUSEMATERIALSOURCE] == D3DMCS_COLOR1) {
4115 if (This->stateBlock->renderState[WINED3DRS_AMBIENTMATERIALSOURCE] == D3DMCS_COLOR1) {
4116 Parm = GL_AMBIENT_AND_DIFFUSE;
4120 } else if (This->stateBlock->renderState[WINED3DRS_AMBIENTMATERIALSOURCE] == D3DMCS_COLOR1) {
4122 } else if (This->stateBlock->renderState[WINED3DRS_EMISSIVEMATERIALSOURCE] == D3DMCS_COLOR1) {
4124 } else if (This->stateBlock->renderState[WINED3DRS_SPECULARMATERIALSOURCE] == D3DMCS_COLOR1) {
4131 if (This->tracking_color != DISABLED_TRACKING) This->tracking_color = NEEDS_DISABLE;
4133 This->tracking_color = NEEDS_TRACKING;
4134 This->tracking_parm = Parm;
4138 if (This->tracking_color != DISABLED_TRACKING) This->tracking_color = NEEDS_DISABLE;
4143 case WINED3DRS_LINEPATTERN :
4149 tmppattern.d = Value;
4151 TRACE("Line pattern: repeat %d bits %x\n", tmppattern.lp.wRepeatFactor, tmppattern.lp.wLinePattern);
4153 if (tmppattern.lp.wRepeatFactor) {
4154 glLineStipple(tmppattern.lp.wRepeatFactor, tmppattern.lp.wLinePattern);
4155 checkGLcall("glLineStipple(repeat, linepattern)");
4156 glEnable(GL_LINE_STIPPLE);
4157 checkGLcall("glEnable(GL_LINE_STIPPLE);");
4159 glDisable(GL_LINE_STIPPLE);
4160 checkGLcall("glDisable(GL_LINE_STIPPLE);");
4165 case WINED3DRS_ZBIAS : /* D3D8 only */
4169 TRACE("ZBias value %f\n", tmpvalue.f);
4170 glPolygonOffset(0, -tmpvalue.f);
4171 checkGLcall("glPolygonOffset(0, -Value)");
4172 glEnable(GL_POLYGON_OFFSET_FILL);
4173 checkGLcall("glEnable(GL_POLYGON_OFFSET_FILL);");
4174 glEnable(GL_POLYGON_OFFSET_LINE);
4175 checkGLcall("glEnable(GL_POLYGON_OFFSET_LINE);");
4176 glEnable(GL_POLYGON_OFFSET_POINT);
4177 checkGLcall("glEnable(GL_POLYGON_OFFSET_POINT);");
4179 glDisable(GL_POLYGON_OFFSET_FILL);
4180 checkGLcall("glDisable(GL_POLYGON_OFFSET_FILL);");
4181 glDisable(GL_POLYGON_OFFSET_LINE);
4182 checkGLcall("glDisable(GL_POLYGON_OFFSET_LINE);");
4183 glDisable(GL_POLYGON_OFFSET_POINT);
4184 checkGLcall("glDisable(GL_POLYGON_OFFSET_POINT);");
4189 case WINED3DRS_NORMALIZENORMALS :
4191 glEnable(GL_NORMALIZE);
4192 checkGLcall("glEnable(GL_NORMALIZE);");
4194 glDisable(GL_NORMALIZE);
4195 checkGLcall("glDisable(GL_NORMALIZE);");
4199 case WINED3DRS_POINTSIZE :
4200 /* FIXME: check that pointSize isn't outside glGetFloatv( GL_POINT_SIZE_MAX_ARB, &maxSize ); or -ve */
4202 TRACE("Set point size to %f\n", tmpvalue.f);
4203 glPointSize(tmpvalue.f);
4204 checkGLcall("glPointSize(...);");
4207 case WINED3DRS_POINTSIZE_MIN :
4208 if (GL_SUPPORT(EXT_POINT_PARAMETERS)) {
4210 GL_EXTCALL(glPointParameterfEXT)(GL_POINT_SIZE_MIN_EXT, tmpvalue.f);
4211 checkGLcall("glPointParameterfEXT(...);");
4213 FIXME("WINED3DRS_POINTSIZE_MIN not supported on this opengl\n");
4217 case WINED3DRS_POINTSIZE_MAX :
4218 if (GL_SUPPORT(EXT_POINT_PARAMETERS)) {
4220 GL_EXTCALL(glPointParameterfEXT)(GL_POINT_SIZE_MAX_EXT, tmpvalue.f);
4221 checkGLcall("glPointParameterfEXT(...);");
4223 FIXME("WINED3DRS_POINTSIZE_MAX not supported on this opengl\n");
4227 case WINED3DRS_POINTSCALE_A :
4228 case WINED3DRS_POINTSCALE_B :
4229 case WINED3DRS_POINTSCALE_C :
4230 case WINED3DRS_POINTSCALEENABLE :
4233 * POINTSCALEENABLE controls how point size value is treated. If set to
4234 * true, the point size is scaled with respect to height of viewport.
4235 * When set to false point size is in pixels.
4237 * http://msdn.microsoft.com/library/en-us/directx9_c/point_sprites.asp
4240 /* Default values */
4241 GLfloat att[3] = {1.0f, 0.0f, 0.0f};
4244 * Minimum valid point size for OpenGL is 1.0f. For Direct3D it is 0.0f.
4245 * This means that OpenGL will clamp really small point sizes to 1.0f.
4246 * To correct for this we need to multiply by the scale factor when sizes
4247 * are less than 1.0f. scale_factor = 1.0f / point_size.
4249 GLfloat pointSize = *((float*)&This->stateBlock->renderState[WINED3DRS_POINTSIZE]);
4250 if(pointSize > 0.0f) {
4251 GLfloat scaleFactor;
4253 if(pointSize < 1.0f) {
4254 scaleFactor = pointSize * pointSize;
4259 if(This->stateBlock->renderState[WINED3DRS_POINTSCALEENABLE]) {
4260 att[0] = *((float*)&This->stateBlock->renderState[WINED3DRS_POINTSCALE_A]) /
4261 (This->stateBlock->viewport.Height * This->stateBlock->viewport.Height * scaleFactor);
4262 att[1] = *((float*)&This->stateBlock->renderState[WINED3DRS_POINTSCALE_B]) /
4263 (This->stateBlock->viewport.Height * This->stateBlock->viewport.Height * scaleFactor);
4264 att[2] = *((float*)&This->stateBlock->renderState[WINED3DRS_POINTSCALE_C]) /
4265 (This->stateBlock->viewport.Height * This->stateBlock->viewport.Height * scaleFactor);
4269 if(GL_SUPPORT(ARB_POINT_PARAMETERS)) {
4270 GL_EXTCALL(glPointParameterfvARB)(GL_POINT_DISTANCE_ATTENUATION_ARB, att);
4271 checkGLcall("glPointParameterfvARB(GL_DISTANCE_ATTENUATION_ARB, ...");
4273 else if(GL_SUPPORT(EXT_POINT_PARAMETERS)) {
4274 GL_EXTCALL(glPointParameterfvEXT)(GL_DISTANCE_ATTENUATION_EXT, att);
4275 checkGLcall("glPointParameterfvEXT(GL_DISTANCE_ATTENUATION_EXT, ...");
4277 TRACE("POINT_PARAMETERS not supported in this version of opengl\n");
4281 case WINED3DRS_COLORWRITEENABLE :
4283 TRACE("Color mask: r(%d) g(%d) b(%d) a(%d)\n",
4284 Value & D3DCOLORWRITEENABLE_RED ? 1 : 0,
4285 Value & D3DCOLORWRITEENABLE_GREEN ? 1 : 0,
4286 Value & D3DCOLORWRITEENABLE_BLUE ? 1 : 0,
4287 Value & D3DCOLORWRITEENABLE_ALPHA ? 1 : 0);
4288 glColorMask(Value & D3DCOLORWRITEENABLE_RED ? GL_TRUE : GL_FALSE,
4289 Value & D3DCOLORWRITEENABLE_GREEN ? GL_TRUE : GL_FALSE,
4290 Value & D3DCOLORWRITEENABLE_BLUE ? GL_TRUE : GL_FALSE,
4291 Value & D3DCOLORWRITEENABLE_ALPHA ? GL_TRUE : GL_FALSE);
4292 checkGLcall("glColorMask(...)");
4296 case WINED3DRS_LOCALVIEWER :
4298 GLint state = (Value) ? 1 : 0;
4299 TRACE("Local Viewer Enable to %ul\n", (BOOL) Value);
4300 glLightModeli(GL_LIGHT_MODEL_LOCAL_VIEWER, state);
4304 case WINED3DRS_LASTPIXEL :
4307 TRACE("Last Pixel Drawing Enabled\n");
4309 FIXME("Last Pixel Drawing Disabled, not handled yet\n");
4314 case WINED3DRS_SOFTWAREVERTEXPROCESSING :
4317 TRACE("Software Processing Enabled\n");
4319 TRACE("Software Processing Disabled\n");
4324 /** not supported */
4325 case WINED3DRS_ZVISIBLE :
4328 return WINED3DERR_INVALIDCALL;
4330 case WINED3DRS_POINTSPRITEENABLE :
4332 /* TODO: NV_POINT_SPRITE */
4333 if (!GL_SUPPORT(ARB_POINT_SPRITE)) {
4334 TRACE("Point sprites not supported\n");
4339 * Point sprites are always enabled. Value controls texture coordinate
4340 * replacement mode. Must be set true for point sprites to use
4343 glEnable(GL_POINT_SPRITE_ARB);
4344 checkGLcall("glEnable(GL_POINT_SPRITE_ARB)");
4347 glTexEnvf(GL_POINT_SPRITE_ARB, GL_COORD_REPLACE_ARB, TRUE);
4348 checkGLcall("glTexEnvf(GL_POINT_SPRITE, GL_COORD_REPLACE, TRUE)");
4350 glTexEnvf(GL_POINT_SPRITE_ARB, GL_COORD_REPLACE_ARB, FALSE);
4351 checkGLcall("glTexEnvf(GL_POINT_SPRITE, GL_COORD_REPLACE, FALSE)");
4355 case WINED3DRS_EDGEANTIALIAS :
4358 glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
4360 checkGLcall("glEnable(GL_BLEND)");
4361 glEnable(GL_LINE_SMOOTH);
4362 checkGLcall("glEnable(GL_LINE_SMOOTH)");
4364 if(!This->stateBlock->renderState[WINED3DRS_ALPHABLENDENABLE]) {
4365 glDisable(GL_BLEND);
4366 checkGLcall("glDisable(GL_BLEND)");
4368 glDisable(GL_LINE_SMOOTH);
4369 checkGLcall("glDisable(GL_LINE_SMOOTH)");
4373 case WINED3DRS_WRAP0 :
4374 case WINED3DRS_WRAP1 :
4375 case WINED3DRS_WRAP2 :
4376 case WINED3DRS_WRAP3 :
4377 case WINED3DRS_WRAP4 :
4378 case WINED3DRS_WRAP5 :
4379 case WINED3DRS_WRAP6 :
4380 case WINED3DRS_WRAP7 :
4381 case WINED3DRS_WRAP8 :
4382 case WINED3DRS_WRAP9 :
4383 case WINED3DRS_WRAP10 :
4384 case WINED3DRS_WRAP11 :
4385 case WINED3DRS_WRAP12 :
4386 case WINED3DRS_WRAP13 :
4387 case WINED3DRS_WRAP14 :
4388 case WINED3DRS_WRAP15 :
4390 http://www.cosc.brocku.ca/Offerings/3P98/course/lectures/texture/
4391 http://msdn.microsoft.com/archive/default.asp?url=/archive/en-us/directx9_c/directx/graphics/programmingguide/FixedFunction/Textures/texturewrapping.asp
4392 http://www.gamedev.net/reference/programming/features/rendererdll3/page2.asp
4393 Descussion that ways to turn on WRAPing to solve an opengl conversion problem.
4394 http://www.flipcode.org/cgi-bin/fcmsg.cgi?thread_show=10248
4396 so far as I can tell, wrapping and texture-coordinate generate go hand in hand,
4398 TRACE("(%p)->(%s,%ld) Texture wraping not yet supported\n",This, debug_d3drenderstate(State), Value);
4400 case WINED3DRS_MULTISAMPLEANTIALIAS :
4402 if (!GL_SUPPORT(ARB_MULTISAMPLE)) {
4403 TRACE("Multisample antialiasing not supported\n");
4408 glEnable(GL_MULTISAMPLE_ARB);
4409 checkGLcall("glEnable(GL_MULTISAMPLE_ARB)");
4411 glDisable(GL_MULTISAMPLE_ARB);
4412 checkGLcall("glDisable(GL_MULTISAMPLE_ARB)");
4416 case WINED3DRS_SCISSORTESTENABLE :
4419 glEnable(GL_SCISSOR_TEST);
4420 checkGLcall("glEnable(GL_SCISSOR_TEST)");
4422 glDisable(GL_SCISSOR_TEST);
4423 checkGLcall("glDisable(GL_SCISSOR_TEST)");
4427 case WINED3DRS_SLOPESCALEDEPTHBIAS :
4431 glEnable(GL_POLYGON_OFFSET_FILL);
4432 checkGLcall("glEnable(GL_POLYGON_OFFSET_FILL)");
4433 glPolygonOffset(tmpvalue.f, *((float*)&This->stateBlock->renderState[WINED3DRS_DEPTHBIAS]));
4434 checkGLcall("glPolygonOffset(...)");
4436 glDisable(GL_POLYGON_OFFSET_FILL);
4437 checkGLcall("glDisable(GL_POLYGON_OFFSET_FILL)");
4441 case WINED3DRS_ANTIALIASEDLINEENABLE :
4444 glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
4446 checkGLcall("glEnable(GL_BLEND)");
4447 glEnable(GL_LINE_SMOOTH);
4448 checkGLcall("glEnable(GL_LINE_SMOOTH)");
4450 glDisable(GL_BLEND);
4451 checkGLcall("glDisable(GL_BLEND)");
4452 glDisable(GL_LINE_SMOOTH);
4453 checkGLcall("glDisable(GL_LINE_SMOOTH)");
4457 case WINED3DRS_DEPTHBIAS :
4461 glEnable(GL_POLYGON_OFFSET_FILL);
4462 checkGLcall("glEnable(GL_POLYGON_OFFSET_FILL)");
4463 glPolygonOffset(*((float*)&This->stateBlock->renderState[WINED3DRS_SLOPESCALEDEPTHBIAS]), tmpvalue.f);
4464 checkGLcall("glPolygonOffset(...)");
4466 glDisable(GL_POLYGON_OFFSET_FILL);
4467 checkGLcall("glDisable(GL_POLYGON_OFFSET_FILL)");
4472 case WINED3DRS_TEXTUREPERSPECTIVE :
4475 glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST);
4477 glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_FASTEST);
4481 case WINED3DRS_STIPPLEDALPHA :
4484 ERR(" Stippled Alpha not supported yet.\n");
4487 case WINED3DRS_ANTIALIAS :
4490 ERR(" Antialias not supported yet.\n");
4494 FIXME("(%p)->(%s,%ld) not handled yet\n", This, debug_d3drenderstate(State), Value);
4502 static HRESULT WINAPI IWineD3DDeviceImpl_GetRenderState(IWineD3DDevice *iface, D3DRENDERSTATETYPE State, DWORD *pValue) {
4503 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4504 TRACE("(%p) for State %d = %ld\n", This, State, This->stateBlock->renderState[State]);
4505 *pValue = This->stateBlock->renderState[State];
4510 * Get / Set Sampler States
4511 * TODO: Verify against dx9 definitions
4514 static HRESULT WINAPI IWineD3DDeviceImpl_SetSamplerState(IWineD3DDevice *iface, DWORD Sampler, WINED3DSAMPLERSTATETYPE Type, DWORD Value) {
4515 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4517 * SetSampler is designed to allow for more than the standard up to 8 textures
4518 * and Geforce has stopped supporting more than 6 standard textures in openGL.
4519 * So I have to use ARB for Gforce. (maybe if the sampler > 4 then use ARB?)
4521 * http://developer.nvidia.com/object/General_FAQ.html#t6
4523 * There are two new settings for GForce
4525 * GL_MAX_TEXTURE_IMAGE_UNITS_ARB
4526 * and the texture one:
4527 * GL_MAX_TEXTURE_COORDS_ARB.
4528 * Ok GForce say it's ok to use glTexParameter/glGetTexParameter(...).
4530 /** NOTE: States are appled in IWineD3DBaseTextre ApplyStateChanges and IWineD3DDevice SetupTextureStates**/
4531 if(Sampler > GL_LIMITS(sampler_stages) || Sampler < 0 || Type > WINED3D_HIGHEST_SAMPLER_STATE || Type < 0) {
4532 FIXME("sampler %ld type %s(%u) is out of range [max_samplers=%d, highest_state=%d]\n",
4533 Sampler, debug_d3dsamplerstate(Type), Type, GL_LIMITS(sampler_stages), WINED3D_HIGHEST_SAMPLER_STATE);
4534 return WINED3DERR_INVALIDCALL;
4537 TRACE("(%p) : Sampler=%ld, Type=%s(%d), Value=%ld\n", This, Sampler,
4538 debug_d3dsamplerstate(Type), Type, Value);
4539 This->updateStateBlock->samplerState[Sampler][Type] = Value;
4540 This->updateStateBlock->set.samplerState[Sampler][Type] = Value;
4541 This->updateStateBlock->changed.samplerState[Sampler][Type] = Value;
4543 /* Handle recording of state blocks */
4544 if (This->isRecordingState) {
4545 TRACE("Recording... not performing anything\n");
4552 static HRESULT WINAPI IWineD3DDeviceImpl_GetSamplerState(IWineD3DDevice *iface, DWORD Sampler, WINED3DSAMPLERSTATETYPE Type, DWORD* Value) {
4553 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4554 /** TODO: check that sampler is in range **/
4555 *Value = This->updateStateBlock->samplerState[Sampler][Type];
4556 TRACE("(%p) : Sampler %ld Type %u Returning %ld\n", This, Sampler, Type, *Value);
4561 static HRESULT WINAPI IWineD3DDeviceImpl_SetScissorRect(IWineD3DDevice *iface, CONST RECT* pRect) {
4562 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4565 /** FIXME: Windows uses a top,left origin openGL uses a bottom Right? **/
4566 TRACE("(%p)Setting new Scissor Rect to %ld:%ld-%ld:%ld\n", This, pRect->left, pRect->top, pRect->right, pRect->bottom);
4567 glScissor(pRect->left, pRect->top, pRect->right - pRect->left, pRect->bottom - pRect->top);
4573 static HRESULT WINAPI IWineD3DDeviceImpl_GetScissorRect(IWineD3DDevice *iface, RECT* pRect) {
4574 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4575 GLint scissorBox[4];
4578 /** FIXME: Windows uses a top,left origin openGL uses a bottom Right? **/
4579 glGetIntegerv(GL_SCISSOR_BOX, scissorBox);
4580 pRect->left = scissorBox[0];
4581 pRect->top = scissorBox[1];
4582 pRect->right = scissorBox[0] + scissorBox[2];
4583 pRect->bottom = scissorBox[1] + scissorBox[3];
4584 TRACE("(%p)Returning a Scissor Rect of %ld:%ld-%ld:%ld\n", This, pRect->left, pRect->top, pRect->right, pRect->bottom);
4589 static HRESULT WINAPI IWineD3DDeviceImpl_SetVertexDeclaration(IWineD3DDevice* iface, IWineD3DVertexDeclaration* pDecl) {
4590 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *) iface;
4591 IWineD3DVertexDeclaration *oldDecl = This->updateStateBlock->vertexDecl;
4593 TRACE("(%p) : pDecl=%p\n", This, pDecl);
4595 This->updateStateBlock->vertexDecl = pDecl;
4596 This->updateStateBlock->changed.vertexDecl = TRUE;
4597 This->updateStateBlock->set.vertexDecl = TRUE;
4599 if (This->isRecordingState) {
4600 TRACE("Recording... not performing anything\n");
4603 if (NULL != pDecl) {
4604 IWineD3DVertexDeclaration_AddRef(pDecl);
4606 if (NULL != oldDecl) {
4607 IWineD3DVertexDeclaration_Release(oldDecl);
4612 static HRESULT WINAPI IWineD3DDeviceImpl_GetVertexDeclaration(IWineD3DDevice* iface, IWineD3DVertexDeclaration** ppDecl) {
4613 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4615 TRACE("(%p) : ppDecl=%p\n", This, ppDecl);
4617 *ppDecl = This->stateBlock->vertexDecl;
4618 if (NULL != *ppDecl) IWineD3DVertexDeclaration_AddRef(*ppDecl);
4622 static HRESULT WINAPI IWineD3DDeviceImpl_SetVertexShader(IWineD3DDevice *iface, IWineD3DVertexShader* pShader) {
4623 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4624 IWineD3DVertexShader* oldShader = This->updateStateBlock->vertexShader;
4626 This->updateStateBlock->vertexShader = pShader;
4627 This->updateStateBlock->changed.vertexShader = TRUE;
4628 This->updateStateBlock->set.vertexShader = TRUE;
4630 if (This->isRecordingState) {
4631 TRACE("Recording... not performing anything\n");
4634 if (NULL != pShader) {
4635 IWineD3DVertexShader_AddRef(pShader);
4637 if (NULL != oldShader) {
4638 IWineD3DVertexShader_Release(oldShader);
4641 if (pShader != NULL && ((IWineD3DVertexShaderImpl *)pShader)->vertexDeclaration != NULL) {
4642 TRACE("(%p) : setting vertexDeclaration(%p)\n", This, ((IWineD3DVertexShaderImpl *)pShader)->vertexDeclaration);
4643 IWineD3DDevice_SetVertexDeclaration(iface, ((IWineD3DVertexShaderImpl *)pShader)->vertexDeclaration);
4646 TRACE("(%p) : setting pShader(%p)\n", This, pShader);
4648 * TODO: merge HAL shaders context switching from prototype
4653 static HRESULT WINAPI IWineD3DDeviceImpl_GetVertexShader(IWineD3DDevice *iface, IWineD3DVertexShader** ppShader) {
4654 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4656 if (NULL == ppShader) {
4657 return WINED3DERR_INVALIDCALL;
4659 *ppShader = This->stateBlock->vertexShader;
4660 if( NULL != *ppShader)
4661 IWineD3DVertexShader_AddRef(*ppShader);
4663 TRACE("(%p) : returning %p\n", This, *ppShader);
4667 static HRESULT WINAPI IWineD3DDeviceImpl_SetVertexShaderConstantB(
4668 IWineD3DDevice *iface,
4670 CONST BOOL *srcData,
4673 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4674 int i, cnt = min(count, MAX_VSHADER_CONSTANTS - (start + 1));
4676 TRACE("(iface %p, srcData %p, start %d, count %d)\n",
4677 iface, srcData, start, count);
4679 if (srcData == NULL || cnt < 0)
4680 return WINED3DERR_INVALIDCALL;
4682 memcpy(&This->updateStateBlock->vertexShaderConstantB[start], srcData, cnt * sizeof(BOOL));
4683 for (i = 0; i < cnt; i++)
4684 TRACE("Set BOOL constant %u to %s\n", i, srcData[i]? "true":"false");
4686 for (i = start; i < cnt + start; ++i) {
4687 This->updateStateBlock->changed.vertexShaderConstantsB[i] = TRUE;
4688 This->updateStateBlock->set.vertexShaderConstantsB[i] = TRUE;
4694 static HRESULT WINAPI IWineD3DDeviceImpl_GetVertexShaderConstantB(
4695 IWineD3DDevice *iface,
4700 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4701 int cnt = min(count, MAX_VSHADER_CONSTANTS - (start + 1));
4703 TRACE("(iface %p, dstData %p, start %d, count %d)\n",
4704 iface, dstData, start, count);
4706 if (dstData == NULL || cnt < 0)
4707 return WINED3DERR_INVALIDCALL;
4709 memcpy(dstData, &This->updateStateBlock->vertexShaderConstantB[start], cnt * sizeof(BOOL));
4713 static HRESULT WINAPI IWineD3DDeviceImpl_SetVertexShaderConstantI(
4714 IWineD3DDevice *iface,
4719 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4720 int i, cnt = min(count, MAX_VSHADER_CONSTANTS - (start + 1));
4722 TRACE("(iface %p, srcData %p, start %d, count %d)\n",
4723 iface, srcData, start, count);
4725 if (srcData == NULL || cnt < 0)
4726 return WINED3DERR_INVALIDCALL;
4728 memcpy(&This->updateStateBlock->vertexShaderConstantI[start * 4], srcData, cnt * sizeof(int) * 4);
4729 for (i = 0; i < cnt; i++)
4730 TRACE("Set INT constant %u to { %d, %d, %d, %d }\n", i,
4731 srcData[i*4], srcData[i*4+1], srcData[i*4+2], srcData[i*4+3]);
4733 for (i = start; i < cnt + start; ++i) {
4734 This->updateStateBlock->changed.vertexShaderConstantsI[i] = TRUE;
4735 This->updateStateBlock->set.vertexShaderConstantsI[i] = TRUE;
4741 static HRESULT WINAPI IWineD3DDeviceImpl_GetVertexShaderConstantI(
4742 IWineD3DDevice *iface,
4747 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4748 int cnt = min(count, MAX_VSHADER_CONSTANTS - (start + 1));
4750 TRACE("(iface %p, dstData %p, start %d, count %d)\n",
4751 iface, dstData, start, count);
4753 if (dstData == NULL || cnt < 0)
4754 return WINED3DERR_INVALIDCALL;
4756 memcpy(dstData, &This->updateStateBlock->vertexShaderConstantI[start * 4], cnt * sizeof(int) * 4);
4760 static HRESULT WINAPI IWineD3DDeviceImpl_SetVertexShaderConstantF(
4761 IWineD3DDevice *iface,
4763 CONST float *srcData,
4766 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4767 int i, cnt = min(count, MAX_VSHADER_CONSTANTS - (start + 1));
4769 TRACE("(iface %p, srcData %p, start %d, count %d)\n",
4770 iface, srcData, start, count);
4772 if (srcData == NULL || cnt < 0)
4773 return WINED3DERR_INVALIDCALL;
4775 memcpy(&This->updateStateBlock->vertexShaderConstantF[start * 4], srcData, cnt * sizeof(float) * 4);
4776 for (i = 0; i < cnt; i++)
4777 TRACE("Set FLOAT constant %u to { %f, %f, %f, %f }\n", i,
4778 srcData[i*4], srcData[i*4+1], srcData[i*4+2], srcData[i*4+3]);
4780 for (i = start; i < cnt + start; ++i) {
4781 This->updateStateBlock->changed.vertexShaderConstantsF[i] = TRUE;
4782 This->updateStateBlock->set.vertexShaderConstantsF[i] = TRUE;
4788 static HRESULT WINAPI IWineD3DDeviceImpl_GetVertexShaderConstantF(
4789 IWineD3DDevice *iface,
4794 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4795 int cnt = min(count, MAX_VSHADER_CONSTANTS - (start + 1));
4797 TRACE("(iface %p, dstData %p, start %d, count %d)\n",
4798 iface, dstData, start, count);
4800 if (dstData == NULL || cnt < 0)
4801 return WINED3DERR_INVALIDCALL;
4803 memcpy(dstData, &This->updateStateBlock->vertexShaderConstantF[start * 4], cnt * sizeof(float) * 4);
4807 static HRESULT WINAPI IWineD3DDeviceImpl_SetPixelShader(IWineD3DDevice *iface, IWineD3DPixelShader *pShader) {
4808 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4809 IWineD3DPixelShader *oldShader = This->updateStateBlock->pixelShader;
4810 This->updateStateBlock->pixelShader = pShader;
4811 This->updateStateBlock->changed.pixelShader = TRUE;
4812 This->updateStateBlock->set.pixelShader = TRUE;
4814 /* Handle recording of state blocks */
4815 if (This->isRecordingState) {
4816 TRACE("Recording... not performing anything\n");
4819 if (NULL != pShader) {
4820 IWineD3DPixelShader_AddRef(pShader);
4822 if (NULL != oldShader) {
4823 IWineD3DPixelShader_Release(oldShader);
4826 TRACE("(%p) : setting pShader(%p)\n", This, pShader);
4828 * TODO: merge HAL shaders context switching from prototype
4833 static HRESULT WINAPI IWineD3DDeviceImpl_GetPixelShader(IWineD3DDevice *iface, IWineD3DPixelShader **ppShader) {
4834 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4836 if (NULL == ppShader) {
4837 WARN("(%p) : PShader is NULL, returning INVALIDCALL\n", This);
4838 return WINED3DERR_INVALIDCALL;
4841 *ppShader = This->stateBlock->pixelShader;
4842 if (NULL != *ppShader) {
4843 IWineD3DPixelShader_AddRef(*ppShader);
4845 TRACE("(%p) : returning %p\n", This, *ppShader);
4849 static HRESULT WINAPI IWineD3DDeviceImpl_SetPixelShaderConstantB(
4850 IWineD3DDevice *iface,
4852 CONST BOOL *srcData,
4855 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4856 int i, cnt = min(count, MAX_PSHADER_CONSTANTS - (start + 1));
4858 TRACE("(iface %p, srcData %p, start %d, count %d)\n",
4859 iface, srcData, start, count);
4861 if (srcData == NULL || cnt < 0)
4862 return WINED3DERR_INVALIDCALL;
4864 memcpy(&This->updateStateBlock->pixelShaderConstantB[start], srcData, cnt * sizeof(BOOL));
4865 for (i = 0; i < cnt; i++)
4866 TRACE("Set BOOL constant %u to %s\n", i, srcData[i]? "true":"false");
4868 for (i = start; i < cnt + start; ++i) {
4869 This->updateStateBlock->changed.pixelShaderConstantsB[i] = TRUE;
4870 This->updateStateBlock->set.pixelShaderConstantsB[i] = TRUE;
4876 static HRESULT WINAPI IWineD3DDeviceImpl_GetPixelShaderConstantB(
4877 IWineD3DDevice *iface,
4882 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4883 int cnt = min(count, MAX_PSHADER_CONSTANTS - (start + 1));
4885 TRACE("(iface %p, dstData %p, start %d, count %d)\n",
4886 iface, dstData, start, count);
4888 if (dstData == NULL || cnt < 0)
4889 return WINED3DERR_INVALIDCALL;
4891 memcpy(dstData, &This->updateStateBlock->pixelShaderConstantB[start], cnt * sizeof(BOOL));
4895 static HRESULT WINAPI IWineD3DDeviceImpl_SetPixelShaderConstantI(
4896 IWineD3DDevice *iface,
4901 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4902 int i, cnt = min(count, MAX_PSHADER_CONSTANTS - (start + 1));
4904 TRACE("(iface %p, srcData %p, start %d, count %d)\n",
4905 iface, srcData, start, count);
4907 if (srcData == NULL || cnt < 0)
4908 return WINED3DERR_INVALIDCALL;
4910 memcpy(&This->updateStateBlock->pixelShaderConstantI[start * 4], srcData, cnt * sizeof(int) * 4);
4911 for (i = 0; i < cnt; i++)
4912 TRACE("Set INT constant %u to { %d, %d, %d, %d }\n", i,
4913 srcData[i*4], srcData[i*4+1], srcData[i*4+2], srcData[i*4+3]);
4915 for (i = start; i < cnt + start; ++i) {
4916 This->updateStateBlock->changed.pixelShaderConstantsI[i] = TRUE;
4917 This->updateStateBlock->set.pixelShaderConstantsI[i] = TRUE;
4923 static HRESULT WINAPI IWineD3DDeviceImpl_GetPixelShaderConstantI(
4924 IWineD3DDevice *iface,
4929 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4930 int cnt = min(count, MAX_PSHADER_CONSTANTS - (start + 1));
4932 TRACE("(iface %p, dstData %p, start %d, count %d)\n",
4933 iface, dstData, start, count);
4935 if (dstData == NULL || cnt < 0)
4936 return WINED3DERR_INVALIDCALL;
4938 memcpy(dstData, &This->updateStateBlock->pixelShaderConstantI[start * 4], cnt * sizeof(int) * 4);
4942 static HRESULT WINAPI IWineD3DDeviceImpl_SetPixelShaderConstantF(
4943 IWineD3DDevice *iface,
4945 CONST float *srcData,
4948 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4949 int i, cnt = min(count, MAX_PSHADER_CONSTANTS - (start + 1));
4951 TRACE("(iface %p, srcData %p, start %d, count %d)\n",
4952 iface, srcData, start, count);
4954 if (srcData == NULL || cnt < 0)
4955 return WINED3DERR_INVALIDCALL;
4957 memcpy(&This->updateStateBlock->pixelShaderConstantF[start * 4], srcData, cnt * sizeof(float) * 4);
4958 for (i = 0; i < cnt; i++)
4959 TRACE("Set FLOAT constant %u to { %f, %f, %f, %f }\n", i,
4960 srcData[i*4], srcData[i*4+1], srcData[i*4+2], srcData[i*4+3]);
4962 for (i = start; i < cnt + start; ++i) {
4963 This->updateStateBlock->changed.pixelShaderConstantsF[i] = TRUE;
4964 This->updateStateBlock->set.pixelShaderConstantsF[i] = TRUE;
4970 static HRESULT WINAPI IWineD3DDeviceImpl_GetPixelShaderConstantF(
4971 IWineD3DDevice *iface,
4976 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4977 int cnt = min(count, MAX_PSHADER_CONSTANTS - (start + 1));
4979 TRACE("(iface %p, dstData %p, start %d, count %d)\n",
4980 iface, dstData, start, count);
4982 if (dstData == NULL || cnt < 0)
4983 return WINED3DERR_INVALIDCALL;
4985 memcpy(dstData, &This->updateStateBlock->pixelShaderConstantF[start * 4], cnt * sizeof(float) * 4);
4989 #define copy_and_next(dest, src, size) memcpy(dest, src, size); dest += (size)
4991 process_vertices_strided(IWineD3DDeviceImpl *This, DWORD dwDestIndex, DWORD dwCount, WineDirect3DVertexStridedData *lpStrideData, DWORD SrcFVF, IWineD3DVertexBufferImpl *dest, DWORD dwFlags) {
4992 char *dest_ptr, *dest_conv = NULL;
4994 DWORD DestFVF = dest->fvf;
4996 D3DMATRIX mat, proj_mat, view_mat, world_mat;
5000 if (SrcFVF & D3DFVF_NORMAL) {
5001 WARN(" lighting state not saved yet... Some strange stuff may happen !\n");
5004 if ( (SrcFVF & D3DFVF_POSITION_MASK) != D3DFVF_XYZ) {
5005 ERR("Source has no position mask\n");
5006 return WINED3DERR_INVALIDCALL;
5009 /* We might access VBOs from this code, so hold the lock */
5012 if (dest->resource.allocatedMemory == NULL) {
5013 /* This may happen if we do direct locking into a vbo. Unlikely,
5014 * but theoretically possible(ddraw processvertices test)
5016 dest->resource.allocatedMemory = HeapAlloc(GetProcessHeap(), 0, dest->resource.size);
5017 if(!dest->resource.allocatedMemory) {
5019 ERR("Out of memory\n");
5020 return E_OUTOFMEMORY;
5024 GL_EXTCALL(glBindBufferARB(GL_ARRAY_BUFFER_ARB, dest->vbo));
5025 checkGLcall("glBindBufferARB");
5026 src = GL_EXTCALL(glMapBufferARB(GL_ARRAY_BUFFER_ARB, GL_READ_ONLY_ARB));
5028 memcpy(dest->resource.allocatedMemory, src, dest->resource.size);
5030 GL_EXTCALL(glUnmapBufferARB(GL_ARRAY_BUFFER_ARB));
5031 checkGLcall("glUnmapBufferARB");
5035 /* Get a pointer into the destination vbo(create one if none exists) and
5036 * write correct opengl data into it. It's cheap and allows us to run drawStridedFast
5038 if(!dest->vbo && GL_SUPPORT(ARB_VERTEX_BUFFER_OBJECT)) {
5043 GL_EXTCALL(glBindBufferARB(GL_ARRAY_BUFFER_ARB, dest->vbo));
5044 dest_conv = GL_EXTCALL(glMapBufferARB(GL_ARRAY_BUFFER_ARB, GL_WRITE_ONLY_ARB));
5046 ERR("glMapBuffer failed\n");
5047 /* Continue without storing converted vertices */
5052 * a) D3DRS_CLIPPING is enabled
5053 * b) WINED3DVOP_CLIP is passed
5055 if(This->stateBlock->renderState[WINED3DRS_CLIPPING]) {
5056 static BOOL warned = FALSE;
5058 * The clipping code is not quite correct. Some things need
5059 * to be checked against IDirect3DDevice3 (!), d3d8 and d3d9,
5060 * so disable clipping for now.
5061 * (The graphics in Half-Life are broken, and my processvertices
5062 * test crashes with IDirect3DDevice3)
5068 FIXME("Clipping is broken and disabled for now\n");
5070 } else doClip = FALSE;
5071 dest_ptr = ((char *) dest->resource.allocatedMemory) + dwDestIndex * get_flexible_vertex_size(DestFVF);
5073 dest_conv = ((char *) dest_conv) + dwDestIndex * get_flexible_vertex_size(DestFVF);
5076 IWineD3DDevice_GetTransform( (IWineD3DDevice *) This,
5079 IWineD3DDevice_GetTransform( (IWineD3DDevice *) This,
5082 IWineD3DDevice_GetTransform( (IWineD3DDevice *) This,
5083 D3DTS_WORLDMATRIX(0),
5086 TRACE("View mat:\n");
5087 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); \
5088 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); \
5089 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); \
5090 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); \
5092 TRACE("Proj mat:\n");
5093 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); \
5094 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); \
5095 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); \
5096 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); \
5098 TRACE("World mat:\n");
5099 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); \
5100 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); \
5101 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); \
5102 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); \
5104 /* Get the viewport */
5105 IWineD3DDevice_GetViewport( (IWineD3DDevice *) This, &vp);
5106 TRACE("Viewport: X=%ld, Y=%ld, Width=%ld, Height=%ld, MinZ=%f, MaxZ=%f\n",
5107 vp.X, vp.Y, vp.Width, vp.Height, vp.MinZ, vp.MaxZ);
5109 multiply_matrix(&mat,&view_mat,&world_mat);
5110 multiply_matrix(&mat,&proj_mat,&mat);
5112 numTextures = (DestFVF & D3DFVF_TEXCOUNT_MASK) >> D3DFVF_TEXCOUNT_SHIFT;
5114 for (i = 0; i < dwCount; i+= 1) {
5115 unsigned int tex_index;
5117 if ( ((DestFVF & D3DFVF_POSITION_MASK) == D3DFVF_XYZ ) ||
5118 ((DestFVF & D3DFVF_POSITION_MASK) == D3DFVF_XYZRHW ) ) {
5119 /* The position first */
5121 (float *) (((char *) lpStrideData->u.s.position.lpData) + i * lpStrideData->u.s.position.dwStride);
5123 TRACE("In: ( %06.2f %06.2f %06.2f )\n", p[0], p[1], p[2]);
5125 /* Multiplication with world, view and projection matrix */
5126 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);
5127 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);
5128 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);
5129 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);
5131 TRACE("x=%f y=%f z=%f rhw=%f\n", x, y, z, rhw);
5133 /* WARNING: The following things are taken from d3d7 and were not yet checked
5134 * against d3d8 or d3d9!
5137 /* Clipping conditions: From
5138 * http://msdn.microsoft.com/archive/default.asp?url=/archive/en-us/directx9_c/directx/graphics/programmingguide/fixedfunction/viewportsclipping/clippingvolumes.asp
5140 * A vertex is clipped if it does not match the following requirements
5144 * 0 < rhw ( Not in d3d7, but tested in d3d7)
5146 * If clipping is on is determined by the D3DVOP_CLIP flag in D3D7, and
5147 * by the D3DRS_CLIPPING in D3D9(according to the msdn, not checked)
5151 if( doClip == FALSE ||
5152 ( (-rhw -eps < x) && (-rhw -eps < y) && ( -eps < z) &&
5153 (x <= rhw + eps) && (y <= rhw + eps ) && (z <= rhw + eps) &&
5156 /* "Normal" viewport transformation (not clipped)
5157 * 1) The values are divided by rhw
5158 * 2) The y axis is negative, so multiply it with -1
5159 * 3) Screen coordinates go from -(Width/2) to +(Width/2) and
5160 * -(Height/2) to +(Height/2). The z range is MinZ to MaxZ
5161 * 4) Multiply x with Width/2 and add Width/2
5162 * 5) The same for the height
5163 * 6) Add the viewpoint X and Y to the 2D coordinates and
5164 * The minimum Z value to z
5165 * 7) rhw = 1 / rhw Reciprocal of Homogeneous W....
5167 * Well, basically it's simply a linear transformation into viewport
5179 z *= vp.MaxZ - vp.MinZ;
5181 x += vp.Width / 2 + vp.X;
5182 y += vp.Height / 2 + vp.Y;
5187 /* That vertex got clipped
5188 * Contrary to OpenGL it is not dropped completely, it just
5189 * undergoes a different calculation.
5191 TRACE("Vertex got clipped\n");
5198 /* Msdn mentions that Direct3D9 keeps a list of clipped vertices
5199 * outside of the main vertex buffer memory. That needs some more
5204 TRACE("Writing (%f %f %f) %f\n", x, y, z, rhw);
5207 ( (float *) dest_ptr)[0] = x;
5208 ( (float *) dest_ptr)[1] = y;
5209 ( (float *) dest_ptr)[2] = z;
5210 ( (float *) dest_ptr)[3] = rhw; /* SIC, see ddraw test! */
5212 dest_ptr += 3 * sizeof(float);
5214 if((DestFVF & D3DFVF_POSITION_MASK) == D3DFVF_XYZRHW) {
5215 dest_ptr += sizeof(float);
5220 ( (float *) dest_conv)[0] = x * w;
5221 ( (float *) dest_conv)[1] = y * w;
5222 ( (float *) dest_conv)[2] = z * w;
5223 ( (float *) dest_conv)[3] = w;
5225 dest_conv += 3 * sizeof(float);
5227 if((DestFVF & D3DFVF_POSITION_MASK) == D3DFVF_XYZRHW) {
5228 dest_conv += sizeof(float);
5232 if (DestFVF & D3DFVF_PSIZE) {
5233 dest_ptr += sizeof(DWORD);
5234 if(dest_conv) dest_conv += sizeof(DWORD);
5236 if (DestFVF & D3DFVF_NORMAL) {
5238 (float *) (((float *) lpStrideData->u.s.normal.lpData) + i * lpStrideData->u.s.normal.dwStride);
5239 /* AFAIK this should go into the lighting information */
5240 FIXME("Didn't expect the destination to have a normal\n");
5241 copy_and_next(dest_ptr, normal, 3 * sizeof(float));
5243 copy_and_next(dest_conv, normal, 3 * sizeof(float));
5247 if (DestFVF & D3DFVF_DIFFUSE) {
5249 (DWORD *) (((char *) lpStrideData->u.s.diffuse.lpData) + i * lpStrideData->u.s.diffuse.dwStride);
5251 static BOOL warned = FALSE;
5253 if(warned == FALSE) {
5254 ERR("No diffuse color in source, but destination has one\n");
5258 *( (DWORD *) dest_ptr) = 0xffffffff;
5259 dest_ptr += sizeof(DWORD);
5262 *( (DWORD *) dest_conv) = 0xffffffff;
5263 dest_conv += sizeof(DWORD);
5267 copy_and_next(dest_ptr, color_d, sizeof(DWORD));
5269 *( (DWORD *) dest_conv) = (*color_d & 0xff00ff00) ; /* Alpha + green */
5270 *( (DWORD *) dest_conv) |= (*color_d & 0x00ff0000) >> 16; /* Red */
5271 *( (DWORD *) dest_conv) |= (*color_d & 0xff0000ff) << 16; /* Blue */
5272 dest_conv += sizeof(DWORD);
5277 if (DestFVF & D3DFVF_SPECULAR) {
5278 /* What's the color value in the feedback buffer? */
5280 (DWORD *) (((char *) lpStrideData->u.s.specular.lpData) + i * lpStrideData->u.s.specular.dwStride);
5282 static BOOL warned = FALSE;
5284 if(warned == FALSE) {
5285 ERR("No specular color in source, but destination has one\n");
5289 *( (DWORD *) dest_ptr) = 0xFF000000;
5290 dest_ptr += sizeof(DWORD);
5293 *( (DWORD *) dest_conv) = 0xFF000000;
5294 dest_conv += sizeof(DWORD);
5298 copy_and_next(dest_ptr, color_s, sizeof(DWORD));
5300 *( (DWORD *) dest_conv) = (*color_s & 0xff00ff00) ; /* Alpha + green */
5301 *( (DWORD *) dest_conv) |= (*color_s & 0x00ff0000) >> 16; /* Red */
5302 *( (DWORD *) dest_conv) |= (*color_s & 0xff0000ff) << 16; /* Blue */
5303 dest_conv += sizeof(DWORD);
5308 for (tex_index = 0; tex_index < numTextures; tex_index++) {
5310 (float *) (((char *) lpStrideData->u.s.texCoords[tex_index].lpData) +
5311 i * lpStrideData->u.s.texCoords[tex_index].dwStride);
5313 ERR("No source texture, but destination requests one\n");
5314 dest_ptr+=GET_TEXCOORD_SIZE_FROM_FVF(DestFVF, tex_index) * sizeof(float);
5315 if(dest_conv) dest_conv += GET_TEXCOORD_SIZE_FROM_FVF(DestFVF, tex_index) * sizeof(float);
5318 copy_and_next(dest_ptr, tex_coord, GET_TEXCOORD_SIZE_FROM_FVF(DestFVF, tex_index) * sizeof(float));
5320 copy_and_next(dest_conv, tex_coord, GET_TEXCOORD_SIZE_FROM_FVF(DestFVF, tex_index) * sizeof(float));
5327 GL_EXTCALL(glUnmapBufferARB(GL_ARRAY_BUFFER_ARB));
5328 checkGLcall("glUnmapBufferARB(GL_ARRAY_BUFFER_ARB)");
5335 #undef copy_and_next
5337 static HRESULT WINAPI IWineD3DDeviceImpl_ProcessVertices(IWineD3DDevice *iface, UINT SrcStartIndex, UINT DestIndex, UINT VertexCount, IWineD3DVertexBuffer* pDestBuffer, IWineD3DVertexBuffer* pVertexDecl, DWORD Flags) {
5338 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5339 IWineD3DVertexBufferImpl *SrcImpl = (IWineD3DVertexBufferImpl *) pVertexDecl;
5340 WineDirect3DVertexStridedData strided;
5341 TRACE("(%p)->(%d,%d,%d,%p,%p,%ld\n", This, SrcStartIndex, DestIndex, VertexCount, pDestBuffer, pVertexDecl, Flags);
5343 /* We don't need the source vbo because this buffer is only used as
5344 * a source for ProcessVertices. Avoid wasting resources by converting the
5345 * buffer and loading the VBO
5348 TRACE("Releaseing the source vbo, it won't be needed\n");
5350 if(!SrcImpl->resource.allocatedMemory) {
5351 /* Rescue the data from the buffer */
5353 SrcImpl->resource.allocatedMemory = HeapAlloc(GetProcessHeap(), 0, SrcImpl->resource.size);
5354 if(!SrcImpl->resource.allocatedMemory) {
5355 ERR("Out of memory\n");
5356 return E_OUTOFMEMORY;
5360 GL_EXTCALL(glBindBufferARB(GL_ARRAY_BUFFER_ARB, SrcImpl->vbo));
5361 checkGLcall("glBindBufferARB");
5363 src = GL_EXTCALL(glMapBufferARB(GL_ARRAY_BUFFER_ARB, GL_READ_ONLY_ARB));
5365 memcpy(SrcImpl->resource.allocatedMemory, src, SrcImpl->resource.size);
5368 GL_EXTCALL(glUnmapBufferARB(GL_ARRAY_BUFFER_ARB));
5369 checkGLcall("glUnmapBufferARB");
5374 GL_EXTCALL(glBindBufferARB(GL_ARRAY_BUFFER_ARB, 0));
5375 checkGLcall("glBindBufferARB");
5376 GL_EXTCALL(glDeleteBuffersARB(1, &SrcImpl->vbo));
5377 checkGLcall("glDeleteBuffersARB");
5383 memset(&strided, 0, sizeof(strided));
5384 primitiveConvertFVFtoOffset(SrcImpl->fvf, get_flexible_vertex_size(SrcImpl->fvf), SrcImpl->resource.allocatedMemory + get_flexible_vertex_size(SrcImpl->fvf) * SrcStartIndex, &strided, 0);
5386 return process_vertices_strided(This, DestIndex, VertexCount, &strided, SrcImpl->fvf, (IWineD3DVertexBufferImpl *) pDestBuffer, Flags);
5390 * Apply / Get / Set Texture Stage States
5391 * TODO: Verify against dx9 definitions
5394 /* 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 */
5395 static void WINAPI IWineD3DDeviceImpl_ApplyTextureUnitState(IWineD3DDevice *iface, DWORD Stage, WINED3DTEXTURESTAGESTATETYPE Type) {
5396 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5397 DWORD Value = This->updateStateBlock->textureState[Stage][Type];
5398 /* FIXME: Handle 3d textures? What if TSS value set before set texture? Need to reapply all values? */
5400 TRACE("(%p) : Stage=%ld, Type=%s(%d), Value=%ld\n", This, Stage, debug_d3dtexturestate(Type), Type, Value);
5402 /* Check that the stage is within limits */
5403 if (Stage >= GL_LIMITS(texture_stages) || Stage < 0) {
5404 TRACE("Attempt to access invalid texture rejected\n");
5411 case WINED3DTSS_ALPHAOP :
5412 case WINED3DTSS_COLOROP :
5413 /* nothing to do as moved to drawprim for now */
5415 case WINED3DTSS_ADDRESSW :
5416 #if 0 /* I'm not sure what D3D does about ADDRESSW appearing twice */
5417 if (Value < minLookup[WINELOOKUP_WARPPARAM] || Value > maxLookup[WINELOOKUP_WARPPARAM]) {
5418 FIXME("Unrecognized or unsupported D3DTADDRESS_* value %ld, state %d\n", Value, Type);
5421 GLint wrapParm = stateLookup[WINELOOKUP_WARPPARAM][Value - minLookup[WINELOOKUP_WARPPARAM]];
5422 TRACE("Setting WRAP_R to %d for %x\n", wrapParm, This->stateBlock->textureDimensions[Stage]);
5423 glTexParameteri(This->stateBlock->textureDimensions[Stage], GL_TEXTURE_WRAP_R, wrapParm);
5424 checkGLcall("glTexParameteri(..., GL_TEXTURE_WRAP_R, wrapParm)");
5427 case WINED3DTSS_TEXCOORDINDEX :
5429 /* Values 0-7 are indexes into the FVF tex coords - See comments in DrawPrimitive */
5431 /* FIXME: From MSDN: The WINED3DTSS_TCI_* flags are mutually exclusive. If you include
5432 one flag, you can still specify an index value, which the system uses to
5433 determine the texture wrapping mode.
5434 eg. SetTextureStageState( 0, D3DTSS_TEXCOORDINDEX, D3DTSS_TCI_CAMERASPACEPOSITION | 1 );
5435 means use the vertex position (camera-space) as the input texture coordinates
5436 for this texture stage, and the wrap mode set in the WINED3DRS_WRAP1 render
5437 state. We do not (yet) support the D3DRENDERSTATE_WRAPx values, nor tie them up
5438 to the TEXCOORDINDEX value */
5441 * Be careful the value of the mask 0xF0000 come from d3d8types.h infos
5443 switch (Value & 0xFFFF0000) {
5444 case D3DTSS_TCI_PASSTHRU:
5445 /*Use the specified texture coordinates contained within the vertex format. This value resolves to zero.*/
5446 glDisable(GL_TEXTURE_GEN_S);
5447 glDisable(GL_TEXTURE_GEN_T);
5448 glDisable(GL_TEXTURE_GEN_R);
5449 glDisable(GL_TEXTURE_GEN_Q);
5450 checkGLcall("glDisable(GL_TEXTURE_GEN_S,T,R,Q)");
5453 case D3DTSS_TCI_CAMERASPACEPOSITION:
5454 /* CameraSpacePosition means use the vertex position, transformed to camera space,
5455 as the input texture coordinates for this stage's texture transformation. This
5456 equates roughly to EYE_LINEAR */
5458 float s_plane[] = { 1.0, 0.0, 0.0, 0.0 };
5459 float t_plane[] = { 0.0, 1.0, 0.0, 0.0 };
5460 float r_plane[] = { 0.0, 0.0, 1.0, 0.0 };
5461 float q_plane[] = { 0.0, 0.0, 0.0, 1.0 };
5462 TRACE("WINED3DTSS_TCI_CAMERASPACEPOSITION - Set eye plane\n");
5464 glMatrixMode(GL_MODELVIEW);
5467 glTexGenfv(GL_S, GL_EYE_PLANE, s_plane);
5468 glTexGenfv(GL_T, GL_EYE_PLANE, t_plane);
5469 glTexGenfv(GL_R, GL_EYE_PLANE, r_plane);
5470 glTexGenfv(GL_Q, GL_EYE_PLANE, q_plane);
5473 TRACE("WINED3DTSS_TCI_CAMERASPACEPOSITION - Set GL_TEXTURE_GEN_x and GL_x, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR\n");
5474 glEnable(GL_TEXTURE_GEN_S);
5475 checkGLcall("glEnable(GL_TEXTURE_GEN_S);");
5476 glTexGeni(GL_S, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR);
5477 checkGLcall("glTexGeni(GL_S, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR)");
5478 glEnable(GL_TEXTURE_GEN_T);
5479 checkGLcall("glEnable(GL_TEXTURE_GEN_T);");
5480 glTexGeni(GL_T, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR);
5481 checkGLcall("glTexGeni(GL_T, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR)");
5482 glEnable(GL_TEXTURE_GEN_R);
5483 checkGLcall("glEnable(GL_TEXTURE_GEN_R);");
5484 glTexGeni(GL_R, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR);
5485 checkGLcall("glTexGeni(GL_R, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR)");
5489 case D3DTSS_TCI_CAMERASPACENORMAL:
5491 if (GL_SUPPORT(NV_TEXGEN_REFLECTION)) {
5492 float s_plane[] = { 1.0, 0.0, 0.0, 0.0 };
5493 float t_plane[] = { 0.0, 1.0, 0.0, 0.0 };
5494 float r_plane[] = { 0.0, 0.0, 1.0, 0.0 };
5495 float q_plane[] = { 0.0, 0.0, 0.0, 1.0 };
5496 TRACE("WINED3DTSS_TCI_CAMERASPACENORMAL - Set eye plane\n");
5498 glMatrixMode(GL_MODELVIEW);
5501 glTexGenfv(GL_S, GL_EYE_PLANE, s_plane);
5502 glTexGenfv(GL_T, GL_EYE_PLANE, t_plane);
5503 glTexGenfv(GL_R, GL_EYE_PLANE, r_plane);
5504 glTexGenfv(GL_Q, GL_EYE_PLANE, q_plane);
5507 glEnable(GL_TEXTURE_GEN_S);
5508 checkGLcall("glEnable(GL_TEXTURE_GEN_S);");
5509 glTexGeni(GL_S, GL_TEXTURE_GEN_MODE, GL_NORMAL_MAP_NV);
5510 checkGLcall("glTexGeni(GL_S, GL_TEXTURE_GEN_MODE, GL_NORMAL_MAP_NV)");
5511 glEnable(GL_TEXTURE_GEN_T);
5512 checkGLcall("glEnable(GL_TEXTURE_GEN_T);");
5513 glTexGeni(GL_T, GL_TEXTURE_GEN_MODE, GL_NORMAL_MAP_NV);
5514 checkGLcall("glTexGeni(GL_T, GL_TEXTURE_GEN_MODE, GL_NORMAL_MAP_NV)");
5515 glEnable(GL_TEXTURE_GEN_R);
5516 checkGLcall("glEnable(GL_TEXTURE_GEN_R);");
5517 glTexGeni(GL_R, GL_TEXTURE_GEN_MODE, GL_NORMAL_MAP_NV);
5518 checkGLcall("glTexGeni(GL_R, GL_TEXTURE_GEN_MODE, GL_NORMAL_MAP_NV)");
5523 case D3DTSS_TCI_CAMERASPACEREFLECTIONVECTOR:
5525 if (GL_SUPPORT(NV_TEXGEN_REFLECTION)) {
5526 float s_plane[] = { 1.0, 0.0, 0.0, 0.0 };
5527 float t_plane[] = { 0.0, 1.0, 0.0, 0.0 };
5528 float r_plane[] = { 0.0, 0.0, 1.0, 0.0 };
5529 float q_plane[] = { 0.0, 0.0, 0.0, 1.0 };
5530 TRACE("WINED3DTSS_TCI_CAMERASPACEREFLECTIONVECTOR - Set eye plane\n");
5532 glMatrixMode(GL_MODELVIEW);
5535 glTexGenfv(GL_S, GL_EYE_PLANE, s_plane);
5536 glTexGenfv(GL_T, GL_EYE_PLANE, t_plane);
5537 glTexGenfv(GL_R, GL_EYE_PLANE, r_plane);
5538 glTexGenfv(GL_Q, GL_EYE_PLANE, q_plane);
5541 glEnable(GL_TEXTURE_GEN_S);
5542 checkGLcall("glEnable(GL_TEXTURE_GEN_S);");
5543 glTexGeni(GL_S, GL_TEXTURE_GEN_MODE, GL_REFLECTION_MAP_NV);
5544 checkGLcall("glTexGeni(GL_S, GL_TEXTURE_GEN_MODE, GL_REFLECTION_MAP_NV)");
5545 glEnable(GL_TEXTURE_GEN_T);
5546 checkGLcall("glEnable(GL_TEXTURE_GEN_T);");
5547 glTexGeni(GL_T, GL_TEXTURE_GEN_MODE, GL_REFLECTION_MAP_NV);
5548 checkGLcall("glTexGeni(GL_T, GL_TEXTURE_GEN_MODE, GL_REFLECTION_MAP_NV)");
5549 glEnable(GL_TEXTURE_GEN_R);
5550 checkGLcall("glEnable(GL_TEXTURE_GEN_R);");
5551 glTexGeni(GL_R, GL_TEXTURE_GEN_MODE, GL_REFLECTION_MAP_NV);
5552 checkGLcall("glTexGeni(GL_R, GL_TEXTURE_GEN_MODE, GL_REFLECTION_MAP_NV)");
5557 /* Unhandled types: */
5560 /* ? disable GL_TEXTURE_GEN_n ? */
5561 glDisable(GL_TEXTURE_GEN_S);
5562 glDisable(GL_TEXTURE_GEN_T);
5563 glDisable(GL_TEXTURE_GEN_R);
5564 glDisable(GL_TEXTURE_GEN_Q);
5565 FIXME("Unhandled WINED3DTSS_TEXCOORDINDEX %lx\n", Value);
5572 case WINED3DTSS_TEXTURETRANSFORMFLAGS :
5573 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);
5576 case WINED3DTSS_BUMPENVMAT00 :
5577 case WINED3DTSS_BUMPENVMAT01 :
5578 TRACE("BUMPENVMAT0%u Stage=%ld, Type=%d, Value =%ld\n", Type - WINED3DTSS_BUMPENVMAT00, Stage, Type, Value);
5580 case WINED3DTSS_BUMPENVMAT10 :
5581 case WINED3DTSS_BUMPENVMAT11 :
5582 TRACE("BUMPENVMAT1%u Stage=%ld, Type=%d, Value =%ld\n", Type - WINED3DTSS_BUMPENVMAT10, Stage, Type, Value);
5585 case WINED3DTSS_BUMPENVLSCALE :
5586 TRACE("BUMPENVLSCALE Stage=%ld, Type=%d, Value =%ld\n", Stage, Type, Value);
5589 case WINED3DTSS_BUMPENVLOFFSET :
5590 TRACE("BUMPENVLOFFSET Stage=%ld, Type=%d, Value =%ld\n", Stage, Type, Value);
5593 case WINED3DTSS_RESULTARG :
5594 TRACE("RESULTARG Still a stub, Stage=%ld, Type=%d, Value =%ld\n", Stage, Type, Value);
5598 /* Put back later: FIXME("(%p) : stub, Stage=%ld, Type=%d, Value =%ld\n", This, Stage, Type, Value); */
5599 TRACE("Still a stub, Stage=%ld, Type=%d, Value =%ld\n", Stage, Type, Value);
5608 * Get / Set Texture Stage States
5609 * TODO: Verify against dx9 definitions
5611 static HRESULT WINAPI IWineD3DDeviceImpl_SetTextureStageState(IWineD3DDevice *iface, DWORD Stage, WINED3DTEXTURESTAGESTATETYPE Type, DWORD Value) {
5612 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5614 /* FIXME: Handle 3d textures? What if TSS value set before set texture? Need to reapply all values? */
5616 TRACE("(%p) : Stage=%ld, Type=%s(%d), Value=%ld\n", This, Stage, debug_d3dtexturestate(Type), Type, Value);
5618 /* Reject invalid texture units */
5619 if (Stage >= GL_LIMITS(texture_stages)) {
5620 TRACE("Attempt to access invalid texture rejected\n");
5621 return WINED3DERR_INVALIDCALL;
5624 This->updateStateBlock->changed.textureState[Stage][Type] = TRUE;
5625 This->updateStateBlock->set.textureState[Stage][Type] = TRUE;
5626 This->updateStateBlock->textureState[Stage][Type] = Value;
5631 static HRESULT WINAPI IWineD3DDeviceImpl_GetTextureStageState(IWineD3DDevice *iface, DWORD Stage, WINED3DTEXTURESTAGESTATETYPE Type, DWORD* pValue) {
5632 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5633 TRACE("(%p) : requesting Stage %ld, Type %d getting %ld\n", This, Stage, Type, This->updateStateBlock->textureState[Stage][Type]);
5634 *pValue = This->updateStateBlock->textureState[Stage][Type];
5641 static HRESULT WINAPI IWineD3DDeviceImpl_SetTexture(IWineD3DDevice *iface, DWORD Stage, IWineD3DBaseTexture* pTexture) {
5643 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5644 IWineD3DBaseTexture *oldTexture;
5646 oldTexture = This->updateStateBlock->textures[Stage];
5647 TRACE("(%p) : Stage(%ld), Texture (%p)\n", This, Stage, pTexture);
5649 #if 0 /* TODO: check so vertex textures */
5650 if (Stage >= D3DVERTEXTEXTURESAMPLER && Stage <= D3DVERTEXTEXTURESAMPLER3){
5651 This->updateStateBlock->vertexTextures[Stage - D3DVERTEXTEXTURESAMPLER] = pTexture;
5656 /* Reject invalid texture units */
5657 if (Stage >= GL_LIMITS(sampler_stages) || Stage < 0) {
5658 WARN("Attempt to access invalid texture rejected\n");
5659 return WINED3DERR_INVALIDCALL;
5662 if(pTexture != NULL) {
5663 /* SetTexture isn't allowed on textures in WINED3DPOOL_SCRATCH;
5665 if(((IWineD3DTextureImpl*)pTexture)->resource.pool == WINED3DPOOL_SCRATCH) {
5666 WARN("(%p) Attempt to set scratch texture rejected\n", pTexture);
5667 return WINED3DERR_INVALIDCALL;
5671 oldTexture = This->updateStateBlock->textures[Stage];
5672 TRACE("GL_LIMITS %d\n",GL_LIMITS(sampler_stages));
5673 TRACE("(%p) : oldtexture(%p)\n", This,oldTexture);
5675 This->updateStateBlock->set.textures[Stage] = TRUE;
5676 This->updateStateBlock->changed.textures[Stage] = TRUE;
5677 TRACE("(%p) : setting new texture to %p\n", This, pTexture);
5678 This->updateStateBlock->textures[Stage] = pTexture;
5680 /* Handle recording of state blocks */
5681 if (This->isRecordingState) {
5682 TRACE("Recording... not performing anything\n");
5686 /** NOTE: MSDN says that setTexture increases the reference count,
5687 * and the the application nust set the texture back to null (or have a leaky application),
5688 * This means we should pass the refcount up to the parent
5689 *******************************/
5690 if (NULL != This->updateStateBlock->textures[Stage]) {
5691 IWineD3DBaseTexture_AddRef(This->updateStateBlock->textures[Stage]);
5694 if (NULL != oldTexture) {
5695 IWineD3DBaseTexture_Release(oldTexture);
5698 /* Reset color keying */
5699 if(Stage == 0 && This->stateBlock->renderState[WINED3DRS_COLORKEYENABLE]) {
5700 BOOL enable_ckey = FALSE;
5703 IWineD3DSurfaceImpl *surf = (IWineD3DSurfaceImpl *) ((IWineD3DTextureImpl *)pTexture)->surfaces[0];
5704 if(surf->CKeyFlags & DDSD_CKSRCBLT) enable_ckey = TRUE;
5708 glAlphaFunc(GL_NOTEQUAL, 0.0);
5709 checkGLcall("glAlphaFunc");
5716 static HRESULT WINAPI IWineD3DDeviceImpl_GetTexture(IWineD3DDevice *iface, DWORD Stage, IWineD3DBaseTexture** ppTexture) {
5717 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5718 TRACE("(%p) : (%ld /* Stage */,%p /* ppTexture */)\n", This, Stage, ppTexture);
5720 /* Reject invalid texture units */
5721 if (Stage >= GL_LIMITS(sampler_stages)) {
5722 TRACE("Attempt to access invalid texture rejected\n");
5723 return WINED3DERR_INVALIDCALL;
5725 *ppTexture=This->updateStateBlock->textures[Stage];
5727 IWineD3DBaseTexture_AddRef(*ppTexture);
5729 return WINED3DERR_INVALIDCALL;
5736 static HRESULT WINAPI IWineD3DDeviceImpl_GetBackBuffer(IWineD3DDevice *iface, UINT iSwapChain, UINT BackBuffer, WINED3DBACKBUFFER_TYPE Type,
5737 IWineD3DSurface **ppBackBuffer) {
5738 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5739 IWineD3DSwapChain *swapChain;
5742 TRACE("(%p) : BackBuf %d Type %d SwapChain %d returning %p\n", This, BackBuffer, Type, iSwapChain, *ppBackBuffer);
5744 hr = IWineD3DDeviceImpl_GetSwapChain(iface, iSwapChain, &swapChain);
5745 if (hr == WINED3D_OK) {
5746 hr = IWineD3DSwapChain_GetBackBuffer(swapChain, BackBuffer, Type, ppBackBuffer);
5747 IWineD3DSwapChain_Release(swapChain);
5749 *ppBackBuffer = NULL;
5754 static HRESULT WINAPI IWineD3DDeviceImpl_GetDeviceCaps(IWineD3DDevice *iface, WINED3DCAPS* pCaps) {
5755 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5756 WARN("(%p) : stub, calling idirect3d for now\n", This);
5757 return IWineD3D_GetDeviceCaps(This->wineD3D, This->adapterNo, This->devType, pCaps);
5760 static HRESULT WINAPI IWineD3DDeviceImpl_GetDisplayMode(IWineD3DDevice *iface, UINT iSwapChain, WINED3DDISPLAYMODE* pMode) {
5761 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5762 IWineD3DSwapChain *swapChain;
5765 if(iSwapChain > 0) {
5766 hr = IWineD3DDeviceImpl_GetSwapChain(iface, iSwapChain, (IWineD3DSwapChain **)&swapChain);
5767 if (hr == WINED3D_OK) {
5768 hr = IWineD3DSwapChain_GetDisplayMode(swapChain, pMode);
5769 IWineD3DSwapChain_Release(swapChain);
5771 FIXME("(%p) Error getting display mode\n", This);
5774 /* Don't read the real display mode,
5775 but return the stored mode instead. X11 can't change the color
5776 depth, and some apps are pretty angry if they SetDisplayMode from
5777 24 to 16 bpp and find out that GetDisplayMode still returns 24 bpp
5779 Also don't relay to the swapchain because with ddraw it's possible
5780 that there isn't a swapchain at all */
5781 pMode->Width = This->ddraw_width;
5782 pMode->Height = This->ddraw_height;
5783 pMode->Format = This->ddraw_format;
5784 pMode->RefreshRate = 0;
5791 static HRESULT WINAPI IWineD3DDeviceImpl_SetHWND(IWineD3DDevice *iface, HWND hWnd) {
5792 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5793 TRACE("(%p)->(%p)\n", This, hWnd);
5795 This->ddraw_window = hWnd;
5799 static HRESULT WINAPI IWineD3DDeviceImpl_GetHWND(IWineD3DDevice *iface, HWND *hWnd) {
5800 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5801 TRACE("(%p)->(%p)\n", This, hWnd);
5803 *hWnd = This->ddraw_window;
5808 * Stateblock related functions
5811 static HRESULT WINAPI IWineD3DDeviceImpl_BeginStateBlock(IWineD3DDevice *iface) {
5812 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5813 IWineD3DStateBlockImpl *object;
5814 TRACE("(%p)", This);
5816 if (This->isRecordingState) {
5817 return WINED3DERR_INVALIDCALL;
5820 object = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(IWineD3DStateBlockImpl));
5821 if (NULL == object ) {
5822 FIXME("(%p)Error allocating memory for stateblock\n", This);
5823 return E_OUTOFMEMORY;
5825 TRACE("(%p) creted object %p\n", This, object);
5826 object->wineD3DDevice= This;
5827 /** FIXME: object->parent = parent; **/
5828 object->parent = NULL;
5829 object->blockType = WINED3DSBT_ALL;
5831 object->lpVtbl = &IWineD3DStateBlock_Vtbl;
5833 IWineD3DStateBlock_Release((IWineD3DStateBlock*)This->updateStateBlock);
5834 This->updateStateBlock = object;
5835 This->isRecordingState = TRUE;
5837 TRACE("(%p) recording stateblock %p\n",This , object);
5841 static HRESULT WINAPI IWineD3DDeviceImpl_EndStateBlock(IWineD3DDevice *iface, IWineD3DStateBlock** ppStateBlock) {
5842 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5844 if (!This->isRecordingState) {
5845 FIXME("(%p) not recording! returning error\n", This);
5846 *ppStateBlock = NULL;
5847 return WINED3DERR_INVALIDCALL;
5850 *ppStateBlock = (IWineD3DStateBlock*)This->updateStateBlock;
5851 This->isRecordingState = FALSE;
5852 This->updateStateBlock = This->stateBlock;
5853 IWineD3DStateBlock_AddRef((IWineD3DStateBlock*)This->updateStateBlock);
5854 /* IWineD3DStateBlock_AddRef(*ppStateBlock); don't need to do this, since we should really just release UpdateStateBlock first */
5855 TRACE("(%p) returning token (ptr to stateblock) of %p\n", This, *ppStateBlock);
5860 * Scene related functions
5862 static HRESULT WINAPI IWineD3DDeviceImpl_BeginScene(IWineD3DDevice *iface) {
5863 /* At the moment we have no need for any functionality at the beginning
5865 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5866 TRACE("(%p) : stub\n", This);
5870 static HRESULT WINAPI IWineD3DDeviceImpl_EndScene(IWineD3DDevice *iface) {
5871 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5872 TRACE("(%p)\n", This);
5874 /* We only have to do this if we need to read the, swapbuffers performs a flush for us */
5876 checkGLcall("glFlush");
5878 TRACE("End Scene\n");
5879 if(This->renderTarget != NULL) {
5881 /* If the container of the rendertarget is a texture then we need to save the data from the pbuffer */
5882 IUnknown *targetContainer = NULL;
5883 if (WINED3D_OK == IWineD3DSurface_GetContainer(This->renderTarget, &IID_IWineD3DBaseTexture, (void **)&targetContainer)
5884 || WINED3D_OK == IWineD3DSurface_GetContainer(This->renderTarget, &IID_IWineD3DDevice, (void **)&targetContainer)) {
5885 TRACE("(%p) : Texture rendertarget %p\n", This ,This->renderTarget);
5886 /** always dirtify for now. we must find a better way to see that surface have been modified
5887 (Modifications should will only occur via draw-primitive, but we do need better locking
5888 switching to render-to-texture should remove the overhead though.
5890 IWineD3DSurface_SetPBufferState(This->renderTarget, TRUE /* inPBuffer */, FALSE /* inTexture */);
5891 IWineD3DSurface_AddDirtyRect(This->renderTarget, NULL);
5892 IWineD3DSurface_PreLoad(This->renderTarget);
5893 IWineD3DSurface_SetPBufferState(This->renderTarget, FALSE /* inPBuffer */, FALSE /* inTexture */);
5894 IUnknown_Release(targetContainer);
5897 This->sceneEnded = TRUE;
5902 static HRESULT WINAPI IWineD3DDeviceImpl_Present(IWineD3DDevice *iface,
5903 CONST RECT* pSourceRect, CONST RECT* pDestRect,
5904 HWND hDestWindowOverride, CONST RGNDATA* pDirtyRegion) {
5905 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5906 IWineD3DSwapChain *swapChain = NULL;
5908 int swapchains = IWineD3DDeviceImpl_GetNumberOfSwapChains(iface);
5910 TRACE("(%p) Presenting the frame\n", This);
5912 for(i = 0 ; i < swapchains ; i ++) {
5914 IWineD3DDeviceImpl_GetSwapChain(iface, i , (IWineD3DSwapChain **)&swapChain);
5915 TRACE("presentinng chain %d, %p\n", i, swapChain);
5916 IWineD3DSwapChain_Present(swapChain, pSourceRect, pDestRect, hDestWindowOverride, pDirtyRegion, 0);
5917 IWineD3DSwapChain_Release(swapChain);
5923 static HRESULT WINAPI IWineD3DDeviceImpl_Clear(IWineD3DDevice *iface, DWORD Count, CONST D3DRECT* pRects,
5924 DWORD Flags, D3DCOLOR Color, float Z, DWORD Stencil) {
5925 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5927 /* TODO: From MSDN This method fails if you specify the D3DCLEAR_ZBUFFER or D3DCLEAR_STENCIL flags when the
5928 render target does not have an attached depth buffer. Similarly, if you specify the D3DCLEAR_STENCIL flag
5929 when the depth-buffer format does not contain stencil buffer information, this method fails. */
5930 GLbitfield glMask = 0;
5931 GLboolean old_ztest;
5932 GLfloat old_z_clear_value;
5933 GLint old_stencil_clear_value;
5934 GLfloat old_color_clear_value[4];
5936 CONST D3DRECT* curRect;
5938 TRACE("(%p) Count (%ld), pRects (%p), Flags (%lx), Z (%f), Stencil (%ld)\n", This,
5939 Count, pRects, Flags, Z, Stencil);
5943 glEnable(GL_SCISSOR_TEST);
5944 checkGLcall("glEnable GL_SCISSOR_TEST");
5946 if (Count > 0 && pRects) {
5952 /* Only set the values up once, as they are not changing */
5953 if (Flags & D3DCLEAR_STENCIL) {
5954 glGetIntegerv(GL_STENCIL_CLEAR_VALUE, &old_stencil_clear_value);
5955 glClearStencil(Stencil);
5956 checkGLcall("glClearStencil");
5957 glMask = glMask | GL_STENCIL_BUFFER_BIT;
5958 glStencilMask(0xFFFFFFFF);
5961 if (Flags & D3DCLEAR_ZBUFFER) {
5962 glGetBooleanv(GL_DEPTH_WRITEMASK, &old_ztest);
5963 glDepthMask(GL_TRUE);
5964 glGetFloatv(GL_DEPTH_CLEAR_VALUE, &old_z_clear_value);
5966 checkGLcall("glClearDepth");
5967 glMask = glMask | GL_DEPTH_BUFFER_BIT;
5970 if (Flags & D3DCLEAR_TARGET) {
5971 TRACE("Clearing screen with glClear to color %lx\n", Color);
5972 glGetFloatv(GL_COLOR_CLEAR_VALUE, old_color_clear_value);
5973 glClearColor(D3DCOLOR_R(Color),
5977 checkGLcall("glClearColor");
5979 /* Clear ALL colors! */
5980 glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
5981 glMask = glMask | GL_COLOR_BUFFER_BIT;
5984 /* Now process each rect in turn */
5985 for (i = 0; i < Count || i == 0; i++) {
5988 /* Note gl uses lower left, width/height */
5989 TRACE("(%p) %p Rect=(%ld,%ld)->(%ld,%ld) glRect=(%ld,%ld), len=%ld, hei=%ld\n", This, curRect,
5990 curRect->x1, curRect->y1, curRect->x2, curRect->y2,
5991 curRect->x1, (((IWineD3DSurfaceImpl *)This->renderTarget)->currentDesc.Height - curRect->y2),
5992 curRect->x2 - curRect->x1, curRect->y2 - curRect->y1);
5993 glScissor(curRect->x1, (((IWineD3DSurfaceImpl *)This->renderTarget)->currentDesc.Height - curRect->y2),
5994 curRect->x2 - curRect->x1, curRect->y2 - curRect->y1);
5995 checkGLcall("glScissor");
5997 glScissor(This->stateBlock->viewport.X,
5998 (((IWineD3DSurfaceImpl *)This->renderTarget)->currentDesc.Height -
5999 (This->stateBlock->viewport.Y + This->stateBlock->viewport.Height)),
6000 This->stateBlock->viewport.Width,
6001 This->stateBlock->viewport.Height);
6002 checkGLcall("glScissor");
6005 /* Clear the selected rectangle (or full screen) */
6007 checkGLcall("glClear");
6009 /* Step to the next rectangle */
6010 if (curRect) curRect = curRect + sizeof(D3DRECT);
6013 /* Restore the old values (why..?) */
6014 if (Flags & D3DCLEAR_STENCIL) {
6015 glClearStencil(old_stencil_clear_value);
6016 glStencilMask(This->stateBlock->renderState[WINED3DRS_STENCILWRITEMASK]);
6018 if (Flags & D3DCLEAR_ZBUFFER) {
6019 glDepthMask(old_ztest);
6020 glClearDepth(old_z_clear_value);
6022 if (Flags & D3DCLEAR_TARGET) {
6023 glClearColor(old_color_clear_value[0],
6024 old_color_clear_value[1],
6025 old_color_clear_value[2],
6026 old_color_clear_value[3]);
6027 glColorMask(This->stateBlock->renderState[WINED3DRS_COLORWRITEENABLE] & D3DCOLORWRITEENABLE_RED ? GL_TRUE : GL_FALSE,
6028 This->stateBlock->renderState[WINED3DRS_COLORWRITEENABLE] & D3DCOLORWRITEENABLE_GREEN ? GL_TRUE : GL_FALSE,
6029 This->stateBlock->renderState[WINED3DRS_COLORWRITEENABLE] & D3DCOLORWRITEENABLE_BLUE ? GL_TRUE : GL_FALSE,
6030 This->stateBlock->renderState[WINED3DRS_COLORWRITEENABLE] & D3DCOLORWRITEENABLE_ALPHA ? GL_TRUE : GL_FALSE);
6033 glDisable(GL_SCISSOR_TEST);
6034 checkGLcall("glDisable");
6043 static HRESULT WINAPI IWineD3DDeviceImpl_DrawPrimitive(IWineD3DDevice *iface, D3DPRIMITIVETYPE PrimitiveType, UINT StartVertex,
6044 UINT PrimitiveCount) {
6046 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
6047 This->stateBlock->streamIsUP = FALSE;
6049 TRACE("(%p) : Type=(%d,%s), Start=%d, Count=%d\n", This, PrimitiveType,
6050 debug_d3dprimitivetype(PrimitiveType),
6051 StartVertex, PrimitiveCount);
6052 drawPrimitive(iface, PrimitiveType, PrimitiveCount, StartVertex, 0/* NumVertices */, -1 /* indxStart */,
6053 0 /* indxSize */, NULL /* indxData */, 0 /* minIndex */, NULL);
6059 /* TODO: baseVIndex needs to be provided from This->stateBlock->baseVertexIndex when called from d3d8 */
6060 static HRESULT WINAPI IWineD3DDeviceImpl_DrawIndexedPrimitive(IWineD3DDevice *iface,
6061 D3DPRIMITIVETYPE PrimitiveType,
6062 INT baseVIndex, UINT minIndex,
6063 UINT NumVertices, UINT startIndex, UINT primCount) {
6065 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
6067 IWineD3DIndexBuffer *pIB;
6068 WINED3DINDEXBUFFER_DESC IdxBufDsc;
6070 pIB = This->stateBlock->pIndexData;
6071 This->stateBlock->streamIsUP = FALSE;
6073 TRACE("(%p) : Type=(%d,%s), min=%d, CountV=%d, startIdx=%d, baseVidx=%d, countP=%d\n", This,
6074 PrimitiveType, debug_d3dprimitivetype(PrimitiveType),
6075 minIndex, NumVertices, startIndex, baseVIndex, primCount);
6077 IWineD3DIndexBuffer_GetDesc(pIB, &IdxBufDsc);
6078 if (IdxBufDsc.Format == WINED3DFMT_INDEX16) {
6084 drawPrimitive(iface, PrimitiveType, primCount, baseVIndex, NumVertices, startIndex,
6085 idxStride, ((IWineD3DIndexBufferImpl *) pIB)->resource.allocatedMemory, minIndex, NULL);
6090 static HRESULT WINAPI IWineD3DDeviceImpl_DrawPrimitiveUP(IWineD3DDevice *iface, D3DPRIMITIVETYPE PrimitiveType,
6091 UINT PrimitiveCount, CONST void* pVertexStreamZeroData,
6092 UINT VertexStreamZeroStride) {
6093 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
6095 TRACE("(%p) : Type=(%d,%s), pCount=%d, pVtxData=%p, Stride=%d\n", This, PrimitiveType,
6096 debug_d3dprimitivetype(PrimitiveType),
6097 PrimitiveCount, pVertexStreamZeroData, VertexStreamZeroStride);
6099 /* release the stream source */
6100 if (This->stateBlock->streamSource[0] != NULL) {
6101 IWineD3DVertexBuffer_Release(This->stateBlock->streamSource[0]);
6104 /* Note in the following, it's not this type, but that's the purpose of streamIsUP */
6105 This->stateBlock->streamSource[0] = (IWineD3DVertexBuffer *)pVertexStreamZeroData;
6106 This->stateBlock->streamStride[0] = VertexStreamZeroStride;
6107 This->stateBlock->streamIsUP = TRUE;
6109 drawPrimitive(iface, PrimitiveType, PrimitiveCount, 0 /* start vertex */, 0 /* NumVertices */,
6110 0 /* indxStart*/, 0 /* indxSize*/, NULL /* indxData */, 0 /* indxMin */, NULL);
6112 /* MSDN specifies stream zero settings must be set to NULL */
6113 This->stateBlock->streamStride[0] = 0;
6114 This->stateBlock->streamSource[0] = NULL;
6116 /*stream zero settings set to null at end, as per the msdn */
6120 static HRESULT WINAPI IWineD3DDeviceImpl_DrawIndexedPrimitiveUP(IWineD3DDevice *iface, D3DPRIMITIVETYPE PrimitiveType,
6121 UINT MinVertexIndex, UINT NumVertices,
6122 UINT PrimitiveCount, CONST void* pIndexData,
6123 WINED3DFORMAT IndexDataFormat,CONST void* pVertexStreamZeroData,
6124 UINT VertexStreamZeroStride) {
6126 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
6128 TRACE("(%p) : Type=(%d,%s), MinVtxIdx=%d, NumVIdx=%d, PCount=%d, pidxdata=%p, IdxFmt=%d, pVtxdata=%p, stride=%d\n",
6129 This, PrimitiveType, debug_d3dprimitivetype(PrimitiveType),
6130 MinVertexIndex, NumVertices, PrimitiveCount, pIndexData,
6131 IndexDataFormat, pVertexStreamZeroData, VertexStreamZeroStride);
6133 if (IndexDataFormat == WINED3DFMT_INDEX16) {
6139 /* release the stream and index data */
6140 if (This->stateBlock->streamSource[0] != NULL) {
6141 IWineD3DVertexBuffer_Release(This->stateBlock->streamSource[0]);
6143 if (This->stateBlock->pIndexData) {
6144 IWineD3DIndexBuffer_Release(This->stateBlock->pIndexData);
6147 /* Note in the following, it's not this type, but that's the purpose of streamIsUP */
6148 This->stateBlock->streamSource[0] = (IWineD3DVertexBuffer *)pVertexStreamZeroData;
6149 This->stateBlock->streamIsUP = TRUE;
6150 This->stateBlock->streamStride[0] = VertexStreamZeroStride;
6152 drawPrimitive(iface, PrimitiveType, PrimitiveCount, 0 /* vertexStart */, NumVertices, 0 /* indxStart */, idxStride, pIndexData, MinVertexIndex, NULL);
6154 /* MSDN specifies stream zero settings and index buffer must be set to NULL */
6155 This->stateBlock->streamSource[0] = NULL;
6156 This->stateBlock->streamStride[0] = 0;
6157 This->stateBlock->pIndexData = NULL;
6162 static HRESULT WINAPI IWineD3DDeviceImpl_DrawPrimitiveStrided (IWineD3DDevice *iface, D3DPRIMITIVETYPE PrimitiveType, UINT PrimitiveCount, WineDirect3DVertexStridedData *DrawPrimStrideData) {
6164 drawPrimitive(iface, PrimitiveType, PrimitiveCount, 0, 0, 0, 0, NULL, 0, DrawPrimStrideData);
6167 /* Yet another way to update a texture, some apps use this to load default textures instead of using surface/texture lock/unlock */
6168 static HRESULT WINAPI IWineD3DDeviceImpl_UpdateTexture (IWineD3DDevice *iface, IWineD3DBaseTexture *pSourceTexture, IWineD3DBaseTexture *pDestinationTexture){
6169 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
6170 HRESULT hr = WINED3D_OK;
6171 WINED3DRESOURCETYPE sourceType;
6172 WINED3DRESOURCETYPE destinationType;
6175 /* TODO: think about moving the code into IWineD3DBaseTexture */
6177 TRACE("(%p) Source %p Destination %p\n", This, pSourceTexture, pDestinationTexture);
6179 /* verify that the source and destination textures aren't NULL */
6180 if (NULL == pSourceTexture || NULL == pDestinationTexture) {
6181 WARN("(%p) : source (%p) and destination (%p) textures must not be NULL, returning WINED3DERR_INVALIDCALL\n",
6182 This, pSourceTexture, pDestinationTexture);
6183 hr = WINED3DERR_INVALIDCALL;
6186 if (pSourceTexture == pDestinationTexture) {
6187 WARN("(%p) : source (%p) and destination (%p) textures must be different, returning WINED3DERR_INVALIDCALL\n",
6188 This, pSourceTexture, pDestinationTexture);
6189 hr = WINED3DERR_INVALIDCALL;
6191 /* Verify that the source and destination textures are the same type */
6192 sourceType = IWineD3DBaseTexture_GetType(pSourceTexture);
6193 destinationType = IWineD3DBaseTexture_GetType(pDestinationTexture);
6195 if (sourceType != destinationType) {
6196 WARN("(%p) Sorce and destination types must match, returning WINED3DERR_INVALIDCALL\n",
6198 hr = WINED3DERR_INVALIDCALL;
6201 /* check that both textures have the identical numbers of levels */
6202 if (IWineD3DBaseTexture_GetLevelCount(pDestinationTexture) != IWineD3DBaseTexture_GetLevelCount(pSourceTexture)) {
6203 WARN("(%p) : source (%p) and destination (%p) textures must have identicle numbers of levels, returning WINED3DERR_INVALIDCALL\n", This, pSourceTexture, pDestinationTexture);
6204 hr = WINED3DERR_INVALIDCALL;
6207 if (WINED3D_OK == hr) {
6209 /* Make sure that the destination texture is loaded */
6210 IWineD3DBaseTexture_PreLoad(pDestinationTexture);
6212 /* Update every surface level of the texture */
6213 levels = IWineD3DBaseTexture_GetLevelCount(pDestinationTexture);
6215 switch (sourceType) {
6216 case WINED3DRTYPE_TEXTURE:
6218 IWineD3DSurface *srcSurface;
6219 IWineD3DSurface *destSurface;
6221 for (i = 0 ; i < levels ; ++i) {
6222 IWineD3DTexture_GetSurfaceLevel((IWineD3DTexture *)pSourceTexture, i, &srcSurface);
6223 IWineD3DTexture_GetSurfaceLevel((IWineD3DTexture *)pDestinationTexture, i, &destSurface);
6224 hr = IWineD3DDevice_UpdateSurface(iface, srcSurface, NULL, destSurface, NULL);
6225 IWineD3DSurface_Release(srcSurface);
6226 IWineD3DSurface_Release(destSurface);
6227 if (WINED3D_OK != hr) {
6228 WARN("(%p) : Call to update surface failed\n", This);
6234 case WINED3DRTYPE_CUBETEXTURE:
6236 IWineD3DSurface *srcSurface;
6237 IWineD3DSurface *destSurface;
6238 WINED3DCUBEMAP_FACES faceType;
6240 for (i = 0 ; i < levels ; ++i) {
6241 /* Update each cube face */
6242 for (faceType = D3DCUBEMAP_FACE_POSITIVE_X; faceType <= D3DCUBEMAP_FACE_NEGATIVE_Z; ++faceType){
6243 hr = IWineD3DCubeTexture_GetCubeMapSurface((IWineD3DCubeTexture *)pSourceTexture, faceType, i, &srcSurface);
6244 if (WINED3D_OK != hr) {
6245 FIXME("(%p) : Failed to get src cube surface facetype %d, level %d\n", This, faceType, i);
6247 TRACE("Got srcSurface %p\n", srcSurface);
6249 hr = IWineD3DCubeTexture_GetCubeMapSurface((IWineD3DCubeTexture *)pDestinationTexture, faceType, i, &destSurface);
6250 if (WINED3D_OK != hr) {
6251 FIXME("(%p) : Failed to get src cube surface facetype %d, level %d\n", This, faceType, i);
6253 TRACE("Got desrSurface %p\n", destSurface);
6255 hr = IWineD3DDevice_UpdateSurface(iface, srcSurface, NULL, destSurface, NULL);
6256 IWineD3DSurface_Release(srcSurface);
6257 IWineD3DSurface_Release(destSurface);
6258 if (WINED3D_OK != hr) {
6259 WARN("(%p) : Call to update surface failed\n", This);
6266 #if 0 /* TODO: Add support for volume textures */
6267 case WINED3DRTYPE_VOLUMETEXTURE:
6269 IWineD3DVolume srcVolume = NULL;
6270 IWineD3DSurface destVolume = NULL;
6272 for (i = 0 ; i < levels ; ++i) {
6273 IWineD3DVolumeTexture_GetVolume((IWineD3DVolumeTexture *)pSourceTexture, i, &srcVolume);
6274 IWineD3DVolumeTexture_GetVolume((IWineD3DVolumeTexture *)pDestinationTexture, i, &destVolume);
6275 hr = IWineD3DFoo_UpdateVolume(iface, srcVolume, NULL, destVolume, NULL);
6276 IWineD3DVolume_Release(srcSurface);
6277 IWineD3DVolume_Release(destSurface);
6278 if (WINED3D_OK != hr) {
6279 WARN("(%p) : Call to update volume failed\n", This);
6287 FIXME("(%p) : Unsupported source and destination type\n", This);
6288 hr = WINED3DERR_INVALIDCALL;
6295 static HRESULT WINAPI IWineD3DDeviceImpl_StretchRect(IWineD3DDevice *iface, IWineD3DSurface *pSourceSurface,
6296 CONST RECT* pSourceRect, IWineD3DSurface *pDestinationSurface,
6297 CONST RECT* pDestRect, WINED3DTEXTUREFILTERTYPE Filter) {
6298 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
6300 TRACE("(%p) : stub\n", This);
6303 static HRESULT WINAPI IWineD3DDeviceImpl_GetRenderTargetData(IWineD3DDevice *iface, IWineD3DSurface *pRenderTarget, IWineD3DSurface *pSurface) {
6304 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
6305 /** TODO: remove remove casts to IWineD3DSurfaceImpl *
6306 * NOTE It may be best to move the code into surface to occomplish this
6307 ****************************************/
6309 WINED3DSURFACE_DESC surfaceDesc;
6310 unsigned int surfaceWidth, surfaceHeight;
6311 glDescriptor *targetGlDescription = NULL;
6312 glDescriptor *surfaceGlDescription = NULL;
6313 IWineD3DSwapChainImpl *container = NULL;
6315 IWineD3DSurface_GetGlDesc(pRenderTarget, &targetGlDescription);
6316 IWineD3DSurface_GetGlDesc(pSurface, &surfaceGlDescription);
6317 memset(&surfaceDesc, 0, sizeof(surfaceDesc));
6319 surfaceDesc.Width = &surfaceWidth;
6320 surfaceDesc.Height = &surfaceHeight;
6321 IWineD3DSurface_GetDesc(pSurface, &surfaceDesc);
6322 /* check to see if it's the backbuffer or the frontbuffer being requested (to make sure the data is up to date)*/
6324 /* Ok, I may need to setup some kind of active swapchain reference on the device */
6325 IWineD3DSurface_GetContainer(pRenderTarget, &IID_IWineD3DSwapChain, (void **)&container);
6327 /* TODO: opengl Context switching for swapchains etc... */
6328 if (NULL != container || pRenderTarget == This->renderTarget || pRenderTarget == This->depthStencilBuffer) {
6329 if (NULL != container && (pRenderTarget == container->backBuffer[0])) {
6330 glReadBuffer(GL_BACK);
6331 vcheckGLcall("glReadBuffer(GL_BACK)");
6332 } else if ((NULL != container && (pRenderTarget == container->frontBuffer)) || (pRenderTarget == This->renderTarget)) {
6333 glReadBuffer(GL_FRONT);
6334 vcheckGLcall("glReadBuffer(GL_FRONT)");
6335 } else if (pRenderTarget == This->depthStencilBuffer) {
6336 FIXME("Reading of depthstencil not yet supported\n");
6339 glReadPixels(surfaceGlDescription->target,
6340 surfaceGlDescription->level,
6343 surfaceGlDescription->glFormat,
6344 surfaceGlDescription->glType,
6345 (void *)IWineD3DSurface_GetData(pSurface));
6346 vcheckGLcall("glReadPixels(...)");
6347 if(NULL != container ){
6348 IWineD3DSwapChain_Release((IWineD3DSwapChain*) container);
6351 IWineD3DBaseTexture *container;
6352 GLenum textureDimensions = GL_TEXTURE_2D;
6354 if (WINED3D_OK == IWineD3DSurface_GetContainer(pSurface, &IID_IWineD3DBaseTexture, (void **)&container)) {
6355 textureDimensions = IWineD3DBaseTexture_GetTextureDimensions(container);
6356 IWineD3DBaseTexture_Release(container);
6358 /* TODO: 2D -> Cube surface coppies etc.. */
6359 if (surfaceGlDescription->target != textureDimensions) {
6360 FIXME("(%p) : Texture dimension mismatch\n", This);
6362 glEnable(textureDimensions);
6363 vcheckGLcall("glEnable(GL_TEXTURE_...)");
6364 /* FIXME: this isn't correct, it need to add a dirty rect if nothing else... */
6365 glBindTexture(targetGlDescription->target, targetGlDescription->textureName);
6366 vcheckGLcall("glBindTexture");
6367 glGetTexImage(surfaceGlDescription->target,
6368 surfaceGlDescription->level,
6369 surfaceGlDescription->glFormat,
6370 surfaceGlDescription->glType,
6371 (void *)IWineD3DSurface_GetData(pSurface));
6372 glDisable(textureDimensions);
6373 vcheckGLcall("glDisable(GL_TEXTURE_...)");
6380 static HRESULT WINAPI IWineD3DDeviceImpl_GetFrontBufferData(IWineD3DDevice *iface,UINT iSwapChain, IWineD3DSurface *pDestSurface) {
6381 IWineD3DSwapChain *swapChain;
6383 hr = IWineD3DDeviceImpl_GetSwapChain(iface, iSwapChain, (IWineD3DSwapChain **)&swapChain);
6384 if(hr == WINED3D_OK) {
6385 hr = IWineD3DSwapChain_GetFrontBufferData(swapChain, pDestSurface);
6386 IWineD3DSwapChain_Release(swapChain);
6391 static HRESULT WINAPI IWineD3DDeviceImpl_ValidateDevice(IWineD3DDevice *iface, DWORD* pNumPasses) {
6392 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
6393 /* return a sensible default */
6395 /* TODO: If the window is minimized then validate device should return something other than WINED3D_OK */
6396 FIXME("(%p) : stub\n", This);
6400 static HRESULT WINAPI IWineD3DDeviceImpl_SetPaletteEntries(IWineD3DDevice *iface, UINT PaletteNumber, CONST PALETTEENTRY* pEntries) {
6401 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
6403 TRACE("(%p) : PaletteNumber %u\n", This, PaletteNumber);
6404 if ( PaletteNumber < 0 || PaletteNumber >= MAX_PALETTES) {
6405 WARN("(%p) : (%u) Out of range 0-%u, returning Invalid Call\n", This, PaletteNumber, MAX_PALETTES);
6406 return WINED3DERR_INVALIDCALL;
6408 for (j = 0; j < 256; ++j) {
6409 This->palettes[PaletteNumber][j].peRed = pEntries[j].peRed;
6410 This->palettes[PaletteNumber][j].peGreen = pEntries[j].peGreen;
6411 This->palettes[PaletteNumber][j].peBlue = pEntries[j].peBlue;
6412 This->palettes[PaletteNumber][j].peFlags = pEntries[j].peFlags;
6414 TRACE("(%p) : returning\n", This);
6418 static HRESULT WINAPI IWineD3DDeviceImpl_GetPaletteEntries(IWineD3DDevice *iface, UINT PaletteNumber, PALETTEENTRY* pEntries) {
6419 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
6421 TRACE("(%p) : PaletteNumber %u\n", This, PaletteNumber);
6422 if ( PaletteNumber < 0 || PaletteNumber >= MAX_PALETTES) {
6423 WARN("(%p) : (%u) Out of range 0-%u, returning Invalid Call\n", This, PaletteNumber, MAX_PALETTES);
6424 return WINED3DERR_INVALIDCALL;
6426 for (j = 0; j < 256; ++j) {
6427 pEntries[j].peRed = This->palettes[PaletteNumber][j].peRed;
6428 pEntries[j].peGreen = This->palettes[PaletteNumber][j].peGreen;
6429 pEntries[j].peBlue = This->palettes[PaletteNumber][j].peBlue;
6430 pEntries[j].peFlags = This->palettes[PaletteNumber][j].peFlags;
6432 TRACE("(%p) : returning\n", This);
6436 static HRESULT WINAPI IWineD3DDeviceImpl_SetCurrentTexturePalette(IWineD3DDevice *iface, UINT PaletteNumber) {
6437 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
6438 TRACE("(%p) : PaletteNumber %u\n", This, PaletteNumber);
6439 if ( PaletteNumber < 0 || PaletteNumber >= MAX_PALETTES) {
6440 WARN("(%p) : (%u) Out of range 0-%u, returning Invalid Call\n", This, PaletteNumber, MAX_PALETTES);
6441 return WINED3DERR_INVALIDCALL;
6443 /*TODO: stateblocks */
6444 This->currentPalette = PaletteNumber;
6445 TRACE("(%p) : returning\n", This);
6449 static HRESULT WINAPI IWineD3DDeviceImpl_GetCurrentTexturePalette(IWineD3DDevice *iface, UINT* PaletteNumber) {
6450 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
6451 if (PaletteNumber == NULL) {
6452 WARN("(%p) : returning Invalid Call\n", This);
6453 return WINED3DERR_INVALIDCALL;
6455 /*TODO: stateblocks */
6456 *PaletteNumber = This->currentPalette;
6457 TRACE("(%p) : returning %u\n", This, *PaletteNumber);
6461 static HRESULT WINAPI IWineD3DDeviceImpl_SetSoftwareVertexProcessing(IWineD3DDevice *iface, BOOL bSoftware) {
6462 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
6463 static BOOL showFixmes = TRUE;
6465 FIXME("(%p) : stub\n", This);
6469 This->softwareVertexProcessing = bSoftware;
6474 static BOOL WINAPI IWineD3DDeviceImpl_GetSoftwareVertexProcessing(IWineD3DDevice *iface) {
6475 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
6476 static BOOL showFixmes = TRUE;
6478 FIXME("(%p) : stub\n", This);
6481 return This->softwareVertexProcessing;
6485 static HRESULT WINAPI IWineD3DDeviceImpl_GetRasterStatus(IWineD3DDevice *iface, UINT iSwapChain, WINED3DRASTER_STATUS* pRasterStatus) {
6486 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
6487 IWineD3DSwapChain *swapChain;
6490 TRACE("(%p) : SwapChain %d returning %p\n", This, iSwapChain, pRasterStatus);
6492 hr = IWineD3DDeviceImpl_GetSwapChain(iface, iSwapChain, (IWineD3DSwapChain **)&swapChain);
6493 if(hr == WINED3D_OK){
6494 hr = IWineD3DSwapChain_GetRasterStatus(swapChain, pRasterStatus);
6495 IWineD3DSwapChain_Release(swapChain);
6497 FIXME("(%p) IWineD3DSwapChain_GetRasterStatus returned in error\n", This);
6503 static HRESULT WINAPI IWineD3DDeviceImpl_SetNPatchMode(IWineD3DDevice *iface, float nSegments) {
6504 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
6505 static BOOL showfixmes = TRUE;
6506 if(nSegments != 0.0f) {
6508 FIXME("(%p) : stub nSegments(%f)\n", This, nSegments);
6515 static float WINAPI IWineD3DDeviceImpl_GetNPatchMode(IWineD3DDevice *iface) {
6516 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
6517 static BOOL showfixmes = TRUE;
6519 FIXME("(%p) : stub returning(%f)\n", This, 0.0f);
6525 static HRESULT WINAPI IWineD3DDeviceImpl_UpdateSurface(IWineD3DDevice *iface, IWineD3DSurface *pSourceSurface, CONST RECT* pSourceRect, IWineD3DSurface *pDestinationSurface, CONST POINT* pDestPoint) {
6526 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *) iface;
6527 /** TODO: remove casts to IWineD3DSurfaceImpl
6528 * NOTE: move code to surface to accomplish this
6529 ****************************************/
6530 IWineD3DSurfaceImpl *pSrcSurface = (IWineD3DSurfaceImpl *)pSourceSurface;
6531 int srcWidth, srcHeight;
6532 unsigned int srcSurfaceWidth, srcSurfaceHeight, destSurfaceWidth, destSurfaceHeight;
6533 WINED3DFORMAT destFormat, srcFormat;
6535 int destLeft, destTop;
6536 WINED3DPOOL srcPool, destPool;
6538 int rowoffset = 0; /* how many bytes to add onto the end of a row to wraparound to the beginning of the next */
6539 glDescriptor *glDescription = NULL;
6540 GLenum textureDimensions = GL_TEXTURE_2D;
6541 IWineD3DBaseTexture *baseTexture;
6543 WINED3DSURFACE_DESC winedesc;
6545 TRACE("(%p) : Source (%p) Rect (%p) Destination (%p) Point(%p)\n", This, pSourceSurface, pSourceRect, pDestinationSurface, pDestPoint);
6546 memset(&winedesc, 0, sizeof(winedesc));
6547 winedesc.Width = &srcSurfaceWidth;
6548 winedesc.Height = &srcSurfaceHeight;
6549 winedesc.Pool = &srcPool;
6550 winedesc.Format = &srcFormat;
6552 IWineD3DSurface_GetDesc(pSourceSurface, &winedesc);
6554 winedesc.Width = &destSurfaceWidth;
6555 winedesc.Height = &destSurfaceHeight;
6556 winedesc.Pool = &destPool;
6557 winedesc.Format = &destFormat;
6558 winedesc.Size = &destSize;
6560 IWineD3DSurface_GetDesc(pDestinationSurface, &winedesc);
6562 if(srcPool != WINED3DPOOL_SYSTEMMEM || destPool != WINED3DPOOL_DEFAULT){
6563 WARN("source %p must be SYSTEMMEM and dest %p must be DEFAULT, returning WINED3DERR_INVALIDCALL\n", pSourceSurface, pDestinationSurface);
6564 return WINED3DERR_INVALIDCALL;
6567 if (destFormat == WINED3DFMT_UNKNOWN) {
6568 TRACE("(%p) : Converting destination surface from WINED3DFMT_UNKNOWN to the source format\n", This);
6569 IWineD3DSurface_SetFormat(pDestinationSurface, srcFormat);
6571 /* Get the update surface description */
6572 IWineD3DSurface_GetDesc(pDestinationSurface, &winedesc);
6575 /* Make sure the surface is loaded and up to date */
6576 IWineD3DSurface_PreLoad(pDestinationSurface);
6578 IWineD3DSurface_GetGlDesc(pDestinationSurface, &glDescription);
6582 /* this needs to be done in lines if the sourceRect != the sourceWidth */
6583 srcWidth = pSourceRect ? pSourceRect->right - pSourceRect->left : srcSurfaceWidth;
6584 srcHeight = pSourceRect ? pSourceRect->top - pSourceRect->bottom : srcSurfaceHeight;
6585 destLeft = pDestPoint ? pDestPoint->x : 0;
6586 destTop = pDestPoint ? pDestPoint->y : 0;
6589 /* This function doesn't support compressed textures
6590 the pitch is just bytesPerPixel * width */
6591 if(srcWidth != srcSurfaceWidth || (pSourceRect != NULL && pSourceRect->left != 0) ){
6592 rowoffset = (srcSurfaceWidth - srcWidth) * pSrcSurface->bytesPerPixel;
6593 offset += pSourceRect->left * pSrcSurface->bytesPerPixel;
6594 /* TODO: do we ever get 3bpp?, would a shift and an add be quicker than a mul (well maybe a cycle or two) */
6596 /* TODO DXT formats */
6598 if(pSourceRect != NULL && pSourceRect->top != 0){
6599 offset += pSourceRect->top * srcWidth * pSrcSurface->bytesPerPixel;
6601 TRACE("(%p) glTexSubImage2D, Level %d, left %d, top %d, width %d, height %d , ftm %d, type %d, memory %p\n"
6603 ,glDescription->level
6608 ,glDescription->glFormat
6609 ,glDescription->glType
6610 ,IWineD3DSurface_GetData(pSourceSurface)
6614 if (IWineD3DSurface_GetData(pSourceSurface) == NULL) {
6616 /* need to lock the surface to get the data */
6617 FIXME("Surfaces has no allocated memory, but should be an in memory only surface\n");
6620 /* TODO: Cube and volume support */
6622 /* not a whole row so we have to do it a line at a time */
6625 /* hopefully using pointer addtion will be quicker than using a point + j * rowoffset */
6626 unsigned char* data =((unsigned char *)IWineD3DSurface_GetData(pSourceSurface)) + offset;
6628 for(j = destTop ; j < (srcHeight + destTop) ; j++){
6630 glTexSubImage2D(glDescription->target
6631 ,glDescription->level
6636 ,glDescription->glFormat
6637 ,glDescription->glType
6638 ,data /* could be quicker using */
6643 } else { /* Full width, so just write out the whole texture */
6645 if (WINED3DFMT_DXT1 == destFormat ||
6646 WINED3DFMT_DXT2 == destFormat ||
6647 WINED3DFMT_DXT3 == destFormat ||
6648 WINED3DFMT_DXT4 == destFormat ||
6649 WINED3DFMT_DXT5 == destFormat) {
6650 if (GL_SUPPORT(EXT_TEXTURE_COMPRESSION_S3TC)) {
6651 if (destSurfaceHeight != srcHeight || destSurfaceWidth != srcWidth) {
6652 /* FIXME: The easy way to do this is lock the destination, and copy the bits accross */
6653 FIXME("Updating part of a compressed texture is not supported at the moment\n");
6654 } if (destFormat != srcFormat) {
6655 FIXME("Updating mixed format compressed texture is not curretly support\n");
6657 GL_EXTCALL(glCompressedTexImage2DARB)(glDescription->target,
6658 glDescription->level,
6659 glDescription->glFormatInternal,
6664 IWineD3DSurface_GetData(pSourceSurface));
6667 FIXME("Attempting to update a DXT compressed texture without hardware support\n");
6672 if (NP2_REPACK == wined3d_settings.nonpower2_mode) {
6674 /* some applications cannot handle odd pitches returned by soft non-power2, so we have
6675 to repack the data from pow2Width/Height to expected Width,Height, this makes the
6676 data returned by GetData non-power2 width/height with hardware non-power2
6677 pow2Width/height are set to surface width height, repacking isn't needed so it
6678 doesn't matter which function gets called. */
6679 glTexSubImage2D(glDescription->target
6680 ,glDescription->level
6685 ,glDescription->glFormat
6686 ,glDescription->glType
6687 ,IWineD3DSurface_GetData(pSourceSurface)
6691 /* not repacked, the data returned by IWineD3DSurface_GetData is pow2Width x pow2Height */
6692 glTexSubImage2D(glDescription->target
6693 ,glDescription->level
6696 ,((IWineD3DSurfaceImpl *)pSourceSurface)->pow2Width
6697 ,((IWineD3DSurfaceImpl *)pSourceSurface)->pow2Height
6698 ,glDescription->glFormat
6699 ,glDescription->glType
6700 ,IWineD3DSurface_GetData(pSourceSurface)
6706 checkGLcall("glTexSubImage2D");
6708 /* I only need to look up baseTexture here, so it may be a good idea to hava a GL_TARGET ->
6709 * GL_DIMENSIONS lookup, or maybe store the dimensions on the surface (but that's making the
6710 * surface bigger than it needs to be hmm.. */
6711 if (WINED3D_OK == IWineD3DSurface_GetContainer(pDestinationSurface, &IID_IWineD3DBaseTexture, (void **)&baseTexture)) {
6712 textureDimensions = IWineD3DBaseTexture_GetTextureDimensions(baseTexture);
6713 IWineD3DBaseTexture_Release(baseTexture);
6716 glDisable(textureDimensions); /* This needs to be managed better.... */
6722 /* Used by DirectX 8 */
6723 static HRESULT WINAPI IWineD3DDeviceImpl_CopyRects(IWineD3DDevice *iface,
6724 IWineD3DSurface* pSourceSurface, CONST RECT* pSourceRectsArray, UINT cRects,
6725 IWineD3DSurface* pDestinationSurface, CONST POINT* pDestPointsArray) {
6727 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
6728 HRESULT hr = WINED3D_OK;
6729 WINED3DFORMAT srcFormat, destFormat;
6730 UINT srcWidth, destWidth;
6731 UINT srcHeight, destHeight;
6733 WINED3DSURFACE_DESC winedesc;
6735 TRACE("(%p) pSrcSur=%p, pSourceRects=%p, cRects=%d, pDstSur=%p, pDestPtsArr=%p\n", This,
6736 pSourceSurface, pSourceRectsArray, cRects, pDestinationSurface, pDestPointsArray);
6739 /* Check that the source texture is in WINED3DPOOL_SYSTEMMEM and the destination texture is in WINED3DPOOL_DEFAULT */
6740 memset(&winedesc, 0, sizeof(winedesc));
6742 winedesc.Format = &srcFormat;
6743 winedesc.Width = &srcWidth;
6744 winedesc.Height = &srcHeight;
6745 winedesc.Size = &srcSize;
6746 IWineD3DSurface_GetDesc(pSourceSurface, &winedesc);
6748 winedesc.Format = &destFormat;
6749 winedesc.Width = &destWidth;
6750 winedesc.Height = &destHeight;
6751 winedesc.Size = NULL;
6752 IWineD3DSurface_GetDesc(pDestinationSurface, &winedesc);
6754 /* Check that the source and destination formats match */
6755 if (srcFormat != destFormat && WINED3DFMT_UNKNOWN != destFormat) {
6756 WARN("(%p) source %p format must match the dest %p format, returning WINED3DERR_INVALIDCALL\n", This, pSourceSurface, pDestinationSurface);
6757 return WINED3DERR_INVALIDCALL;
6758 } else if (WINED3DFMT_UNKNOWN == destFormat) {
6759 TRACE("(%p) : Converting destination surface from WINED3DFMT_UNKNOWN to the source format\n", This);
6760 IWineD3DSurface_SetFormat(pDestinationSurface, srcFormat);
6761 destFormat = srcFormat;
6764 /* Quick if complete copy ... */
6765 if (cRects == 0 && pSourceRectsArray == NULL && pDestPointsArray == NULL) {
6767 if (srcWidth == destWidth && srcHeight == destHeight) {
6768 WINED3DLOCKED_RECT lrSrc;
6769 WINED3DLOCKED_RECT lrDst;
6770 IWineD3DSurface_LockRect(pSourceSurface, &lrSrc, NULL, WINED3DLOCK_READONLY);
6771 IWineD3DSurface_LockRect(pDestinationSurface, &lrDst, NULL, 0L);
6772 TRACE("Locked src and dst, Direct copy as surfaces are equal, w=%d, h=%d\n", srcWidth, srcHeight);
6774 memcpy(lrDst.pBits, lrSrc.pBits, srcSize);
6776 IWineD3DSurface_UnlockRect(pSourceSurface);
6777 IWineD3DSurface_UnlockRect(pDestinationSurface);
6778 TRACE("Unlocked src and dst\n");
6782 FIXME("Wanted to copy all surfaces but size not compatible, returning WINED3DERR_INVALIDCALL\n");
6783 hr = WINED3DERR_INVALIDCALL;
6788 if (NULL != pSourceRectsArray && NULL != pDestPointsArray) {
6790 int bytesPerPixel = ((IWineD3DSurfaceImpl *) pSourceSurface)->bytesPerPixel;
6793 /* Copy rect by rect */
6794 for (i = 0; i < cRects; ++i) {
6795 CONST RECT* r = &pSourceRectsArray[i];
6796 CONST POINT* p = &pDestPointsArray[i];
6799 WINED3DLOCKED_RECT lrSrc;
6800 WINED3DLOCKED_RECT lrDst;
6803 TRACE("Copying rect %d (%ld,%ld),(%ld,%ld) -> (%ld,%ld)\n", i, r->left, r->top, r->right, r->bottom, p->x, p->y);
6804 if (srcFormat == WINED3DFMT_DXT1) {
6805 copyperline = ((r->right - r->left) * bytesPerPixel) / 2; /* DXT1 is half byte per pixel */
6807 copyperline = ((r->right - r->left) * bytesPerPixel);
6810 IWineD3DSurface_LockRect(pSourceSurface, &lrSrc, r, WINED3DLOCK_READONLY);
6811 dest_rect.left = p->x;
6812 dest_rect.top = p->y;
6813 dest_rect.right = p->x + (r->right - r->left);
6814 dest_rect.bottom= p->y + (r->bottom - r->top);
6815 IWineD3DSurface_LockRect(pDestinationSurface, &lrDst, &dest_rect, 0L);
6816 TRACE("Locked src and dst\n");
6818 /* Find where to start */
6819 for (j = 0; j < (r->bottom - r->top - 1); ++j) {
6820 memcpy((char*) lrDst.pBits + (j * lrDst.Pitch), (char*) lrSrc.pBits + (j * lrSrc.Pitch), copyperline);
6822 IWineD3DSurface_UnlockRect(pSourceSurface);
6823 IWineD3DSurface_UnlockRect(pDestinationSurface);
6824 TRACE("Unlocked src and dst\n");
6827 FIXME("Wanted to copy partial surfaces not implemented, returning WINED3DERR_INVALIDCALL\n");
6828 hr = WINED3DERR_INVALIDCALL;
6835 /* Implementation details at http://developer.nvidia.com/attach/6494
6837 http://oss.sgi.com/projects/ogl-sample/registry/NV/evaluators.txt
6838 hmm.. no longer supported use
6839 OpenGL evaluators or tessellate surfaces within your application.
6842 /* http://msdn.microsoft.com/library/default.asp?url=/library/en-us/directx9_c/directx/graphics/reference/d3d/interfaces/idirect3ddevice9/DrawRectPatch.asp */
6843 static HRESULT WINAPI IWineD3DDeviceImpl_DrawRectPatch(IWineD3DDevice *iface, UINT Handle, CONST float* pNumSegs, CONST WINED3DRECTPATCH_INFO* pRectPatchInfo) {
6844 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
6845 TRACE("(%p) Handle(%d) noSegs(%p) rectpatch(%p)\n", This, Handle, pNumSegs, pRectPatchInfo);
6846 FIXME("(%p) : Stub\n", This);
6851 /* http://msdn.microsoft.com/library/default.asp?url=/library/en-us/directx9_c/directx/graphics/reference/d3d/interfaces/idirect3ddevice9/DrawTriPatch.asp */
6852 static HRESULT WINAPI IWineD3DDeviceImpl_DrawTriPatch(IWineD3DDevice *iface, UINT Handle, CONST float* pNumSegs, CONST WINED3DTRIPATCH_INFO* pTriPatchInfo) {
6853 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
6854 TRACE("(%p) Handle(%d) noSegs(%p) tripatch(%p)\n", This, Handle, pNumSegs, pTriPatchInfo);
6855 FIXME("(%p) : Stub\n", This);
6859 static HRESULT WINAPI IWineD3DDeviceImpl_DeletePatch(IWineD3DDevice *iface, UINT Handle) {
6860 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
6861 TRACE("(%p) Handle(%d)\n", This, Handle);
6862 FIXME("(%p) : Stub\n", This);
6866 static HRESULT WINAPI IWineD3DDeviceImpl_ColorFill(IWineD3DDevice *iface, IWineD3DSurface *pSurface, CONST D3DRECT* pRect, D3DCOLOR color) {
6867 /* I couldn't find a 'really' quick way of doing this in openGl so here goes
6868 fill a surface with a block of color! */
6869 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
6870 /* TODO: get rid of the use of IWineD3DSurfaceImpl, move code into surface.c */
6871 IWineD3DSurfaceImpl *surface = (IWineD3DSurfaceImpl *)pSurface;
6872 IWineD3DSwapChainImpl *container = NULL;
6873 BOOL isRenderTarget = FALSE;
6874 unsigned int width, height;
6875 unsigned int top, left;
6878 TRACE("(%p) Colour fill Surface: %p rect: %p color: %ld\n", This, pSurface, pRect, color);
6880 if (surface->resource.pool != WINED3DPOOL_DEFAULT && surface->resource.pool != WINED3DPOOL_SYSTEMMEM) {
6881 FIXME("call to colorfill with non WINED3DPOOL_DEFAULT or WINED3DPOOL_SYSTEMMEM surface\n");
6882 return WINED3DERR_INVALIDCALL;
6885 /* TODO: get rid of IWineD3DSwapChainImpl reference, a 'context' manager may help with this */
6886 if (WINED3D_OK == IWineD3DSurface_GetContainer(pSurface, &IID_IWineD3DSwapChain, (void **)&container) || pSurface == This->renderTarget) {
6887 if (WINED3DUSAGE_RENDERTARGET & surface->resource.usage) {
6888 /* TODO: make sure we set everything back to the way it was, and context management!
6889 glGetIntegerv(GL_READ_BUFFER, &prev_read);
6890 vcheckGLcall("glIntegerv");
6891 glGetIntegerv(GL_PACK_SWAP_BYTES, &prev_store);
6892 vcheckGLcall("glIntegerv");
6894 TRACE("Color fill to render targets may cause some graphics issues\n");
6895 if (pSurface == container->frontBuffer) {
6896 glDrawBuffer(GL_FRONT);
6898 glDrawBuffer(GL_BACK);
6901 if (WINED3DUSAGE_DEPTHSTENCIL & surface->resource.usage) {
6902 FIXME("colouring of depth_stencil? %p buffers is not yet supported? %ld\n", surface, surface->resource.usage);
6904 FIXME("(%p) : Regression %ld %p %p\n", This, surface->resource.usage, pSurface, This->renderTarget);
6906 if (container != NULL) {
6907 IWineD3DSwapChain_Release((IWineD3DSwapChain *)container);
6909 /* we can use GL_STENCIL_INDEX etc...*/
6912 if (container != NULL) {
6913 IWineD3DSwapChain_Release((IWineD3DSwapChain *)container);
6915 isRenderTarget = TRUE;
6917 /* TODO: drawing to GL_FRONT and GL_BACK */
6918 /* TODO: see if things can be speeded up by using the correct
6919 * colour model of the target texture from the start (16 bit graphics on 32 X are slow anyway!) */
6920 if (pRect == NULL) {
6923 width = surface->currentDesc.Width;
6924 height = surface->currentDesc.Height;
6928 width = pRect->x2 - left;
6929 height = pRect->y2 - top;
6932 data = HeapAlloc(GetProcessHeap(), 0, 4 * width);
6933 /* Create a 'line' of color color, in the correct format for the surface */
6934 for (u = 0 ; u < width ; u ++) {
6939 if (isRenderTarget == FALSE) {
6940 glDescriptor *glDesc;
6941 IWineD3DSurface_PreLoad(pSurface);
6943 /* draw a block of the coloured line on the sufrace */
6944 IWineD3DSurface_GetGlDesc(pSurface, &glDesc);
6945 for (v = 0 ; v< height;v++) {
6946 glTexSubImage2D(glDesc->target
6947 ,glDesc->level /* level */
6957 checkGLcall("glTexSubImage2D");
6959 glDisable(glDesc->target);
6961 /** FIXME: Using GLClear may be faster **/
6962 glRasterPos2i(left, top);
6963 glPixelZoom((float)width ,(float)height);
6964 glDrawPixels(1, 1, GL_RGBA, GL_UNSIGNED_BYTE, data);
6965 checkGLcall("glDrawPixels");
6967 HeapFree(GetProcessHeap(), 0, data);
6973 /* rendertarget and deptth stencil functions */
6974 static HRESULT WINAPI IWineD3DDeviceImpl_GetRenderTarget(IWineD3DDevice* iface,DWORD RenderTargetIndex, IWineD3DSurface **ppRenderTarget) {
6975 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
6977 /* FIXME: Implelent RenderTargetIndex >0 */
6978 if(RenderTargetIndex > 0)
6979 FIXME("(%p) : RenderTargetIndex %ld >0 not currently supported\n", This, RenderTargetIndex);
6981 *ppRenderTarget = This->renderTarget;
6982 TRACE("(%p) : RenderTarget %ld Index returning %p\n", This, RenderTargetIndex, *ppRenderTarget);
6983 /* Note inc ref on returned surface */
6984 if(*ppRenderTarget != NULL)
6985 IWineD3DSurface_AddRef(*ppRenderTarget);
6989 static HRESULT WINAPI IWineD3DDeviceImpl_SetFrontBackBuffers(IWineD3DDevice *iface, IWineD3DSurface *Front, IWineD3DSurface *Back) {
6990 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
6991 IWineD3DSurfaceImpl *FrontImpl = (IWineD3DSurfaceImpl *) Front;
6992 IWineD3DSurfaceImpl *BackImpl = (IWineD3DSurfaceImpl *) Back;
6993 IWineD3DSwapChainImpl *Swapchain;
6996 TRACE("(%p)->(%p,%p)\n", This, FrontImpl, BackImpl);
6998 hr = IWineD3DDevice_GetSwapChain(iface, 0, (IWineD3DSwapChain **) &Swapchain);
6999 if(hr != WINED3D_OK) {
7000 ERR("Can't get the swapchain\n");
7004 /* Make sure to release the swapchain */
7005 IWineD3DSwapChain_Release((IWineD3DSwapChain *) Swapchain);
7007 if(FrontImpl && !(FrontImpl->resource.usage & WINED3DUSAGE_RENDERTARGET) ) {
7008 ERR("Trying to set a front buffer which doesn't have WINED3DUSAGE_RENDERTARGET usage\n");
7009 return WINED3DERR_INVALIDCALL;
7011 else if(BackImpl && !(BackImpl->resource.usage & WINED3DUSAGE_RENDERTARGET)) {
7012 ERR("Trying to set a back buffer which doesn't have WINED3DUSAGE_RENDERTARGET usage\n");
7013 return WINED3DERR_INVALIDCALL;
7016 if(Swapchain->frontBuffer != Front) {
7017 TRACE("Changing the front buffer from %p to %p\n", Swapchain->frontBuffer, Front);
7019 if(Swapchain->frontBuffer)
7020 IWineD3DSurface_SetContainer(Swapchain->frontBuffer, NULL);
7021 Swapchain->frontBuffer = Front;
7023 if(Swapchain->frontBuffer) {
7024 IWineD3DSurface_SetContainer(Swapchain->frontBuffer, (IWineD3DBase *) Swapchain);
7028 if(Back && !Swapchain->backBuffer) {
7029 /* We need memory for the back buffer array - only one back buffer this way */
7030 Swapchain->backBuffer = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(IWineD3DSurface *));
7031 if(!Swapchain->backBuffer) {
7032 ERR("Out of memory\n");
7033 return E_OUTOFMEMORY;
7037 if(Swapchain->backBuffer[0] != Back) {
7038 TRACE("Changing the back buffer from %p to %p\n", Swapchain->backBuffer, Back);
7040 if(!Swapchain->backBuffer[0]) {
7041 /* GL was told to draw to the front buffer at creation,
7044 glDrawBuffer(GL_BACK);
7045 checkGLcall("glDrawBuffer(GL_BACK)");
7046 /* Set the backbuffer count to 1 because other code uses it to fing the back buffers */
7047 Swapchain->presentParms.BackBufferCount = 1;
7049 /* That makes problems - disable for now */
7050 /* glDrawBuffer(GL_FRONT); */
7051 checkGLcall("glDrawBuffer(GL_FRONT)");
7052 /* We have lost our back buffer, set this to 0 to avoid confusing other code */
7053 Swapchain->presentParms.BackBufferCount = 0;
7057 if(Swapchain->backBuffer[0])
7058 IWineD3DSurface_SetContainer(Swapchain->backBuffer[0], NULL);
7059 Swapchain->backBuffer[0] = Back;
7061 if(Swapchain->backBuffer[0]) {
7062 IWineD3DSurface_SetContainer(Swapchain->backBuffer[0], (IWineD3DBase *) Swapchain);
7064 HeapFree(GetProcessHeap(), 0, Swapchain->backBuffer);
7072 static HRESULT WINAPI IWineD3DDeviceImpl_GetDepthStencilSurface(IWineD3DDevice* iface, IWineD3DSurface **ppZStencilSurface) {
7073 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
7074 *ppZStencilSurface = This->depthStencilBuffer;
7075 TRACE("(%p) : zStencilSurface returning %p\n", This, *ppZStencilSurface);
7077 if(*ppZStencilSurface != NULL) {
7078 /* Note inc ref on returned surface */
7079 IWineD3DSurface_AddRef(*ppZStencilSurface);
7084 /* internal static helper functions */
7085 static HRESULT WINAPI IWineD3DDeviceImpl_ActiveRender(IWineD3DDevice* iface,
7086 IWineD3DSurface *RenderSurface);
7088 static HRESULT WINAPI IWineD3DDeviceImpl_SetRenderTarget(IWineD3DDevice *iface, DWORD RenderTargetIndex, IWineD3DSurface *pRenderTarget) {
7089 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
7090 HRESULT hr = WINED3D_OK;
7091 WINED3DVIEWPORT viewport;
7093 TRACE("(%p) Swapping rendertarget\n",This);
7094 if (RenderTargetIndex > 0) {
7095 FIXME("(%p) Render targets other than the first are not supported\n",This);
7096 RenderTargetIndex = 0;
7099 /* MSDN says that null disables the render target
7100 but a device must always be associated with a render target
7101 nope MSDN says that we return invalid call to a null rendertarget with an index of 0
7103 see http://msdn.microsoft.com/library/default.asp?url=/library/en-us/directx9_c/directx/graphics/programmingguide/AdvancedTopics/PixelPipe/MultipleRenderTarget.asp
7106 if (RenderTargetIndex == 0 && pRenderTarget == NULL) {
7107 FIXME("Trying to set render target 0 to NULL\n");
7108 return WINED3DERR_INVALIDCALL;
7110 /* TODO: replace Impl* usage with interface usage */
7111 if (!((IWineD3DSurfaceImpl *)pRenderTarget)->resource.usage & WINED3DUSAGE_RENDERTARGET) {
7112 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);
7113 return WINED3DERR_INVALIDCALL;
7115 /** TODO: check that the depth stencil format matches the render target, this is only done in debug
7116 * builds, but I think wine counts as a 'debug' build for now.
7117 ******************************/
7118 /* If we are trying to set what we already have, don't bother */
7119 if (pRenderTarget == This->renderTarget) {
7120 TRACE("Trying to do a NOP SetRenderTarget operation\n");
7122 /* Otherwise, set the render target up */
7124 if (FALSE == This->sceneEnded) {
7125 IWineD3DDevice_EndScene(iface);
7127 TRACE("clearing renderer\n");
7128 /* IWineD3DDeviceImpl_CleanRender(iface); */
7129 /* OpenGL doesn't support 'sharing' of the stencilBuffer so we may incure an extra memory overhead
7130 depending on the renter target implementation being used.
7131 A shared context implementation will share all buffers between all rendertargets (including swapchains),
7132 implementations that use separate pbuffers for different swapchains or rendertargets will have to duplicate the
7133 stencil buffer and incure an extra memory overhead */
7134 hr = IWineD3DDeviceImpl_ActiveRender(iface, pRenderTarget);
7137 if (SUCCEEDED(hr)) {
7138 /* Finally, reset the viewport as the MSDN states. */
7139 /* TODO: Replace impl usage */
7140 viewport.Height = ((IWineD3DSurfaceImpl *)This->renderTarget)->currentDesc.Height;
7141 viewport.Width = ((IWineD3DSurfaceImpl *)This->renderTarget)->currentDesc.Width;
7144 viewport.MaxZ = 1.0f;
7145 viewport.MinZ = 0.0f;
7146 IWineD3DDeviceImpl_SetViewport(iface, &viewport);
7148 FIXME("Unknown error setting the render target\n");
7150 This->sceneEnded = FALSE;
7154 static HRESULT WINAPI IWineD3DDeviceImpl_SetDepthStencilSurface(IWineD3DDevice *iface, IWineD3DSurface *pNewZStencil) {
7155 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
7156 HRESULT hr = WINED3D_OK;
7157 IWineD3DSurface *tmp;
7159 TRACE("(%p) Swapping z-buffer\n",This);
7161 if (pNewZStencil == This->stencilBufferTarget) {
7162 TRACE("Trying to do a NOP SetRenderTarget operation\n");
7164 /** OpenGL doesn't support 'sharing' of the stencilBuffer so we may incure an extra memory overhead
7165 * depending on the renter target implementation being used.
7166 * A shared context implementation will share all buffers between all rendertargets (including swapchains),
7167 * implementations that use separate pbuffers for different swapchains or rendertargets will have to duplicate the
7168 * stencil buffer and incure an extra memory overhead
7169 ******************************************************/
7172 tmp = This->stencilBufferTarget;
7173 This->stencilBufferTarget = pNewZStencil;
7174 /* should we be calling the parent or the wined3d surface? */
7175 if (NULL != This->stencilBufferTarget) IWineD3DSurface_AddRef(This->stencilBufferTarget);
7176 if (NULL != tmp) IWineD3DSurface_Release(tmp);
7178 /** TODO: glEnable/glDisable on depth/stencil depending on
7179 * pNewZStencil is NULL and the depth/stencil is enabled in d3d
7180 **********************************************************/
7187 #ifdef GL_VERSION_1_3
7188 /* Internal functions not in DirectX */
7189 /** TODO: move this off to the opengl context manager
7190 *(the swapchain doesn't need to know anything about offscreen rendering!)
7191 ****************************************************/
7193 static HRESULT WINAPI IWineD3DDeviceImpl_CleanRender(IWineD3DDevice* iface, IWineD3DSwapChainImpl *swapchain)
7195 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
7197 TRACE("(%p), %p\n", This, swapchain);
7199 if (swapchain->win != swapchain->drawable) {
7200 /* Set everything back the way it ws */
7201 swapchain->render_ctx = swapchain->glCtx;
7202 swapchain->drawable = swapchain->win;
7207 /* TODO: move this off into a context manager so that GLX_ATI_render_texture and other types of surface can be used. */
7208 static HRESULT WINAPI IWineD3DDeviceImpl_FindGLContext(IWineD3DDevice *iface, IWineD3DSurface *pSurface, glContext **context) {
7209 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
7212 unsigned int height;
7213 WINED3DFORMAT format;
7214 WINED3DSURFACE_DESC surfaceDesc;
7215 memset(&surfaceDesc, 0, sizeof(surfaceDesc));
7216 surfaceDesc.Width = &width;
7217 surfaceDesc.Height = &height;
7218 surfaceDesc.Format = &format;
7219 IWineD3DSurface_GetDesc(pSurface, &surfaceDesc);
7221 /* I need a get width/height function (and should do something with the format) */
7222 for (i = 0; i < CONTEXT_CACHE; ++i) {
7223 /** NOTE: the contextCache[i].pSurface == pSurface check ceates onepbuffer per surface
7224 ATI cards don't destroy pbuffers, but as soon as resource releasing callbacks are inplace
7225 the pSurface can be set to 0 allowing it to be reused from cache **/
7226 if (This->contextCache[i].Width == width && This->contextCache[i].Height == height
7227 && (pbuffer_per_surface == FALSE || This->contextCache[i].pSurface == pSurface || This->contextCache[i].pSurface == NULL)) {
7228 *context = &This->contextCache[i];
7231 if (This->contextCache[i].Width == 0) {
7232 This->contextCache[i].pSurface = pSurface;
7233 This->contextCache[i].Width = width;
7234 This->contextCache[i].Height = height;
7235 *context = &This->contextCache[i];
7239 if (i == CONTEXT_CACHE) {
7240 int minUsage = 0x7FFFFFFF; /* MAX_INT */
7241 glContext *dropContext = 0;
7242 for (i = 0; i < CONTEXT_CACHE; i++) {
7243 if (This->contextCache[i].usedcount < minUsage) {
7244 dropContext = &This->contextCache[i];
7245 minUsage = This->contextCache[i].usedcount;
7248 /* clean up the context (this doesn't work for ATI at the moment */
7250 glXDestroyContext(swapchain->display, dropContext->context);
7251 glXDestroyPbuffer(swapchain->display, dropContext->drawable);
7254 dropContext->Width = 0;
7255 dropContext->pSurface = pSurface;
7256 *context = dropContext;
7258 if (++This->contextCache[i].usedcount == 0x7FFFFFFF /* MAX_INT */ - 1 ) {
7259 for (i = 0; i < CONTEXT_CACHE; i++) {
7260 This->contextCache[i].usedcount = max(0, This->contextCache[i].usedcount - (0x7FFFFFFF /* MAX_INT */ >> 1));
7264 if (*context != NULL)
7267 return E_OUTOFMEMORY;
7271 /** FIXME: This is currently used called whenever SetRenderTarget or SetStencilBuffer are called
7272 * the functionality needs splitting up so that we don't do more than we should do.
7273 * this only seems to impact performance a little.
7274 ******************************/
7275 static HRESULT WINAPI IWineD3DDeviceImpl_ActiveRender(IWineD3DDevice* iface,
7276 IWineD3DSurface *RenderSurface) {
7277 HRESULT ret = WINED3DERR_INVALIDCALL;
7280 * Currently only active for GLX >= 1.3
7281 * for others versions we'll have to use GLXPixmaps
7283 * normally we must test GLX_VERSION_1_3 but nvidia headers are not correct
7284 * as they implement GLX 1.3 but only define GLX_VERSION_1_2
7285 * so only check OpenGL version
7286 * ..........................
7287 * I don't believe that it is a problem with NVidia headers,
7288 * XFree only supports GLX1.2, nVidia (and ATI to some extent) provide 1.3 functions
7289 * in GLX 1.2, there is no mention of the correct way to tell if the extensions are provided.
7291 * Your application will report GLX version 1.2 on glXQueryVersion.
7292 * However, it is safe to call the GLX 1.3 functions as described below.
7294 #if defined(GL_VERSION_1_3)
7296 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
7297 IWineD3DSurface *StencilSurface = This->stencilBufferTarget;
7298 IWineD3DSurface *tmp;
7299 /** TODO: we only need to look up the configuration !IF! we are setting the target to a texture **/
7300 GLXFBConfig* cfgs = NULL;
7304 IWineD3DSwapChain *currentSwapchain;
7305 IWineD3DSwapChainImpl *swapchain;
7306 /** TODO: get rid of Impl usage we should always create a zbuffer/stencil with our contexts if possible,
7307 * but switch them off if the StencilSurface is set to NULL
7308 ** *********************************************************/
7309 D3DFORMAT BackBufferFormat = ((IWineD3DSurfaceImpl *) RenderSurface)->resource.format;
7310 D3DFORMAT StencilBufferFormat = (NULL != StencilSurface) ? ((IWineD3DSurfaceImpl *) StencilSurface)->resource.format : 0;
7313 if StencilSurface == NULL && zBufferTarget != NULL then switch the zbuffer off,
7314 it StencilSurface != NULL && zBufferTarget == NULL switch it on
7317 #define PUSH1(att) attribs[nAttribs++] = (att);
7318 #define PUSH2(att,value) attribs[nAttribs++] = (att); attribs[nAttribs++] = (value);
7320 /* PUSH2(GLX_BIND_TO_TEXTURE_RGBA_ATI, True); examples of this are few and far between (but I've got a nice working one!)*/
7322 /** TODO: remove the reff to Impl (context manager should fix this!) **/
7323 IWineD3DSwapChainImpl *impSwapChain;
7324 IWineD3DDevice_GetSwapChain(iface, 0, (IWineD3DSwapChain **)&impSwapChain);
7325 if (NULL == impSwapChain) { /* NOTE: This should NEVER fail */
7326 ERR("(%p) Failed to get a the implicit swapchain\n", iface);
7331 PUSH2(GLX_DRAWABLE_TYPE, GLX_PBUFFER_BIT);
7332 PUSH2(GLX_X_RENDERABLE, TRUE);
7333 PUSH2(GLX_DOUBLEBUFFER, TRUE);
7334 TRACE("calling makeglcfg\n");
7335 D3DFmtMakeGlCfg(BackBufferFormat, StencilBufferFormat, attribs, &nAttribs, FALSE /* alternate */);
7338 TRACE("calling chooseFGConfig\n");
7339 cfgs = glXChooseFBConfig(impSwapChain->display, DefaultScreen(impSwapChain->display),
7342 if (!cfgs) { /* OK we didn't find the exact config, so use any reasonable match */
7343 /* TODO: fill in the 'requested' and 'current' depths, also make sure that's
7344 why we failed and only show this message once! */
7345 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"); /**/
7347 PUSH2(GLX_DRAWABLE_TYPE, GLX_PBUFFER_BIT | GLX_WINDOW_BIT);
7348 /* PUSH2(GLX_X_RENDERABLE, TRUE); */
7349 PUSH2(GLX_RENDER_TYPE, GLX_RGBA_BIT);
7350 PUSH2(GLX_DOUBLEBUFFER, FALSE);
7351 TRACE("calling makeglcfg\n");
7352 D3DFmtMakeGlCfg(BackBufferFormat, StencilBufferFormat, attribs, &nAttribs, TRUE /* alternate */);
7354 cfgs = glXChooseFBConfig(impSwapChain->display, DefaultScreen(impSwapChain->display),
7361 for (i = 0; i < nCfgs; ++i) {
7362 TRACE("for (%u,%s)/(%u,%s) found config[%d]@%p\n", BackBufferFormat,
7363 debug_d3dformat(BackBufferFormat), StencilBufferFormat,
7364 debug_d3dformat(StencilBufferFormat), i, cfgs[i]);
7367 if (NULL != This->renderTarget) {
7369 vcheckGLcall("glFlush");
7370 /** This is only useful if the old render target was a swapchain,
7371 * we need to supercede this with a function that displays
7372 * the current buffer on the screen. This is easy to do in glx1.3 but
7373 * we need to do copy-write pixels in glx 1.2.
7374 ************************************************/
7375 glXSwapBuffers(impSwapChain->display, impSwapChain->drawable);
7377 printf("Hit Enter to get next frame ...\n");
7383 if (IWineD3DSurface_GetContainer(This->renderTarget, &IID_IWineD3DSwapChain, (void **)¤tSwapchain) != WINED3D_OK) {
7384 /* the selected render target doesn't belong to a swapchain, so use the devices implicit swapchain */
7385 IWineD3DDevice_GetSwapChain(iface, 0, ¤tSwapchain);
7389 * TODO: remove the use of IWineD3DSwapChainImpl, a context manager will help since it will replace the
7390 * renderTarget = swapchain->backBuffer[i] bit and anything to do with *glContexts
7391 **********************************************************************/
7392 if (IWineD3DSurface_GetContainer(RenderSurface, &IID_IWineD3DSwapChain, (void **)&swapchain) == WINED3D_OK) {
7393 /* We also need to make sure that the lights &co are also in the context of the swapchains */
7394 /* FIXME: If the render target gets sent to the frontBuffer should be be presenting it raw? */
7395 TRACE("making swapchain active\n");
7396 if (RenderSurface != This->renderTarget) {
7397 BOOL backbuf = FALSE;
7400 for(i = 0; i < swapchain->presentParms.BackBufferCount; i++) {
7401 if(RenderSurface == swapchain->backBuffer[i]) {
7409 /* This could be flagged so that some operations work directly with the front buffer */
7410 FIXME("Attempting to set the renderTarget to the frontBuffer\n");
7412 if (glXMakeCurrent(swapchain->display, swapchain->win, swapchain->glCtx)
7414 TRACE("Error in setting current context: context %p drawable %ld !\n",
7415 impSwapChain->glCtx, impSwapChain->win);
7418 IWineD3DDeviceImpl_CleanRender(iface, (IWineD3DSwapChainImpl *)currentSwapchain);
7420 checkGLcall("glXMakeContextCurrent");
7422 IWineD3DSwapChain_Release((IWineD3DSwapChain *)swapchain);
7424 else if (pbuffer_support && cfgs != NULL /* && some test to make sure that opengl supports pbuffers */) {
7426 /** ********************************************************************
7427 * This is a quickly hacked out implementation of offscreen textures.
7428 * It will work in most cases but there may be problems if the client
7429 * modifies the texture directly, or expects the contents of the rendertarget
7432 * There are some real speed vs compatibility issues here:
7433 * we should really use a new context for every texture, but that eats ram.
7434 * we should also be restoring the texture to the pbuffer but that eats CPU
7435 * we can also 'reuse' the current pbuffer if the size is larger than the requested buffer,
7436 * but if this means reusing the display backbuffer then we need to make sure that
7437 * states are correctly preserved.
7438 * In many cases I would expect that we can 'skip' some functions, such as preserving states,
7439 * and gain a good performance increase at the cost of compatibility.
7440 * I would suggest that, when this is the case, a user configurable flag be made
7441 * available, allowing the user to choose the best emulated experience for them.
7442 *********************************************************************/
7444 XVisualInfo *visinfo;
7445 glContext *newContext;
7447 /* Here were using a shared context model */
7448 if (WINED3D_OK != IWineD3DDeviceImpl_FindGLContext(iface, RenderSurface, &newContext)) {
7449 FIXME("(%p) : Failed to find a context for surface %p\n", iface, RenderSurface);
7452 /* If the context doesn't exist then create a new one */
7453 /* TODO: This should really be part of findGlContext */
7454 if (NULL == newContext->context) {
7456 TRACE("making new buffer\n");
7458 PUSH2(GLX_PBUFFER_WIDTH, newContext->Width);
7459 PUSH2(GLX_PBUFFER_HEIGHT, newContext->Height);
7462 newContext->drawable = glXCreatePbuffer(impSwapChain->display, cfgs[0], attribs);
7464 /** ****************************************
7465 *GLX1.3 isn't supported by XFree 'yet' until that point ATI emulates pBuffers
7467 * In future releases, we may provide the calls glXCreateNewContext,
7468 * glXQueryDrawable and glXMakeContextCurrent.
7469 * so until then we have to use glXGetVisualFromFBConfig &co..
7470 ********************************************/
7473 visinfo = glXGetVisualFromFBConfig(impSwapChain->display, cfgs[0]);
7475 ERR("Error: couldn't get an RGBA, double-buffered visual\n");
7477 newContext->context = glXCreateContext(impSwapChain->display, visinfo, impSwapChain->glCtx, GL_TRUE);
7481 if (NULL == newContext || NULL == newContext->context) {
7482 ERR("(%p) : Failed to find a context for surface %p\n", iface, RenderSurface);
7484 /* Debug logging, (this function leaks), change to a TRACE when the leak is plugged */
7485 if (glXMakeCurrent(impSwapChain->display, newContext->drawable, newContext->context) == False) {
7486 TRACE("Error in setting current context: context %p drawable %ld\n", newContext->context, newContext->drawable);
7489 /* Clean up the old context */
7490 IWineD3DDeviceImpl_CleanRender(iface, (IWineD3DSwapChainImpl *)currentSwapchain);
7491 /* Set the current context of the swapchain to the new context */
7492 impSwapChain->drawable = newContext->drawable;
7493 impSwapChain->render_ctx = newContext->context;
7497 #if 1 /* Apply the stateblock to the new context
7498 FIXME: This is a bit of a hack, each context should know it's own state,
7499 the directX current directX state should then be applied to the context */
7502 IWineD3DStateBlockImpl *oldUpdateStateBlock;
7503 oldUpdateStateBlock = This->updateStateBlock;
7504 oldRecording= This->isRecordingState;
7505 This->isRecordingState = FALSE;
7506 This->updateStateBlock = This->stateBlock;
7507 IWineD3DStateBlock_Apply((IWineD3DStateBlock *)This->stateBlock);
7509 This->isRecordingState = oldRecording;
7510 This->updateStateBlock = oldUpdateStateBlock;
7515 /* clean up the current rendertargets swapchain (if it belonged to one) */
7516 if (currentSwapchain != NULL) {
7517 IWineD3DSwapChain_Release((IWineD3DSwapChain *)currentSwapchain);
7520 /* Were done with the opengl context management, setup the rendertargets */
7522 tmp = This->renderTarget;
7523 This->renderTarget = RenderSurface;
7524 IWineD3DSurface_AddRef(This->renderTarget);
7525 IWineD3DSurface_Release(tmp);
7531 /* The surface must be rendered upside down to cancel the flip produce by glCopyTexImage */
7532 /* Check that the container is not a swapchain member */
7534 IWineD3DSwapChain *tmpSwapChain;
7535 if (WINED3D_OK != IWineD3DSurface_GetContainer(This->renderTarget, &IID_IWineD3DSwapChain, (void **)&tmpSwapChain)) {
7536 This->renderUpsideDown = TRUE;
7538 This->renderUpsideDown = FALSE;
7539 IWineD3DSwapChain_Release(tmpSwapChain);
7541 /* Force updating the cull mode */
7542 TRACE("setting render state\n");
7543 IWineD3DDevice_GetRenderState(iface, WINED3DRS_CULLMODE, &value);
7544 IWineD3DDevice_SetRenderState(iface, WINED3DRS_CULLMODE, value);
7546 /* Force updating projection matrix */
7547 This->last_was_rhw = FALSE;
7548 This->proj_valid = FALSE;
7556 ERR("cannot get valides GLXFBConfig for (%u,%s)/(%u,%s)\n", BackBufferFormat,
7557 debug_d3dformat(BackBufferFormat), StencilBufferFormat, debug_d3dformat(StencilBufferFormat));
7562 if ( NULL != impSwapChain) {
7563 IWineD3DSwapChain_Release((IWineD3DSwapChain *)impSwapChain);
7571 static HRESULT WINAPI IWineD3DDeviceImpl_SetCursorProperties(IWineD3DDevice* iface, UINT XHotSpot,
7572 UINT YHotSpot, IWineD3DSurface *pCursorBitmap) {
7573 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *) iface;
7574 /* TODO: the use of Impl is deprecated. */
7575 /* some basic validation checks */
7576 IWineD3DSurfaceImpl * pSur = (IWineD3DSurfaceImpl *) pCursorBitmap;
7578 TRACE("(%p) : Spot Pos(%u,%u)\n", This, XHotSpot, YHotSpot);
7580 if (WINED3DFMT_A8R8G8B8 != pSur->resource.format) {
7581 ERR("(%p) : surface(%p) has an invalid format\n", This, pCursorBitmap);
7582 return WINED3DERR_INVALIDCALL;
7584 if (32 != pSur->currentDesc.Height || 32 != pSur->currentDesc.Width) {
7585 ERR("(%p) : surface(%p) has an invalid size\n", This, pCursorBitmap);
7586 return WINED3DERR_INVALIDCALL;
7588 /* TODO: make the cursor 'real' */
7590 This->xHotSpot = XHotSpot;
7591 This->yHotSpot = YHotSpot;
7596 static void WINAPI IWineD3DDeviceImpl_SetCursorPosition(IWineD3DDevice* iface, int XScreenSpace, int YScreenSpace, DWORD Flags) {
7597 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *) iface;
7598 TRACE("(%p) : SetPos to (%u,%u)\n", This, XScreenSpace, YScreenSpace);
7600 This->xScreenSpace = XScreenSpace;
7601 This->yScreenSpace = YScreenSpace;
7607 static BOOL WINAPI IWineD3DDeviceImpl_ShowCursor(IWineD3DDevice* iface, BOOL bShow) {
7608 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *) iface;
7609 TRACE("(%p) : visible(%d)\n", This, bShow);
7611 This->bCursorVisible = bShow;
7616 static HRESULT WINAPI IWineD3DDeviceImpl_TestCooperativeLevel(IWineD3DDevice* iface) {
7617 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *) iface;
7618 TRACE("(%p) : state (%lu)\n", This, This->state);
7619 /* TODO: Implement wrapping of the WndProc so that mimimize and maxamise can be monitored and the states adjusted. */
7620 switch (This->state) {
7623 case WINED3DERR_DEVICELOST:
7625 ResourceList *resourceList = This->resources;
7626 while (NULL != resourceList) {
7627 if (((IWineD3DResourceImpl *)resourceList->resource)->resource.pool == WINED3DPOOL_DEFAULT /* TODO: IWineD3DResource_GetPool(resourceList->resource)*/)
7628 return WINED3DERR_DEVICENOTRESET;
7629 resourceList = resourceList->next;
7631 return WINED3DERR_DEVICELOST;
7633 case WINED3DERR_DRIVERINTERNALERROR:
7634 return WINED3DERR_DRIVERINTERNALERROR;
7638 return WINED3DERR_DRIVERINTERNALERROR;
7642 static HRESULT WINAPI IWineD3DDeviceImpl_EvictManagedResources(IWineD3DDevice* iface) {
7643 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *) iface;
7644 /** FIXME: Resource tracking needs to be done,
7645 * The closes we can do to this is set the priorities of all managed textures low
7646 * and then reset them.
7647 ***********************************************************/
7648 FIXME("(%p) : stub\n", This);
7652 static HRESULT WINAPI IWineD3DDeviceImpl_Reset(IWineD3DDevice* iface, WINED3DPRESENT_PARAMETERS* pPresentationParameters) {
7653 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *) iface;
7654 /** FIXME: Resource trascking needs to be done.
7655 * in effect this pulls all non only default
7656 * textures out of video memory and deletes all glTextures (glDeleteTextures)
7657 * and should clear down the context and set it up according to pPresentationParameters
7658 ***********************************************************/
7659 FIXME("(%p) : stub\n", This);
7663 static HRESULT WINAPI IWineD3DDeviceImpl_SetDialogBoxMode(IWineD3DDevice *iface, BOOL bEnableDialogs) {
7664 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
7665 /** FIXME: always true at the moment **/
7666 if(bEnableDialogs == FALSE) {
7667 FIXME("(%p) Dialogs cannot be disabled yet\n", This);
7673 static HRESULT WINAPI IWineD3DDeviceImpl_GetCreationParameters(IWineD3DDevice *iface, WINED3DDEVICE_CREATION_PARAMETERS *pParameters) {
7674 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *) iface;
7675 TRACE("(%p) : pParameters %p\n", This, pParameters);
7677 *pParameters = This->createParms;
7681 static void WINAPI IWineD3DDeviceImpl_SetGammaRamp(IWineD3DDevice * iface, UINT iSwapChain, DWORD Flags, CONST WINED3DGAMMARAMP* pRamp) {
7682 IWineD3DSwapChain *swapchain;
7683 HRESULT hrc = WINED3D_OK;
7685 TRACE("Relaying to swapchain\n");
7687 if ((hrc = IWineD3DDeviceImpl_GetSwapChain(iface, iSwapChain, &swapchain)) == WINED3D_OK) {
7688 IWineD3DSwapChain_SetGammaRamp(swapchain, Flags, (WINED3DGAMMARAMP *)pRamp);
7689 IWineD3DSwapChain_Release(swapchain);
7694 static void WINAPI IWineD3DDeviceImpl_GetGammaRamp(IWineD3DDevice *iface, UINT iSwapChain, 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 hrc =IWineD3DSwapChain_GetGammaRamp(swapchain, pRamp);
7702 IWineD3DSwapChain_Release(swapchain);
7708 /** ********************************************************
7709 * Notification functions
7710 ** ********************************************************/
7711 /** This function must be called in the release of a resource when ref == 0,
7712 * the contents of resource must still be correct,
7713 * any handels to other resource held by the caller must be closed
7714 * (e.g. a texture should release all held surfaces because telling the device that it's been released.)
7715 *****************************************************/
7716 static void WINAPI IWineD3DDeviceImpl_AddResource(IWineD3DDevice *iface, IWineD3DResource *resource){
7717 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
7718 ResourceList* resourceList;
7720 TRACE("(%p) : resource %p\n", This, resource);
7722 EnterCriticalSection(&resourceStoreCriticalSection);
7724 /* add a new texture to the frot of the linked list */
7725 resourceList = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(ResourceList));
7726 resourceList->resource = resource;
7728 /* Get the old head */
7729 resourceList->next = This->resources;
7731 This->resources = resourceList;
7732 TRACE("Added resource %p with element %p pointing to %p\n", resource, resourceList, resourceList->next);
7735 LeaveCriticalSection(&resourceStoreCriticalSection);
7740 static void WINAPI IWineD3DDeviceImpl_RemoveResource(IWineD3DDevice *iface, IWineD3DResource *resource){
7741 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
7742 ResourceList* resourceList = NULL;
7743 ResourceList* previousResourceList = NULL;
7745 TRACE("(%p) : resource %p\n", This, resource);
7748 EnterCriticalSection(&resourceStoreCriticalSection);
7750 resourceList = This->resources;
7752 while (resourceList != NULL) {
7753 if(resourceList->resource == resource) break;
7754 previousResourceList = resourceList;
7755 resourceList = resourceList->next;
7758 if (resourceList == NULL) {
7759 FIXME("Attempted to remove resource %p that hasn't been stored\n", resource);
7761 LeaveCriticalSection(&resourceStoreCriticalSection);
7765 TRACE("Found resource %p with element %p pointing to %p (previous %p)\n", resourceList->resource, resourceList, resourceList->next, previousResourceList);
7767 /* make sure we don't leave a hole in the list */
7768 if (previousResourceList != NULL) {
7769 previousResourceList->next = resourceList->next;
7771 This->resources = resourceList->next;
7775 LeaveCriticalSection(&resourceStoreCriticalSection);
7781 static void WINAPI IWineD3DDeviceImpl_ResourceReleased(IWineD3DDevice *iface, IWineD3DResource *resource){
7782 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *) iface;
7785 TRACE("(%p) : resource %p\n", This, resource);
7786 switch(IWineD3DResource_GetType(resource)){
7787 case WINED3DRTYPE_SURFACE:
7788 /* TODO: check front and back buffers, rendertargets etc.. possibly swapchains? */
7790 case WINED3DRTYPE_TEXTURE:
7791 case WINED3DRTYPE_CUBETEXTURE:
7792 case WINED3DRTYPE_VOLUMETEXTURE:
7793 for (counter = 0; counter < GL_LIMITS(sampler_stages); counter++) {
7794 if (This->stateBlock != NULL && This->stateBlock->textures[counter] == (IWineD3DBaseTexture *)resource) {
7795 WARN("Texture being released is still by a stateblock, Stage = %u Texture = %p\n", counter, resource);
7796 This->stateBlock->textures[counter] = NULL;
7798 if (This->updateStateBlock != This->stateBlock ){
7799 if (This->updateStateBlock->textures[counter] == (IWineD3DBaseTexture *)resource) {
7800 WARN("Texture being released is still by a stateblock, Stage = %u Texture = %p\n", counter, resource);
7801 This->updateStateBlock->textures[counter] = NULL;
7806 case WINED3DRTYPE_VOLUME:
7807 /* TODO: nothing really? */
7809 case WINED3DRTYPE_VERTEXBUFFER:
7810 /* MSDN: When an application no longer holds a references to this interface, the interface will automatically be freed. */
7813 TRACE("Cleaning up stream pointers\n");
7815 for(streamNumber = 0; streamNumber < MAX_STREAMS; streamNumber ++){
7816 /* FINDOUT: should a warn be generated if were recording and updateStateBlock->streamSource is lost?
7817 FINDOUT: should changes.streamSource[StreamNumber] be set ?
7819 if (This->updateStateBlock != NULL ) { /* ==NULL when device is being destroyed */
7820 if ((IWineD3DResource *)This->updateStateBlock->streamSource[streamNumber] == resource) {
7821 FIXME("Vertex buffer released whlst bound to a state block stream %d\n", streamNumber);
7822 This->updateStateBlock->streamSource[streamNumber] = 0;
7823 /* Set changed flag? */
7826 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) */
7827 if ((IWineD3DResource *)This->stateBlock->streamSource[streamNumber] == resource) {
7828 TRACE("Vertex buffer released whlst bound to a state block stream %d\n", streamNumber);
7829 This->stateBlock->streamSource[streamNumber] = 0;
7832 #if 0 /* TODO: Manage internal tracking properly so that 'this shouldn't happen' */
7833 else { /* This shouldn't happen */
7834 FIXME("Calling application has released the device before relasing all the resources bound to the device\n");
7841 case WINED3DRTYPE_INDEXBUFFER:
7842 /* MSDN: When an application no longer holds a references to this interface, the interface will automatically be freed.*/
7843 if (This->updateStateBlock != NULL ) { /* ==NULL when device is being destroyed */
7844 if (This->updateStateBlock->pIndexData == (IWineD3DIndexBuffer *)resource) {
7845 This->updateStateBlock->pIndexData = NULL;
7848 if (This->stateBlock != NULL ) { /* ==NULL when device is being destroyed */
7849 if (This->stateBlock->pIndexData == (IWineD3DIndexBuffer *)resource) {
7850 This->stateBlock->pIndexData = NULL;
7856 FIXME("(%p) unknown resource type %p %u\n", This, resource, IWineD3DResource_GetType(resource));
7861 /* Remove the resoruce from the resourceStore */
7862 IWineD3DDeviceImpl_RemoveResource(iface, resource);
7864 TRACE("Resource released\n");
7868 /**********************************************************
7869 * IWineD3DDevice VTbl follows
7870 **********************************************************/
7872 const IWineD3DDeviceVtbl IWineD3DDevice_Vtbl =
7874 /*** IUnknown methods ***/
7875 IWineD3DDeviceImpl_QueryInterface,
7876 IWineD3DDeviceImpl_AddRef,
7877 IWineD3DDeviceImpl_Release,
7878 /*** IWineD3DDevice methods ***/
7879 IWineD3DDeviceImpl_GetParent,
7880 /*** Creation methods**/
7881 IWineD3DDeviceImpl_CreateVertexBuffer,
7882 IWineD3DDeviceImpl_CreateIndexBuffer,
7883 IWineD3DDeviceImpl_CreateStateBlock,
7884 IWineD3DDeviceImpl_CreateSurface,
7885 IWineD3DDeviceImpl_CreateTexture,
7886 IWineD3DDeviceImpl_CreateVolumeTexture,
7887 IWineD3DDeviceImpl_CreateVolume,
7888 IWineD3DDeviceImpl_CreateCubeTexture,
7889 IWineD3DDeviceImpl_CreateQuery,
7890 IWineD3DDeviceImpl_CreateAdditionalSwapChain,
7891 IWineD3DDeviceImpl_CreateVertexDeclaration,
7892 IWineD3DDeviceImpl_CreateVertexShader,
7893 IWineD3DDeviceImpl_CreatePixelShader,
7894 IWineD3DDeviceImpl_CreatePalette,
7895 /*** Odd functions **/
7896 IWineD3DDeviceImpl_Init3D,
7897 IWineD3DDeviceImpl_Uninit3D,
7898 IWineD3DDeviceImpl_EnumDisplayModes,
7899 IWineD3DDeviceImpl_EvictManagedResources,
7900 IWineD3DDeviceImpl_GetAvailableTextureMem,
7901 IWineD3DDeviceImpl_GetBackBuffer,
7902 IWineD3DDeviceImpl_GetCreationParameters,
7903 IWineD3DDeviceImpl_GetDeviceCaps,
7904 IWineD3DDeviceImpl_GetDirect3D,
7905 IWineD3DDeviceImpl_GetDisplayMode,
7906 IWineD3DDeviceImpl_SetDisplayMode,
7907 IWineD3DDeviceImpl_GetHWND,
7908 IWineD3DDeviceImpl_SetHWND,
7909 IWineD3DDeviceImpl_GetNumberOfSwapChains,
7910 IWineD3DDeviceImpl_GetRasterStatus,
7911 IWineD3DDeviceImpl_GetSwapChain,
7912 IWineD3DDeviceImpl_Reset,
7913 IWineD3DDeviceImpl_SetDialogBoxMode,
7914 IWineD3DDeviceImpl_SetCursorProperties,
7915 IWineD3DDeviceImpl_SetCursorPosition,
7916 IWineD3DDeviceImpl_ShowCursor,
7917 IWineD3DDeviceImpl_TestCooperativeLevel,
7918 IWineD3DDeviceImpl_EnumZBufferFormats,
7919 IWineD3DDeviceImpl_EnumTextureFormats,
7920 /*** Getters and setters **/
7921 IWineD3DDeviceImpl_SetClipPlane,
7922 IWineD3DDeviceImpl_GetClipPlane,
7923 IWineD3DDeviceImpl_SetClipStatus,
7924 IWineD3DDeviceImpl_GetClipStatus,
7925 IWineD3DDeviceImpl_SetCurrentTexturePalette,
7926 IWineD3DDeviceImpl_GetCurrentTexturePalette,
7927 IWineD3DDeviceImpl_SetDepthStencilSurface,
7928 IWineD3DDeviceImpl_GetDepthStencilSurface,
7929 IWineD3DDeviceImpl_SetFVF,
7930 IWineD3DDeviceImpl_GetFVF,
7931 IWineD3DDeviceImpl_SetGammaRamp,
7932 IWineD3DDeviceImpl_GetGammaRamp,
7933 IWineD3DDeviceImpl_SetIndices,
7934 IWineD3DDeviceImpl_GetIndices,
7935 IWineD3DDeviceImpl_SetLight,
7936 IWineD3DDeviceImpl_GetLight,
7937 IWineD3DDeviceImpl_SetLightEnable,
7938 IWineD3DDeviceImpl_GetLightEnable,
7939 IWineD3DDeviceImpl_SetMaterial,
7940 IWineD3DDeviceImpl_GetMaterial,
7941 IWineD3DDeviceImpl_SetNPatchMode,
7942 IWineD3DDeviceImpl_GetNPatchMode,
7943 IWineD3DDeviceImpl_SetPaletteEntries,
7944 IWineD3DDeviceImpl_GetPaletteEntries,
7945 IWineD3DDeviceImpl_SetPixelShader,
7946 IWineD3DDeviceImpl_GetPixelShader,
7947 IWineD3DDeviceImpl_SetPixelShaderConstantB,
7948 IWineD3DDeviceImpl_GetPixelShaderConstantB,
7949 IWineD3DDeviceImpl_SetPixelShaderConstantI,
7950 IWineD3DDeviceImpl_GetPixelShaderConstantI,
7951 IWineD3DDeviceImpl_SetPixelShaderConstantF,
7952 IWineD3DDeviceImpl_GetPixelShaderConstantF,
7953 IWineD3DDeviceImpl_SetRenderState,
7954 IWineD3DDeviceImpl_GetRenderState,
7955 IWineD3DDeviceImpl_SetRenderTarget,
7956 IWineD3DDeviceImpl_GetRenderTarget,
7957 IWineD3DDeviceImpl_SetFrontBackBuffers,
7958 IWineD3DDeviceImpl_SetSamplerState,
7959 IWineD3DDeviceImpl_GetSamplerState,
7960 IWineD3DDeviceImpl_SetScissorRect,
7961 IWineD3DDeviceImpl_GetScissorRect,
7962 IWineD3DDeviceImpl_SetSoftwareVertexProcessing,
7963 IWineD3DDeviceImpl_GetSoftwareVertexProcessing,
7964 IWineD3DDeviceImpl_SetStreamSource,
7965 IWineD3DDeviceImpl_GetStreamSource,
7966 IWineD3DDeviceImpl_SetStreamSourceFreq,
7967 IWineD3DDeviceImpl_GetStreamSourceFreq,
7968 IWineD3DDeviceImpl_SetTexture,
7969 IWineD3DDeviceImpl_GetTexture,
7970 IWineD3DDeviceImpl_SetTextureStageState,
7971 IWineD3DDeviceImpl_GetTextureStageState,
7972 IWineD3DDeviceImpl_SetTransform,
7973 IWineD3DDeviceImpl_GetTransform,
7974 IWineD3DDeviceImpl_SetVertexDeclaration,
7975 IWineD3DDeviceImpl_GetVertexDeclaration,
7976 IWineD3DDeviceImpl_SetVertexShader,
7977 IWineD3DDeviceImpl_GetVertexShader,
7978 IWineD3DDeviceImpl_SetVertexShaderConstantB,
7979 IWineD3DDeviceImpl_GetVertexShaderConstantB,
7980 IWineD3DDeviceImpl_SetVertexShaderConstantI,
7981 IWineD3DDeviceImpl_GetVertexShaderConstantI,
7982 IWineD3DDeviceImpl_SetVertexShaderConstantF,
7983 IWineD3DDeviceImpl_GetVertexShaderConstantF,
7984 IWineD3DDeviceImpl_SetViewport,
7985 IWineD3DDeviceImpl_GetViewport,
7986 IWineD3DDeviceImpl_MultiplyTransform,
7987 IWineD3DDeviceImpl_ValidateDevice,
7988 IWineD3DDeviceImpl_ProcessVertices,
7989 /*** State block ***/
7990 IWineD3DDeviceImpl_BeginStateBlock,
7991 IWineD3DDeviceImpl_EndStateBlock,
7992 /*** Scene management ***/
7993 IWineD3DDeviceImpl_BeginScene,
7994 IWineD3DDeviceImpl_EndScene,
7995 IWineD3DDeviceImpl_Present,
7996 IWineD3DDeviceImpl_Clear,
7998 IWineD3DDeviceImpl_DrawPrimitive,
7999 IWineD3DDeviceImpl_DrawIndexedPrimitive,
8000 IWineD3DDeviceImpl_DrawPrimitiveUP,
8001 IWineD3DDeviceImpl_DrawIndexedPrimitiveUP,
8002 IWineD3DDeviceImpl_DrawPrimitiveStrided,
8003 IWineD3DDeviceImpl_DrawRectPatch,
8004 IWineD3DDeviceImpl_DrawTriPatch,
8005 IWineD3DDeviceImpl_DeletePatch,
8006 IWineD3DDeviceImpl_ColorFill,
8007 IWineD3DDeviceImpl_UpdateTexture,
8008 IWineD3DDeviceImpl_UpdateSurface,
8009 IWineD3DDeviceImpl_CopyRects,
8010 IWineD3DDeviceImpl_StretchRect,
8011 IWineD3DDeviceImpl_GetRenderTargetData,
8012 IWineD3DDeviceImpl_GetFrontBufferData,
8013 /*** Internal use IWineD3DDevice methods ***/
8014 IWineD3DDeviceImpl_SetupTextureStates,
8015 /*** object tracking ***/
8016 IWineD3DDeviceImpl_ResourceReleased
8020 const DWORD SavedPixelStates_R[NUM_SAVEDPIXELSTATES_R] = {
8021 WINED3DRS_ALPHABLENDENABLE ,
8022 WINED3DRS_ALPHAFUNC ,
8023 WINED3DRS_ALPHAREF ,
8024 WINED3DRS_ALPHATESTENABLE ,
8026 WINED3DRS_COLORWRITEENABLE ,
8027 WINED3DRS_DESTBLEND ,
8028 WINED3DRS_DITHERENABLE ,
8029 WINED3DRS_FILLMODE ,
8030 WINED3DRS_FOGDENSITY ,
8032 WINED3DRS_FOGSTART ,
8033 WINED3DRS_LASTPIXEL ,
8034 WINED3DRS_SHADEMODE ,
8035 WINED3DRS_SRCBLEND ,
8036 WINED3DRS_STENCILENABLE ,
8037 WINED3DRS_STENCILFAIL ,
8038 WINED3DRS_STENCILFUNC ,
8039 WINED3DRS_STENCILMASK ,
8040 WINED3DRS_STENCILPASS ,
8041 WINED3DRS_STENCILREF ,
8042 WINED3DRS_STENCILWRITEMASK ,
8043 WINED3DRS_STENCILZFAIL ,
8044 WINED3DRS_TEXTUREFACTOR ,
8055 WINED3DRS_ZWRITEENABLE
8058 const DWORD SavedPixelStates_T[NUM_SAVEDPIXELSTATES_T] = {
8059 WINED3DTSS_ADDRESSW ,
8060 WINED3DTSS_ALPHAARG0 ,
8061 WINED3DTSS_ALPHAARG1 ,
8062 WINED3DTSS_ALPHAARG2 ,
8063 WINED3DTSS_ALPHAOP ,
8064 WINED3DTSS_BUMPENVLOFFSET ,
8065 WINED3DTSS_BUMPENVLSCALE ,
8066 WINED3DTSS_BUMPENVMAT00 ,
8067 WINED3DTSS_BUMPENVMAT01 ,
8068 WINED3DTSS_BUMPENVMAT10 ,
8069 WINED3DTSS_BUMPENVMAT11 ,
8070 WINED3DTSS_COLORARG0 ,
8071 WINED3DTSS_COLORARG1 ,
8072 WINED3DTSS_COLORARG2 ,
8073 WINED3DTSS_COLOROP ,
8074 WINED3DTSS_RESULTARG ,
8075 WINED3DTSS_TEXCOORDINDEX ,
8076 WINED3DTSS_TEXTURETRANSFORMFLAGS
8079 const DWORD SavedPixelStates_S[NUM_SAVEDPIXELSTATES_S] = {
8080 WINED3DSAMP_ADDRESSU ,
8081 WINED3DSAMP_ADDRESSV ,
8082 WINED3DSAMP_ADDRESSW ,
8083 WINED3DSAMP_BORDERCOLOR ,
8084 WINED3DSAMP_MAGFILTER ,
8085 WINED3DSAMP_MINFILTER ,
8086 WINED3DSAMP_MIPFILTER ,
8087 WINED3DSAMP_MIPMAPLODBIAS ,
8088 WINED3DSAMP_MAXMIPLEVEL ,
8089 WINED3DSAMP_MAXANISOTROPY ,
8090 WINED3DSAMP_SRGBTEXTURE ,
8091 WINED3DSAMP_ELEMENTINDEX
8094 const DWORD SavedVertexStates_R[NUM_SAVEDVERTEXSTATES_R] = {
8096 WINED3DRS_AMBIENTMATERIALSOURCE ,
8097 WINED3DRS_CLIPPING ,
8098 WINED3DRS_CLIPPLANEENABLE ,
8099 WINED3DRS_COLORVERTEX ,
8100 WINED3DRS_DIFFUSEMATERIALSOURCE ,
8101 WINED3DRS_EMISSIVEMATERIALSOURCE ,
8102 WINED3DRS_FOGDENSITY ,
8104 WINED3DRS_FOGSTART ,
8105 WINED3DRS_FOGTABLEMODE ,
8106 WINED3DRS_FOGVERTEXMODE ,
8107 WINED3DRS_INDEXEDVERTEXBLENDENABLE ,
8108 WINED3DRS_LIGHTING ,
8109 WINED3DRS_LOCALVIEWER ,
8110 WINED3DRS_MULTISAMPLEANTIALIAS ,
8111 WINED3DRS_MULTISAMPLEMASK ,
8112 WINED3DRS_NORMALIZENORMALS ,
8113 WINED3DRS_PATCHEDGESTYLE ,
8114 WINED3DRS_POINTSCALE_A ,
8115 WINED3DRS_POINTSCALE_B ,
8116 WINED3DRS_POINTSCALE_C ,
8117 WINED3DRS_POINTSCALEENABLE ,
8118 WINED3DRS_POINTSIZE ,
8119 WINED3DRS_POINTSIZE_MAX ,
8120 WINED3DRS_POINTSIZE_MIN ,
8121 WINED3DRS_POINTSPRITEENABLE ,
8122 WINED3DRS_RANGEFOGENABLE ,
8123 WINED3DRS_SPECULARMATERIALSOURCE ,
8124 WINED3DRS_TWEENFACTOR ,
8125 WINED3DRS_VERTEXBLEND
8128 const DWORD SavedVertexStates_T[NUM_SAVEDVERTEXSTATES_T] = {
8129 WINED3DTSS_TEXCOORDINDEX ,
8130 WINED3DTSS_TEXTURETRANSFORMFLAGS
8133 const DWORD SavedVertexStates_S[NUM_SAVEDVERTEXSTATES_S] = {
8134 WINED3DSAMP_DMAPOFFSET