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