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
10 * Copyright 2006 Henri Verbeet
12 * This library is free software; you can redistribute it and/or
13 * modify it under the terms of the GNU Lesser General Public
14 * License as published by the Free Software Foundation; either
15 * version 2.1 of the License, or (at your option) any later version.
17 * This library is distributed in the hope that it will be useful,
18 * but WITHOUT ANY WARRANTY; without even the implied warranty of
19 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
20 * Lesser General Public License for more details.
22 * You should have received a copy of the GNU Lesser General Public
23 * License along with this library; if not, write to the Free Software
24 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
32 #include "wined3d_private.h"
34 WINE_DEFAULT_DEBUG_CHANNEL(d3d);
35 WINE_DECLARE_DEBUG_CHANNEL(d3d_shader);
36 #define GLINFO_LOCATION ((IWineD3DImpl *)(This->wineD3D))->gl_info
38 /* Define the default light parameters as specified by MSDN */
39 const WINED3DLIGHT WINED3D_default_light = {
41 WINED3DLIGHT_DIRECTIONAL, /* Type */
42 { 1.0, 1.0, 1.0, 0.0 }, /* Diffuse r,g,b,a */
43 { 0.0, 0.0, 0.0, 0.0 }, /* Specular r,g,b,a */
44 { 0.0, 0.0, 0.0, 0.0 }, /* Ambient r,g,b,a, */
45 { 0.0, 0.0, 0.0 }, /* Position x,y,z */
46 { 0.0, 0.0, 1.0 }, /* Direction x,y,z */
49 0.0, 0.0, 0.0, /* Attenuation 0,1,2 */
54 /* x11drv GDI escapes */
55 #define X11DRV_ESCAPE 6789
56 enum x11drv_escape_codes
58 X11DRV_GET_DISPLAY, /* get X11 display for a DC */
59 X11DRV_GET_DRAWABLE, /* get current drawable for a DC */
60 X11DRV_GET_FONT, /* get current X font for a DC */
63 /* retrieve the X display to use on a given DC */
64 inline static Display *get_display( HDC hdc )
67 enum x11drv_escape_codes escape = X11DRV_GET_DISPLAY;
69 if (!ExtEscape( hdc, X11DRV_ESCAPE, sizeof(escape), (LPCSTR)&escape,
70 sizeof(display), (LPSTR)&display )) display = NULL;
74 /* allocate one pbuffer per surface */
75 BOOL pbuffer_per_surface = FALSE;
77 /* static function declarations */
78 static void WINAPI IWineD3DDeviceImpl_AddResource(IWineD3DDevice *iface, IWineD3DResource *resource);
80 static void WINAPI IWineD3DDeviceImpl_ApplyTextureUnitState(IWineD3DDevice *iface, DWORD Stage, WINED3DTEXTURESTAGESTATETYPE Type);
83 #define D3DMEMCHECK(object, ppResult) if(NULL == object) { *ppResult = NULL; WARN("Out of memory\n"); return WINED3DERR_OUTOFVIDEOMEMORY;}
85 #define D3DCREATEOBJECTINSTANCE(object, type) { \
86 object=HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(IWineD3D##type##Impl)); \
87 D3DMEMCHECK(object, pp##type); \
88 object->lpVtbl = &IWineD3D##type##_Vtbl; \
89 object->wineD3DDevice = This; \
90 object->parent = parent; \
92 *pp##type = (IWineD3D##type *) object; \
95 #define D3DCREATESHADEROBJECTINSTANCE(object, type) { \
96 object=HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(IWineD3D##type##Impl)); \
97 D3DMEMCHECK(object, pp##type); \
98 object->lpVtbl = &IWineD3D##type##_Vtbl; \
99 object->parent = parent; \
101 object->baseShader.device = (IWineD3DDevice*) This; \
102 *pp##type = (IWineD3D##type *) object; \
105 #define D3DCREATERESOURCEOBJECTINSTANCE(object, type, d3dtype, _size){ \
106 object=HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(IWineD3D##type##Impl)); \
107 D3DMEMCHECK(object, pp##type); \
108 object->lpVtbl = &IWineD3D##type##_Vtbl; \
109 object->resource.wineD3DDevice = This; \
110 object->resource.parent = parent; \
111 object->resource.resourceType = d3dtype; \
112 object->resource.ref = 1; \
113 object->resource.pool = Pool; \
114 object->resource.format = Format; \
115 object->resource.usage = Usage; \
116 object->resource.size = _size; \
117 /* Check that we have enough video ram left */ \
118 if (Pool == WINED3DPOOL_DEFAULT) { \
119 if (IWineD3DDevice_GetAvailableTextureMem(iface) <= _size) { \
120 WARN("Out of 'bogus' video memory\n"); \
121 HeapFree(GetProcessHeap(), 0, object); \
123 return WINED3DERR_OUTOFVIDEOMEMORY; \
125 globalChangeGlRam(_size); \
127 object->resource.allocatedMemory = (0 == _size ? NULL : Pool == WINED3DPOOL_DEFAULT ? NULL : HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, _size)); \
128 if (object->resource.allocatedMemory == NULL && _size != 0 && Pool != WINED3DPOOL_DEFAULT) { \
129 FIXME("Out of memory!\n"); \
130 HeapFree(GetProcessHeap(), 0, object); \
132 return WINED3DERR_OUTOFVIDEOMEMORY; \
134 *pp##type = (IWineD3D##type *) object; \
135 IWineD3DDeviceImpl_AddResource(iface, (IWineD3DResource *)object) ;\
136 TRACE("(%p) : Created resource %p\n", This, object); \
139 #define D3DINITIALIZEBASETEXTURE(_basetexture) { \
140 _basetexture.levels = Levels; \
141 _basetexture.filterType = (Usage & WINED3DUSAGE_AUTOGENMIPMAP) ? WINED3DTEXF_LINEAR : WINED3DTEXF_NONE; \
142 _basetexture.LOD = 0; \
143 _basetexture.dirty = TRUE; \
146 /**********************************************************
147 * Global variable / Constants follow
148 **********************************************************/
149 const float identity[16] = {1,0,0,0, 0,1,0,0, 0,0,1,0, 0,0,0,1}; /* When needed for comparisons */
151 /**********************************************************
152 * Utility functions follow
153 **********************************************************/
154 /* Convert the WINED3DLIGHT properties into equivalent gl lights */
155 static void setup_light(IWineD3DDevice *iface, LONG Index, PLIGHTINFOEL *lightInfo) {
158 float colRGBA[] = {0.0, 0.0, 0.0, 0.0};
159 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
161 /* Light settings are affected by the model view in OpenGL, the View transform in direct3d*/
162 glMatrixMode(GL_MODELVIEW);
164 glLoadMatrixf((float *)&This->stateBlock->transforms[WINED3DTS_VIEW].u.m[0][0]);
167 colRGBA[0] = lightInfo->OriginalParms.Diffuse.r;
168 colRGBA[1] = lightInfo->OriginalParms.Diffuse.g;
169 colRGBA[2] = lightInfo->OriginalParms.Diffuse.b;
170 colRGBA[3] = lightInfo->OriginalParms.Diffuse.a;
171 glLightfv(GL_LIGHT0+Index, GL_DIFFUSE, colRGBA);
172 checkGLcall("glLightfv");
175 colRGBA[0] = lightInfo->OriginalParms.Specular.r;
176 colRGBA[1] = lightInfo->OriginalParms.Specular.g;
177 colRGBA[2] = lightInfo->OriginalParms.Specular.b;
178 colRGBA[3] = lightInfo->OriginalParms.Specular.a;
179 glLightfv(GL_LIGHT0+Index, GL_SPECULAR, colRGBA);
180 checkGLcall("glLightfv");
183 colRGBA[0] = lightInfo->OriginalParms.Ambient.r;
184 colRGBA[1] = lightInfo->OriginalParms.Ambient.g;
185 colRGBA[2] = lightInfo->OriginalParms.Ambient.b;
186 colRGBA[3] = lightInfo->OriginalParms.Ambient.a;
187 glLightfv(GL_LIGHT0+Index, GL_AMBIENT, colRGBA);
188 checkGLcall("glLightfv");
190 /* Attenuation - Are these right? guessing... */
191 glLightf(GL_LIGHT0+Index, GL_CONSTANT_ATTENUATION, lightInfo->OriginalParms.Attenuation0);
192 checkGLcall("glLightf");
193 glLightf(GL_LIGHT0+Index, GL_LINEAR_ATTENUATION, lightInfo->OriginalParms.Attenuation1);
194 checkGLcall("glLightf");
196 if ((lightInfo->OriginalParms.Range *lightInfo->OriginalParms.Range) >= FLT_MIN) {
197 quad_att = 1.4/(lightInfo->OriginalParms.Range *lightInfo->OriginalParms.Range);
199 quad_att = 0; /* 0 or MAX? (0 seems to be ok) */
202 if (quad_att < lightInfo->OriginalParms.Attenuation2) quad_att = lightInfo->OriginalParms.Attenuation2;
203 glLightf(GL_LIGHT0+Index, GL_QUADRATIC_ATTENUATION, quad_att);
204 checkGLcall("glLightf");
206 switch (lightInfo->OriginalParms.Type) {
207 case WINED3DLIGHT_POINT:
209 glLightfv(GL_LIGHT0+Index, GL_POSITION, &lightInfo->lightPosn[0]);
210 checkGLcall("glLightfv");
211 glLightf(GL_LIGHT0 + Index, GL_SPOT_CUTOFF, lightInfo->cutoff);
212 checkGLcall("glLightf");
216 case WINED3DLIGHT_SPOT:
218 glLightfv(GL_LIGHT0+Index, GL_POSITION, &lightInfo->lightPosn[0]);
219 checkGLcall("glLightfv");
221 glLightfv(GL_LIGHT0+Index, GL_SPOT_DIRECTION, &lightInfo->lightDirn[0]);
222 checkGLcall("glLightfv");
223 glLightf(GL_LIGHT0 + Index, GL_SPOT_EXPONENT, lightInfo->exponent);
224 checkGLcall("glLightf");
225 glLightf(GL_LIGHT0 + Index, GL_SPOT_CUTOFF, lightInfo->cutoff);
226 checkGLcall("glLightf");
230 case WINED3DLIGHT_DIRECTIONAL:
232 glLightfv(GL_LIGHT0+Index, GL_POSITION, &lightInfo->lightPosn[0]); /* Note gl uses w position of 0 for direction! */
233 checkGLcall("glLightfv");
234 glLightf(GL_LIGHT0+Index, GL_SPOT_CUTOFF, lightInfo->cutoff);
235 checkGLcall("glLightf");
236 glLightf(GL_LIGHT0+Index, GL_SPOT_EXPONENT, 0.0f);
237 checkGLcall("glLightf");
241 FIXME("Unrecognized light type %d\n", lightInfo->OriginalParms.Type);
244 /* Restore the modelview matrix */
248 /**********************************************************
249 * GLSL helper functions follow
250 **********************************************************/
252 /** Attach a GLSL pixel or vertex shader object to the shader program */
253 static void attach_glsl_shader(IWineD3DDevice *iface, IWineD3DBaseShader* shader) {
255 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
256 GLhandleARB shaderObj = ((IWineD3DBaseShaderImpl*)shader)->baseShader.prgId;
257 if (This->stateBlock->glsl_program && shaderObj != 0) {
258 TRACE_(d3d_shader)("Attaching GLSL shader object %u to program %u\n", shaderObj, This->stateBlock->glsl_program->programId);
259 GL_EXTCALL(glAttachObjectARB(This->stateBlock->glsl_program->programId, shaderObj));
260 checkGLcall("glAttachObjectARB");
264 /** Sets the GLSL program ID for the given pixel and vertex shader combination.
265 * It sets the programId on the current StateBlock (because it should be called
266 * inside of the DrawPrimitive() part of the render loop).
268 * If a program for the given combination does not exist, create one, and store
269 * the program in the list. If it creates a program, it will link the given
272 * We keep the shader programs around on a list because linking
273 * shader objects together is an expensive operation. It's much
274 * faster to loop through a list of pre-compiled & linked programs
275 * each time that the application sets a new pixel or vertex shader
276 * than it is to re-link them together at that time.
278 * The list will be deleted in IWineD3DDevice::Release().
280 void set_glsl_shader_program(IWineD3DDevice *iface) {
282 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
283 IWineD3DPixelShader *pshader = This->stateBlock->pixelShader;
284 IWineD3DVertexShader *vshader = This->stateBlock->vertexShader;
285 struct glsl_shader_prog_link *curLink = NULL;
286 struct glsl_shader_prog_link *newLink = NULL;
287 struct list *ptr = NULL;
288 GLhandleARB programId = 0;
292 ptr = list_head( &This->glsl_shader_progs );
294 /* At least one program exists - see if it matches our ps/vs combination */
295 curLink = LIST_ENTRY( ptr, struct glsl_shader_prog_link, entry );
296 if (vshader == curLink->vertexShader && pshader == curLink->pixelShader) {
297 /* Existing Program found, use it */
298 TRACE_(d3d_shader)("Found existing program (%u) for this vertex/pixel shader combination\n",
300 This->stateBlock->glsl_program = curLink;
303 /* This isn't the entry we need - try the next one */
304 ptr = list_next( &This->glsl_shader_progs, ptr );
307 /* If we get to this point, then no matching program exists, so we create one */
308 programId = GL_EXTCALL(glCreateProgramObjectARB());
309 TRACE_(d3d_shader)("Created new GLSL shader program %u\n", programId);
311 /* Allocate a new link for the list of programs */
312 newLink = HeapAlloc(GetProcessHeap(), 0, sizeof(struct glsl_shader_prog_link));
313 newLink->programId = programId;
314 This->stateBlock->glsl_program = newLink;
316 /* Attach GLSL vshader */
317 if (NULL != vshader && This->vs_selected_mode == SHADER_GLSL) {
319 int max_attribs = 16; /* TODO: Will this always be the case? It is at the moment... */
322 TRACE("Attaching vertex shader to GLSL program\n");
323 attach_glsl_shader(iface, (IWineD3DBaseShader*)vshader);
325 /* Bind vertex attributes to a corresponding index number to match
326 * the same index numbers as ARB_vertex_programs (makes loading
327 * vertex attributes simpler). With this method, we can use the
328 * exact same code to load the attributes later for both ARB and
331 * We have to do this here because we need to know the Program ID
332 * in order to make the bindings work, and it has to be done prior
333 * to linking the GLSL program. */
334 for (i = 0; i < max_attribs; ++i) {
335 snprintf(tmp_name, sizeof(tmp_name), "attrib%i", i);
336 GL_EXTCALL(glBindAttribLocationARB(programId, i, tmp_name));
338 checkGLcall("glBindAttribLocationARB");
339 newLink->vertexShader = vshader;
342 /* Attach GLSL pshader */
343 if (NULL != pshader && This->ps_selected_mode == SHADER_GLSL) {
344 TRACE("Attaching pixel shader to GLSL program\n");
345 attach_glsl_shader(iface, (IWineD3DBaseShader*)pshader);
346 newLink->pixelShader = pshader;
349 /* Link the program */
350 TRACE_(d3d_shader)("Linking GLSL shader program %u\n", programId);
351 GL_EXTCALL(glLinkProgramARB(programId));
352 print_glsl_info_log(&GLINFO_LOCATION, programId);
353 list_add_head( &This->glsl_shader_progs, &newLink->entry);
355 newLink->vuniformF_locations = HeapAlloc(GetProcessHeap(), 0, sizeof(GLhandleARB) * GL_LIMITS(vshader_constantsF));
356 for (i = 0; i < GL_LIMITS(vshader_constantsF); ++i) {
357 snprintf(glsl_name, sizeof(glsl_name), "VC[%i]", i);
358 newLink->vuniformF_locations[i] = GL_EXTCALL(glGetUniformLocationARB(programId, glsl_name));
360 newLink->puniformF_locations = HeapAlloc(GetProcessHeap(), 0, sizeof(GLhandleARB) * GL_LIMITS(pshader_constantsF));
361 for (i = 0; i < GL_LIMITS(pshader_constantsF); ++i) {
362 snprintf(glsl_name, sizeof(glsl_name), "PC[%i]", i);
363 newLink->puniformF_locations[i] = GL_EXTCALL(glGetUniformLocationARB(programId, glsl_name));
369 /** Detach the GLSL pixel or vertex shader object from the shader program */
370 static void detach_glsl_shader(IWineD3DDevice *iface, GLhandleARB shaderObj, GLhandleARB programId) {
372 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
374 if (shaderObj != 0 && programId != 0) {
375 TRACE_(d3d_shader)("Detaching GLSL shader object %u from program %u\n", shaderObj, programId);
376 GL_EXTCALL(glDetachObjectARB(programId, shaderObj));
377 checkGLcall("glDetachObjectARB");
381 /** Delete a GLSL shader program */
382 static void delete_glsl_shader_program(IWineD3DDevice *iface, GLhandleARB obj) {
384 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
387 TRACE_(d3d_shader)("Deleting GLSL shader program %u\n", obj);
388 GL_EXTCALL(glDeleteObjectARB(obj));
389 checkGLcall("glDeleteObjectARB");
393 /** Delete the list of linked programs this shader is associated with.
394 * Also at this point, check to see if there are any objects left attached
395 * to each GLSL program. If not, delete the GLSL program object.
396 * This will be run when a device is released. */
397 static void delete_glsl_shader_list(IWineD3DDevice* iface) {
399 struct list *ptr = NULL;
400 struct glsl_shader_prog_link *curLink = NULL;
401 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
405 GLhandleARB objList[2]; /* There should never be more than 2 objects attached
406 (one pixel shader and one vertex shader at most) */
408 ptr = list_head( &This->glsl_shader_progs );
410 /* First, get the current item,
411 * save the link to the next pointer,
412 * detach and delete shader objects,
413 * then de-allocate the list item's memory */
414 curLink = LIST_ENTRY( ptr, struct glsl_shader_prog_link, entry );
415 ptr = list_next( &This->glsl_shader_progs, ptr );
417 /* See if this object is still attached to the program - it may have been detached already */
418 GL_EXTCALL(glGetAttachedObjectsARB(curLink->programId, 2, &numAttached, objList));
419 TRACE_(d3d_shader)("%i GLSL objects are currently attached to program %u\n", numAttached, curLink->programId);
420 for (i = 0; i < numAttached; i++) {
421 detach_glsl_shader(iface, objList[i], curLink->programId);
424 delete_glsl_shader_program(iface, curLink->programId);
426 /* Free the uniform locations */
427 HeapFree(GetProcessHeap(), 0, curLink->vuniformF_locations);
428 HeapFree(GetProcessHeap(), 0, curLink->puniformF_locations);
430 /* Free the memory for this list item */
431 HeapFree(GetProcessHeap(), 0, curLink);
436 /* Apply the current values to the specified texture stage */
437 static void WINAPI IWineD3DDeviceImpl_SetupTextureStates(IWineD3DDevice *iface, DWORD Sampler, DWORD texture_idx, DWORD Flags) {
438 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
446 /* In addition, IDirect3DDevice9::SetSamplerState will now be used for filtering, tiling,
447 clamping, MIPLOD, etc. This will work for up to 16 samplers.
450 if (Sampler >= GL_LIMITS(sampler_stages)) {
451 FIXME("Trying to set the state of more samplers %d than are supported %d by this openGL implementation\n", Sampler, GL_LIMITS(sampler_stages));
454 VTRACE(("Activating appropriate texture state %d\n", Sampler));
455 if (GL_SUPPORT(ARB_MULTITEXTURE)) {
457 GL_EXTCALL(glActiveTextureARB(GL_TEXTURE0_ARB + texture_idx));
458 checkGLcall("glActiveTextureARB");
460 /* Could we use bindTexture and then apply the states instead of GLACTIVETEXTURE */
461 } else if (Sampler > 0) {
462 FIXME("Program using multiple concurrent textures which this opengl implementation doesn't support\n");
466 /* TODO: change this to a lookup table
467 LOOKUP_TEXTURE_STATES lists all texture states that should be applied.
468 LOOKUP_CONTEXT_SATES list all context applicable states that can be applied
469 etc.... it's a lot cleaner, quicker and possibly easier to maintain than running a switch and setting a skip flag...
470 especially when there are a number of groups of states. */
472 TRACE("-----------------------> Updating the texture at Sampler %d to have new texture state information\n", Sampler);
474 /* 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 */
475 #define APPLY_STATE(_state) IWineD3DDeviceImpl_ApplyTextureUnitState(iface, Sampler, _state)
476 /* these are the only two supported states that need to be applied */
477 APPLY_STATE(WINED3DTSS_TEXCOORDINDEX);
478 APPLY_STATE(WINED3DTSS_TEXTURETRANSFORMFLAGS);
479 #if 0 /* not supported at the moment */
480 APPLY_STATE(WINED3DTSS_BUMPENVMAT00);
481 APPLY_STATE(WINED3DTSS_BUMPENVMAT01);
482 APPLY_STATE(WINED3DTSS_BUMPENVMAT10);
483 APPLY_STATE(WINED3DTSS_BUMPENVMAT11);
484 APPLY_STATE(WINED3DTSS_BUMPENVLSCALE);
485 APPLY_STATE(WINED3DTSS_BUMPENVLOFFSET);
486 APPLY_STATE(WINED3DTSS_RESULTARG);
487 APPLY_STATE(WINED3DTSS_CONSTANT);
489 /* a quick sanity check in case someone forgot to update this function */
490 if (WINED3D_HIGHEST_TEXTURE_STATE > WINED3DTSS_CONSTANT) {
491 FIXME("(%p) : There are more texture states than expected, update device.c to match\n", This);
495 /* apply any sampler states that always need applying */
496 if (GL_SUPPORT(EXT_TEXTURE_LOD_BIAS)) {
497 tmpvalue.d = This->stateBlock->samplerState[Sampler][WINED3DSAMP_MIPMAPLODBIAS];
498 glTexEnvf(GL_TEXTURE_FILTER_CONTROL_EXT,
499 GL_TEXTURE_LOD_BIAS_EXT,
501 checkGLcall("glTexEnvi GL_TEXTURE_LOD_BIAS_EXT ...");
504 D3DCOLORTOGLFLOAT4(This->stateBlock->renderState[WINED3DRS_TEXTUREFACTOR], col);
505 glTexEnvfv(GL_TEXTURE_ENV, GL_TEXTURE_ENV_COLOR, &col[0]);
506 checkGLcall("glTexEnvfv(GL_TEXTURE_ENV, GL_TEXTURE_ENV_COLOR, color);");
508 /* TODO: NV_POINT_SPRITE */
509 if (GL_SUPPORT(ARB_POINT_SPRITE)) {
510 if (This->stateBlock->renderState[WINED3DRS_POINTSPRITEENABLE]) {
511 /* Doesn't work with GL_POINT_SMOOTH on on my ATI 9600, but then ATI drivers are buggered! */
512 glDisable(GL_POINT_SMOOTH);
514 /* Centre the texture on the vertex */
515 VTRACE(("glTexEnvf( GL_POINT_SPRITE_ARB, GL_COORD_REPLACE_ARB, GL_TRUE)\n"));
516 glTexEnvf( GL_POINT_SPRITE_ARB, GL_COORD_REPLACE_ARB, GL_TRUE);
518 VTRACE(("glTexEnvf( GL_POINT_SPRITE_ARB, GL_COORD_REPLACE_ARB, GL_TRUE)\n"));
519 glTexEnvf( GL_POINT_SPRITE_ARB, GL_COORD_REPLACE_ARB, GL_TRUE);
520 checkGLcall("glTexEnvf(...)");
521 VTRACE(("glEnable( GL_POINT_SPRITE_ARB )\n"));
522 glEnable( GL_POINT_SPRITE_ARB );
523 checkGLcall("glEnable(...)");
525 VTRACE(("glDisable( GL_POINT_SPRITE_ARB )\n"));
526 glDisable( GL_POINT_SPRITE_ARB );
527 checkGLcall("glEnable(...)");
531 TRACE("-----------------------> Updated the texture at Sampler %d to have new texture state information\n", Sampler);
534 /**********************************************************
535 * IUnknown parts follows
536 **********************************************************/
538 static HRESULT WINAPI IWineD3DDeviceImpl_QueryInterface(IWineD3DDevice *iface,REFIID riid,LPVOID *ppobj)
540 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
542 TRACE("(%p)->(%s,%p)\n",This,debugstr_guid(riid),ppobj);
543 if (IsEqualGUID(riid, &IID_IUnknown)
544 || IsEqualGUID(riid, &IID_IWineD3DBase)
545 || IsEqualGUID(riid, &IID_IWineD3DDevice)) {
546 IUnknown_AddRef(iface);
551 return E_NOINTERFACE;
554 static ULONG WINAPI IWineD3DDeviceImpl_AddRef(IWineD3DDevice *iface) {
555 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
556 ULONG refCount = InterlockedIncrement(&This->ref);
558 TRACE("(%p) : AddRef increasing from %d\n", This, refCount - 1);
562 static ULONG WINAPI IWineD3DDeviceImpl_Release(IWineD3DDevice *iface) {
563 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
564 ULONG refCount = InterlockedDecrement(&This->ref);
566 TRACE("(%p) : Releasing from %d\n", This, refCount + 1);
569 /* TODO: Clean up all the surfaces and textures! */
570 /* NOTE: You must release the parent if the object was created via a callback
571 ** ***************************/
573 /* Delete any GLSL shader programs that may exist */
574 if (This->vs_selected_mode == SHADER_GLSL ||
575 This->ps_selected_mode == SHADER_GLSL)
576 delete_glsl_shader_list(iface);
578 /* Release the update stateblock */
579 if(IWineD3DStateBlock_Release((IWineD3DStateBlock *)This->updateStateBlock) > 0){
580 if(This->updateStateBlock != This->stateBlock)
581 FIXME("(%p) Something's still holding the Update stateblock\n",This);
583 This->updateStateBlock = NULL;
584 { /* because were not doing proper internal refcounts releasing the primary state block
585 causes recursion with the extra checks in ResourceReleased, to avoid this we have
586 to set this->stateBlock = NULL; first */
587 IWineD3DStateBlock *stateBlock = (IWineD3DStateBlock *)This->stateBlock;
588 This->stateBlock = NULL;
590 /* Release the stateblock */
591 if(IWineD3DStateBlock_Release(stateBlock) > 0){
592 FIXME("(%p) Something's still holding the Update stateblock\n",This);
596 if (This->resources != NULL ) {
597 FIXME("(%p) Device released with resources still bound, acceptable but unexpected\n", This);
598 dumpResources(This->resources);
602 IWineD3D_Release(This->wineD3D);
603 This->wineD3D = NULL;
604 HeapFree(GetProcessHeap(), 0, This);
605 TRACE("Freed device %p\n", This);
611 /**********************************************************
612 * IWineD3DDevice implementation follows
613 **********************************************************/
614 static HRESULT WINAPI IWineD3DDeviceImpl_GetParent(IWineD3DDevice *iface, IUnknown **pParent) {
615 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
616 *pParent = This->parent;
617 IUnknown_AddRef(This->parent);
621 static void CreateVBO(IWineD3DVertexBufferImpl *object) {
622 IWineD3DDeviceImpl *This = object->resource.wineD3DDevice; /* Needed for GL_EXTCALL */
623 GLenum error, glUsage;
624 DWORD vboUsage = object->resource.usage;
625 if(object->Flags & VBFLAG_VBOCREATEFAIL) {
626 WARN("Creating a vbo failed once, not trying again\n");
630 TRACE("Creating an OpenGL vertex buffer object for IWineD3DVertexBuffer %p Usage(%s)\n", object, debug_d3dusage(vboUsage));
633 /* Make sure that the gl error is cleared. Do not use checkGLcall
634 * here because checkGLcall just prints a fixme and continues. However,
635 * if an error during VBO creation occurs we can fall back to non-vbo operation
636 * with full functionality(but performance loss)
638 while(glGetError() != GL_NO_ERROR);
640 /* Basically the FVF parameter passed to CreateVertexBuffer is no good
641 * It is the FVF set with IWineD3DDevice::SetFVF or the Vertex Declaration set with
642 * IWineD3DDevice::SetVertexDeclaration that decides how the vertices in the buffer
643 * look like. This means that on each DrawPrimitive call the vertex buffer has to be verified
644 * to check if the rhw and color values are in the correct format.
647 GL_EXTCALL(glGenBuffersARB(1, &object->vbo));
648 error = glGetError();
649 if(object->vbo == 0 || error != GL_NO_ERROR) {
650 WARN("Failed to create a VBO with error %d\n", error);
654 GL_EXTCALL(glBindBufferARB(GL_ARRAY_BUFFER_ARB, object->vbo));
655 error = glGetError();
656 if(error != GL_NO_ERROR) {
657 WARN("Failed to bind the VBO, error %d\n", error);
661 /* Transformed vertices are horribly inflexible. If the app specifies an
662 * vertex buffer with transformed vertices in default pool without DYNAMIC
663 * usage assume DYNAMIC usage and print a warning. The app will have to update
664 * the vertices regularily for them to be useful
666 if(((object->fvf & WINED3DFVF_POSITION_MASK) == WINED3DFVF_XYZRHW) &&
667 !(vboUsage & WINED3DUSAGE_DYNAMIC)) {
668 WARN("Application creates a vertex buffer holding transformed vertices which doesn't specify dynamic usage\n");
669 vboUsage |= WINED3DUSAGE_DYNAMIC;
672 /* Don't use static, because dx apps tend to update the buffer
673 * quite often even if they specify 0 usage
675 switch(vboUsage & (D3DUSAGE_WRITEONLY | D3DUSAGE_DYNAMIC) ) {
676 case D3DUSAGE_WRITEONLY | D3DUSAGE_DYNAMIC:
677 TRACE("Gl usage = GL_STREAM_DRAW\n");
678 glUsage = GL_STREAM_DRAW_ARB;
680 case D3DUSAGE_WRITEONLY:
681 TRACE("Gl usage = GL_DYNAMIC_DRAW\n");
682 glUsage = GL_DYNAMIC_DRAW_ARB;
684 case D3DUSAGE_DYNAMIC:
685 TRACE("Gl usage = GL_STREAM_COPY\n");
686 glUsage = GL_STREAM_COPY_ARB;
689 TRACE("Gl usage = GL_DYNAMIC_COPY\n");
690 glUsage = GL_DYNAMIC_COPY_ARB;
694 /* Reserve memory for the buffer. The amount of data won't change
695 * so we are safe with calling glBufferData once with a NULL ptr and
696 * calling glBufferSubData on updates
698 GL_EXTCALL(glBufferDataARB(GL_ARRAY_BUFFER_ARB, object->resource.size, NULL, glUsage));
699 error = glGetError();
700 if(error != GL_NO_ERROR) {
701 WARN("glBufferDataARB failed with error %d\n", error);
709 /* Clean up all vbo init, but continue because we can work without a vbo :-) */
710 FIXME("Failed to create a vertex buffer object. Continuing, but performance issues can occur\n");
711 if(object->vbo) GL_EXTCALL(glDeleteBuffersARB(1, &object->vbo));
713 object->Flags |= VBFLAG_VBOCREATEFAIL;
718 static HRESULT WINAPI IWineD3DDeviceImpl_CreateVertexBuffer(IWineD3DDevice *iface, UINT Size, DWORD Usage,
719 DWORD FVF, WINED3DPOOL Pool, IWineD3DVertexBuffer** ppVertexBuffer, HANDLE *sharedHandle,
721 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
722 IWineD3DVertexBufferImpl *object;
723 WINED3DFORMAT Format = WINED3DFMT_VERTEXDATA; /* Dummy format for now */
724 int dxVersion = ( (IWineD3DImpl *) This->wineD3D)->dxVersion;
726 D3DCREATERESOURCEOBJECTINSTANCE(object, VertexBuffer, WINED3DRTYPE_VERTEXBUFFER, Size)
728 TRACE("(%p) : Size=%d, Usage=%d, FVF=%x, Pool=%d - Memory@%p, Iface@%p\n", This, Size, Usage, FVF, Pool, object->resource.allocatedMemory, object);
729 *ppVertexBuffer = (IWineD3DVertexBuffer *)object;
731 if(Size == 0) return WINED3DERR_INVALIDCALL;
733 if (Pool == WINED3DPOOL_DEFAULT ) { /* Allocate some system memory for now */
734 object->resource.allocatedMemory = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, object->resource.size);
738 /* Observations show that drawStridedSlow is faster on dynamic VBs than converting +
739 * drawStridedFast (half-life 2).
741 * Basically converting the vertices in the buffer is quite expensive, and observations
742 * show that drawStridedSlow is faster than converting + uploading + drawStridedFast.
743 * Therefore do not create a VBO for WINED3DUSAGE_DYNAMIC buffers.
745 * Direct3D7 has another problem: Its vertexbuffer api doesn't offer a way to specify
746 * the range of vertices being locked, so each lock will require the whole buffer to be transformed.
747 * Moreover geometry data in dx7 is quite simple, so drawStridedSlow isn't a big hit. A plus
748 * is that the vertex buffers fvf can be trusted in dx7. So only create non-converted vbos for
750 * There is a IDirect3DVertexBuffer7::Optimize call after which the buffer can't be locked any
751 * more. In this call we can convert dx7 buffers too.
753 conv = ((FVF & WINED3DFVF_POSITION_MASK) == WINED3DFVF_XYZRHW ) || (FVF & (WINED3DFVF_DIFFUSE | WINED3DFVF_SPECULAR));
754 if( GL_SUPPORT(ARB_VERTEX_BUFFER_OBJECT) && Pool != WINED3DPOOL_SYSTEMMEM && !(Usage & WINED3DUSAGE_DYNAMIC) &&
755 (dxVersion > 7 || !conv) ) {
758 /* DX7 buffers can be locked directly into the VBO (no conversion, see above */
759 if(dxVersion == 7 && object->vbo) {
760 HeapFree(GetProcessHeap(), 0, object->resource.allocatedMemory);
761 object->resource.allocatedMemory = NULL;
768 static HRESULT WINAPI IWineD3DDeviceImpl_CreateIndexBuffer(IWineD3DDevice *iface, UINT Length, DWORD Usage,
769 WINED3DFORMAT Format, WINED3DPOOL Pool, IWineD3DIndexBuffer** ppIndexBuffer,
770 HANDLE *sharedHandle, IUnknown *parent) {
771 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
772 IWineD3DIndexBufferImpl *object;
773 TRACE("(%p) Creating index buffer\n", This);
775 /* Allocate the storage for the device */
776 D3DCREATERESOURCEOBJECTINSTANCE(object,IndexBuffer,WINED3DRTYPE_INDEXBUFFER, Length)
779 if (Pool == WINED3DPOOL_DEFAULT ) { /* Allocate some system memory for now */
780 object->resource.allocatedMemory = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,object->resource.size);
783 TRACE("(%p) : Len=%d, Use=%x, Format=(%u,%s), Pool=%d - Memory@%p, Iface@%p\n", This, Length, Usage, Format,
784 debug_d3dformat(Format), Pool, object, object->resource.allocatedMemory);
785 *ppIndexBuffer = (IWineD3DIndexBuffer *) object;
790 static HRESULT WINAPI IWineD3DDeviceImpl_CreateStateBlock(IWineD3DDevice* iface, WINED3DSTATEBLOCKTYPE Type, IWineD3DStateBlock** ppStateBlock, IUnknown *parent) {
792 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
793 IWineD3DStateBlockImpl *object;
797 D3DCREATEOBJECTINSTANCE(object, StateBlock)
798 object->blockType = Type;
800 /* Special case - Used during initialization to produce a placeholder stateblock
801 so other functions called can update a state block */
802 if (Type == WINED3DSBT_INIT) {
803 /* Don't bother increasing the reference count otherwise a device will never
804 be freed due to circular dependencies */
808 temp_result = allocate_shader_constants(object);
809 if (WINED3D_OK != temp_result)
812 /* Otherwise, might as well set the whole state block to the appropriate values */
813 if (This->stateBlock != NULL)
814 stateblock_copy((IWineD3DStateBlock*) object, (IWineD3DStateBlock*) This->stateBlock);
816 memset(object->streamFreq, 1, sizeof(object->streamFreq));
818 /* Reset the ref and type after kludging it */
819 object->wineD3DDevice = This;
821 object->blockType = Type;
823 TRACE("Updating changed flags appropriate for type %d\n", Type);
825 if (Type == WINED3DSBT_ALL) {
827 TRACE("ALL => Pretend everything has changed\n");
828 stateblock_savedstates_set((IWineD3DStateBlock*) object, &object->changed, TRUE);
830 } else if (Type == WINED3DSBT_PIXELSTATE) {
832 TRACE("PIXELSTATE => Pretend all pixel shates have changed\n");
833 stateblock_savedstates_set((IWineD3DStateBlock*) object, &object->changed, FALSE);
835 object->changed.pixelShader = TRUE;
837 /* Pixel Shader Constants */
838 for (i = 0; i < GL_LIMITS(pshader_constantsF); ++i)
839 object->changed.pixelShaderConstantsF[i] = TRUE;
840 for (i = 0; i < MAX_CONST_B; ++i)
841 object->changed.pixelShaderConstantsB[i] = TRUE;
842 for (i = 0; i < MAX_CONST_I; ++i)
843 object->changed.pixelShaderConstantsI[i] = TRUE;
845 for (i = 0; i < NUM_SAVEDPIXELSTATES_R; i++) {
846 object->changed.renderState[SavedPixelStates_R[i]] = TRUE;
848 for (j = 0; j < GL_LIMITS(texture_stages); j++) {
849 for (i = 0; i < NUM_SAVEDPIXELSTATES_T; i++) {
850 object->changed.textureState[j][SavedPixelStates_T[i]] = TRUE;
853 for (j = 0 ; j < 16; j++) {
854 for (i =0; i < NUM_SAVEDPIXELSTATES_S;i++) {
856 object->changed.samplerState[j][SavedPixelStates_S[i]] = TRUE;
860 } else if (Type == WINED3DSBT_VERTEXSTATE) {
862 TRACE("VERTEXSTATE => Pretend all vertex shates have changed\n");
863 stateblock_savedstates_set((IWineD3DStateBlock*) object, &object->changed, FALSE);
865 object->changed.vertexShader = TRUE;
867 /* Vertex Shader Constants */
868 for (i = 0; i < GL_LIMITS(vshader_constantsF); ++i)
869 object->changed.vertexShaderConstantsF[i] = TRUE;
870 for (i = 0; i < MAX_CONST_B; ++i)
871 object->changed.vertexShaderConstantsB[i] = TRUE;
872 for (i = 0; i < MAX_CONST_I; ++i)
873 object->changed.vertexShaderConstantsI[i] = TRUE;
875 for (i = 0; i < NUM_SAVEDVERTEXSTATES_R; i++) {
876 object->changed.renderState[SavedVertexStates_R[i]] = TRUE;
878 for (j = 0; j < GL_LIMITS(texture_stages); j++) {
879 for (i = 0; i < NUM_SAVEDVERTEXSTATES_T; i++) {
880 object->changed.textureState[j][SavedVertexStates_T[i]] = TRUE;
883 for (j = 0 ; j < 16; j++){
884 for (i =0; i < NUM_SAVEDVERTEXSTATES_S;i++) {
885 object->changed.samplerState[j][SavedVertexStates_S[i]] = TRUE;
889 /* Duplicate light chain */
891 PLIGHTINFOEL *src = NULL;
892 PLIGHTINFOEL *dst = NULL;
893 PLIGHTINFOEL *newEl = NULL;
894 src = This->stateBlock->lights;
895 object->lights = NULL;
899 newEl = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(PLIGHTINFOEL));
900 if (newEl == NULL) return WINED3DERR_OUTOFVIDEOMEMORY;
901 memcpy(newEl, src, sizeof(PLIGHTINFOEL));
903 newEl->changed = TRUE;
904 newEl->enabledChanged = TRUE;
906 object->lights = newEl;
917 FIXME("Unrecognized state block type %d\n", Type);
920 TRACE("(%p) returning token (ptr to stateblock) of %p\n", This, object);
925 /* ************************************
927 [in] Render targets are not lockable unless the application specifies TRUE for Lockable. Note that lockable render targets reduce performance on some graphics hardware.
930 [in] Set this flag to TRUE to enable z-buffer discarding, and FALSE otherwise.
932 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.
934 ******************************** */
936 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) {
937 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
938 IWineD3DSurfaceImpl *object; /*NOTE: impl ref allowed since this is a create function */
939 unsigned int pow2Width, pow2Height;
940 unsigned int Size = 1;
941 const PixelFormatDesc *tableEntry = getFormatDescEntry(Format);
942 TRACE("(%p) Create surface\n",This);
944 /** FIXME: Check ranges on the inputs are valid
947 * [in] Quality level. The valid range is between zero and one less than the level
948 * returned by pQualityLevels used by IDirect3D9::CheckDeviceMultiSampleType.
949 * Passing a larger value returns the error WINED3DERR_INVALIDCALL. The MultisampleQuality
950 * values of paired render targets, depth stencil surfaces, and the MultiSample type
952 *******************************/
957 * [in] Set this flag to TRUE to enable z-buffer discarding, and FALSE otherwise.
959 * If this flag is set, the contents of the depth stencil buffer will be
960 * invalid after calling either IDirect3DDevice9::Present or * IDirect3DDevice9::SetDepthStencilSurface
961 * with a different depth surface.
963 *This flag has the same behavior as the constant, D3DPRESENTFLAG_DISCARD_DEPTHSTENCIL, in D3DPRESENTFLAG.
964 ***************************/
966 if(MultisampleQuality < 0) {
967 FIXME("Invalid multisample level %d\n", MultisampleQuality);
968 return WINED3DERR_INVALIDCALL; /* TODO: Check that this is the case! */
971 if(MultisampleQuality > 0) {
972 FIXME("MultisampleQuality set to %d, substituting 0\n", MultisampleQuality);
973 MultisampleQuality=0;
976 /** FIXME: Check that the format is supported
978 *******************************/
980 /* Non-power2 support */
981 if (wined3d_settings.nonpower2_mode == NP2_NATIVE) {
985 /* Find the nearest pow2 match */
986 pow2Width = pow2Height = 1;
987 while (pow2Width < Width) pow2Width <<= 1;
988 while (pow2Height < Height) pow2Height <<= 1;
991 if (pow2Width > Width || pow2Height > Height) {
992 /** TODO: add support for non power two compressed textures (OpenGL 2 provices support for * non-power-two textures gratis) **/
993 if (Format == WINED3DFMT_DXT1 || Format == WINED3DFMT_DXT2 || Format == WINED3DFMT_DXT3
994 || Format == WINED3DFMT_DXT4 || Format == WINED3DFMT_DXT5) {
995 FIXME("(%p) Compressed non-power-two textures are not supported w(%d) h(%d)\n",
996 This, Width, Height);
997 return WINED3DERR_NOTAVAILABLE;
1001 /** DXTn mipmaps use the same number of 'levels' down to eg. 8x1, but since
1002 * it is based around 4x4 pixel blocks it requires padding, so allocate enough
1004 *********************************/
1005 if (WINED3DFMT_UNKNOWN == Format) {
1007 } else if (Format == WINED3DFMT_DXT1) {
1008 /* DXT1 is half byte per pixel */
1009 Size = ((max(pow2Width,4) * tableEntry->bpp) * max(pow2Height,4)) >> 1;
1011 } else if (Format == WINED3DFMT_DXT2 || Format == WINED3DFMT_DXT3 ||
1012 Format == WINED3DFMT_DXT4 || Format == WINED3DFMT_DXT5) {
1013 Size = ((max(pow2Width,4) * tableEntry->bpp) * max(pow2Height,4));
1015 /* The pitch is a multiple of 4 bytes */
1016 Size = ((pow2Width * tableEntry->bpp) + SURFACE_ALIGNMENT - 1) & ~(SURFACE_ALIGNMENT - 1);
1020 /** Create and initialise the surface resource **/
1021 D3DCREATERESOURCEOBJECTINSTANCE(object,Surface,WINED3DRTYPE_SURFACE, Size)
1022 /* "Standalone" surface */
1023 IWineD3DSurface_SetContainer((IWineD3DSurface *)object, NULL);
1025 object->currentDesc.Width = Width;
1026 object->currentDesc.Height = Height;
1027 object->currentDesc.MultiSampleType = MultiSample;
1028 object->currentDesc.MultiSampleQuality = MultisampleQuality;
1030 /* Setup some glformat defaults */
1031 object->glDescription.glFormat = tableEntry->glFormat;
1032 object->glDescription.glFormatInternal = tableEntry->glInternal;
1033 object->glDescription.glType = tableEntry->glType;
1035 object->glDescription.textureName = 0;
1036 object->glDescription.level = Level;
1037 object->glDescription.target = GL_TEXTURE_2D;
1040 object->pow2Width = pow2Width;
1041 object->pow2Height = pow2Height;
1044 object->Flags = 0; /* We start without flags set */
1045 object->Flags |= (pow2Width != Width || pow2Height != Height) ? SFLAG_NONPOW2 : 0;
1046 object->Flags |= Discard ? SFLAG_DISCARD : 0;
1047 object->Flags |= (WINED3DFMT_D16_LOCKABLE == Format) ? SFLAG_LOCKABLE : 0;
1048 object->Flags |= Lockable ? SFLAG_LOCKABLE : 0;
1051 if (WINED3DFMT_UNKNOWN != Format) {
1052 object->bytesPerPixel = tableEntry->bpp;
1053 object->pow2Size = ((pow2Width * object->bytesPerPixel) + SURFACE_ALIGNMENT - 1) & ~(SURFACE_ALIGNMENT - 1);
1054 object->pow2Size *= pow2Height;
1056 object->bytesPerPixel = 0;
1057 object->pow2Size = 0;
1060 /** TODO: change this into a texture transform matrix so that it's processed in hardware **/
1062 TRACE("Pool %d %d %d %d\n",Pool, WINED3DPOOL_DEFAULT, WINED3DPOOL_MANAGED, WINED3DPOOL_SYSTEMMEM);
1064 /** Quick lockable sanity check TODO: remove this after surfaces, usage and lockability have been debugged properly
1065 * this function is too deep to need to care about things like this.
1066 * Levels need to be checked too, and possibly Type since they all affect what can be done.
1067 * ****************************************/
1069 case WINED3DPOOL_SCRATCH:
1071 FIXME("Create surface called with a pool of SCRATCH and a Lockable of FALSE \
1072 which are mutually exclusive, setting lockable to true\n");
1075 case WINED3DPOOL_SYSTEMMEM:
1076 if(!Lockable) FIXME("Create surface called with a pool of SYSTEMMEM and a Lockable of FALSE, \
1077 this is acceptable but unexpected (I can't know how the surface can be usable!)\n");
1078 case WINED3DPOOL_MANAGED:
1079 if(Usage == WINED3DUSAGE_DYNAMIC) FIXME("Create surface called with a pool of MANAGED and a \
1080 Usage of DYNAMIC which are mutually exclusive, not doing \
1081 anything just telling you.\n");
1083 case WINED3DPOOL_DEFAULT: /*TODO: Create offscreen plain can cause this check to fail..., find out if it should */
1084 if(!(Usage & WINED3DUSAGE_DYNAMIC) && !(Usage & WINED3DUSAGE_RENDERTARGET)
1085 && !(Usage && WINED3DUSAGE_DEPTHSTENCIL ) && Lockable)
1086 WARN("Creating a surface with a POOL of DEFAULT with Lockable true, that doesn't specify DYNAMIC usage.\n");
1089 FIXME("(%p) Unknown pool %d\n", This, Pool);
1093 if (Usage & WINED3DUSAGE_RENDERTARGET && Pool != WINED3DPOOL_DEFAULT) {
1094 FIXME("Trying to create a render target that isn't in the default pool\n");
1097 /* mark the texture as dirty so that it gets loaded first time around*/
1098 IWineD3DSurface_AddDirtyRect(*ppSurface, NULL);
1099 TRACE("(%p) : w(%d) h(%d) fmt(%d,%s) lockable(%d) surf@%p, surfmem@%p, %d bytes\n",
1100 This, Width, Height, Format, debug_d3dformat(Format),
1101 (WINED3DFMT_D16_LOCKABLE == Format), *ppSurface, object->resource.allocatedMemory, object->resource.size);
1103 /* Store the DirectDraw primary surface. This is the first rendertarget surface created */
1104 if( (Usage & WINED3DUSAGE_RENDERTARGET) && (!This->ddraw_primary) )
1105 This->ddraw_primary = (IWineD3DSurface *) object;
1107 /* Look at the implementation and set the correct Vtable */
1109 case SURFACE_OPENGL:
1110 /* Nothing to do, it's set already */
1114 object->lpVtbl = &IWineGDISurface_Vtbl;
1118 /* To be sure to catch this */
1119 ERR("Unknown requested surface implementation %d!\n", Impl);
1120 IWineD3DSurface_Release((IWineD3DSurface *) object);
1121 return WINED3DERR_INVALIDCALL;
1124 /* Call the private setup routine */
1125 return IWineD3DSurface_PrivateSetup( (IWineD3DSurface *) object );
1129 static HRESULT WINAPI IWineD3DDeviceImpl_CreateTexture(IWineD3DDevice *iface, UINT Width, UINT Height, UINT Levels,
1130 DWORD Usage, WINED3DFORMAT Format, WINED3DPOOL Pool,
1131 IWineD3DTexture** ppTexture, HANDLE* pSharedHandle, IUnknown *parent,
1132 D3DCB_CREATESURFACEFN D3DCB_CreateSurface) {
1134 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
1135 IWineD3DTextureImpl *object;
1140 unsigned int pow2Width;
1141 unsigned int pow2Height;
1144 TRACE("(%p) : Width %d, Height %d, Levels %d, Usage %#x\n", This, Width, Height, Levels, Usage);
1145 TRACE("Format %#x (%s), Pool %#x, ppTexture %p, pSharedHandle %p, parent %p\n",
1146 Format, debug_d3dformat(Format), Pool, ppTexture, pSharedHandle, parent);
1148 /* TODO: It should only be possible to create textures for formats
1149 that are reported as supported */
1150 if (WINED3DFMT_UNKNOWN >= Format) {
1151 WARN("(%p) : Texture cannot be created with a format of WINED3DFMT_UNKNOWN\n", This);
1152 return WINED3DERR_INVALIDCALL;
1155 D3DCREATERESOURCEOBJECTINSTANCE(object, Texture, WINED3DRTYPE_TEXTURE, 0);
1156 D3DINITIALIZEBASETEXTURE(object->baseTexture);
1157 object->width = Width;
1158 object->height = Height;
1160 /** Non-power2 support **/
1161 if (wined3d_settings.nonpower2_mode == NP2_NATIVE) {
1163 pow2Height = Height;
1165 /* Find the nearest pow2 match */
1166 pow2Width = pow2Height = 1;
1167 while (pow2Width < Width) pow2Width <<= 1;
1168 while (pow2Height < Height) pow2Height <<= 1;
1171 /** FIXME: add support for real non-power-two if it's provided by the video card **/
1172 /* Precalculated scaling for 'faked' non power of two texture coords */
1173 object->pow2scalingFactorX = (((float)Width) / ((float)pow2Width));
1174 object->pow2scalingFactorY = (((float)Height) / ((float)pow2Height));
1175 TRACE(" xf(%f) yf(%f)\n", object->pow2scalingFactorX, object->pow2scalingFactorY);
1177 /* Calculate levels for mip mapping */
1179 TRACE("calculating levels %d\n", object->baseTexture.levels);
1180 object->baseTexture.levels++;
1183 while (tmpW > 1 || tmpH > 1) {
1184 tmpW = max(1, tmpW >> 1);
1185 tmpH = max(1, tmpH >> 1);
1186 object->baseTexture.levels++;
1188 TRACE("Calculated levels = %d\n", object->baseTexture.levels);
1191 /* Generate all the surfaces */
1194 for (i = 0; i < object->baseTexture.levels; i++)
1196 /* use the callback to create the texture surface */
1197 hr = D3DCB_CreateSurface(This->parent, tmpW, tmpH, Format, Usage, Pool, i, &object->surfaces[i],NULL);
1198 if (hr!= WINED3D_OK || ( (IWineD3DSurfaceImpl *) object->surfaces[i])->Flags & SFLAG_OVERSIZE) {
1199 FIXME("Failed to create surface %p\n", object);
1201 object->surfaces[i] = NULL;
1202 IWineD3DTexture_Release((IWineD3DTexture *)object);
1208 IWineD3DSurface_SetContainer(object->surfaces[i], (IWineD3DBase *)object);
1209 TRACE("Created surface level %d @ %p\n", i, object->surfaces[i]);
1210 /* calculate the next mipmap level */
1211 tmpW = max(1, tmpW >> 1);
1212 tmpH = max(1, tmpH >> 1);
1215 TRACE("(%p) : Created texture %p\n", This, object);
1219 static HRESULT WINAPI IWineD3DDeviceImpl_CreateVolumeTexture(IWineD3DDevice *iface,
1220 UINT Width, UINT Height, UINT Depth,
1221 UINT Levels, DWORD Usage,
1222 WINED3DFORMAT Format, WINED3DPOOL Pool,
1223 IWineD3DVolumeTexture **ppVolumeTexture,
1224 HANDLE *pSharedHandle, IUnknown *parent,
1225 D3DCB_CREATEVOLUMEFN D3DCB_CreateVolume) {
1227 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
1228 IWineD3DVolumeTextureImpl *object;
1234 /* TODO: It should only be possible to create textures for formats
1235 that are reported as supported */
1236 if (WINED3DFMT_UNKNOWN >= Format) {
1237 WARN("(%p) : Texture cannot be created with a format of WINED3DFMT_UNKNOWN\n", This);
1238 return WINED3DERR_INVALIDCALL;
1241 D3DCREATERESOURCEOBJECTINSTANCE(object, VolumeTexture, WINED3DRTYPE_VOLUMETEXTURE, 0);
1242 D3DINITIALIZEBASETEXTURE(object->baseTexture);
1244 TRACE("(%p) : W(%d) H(%d) D(%d), Lvl(%d) Usage(%d), Fmt(%u,%s), Pool(%s)\n", This, Width, Height,
1245 Depth, Levels, Usage, Format, debug_d3dformat(Format), debug_d3dpool(Pool));
1247 object->width = Width;
1248 object->height = Height;
1249 object->depth = Depth;
1251 /* Calculate levels for mip mapping */
1253 object->baseTexture.levels++;
1257 while (tmpW > 1 || tmpH > 1 || tmpD > 1) {
1258 tmpW = max(1, tmpW >> 1);
1259 tmpH = max(1, tmpH >> 1);
1260 tmpD = max(1, tmpD >> 1);
1261 object->baseTexture.levels++;
1263 TRACE("Calculated levels = %d\n", object->baseTexture.levels);
1266 /* Generate all the surfaces */
1271 for (i = 0; i < object->baseTexture.levels; i++)
1273 /* Create the volume */
1274 D3DCB_CreateVolume(This->parent, Width, Height, Depth, Format, Pool, Usage,
1275 (IWineD3DVolume **)&object->volumes[i], pSharedHandle);
1277 /* Set its container to this object */
1278 IWineD3DVolume_SetContainer(object->volumes[i], (IWineD3DBase *)object);
1280 /* calcualte the next mipmap level */
1281 tmpW = max(1, tmpW >> 1);
1282 tmpH = max(1, tmpH >> 1);
1283 tmpD = max(1, tmpD >> 1);
1286 *ppVolumeTexture = (IWineD3DVolumeTexture *) object;
1287 TRACE("(%p) : Created volume texture %p\n", This, object);
1291 static HRESULT WINAPI IWineD3DDeviceImpl_CreateVolume(IWineD3DDevice *iface,
1292 UINT Width, UINT Height, UINT Depth,
1294 WINED3DFORMAT Format, WINED3DPOOL Pool,
1295 IWineD3DVolume** ppVolume,
1296 HANDLE* pSharedHandle, IUnknown *parent) {
1298 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
1299 IWineD3DVolumeImpl *object; /** NOTE: impl ref allowed since this is a create function **/
1300 const PixelFormatDesc *formatDesc = getFormatDescEntry(Format);
1302 D3DCREATERESOURCEOBJECTINSTANCE(object, Volume, WINED3DRTYPE_VOLUME, ((Width * formatDesc->bpp) * Height * Depth))
1304 TRACE("(%p) : W(%d) H(%d) D(%d), Usage(%d), Fmt(%u,%s), Pool(%s)\n", This, Width, Height,
1305 Depth, Usage, Format, debug_d3dformat(Format), debug_d3dpool(Pool));
1307 object->currentDesc.Width = Width;
1308 object->currentDesc.Height = Height;
1309 object->currentDesc.Depth = Depth;
1310 object->bytesPerPixel = formatDesc->bpp;
1312 /** Note: Volume textures cannot be dxtn, hence no need to check here **/
1313 object->lockable = TRUE;
1314 object->locked = FALSE;
1315 memset(&object->lockedBox, 0, sizeof(WINED3DBOX));
1316 object->dirty = TRUE;
1318 return IWineD3DVolume_AddDirtyBox((IWineD3DVolume *) object, NULL);
1321 static HRESULT WINAPI IWineD3DDeviceImpl_CreateCubeTexture(IWineD3DDevice *iface, UINT EdgeLength,
1322 UINT Levels, DWORD Usage,
1323 WINED3DFORMAT Format, WINED3DPOOL Pool,
1324 IWineD3DCubeTexture **ppCubeTexture,
1325 HANDLE *pSharedHandle, IUnknown *parent,
1326 D3DCB_CREATESURFACEFN D3DCB_CreateSurface) {
1328 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
1329 IWineD3DCubeTextureImpl *object; /** NOTE: impl ref allowed since this is a create function **/
1333 unsigned int pow2EdgeLength = EdgeLength;
1335 /* TODO: It should only be possible to create textures for formats
1336 that are reported as supported */
1337 if (WINED3DFMT_UNKNOWN >= Format) {
1338 WARN("(%p) : Texture cannot be created with a format of WINED3DFMT_UNKNOWN\n", This);
1339 return WINED3DERR_INVALIDCALL;
1342 D3DCREATERESOURCEOBJECTINSTANCE(object, CubeTexture, WINED3DRTYPE_CUBETEXTURE, 0);
1343 D3DINITIALIZEBASETEXTURE(object->baseTexture);
1345 TRACE("(%p) Create Cube Texture\n", This);
1347 /** Non-power2 support **/
1349 /* Find the nearest pow2 match */
1351 while (pow2EdgeLength < EdgeLength) pow2EdgeLength <<= 1;
1353 object->edgeLength = EdgeLength;
1354 /* TODO: support for native non-power 2 */
1355 /* Precalculated scaling for 'faked' non power of two texture coords */
1356 object->pow2scalingFactor = ((float)EdgeLength) / ((float)pow2EdgeLength);
1358 /* Calculate levels for mip mapping */
1360 object->baseTexture.levels++;
1363 tmpW = max(1, tmpW >> 1);
1364 object->baseTexture.levels++;
1366 TRACE("Calculated levels = %d\n", object->baseTexture.levels);
1369 /* Generate all the surfaces */
1371 for (i = 0; i < object->baseTexture.levels; i++) {
1373 /* Create the 6 faces */
1374 for (j = 0; j < 6; j++) {
1376 hr=D3DCB_CreateSurface(This->parent, tmpW, tmpW, Format, Usage, Pool,
1377 i /* Level */, &object->surfaces[j][i],pSharedHandle);
1379 if(hr!= WINED3D_OK) {
1383 for (l = 0; l < j; l++) {
1384 IWineD3DSurface_Release(object->surfaces[j][i]);
1386 for (k = 0; k < i; k++) {
1387 for (l = 0; l < 6; l++) {
1388 IWineD3DSurface_Release(object->surfaces[l][j]);
1392 FIXME("(%p) Failed to create surface\n",object);
1393 HeapFree(GetProcessHeap(),0,object);
1394 *ppCubeTexture = NULL;
1397 IWineD3DSurface_SetContainer(object->surfaces[j][i], (IWineD3DBase *)object);
1398 TRACE("Created surface level %d @ %p,\n", i, object->surfaces[j][i]);
1400 tmpW = max(1, tmpW >> 1);
1403 TRACE("(%p) : Created Cube Texture %p\n", This, object);
1404 *ppCubeTexture = (IWineD3DCubeTexture *) object;
1408 static HRESULT WINAPI IWineD3DDeviceImpl_CreateQuery(IWineD3DDevice *iface, WINED3DQUERYTYPE Type, IWineD3DQuery **ppQuery, IUnknown* parent) {
1409 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
1410 IWineD3DQueryImpl *object; /*NOTE: impl ref allowed since this is a create function */
1412 if (NULL == ppQuery) {
1413 /* Just a check to see if we support this type of query */
1414 HRESULT hr = WINED3DERR_NOTAVAILABLE;
1416 case WINED3DQUERYTYPE_OCCLUSION:
1417 TRACE("(%p) occlusion query\n", This);
1418 if (GL_SUPPORT(ARB_OCCLUSION_QUERY))
1421 WARN("Unsupported in local OpenGL implementation: ARB_OCCLUSION_QUERY/NV_OCCLUSION_QUERY\n");
1423 case WINED3DQUERYTYPE_VCACHE:
1424 case WINED3DQUERYTYPE_RESOURCEMANAGER:
1425 case WINED3DQUERYTYPE_VERTEXSTATS:
1426 case WINED3DQUERYTYPE_EVENT:
1427 case WINED3DQUERYTYPE_TIMESTAMP:
1428 case WINED3DQUERYTYPE_TIMESTAMPDISJOINT:
1429 case WINED3DQUERYTYPE_TIMESTAMPFREQ:
1430 case WINED3DQUERYTYPE_PIPELINETIMINGS:
1431 case WINED3DQUERYTYPE_INTERFACETIMINGS:
1432 case WINED3DQUERYTYPE_VERTEXTIMINGS:
1433 case WINED3DQUERYTYPE_PIXELTIMINGS:
1434 case WINED3DQUERYTYPE_BANDWIDTHTIMINGS:
1435 case WINED3DQUERYTYPE_CACHEUTILIZATION:
1437 FIXME("(%p) Unhandled query type %d\n", This, Type);
1442 D3DCREATEOBJECTINSTANCE(object, Query)
1443 object->type = Type;
1444 /* allocated the 'extended' data based on the type of query requested */
1446 case WINED3DQUERYTYPE_OCCLUSION:
1447 if(GL_SUPPORT(ARB_OCCLUSION_QUERY)) {
1448 TRACE("(%p) Allocating data for an occlusion query\n", This);
1449 object->extendedData = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(WineQueryOcclusionData));
1450 GL_EXTCALL(glGenQueriesARB(1, &((WineQueryOcclusionData *)(object->extendedData))->queryId));
1453 case WINED3DQUERYTYPE_VCACHE:
1454 case WINED3DQUERYTYPE_RESOURCEMANAGER:
1455 case WINED3DQUERYTYPE_VERTEXSTATS:
1456 case WINED3DQUERYTYPE_EVENT:
1457 case WINED3DQUERYTYPE_TIMESTAMP:
1458 case WINED3DQUERYTYPE_TIMESTAMPDISJOINT:
1459 case WINED3DQUERYTYPE_TIMESTAMPFREQ:
1460 case WINED3DQUERYTYPE_PIPELINETIMINGS:
1461 case WINED3DQUERYTYPE_INTERFACETIMINGS:
1462 case WINED3DQUERYTYPE_VERTEXTIMINGS:
1463 case WINED3DQUERYTYPE_PIXELTIMINGS:
1464 case WINED3DQUERYTYPE_BANDWIDTHTIMINGS:
1465 case WINED3DQUERYTYPE_CACHEUTILIZATION:
1467 object->extendedData = 0;
1468 FIXME("(%p) Unhandled query type %d\n",This , Type);
1470 TRACE("(%p) : Created Query %p\n", This, object);
1474 /* example at http://www.fairyengine.com/articles/dxmultiviews.htm */
1475 static HRESULT WINAPI IWineD3DDeviceImpl_CreateAdditionalSwapChain(IWineD3DDevice* iface, WINED3DPRESENT_PARAMETERS* pPresentationParameters, IWineD3DSwapChain** ppSwapChain,
1477 D3DCB_CREATERENDERTARGETFN D3DCB_CreateRenderTarget,
1478 D3DCB_CREATEDEPTHSTENCILSURFACEFN D3DCB_CreateDepthStencil) {
1479 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
1482 IWineD3DSwapChainImpl *object; /** NOTE: impl ref allowed since this is a create function **/
1484 XVisualInfo template;
1485 GLXContext oldContext;
1486 Drawable oldDrawable;
1487 HRESULT hr = WINED3D_OK;
1489 TRACE("(%p) : Created Aditional Swap Chain\n", This);
1491 /** FIXME: Test under windows to find out what the life cycle of a swap chain is,
1492 * does a device hold a reference to a swap chain giving them a lifetime of the device
1493 * or does the swap chain notify the device of its destruction.
1494 *******************************/
1496 /* Check the params */
1497 if(*pPresentationParameters->BackBufferCount > D3DPRESENT_BACK_BUFFER_MAX) {
1498 ERR("App requested %d back buffers, this is not supported for now\n", *pPresentationParameters->BackBufferCount);
1499 return WINED3DERR_INVALIDCALL;
1500 } else if (*pPresentationParameters->BackBufferCount > 1) {
1501 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");
1504 D3DCREATEOBJECTINSTANCE(object, SwapChain)
1506 /*********************
1507 * Lookup the window Handle and the relating X window handle
1508 ********************/
1510 /* Setup hwnd we are using, plus which display this equates to */
1511 object->win_handle = *(pPresentationParameters->hDeviceWindow);
1512 if (!object->win_handle) {
1513 object->win_handle = This->createParms.hFocusWindow;
1516 object->win_handle = GetAncestor(object->win_handle, GA_ROOT);
1517 if ( !( object->win = (Window)GetPropA(object->win_handle, "__wine_x11_whole_window") ) ) {
1518 ERR("Can't get drawable (window), HWND:%p doesn't have the property __wine_x11_whole_window\n", object->win_handle);
1519 return WINED3DERR_NOTAVAILABLE;
1521 hDc = GetDC(object->win_handle);
1522 object->display = get_display(hDc);
1523 ReleaseDC(object->win_handle, hDc);
1524 TRACE("Using a display of %p %p\n", object->display, hDc);
1526 if (NULL == object->display || NULL == hDc) {
1527 WARN("Failed to get a display and HDc for Window %p\n", object->win_handle);
1528 return WINED3DERR_NOTAVAILABLE;
1531 if (object->win == 0) {
1532 WARN("Failed to get a valid XVisuial ID for the window %p\n", object->win_handle);
1533 return WINED3DERR_NOTAVAILABLE;
1536 * Create an opengl context for the display visual
1537 * NOTE: the visual is chosen as the window is created and the glcontext cannot
1538 * use different properties after that point in time. FIXME: How to handle when requested format
1539 * doesn't match actual visual? Cannot choose one here - code removed as it ONLY works if the one
1540 * it chooses is identical to the one already being used!
1541 **********************************/
1543 /** FIXME: Handle stencil appropriately via EnableAutoDepthStencil / AutoDepthStencilFormat **/
1546 /* Create a new context for this swapchain */
1547 template.visualid = (VisualID)GetPropA(GetDesktopWindow(), "__wine_x11_visual_id");
1548 /* TODO: change this to find a similar visual, but one with a stencil/zbuffer buffer that matches the request
1549 (or the best possible if none is requested) */
1550 TRACE("Found x visual ID : %ld\n", template.visualid);
1552 object->visInfo = XGetVisualInfo(object->display, VisualIDMask, &template, &num);
1553 if (NULL == object->visInfo) {
1554 ERR("cannot really get XVisual\n");
1556 return WINED3DERR_NOTAVAILABLE;
1559 /* Write out some debug info about the visual/s */
1560 TRACE("Using x visual ID : %ld\n", template.visualid);
1561 TRACE(" visual info: %p\n", object->visInfo);
1562 TRACE(" num items : %d\n", num);
1563 for (n = 0;n < num; n++) {
1564 TRACE("=====item=====: %d\n", n + 1);
1565 TRACE(" visualid : %ld\n", object->visInfo[n].visualid);
1566 TRACE(" screen : %d\n", object->visInfo[n].screen);
1567 TRACE(" depth : %u\n", object->visInfo[n].depth);
1568 TRACE(" class : %d\n", object->visInfo[n].class);
1569 TRACE(" red_mask : %ld\n", object->visInfo[n].red_mask);
1570 TRACE(" green_mask : %ld\n", object->visInfo[n].green_mask);
1571 TRACE(" blue_mask : %ld\n", object->visInfo[n].blue_mask);
1572 TRACE(" colormap_size : %d\n", object->visInfo[n].colormap_size);
1573 TRACE(" bits_per_rgb : %d\n", object->visInfo[n].bits_per_rgb);
1574 /* log some extra glx info */
1575 glXGetConfig(object->display, object->visInfo, GLX_AUX_BUFFERS, &value);
1576 TRACE(" gl_aux_buffers : %d\n", value);
1577 glXGetConfig(object->display, object->visInfo, GLX_BUFFER_SIZE ,&value);
1578 TRACE(" gl_buffer_size : %d\n", value);
1579 glXGetConfig(object->display, object->visInfo, GLX_RED_SIZE, &value);
1580 TRACE(" gl_red_size : %d\n", value);
1581 glXGetConfig(object->display, object->visInfo, GLX_GREEN_SIZE, &value);
1582 TRACE(" gl_green_size : %d\n", value);
1583 glXGetConfig(object->display, object->visInfo, GLX_BLUE_SIZE, &value);
1584 TRACE(" gl_blue_size : %d\n", value);
1585 glXGetConfig(object->display, object->visInfo, GLX_ALPHA_SIZE, &value);
1586 TRACE(" gl_alpha_size : %d\n", value);
1587 glXGetConfig(object->display, object->visInfo, GLX_DEPTH_SIZE ,&value);
1588 TRACE(" gl_depth_size : %d\n", value);
1589 glXGetConfig(object->display, object->visInfo, GLX_STENCIL_SIZE, &value);
1590 TRACE(" gl_stencil_size : %d\n", value);
1592 /* Now choose a similar visual ID*/
1594 #ifdef USE_CONTEXT_MANAGER
1596 /** TODO: use a context mamager **/
1600 IWineD3DSwapChain *implSwapChain;
1601 if (WINED3D_OK != IWineD3DDevice_GetSwapChain(iface, 0, &implSwapChain)) {
1602 /* The first time around we create the context that is shared with all other swapchains and render targets */
1603 object->glCtx = glXCreateContext(object->display, object->visInfo, NULL, GL_TRUE);
1604 TRACE("Creating implicit context for vis %p, hwnd %p\n", object->display, object->visInfo);
1607 TRACE("Creating context for vis %p, hwnd %p\n", object->display, object->visInfo);
1608 /* TODO: don't use Impl structures outside of create functions! (a context manager will replace the ->glCtx) */
1609 /* and create a new context with the implicit swapchains context as the shared context */
1610 object->glCtx = glXCreateContext(object->display, object->visInfo, ((IWineD3DSwapChainImpl *)implSwapChain)->glCtx, GL_TRUE);
1611 IWineD3DSwapChain_Release(implSwapChain);
1616 XFree(object->visInfo);
1617 object->visInfo = NULL;
1621 if (!object->glCtx) {
1622 ERR("Failed to create GLX context\n");
1623 return WINED3DERR_NOTAVAILABLE;
1625 TRACE("Context created (HWND=%p, glContext=%p, Window=%ld, VisInfo=%p)\n",
1626 object->win_handle, object->glCtx, object->win, object->visInfo);
1629 /*********************
1630 * Windowed / Fullscreen
1631 *******************/
1634 * TODO: MSDN says that we are only allowed one fullscreen swapchain per device,
1635 * so we should really check to see if there is a fullscreen swapchain already
1636 * I think Windows and X have different ideas about fullscreen, does a single head count as full screen?
1637 **************************************/
1639 if (!*(pPresentationParameters->Windowed)) {
1645 /* Get info on the current display setup */
1646 hdc = CreateDCA("DISPLAY", NULL, NULL, NULL);
1647 bpp = GetDeviceCaps(hdc, BITSPIXEL);
1650 /* Change the display settings */
1651 memset(&devmode, 0, sizeof(DEVMODEW));
1652 devmode.dmFields = DM_BITSPERPEL | DM_PELSWIDTH | DM_PELSHEIGHT;
1653 devmode.dmBitsPerPel = (bpp >= 24) ? 32 : bpp; /* Stupid XVidMode cannot change bpp */
1654 devmode.dmPelsWidth = *(pPresentationParameters->BackBufferWidth);
1655 devmode.dmPelsHeight = *(pPresentationParameters->BackBufferHeight);
1656 MultiByteToWideChar(CP_ACP, 0, "Gamers CG", -1, devmode.dmDeviceName, CCHDEVICENAME);
1657 ChangeDisplaySettingsExW(devmode.dmDeviceName, &devmode, object->win_handle, CDS_FULLSCREEN, NULL);
1659 /* Make popup window */
1660 SetWindowLongA(object->win_handle, GWL_STYLE, WS_POPUP);
1661 SetWindowPos(object->win_handle, HWND_TOP, 0, 0,
1662 *(pPresentationParameters->BackBufferWidth),
1663 *(pPresentationParameters->BackBufferHeight), SWP_SHOWWINDOW | SWP_FRAMECHANGED);
1665 /* For GetDisplayMode */
1666 This->ddraw_width = devmode.dmPelsWidth;
1667 This->ddraw_height = devmode.dmPelsHeight;
1668 This->ddraw_format = *(pPresentationParameters->BackBufferFormat);
1672 /** MSDN: If Windowed is TRUE and either of the BackBufferWidth/Height values is zero,
1673 * then the corresponding dimension of the client area of the hDeviceWindow
1674 * (or the focus window, if hDeviceWindow is NULL) is taken.
1675 **********************/
1677 if (*(pPresentationParameters->Windowed) &&
1678 ((*(pPresentationParameters->BackBufferWidth) == 0) ||
1679 (*(pPresentationParameters->BackBufferHeight) == 0))) {
1682 GetClientRect(object->win_handle, &Rect);
1684 if (*(pPresentationParameters->BackBufferWidth) == 0) {
1685 *(pPresentationParameters->BackBufferWidth) = Rect.right;
1686 TRACE("Updating width to %d\n", *(pPresentationParameters->BackBufferWidth));
1688 if (*(pPresentationParameters->BackBufferHeight) == 0) {
1689 *(pPresentationParameters->BackBufferHeight) = Rect.bottom;
1690 TRACE("Updating height to %d\n", *(pPresentationParameters->BackBufferHeight));
1694 /*********************
1695 * finish off parameter initialization
1696 *******************/
1698 /* Put the correct figures in the presentation parameters */
1699 TRACE("Copying across presentation parameters\n");
1700 object->presentParms.BackBufferWidth = *(pPresentationParameters->BackBufferWidth);
1701 object->presentParms.BackBufferHeight = *(pPresentationParameters->BackBufferHeight);
1702 object->presentParms.BackBufferFormat = *(pPresentationParameters->BackBufferFormat);
1703 object->presentParms.BackBufferCount = *(pPresentationParameters->BackBufferCount);
1704 object->presentParms.MultiSampleType = *(pPresentationParameters->MultiSampleType);
1705 object->presentParms.MultiSampleQuality = NULL == pPresentationParameters->MultiSampleQuality ? 0 : *(pPresentationParameters->MultiSampleQuality);
1706 object->presentParms.SwapEffect = *(pPresentationParameters->SwapEffect);
1707 object->presentParms.hDeviceWindow = *(pPresentationParameters->hDeviceWindow);
1708 object->presentParms.Windowed = *(pPresentationParameters->Windowed);
1709 object->presentParms.EnableAutoDepthStencil = *(pPresentationParameters->EnableAutoDepthStencil);
1710 object->presentParms.AutoDepthStencilFormat = *(pPresentationParameters->AutoDepthStencilFormat);
1711 object->presentParms.Flags = *(pPresentationParameters->Flags);
1712 object->presentParms.FullScreen_RefreshRateInHz = *(pPresentationParameters->FullScreen_RefreshRateInHz);
1713 object->presentParms.PresentationInterval = *(pPresentationParameters->PresentationInterval);
1716 /*********************
1717 * Create the back, front and stencil buffers
1718 *******************/
1720 TRACE("calling rendertarget CB\n");
1721 hr = D3DCB_CreateRenderTarget((IUnknown *) This->parent,
1722 object->presentParms.BackBufferWidth,
1723 object->presentParms.BackBufferHeight,
1724 object->presentParms.BackBufferFormat,
1725 object->presentParms.MultiSampleType,
1726 object->presentParms.MultiSampleQuality,
1727 TRUE /* Lockable */,
1728 &object->frontBuffer,
1729 NULL /* pShared (always null)*/);
1730 if (object->frontBuffer != NULL)
1731 IWineD3DSurface_SetContainer(object->frontBuffer, (IWineD3DBase *)object);
1733 if(object->presentParms.BackBufferCount > 0) {
1736 object->backBuffer = HeapAlloc(GetProcessHeap(), 0, sizeof(IWineD3DSurface *) * object->presentParms.BackBufferCount);
1737 if(!object->backBuffer) {
1738 ERR("Out of memory\n");
1740 if (object->frontBuffer) {
1741 IUnknown *bufferParent;
1742 IWineD3DSurface_GetParent(object->frontBuffer, &bufferParent);
1743 IUnknown_Release(bufferParent); /* once for the get parent */
1744 if (IUnknown_Release(bufferParent) > 0) {
1745 FIXME("(%p) Something's still holding the front buffer\n",This);
1748 HeapFree(GetProcessHeap(), 0, object);
1749 return E_OUTOFMEMORY;
1752 for(i = 0; i < object->presentParms.BackBufferCount; i++) {
1753 TRACE("calling rendertarget CB\n");
1754 hr = D3DCB_CreateRenderTarget((IUnknown *) This->parent,
1755 object->presentParms.BackBufferWidth,
1756 object->presentParms.BackBufferHeight,
1757 object->presentParms.BackBufferFormat,
1758 object->presentParms.MultiSampleType,
1759 object->presentParms.MultiSampleQuality,
1760 TRUE /* Lockable */,
1761 &object->backBuffer[i],
1762 NULL /* pShared (always null)*/);
1763 if(hr == WINED3D_OK && object->backBuffer[i]) {
1764 IWineD3DSurface_SetContainer(object->backBuffer[i], (IWineD3DBase *)object);
1770 object->backBuffer = NULL;
1773 if (object->backBuffer != NULL) {
1775 glDrawBuffer(GL_BACK);
1776 checkGLcall("glDrawBuffer(GL_BACK)");
1779 /* Single buffering - draw to front buffer */
1781 glDrawBuffer(GL_FRONT);
1782 checkGLcall("glDrawBuffer(GL_FRONT)");
1786 /* Under directX swapchains share the depth stencil, so only create one depth-stencil */
1787 if (*(pPresentationParameters->EnableAutoDepthStencil) && hr == WINED3D_OK) {
1788 TRACE("Creating depth stencil buffer\n");
1789 if (This->depthStencilBuffer == NULL ) {
1790 hr = D3DCB_CreateDepthStencil((IUnknown *) This->parent,
1791 object->presentParms.BackBufferWidth,
1792 object->presentParms.BackBufferHeight,
1793 object->presentParms.AutoDepthStencilFormat,
1794 object->presentParms.MultiSampleType,
1795 object->presentParms.MultiSampleQuality,
1796 FALSE /* FIXME: Discard */,
1797 &This->depthStencilBuffer,
1798 NULL /* pShared (always null)*/ );
1799 if (This->depthStencilBuffer != NULL)
1800 IWineD3DSurface_SetContainer(This->depthStencilBuffer, 0);
1803 /** TODO: A check on width, height and multisample types
1804 *(since the zbuffer must be at least as large as the render target and have the same multisample parameters)
1805 ****************************/
1806 object->wantsDepthStencilBuffer = TRUE;
1808 object->wantsDepthStencilBuffer = FALSE;
1811 TRACE("FrontBuf @ %p, BackBuf @ %p, DepthStencil %d\n",object->frontBuffer, object->backBuffer ? object->backBuffer[0] : NULL, object->wantsDepthStencilBuffer);
1814 /*********************
1815 * init the default renderTarget management
1816 *******************/
1817 object->drawable = object->win;
1818 object->render_ctx = object->glCtx;
1820 if (hr == WINED3D_OK) {
1821 /*********************
1822 * Setup some defaults and clear down the buffers
1823 *******************/
1825 /** save current context and drawable **/
1826 oldContext = glXGetCurrentContext();
1827 oldDrawable = glXGetCurrentDrawable();
1829 TRACE("Activating context (display %p context %p drawable %ld)!\n", object->display, object->glCtx, object->win);
1830 if (glXMakeCurrent(object->display, object->win, object->glCtx) == False) {
1831 ERR("Error in setting current context (display %p context %p drawable %ld)!\n", object->display, object->glCtx, object->win);
1833 checkGLcall("glXMakeCurrent");
1835 TRACE("Setting up the screen\n");
1836 /* Clear the screen */
1837 glClearColor(1.0, 0.0, 0.0, 0.0);
1838 checkGLcall("glClearColor");
1841 glClearStencil(0xffff);
1843 checkGLcall("glClear");
1845 glColor3f(1.0, 1.0, 1.0);
1846 checkGLcall("glColor3f");
1848 glEnable(GL_LIGHTING);
1849 checkGLcall("glEnable");
1851 glLightModeli(GL_LIGHT_MODEL_LOCAL_VIEWER, GL_TRUE);
1852 checkGLcall("glLightModeli(GL_LIGHT_MODEL_LOCAL_VIEWER, GL_TRUE);");
1854 glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE_EXT);
1855 checkGLcall("glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE_EXT);");
1857 glLightModeli(GL_LIGHT_MODEL_COLOR_CONTROL, GL_SEPARATE_SPECULAR_COLOR);
1858 checkGLcall("glLightModeli(GL_LIGHT_MODEL_COLOR_CONTROL, GL_SEPARATE_SPECULAR_COLOR);");
1860 /* switch back to the original context (if there was one)*/
1861 if (This->swapchains) {
1862 /** TODO: restore the context and drawable **/
1863 glXMakeCurrent(object->display, oldDrawable, oldContext);
1866 /* Set the surface alignment. This never changes, so we are safe to set it once per context*/
1867 glPixelStorei(GL_PACK_ALIGNMENT, SURFACE_ALIGNMENT);
1868 checkGLcall("glPixelStorei(GL_PACK_ALIGNMENT, SURFACE_ALIGNMENT);");
1869 glPixelStorei(GL_UNPACK_ALIGNMENT, SURFACE_ALIGNMENT);
1870 checkGLcall("glPixelStorei(GL_UNPACK_ALIGNMENT, SURFACE_ALIGNMENT);");
1874 TRACE("Set swapchain to %p\n", object);
1875 } else { /* something went wrong so clean up */
1876 IUnknown* bufferParent;
1877 if (object->frontBuffer) {
1879 IWineD3DSurface_GetParent(object->frontBuffer, &bufferParent);
1880 IUnknown_Release(bufferParent); /* once for the get parent */
1881 if (IUnknown_Release(bufferParent) > 0) {
1882 FIXME("(%p) Something's still holding the front buffer\n",This);
1885 if (object->backBuffer) {
1887 for(i = 0; i < object->presentParms.BackBufferCount; i++) {
1888 if(object->backBuffer[i]) {
1889 IWineD3DSurface_GetParent(object->backBuffer[i], &bufferParent);
1890 IUnknown_Release(bufferParent); /* once for the get parent */
1891 if (IUnknown_Release(bufferParent) > 0) {
1892 FIXME("(%p) Something's still holding the back buffer\n",This);
1896 HeapFree(GetProcessHeap(), 0, object->backBuffer);
1897 object->backBuffer = NULL;
1899 /* NOTE: don't clean up the depthstencil buffer because it belongs to the device */
1900 /* Clean up the context */
1901 /* check that we are the current context first (we shouldn't be though!) */
1902 if (object->glCtx != 0) {
1903 if(glXGetCurrentContext() == object->glCtx) {
1904 glXMakeCurrent(object->display, None, NULL);
1906 glXDestroyContext(object->display, object->glCtx);
1908 HeapFree(GetProcessHeap(), 0, object);
1915 /** NOTE: These are ahead of the other getters and setters to save using a forward declaration **/
1916 static UINT WINAPI IWineD3DDeviceImpl_GetNumberOfSwapChains(IWineD3DDevice *iface) {
1917 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
1918 TRACE("(%p)\n", This);
1920 return This->NumberOfSwapChains;
1923 static HRESULT WINAPI IWineD3DDeviceImpl_GetSwapChain(IWineD3DDevice *iface, UINT iSwapChain, IWineD3DSwapChain **pSwapChain) {
1924 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
1925 TRACE("(%p) : swapchain %d\n", This, iSwapChain);
1927 if(iSwapChain < This->NumberOfSwapChains) {
1928 *pSwapChain = This->swapchains[iSwapChain];
1929 IWineD3DSwapChain_AddRef(*pSwapChain);
1930 TRACE("(%p) returning %p\n", This, *pSwapChain);
1933 TRACE("Swapchain out of range\n");
1935 return WINED3DERR_INVALIDCALL;
1940 * Vertex Declaration
1942 static HRESULT WINAPI IWineD3DDeviceImpl_CreateVertexDeclaration(IWineD3DDevice* iface, CONST VOID* pDeclaration, IWineD3DVertexDeclaration** ppVertexDeclaration, IUnknown *parent) {
1943 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
1944 IWineD3DVertexDeclarationImpl *object = NULL;
1945 HRESULT hr = WINED3D_OK;
1946 TRACE("(%p) : directXVersion=%u, pFunction=%p, ppDecl=%p\n", This, ((IWineD3DImpl *)This->wineD3D)->dxVersion, pDeclaration, ppVertexDeclaration);
1947 D3DCREATEOBJECTINSTANCE(object, VertexDeclaration)
1950 hr = IWineD3DVertexDeclaration_SetDeclaration((IWineD3DVertexDeclaration *)object, (void *)pDeclaration);
1955 /* http://msdn.microsoft.com/archive/default.asp?url=/archive/en-us/directx9_c/directx/graphics/programmingguide/programmable/vertexshaders/vscreate.asp */
1956 static HRESULT WINAPI IWineD3DDeviceImpl_CreateVertexShader(IWineD3DDevice *iface, CONST DWORD *pDeclaration, CONST DWORD *pFunction, IWineD3DVertexShader **ppVertexShader, IUnknown *parent) {
1957 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
1958 IWineD3DVertexShaderImpl *object; /* NOTE: impl usage is ok, this is a create */
1959 HRESULT hr = WINED3D_OK;
1960 D3DCREATESHADEROBJECTINSTANCE(object, VertexShader)
1961 object->baseShader.shader_ins = IWineD3DVertexShaderImpl_shader_ins;
1963 TRACE("(%p) : Created Vertex shader %p\n", This, *ppVertexShader);
1965 /* If a vertex declaration has been passed, save it to the vertex shader, this affects d3d8 only. */
1966 /* Further it needs to be set before calling SetFunction as SetFunction needs the declaration. */
1967 if (pDeclaration != NULL) {
1968 IWineD3DVertexDeclaration *vertexDeclaration;
1969 hr = IWineD3DDevice_CreateVertexDeclaration(iface, pDeclaration, &vertexDeclaration ,NULL);
1970 if (WINED3D_OK == hr) {
1971 TRACE("(%p) : Setting vertex declaration to %p\n", This, vertexDeclaration);
1972 object->vertexDeclaration = vertexDeclaration;
1974 FIXME("(%p) : Failed to set the declaration, returning WINED3DERR_INVALIDCALL\n", iface);
1975 IWineD3DVertexShader_Release(*ppVertexShader);
1976 return WINED3DERR_INVALIDCALL;
1980 hr = IWineD3DVertexShader_SetFunction(*ppVertexShader, pFunction);
1982 if (WINED3D_OK != hr) {
1983 FIXME("(%p) : Failed to set the function, returning WINED3DERR_INVALIDCALL\n", iface);
1984 IWineD3DVertexShader_Release(*ppVertexShader);
1985 return WINED3DERR_INVALIDCALL;
1988 #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. */
1989 if(Usage == WINED3DUSAGE_SOFTWAREVERTEXPROCESSING) {
2000 static HRESULT WINAPI IWineD3DDeviceImpl_CreatePixelShader(IWineD3DDevice *iface, CONST DWORD *pFunction, IWineD3DPixelShader **ppPixelShader, IUnknown *parent) {
2001 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2002 IWineD3DPixelShaderImpl *object; /* NOTE: impl allowed, this is a create */
2003 HRESULT hr = WINED3D_OK;
2005 D3DCREATESHADEROBJECTINSTANCE(object, PixelShader)
2006 object->baseShader.shader_ins = IWineD3DPixelShaderImpl_shader_ins;
2007 hr = IWineD3DPixelShader_SetFunction(*ppPixelShader, pFunction);
2008 if (WINED3D_OK == hr) {
2009 TRACE("(%p) : Created Pixel shader %p\n", This, *ppPixelShader);
2011 WARN("(%p) : Failed to create pixel shader\n", This);
2017 static HRESULT WINAPI IWineD3DDeviceImpl_CreatePalette(IWineD3DDevice *iface, DWORD Flags, PALETTEENTRY *PalEnt, IWineD3DPalette **Palette, IUnknown *Parent) {
2018 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *) iface;
2019 IWineD3DPaletteImpl *object;
2021 TRACE("(%p)->(%x, %p, %p, %p)\n", This, Flags, PalEnt, Palette, Parent);
2023 /* Create the new object */
2024 object = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(IWineD3DPaletteImpl));
2026 ERR("Out of memory when allocating memory for a IWineD3DPalette implementation\n");
2027 return E_OUTOFMEMORY;
2030 object->lpVtbl = &IWineD3DPalette_Vtbl;
2032 object->Flags = Flags;
2033 object->parent = Parent;
2034 object->wineD3DDevice = This;
2035 object->palNumEntries = IWineD3DPaletteImpl_Size(Flags);
2037 object->hpal = CreatePalette((const LOGPALETTE*)&(object->palVersion));
2040 HeapFree( GetProcessHeap(), 0, object);
2041 return E_OUTOFMEMORY;
2044 hr = IWineD3DPalette_SetEntries((IWineD3DPalette *) object, 0, 0, IWineD3DPaletteImpl_Size(Flags), PalEnt);
2046 IWineD3DPalette_Release((IWineD3DPalette *) object);
2050 *Palette = (IWineD3DPalette *) object;
2055 static HRESULT WINAPI IWineD3DDeviceImpl_Init3D(IWineD3DDevice *iface, WINED3DPRESENT_PARAMETERS* pPresentationParameters, D3DCB_CREATEADDITIONALSWAPCHAIN D3DCB_CreateAdditionalSwapChain) {
2056 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *) iface;
2057 IWineD3DSwapChainImpl *swapchain;
2059 TRACE("(%p)->(%p,%p)\n", This, pPresentationParameters, D3DCB_CreateAdditionalSwapChain);
2060 if(This->d3d_initialized) return WINED3DERR_INVALIDCALL;
2062 /* TODO: Test if OpenGL is compiled in and loaded */
2064 /* Setup the implicit swapchain */
2065 TRACE("Creating implicit swapchain\n");
2066 if (D3D_OK != D3DCB_CreateAdditionalSwapChain((IUnknown *) This->parent, pPresentationParameters, (IWineD3DSwapChain **)&swapchain) || swapchain == NULL) {
2067 WARN("Failed to create implicit swapchain\n");
2068 return WINED3DERR_INVALIDCALL;
2071 This->NumberOfSwapChains = 1;
2072 This->swapchains = HeapAlloc(GetProcessHeap(), 0, This->NumberOfSwapChains * sizeof(IWineD3DSwapChain *));
2073 if(!This->swapchains) {
2074 ERR("Out of memory!\n");
2075 IWineD3DSwapChain_Release( (IWineD3DSwapChain *) swapchain);
2076 return E_OUTOFMEMORY;
2078 This->swapchains[0] = (IWineD3DSwapChain *) swapchain;
2080 if(swapchain->backBuffer && swapchain->backBuffer[0]) {
2081 TRACE("Setting rendertarget to %p\n", swapchain->backBuffer);
2082 This->renderTarget = swapchain->backBuffer[0];
2085 TRACE("Setting rendertarget to %p\n", swapchain->frontBuffer);
2086 This->renderTarget = swapchain->frontBuffer;
2088 IWineD3DSurface_AddRef(This->renderTarget);
2089 /* Depth Stencil support */
2090 This->stencilBufferTarget = This->depthStencilBuffer;
2091 if (NULL != This->stencilBufferTarget) {
2092 IWineD3DSurface_AddRef(This->stencilBufferTarget);
2095 /* Set up some starting GL setup */
2098 * Initialize openGL extension related variables
2099 * with Default values
2102 ((IWineD3DImpl *) This->wineD3D)->isGLInfoValid = IWineD3DImpl_FillGLCaps( This->wineD3D, swapchain->display);
2103 /* Setup all the devices defaults */
2104 IWineD3DStateBlock_InitStartupStateBlock((IWineD3DStateBlock *)This->stateBlock);
2106 IWineD3DImpl_CheckGraphicsMemory();
2110 /* Initialize our list of GLSL programs */
2111 list_init(&This->glsl_shader_progs);
2113 { /* Set a default viewport */
2117 vp.Width = *(pPresentationParameters->BackBufferWidth);
2118 vp.Height = *(pPresentationParameters->BackBufferHeight);
2121 IWineD3DDevice_SetViewport((IWineD3DDevice *)This, &vp);
2124 /* Initialize the current view state */
2125 This->modelview_valid = 1;
2126 This->proj_valid = 0;
2127 This->view_ident = 1;
2128 This->last_was_rhw = 0;
2129 glGetIntegerv(GL_MAX_LIGHTS, &This->maxConcurrentLights);
2130 TRACE("(%p) All defaults now set up, leaving Init3D with %p\n", This, This);
2132 /* Clear the screen */
2133 IWineD3DDevice_Clear((IWineD3DDevice *) This, 0, NULL, WINED3DCLEAR_STENCIL|WINED3DCLEAR_ZBUFFER|WINED3DCLEAR_TARGET, 0x00, 1.0, 0);
2135 This->d3d_initialized = TRUE;
2139 static HRESULT WINAPI IWineD3DDeviceImpl_Uninit3D(IWineD3DDevice *iface) {
2140 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *) iface;
2142 IUnknown* stencilBufferParent;
2143 IUnknown* swapChainParent;
2145 TRACE("(%p)\n", This);
2147 if(!This->d3d_initialized) return WINED3DERR_INVALIDCALL;
2149 /* Delete the mouse cursor texture */
2150 if(This->cursorTexture) {
2152 glDeleteTextures(1, &This->cursorTexture);
2154 This->cursorTexture = 0;
2157 for(sampler = 0; sampler < GL_LIMITS(sampler_stages); ++sampler) {
2158 IWineD3DDevice_SetTexture(iface, sampler, NULL);
2161 /* Release the buffers (with sanity checks)*/
2162 TRACE("Releasing the depth stencil buffer at %p\n", This->stencilBufferTarget);
2163 if(This->stencilBufferTarget != NULL && (IWineD3DSurface_Release(This->stencilBufferTarget) >0)){
2164 if(This->depthStencilBuffer != This->stencilBufferTarget)
2165 FIXME("(%p) Something's still holding the depthStencilBuffer\n",This);
2167 This->stencilBufferTarget = NULL;
2169 TRACE("Releasing the render target at %p\n", This->renderTarget);
2170 if(IWineD3DSurface_Release(This->renderTarget) >0){
2171 /* This check is a bit silly, itshould be in swapchain_release FIXME("(%p) Something's still holding the renderTarget\n",This); */
2173 TRACE("Setting rendertarget to NULL\n");
2174 This->renderTarget = NULL;
2176 if (This->depthStencilBuffer) {
2177 IWineD3DSurface_GetParent(This->depthStencilBuffer, &stencilBufferParent);
2178 IUnknown_Release(stencilBufferParent); /* once for the get parent */
2179 if(IUnknown_Release(stencilBufferParent) >0){ /* the second time for when it was created */
2180 FIXME("(%p) Something's still holding the depthStencilBuffer\n",This);
2182 This->depthStencilBuffer = NULL;
2185 for(i=0; i < This->NumberOfSwapChains; i++) {
2186 TRACE("Releasing the implicit swapchain %d\n", i);
2187 /* Swapchain 0 is special because it's created in startup with a hanging parent, so we have to release its parent now */
2188 IWineD3DSwapChain_GetParent(This->swapchains[i], &swapChainParent);
2189 IUnknown_Release(swapChainParent); /* once for the get parent */
2190 if (IUnknown_Release(swapChainParent) > 0) { /* the second time for when it was created */
2191 FIXME("(%p) Something's still holding the implicit swapchain\n", This);
2195 HeapFree(GetProcessHeap(), 0, This->swapchains);
2196 This->swapchains = NULL;
2197 This->NumberOfSwapChains = 0;
2199 This->d3d_initialized = FALSE;
2203 static void WINAPI IWineD3DDeviceImpl_SetFullscreen(IWineD3DDevice *iface, BOOL fullscreen) {
2204 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *) iface;
2205 TRACE("(%p) Setting DDraw fullscreen mode to %s\n", This, fullscreen ? "true" : "false");
2207 /* DirectDraw apps can change between fullscreen and windowed mode after device creation with
2208 * IDirectDraw7::SetCooperativeLevel. The GDI surface implementation needs to know this.
2209 * DDraw doesn't necessarily have a swapchain, so we have to store the fullscreen flag
2212 This->ddraw_fullscreen = fullscreen;
2215 static HRESULT WINAPI IWineD3DDeviceImpl_EnumDisplayModes(IWineD3DDevice *iface, DWORD Flags, UINT Width, UINT Height, WINED3DFORMAT pixelformat, LPVOID context, D3DCB_ENUMDISPLAYMODESCALLBACK callback) {
2216 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2220 const PixelFormatDesc *formatDesc = getFormatDescEntry(pixelformat);
2222 TRACE("(%p)->(%x,%d,%d,%d,%p,%p)\n", This, Flags, Width, Height, pixelformat, context, callback);
2224 for (i = 0; EnumDisplaySettingsExW(NULL, i, &DevModeW, 0); i++) {
2225 /* Ignore some modes if a description was passed */
2226 if ( (Width > 0) && (Width != DevModeW.dmPelsWidth)) continue;
2227 if ( (Height > 0) && (Height != DevModeW.dmPelsHeight)) continue;
2228 if ( (pixelformat != WINED3DFMT_UNKNOWN) && ( formatDesc->bpp != DevModeW.dmBitsPerPel) ) continue;
2230 TRACE("Enumerating %dx%d@%s\n", DevModeW.dmPelsWidth, DevModeW.dmPelsHeight, debug_d3dformat(pixelformat_for_depth(DevModeW.dmBitsPerPel)));
2232 if (callback((IUnknown *) This, (UINT) DevModeW.dmPelsWidth, (UINT) DevModeW.dmPelsHeight, pixelformat_for_depth(DevModeW.dmBitsPerPel), 60.0, context) == DDENUMRET_CANCEL)
2239 static HRESULT WINAPI IWineD3DDeviceImpl_SetDisplayMode(IWineD3DDevice *iface, UINT iSwapChain, WINED3DDISPLAYMODE* pMode) {
2241 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2243 const PixelFormatDesc *formatDesc = getFormatDescEntry(pMode->Format);
2245 TRACE("(%p)->(%d,%p) Mode=%dx%dx@%d, %s\n", This, iSwapChain, pMode, pMode->Width, pMode->Height, pMode->RefreshRate, debug_d3dformat(pMode->Format));
2247 /* Resize the screen even without a window:
2248 * The app could have unset it with SetCooperativeLevel, but not called
2249 * RestoreDisplayMode first. Then the release will call RestoreDisplayMode,
2250 * but we don't have any hwnd
2253 devmode.dmFields = DM_BITSPERPEL | DM_PELSWIDTH | DM_PELSHEIGHT;
2254 devmode.dmBitsPerPel = formatDesc->bpp * 8;
2255 if(devmode.dmBitsPerPel == 24) devmode.dmBitsPerPel = 32;
2256 devmode.dmPelsWidth = pMode->Width;
2257 devmode.dmPelsHeight = pMode->Height;
2259 devmode.dmDisplayFrequency = pMode->RefreshRate;
2260 if (pMode->RefreshRate != 0) {
2261 devmode.dmFields |= DM_DISPLAYFREQUENCY;
2264 /* Only change the mode if necessary */
2265 if( (This->ddraw_width == pMode->Width) &&
2266 (This->ddraw_height == pMode->Height) &&
2267 (This->ddraw_format == pMode->Format) &&
2268 (pMode->RefreshRate == 0) ) {
2272 ret = ChangeDisplaySettingsExW(NULL, &devmode, NULL, CDS_FULLSCREEN, NULL);
2273 if (ret != DISP_CHANGE_SUCCESSFUL) {
2274 if(devmode.dmDisplayFrequency != 0) {
2275 WARN("ChangeDisplaySettingsExW failed, trying without the refresh rate\n");
2276 devmode.dmFields &= ~DM_DISPLAYFREQUENCY;
2277 devmode.dmDisplayFrequency = 0;
2278 ret = ChangeDisplaySettingsExW(NULL, &devmode, NULL, CDS_FULLSCREEN, NULL) != DISP_CHANGE_SUCCESSFUL;
2280 if(ret != DISP_CHANGE_SUCCESSFUL) {
2281 return DDERR_INVALIDMODE;
2285 /* Store the new values */
2286 This->ddraw_width = pMode->Width;
2287 This->ddraw_height = pMode->Height;
2288 This->ddraw_format = pMode->Format;
2290 /* Only do this with a window of course */
2291 if(This->ddraw_window)
2292 MoveWindow(This->ddraw_window, 0, 0, pMode->Width, pMode->Height, TRUE);
2297 static HRESULT WINAPI IWineD3DDeviceImpl_GetDirect3D(IWineD3DDevice *iface, IWineD3D **ppD3D) {
2298 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2299 *ppD3D= This->wineD3D;
2300 TRACE("(%p) : wineD3D returning %p\n", This, *ppD3D);
2301 IWineD3D_AddRef(*ppD3D);
2305 static UINT WINAPI IWineD3DDeviceImpl_GetAvailableTextureMem(IWineD3DDevice *iface) {
2306 /** NOTE: There's a probably a hack-around for this one by putting as many pbuffers, VBOs (or whatever)
2307 * into the video ram as possible and seeing how many fit
2308 * you can also get the correct initial value from nvidia and ATI's driver via X
2309 * texture memory is video memory + AGP memory
2310 *******************/
2311 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2312 static BOOL showfixmes = TRUE;
2314 FIXME("(%p) : stub, simulating %dMB for now, returning %dMB left\n", This,
2315 (wined3d_settings.emulated_textureram/(1024*1024)),
2316 ((wined3d_settings.emulated_textureram - wineD3DGlobalStatistics->glsurfaceram) / (1024*1024)));
2319 TRACE("(%p) : simulating %dMB, returning %dMB left\n", This,
2320 (wined3d_settings.emulated_textureram/(1024*1024)),
2321 ((wined3d_settings.emulated_textureram - wineD3DGlobalStatistics->glsurfaceram) / (1024*1024)));
2322 /* return simulated texture memory left */
2323 return (wined3d_settings.emulated_textureram - wineD3DGlobalStatistics->glsurfaceram);
2331 static HRESULT WINAPI IWineD3DDeviceImpl_SetFVF(IWineD3DDevice *iface, DWORD fvf) {
2332 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2333 HRESULT hr = WINED3D_OK;
2335 /* Update the current state block */
2336 This->updateStateBlock->fvf = fvf;
2337 This->updateStateBlock->changed.fvf = TRUE;
2338 This->updateStateBlock->set.fvf = TRUE;
2340 TRACE("(%p) : FVF Shader FVF set to %x\n", This, fvf);
2345 static HRESULT WINAPI IWineD3DDeviceImpl_GetFVF(IWineD3DDevice *iface, DWORD *pfvf) {
2346 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2347 TRACE("(%p) : GetFVF returning %x\n", This, This->stateBlock->fvf);
2348 *pfvf = This->stateBlock->fvf;
2353 * Get / Set Stream Source
2355 static HRESULT WINAPI IWineD3DDeviceImpl_SetStreamSource(IWineD3DDevice *iface, UINT StreamNumber,IWineD3DVertexBuffer* pStreamData, UINT OffsetInBytes, UINT Stride) {
2356 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2357 IWineD3DVertexBuffer *oldSrc;
2359 /**TODO: instance and index data, see
2360 http://msdn.microsoft.com/library/default.asp?url=/library/en-us/directx9_c/directx/graphics/programmingguide/advancedtopics/DrawingMultipleInstances.asp
2362 http://msdn.microsoft.com/library/default.asp?url=/library/en-us/directx9_c/directx/graphics/reference/d3d/interfaces/idirect3ddevice9/SetStreamSourceFreq.asp
2365 /* D3d9 only, but shouldn't hurt d3d8 */
2368 streamFlags = StreamNumber &(WINED3DSTREAMSOURCE_INDEXEDDATA | WINED3DSTREAMSOURCE_INSTANCEDATA);
2370 if (streamFlags & WINED3DSTREAMSOURCE_INDEXEDDATA) {
2371 FIXME("stream index data not supported\n");
2373 if (streamFlags & WINED3DSTREAMSOURCE_INDEXEDDATA) {
2374 FIXME("stream instance data not supported\n");
2378 StreamNumber&= ~(WINED3DSTREAMSOURCE_INDEXEDDATA | WINED3DSTREAMSOURCE_INSTANCEDATA);
2380 if (StreamNumber >= MAX_STREAMS) {
2381 WARN("Stream out of range %d\n", StreamNumber);
2382 return WINED3DERR_INVALIDCALL;
2385 oldSrc = This->stateBlock->streamSource[StreamNumber];
2386 TRACE("(%p) : StreamNo: %d, OldStream (%p), NewStream (%p), NewStride %d\n", This, StreamNumber, oldSrc, pStreamData, Stride);
2388 This->updateStateBlock->changed.streamSource[StreamNumber] = TRUE;
2389 This->updateStateBlock->set.streamSource[StreamNumber] = TRUE;
2390 This->updateStateBlock->streamStride[StreamNumber] = Stride;
2391 This->updateStateBlock->streamSource[StreamNumber] = pStreamData;
2392 This->updateStateBlock->streamOffset[StreamNumber] = OffsetInBytes;
2393 This->updateStateBlock->streamFlags[StreamNumber] = streamFlags;
2395 /* Handle recording of state blocks */
2396 if (This->isRecordingState) {
2397 TRACE("Recording... not performing anything\n");
2401 /* Same stream object: no action */
2402 if (oldSrc == pStreamData)
2405 /* Need to do a getParent and pass the reffs up */
2406 /* MSDN says ..... When an application no longer holds a references to this interface, the interface will automatically be freed.
2407 which suggests that we shouldn't be ref counting? and do need a _release on the stream source to reset the stream source
2408 so for now, just count internally */
2409 if (pStreamData != NULL) {
2410 IWineD3DVertexBufferImpl *vbImpl = (IWineD3DVertexBufferImpl *) pStreamData;
2411 if( (vbImpl->Flags & VBFLAG_STREAM) && vbImpl->stream != StreamNumber) {
2412 WARN("Assigning a Vertex Buffer to stream %d which is already assigned to stream %d\n", StreamNumber, vbImpl->stream);
2414 vbImpl->stream = StreamNumber;
2415 vbImpl->Flags |= VBFLAG_STREAM;
2416 IWineD3DVertexBuffer_AddRef(pStreamData);
2418 if (oldSrc != NULL) {
2419 ((IWineD3DVertexBufferImpl *) oldSrc)->Flags &= ~VBFLAG_STREAM;
2420 IWineD3DVertexBuffer_Release(oldSrc);
2426 static HRESULT WINAPI IWineD3DDeviceImpl_GetStreamSource(IWineD3DDevice *iface, UINT StreamNumber,IWineD3DVertexBuffer** pStream, UINT *pOffset, UINT* pStride) {
2427 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2430 TRACE("(%p) : StreamNo: %d, Stream (%p), Stride %d\n", This, StreamNumber,
2431 This->stateBlock->streamSource[StreamNumber], This->stateBlock->streamStride[StreamNumber]);
2434 streamFlags = StreamNumber &(WINED3DSTREAMSOURCE_INDEXEDDATA | WINED3DSTREAMSOURCE_INSTANCEDATA);
2436 if (streamFlags & WINED3DSTREAMSOURCE_INDEXEDDATA) {
2437 FIXME("stream index data not supported\n");
2439 if (streamFlags & WINED3DSTREAMSOURCE_INDEXEDDATA) {
2440 FIXME("stream instance data not supported\n");
2444 StreamNumber&= ~(WINED3DSTREAMSOURCE_INDEXEDDATA | WINED3DSTREAMSOURCE_INSTANCEDATA);
2446 if (StreamNumber >= MAX_STREAMS) {
2447 WARN("Stream out of range %d\n", StreamNumber);
2448 return WINED3DERR_INVALIDCALL;
2450 *pStream = This->stateBlock->streamSource[StreamNumber];
2451 *pStride = This->stateBlock->streamStride[StreamNumber];
2453 *pOffset = This->stateBlock->streamOffset[StreamNumber];
2456 if (*pStream == NULL) {
2457 FIXME("Attempting to get an empty stream %d, returning WINED3DERR_INVALIDCALL\n", StreamNumber);
2458 return WINED3DERR_INVALIDCALL;
2461 IWineD3DVertexBuffer_AddRef(*pStream); /* We have created a new reference to the VB */
2465 /*Should be quite easy, just an extension of vertexdata
2467 http://msdn.microsoft.com/archive/default.asp?url=/archive/en-us/directx9_c_Summer_04/directx/graphics/programmingguide/advancedtopics/DrawingMultipleInstances.asp
2469 The divider is a bit odd though
2471 VertexOffset = StartVertex / Divider * StreamStride +
2472 VertexIndex / Divider * StreamStride + StreamOffset
2475 static HRESULT WINAPI IWineD3DDeviceImpl_SetStreamSourceFreq(IWineD3DDevice *iface, UINT StreamNumber, UINT Divider) {
2476 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2478 TRACE("(%p) StreamNumber(%d), Divider(%d)\n", This, StreamNumber, Divider);
2479 This->updateStateBlock->streamFlags[StreamNumber] = Divider & (WINED3DSTREAMSOURCE_INSTANCEDATA | WINED3DSTREAMSOURCE_INDEXEDDATA );
2481 This->updateStateBlock->changed.streamFreq[StreamNumber] = TRUE;
2482 This->updateStateBlock->set.streamFreq[StreamNumber] = TRUE;
2483 This->updateStateBlock->streamFreq[StreamNumber] = Divider & 0x7FFFFF;
2485 if (This->updateStateBlock->streamFlags[StreamNumber] || This->updateStateBlock->streamFreq[StreamNumber] != 1) {
2486 FIXME("Stream indexing not fully supported\n");
2492 static HRESULT WINAPI IWineD3DDeviceImpl_GetStreamSourceFreq(IWineD3DDevice *iface, UINT StreamNumber, UINT* Divider) {
2493 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2495 TRACE("(%p) StreamNumber(%d), Divider(%p)\n", This, StreamNumber, Divider);
2496 *Divider = This->updateStateBlock->streamFreq[StreamNumber] | This->updateStateBlock->streamFlags[StreamNumber];
2498 TRACE("(%p) : returning %d\n", This, *Divider);
2504 * Get / Set & Multiply Transform
2506 static HRESULT WINAPI IWineD3DDeviceImpl_SetTransform(IWineD3DDevice *iface, WINED3DTRANSFORMSTATETYPE d3dts, CONST WINED3DMATRIX* lpmatrix) {
2507 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2509 /* Most of this routine, comments included copied from ddraw tree initially: */
2510 TRACE("(%p) : Transform State=%s\n", This, debug_d3dtstype(d3dts));
2512 /* Handle recording of state blocks */
2513 if (This->isRecordingState) {
2514 TRACE("Recording... not performing anything\n");
2515 This->updateStateBlock->changed.transform[d3dts] = TRUE;
2516 This->updateStateBlock->set.transform[d3dts] = TRUE;
2517 memcpy(&This->updateStateBlock->transforms[d3dts], lpmatrix, sizeof(WINED3DMATRIX));
2522 * If the new matrix is the same as the current one,
2523 * we cut off any further processing. this seems to be a reasonable
2524 * optimization because as was noticed, some apps (warcraft3 for example)
2525 * tend towards setting the same matrix repeatedly for some reason.
2527 * From here on we assume that the new matrix is different, wherever it matters.
2529 if (!memcmp(&This->stateBlock->transforms[d3dts].u.m[0][0], lpmatrix, sizeof(WINED3DMATRIX))) {
2530 TRACE("The app is setting the same matrix over again\n");
2533 conv_mat(lpmatrix, &This->stateBlock->transforms[d3dts].u.m[0][0]);
2537 ScreenCoord = ProjectionMat * ViewMat * WorldMat * ObjectCoord
2538 where ViewMat = Camera space, WorldMat = world space.
2540 In OpenGL, camera and world space is combined into GL_MODELVIEW
2541 matrix. The Projection matrix stay projection matrix.
2544 /* Capture the times we can just ignore the change for now */
2545 if (d3dts == WINED3DTS_WORLDMATRIX(0)) {
2546 This->modelview_valid = FALSE;
2549 } else if (d3dts == WINED3DTS_PROJECTION) {
2550 This->proj_valid = FALSE;
2553 } else if (d3dts >= WINED3DTS_WORLDMATRIX(1) && d3dts <= WINED3DTS_WORLDMATRIX(255)) {
2554 /* Indexed Vertex Blending Matrices 256 -> 511 */
2555 /* Use arb_vertex_blend or NV_VERTEX_WEIGHTING? */
2556 FIXME("WINED3DTS_WORLDMATRIX(1..255) not handled\n");
2560 /* Now we really are going to have to change a matrix */
2563 if (d3dts >= WINED3DTS_TEXTURE0 && d3dts <= WINED3DTS_TEXTURE7) { /* handle texture matrices */
2564 /* This is now set with the texture unit states, it may be a good idea to flag the change though! */
2565 } else if (d3dts == WINED3DTS_VIEW) { /* handle the VIEW matrice */
2568 /* If we are changing the View matrix, reset the light and clipping planes to the new view
2569 * NOTE: We have to reset the positions even if the light/plane is not currently
2570 * enabled, since the call to enable it will not reset the position.
2571 * NOTE2: Apparently texture transforms do NOT need reapplying
2574 PLIGHTINFOEL *lightChain = NULL;
2575 This->modelview_valid = FALSE;
2576 This->view_ident = !memcmp(lpmatrix, identity, 16 * sizeof(float));
2578 glMatrixMode(GL_MODELVIEW);
2579 checkGLcall("glMatrixMode(GL_MODELVIEW)");
2581 glLoadMatrixf((float *)lpmatrix);
2582 checkGLcall("glLoadMatrixf(...)");
2585 lightChain = This->stateBlock->lights;
2586 while (lightChain && lightChain->glIndex != -1) {
2587 glLightfv(GL_LIGHT0 + lightChain->glIndex, GL_POSITION, lightChain->lightPosn);
2588 checkGLcall("glLightfv posn");
2589 glLightfv(GL_LIGHT0 + lightChain->glIndex, GL_SPOT_DIRECTION, lightChain->lightDirn);
2590 checkGLcall("glLightfv dirn");
2591 lightChain = lightChain->next;
2594 /* Reset Clipping Planes if clipping is enabled */
2595 for (k = 0; k < GL_LIMITS(clipplanes); k++) {
2596 glClipPlane(GL_CLIP_PLANE0 + k, This->stateBlock->clipplane[k]);
2597 checkGLcall("glClipPlane");
2601 } else { /* What was requested!?? */
2602 WARN("invalid matrix specified: %i\n", d3dts);
2605 /* Release lock, all done */
2610 static HRESULT WINAPI IWineD3DDeviceImpl_GetTransform(IWineD3DDevice *iface, WINED3DTRANSFORMSTATETYPE State, WINED3DMATRIX* pMatrix) {
2611 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2612 TRACE("(%p) : for Transform State %s\n", This, debug_d3dtstype(State));
2613 memcpy(pMatrix, &This->stateBlock->transforms[State], sizeof(WINED3DMATRIX));
2617 static HRESULT WINAPI IWineD3DDeviceImpl_MultiplyTransform(IWineD3DDevice *iface, WINED3DTRANSFORMSTATETYPE State, CONST WINED3DMATRIX* pMatrix) {
2618 WINED3DMATRIX *mat = NULL;
2621 /* Note: Using 'updateStateBlock' rather than 'stateblock' in the code
2622 * below means it will be recorded in a state block change, but it
2623 * works regardless where it is recorded.
2624 * If this is found to be wrong, change to StateBlock.
2626 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2627 TRACE("(%p) : For state %s\n", This, debug_d3dtstype(State));
2629 if (State < HIGHEST_TRANSFORMSTATE)
2631 mat = &This->updateStateBlock->transforms[State];
2633 FIXME("Unhandled transform state!!\n");
2636 multiply_matrix(&temp, mat, (WINED3DMATRIX *) pMatrix);
2638 /* Apply change via set transform - will reapply to eg. lights this way */
2639 return IWineD3DDeviceImpl_SetTransform(iface, State, &temp);
2645 /* Note lights are real special cases. Although the device caps state only eg. 8 are supported,
2646 you can reference any indexes you want as long as that number max are enabled at any
2647 one point in time! Therefore since the indexes can be anything, we need a linked list of them.
2648 However, this causes stateblock problems. When capturing the state block, I duplicate the list,
2649 but when recording, just build a chain pretty much of commands to be replayed. */
2651 static HRESULT WINAPI IWineD3DDeviceImpl_SetLight(IWineD3DDevice *iface, DWORD Index, CONST WINED3DLIGHT* pLight) {
2653 PLIGHTINFOEL *object, *temp;
2655 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2656 TRACE("(%p) : Idx(%d), pLight(%p)\n", This, Index, pLight);
2658 /* If recording state block, just add to end of lights chain */
2659 if (This->isRecordingState) {
2660 object = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(PLIGHTINFOEL));
2661 if (NULL == object) {
2662 return WINED3DERR_OUTOFVIDEOMEMORY;
2664 memcpy(&object->OriginalParms, pLight, sizeof(WINED3DLIGHT));
2665 object->OriginalIndex = Index;
2666 object->glIndex = -1;
2667 object->changed = TRUE;
2669 /* Add to the END of the chain of lights changes to be replayed */
2670 if (This->updateStateBlock->lights == NULL) {
2671 This->updateStateBlock->lights = object;
2673 temp = This->updateStateBlock->lights;
2674 while (temp->next != NULL) temp=temp->next;
2675 temp->next = object;
2677 TRACE("Recording... not performing anything more\n");
2681 /* Ok, not recording any longer so do real work */
2682 object = This->stateBlock->lights;
2683 while (object != NULL && object->OriginalIndex != Index) object = object->next;
2685 /* If we didn't find it in the list of lights, time to add it */
2686 if (object == NULL) {
2687 PLIGHTINFOEL *insertAt,*prevPos;
2689 object = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(PLIGHTINFOEL));
2690 if (NULL == object) {
2691 return WINED3DERR_OUTOFVIDEOMEMORY;
2693 object->OriginalIndex = Index;
2694 object->glIndex = -1;
2696 /* Add it to the front of list with the idea that lights will be changed as needed
2697 BUT after any lights currently assigned GL indexes */
2698 insertAt = This->stateBlock->lights;
2700 while (insertAt != NULL && insertAt->glIndex != -1) {
2702 insertAt = insertAt->next;
2705 if (insertAt == NULL && prevPos == NULL) { /* Start of list */
2706 This->stateBlock->lights = object;
2707 } else if (insertAt == NULL) { /* End of list */
2708 prevPos->next = object;
2709 object->prev = prevPos;
2710 } else { /* Middle of chain */
2711 if (prevPos == NULL) {
2712 This->stateBlock->lights = object;
2714 prevPos->next = object;
2716 object->prev = prevPos;
2717 object->next = insertAt;
2718 insertAt->prev = object;
2722 /* Initialize the object */
2723 TRACE("Light %d setting to type %d, Diffuse(%f,%f,%f,%f), Specular(%f,%f,%f,%f), Ambient(%f,%f,%f,%f)\n", Index, pLight->Type,
2724 pLight->Diffuse.r, pLight->Diffuse.g, pLight->Diffuse.b, pLight->Diffuse.a,
2725 pLight->Specular.r, pLight->Specular.g, pLight->Specular.b, pLight->Specular.a,
2726 pLight->Ambient.r, pLight->Ambient.g, pLight->Ambient.b, pLight->Ambient.a);
2727 TRACE("... Pos(%f,%f,%f), Dirn(%f,%f,%f)\n", pLight->Position.x, pLight->Position.y, pLight->Position.z,
2728 pLight->Direction.x, pLight->Direction.y, pLight->Direction.z);
2729 TRACE("... Range(%f), Falloff(%f), Theta(%f), Phi(%f)\n", pLight->Range, pLight->Falloff, pLight->Theta, pLight->Phi);
2731 /* Save away the information */
2732 memcpy(&object->OriginalParms, pLight, sizeof(WINED3DLIGHT));
2734 switch (pLight->Type) {
2735 case WINED3DLIGHT_POINT:
2737 object->lightPosn[0] = pLight->Position.x;
2738 object->lightPosn[1] = pLight->Position.y;
2739 object->lightPosn[2] = pLight->Position.z;
2740 object->lightPosn[3] = 1.0f;
2741 object->cutoff = 180.0f;
2745 case WINED3DLIGHT_DIRECTIONAL:
2747 object->lightPosn[0] = -pLight->Direction.x;
2748 object->lightPosn[1] = -pLight->Direction.y;
2749 object->lightPosn[2] = -pLight->Direction.z;
2750 object->lightPosn[3] = 0.0;
2751 object->exponent = 0.0f;
2752 object->cutoff = 180.0f;
2755 case WINED3DLIGHT_SPOT:
2757 object->lightPosn[0] = pLight->Position.x;
2758 object->lightPosn[1] = pLight->Position.y;
2759 object->lightPosn[2] = pLight->Position.z;
2760 object->lightPosn[3] = 1.0;
2763 object->lightDirn[0] = pLight->Direction.x;
2764 object->lightDirn[1] = pLight->Direction.y;
2765 object->lightDirn[2] = pLight->Direction.z;
2766 object->lightDirn[3] = 1.0;
2769 * opengl-ish and d3d-ish spot lights use too different models for the
2770 * light "intensity" as a function of the angle towards the main light direction,
2771 * so we only can approximate very roughly.
2772 * however spot lights are rather rarely used in games (if ever used at all).
2773 * furthermore if still used, probably nobody pays attention to such details.
2775 if (pLight->Falloff == 0) {
2778 rho = pLight->Theta + (pLight->Phi - pLight->Theta)/(2*pLight->Falloff);
2780 if (rho < 0.0001) rho = 0.0001f;
2781 object->exponent = -0.3/log(cos(rho/2));
2782 if (object->exponent > 128.0) {
2783 object->exponent = 128.0;
2785 object->cutoff = pLight->Phi*90/M_PI;
2791 FIXME("Unrecognized light type %d\n", pLight->Type);
2794 /* Update the live definitions if the light is currently assigned a glIndex */
2795 if (object->glIndex != -1) {
2796 setup_light(iface, object->glIndex, object);
2801 static HRESULT WINAPI IWineD3DDeviceImpl_GetLight(IWineD3DDevice *iface, DWORD Index, WINED3DLIGHT* pLight) {
2802 PLIGHTINFOEL *lightInfo = NULL;
2803 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2804 TRACE("(%p) : Idx(%d), pLight(%p)\n", This, Index, pLight);
2806 /* Locate the light in the live lights */
2807 lightInfo = This->stateBlock->lights;
2808 while (lightInfo != NULL && lightInfo->OriginalIndex != Index) lightInfo = lightInfo->next;
2810 if (lightInfo == NULL) {
2811 TRACE("Light information requested but light not defined\n");
2812 return WINED3DERR_INVALIDCALL;
2815 memcpy(pLight, &lightInfo->OriginalParms, sizeof(WINED3DLIGHT));
2820 * Get / Set Light Enable
2821 * (Note for consistency, renamed d3dx function by adding the 'set' prefix)
2823 static HRESULT WINAPI IWineD3DDeviceImpl_SetLightEnable(IWineD3DDevice *iface, DWORD Index, BOOL Enable) {
2824 PLIGHTINFOEL *lightInfo = NULL;
2825 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2826 TRACE("(%p) : Idx(%d), enable? %d\n", This, Index, Enable);
2828 /* Tests show true = 128...not clear why */
2830 Enable = Enable? 128: 0;
2832 /* If recording state block, just add to end of lights chain with changedEnable set to true */
2833 if (This->isRecordingState) {
2834 lightInfo = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(PLIGHTINFOEL));
2835 if (NULL == lightInfo) {
2836 return WINED3DERR_OUTOFVIDEOMEMORY;
2838 lightInfo->OriginalIndex = Index;
2839 lightInfo->glIndex = -1;
2840 lightInfo->enabledChanged = TRUE;
2841 lightInfo->lightEnabled = Enable;
2843 /* Add to the END of the chain of lights changes to be replayed */
2844 if (This->updateStateBlock->lights == NULL) {
2845 This->updateStateBlock->lights = lightInfo;
2847 PLIGHTINFOEL *temp = This->updateStateBlock->lights;
2848 while (temp->next != NULL) temp=temp->next;
2849 temp->next = lightInfo;
2851 TRACE("Recording... not performing anything more\n");
2855 /* Not recording... So, locate the light in the live lights */
2856 lightInfo = This->stateBlock->lights;
2857 while (lightInfo != NULL && lightInfo->OriginalIndex != Index) lightInfo = lightInfo->next;
2859 /* Special case - enabling an undefined light creates one with a strict set of parms! */
2860 if (lightInfo == NULL) {
2862 TRACE("Light enabled requested but light not defined, so defining one!\n");
2863 IWineD3DDeviceImpl_SetLight(iface, Index, &WINED3D_default_light);
2865 /* Search for it again! Should be fairly quick as near head of list */
2866 lightInfo = This->stateBlock->lights;
2867 while (lightInfo != NULL && lightInfo->OriginalIndex != Index) lightInfo = lightInfo->next;
2868 if (lightInfo == NULL) {
2869 FIXME("Adding default lights has failed dismally\n");
2870 return WINED3DERR_INVALIDCALL;
2874 /* OK, we now have a light... */
2877 /* If we are disabling it, check it was enabled, and
2878 still only do something if it has assigned a glIndex (which it should have!) */
2879 if ((lightInfo->lightEnabled) && (lightInfo->glIndex != -1)) {
2880 TRACE("Disabling light set up at gl idx %d\n", lightInfo->glIndex);
2882 glDisable(GL_LIGHT0 + lightInfo->glIndex);
2883 checkGLcall("glDisable GL_LIGHT0+Index");
2886 TRACE("Nothing to do as light was not enabled\n");
2888 lightInfo->lightEnabled = Enable;
2891 /* We are enabling it. If it is enabled, it's really simple */
2892 if (lightInfo->lightEnabled) {
2894 TRACE("Nothing to do as light was enabled\n");
2896 /* If it already has a glIndex, it's still simple */
2897 } else if (lightInfo->glIndex != -1) {
2898 TRACE("Reusing light as already set up at gl idx %d\n", lightInfo->glIndex);
2899 lightInfo->lightEnabled = Enable;
2901 glEnable(GL_LIGHT0 + lightInfo->glIndex);
2902 checkGLcall("glEnable GL_LIGHT0+Index already setup");
2905 /* Otherwise got to find space - lights are ordered gl indexes first */
2907 PLIGHTINFOEL *bsf = NULL;
2908 PLIGHTINFOEL *pos = This->stateBlock->lights;
2909 PLIGHTINFOEL *prev = NULL;
2913 /* Try to minimize changes as much as possible */
2914 while (pos != NULL && pos->glIndex != -1 && Index < This->maxConcurrentLights) {
2916 /* Try to remember which index can be replaced if necessary */
2917 if (bsf==NULL && !pos->lightEnabled) {
2918 /* Found a light we can replace, save as best replacement */
2922 /* Step to next space */
2928 /* If we have too many active lights, fail the call */
2929 if ((Index == This->maxConcurrentLights) && (bsf == NULL)) {
2930 FIXME("Program requests too many concurrent lights\n");
2931 return WINED3DERR_INVALIDCALL;
2933 /* If we have allocated all lights, but not all are enabled,
2934 reuse one which is not enabled */
2935 } else if (Index == This->maxConcurrentLights) {
2936 /* use bsf - Simply swap the new light and the BSF one */
2937 PLIGHTINFOEL *bsfNext = bsf->next;
2938 PLIGHTINFOEL *bsfPrev = bsf->prev;
2941 if (lightInfo->next != NULL) lightInfo->next->prev = bsf;
2942 if (bsf->prev != NULL) {
2943 bsf->prev->next = lightInfo;
2945 This->stateBlock->lights = lightInfo;
2948 /* If not side by side, lots of chains to update */
2949 if (bsf->next != lightInfo) {
2950 lightInfo->prev->next = bsf;
2951 bsf->next->prev = lightInfo;
2952 bsf->next = lightInfo->next;
2953 bsf->prev = lightInfo->prev;
2954 lightInfo->next = bsfNext;
2955 lightInfo->prev = bsfPrev;
2959 bsf->prev = lightInfo;
2960 bsf->next = lightInfo->next;
2961 lightInfo->next = bsf;
2962 lightInfo->prev = bsfPrev;
2967 glIndex = bsf->glIndex;
2969 lightInfo->glIndex = glIndex;
2970 lightInfo->lightEnabled = Enable;
2972 /* Finally set up the light in gl itself */
2973 TRACE("Replacing light which was set up at gl idx %d\n", lightInfo->glIndex);
2975 setup_light(iface, glIndex, lightInfo);
2976 glEnable(GL_LIGHT0 + glIndex);
2977 checkGLcall("glEnable GL_LIGHT0 new setup");
2980 /* If we reached the end of the allocated lights, with space in the
2981 gl lights, setup a new light */
2982 } else if (pos->glIndex == -1) {
2984 /* We reached the end of the allocated gl lights, so already
2985 know the index of the next one! */
2987 lightInfo->glIndex = glIndex;
2988 lightInfo->lightEnabled = Enable;
2990 /* In an ideal world, it's already in the right place */
2991 if (lightInfo->prev == NULL || lightInfo->prev->glIndex!=-1) {
2992 /* No need to move it */
2994 /* Remove this light from the list */
2995 lightInfo->prev->next = lightInfo->next;
2996 if (lightInfo->next != NULL) {
2997 lightInfo->next->prev = lightInfo->prev;
3000 /* Add in at appropriate place (inbetween prev and pos) */
3001 lightInfo->prev = prev;
3002 lightInfo->next = pos;
3004 This->stateBlock->lights = lightInfo;
3006 prev->next = lightInfo;
3009 pos->prev = lightInfo;
3013 /* Finally set up the light in gl itself */
3014 TRACE("Defining new light at gl idx %d\n", lightInfo->glIndex);
3016 setup_light(iface, glIndex, lightInfo);
3017 glEnable(GL_LIGHT0 + glIndex);
3018 checkGLcall("glEnable GL_LIGHT0 new setup");
3027 static HRESULT WINAPI IWineD3DDeviceImpl_GetLightEnable(IWineD3DDevice *iface, DWORD Index,BOOL* pEnable) {
3029 PLIGHTINFOEL *lightInfo = NULL;
3030 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3031 TRACE("(%p) : for idx(%d)\n", This, Index);
3033 /* Locate the light in the live lights */
3034 lightInfo = This->stateBlock->lights;
3035 while (lightInfo != NULL && lightInfo->OriginalIndex != Index) lightInfo = lightInfo->next;
3037 if (lightInfo == NULL) {
3038 TRACE("Light enabled state requested but light not defined\n");
3039 return WINED3DERR_INVALIDCALL;
3041 *pEnable = lightInfo->lightEnabled;
3046 * Get / Set Clip Planes
3048 static HRESULT WINAPI IWineD3DDeviceImpl_SetClipPlane(IWineD3DDevice *iface, DWORD Index, CONST float *pPlane) {
3049 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3050 TRACE("(%p) : for idx %d, %p\n", This, Index, pPlane);
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 This->updateStateBlock->changed.clipplane[Index] = TRUE;
3059 This->updateStateBlock->set.clipplane[Index] = TRUE;
3060 This->updateStateBlock->clipplane[Index][0] = pPlane[0];
3061 This->updateStateBlock->clipplane[Index][1] = pPlane[1];
3062 This->updateStateBlock->clipplane[Index][2] = pPlane[2];
3063 This->updateStateBlock->clipplane[Index][3] = pPlane[3];
3065 /* Handle recording of state blocks */
3066 if (This->isRecordingState) {
3067 TRACE("Recording... not performing anything\n");
3075 /* Clip Plane settings are affected by the model view in OpenGL, the View transform in direct3d */
3076 glMatrixMode(GL_MODELVIEW);
3078 glLoadMatrixf((float *) &This->stateBlock->transforms[WINED3DTS_VIEW].u.m[0][0]);
3080 TRACE("Clipplane [%f,%f,%f,%f]\n",
3081 This->updateStateBlock->clipplane[Index][0],
3082 This->updateStateBlock->clipplane[Index][1],
3083 This->updateStateBlock->clipplane[Index][2],
3084 This->updateStateBlock->clipplane[Index][3]);
3085 glClipPlane(GL_CLIP_PLANE0 + Index, This->updateStateBlock->clipplane[Index]);
3086 checkGLcall("glClipPlane");
3094 static HRESULT WINAPI IWineD3DDeviceImpl_GetClipPlane(IWineD3DDevice *iface, DWORD Index, float *pPlane) {
3095 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3096 TRACE("(%p) : for idx %d\n", This, Index);
3098 /* Validate Index */
3099 if (Index >= GL_LIMITS(clipplanes)) {
3100 TRACE("Application has requested clipplane this device doesn't support\n");
3101 return WINED3DERR_INVALIDCALL;
3104 pPlane[0] = This->stateBlock->clipplane[Index][0];
3105 pPlane[1] = This->stateBlock->clipplane[Index][1];
3106 pPlane[2] = This->stateBlock->clipplane[Index][2];
3107 pPlane[3] = This->stateBlock->clipplane[Index][3];
3112 * Get / Set Clip Plane Status
3113 * WARNING: This code relies on the fact that D3DCLIPSTATUS8 == D3DCLIPSTATUS9
3115 static HRESULT WINAPI IWineD3DDeviceImpl_SetClipStatus(IWineD3DDevice *iface, CONST WINED3DCLIPSTATUS* pClipStatus) {
3116 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3117 FIXME("(%p) : stub\n", This);
3118 if (NULL == pClipStatus) {
3119 return WINED3DERR_INVALIDCALL;
3121 This->updateStateBlock->clip_status.ClipUnion = pClipStatus->ClipUnion;
3122 This->updateStateBlock->clip_status.ClipIntersection = pClipStatus->ClipIntersection;
3126 static HRESULT WINAPI IWineD3DDeviceImpl_GetClipStatus(IWineD3DDevice *iface, WINED3DCLIPSTATUS* pClipStatus) {
3127 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3128 FIXME("(%p) : stub\n", This);
3129 if (NULL == pClipStatus) {
3130 return WINED3DERR_INVALIDCALL;
3132 pClipStatus->ClipUnion = This->updateStateBlock->clip_status.ClipUnion;
3133 pClipStatus->ClipIntersection = This->updateStateBlock->clip_status.ClipIntersection;
3138 * Get / Set Material
3140 static HRESULT WINAPI IWineD3DDeviceImpl_SetMaterial(IWineD3DDevice *iface, CONST WINED3DMATERIAL* pMaterial) {
3141 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3143 This->updateStateBlock->changed.material = TRUE;
3144 This->updateStateBlock->set.material = TRUE;
3145 memcpy(&This->updateStateBlock->material, pMaterial, sizeof(WINED3DMATERIAL));
3147 /* Handle recording of state blocks */
3148 if (This->isRecordingState) {
3149 TRACE("Recording... not performing anything\n");
3154 TRACE("(%p) : Diffuse (%f,%f,%f,%f)\n", This, pMaterial->Diffuse.r, pMaterial->Diffuse.g,
3155 pMaterial->Diffuse.b, pMaterial->Diffuse.a);
3156 TRACE("(%p) : Ambient (%f,%f,%f,%f)\n", This, pMaterial->Ambient.r, pMaterial->Ambient.g,
3157 pMaterial->Ambient.b, pMaterial->Ambient.a);
3158 TRACE("(%p) : Specular (%f,%f,%f,%f)\n", This, pMaterial->Specular.r, pMaterial->Specular.g,
3159 pMaterial->Specular.b, pMaterial->Specular.a);
3160 TRACE("(%p) : Emissive (%f,%f,%f,%f)\n", This, pMaterial->Emissive.r, pMaterial->Emissive.g,
3161 pMaterial->Emissive.b, pMaterial->Emissive.a);
3162 TRACE("(%p) : Power (%f)\n", This, pMaterial->Power);
3164 glMaterialfv(GL_FRONT_AND_BACK, GL_AMBIENT, (float*) &This->updateStateBlock->material.Ambient);
3165 checkGLcall("glMaterialfv(GL_AMBIENT)");
3166 glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, (float*) &This->updateStateBlock->material.Diffuse);
3167 checkGLcall("glMaterialfv(GL_DIFFUSE)");
3169 /* Only change material color if specular is enabled, otherwise it is set to black */
3170 if (This->stateBlock->renderState[WINED3DRS_SPECULARENABLE]) {
3171 glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, (float*) &This->updateStateBlock->material.Specular);
3172 checkGLcall("glMaterialfv(GL_SPECULAR");
3174 float black[4] = {0.0f, 0.0f, 0.0f, 0.0f};
3175 glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, &black[0]);
3176 checkGLcall("glMaterialfv(GL_SPECULAR");
3178 glMaterialfv(GL_FRONT_AND_BACK, GL_EMISSION, (float*) &This->updateStateBlock->material.Emissive);
3179 checkGLcall("glMaterialfv(GL_EMISSION)");
3180 glMaterialf(GL_FRONT_AND_BACK, GL_SHININESS, This->updateStateBlock->material.Power);
3181 checkGLcall("glMaterialf(GL_SHININESS");
3187 static HRESULT WINAPI IWineD3DDeviceImpl_GetMaterial(IWineD3DDevice *iface, WINED3DMATERIAL* pMaterial) {
3188 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3189 memcpy(pMaterial, &This->updateStateBlock->material, sizeof (WINED3DMATERIAL));
3190 TRACE("(%p) : Diffuse (%f,%f,%f,%f)\n", This, pMaterial->Diffuse.r, pMaterial->Diffuse.g,
3191 pMaterial->Diffuse.b, pMaterial->Diffuse.a);
3192 TRACE("(%p) : Ambient (%f,%f,%f,%f)\n", This, pMaterial->Ambient.r, pMaterial->Ambient.g,
3193 pMaterial->Ambient.b, pMaterial->Ambient.a);
3194 TRACE("(%p) : Specular (%f,%f,%f,%f)\n", This, pMaterial->Specular.r, pMaterial->Specular.g,
3195 pMaterial->Specular.b, pMaterial->Specular.a);
3196 TRACE("(%p) : Emissive (%f,%f,%f,%f)\n", This, pMaterial->Emissive.r, pMaterial->Emissive.g,
3197 pMaterial->Emissive.b, pMaterial->Emissive.a);
3198 TRACE("(%p) : Power (%f)\n", This, pMaterial->Power);
3206 static HRESULT WINAPI IWineD3DDeviceImpl_SetIndices(IWineD3DDevice *iface, IWineD3DIndexBuffer* pIndexData,
3207 UINT BaseVertexIndex) {
3208 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3209 IWineD3DIndexBuffer *oldIdxs;
3211 TRACE("(%p) : Setting to %p, base %d\n", This, pIndexData, BaseVertexIndex);
3212 oldIdxs = This->updateStateBlock->pIndexData;
3214 This->updateStateBlock->changed.indices = TRUE;
3215 This->updateStateBlock->set.indices = TRUE;
3216 This->updateStateBlock->pIndexData = pIndexData;
3217 This->updateStateBlock->baseVertexIndex = BaseVertexIndex;
3219 /* Handle recording of state blocks */
3220 if (This->isRecordingState) {
3221 TRACE("Recording... not performing anything\n");
3225 if (NULL != pIndexData) {
3226 IWineD3DIndexBuffer_AddRef(pIndexData);
3228 if (NULL != oldIdxs) {
3229 IWineD3DIndexBuffer_Release(oldIdxs);
3234 static HRESULT WINAPI IWineD3DDeviceImpl_GetIndices(IWineD3DDevice *iface, IWineD3DIndexBuffer** ppIndexData, UINT* pBaseVertexIndex) {
3235 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3237 *ppIndexData = This->stateBlock->pIndexData;
3239 /* up ref count on ppindexdata */
3241 IWineD3DIndexBuffer_AddRef(*ppIndexData);
3242 *pBaseVertexIndex = This->stateBlock->baseVertexIndex;
3243 TRACE("(%p) index data set to %p + %u\n", This, ppIndexData, This->stateBlock->baseVertexIndex);
3245 TRACE("(%p) No index data set\n", This);
3247 TRACE("Returning %p %d\n", *ppIndexData, *pBaseVertexIndex);
3253 * Get / Set Viewports
3255 static HRESULT WINAPI IWineD3DDeviceImpl_SetViewport(IWineD3DDevice *iface, CONST WINED3DVIEWPORT* pViewport) {
3256 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3258 TRACE("(%p)\n", This);
3259 This->updateStateBlock->changed.viewport = TRUE;
3260 This->updateStateBlock->set.viewport = TRUE;
3261 memcpy(&This->updateStateBlock->viewport, pViewport, sizeof(WINED3DVIEWPORT));
3263 /* Handle recording of state blocks */
3264 if (This->isRecordingState) {
3265 TRACE("Recording... not performing anything\n");
3268 This->viewport_changed = TRUE;
3272 TRACE("(%p) : x=%d, y=%d, wid=%d, hei=%d, minz=%f, maxz=%f\n", This,
3273 pViewport->X, pViewport->Y, pViewport->Width, pViewport->Height, pViewport->MinZ, pViewport->MaxZ);
3275 glDepthRange(pViewport->MinZ, pViewport->MaxZ);
3276 checkGLcall("glDepthRange");
3277 /* Note: GL requires lower left, DirectX supplies upper left */
3278 /* TODO: replace usage of renderTarget with context management */
3279 glViewport(pViewport->X,
3280 (((IWineD3DSurfaceImpl *)This->renderTarget)->currentDesc.Height - (pViewport->Y + pViewport->Height)),
3281 pViewport->Width, pViewport->Height);
3283 checkGLcall("glViewport");
3291 static HRESULT WINAPI IWineD3DDeviceImpl_GetViewport(IWineD3DDevice *iface, WINED3DVIEWPORT* pViewport) {
3292 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3293 TRACE("(%p)\n", This);
3294 memcpy(pViewport, &This->stateBlock->viewport, sizeof(WINED3DVIEWPORT));
3298 static void renderstate_stencil_twosided(
3299 IWineD3DDeviceImpl *This,
3306 GLint stencilPass ) {
3307 #if 0 /* Don't use OpenGL 2.0 calls for now */
3308 if(GL_EXTCALL(glStencilFuncSeparate) && GL_EXTCALL(glStencilOpSeparate)) {
3309 GL_EXTCALL(glStencilFuncSeparate(face, func, ref, mask));
3310 checkGLcall("glStencilFuncSeparate(...)");
3311 GL_EXTCALL(glStencilOpSeparate(face, stencilFail, depthFail, stencilPass));
3312 checkGLcall("glStencilOpSeparate(...)");
3316 if(GL_SUPPORT(EXT_STENCIL_TWO_SIDE)) {
3317 glEnable(GL_STENCIL_TEST_TWO_SIDE_EXT);
3318 checkGLcall("glEnable(GL_STENCIL_TEST_TWO_SIDE_EXT)");
3319 GL_EXTCALL(glActiveStencilFaceEXT(face));
3320 checkGLcall("glActiveStencilFaceEXT(...)");
3321 glStencilFunc(func, ref, mask);
3322 checkGLcall("glStencilFunc(...)");
3323 glStencilOp(stencilFail, depthFail, stencilPass);
3324 checkGLcall("glStencilOp(...)");
3325 } else if(GL_SUPPORT(ATI_SEPARATE_STENCIL)) {
3326 GL_EXTCALL(glStencilFuncSeparateATI(face, func, ref, mask));
3327 checkGLcall("glStencilFuncSeparateATI(...)");
3328 GL_EXTCALL(glStencilOpSeparateATI(face, stencilFail, depthFail, stencilPass));
3329 checkGLcall("glStencilOpSeparateATI(...)");
3331 ERR("Separate (two sided) stencil not supported on this version of opengl. Caps weren't honored?\n");
3335 static void renderstate_stencil(IWineD3DDeviceImpl *This, WINED3DRENDERSTATETYPE State, DWORD Value) {
3336 DWORD onesided_enable = FALSE;
3337 DWORD twosided_enable = FALSE;
3338 GLint func = GL_ALWAYS;
3339 GLint func_ccw = GL_ALWAYS;
3342 GLint stencilFail = GL_KEEP;
3343 GLint depthFail = GL_KEEP;
3344 GLint stencilPass = GL_KEEP;
3345 GLint stencilFail_ccw = GL_KEEP;
3346 GLint depthFail_ccw = GL_KEEP;
3347 GLint stencilPass_ccw = GL_KEEP;
3349 if( This->stateBlock->set.renderState[WINED3DRS_STENCILENABLE] )
3350 onesided_enable = This->stateBlock->renderState[WINED3DRS_STENCILENABLE];
3351 if( This->stateBlock->set.renderState[WINED3DRS_TWOSIDEDSTENCILMODE] )
3352 twosided_enable = This->stateBlock->renderState[WINED3DRS_TWOSIDEDSTENCILMODE];
3353 if( This->stateBlock->set.renderState[WINED3DRS_STENCILFUNC] )
3354 if( !( func = CompareFunc(This->stateBlock->renderState[WINED3DRS_STENCILFUNC]) ) )
3356 if( This->stateBlock->set.renderState[WINED3DRS_CCW_STENCILFUNC] )
3357 if( !( func_ccw = CompareFunc(This->stateBlock->renderState[WINED3DRS_CCW_STENCILFUNC]) ) )
3359 if( This->stateBlock->set.renderState[WINED3DRS_STENCILREF] )
3360 ref = This->stateBlock->renderState[WINED3DRS_STENCILREF];
3361 if( This->stateBlock->set.renderState[WINED3DRS_STENCILMASK] )
3362 mask = This->stateBlock->renderState[WINED3DRS_STENCILMASK];
3363 if( This->stateBlock->set.renderState[WINED3DRS_STENCILFAIL] )
3364 stencilFail = StencilOp(This->stateBlock->renderState[WINED3DRS_STENCILFAIL]);
3365 if( This->stateBlock->set.renderState[WINED3DRS_STENCILZFAIL] )
3366 depthFail = StencilOp(This->stateBlock->renderState[WINED3DRS_STENCILZFAIL]);
3367 if( This->stateBlock->set.renderState[WINED3DRS_STENCILPASS] )
3368 stencilPass = StencilOp(This->stateBlock->renderState[WINED3DRS_STENCILPASS]);
3369 if( This->stateBlock->set.renderState[WINED3DRS_CCW_STENCILFAIL] )
3370 stencilFail_ccw = StencilOp(This->stateBlock->renderState[WINED3DRS_CCW_STENCILFAIL]);
3371 if( This->stateBlock->set.renderState[WINED3DRS_CCW_STENCILZFAIL] )
3372 depthFail_ccw = StencilOp(This->stateBlock->renderState[WINED3DRS_CCW_STENCILZFAIL]);
3373 if( This->stateBlock->set.renderState[WINED3DRS_CCW_STENCILPASS] )
3374 stencilPass_ccw = StencilOp(This->stateBlock->renderState[WINED3DRS_CCW_STENCILPASS]);
3376 TRACE("(onesided %d, twosided %d, ref %x, mask %x, \
3377 GL_FRONT: func: %x, fail %x, zfail %x, zpass %x \
3378 GL_BACK: func: %x, fail %x, zfail %x, zpass %x )\n",
3379 onesided_enable, twosided_enable, ref, mask,
3380 func, stencilFail, depthFail, stencilPass,
3381 func_ccw, stencilFail_ccw, depthFail_ccw, stencilPass_ccw);
3383 if (twosided_enable) {
3384 renderstate_stencil_twosided(This, GL_FRONT, func, ref, mask, stencilFail, depthFail, stencilPass);
3385 renderstate_stencil_twosided(This, GL_BACK, func_ccw, ref, mask, stencilFail_ccw, depthFail_ccw, stencilPass_ccw);
3387 if (onesided_enable) {
3388 glEnable(GL_STENCIL_TEST);
3389 checkGLcall("glEnable GL_STENCIL_TEST");
3390 glStencilFunc(func, ref, mask);
3391 checkGLcall("glStencilFunc(...)");
3392 glStencilOp(stencilFail, depthFail, stencilPass);
3393 checkGLcall("glStencilOp(...)");
3395 glDisable(GL_STENCIL_TEST);
3396 checkGLcall("glDisable GL_STENCIL_TEST");
3402 * Get / Set Render States
3403 * TODO: Verify against dx9 definitions
3405 static HRESULT WINAPI IWineD3DDeviceImpl_SetRenderState(IWineD3DDevice *iface, WINED3DRENDERSTATETYPE State, DWORD Value) {
3407 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3408 DWORD OldValue = This->stateBlock->renderState[State];
3410 /* Simple way of referring to either a DWORD or a 4 byte float */
3416 TRACE("(%p)->state = %s(%d), value = %d\n", This, debug_d3drenderstate(State), State, Value);
3417 This->updateStateBlock->changed.renderState[State] = TRUE;
3418 This->updateStateBlock->set.renderState[State] = TRUE;
3419 This->updateStateBlock->renderState[State] = Value;
3421 /* Handle recording of state blocks */
3422 if (This->isRecordingState) {
3423 TRACE("Recording... not performing anything\n");
3430 case WINED3DRS_FILLMODE :
3431 switch ((WINED3DFILLMODE) Value) {
3432 case WINED3DFILL_POINT : glPolygonMode(GL_FRONT_AND_BACK, GL_POINT); break;
3433 case WINED3DFILL_WIREFRAME : glPolygonMode(GL_FRONT_AND_BACK, GL_LINE); break;
3434 case WINED3DFILL_SOLID : glPolygonMode(GL_FRONT_AND_BACK, GL_FILL); break;
3436 FIXME("Unrecognized WINED3DRS_FILLMODE value %d\n", Value);
3438 checkGLcall("glPolygonMode (fillmode)");
3441 case WINED3DRS_LIGHTING :
3443 glEnable(GL_LIGHTING);
3444 checkGLcall("glEnable GL_LIGHTING");
3446 glDisable(GL_LIGHTING);
3447 checkGLcall("glDisable GL_LIGHTING");
3451 case WINED3DRS_ZENABLE :
3452 switch ((WINED3DZBUFFERTYPE) Value) {
3453 case WINED3DZB_FALSE:
3454 glDisable(GL_DEPTH_TEST);
3455 checkGLcall("glDisable GL_DEPTH_TEST");
3457 case WINED3DZB_TRUE:
3458 glEnable(GL_DEPTH_TEST);
3459 checkGLcall("glEnable GL_DEPTH_TEST");
3461 case WINED3DZB_USEW:
3462 glEnable(GL_DEPTH_TEST);
3463 checkGLcall("glEnable GL_DEPTH_TEST");
3464 FIXME("W buffer is not well handled\n");
3467 FIXME("Unrecognized WINED3DZBUFFERTYPE value %d\n", Value);
3471 case WINED3DRS_CULLMODE :
3473 /* If we are culling "back faces with clockwise vertices" then
3474 set front faces to be counter clockwise and enable culling
3476 switch ((WINED3DCULL) Value) {
3477 case WINED3DCULL_NONE:
3478 glDisable(GL_CULL_FACE);
3479 checkGLcall("glDisable GL_CULL_FACE");
3481 case WINED3DCULL_CW:
3482 glEnable(GL_CULL_FACE);
3483 checkGLcall("glEnable GL_CULL_FACE");
3484 if (This->render_offscreen) {
3486 checkGLcall("glFrontFace GL_CW");
3488 glFrontFace(GL_CCW);
3489 checkGLcall("glFrontFace GL_CCW");
3491 glCullFace(GL_BACK);
3493 case WINED3DCULL_CCW:
3494 glEnable(GL_CULL_FACE);
3495 checkGLcall("glEnable GL_CULL_FACE");
3496 if (This->render_offscreen) {
3497 glFrontFace(GL_CCW);
3498 checkGLcall("glFrontFace GL_CCW");
3501 checkGLcall("glFrontFace GL_CW");
3503 glCullFace(GL_BACK);
3506 FIXME("Unrecognized/Unhandled WINED3DCULL value %d\n", Value);
3510 case WINED3DRS_SHADEMODE :
3511 switch ((WINED3DSHADEMODE) Value) {
3512 case WINED3DSHADE_FLAT:
3513 glShadeModel(GL_FLAT);
3514 checkGLcall("glShadeModel");
3516 case WINED3DSHADE_GOURAUD:
3517 glShadeModel(GL_SMOOTH);
3518 checkGLcall("glShadeModel");
3520 case WINED3DSHADE_PHONG:
3521 FIXME("WINED3DSHADE_PHONG isn't supported\n");
3524 FIXME("Unrecognized/Unhandled WINED3DSHADEMODE value %d\n", Value);
3528 case WINED3DRS_DITHERENABLE :
3530 glEnable(GL_DITHER);
3531 checkGLcall("glEnable GL_DITHER");
3533 glDisable(GL_DITHER);
3534 checkGLcall("glDisable GL_DITHER");
3538 case WINED3DRS_ZWRITEENABLE :
3541 checkGLcall("glDepthMask");
3544 checkGLcall("glDepthMask");
3548 case WINED3DRS_ZFUNC :
3550 int glParm = CompareFunc(Value);
3553 glDepthFunc(glParm);
3554 checkGLcall("glDepthFunc");
3559 case WINED3DRS_AMBIENT :
3562 D3DCOLORTOGLFLOAT4(Value, col);
3563 TRACE("Setting ambient to (%f,%f,%f,%f)\n", col[0], col[1], col[2], col[3]);
3564 glLightModelfv(GL_LIGHT_MODEL_AMBIENT, col);
3565 checkGLcall("glLightModel for MODEL_AMBIENT");
3570 case WINED3DRS_ALPHABLENDENABLE :
3573 checkGLcall("glEnable GL_BLEND");
3575 glDisable(GL_BLEND);
3576 checkGLcall("glDisable GL_BLEND");
3580 case WINED3DRS_SRCBLEND :
3581 case WINED3DRS_DESTBLEND :
3583 int newVal = GL_ZERO;
3585 case WINED3DBLEND_ZERO : newVal = GL_ZERO; break;
3586 case WINED3DBLEND_ONE : newVal = GL_ONE; break;
3587 case WINED3DBLEND_SRCCOLOR : newVal = GL_SRC_COLOR; break;
3588 case WINED3DBLEND_INVSRCCOLOR : newVal = GL_ONE_MINUS_SRC_COLOR; break;
3589 case WINED3DBLEND_SRCALPHA : newVal = GL_SRC_ALPHA; break;
3590 case WINED3DBLEND_INVSRCALPHA : newVal = GL_ONE_MINUS_SRC_ALPHA; break;
3591 case WINED3DBLEND_DESTALPHA : newVal = GL_DST_ALPHA; break;
3592 case WINED3DBLEND_INVDESTALPHA : newVal = GL_ONE_MINUS_DST_ALPHA; break;
3593 case WINED3DBLEND_DESTCOLOR : newVal = GL_DST_COLOR; break;
3594 case WINED3DBLEND_INVDESTCOLOR : newVal = GL_ONE_MINUS_DST_COLOR; break;
3595 case WINED3DBLEND_SRCALPHASAT : newVal = GL_SRC_ALPHA_SATURATE; break;
3597 case WINED3DBLEND_BOTHSRCALPHA : newVal = GL_SRC_ALPHA;
3598 This->srcBlend = newVal;
3599 This->dstBlend = newVal;
3602 case WINED3DBLEND_BOTHINVSRCALPHA : newVal = GL_ONE_MINUS_SRC_ALPHA;
3603 This->srcBlend = newVal;
3604 This->dstBlend = newVal;
3606 case WINED3DBLEND_BLENDFACTOR : newVal = GL_CONSTANT_COLOR; break;
3607 case WINED3DBLEND_INVBLENDFACTOR : newVal = GL_ONE_MINUS_CONSTANT_COLOR; break;
3609 FIXME("Unrecognized src/dest blend value %d (%d)\n", Value, State);
3612 if (State == WINED3DRS_SRCBLEND) This->srcBlend = newVal;
3613 if (State == WINED3DRS_DESTBLEND) This->dstBlend = newVal;
3614 TRACE("glBlendFunc src=%x, dst=%x\n", This->srcBlend, This->dstBlend);
3615 glBlendFunc(This->srcBlend, This->dstBlend);
3617 checkGLcall("glBlendFunc");
3621 case WINED3DRS_ALPHATESTENABLE :
3622 case WINED3DRS_ALPHAFUNC :
3623 case WINED3DRS_ALPHAREF :
3624 case WINED3DRS_COLORKEYENABLE :
3628 BOOL enable_ckey = FALSE;
3630 IWineD3DSurfaceImpl *surf;
3632 /* Find out if the texture on the first stage has a ckey set */
3633 if(This->stateBlock->textures[0]) {
3634 surf = (IWineD3DSurfaceImpl *) ((IWineD3DTextureImpl *)This->stateBlock->textures[0])->surfaces[0];
3635 if(surf->CKeyFlags & DDSD_CKSRCBLT) enable_ckey = TRUE;
3638 if (This->stateBlock->renderState[WINED3DRS_ALPHATESTENABLE] ||
3639 (This->stateBlock->renderState[WINED3DRS_COLORKEYENABLE] && enable_ckey)) {
3640 glEnable(GL_ALPHA_TEST);
3641 checkGLcall("glEnable GL_ALPHA_TEST");
3643 glDisable(GL_ALPHA_TEST);
3644 checkGLcall("glDisable GL_ALPHA_TEST");
3645 /* Alpha test is disabled, don't bother setting the params - it will happen on the next
3651 if(This->stateBlock->renderState[WINED3DRS_COLORKEYENABLE] && enable_ckey) {
3652 glParm = GL_NOTEQUAL;
3655 ref = ((float) This->stateBlock->renderState[WINED3DRS_ALPHAREF]) / 255.0f;
3656 glParm = CompareFunc(This->stateBlock->renderState[WINED3DRS_ALPHAFUNC]);
3659 This->alphafunc = glParm;
3660 glAlphaFunc(glParm, ref);
3661 checkGLcall("glAlphaFunc");
3666 case WINED3DRS_CLIPPLANEENABLE :
3667 case WINED3DRS_CLIPPING :
3669 /* Ensure we only do the changed clip planes */
3670 DWORD enable = 0xFFFFFFFF;
3671 DWORD disable = 0x00000000;
3673 /* If enabling / disabling all */
3674 if (State == WINED3DRS_CLIPPING) {
3676 enable = This->stateBlock->renderState[WINED3DRS_CLIPPLANEENABLE];
3679 disable = This->stateBlock->renderState[WINED3DRS_CLIPPLANEENABLE];
3683 enable = Value & ~OldValue;
3684 disable = ~Value & OldValue;
3687 if (enable & WINED3DCLIPPLANE0) { glEnable(GL_CLIP_PLANE0); checkGLcall("glEnable(clip plane 0)"); }
3688 if (enable & WINED3DCLIPPLANE1) { glEnable(GL_CLIP_PLANE1); checkGLcall("glEnable(clip plane 1)"); }
3689 if (enable & WINED3DCLIPPLANE2) { glEnable(GL_CLIP_PLANE2); checkGLcall("glEnable(clip plane 2)"); }
3690 if (enable & WINED3DCLIPPLANE3) { glEnable(GL_CLIP_PLANE3); checkGLcall("glEnable(clip plane 3)"); }
3691 if (enable & WINED3DCLIPPLANE4) { glEnable(GL_CLIP_PLANE4); checkGLcall("glEnable(clip plane 4)"); }
3692 if (enable & WINED3DCLIPPLANE5) { glEnable(GL_CLIP_PLANE5); checkGLcall("glEnable(clip plane 5)"); }
3694 if (disable & WINED3DCLIPPLANE0) { glDisable(GL_CLIP_PLANE0); checkGLcall("glDisable(clip plane 0)"); }
3695 if (disable & WINED3DCLIPPLANE1) { glDisable(GL_CLIP_PLANE1); checkGLcall("glDisable(clip plane 1)"); }
3696 if (disable & WINED3DCLIPPLANE2) { glDisable(GL_CLIP_PLANE2); checkGLcall("glDisable(clip plane 2)"); }
3697 if (disable & WINED3DCLIPPLANE3) { glDisable(GL_CLIP_PLANE3); checkGLcall("glDisable(clip plane 3)"); }
3698 if (disable & WINED3DCLIPPLANE4) { glDisable(GL_CLIP_PLANE4); checkGLcall("glDisable(clip plane 4)"); }
3699 if (disable & WINED3DCLIPPLANE5) { glDisable(GL_CLIP_PLANE5); checkGLcall("glDisable(clip plane 5)"); }
3701 /** update clipping status */
3703 This->stateBlock->clip_status.ClipUnion = 0;
3704 This->stateBlock->clip_status.ClipIntersection = 0xFFFFFFFF;
3706 This->stateBlock->clip_status.ClipUnion = 0;
3707 This->stateBlock->clip_status.ClipIntersection = 0;
3712 case WINED3DRS_BLENDOP :
3714 int glParm = GL_FUNC_ADD;
3716 switch ((WINED3DBLENDOP) Value) {
3717 case WINED3DBLENDOP_ADD : glParm = GL_FUNC_ADD; break;
3718 case WINED3DBLENDOP_SUBTRACT : glParm = GL_FUNC_SUBTRACT; break;
3719 case WINED3DBLENDOP_REVSUBTRACT : glParm = GL_FUNC_REVERSE_SUBTRACT; break;
3720 case WINED3DBLENDOP_MIN : glParm = GL_MIN; break;
3721 case WINED3DBLENDOP_MAX : glParm = GL_MAX; break;
3723 FIXME("Unrecognized/Unhandled WINED3DBLENDOP value %d\n", Value);
3726 if(GL_SUPPORT(EXT_BLEND_MINMAX)) {
3727 TRACE("glBlendEquation(%x)\n", glParm);
3728 GL_EXTCALL(glBlendEquation(glParm));
3729 checkGLcall("glBlendEquation");
3731 WARN("Unsupported in local OpenGL implementation: glBlendEquation\n");
3736 case WINED3DRS_TEXTUREFACTOR :
3740 /* Note the texture color applies to all textures whereas
3741 GL_TEXTURE_ENV_COLOR applies to active only */
3743 D3DCOLORTOGLFLOAT4(Value, col);
3745 if (!GL_SUPPORT(NV_REGISTER_COMBINERS)) {
3746 /* And now the default texture color as well */
3747 for (i = 0; i < GL_LIMITS(texture_stages); i++) {
3748 /* Note the WINED3DRS value applies to all textures, but GL has one
3749 per texture, so apply it now ready to be used! */
3750 if (GL_SUPPORT(ARB_MULTITEXTURE)) {
3751 GL_EXTCALL(glActiveTextureARB(GL_TEXTURE0_ARB + i));
3752 checkGLcall("glActiveTextureARB");
3754 FIXME("Program using multiple concurrent textures which this opengl implementation doesn't support\n");
3757 glTexEnvfv(GL_TEXTURE_ENV, GL_TEXTURE_ENV_COLOR, &col[0]);
3758 checkGLcall("glTexEnvfv(GL_TEXTURE_ENV, GL_TEXTURE_ENV_COLOR, color);");
3764 case WINED3DRS_SPECULARENABLE :
3766 /* Originally this used glLightModeli(GL_LIGHT_MODEL_COLOR_CONTROL,GL_SEPARATE_SPECULAR_COLOR)
3767 and (GL_LIGHT_MODEL_COLOR_CONTROL,GL_SINGLE_COLOR) to swap between enabled/disabled
3768 specular color. This is wrong:
3769 Separate specular color means the specular colour is maintained separately, whereas
3770 single color means it is merged in. However in both cases they are being used to
3772 To disable specular color, set it explicitly to black and turn off GL_COLOR_SUM_EXT
3773 NOTE: If not supported don't give FIXMEs the impact is really minimal and very few people are
3777 * If register combiners are enabled, enabling / disabling GL_COLOR_SUM has no effect.
3778 * Instead, we need to setup the FinalCombiner properly.
3780 * The default setup for the FinalCombiner is:
3782 * <variable> <input> <mapping> <usage>
3783 * GL_VARIABLE_A_NV GL_FOG, GL_UNSIGNED_IDENTITY_NV GL_ALPHA
3784 * GL_VARIABLE_B_NV GL_SPARE0_PLUS_SECONDARY_COLOR_NV GL_UNSIGNED_IDENTITY_NV GL_RGB
3785 * GL_VARIABLE_C_NV GL_FOG GL_UNSIGNED_IDENTITY_NV GL_RGB
3786 * GL_VARIABLE_D_NV GL_ZERO GL_UNSIGNED_IDENTITY_NV GL_RGB
3787 * GL_VARIABLE_E_NV GL_ZERO GL_UNSIGNED_IDENTITY_NV GL_RGB
3788 * GL_VARIABLE_F_NV GL_ZERO GL_UNSIGNED_IDENTITY_NV GL_RGB
3789 * GL_VARIABLE_G_NV GL_SPARE0_NV GL_UNSIGNED_IDENTITY_NV GL_ALPHA
3791 * That's pretty much fine as it is, except for variable B, which needs to take
3792 * either GL_SPARE0_PLUS_SECONDARY_COLOR_NV or GL_SPARE0_NV, depending on
3793 * whether WINED3DRS_SPECULARENABLE is enabled or not.
3797 glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, (float*) &This->updateStateBlock->material.Specular);
3798 checkGLcall("glMaterialfv");
3799 if (GL_SUPPORT(EXT_SECONDARY_COLOR)) {
3800 glEnable(GL_COLOR_SUM_EXT);
3802 TRACE("Specular colors cannot be enabled in this version of opengl\n");
3804 checkGLcall("glEnable(GL_COLOR_SUM)");
3806 if (GL_SUPPORT(NV_REGISTER_COMBINERS)) {
3807 GL_EXTCALL(glFinalCombinerInputNV(GL_VARIABLE_B_NV, GL_SPARE0_PLUS_SECONDARY_COLOR_NV, GL_UNSIGNED_IDENTITY_NV, GL_RGB));
3808 checkGLcall("glFinalCombinerInputNV()");
3811 float black[4] = {0.0f, 0.0f, 0.0f, 0.0f};
3813 /* for the case of enabled lighting: */
3814 glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, &black[0]);
3815 checkGLcall("glMaterialfv");
3817 /* for the case of disabled lighting: */
3818 if (GL_SUPPORT(EXT_SECONDARY_COLOR)) {
3819 glDisable(GL_COLOR_SUM_EXT);
3821 TRACE("Specular colors cannot be disabled in this version of opengl\n");
3823 checkGLcall("glDisable(GL_COLOR_SUM)");
3825 if (GL_SUPPORT(NV_REGISTER_COMBINERS)) {
3826 GL_EXTCALL(glFinalCombinerInputNV(GL_VARIABLE_B_NV, GL_SPARE0_NV, GL_UNSIGNED_IDENTITY_NV, GL_RGB));
3827 checkGLcall("glFinalCombinerInputNV()");
3833 case WINED3DRS_STENCILENABLE :
3834 case WINED3DRS_TWOSIDEDSTENCILMODE :
3835 case WINED3DRS_STENCILFUNC :
3836 case WINED3DRS_CCW_STENCILFUNC :
3837 case WINED3DRS_STENCILREF :
3838 case WINED3DRS_STENCILMASK :
3839 case WINED3DRS_STENCILFAIL :
3840 case WINED3DRS_STENCILZFAIL :
3841 case WINED3DRS_STENCILPASS :
3842 case WINED3DRS_CCW_STENCILFAIL :
3843 case WINED3DRS_CCW_STENCILZFAIL :
3844 case WINED3DRS_CCW_STENCILPASS :
3845 renderstate_stencil(This, State, Value);
3847 case WINED3DRS_STENCILWRITEMASK :
3849 glStencilMask(Value);
3850 TRACE("glStencilMask(%u)\n", Value);
3851 checkGLcall("glStencilMask");
3855 case WINED3DRS_FOGENABLE :
3859 checkGLcall("glEnable GL_FOG");
3862 checkGLcall("glDisable GL_FOG");
3867 case WINED3DRS_RANGEFOGENABLE :
3870 TRACE("Enabled RANGEFOG\n");
3872 TRACE("Disabled RANGEFOG\n");
3877 case WINED3DRS_FOGCOLOR :
3880 D3DCOLORTOGLFLOAT4(Value, col);
3881 /* Set the default alpha blend color */
3882 glFogfv(GL_FOG_COLOR, &col[0]);
3883 checkGLcall("glFog GL_FOG_COLOR");
3887 case WINED3DRS_FOGTABLEMODE :
3888 case WINED3DRS_FOGVERTEXMODE :
3890 /* 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." */
3891 if(This->stateBlock->renderState[WINED3DRS_FOGTABLEMODE] == WINED3DFOG_NONE) {
3892 glHint(GL_FOG_HINT, GL_FASTEST);
3893 checkGLcall("glHint(GL_FOG_HINT, GL_FASTEST)");
3894 switch (This->stateBlock->renderState[WINED3DRS_FOGVERTEXMODE]) {
3895 /* Processed vertices have their fog factor stored in the specular value. Fall too the none case.
3896 * If we are drawing untransformed vertices atm, d3ddevice_set_ortho will update the fog
3898 case WINED3DFOG_EXP: {
3899 if(!This->last_was_rhw) {
3900 glFogi(GL_FOG_MODE, GL_EXP);
3901 checkGLcall("glFogi(GL_FOG_MODE, GL_EXP");
3902 if(GL_SUPPORT(EXT_FOG_COORD)) {
3903 glFogi(GL_FOG_COORDINATE_SOURCE_EXT, GL_FRAGMENT_DEPTH_EXT);
3904 checkGLcall("glFogi(GL_FOG_COORDINATE_SOURCE_EXT, GL_FRAGMENT_DEPTH_EXT");
3905 IWineD3DDevice_SetRenderState(iface, WINED3DRS_FOGSTART, This->stateBlock->renderState[WINED3DRS_FOGSTART]);
3906 IWineD3DDevice_SetRenderState(iface, WINED3DRS_FOGEND, This->stateBlock->renderState[WINED3DRS_FOGEND]);
3911 case WINED3DFOG_EXP2: {
3912 if(!This->last_was_rhw) {
3913 glFogi(GL_FOG_MODE, GL_EXP2);
3914 checkGLcall("glFogi(GL_FOG_MODE, GL_EXP2");
3915 if(GL_SUPPORT(EXT_FOG_COORD)) {
3916 glFogi(GL_FOG_COORDINATE_SOURCE_EXT, GL_FRAGMENT_DEPTH_EXT);
3917 checkGLcall("glFogi(GL_FOG_COORDINATE_SOURCE_EXT, GL_FRAGMENT_DEPTH_EXT");
3918 IWineD3DDevice_SetRenderState(iface, WINED3DRS_FOGSTART, This->stateBlock->renderState[WINED3DRS_FOGSTART]);
3919 IWineD3DDevice_SetRenderState(iface, WINED3DRS_FOGEND, This->stateBlock->renderState[WINED3DRS_FOGEND]);
3924 case WINED3DFOG_LINEAR: {
3925 if(!This->last_was_rhw) {
3926 glFogi(GL_FOG_MODE, GL_LINEAR);
3927 checkGLcall("glFogi(GL_FOG_MODE, GL_LINEAR");
3928 if(GL_SUPPORT(EXT_FOG_COORD)) {
3929 glFogi(GL_FOG_COORDINATE_SOURCE_EXT, GL_FRAGMENT_DEPTH_EXT);
3930 checkGLcall("glFogi(GL_FOG_COORDINATE_SOURCE_EXT, GL_FRAGMENT_DEPTH_EXT");
3931 IWineD3DDevice_SetRenderState(iface, WINED3DRS_FOGSTART, This->stateBlock->renderState[WINED3DRS_FOGSTART]);
3932 IWineD3DDevice_SetRenderState(iface, WINED3DRS_FOGEND, This->stateBlock->renderState[WINED3DRS_FOGEND]);
3937 case WINED3DFOG_NONE: {
3938 /* Both are none? According to msdn the alpha channel of the specular
3939 * color contains a fog factor. Set it in drawStridedSlow.
3940 * Same happens with Vertexfog on transformed vertices
3942 if(GL_SUPPORT(EXT_FOG_COORD)) {
3943 glFogi(GL_FOG_COORDINATE_SOURCE_EXT, GL_FOG_COORDINATE_EXT);
3944 checkGLcall("glFogi(GL_FOG_COORDINATE_SOURCE_EXT, GL_FOG_COORDINATE_EXT)\n");
3945 glFogi(GL_FOG_MODE, GL_LINEAR);
3946 checkGLcall("glFogi(GL_FOG_MODE, GL_LINEAR)");
3947 glFogf(GL_FOG_START, (float) 0xff);
3948 checkGLcall("glFogfv GL_FOG_START");
3949 glFogf(GL_FOG_END, 0.0);
3950 checkGLcall("glFogfv GL_FOG_END");
3952 /* Disable GL fog, handle this in software in drawStridedSlow */
3954 checkGLcall("glDisable(GL_FOG)");
3958 default: FIXME("Unexpected WINED3DRS_FOGVERTEXMODE %d\n", This->stateBlock->renderState[WINED3DRS_FOGVERTEXMODE]);
3961 glHint(GL_FOG_HINT, GL_NICEST);
3962 checkGLcall("glHint(GL_FOG_HINT, GL_NICEST)");
3963 switch (This->stateBlock->renderState[WINED3DRS_FOGTABLEMODE]) {
3964 case WINED3DFOG_EXP:
3965 glFogi(GL_FOG_MODE, GL_EXP);
3966 checkGLcall("glFogi(GL_FOG_MODE, GL_EXP");
3967 if(GL_SUPPORT(EXT_FOG_COORD)) {
3968 glFogi(GL_FOG_COORDINATE_SOURCE_EXT, GL_FRAGMENT_DEPTH_EXT);
3969 checkGLcall("glFogi(GL_FOG_COORDINATE_SOURCE_EXT, GL_FRAGMENT_DEPTH_EXT");
3970 IWineD3DDevice_SetRenderState(iface, WINED3DRS_FOGSTART, This->stateBlock->renderState[WINED3DRS_FOGSTART]);
3971 IWineD3DDevice_SetRenderState(iface, WINED3DRS_FOGEND, This->stateBlock->renderState[WINED3DRS_FOGEND]);
3974 case WINED3DFOG_EXP2:
3975 glFogi(GL_FOG_MODE, GL_EXP2);
3976 checkGLcall("glFogi(GL_FOG_MODE, GL_EXP2");
3977 if(GL_SUPPORT(EXT_FOG_COORD)) {
3978 glFogi(GL_FOG_COORDINATE_SOURCE_EXT, GL_FRAGMENT_DEPTH_EXT);
3979 checkGLcall("glFogi(GL_FOG_COORDINATE_SOURCE_EXT, GL_FRAGMENT_DEPTH_EXT");
3980 IWineD3DDevice_SetRenderState(iface, WINED3DRS_FOGSTART, This->stateBlock->renderState[WINED3DRS_FOGSTART]);
3981 IWineD3DDevice_SetRenderState(iface, WINED3DRS_FOGEND, This->stateBlock->renderState[WINED3DRS_FOGEND]);
3984 case WINED3DFOG_LINEAR:
3985 glFogi(GL_FOG_MODE, GL_LINEAR);
3986 checkGLcall("glFogi(GL_FOG_MODE, GL_LINEAR");
3987 if(GL_SUPPORT(EXT_FOG_COORD)) {
3988 glFogi(GL_FOG_COORDINATE_SOURCE_EXT, GL_FRAGMENT_DEPTH_EXT);
3989 checkGLcall("glFogi(GL_FOG_COORDINATE_SOURCE_EXT, GL_FRAGMENT_DEPTH_EXT");
3990 IWineD3DDevice_SetRenderState(iface, WINED3DRS_FOGSTART, This->stateBlock->renderState[WINED3DRS_FOGSTART]);
3991 IWineD3DDevice_SetRenderState(iface, WINED3DRS_FOGEND, This->stateBlock->renderState[WINED3DRS_FOGEND]);
3994 case WINED3DFOG_NONE:
3995 default: /* Won't happen */
3996 FIXME("Unexpected WINED3DRS_FOGTABLEMODE %d\n", This->stateBlock->renderState[WINED3DRS_FOGTABLEMODE]);
3999 if (GL_SUPPORT(NV_FOG_DISTANCE)) {
4000 glFogi(GL_FOG_DISTANCE_MODE_NV, GL_EYE_PLANE_ABSOLUTE_NV);
4005 case WINED3DRS_FOGSTART :
4008 glFogfv(GL_FOG_START, &tmpvalue.f);
4009 checkGLcall("glFogf(GL_FOG_START, (float) Value)");
4010 TRACE("Fog Start == %f\n", tmpvalue.f);
4014 case WINED3DRS_FOGEND :
4017 glFogfv(GL_FOG_END, &tmpvalue.f);
4018 checkGLcall("glFogf(GL_FOG_END, (float) Value)");
4019 TRACE("Fog End == %f\n", tmpvalue.f);
4023 case WINED3DRS_FOGDENSITY :
4026 glFogfv(GL_FOG_DENSITY, &tmpvalue.f);
4027 checkGLcall("glFogf(GL_FOG_DENSITY, (float) Value)");
4031 case WINED3DRS_VERTEXBLEND :
4033 This->updateStateBlock->vertex_blend = (WINED3DVERTEXBLENDFLAGS) Value;
4034 TRACE("Vertex Blending state to %d\n", Value);
4038 case WINED3DRS_TWEENFACTOR :
4041 This->updateStateBlock->tween_factor = tmpvalue.f;
4042 TRACE("Vertex Blending Tween Factor to %f\n", This->updateStateBlock->tween_factor);
4046 case WINED3DRS_INDEXEDVERTEXBLENDENABLE :
4048 TRACE("Indexed Vertex Blend Enable to %u\n", (BOOL) Value);
4052 case WINED3DRS_COLORVERTEX :
4053 case WINED3DRS_DIFFUSEMATERIALSOURCE :
4054 case WINED3DRS_SPECULARMATERIALSOURCE :
4055 case WINED3DRS_AMBIENTMATERIALSOURCE :
4056 case WINED3DRS_EMISSIVEMATERIALSOURCE :
4058 GLenum Parm = GL_AMBIENT_AND_DIFFUSE;
4060 if (This->stateBlock->renderState[WINED3DRS_COLORVERTEX]) {
4061 TRACE("diff %d, amb %d, emis %d, spec %d\n",
4062 This->stateBlock->renderState[WINED3DRS_DIFFUSEMATERIALSOURCE],
4063 This->stateBlock->renderState[WINED3DRS_AMBIENTMATERIALSOURCE],
4064 This->stateBlock->renderState[WINED3DRS_EMISSIVEMATERIALSOURCE],
4065 This->stateBlock->renderState[WINED3DRS_SPECULARMATERIALSOURCE]);
4067 if (This->stateBlock->renderState[WINED3DRS_DIFFUSEMATERIALSOURCE] == WINED3DMCS_COLOR1) {
4068 if (This->stateBlock->renderState[WINED3DRS_AMBIENTMATERIALSOURCE] == WINED3DMCS_COLOR1) {
4069 Parm = GL_AMBIENT_AND_DIFFUSE;
4073 } else if (This->stateBlock->renderState[WINED3DRS_AMBIENTMATERIALSOURCE] == WINED3DMCS_COLOR1) {
4075 } else if (This->stateBlock->renderState[WINED3DRS_EMISSIVEMATERIALSOURCE] == WINED3DMCS_COLOR1) {
4077 } else if (This->stateBlock->renderState[WINED3DRS_SPECULARMATERIALSOURCE] == WINED3DMCS_COLOR1) {
4084 if (This->tracking_color != DISABLED_TRACKING) This->tracking_color = NEEDS_DISABLE;
4086 This->tracking_color = NEEDS_TRACKING;
4087 This->tracking_parm = Parm;
4091 if (This->tracking_color != DISABLED_TRACKING) This->tracking_color = NEEDS_DISABLE;
4096 case WINED3DRS_LINEPATTERN :
4100 WINED3DLINEPATTERN lp;
4102 tmppattern.d = Value;
4104 TRACE("Line pattern: repeat %d bits %x\n", tmppattern.lp.wRepeatFactor, tmppattern.lp.wLinePattern);
4106 if (tmppattern.lp.wRepeatFactor) {
4107 glLineStipple(tmppattern.lp.wRepeatFactor, tmppattern.lp.wLinePattern);
4108 checkGLcall("glLineStipple(repeat, linepattern)");
4109 glEnable(GL_LINE_STIPPLE);
4110 checkGLcall("glEnable(GL_LINE_STIPPLE);");
4112 glDisable(GL_LINE_STIPPLE);
4113 checkGLcall("glDisable(GL_LINE_STIPPLE);");
4118 case WINED3DRS_ZBIAS : /* D3D8 only */
4122 TRACE("ZBias value %f\n", tmpvalue.f);
4123 glPolygonOffset(0, -tmpvalue.f);
4124 checkGLcall("glPolygonOffset(0, -Value)");
4125 glEnable(GL_POLYGON_OFFSET_FILL);
4126 checkGLcall("glEnable(GL_POLYGON_OFFSET_FILL);");
4127 glEnable(GL_POLYGON_OFFSET_LINE);
4128 checkGLcall("glEnable(GL_POLYGON_OFFSET_LINE);");
4129 glEnable(GL_POLYGON_OFFSET_POINT);
4130 checkGLcall("glEnable(GL_POLYGON_OFFSET_POINT);");
4132 glDisable(GL_POLYGON_OFFSET_FILL);
4133 checkGLcall("glDisable(GL_POLYGON_OFFSET_FILL);");
4134 glDisable(GL_POLYGON_OFFSET_LINE);
4135 checkGLcall("glDisable(GL_POLYGON_OFFSET_LINE);");
4136 glDisable(GL_POLYGON_OFFSET_POINT);
4137 checkGLcall("glDisable(GL_POLYGON_OFFSET_POINT);");
4142 case WINED3DRS_NORMALIZENORMALS :
4144 glEnable(GL_NORMALIZE);
4145 checkGLcall("glEnable(GL_NORMALIZE);");
4147 glDisable(GL_NORMALIZE);
4148 checkGLcall("glDisable(GL_NORMALIZE);");
4152 case WINED3DRS_POINTSIZE :
4153 /* FIXME: check that pointSize isn't outside glGetFloatv( GL_POINT_SIZE_MAX_ARB, &maxSize ); or -ve */
4155 TRACE("Set point size to %f\n", tmpvalue.f);
4156 glPointSize(tmpvalue.f);
4157 checkGLcall("glPointSize(...);");
4160 case WINED3DRS_POINTSIZE_MIN :
4161 if (GL_SUPPORT(EXT_POINT_PARAMETERS)) {
4163 GL_EXTCALL(glPointParameterfEXT)(GL_POINT_SIZE_MIN_EXT, tmpvalue.f);
4164 checkGLcall("glPointParameterfEXT(...);");
4166 FIXME("WINED3DRS_POINTSIZE_MIN not supported on this opengl\n");
4170 case WINED3DRS_POINTSIZE_MAX :
4171 if (GL_SUPPORT(EXT_POINT_PARAMETERS)) {
4173 GL_EXTCALL(glPointParameterfEXT)(GL_POINT_SIZE_MAX_EXT, tmpvalue.f);
4174 checkGLcall("glPointParameterfEXT(...);");
4176 FIXME("WINED3DRS_POINTSIZE_MAX not supported on this opengl\n");
4180 case WINED3DRS_POINTSCALE_A :
4181 case WINED3DRS_POINTSCALE_B :
4182 case WINED3DRS_POINTSCALE_C :
4183 case WINED3DRS_POINTSCALEENABLE :
4186 * POINTSCALEENABLE controls how point size value is treated. If set to
4187 * true, the point size is scaled with respect to height of viewport.
4188 * When set to false point size is in pixels.
4190 * http://msdn.microsoft.com/library/en-us/directx9_c/point_sprites.asp
4193 /* Default values */
4194 GLfloat att[3] = {1.0f, 0.0f, 0.0f};
4197 * Minimum valid point size for OpenGL is 1.0f. For Direct3D it is 0.0f.
4198 * This means that OpenGL will clamp really small point sizes to 1.0f.
4199 * To correct for this we need to multiply by the scale factor when sizes
4200 * are less than 1.0f. scale_factor = 1.0f / point_size.
4202 GLfloat pointSize = *((float*)&This->stateBlock->renderState[WINED3DRS_POINTSIZE]);
4203 if(pointSize > 0.0f) {
4204 GLfloat scaleFactor;
4206 if(pointSize < 1.0f) {
4207 scaleFactor = pointSize * pointSize;
4212 if(This->stateBlock->renderState[WINED3DRS_POINTSCALEENABLE]) {
4213 att[0] = *((float*)&This->stateBlock->renderState[WINED3DRS_POINTSCALE_A]) /
4214 (This->stateBlock->viewport.Height * This->stateBlock->viewport.Height * scaleFactor);
4215 att[1] = *((float*)&This->stateBlock->renderState[WINED3DRS_POINTSCALE_B]) /
4216 (This->stateBlock->viewport.Height * This->stateBlock->viewport.Height * scaleFactor);
4217 att[2] = *((float*)&This->stateBlock->renderState[WINED3DRS_POINTSCALE_C]) /
4218 (This->stateBlock->viewport.Height * This->stateBlock->viewport.Height * scaleFactor);
4222 if(GL_SUPPORT(ARB_POINT_PARAMETERS)) {
4223 GL_EXTCALL(glPointParameterfvARB)(GL_POINT_DISTANCE_ATTENUATION_ARB, att);
4224 checkGLcall("glPointParameterfvARB(GL_DISTANCE_ATTENUATION_ARB, ...");
4226 else if(GL_SUPPORT(EXT_POINT_PARAMETERS)) {
4227 GL_EXTCALL(glPointParameterfvEXT)(GL_DISTANCE_ATTENUATION_EXT, att);
4228 checkGLcall("glPointParameterfvEXT(GL_DISTANCE_ATTENUATION_EXT, ...");
4230 TRACE("POINT_PARAMETERS not supported in this version of opengl\n");
4234 case WINED3DRS_COLORWRITEENABLE :
4236 TRACE("Color mask: r(%d) g(%d) b(%d) a(%d)\n",
4237 Value & WINED3DCOLORWRITEENABLE_RED ? 1 : 0,
4238 Value & WINED3DCOLORWRITEENABLE_GREEN ? 1 : 0,
4239 Value & WINED3DCOLORWRITEENABLE_BLUE ? 1 : 0,
4240 Value & WINED3DCOLORWRITEENABLE_ALPHA ? 1 : 0);
4241 glColorMask(Value & WINED3DCOLORWRITEENABLE_RED ? GL_TRUE : GL_FALSE,
4242 Value & WINED3DCOLORWRITEENABLE_GREEN ? GL_TRUE : GL_FALSE,
4243 Value & WINED3DCOLORWRITEENABLE_BLUE ? GL_TRUE : GL_FALSE,
4244 Value & WINED3DCOLORWRITEENABLE_ALPHA ? GL_TRUE : GL_FALSE);
4245 checkGLcall("glColorMask(...)");
4249 case WINED3DRS_LOCALVIEWER :
4251 GLint state = (Value) ? 1 : 0;
4252 TRACE("Local Viewer Enable to %ul\n", (BOOL) Value);
4253 glLightModeli(GL_LIGHT_MODEL_LOCAL_VIEWER, state);
4257 case WINED3DRS_LASTPIXEL :
4260 TRACE("Last Pixel Drawing Enabled\n");
4262 FIXME("Last Pixel Drawing Disabled, not handled yet\n");
4267 case WINED3DRS_SOFTWAREVERTEXPROCESSING :
4270 TRACE("Software Processing Enabled\n");
4272 TRACE("Software Processing Disabled\n");
4277 /** not supported */
4278 case WINED3DRS_ZVISIBLE :
4281 return WINED3DERR_INVALIDCALL;
4283 case WINED3DRS_POINTSPRITEENABLE :
4285 /* TODO: NV_POINT_SPRITE */
4286 if (!GL_SUPPORT(ARB_POINT_SPRITE)) {
4287 TRACE("Point sprites not supported\n");
4292 * Point sprites are always enabled. Value controls texture coordinate
4293 * replacement mode. Must be set true for point sprites to use
4296 glEnable(GL_POINT_SPRITE_ARB);
4297 checkGLcall("glEnable(GL_POINT_SPRITE_ARB)");
4300 glTexEnvf(GL_POINT_SPRITE_ARB, GL_COORD_REPLACE_ARB, TRUE);
4301 checkGLcall("glTexEnvf(GL_POINT_SPRITE, GL_COORD_REPLACE, TRUE)");
4303 glTexEnvf(GL_POINT_SPRITE_ARB, GL_COORD_REPLACE_ARB, FALSE);
4304 checkGLcall("glTexEnvf(GL_POINT_SPRITE, GL_COORD_REPLACE, FALSE)");
4308 case WINED3DRS_EDGEANTIALIAS :
4311 glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
4313 checkGLcall("glEnable(GL_BLEND)");
4314 glEnable(GL_LINE_SMOOTH);
4315 checkGLcall("glEnable(GL_LINE_SMOOTH)");
4317 if(!This->stateBlock->renderState[WINED3DRS_ALPHABLENDENABLE]) {
4318 glDisable(GL_BLEND);
4319 checkGLcall("glDisable(GL_BLEND)");
4321 glDisable(GL_LINE_SMOOTH);
4322 checkGLcall("glDisable(GL_LINE_SMOOTH)");
4326 case WINED3DRS_WRAP0 :
4327 case WINED3DRS_WRAP1 :
4328 case WINED3DRS_WRAP2 :
4329 case WINED3DRS_WRAP3 :
4330 case WINED3DRS_WRAP4 :
4331 case WINED3DRS_WRAP5 :
4332 case WINED3DRS_WRAP6 :
4333 case WINED3DRS_WRAP7 :
4334 case WINED3DRS_WRAP8 :
4335 case WINED3DRS_WRAP9 :
4336 case WINED3DRS_WRAP10 :
4337 case WINED3DRS_WRAP11 :
4338 case WINED3DRS_WRAP12 :
4339 case WINED3DRS_WRAP13 :
4340 case WINED3DRS_WRAP14 :
4341 case WINED3DRS_WRAP15 :
4343 http://www.cosc.brocku.ca/Offerings/3P98/course/lectures/texture/
4344 http://msdn.microsoft.com/archive/default.asp?url=/archive/en-us/directx9_c/directx/graphics/programmingguide/FixedFunction/Textures/texturewrapping.asp
4345 http://www.gamedev.net/reference/programming/features/rendererdll3/page2.asp
4346 Descussion that ways to turn on WRAPing to solve an opengl conversion problem.
4347 http://www.flipcode.org/cgi-bin/fcmsg.cgi?thread_show=10248
4349 so far as I can tell, wrapping and texture-coordinate generate go hand in hand,
4353 ERR("(%p)->(%s,%d) Texture wraping not yet supported\n",This, debug_d3drenderstate(State), Value);
4358 case WINED3DRS_MULTISAMPLEANTIALIAS :
4360 if( GL_SUPPORT(ARB_MULTISAMPLE) ) {
4362 glEnable(GL_MULTISAMPLE_ARB);
4363 checkGLcall("glEnable(GL_MULTISAMPLE_ARB)");
4365 glDisable(GL_MULTISAMPLE_ARB);
4366 checkGLcall("glDisable(GL_MULTISAMPLE_ARB)");
4370 ERR("Multisample antialiasing not supported by gl\n");
4376 case WINED3DRS_SCISSORTESTENABLE :
4379 glEnable(GL_SCISSOR_TEST);
4380 checkGLcall("glEnable(GL_SCISSOR_TEST)");
4382 glDisable(GL_SCISSOR_TEST);
4383 checkGLcall("glDisable(GL_SCISSOR_TEST)");
4387 case WINED3DRS_SLOPESCALEDEPTHBIAS :
4391 glEnable(GL_POLYGON_OFFSET_FILL);
4392 checkGLcall("glEnable(GL_POLYGON_OFFSET_FILL)");
4393 glPolygonOffset(tmpvalue.f, *((float*)&This->stateBlock->renderState[WINED3DRS_DEPTHBIAS]));
4394 checkGLcall("glPolygonOffset(...)");
4396 glDisable(GL_POLYGON_OFFSET_FILL);
4397 checkGLcall("glDisable(GL_POLYGON_OFFSET_FILL)");
4401 case WINED3DRS_ANTIALIASEDLINEENABLE :
4404 glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
4406 checkGLcall("glEnable(GL_BLEND)");
4407 glEnable(GL_LINE_SMOOTH);
4408 checkGLcall("glEnable(GL_LINE_SMOOTH)");
4410 glDisable(GL_BLEND);
4411 checkGLcall("glDisable(GL_BLEND)");
4412 glDisable(GL_LINE_SMOOTH);
4413 checkGLcall("glDisable(GL_LINE_SMOOTH)");
4417 case WINED3DRS_DEPTHBIAS :
4421 glEnable(GL_POLYGON_OFFSET_FILL);
4422 checkGLcall("glEnable(GL_POLYGON_OFFSET_FILL)");
4423 glPolygonOffset(*((float*)&This->stateBlock->renderState[WINED3DRS_SLOPESCALEDEPTHBIAS]), tmpvalue.f);
4424 checkGLcall("glPolygonOffset(...)");
4426 glDisable(GL_POLYGON_OFFSET_FILL);
4427 checkGLcall("glDisable(GL_POLYGON_OFFSET_FILL)");
4432 case WINED3DRS_TEXTUREPERSPECTIVE :
4435 glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST);
4437 glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_FASTEST);
4441 case WINED3DRS_STIPPLEDALPHA :
4444 ERR(" Stippled Alpha not supported yet.\n");
4447 case WINED3DRS_ANTIALIAS :
4450 ERR(" Antialias not supported yet.\n");
4454 case WINED3DRS_MULTISAMPLEMASK :
4456 if(0xFFFFFFFF != Value)
4457 ERR("(%p)->(%s,%d) not yet implemented\n", This, debug_d3drenderstate(State), Value);
4461 case WINED3DRS_PATCHEDGESTYLE :
4463 if(WINED3DPATCHEDGE_DISCRETE != Value)
4464 ERR("(%p)->(%s,%d) not yet implemented\n", This, debug_d3drenderstate(State), Value);
4468 case WINED3DRS_PATCHSEGMENTS :
4470 /* available in d3d8 but in d3d9 it was replaced by IDirect3DDevice9::SetNPatchMode */
4472 if(tmpvalue.d != Value)
4473 ERR("(%p)->(%s,%d) not yet implemented\n", This, debug_d3drenderstate(State), Value);
4477 case WINED3DRS_DEBUGMONITORTOKEN :
4479 /* Only useful for "debug builds". */
4480 if(0xbaadcafe != Value) {
4481 /* MSDN says the default is D3DDMT_ENABLE but our tests confirm 0xbaadcafe is the default. */
4482 /* MSDN says anything other than D3DDMT_ENABLE or DISABLE does not change the state,
4483 * but our tests disagree.
4484 * We do not claim to implement a debugging lib, so do not write an ERR
4486 WARN("(%p)->(%s,%d) not yet implemented\n", This, debug_d3drenderstate(State), Value);
4491 case WINED3DRS_POSITIONDEGREE :
4493 if(WINED3DDEGREE_CUBIC != Value)
4494 ERR("(%p)->(%s,%d) not yet implemented\n", This, debug_d3drenderstate(State), Value);
4498 case WINED3DRS_NORMALDEGREE :
4500 if(WINED3DDEGREE_LINEAR != Value)
4501 ERR("(%p)->(%s,%d) not yet implemented\n", This, debug_d3drenderstate(State), Value);
4505 case WINED3DRS_MINTESSELLATIONLEVEL :
4506 case WINED3DRS_MAXTESSELLATIONLEVEL :
4507 case WINED3DRS_ADAPTIVETESS_X :
4508 case WINED3DRS_ADAPTIVETESS_Y :
4509 case WINED3DRS_ADAPTIVETESS_Z :
4510 case WINED3DRS_ADAPTIVETESS_W :
4512 if(This->stateBlock->renderState[WINED3DRS_ENABLEADAPTIVETESSELLATION])
4513 FIXME("(%p)->(%s,%d) not yet implemented\n", This, debug_d3drenderstate(State), Value);
4515 TRACE("(%p)->(%s,%d): recording state but WINED3DRS_ENABLEADAPTIVETESSELLATION is not enabled\n", This, debug_d3drenderstate(State), Value);
4519 case WINED3DRS_ENABLEADAPTIVETESSELLATION:
4522 ERR("(%p)->(%s,%d) not yet implemented\n", This, debug_d3drenderstate(State), Value);
4526 case WINED3DRS_COLORWRITEENABLE1 :
4527 case WINED3DRS_COLORWRITEENABLE2 :
4528 case WINED3DRS_COLORWRITEENABLE3 :
4530 /* depends on WINED3DRS_COLORWRITEENABLE. */
4531 if(0x0000000F != Value)
4532 ERR("(%p)->(%s,%d) not yet implemented. Missing of cap D3DPMISCCAPS_INDEPENDENTWRITEMASKS wasn't honored?\n", This, debug_d3drenderstate(State), Value);
4536 case WINED3DRS_BLENDFACTOR :
4540 TRACE("Setting BlendFactor to %d\n", Value);
4542 D3DCOLORTOGLFLOAT4(Value, col);
4543 if (0xFFFFFFFF != Value) {
4545 checkGLcall("glEnable(GL_BLEND)");
4548 glDisable(GL_BLEND);
4549 checkGLcall("glDisable(GL_BLEND)");
4551 glBlendColor (col[0],col[1],col[2],col[3]);
4555 case WINED3DRS_SRGBWRITEENABLE :
4558 ERR("(%p)->(%s,%d) not yet implemented\n", This, debug_d3drenderstate(State), Value);
4562 case WINED3DRS_SEPARATEALPHABLENDENABLE :
4565 ERR("(%p)->(%s,%d) not yet implemented. Missing of cap D3DPMISCCAPS_SEPARATEALPHABLEND wasn't honored?\n", This, debug_d3drenderstate(State), Value);
4569 case WINED3DRS_SRCBLENDALPHA :
4570 case WINED3DRS_DESTBLENDALPHA :
4571 case WINED3DRS_BLENDOPALPHA :
4573 if(This->stateBlock->renderState[WINED3DRS_SEPARATEALPHABLENDENABLE])
4574 FIXME("(%p)->(%s,%d) not yet implemented\n", This, debug_d3drenderstate(State), Value);
4576 TRACE("(%p)->(%s,%d): recording state but WINED3DRS_SEPARATEALPHABLENDENABLE is not enabled\n", This, debug_d3drenderstate(State), Value);
4581 FIXME("(%p)->(%s,%d) unknown state\n", This, debug_d3drenderstate(State), Value);
4589 static HRESULT WINAPI IWineD3DDeviceImpl_GetRenderState(IWineD3DDevice *iface, WINED3DRENDERSTATETYPE State, DWORD *pValue) {
4590 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4591 TRACE("(%p) for State %d = %d\n", This, State, This->stateBlock->renderState[State]);
4592 *pValue = This->stateBlock->renderState[State];
4597 * Get / Set Sampler States
4598 * TODO: Verify against dx9 definitions
4601 static HRESULT WINAPI IWineD3DDeviceImpl_SetSamplerState(IWineD3DDevice *iface, DWORD Sampler, WINED3DSAMPLERSTATETYPE Type, DWORD Value) {
4602 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4604 * SetSampler is designed to allow for more than the standard up to 8 textures
4605 * and Geforce has stopped supporting more than 6 standard textures in openGL.
4606 * So I have to use ARB for Gforce. (maybe if the sampler > 4 then use ARB?)
4608 * http://developer.nvidia.com/object/General_FAQ.html#t6
4610 * There are two new settings for GForce
4612 * GL_MAX_TEXTURE_IMAGE_UNITS_ARB
4613 * and the texture one:
4614 * GL_MAX_TEXTURE_COORDS_ARB.
4615 * Ok GForce say it's ok to use glTexParameter/glGetTexParameter(...).
4617 /** NOTE: States are appled in IWineD3DBaseTextre ApplyStateChanges and IWineD3DDevice SetupTextureStates**/
4618 if(Sampler > GL_LIMITS(sampler_stages) || Sampler < 0 || Type > WINED3D_HIGHEST_SAMPLER_STATE || Type < 0) {
4619 FIXME("sampler %d type %s(%u) is out of range [max_samplers=%d, highest_state=%d]\n",
4620 Sampler, debug_d3dsamplerstate(Type), Type, GL_LIMITS(sampler_stages), WINED3D_HIGHEST_SAMPLER_STATE);
4621 return WINED3DERR_INVALIDCALL;
4624 TRACE("(%p) : Sampler=%d, Type=%s(%d), Value=%d\n", This, Sampler,
4625 debug_d3dsamplerstate(Type), Type, Value);
4626 This->updateStateBlock->samplerState[Sampler][Type] = Value;
4627 This->updateStateBlock->set.samplerState[Sampler][Type] = Value;
4628 This->updateStateBlock->changed.samplerState[Sampler][Type] = Value;
4630 /* Handle recording of state blocks */
4631 if (This->isRecordingState) {
4632 TRACE("Recording... not performing anything\n");
4639 static HRESULT WINAPI IWineD3DDeviceImpl_GetSamplerState(IWineD3DDevice *iface, DWORD Sampler, WINED3DSAMPLERSTATETYPE Type, DWORD* Value) {
4640 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4641 /** TODO: check that sampler is in range **/
4642 *Value = This->stateBlock->samplerState[Sampler][Type];
4643 TRACE("(%p) : Sampler %d Type %u Returning %d\n", This, Sampler, Type, *Value);
4648 static HRESULT WINAPI IWineD3DDeviceImpl_SetScissorRect(IWineD3DDevice *iface, CONST RECT* pRect) {
4649 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4653 GetClientRect(((IWineD3DSwapChainImpl *)This->swapchains[0])->win_handle, &windowRect);
4654 /* Warning: glScissor uses window coordinates, not viewport coordinates, so our viewport correction does not apply
4655 * Warning2: Even in windowed mode the coords are relative to the window, not the screen
4657 winHeight = windowRect.bottom - windowRect.top;
4658 TRACE("(%p)Setting new Scissor Rect to %d:%d-%d:%d\n", This, pRect->left, pRect->bottom - winHeight,
4659 pRect->right - pRect->left, pRect->bottom - pRect->top);
4661 glScissor(pRect->left, winHeight - pRect->bottom, pRect->right - pRect->left, pRect->bottom - pRect->top);
4662 checkGLcall("glScissor");
4668 static HRESULT WINAPI IWineD3DDeviceImpl_GetScissorRect(IWineD3DDevice *iface, RECT* pRect) {
4669 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4670 GLint scissorBox[4];
4673 /** FIXME: Windows uses a top,left origin openGL uses a bottom Right? **/
4674 glGetIntegerv(GL_SCISSOR_BOX, scissorBox);
4675 pRect->left = scissorBox[0];
4676 pRect->top = scissorBox[1];
4677 pRect->right = scissorBox[0] + scissorBox[2];
4678 pRect->bottom = scissorBox[1] + scissorBox[3];
4679 TRACE("(%p)Returning a Scissor Rect of %d:%d-%d:%d\n", This, pRect->left, pRect->top, pRect->right, pRect->bottom);
4684 static HRESULT WINAPI IWineD3DDeviceImpl_SetVertexDeclaration(IWineD3DDevice* iface, IWineD3DVertexDeclaration* pDecl) {
4685 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *) iface;
4686 IWineD3DVertexDeclaration *oldDecl = This->updateStateBlock->vertexDecl;
4688 TRACE("(%p) : pDecl=%p\n", This, pDecl);
4690 This->updateStateBlock->vertexDecl = pDecl;
4691 This->updateStateBlock->changed.vertexDecl = TRUE;
4692 This->updateStateBlock->set.vertexDecl = TRUE;
4694 if (This->isRecordingState) {
4695 TRACE("Recording... not performing anything\n");
4698 if (NULL != pDecl) {
4699 IWineD3DVertexDeclaration_AddRef(pDecl);
4701 if (NULL != oldDecl) {
4702 IWineD3DVertexDeclaration_Release(oldDecl);
4707 static HRESULT WINAPI IWineD3DDeviceImpl_GetVertexDeclaration(IWineD3DDevice* iface, IWineD3DVertexDeclaration** ppDecl) {
4708 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4710 TRACE("(%p) : ppDecl=%p\n", This, ppDecl);
4712 *ppDecl = This->stateBlock->vertexDecl;
4713 if (NULL != *ppDecl) IWineD3DVertexDeclaration_AddRef(*ppDecl);
4717 static HRESULT WINAPI IWineD3DDeviceImpl_SetVertexShader(IWineD3DDevice *iface, IWineD3DVertexShader* pShader) {
4718 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4719 IWineD3DVertexShader* oldShader = This->updateStateBlock->vertexShader;
4721 This->updateStateBlock->vertexShader = pShader;
4722 This->updateStateBlock->changed.vertexShader = TRUE;
4723 This->updateStateBlock->set.vertexShader = TRUE;
4725 if (This->isRecordingState) {
4726 TRACE("Recording... not performing anything\n");
4729 if (NULL != pShader) {
4730 IWineD3DVertexShader_AddRef(pShader);
4732 if (NULL != oldShader) {
4733 IWineD3DVertexShader_Release(oldShader);
4736 TRACE("(%p) : setting pShader(%p)\n", This, pShader);
4738 * TODO: merge HAL shaders context switching from prototype
4743 static HRESULT WINAPI IWineD3DDeviceImpl_GetVertexShader(IWineD3DDevice *iface, IWineD3DVertexShader** ppShader) {
4744 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4746 if (NULL == ppShader) {
4747 return WINED3DERR_INVALIDCALL;
4749 *ppShader = This->stateBlock->vertexShader;
4750 if( NULL != *ppShader)
4751 IWineD3DVertexShader_AddRef(*ppShader);
4753 TRACE("(%p) : returning %p\n", This, *ppShader);
4757 static HRESULT WINAPI IWineD3DDeviceImpl_SetVertexShaderConstantB(
4758 IWineD3DDevice *iface,
4760 CONST BOOL *srcData,
4763 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4764 int i, cnt = min(count, MAX_CONST_B - start);
4766 TRACE("(iface %p, srcData %p, start %d, count %d)\n",
4767 iface, srcData, start, count);
4769 if (srcData == NULL || cnt < 0)
4770 return WINED3DERR_INVALIDCALL;
4772 memcpy(&This->updateStateBlock->vertexShaderConstantB[start], srcData, cnt * sizeof(BOOL));
4773 for (i = 0; i < cnt; i++)
4774 TRACE("Set BOOL constant %u to %s\n", start + i, srcData[i]? "true":"false");
4776 for (i = start; i < cnt + start; ++i) {
4777 This->updateStateBlock->changed.vertexShaderConstantsB[i] = TRUE;
4778 This->updateStateBlock->set.vertexShaderConstantsB[i] = TRUE;
4784 static HRESULT WINAPI IWineD3DDeviceImpl_GetVertexShaderConstantB(
4785 IWineD3DDevice *iface,
4790 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4791 int cnt = min(count, MAX_CONST_B - start);
4793 TRACE("(iface %p, dstData %p, start %d, count %d)\n",
4794 iface, dstData, start, count);
4796 if (dstData == NULL || cnt < 0)
4797 return WINED3DERR_INVALIDCALL;
4799 memcpy(dstData, &This->stateBlock->vertexShaderConstantB[start], cnt * sizeof(BOOL));
4803 static HRESULT WINAPI IWineD3DDeviceImpl_SetVertexShaderConstantI(
4804 IWineD3DDevice *iface,
4809 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4810 int i, cnt = min(count, MAX_CONST_I - start);
4812 TRACE("(iface %p, srcData %p, start %d, count %d)\n",
4813 iface, srcData, start, count);
4815 if (srcData == NULL || cnt < 0)
4816 return WINED3DERR_INVALIDCALL;
4818 memcpy(&This->updateStateBlock->vertexShaderConstantI[start * 4], srcData, cnt * sizeof(int) * 4);
4819 for (i = 0; i < cnt; i++)
4820 TRACE("Set INT constant %u to { %d, %d, %d, %d }\n", start + i,
4821 srcData[i*4], srcData[i*4+1], srcData[i*4+2], srcData[i*4+3]);
4823 for (i = start; i < cnt + start; ++i) {
4824 This->updateStateBlock->changed.vertexShaderConstantsI[i] = TRUE;
4825 This->updateStateBlock->set.vertexShaderConstantsI[i] = TRUE;
4831 static HRESULT WINAPI IWineD3DDeviceImpl_GetVertexShaderConstantI(
4832 IWineD3DDevice *iface,
4837 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4838 int cnt = min(count, MAX_CONST_I - start);
4840 TRACE("(iface %p, dstData %p, start %d, count %d)\n",
4841 iface, dstData, start, count);
4843 if (dstData == NULL || ((signed int) MAX_CONST_I - (signed int) start) <= (signed int) 0)
4844 return WINED3DERR_INVALIDCALL;
4846 memcpy(dstData, &This->stateBlock->vertexShaderConstantI[start * 4], cnt * sizeof(int) * 4);
4850 static HRESULT WINAPI IWineD3DDeviceImpl_SetVertexShaderConstantF(
4851 IWineD3DDevice *iface,
4853 CONST float *srcData,
4856 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4857 int i, cnt = min(count, GL_LIMITS(vshader_constantsF) - start);
4859 TRACE("(iface %p, srcData %p, start %d, count %d)\n",
4860 iface, srcData, start, count);
4862 if (srcData == NULL || ((signed int) GL_LIMITS(vshader_constantsF) - (signed int) start) <= (signed int) 0)
4863 return WINED3DERR_INVALIDCALL;
4865 memcpy(&This->updateStateBlock->vertexShaderConstantF[start * 4], srcData, cnt * sizeof(float) * 4);
4866 for (i = 0; i < cnt; i++)
4867 TRACE("Set FLOAT constant %u to { %f, %f, %f, %f }\n", start + i,
4868 srcData[i*4], srcData[i*4+1], srcData[i*4+2], srcData[i*4+3]);
4870 for (i = start; i < cnt + start; ++i) {
4871 if (!This->updateStateBlock->set.vertexShaderConstantsF[i]) {
4872 constant_entry *ptr = HeapAlloc(GetProcessHeap(), 0, sizeof(constant_entry));
4874 list_add_head(&This->updateStateBlock->set_vconstantsF, &ptr->entry);
4875 This->updateStateBlock->set.vertexShaderConstantsF[i] = TRUE;
4877 This->updateStateBlock->changed.vertexShaderConstantsF[i] = TRUE;
4883 static HRESULT WINAPI IWineD3DDeviceImpl_GetVertexShaderConstantF(
4884 IWineD3DDevice *iface,
4889 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4890 int cnt = min(count, GL_LIMITS(vshader_constantsF) - start);
4892 TRACE("(iface %p, dstData %p, start %d, count %d)\n",
4893 iface, dstData, start, count);
4895 if (dstData == NULL || cnt < 0)
4896 return WINED3DERR_INVALIDCALL;
4898 memcpy(dstData, &This->stateBlock->vertexShaderConstantF[start * 4], cnt * sizeof(float) * 4);
4902 static HRESULT WINAPI IWineD3DDeviceImpl_SetPixelShader(IWineD3DDevice *iface, IWineD3DPixelShader *pShader) {
4903 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4904 IWineD3DPixelShader *oldShader = This->updateStateBlock->pixelShader;
4905 This->updateStateBlock->pixelShader = pShader;
4906 This->updateStateBlock->changed.pixelShader = TRUE;
4907 This->updateStateBlock->set.pixelShader = TRUE;
4909 /* Handle recording of state blocks */
4910 if (This->isRecordingState) {
4911 TRACE("Recording... not performing anything\n");
4914 if (NULL != pShader) {
4915 IWineD3DPixelShader_AddRef(pShader);
4917 if (NULL != oldShader) {
4918 IWineD3DPixelShader_Release(oldShader);
4921 TRACE("(%p) : setting pShader(%p)\n", This, pShader);
4923 * TODO: merge HAL shaders context switching from prototype
4928 static HRESULT WINAPI IWineD3DDeviceImpl_GetPixelShader(IWineD3DDevice *iface, IWineD3DPixelShader **ppShader) {
4929 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4931 if (NULL == ppShader) {
4932 WARN("(%p) : PShader is NULL, returning INVALIDCALL\n", This);
4933 return WINED3DERR_INVALIDCALL;
4936 *ppShader = This->stateBlock->pixelShader;
4937 if (NULL != *ppShader) {
4938 IWineD3DPixelShader_AddRef(*ppShader);
4940 TRACE("(%p) : returning %p\n", This, *ppShader);
4944 static HRESULT WINAPI IWineD3DDeviceImpl_SetPixelShaderConstantB(
4945 IWineD3DDevice *iface,
4947 CONST BOOL *srcData,
4950 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4951 int i, cnt = min(count, MAX_CONST_B - start);
4953 TRACE("(iface %p, srcData %p, start %d, count %d)\n",
4954 iface, srcData, start, count);
4956 if (srcData == NULL || cnt < 0)
4957 return WINED3DERR_INVALIDCALL;
4959 memcpy(&This->updateStateBlock->pixelShaderConstantB[start], srcData, cnt * sizeof(BOOL));
4960 for (i = 0; i < cnt; i++)
4961 TRACE("Set BOOL constant %u to %s\n", start + i, srcData[i]? "true":"false");
4963 for (i = start; i < cnt + start; ++i) {
4964 This->updateStateBlock->changed.pixelShaderConstantsB[i] = TRUE;
4965 This->updateStateBlock->set.pixelShaderConstantsB[i] = TRUE;
4971 static HRESULT WINAPI IWineD3DDeviceImpl_GetPixelShaderConstantB(
4972 IWineD3DDevice *iface,
4977 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4978 int cnt = min(count, MAX_CONST_B - start);
4980 TRACE("(iface %p, dstData %p, start %d, count %d)\n",
4981 iface, dstData, start, count);
4983 if (dstData == NULL || cnt < 0)
4984 return WINED3DERR_INVALIDCALL;
4986 memcpy(dstData, &This->stateBlock->pixelShaderConstantB[start], cnt * sizeof(BOOL));
4990 static HRESULT WINAPI IWineD3DDeviceImpl_SetPixelShaderConstantI(
4991 IWineD3DDevice *iface,
4996 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4997 int i, cnt = min(count, MAX_CONST_I - start);
4999 TRACE("(iface %p, srcData %p, start %d, count %d)\n",
5000 iface, srcData, start, count);
5002 if (srcData == NULL || cnt < 0)
5003 return WINED3DERR_INVALIDCALL;
5005 memcpy(&This->updateStateBlock->pixelShaderConstantI[start * 4], srcData, cnt * sizeof(int) * 4);
5006 for (i = 0; i < cnt; i++)
5007 TRACE("Set INT constant %u to { %d, %d, %d, %d }\n", start + i,
5008 srcData[i*4], srcData[i*4+1], srcData[i*4+2], srcData[i*4+3]);
5010 for (i = start; i < cnt + start; ++i) {
5011 This->updateStateBlock->changed.pixelShaderConstantsI[i] = TRUE;
5012 This->updateStateBlock->set.pixelShaderConstantsI[i] = TRUE;
5018 static HRESULT WINAPI IWineD3DDeviceImpl_GetPixelShaderConstantI(
5019 IWineD3DDevice *iface,
5024 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5025 int cnt = min(count, MAX_CONST_I - start);
5027 TRACE("(iface %p, dstData %p, start %d, count %d)\n",
5028 iface, dstData, start, count);
5030 if (dstData == NULL || cnt < 0)
5031 return WINED3DERR_INVALIDCALL;
5033 memcpy(dstData, &This->stateBlock->pixelShaderConstantI[start * 4], cnt * sizeof(int) * 4);
5037 static HRESULT WINAPI IWineD3DDeviceImpl_SetPixelShaderConstantF(
5038 IWineD3DDevice *iface,
5040 CONST float *srcData,
5043 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5044 int i, cnt = min(count, GL_LIMITS(pshader_constantsF) - start);
5046 TRACE("(iface %p, srcData %p, start %d, count %d)\n",
5047 iface, srcData, start, count);
5049 if (srcData == NULL || cnt < 0)
5050 return WINED3DERR_INVALIDCALL;
5052 memcpy(&This->updateStateBlock->pixelShaderConstantF[start * 4], srcData, cnt * sizeof(float) * 4);
5053 for (i = 0; i < cnt; i++)
5054 TRACE("Set FLOAT constant %u to { %f, %f, %f, %f }\n", start + i,
5055 srcData[i*4], srcData[i*4+1], srcData[i*4+2], srcData[i*4+3]);
5057 for (i = start; i < cnt + start; ++i) {
5058 if (!This->updateStateBlock->set.pixelShaderConstantsF[i]) {
5059 constant_entry *ptr = HeapAlloc(GetProcessHeap(), 0, sizeof(constant_entry));
5061 list_add_head(&This->updateStateBlock->set_pconstantsF, &ptr->entry);
5062 This->updateStateBlock->set.pixelShaderConstantsF[i] = TRUE;
5064 This->updateStateBlock->changed.pixelShaderConstantsF[i] = TRUE;
5070 static HRESULT WINAPI IWineD3DDeviceImpl_GetPixelShaderConstantF(
5071 IWineD3DDevice *iface,
5076 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5077 int cnt = min(count, GL_LIMITS(pshader_constantsF) - start);
5079 TRACE("(iface %p, dstData %p, start %d, count %d)\n",
5080 iface, dstData, start, count);
5082 if (dstData == NULL || cnt < 0)
5083 return WINED3DERR_INVALIDCALL;
5085 memcpy(dstData, &This->stateBlock->pixelShaderConstantF[start * 4], cnt * sizeof(float) * 4);
5089 #define copy_and_next(dest, src, size) memcpy(dest, src, size); dest += (size)
5091 process_vertices_strided(IWineD3DDeviceImpl *This, DWORD dwDestIndex, DWORD dwCount, WineDirect3DVertexStridedData *lpStrideData, DWORD SrcFVF, IWineD3DVertexBufferImpl *dest, DWORD dwFlags) {
5092 char *dest_ptr, *dest_conv = NULL;
5094 DWORD DestFVF = dest->fvf;
5096 WINED3DMATRIX mat, proj_mat, view_mat, world_mat;
5100 if (SrcFVF & WINED3DFVF_NORMAL) {
5101 WARN(" lighting state not saved yet... Some strange stuff may happen !\n");
5104 if ( (SrcFVF & WINED3DFVF_POSITION_MASK) != WINED3DFVF_XYZ) {
5105 ERR("Source has no position mask\n");
5106 return WINED3DERR_INVALIDCALL;
5109 /* We might access VBOs from this code, so hold the lock */
5112 if (dest->resource.allocatedMemory == NULL) {
5113 /* This may happen if we do direct locking into a vbo. Unlikely,
5114 * but theoretically possible(ddraw processvertices test)
5116 dest->resource.allocatedMemory = HeapAlloc(GetProcessHeap(), 0, dest->resource.size);
5117 if(!dest->resource.allocatedMemory) {
5119 ERR("Out of memory\n");
5120 return E_OUTOFMEMORY;
5124 GL_EXTCALL(glBindBufferARB(GL_ARRAY_BUFFER_ARB, dest->vbo));
5125 checkGLcall("glBindBufferARB");
5126 src = GL_EXTCALL(glMapBufferARB(GL_ARRAY_BUFFER_ARB, GL_READ_ONLY_ARB));
5128 memcpy(dest->resource.allocatedMemory, src, dest->resource.size);
5130 GL_EXTCALL(glUnmapBufferARB(GL_ARRAY_BUFFER_ARB));
5131 checkGLcall("glUnmapBufferARB");
5135 /* Get a pointer into the destination vbo(create one if none exists) and
5136 * write correct opengl data into it. It's cheap and allows us to run drawStridedFast
5138 if(!dest->vbo && GL_SUPPORT(ARB_VERTEX_BUFFER_OBJECT)) {
5143 GL_EXTCALL(glBindBufferARB(GL_ARRAY_BUFFER_ARB, dest->vbo));
5144 dest_conv = GL_EXTCALL(glMapBufferARB(GL_ARRAY_BUFFER_ARB, GL_WRITE_ONLY_ARB));
5146 ERR("glMapBuffer failed\n");
5147 /* Continue without storing converted vertices */
5152 * a) WINED3DRS_CLIPPING is enabled
5153 * b) WINED3DVOP_CLIP is passed
5155 if(This->stateBlock->renderState[WINED3DRS_CLIPPING]) {
5156 static BOOL warned = FALSE;
5158 * The clipping code is not quite correct. Some things need
5159 * to be checked against IDirect3DDevice3 (!), d3d8 and d3d9,
5160 * so disable clipping for now.
5161 * (The graphics in Half-Life are broken, and my processvertices
5162 * test crashes with IDirect3DDevice3)
5168 FIXME("Clipping is broken and disabled for now\n");
5170 } else doClip = FALSE;
5171 dest_ptr = ((char *) dest->resource.allocatedMemory) + dwDestIndex * get_flexible_vertex_size(DestFVF);
5173 dest_conv = ((char *) dest_conv) + dwDestIndex * get_flexible_vertex_size(DestFVF);
5176 IWineD3DDevice_GetTransform( (IWineD3DDevice *) This,
5179 IWineD3DDevice_GetTransform( (IWineD3DDevice *) This,
5180 WINED3DTS_PROJECTION,
5182 IWineD3DDevice_GetTransform( (IWineD3DDevice *) This,
5183 WINED3DTS_WORLDMATRIX(0),
5186 TRACE("View mat:\n");
5187 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); \
5188 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); \
5189 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); \
5190 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); \
5192 TRACE("Proj mat:\n");
5193 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); \
5194 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); \
5195 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); \
5196 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); \
5198 TRACE("World mat:\n");
5199 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); \
5200 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); \
5201 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); \
5202 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); \
5204 /* Get the viewport */
5205 IWineD3DDevice_GetViewport( (IWineD3DDevice *) This, &vp);
5206 TRACE("Viewport: X=%d, Y=%d, Width=%d, Height=%d, MinZ=%f, MaxZ=%f\n",
5207 vp.X, vp.Y, vp.Width, vp.Height, vp.MinZ, vp.MaxZ);
5209 multiply_matrix(&mat,&view_mat,&world_mat);
5210 multiply_matrix(&mat,&proj_mat,&mat);
5212 numTextures = (DestFVF & WINED3DFVF_TEXCOUNT_MASK) >> WINED3DFVF_TEXCOUNT_SHIFT;
5214 for (i = 0; i < dwCount; i+= 1) {
5215 unsigned int tex_index;
5217 if ( ((DestFVF & WINED3DFVF_POSITION_MASK) == WINED3DFVF_XYZ ) ||
5218 ((DestFVF & WINED3DFVF_POSITION_MASK) == WINED3DFVF_XYZRHW ) ) {
5219 /* The position first */
5221 (float *) (((char *) lpStrideData->u.s.position.lpData) + i * lpStrideData->u.s.position.dwStride);
5223 TRACE("In: ( %06.2f %06.2f %06.2f )\n", p[0], p[1], p[2]);
5225 /* Multiplication with world, view and projection matrix */
5226 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);
5227 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);
5228 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);
5229 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);
5231 TRACE("x=%f y=%f z=%f rhw=%f\n", x, y, z, rhw);
5233 /* WARNING: The following things are taken from d3d7 and were not yet checked
5234 * against d3d8 or d3d9!
5237 /* Clipping conditions: From
5238 * http://msdn.microsoft.com/archive/default.asp?url=/archive/en-us/directx9_c/directx/graphics/programmingguide/fixedfunction/viewportsclipping/clippingvolumes.asp
5240 * A vertex is clipped if it does not match the following requirements
5244 * 0 < rhw ( Not in d3d7, but tested in d3d7)
5246 * If clipping is on is determined by the D3DVOP_CLIP flag in D3D7, and
5247 * by the D3DRS_CLIPPING in D3D9(according to the msdn, not checked)
5252 ( (-rhw -eps < x) && (-rhw -eps < y) && ( -eps < z) &&
5253 (x <= rhw + eps) && (y <= rhw + eps ) && (z <= rhw + eps) &&
5256 /* "Normal" viewport transformation (not clipped)
5257 * 1) The values are divided by rhw
5258 * 2) The y axis is negative, so multiply it with -1
5259 * 3) Screen coordinates go from -(Width/2) to +(Width/2) and
5260 * -(Height/2) to +(Height/2). The z range is MinZ to MaxZ
5261 * 4) Multiply x with Width/2 and add Width/2
5262 * 5) The same for the height
5263 * 6) Add the viewpoint X and Y to the 2D coordinates and
5264 * The minimum Z value to z
5265 * 7) rhw = 1 / rhw Reciprocal of Homogeneous W....
5267 * Well, basically it's simply a linear transformation into viewport
5279 z *= vp.MaxZ - vp.MinZ;
5281 x += vp.Width / 2 + vp.X;
5282 y += vp.Height / 2 + vp.Y;
5287 /* That vertex got clipped
5288 * Contrary to OpenGL it is not dropped completely, it just
5289 * undergoes a different calculation.
5291 TRACE("Vertex got clipped\n");
5298 /* Msdn mentions that Direct3D9 keeps a list of clipped vertices
5299 * outside of the main vertex buffer memory. That needs some more
5304 TRACE("Writing (%f %f %f) %f\n", x, y, z, rhw);
5307 ( (float *) dest_ptr)[0] = x;
5308 ( (float *) dest_ptr)[1] = y;
5309 ( (float *) dest_ptr)[2] = z;
5310 ( (float *) dest_ptr)[3] = rhw; /* SIC, see ddraw test! */
5312 dest_ptr += 3 * sizeof(float);
5314 if((DestFVF & WINED3DFVF_POSITION_MASK) == WINED3DFVF_XYZRHW) {
5315 dest_ptr += sizeof(float);
5320 ( (float *) dest_conv)[0] = x * w;
5321 ( (float *) dest_conv)[1] = y * w;
5322 ( (float *) dest_conv)[2] = z * w;
5323 ( (float *) dest_conv)[3] = w;
5325 dest_conv += 3 * sizeof(float);
5327 if((DestFVF & WINED3DFVF_POSITION_MASK) == WINED3DFVF_XYZRHW) {
5328 dest_conv += sizeof(float);
5332 if (DestFVF & WINED3DFVF_PSIZE) {
5333 dest_ptr += sizeof(DWORD);
5334 if(dest_conv) dest_conv += sizeof(DWORD);
5336 if (DestFVF & WINED3DFVF_NORMAL) {
5338 (float *) (((float *) lpStrideData->u.s.normal.lpData) + i * lpStrideData->u.s.normal.dwStride);
5339 /* AFAIK this should go into the lighting information */
5340 FIXME("Didn't expect the destination to have a normal\n");
5341 copy_and_next(dest_ptr, normal, 3 * sizeof(float));
5343 copy_and_next(dest_conv, normal, 3 * sizeof(float));
5347 if (DestFVF & WINED3DFVF_DIFFUSE) {
5349 (DWORD *) (((char *) lpStrideData->u.s.diffuse.lpData) + i * lpStrideData->u.s.diffuse.dwStride);
5351 static BOOL warned = FALSE;
5354 ERR("No diffuse color in source, but destination has one\n");
5358 *( (DWORD *) dest_ptr) = 0xffffffff;
5359 dest_ptr += sizeof(DWORD);
5362 *( (DWORD *) dest_conv) = 0xffffffff;
5363 dest_conv += sizeof(DWORD);
5367 copy_and_next(dest_ptr, color_d, sizeof(DWORD));
5369 *( (DWORD *) dest_conv) = (*color_d & 0xff00ff00) ; /* Alpha + green */
5370 *( (DWORD *) dest_conv) |= (*color_d & 0x00ff0000) >> 16; /* Red */
5371 *( (DWORD *) dest_conv) |= (*color_d & 0xff0000ff) << 16; /* Blue */
5372 dest_conv += sizeof(DWORD);
5377 if (DestFVF & WINED3DFVF_SPECULAR) {
5378 /* What's the color value in the feedback buffer? */
5380 (DWORD *) (((char *) lpStrideData->u.s.specular.lpData) + i * lpStrideData->u.s.specular.dwStride);
5382 static BOOL warned = FALSE;
5385 ERR("No specular color in source, but destination has one\n");
5389 *( (DWORD *) dest_ptr) = 0xFF000000;
5390 dest_ptr += sizeof(DWORD);
5393 *( (DWORD *) dest_conv) = 0xFF000000;
5394 dest_conv += sizeof(DWORD);
5398 copy_and_next(dest_ptr, color_s, sizeof(DWORD));
5400 *( (DWORD *) dest_conv) = (*color_s & 0xff00ff00) ; /* Alpha + green */
5401 *( (DWORD *) dest_conv) |= (*color_s & 0x00ff0000) >> 16; /* Red */
5402 *( (DWORD *) dest_conv) |= (*color_s & 0xff0000ff) << 16; /* Blue */
5403 dest_conv += sizeof(DWORD);
5408 for (tex_index = 0; tex_index < numTextures; tex_index++) {
5410 (float *) (((char *) lpStrideData->u.s.texCoords[tex_index].lpData) +
5411 i * lpStrideData->u.s.texCoords[tex_index].dwStride);
5413 ERR("No source texture, but destination requests one\n");
5414 dest_ptr+=GET_TEXCOORD_SIZE_FROM_FVF(DestFVF, tex_index) * sizeof(float);
5415 if(dest_conv) dest_conv += GET_TEXCOORD_SIZE_FROM_FVF(DestFVF, tex_index) * sizeof(float);
5418 copy_and_next(dest_ptr, tex_coord, GET_TEXCOORD_SIZE_FROM_FVF(DestFVF, tex_index) * sizeof(float));
5420 copy_and_next(dest_conv, tex_coord, GET_TEXCOORD_SIZE_FROM_FVF(DestFVF, tex_index) * sizeof(float));
5427 GL_EXTCALL(glUnmapBufferARB(GL_ARRAY_BUFFER_ARB));
5428 checkGLcall("glUnmapBufferARB(GL_ARRAY_BUFFER_ARB)");
5435 #undef copy_and_next
5437 static HRESULT WINAPI IWineD3DDeviceImpl_ProcessVertices(IWineD3DDevice *iface, UINT SrcStartIndex, UINT DestIndex, UINT VertexCount, IWineD3DVertexBuffer* pDestBuffer, IWineD3DVertexBuffer* pVertexDecl, DWORD Flags) {
5438 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5439 IWineD3DVertexBufferImpl *SrcImpl = (IWineD3DVertexBufferImpl *) pVertexDecl;
5440 WineDirect3DVertexStridedData strided;
5441 TRACE("(%p)->(%d,%d,%d,%p,%p,%d\n", This, SrcStartIndex, DestIndex, VertexCount, pDestBuffer, pVertexDecl, Flags);
5444 WARN("NULL source vertex buffer\n");
5445 return WINED3DERR_INVALIDCALL;
5447 /* We don't need the source vbo because this buffer is only used as
5448 * a source for ProcessVertices. Avoid wasting resources by converting the
5449 * buffer and loading the VBO
5452 TRACE("Releasing the source vbo, it won't be needed\n");
5454 if(!SrcImpl->resource.allocatedMemory) {
5455 /* Rescue the data from the buffer */
5457 SrcImpl->resource.allocatedMemory = HeapAlloc(GetProcessHeap(), 0, SrcImpl->resource.size);
5458 if(!SrcImpl->resource.allocatedMemory) {
5459 ERR("Out of memory\n");
5460 return E_OUTOFMEMORY;
5464 GL_EXTCALL(glBindBufferARB(GL_ARRAY_BUFFER_ARB, SrcImpl->vbo));
5465 checkGLcall("glBindBufferARB");
5467 src = GL_EXTCALL(glMapBufferARB(GL_ARRAY_BUFFER_ARB, GL_READ_ONLY_ARB));
5469 memcpy(SrcImpl->resource.allocatedMemory, src, SrcImpl->resource.size);
5472 GL_EXTCALL(glUnmapBufferARB(GL_ARRAY_BUFFER_ARB));
5473 checkGLcall("glUnmapBufferARB");
5478 GL_EXTCALL(glBindBufferARB(GL_ARRAY_BUFFER_ARB, 0));
5479 checkGLcall("glBindBufferARB");
5480 GL_EXTCALL(glDeleteBuffersARB(1, &SrcImpl->vbo));
5481 checkGLcall("glDeleteBuffersARB");
5487 memset(&strided, 0, sizeof(strided));
5488 primitiveConvertFVFtoOffset(SrcImpl->fvf, get_flexible_vertex_size(SrcImpl->fvf), SrcImpl->resource.allocatedMemory + get_flexible_vertex_size(SrcImpl->fvf) * SrcStartIndex, &strided, 0);
5490 return process_vertices_strided(This, DestIndex, VertexCount, &strided, SrcImpl->fvf, (IWineD3DVertexBufferImpl *) pDestBuffer, Flags);
5494 * Apply / Get / Set Texture Stage States
5495 * TODO: Verify against dx9 definitions
5498 /* 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 */
5499 static void WINAPI IWineD3DDeviceImpl_ApplyTextureUnitState(IWineD3DDevice *iface, DWORD Stage, WINED3DTEXTURESTAGESTATETYPE Type) {
5500 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5501 DWORD Value = This->updateStateBlock->textureState[Stage][Type];
5502 /* FIXME: Handle 3d textures? What if TSS value set before set texture? Need to reapply all values? */
5504 TRACE("(%p) : Stage=%d, Type=%s(%d), Value=%d\n", This, Stage, debug_d3dtexturestate(Type), Type, Value);
5506 /* Check that the stage is within limits */
5507 if (Stage >= GL_LIMITS(texture_stages) || Stage < 0) {
5508 TRACE("Attempt to access invalid texture rejected\n");
5515 case WINED3DTSS_ALPHAOP :
5516 case WINED3DTSS_COLOROP :
5517 /* nothing to do as moved to drawprim for now */
5519 case WINED3DTSS_ADDRESSW :
5520 #if 0 /* I'm not sure what D3D does about ADDRESSW appearing twice */
5521 if (Value < minLookup[WINELOOKUP_WARPPARAM] || Value > maxLookup[WINELOOKUP_WARPPARAM]) {
5522 FIXME("Unrecognized or unsupported WINED3DTADDRESS_* value %d, state %d\n", Value, Type);
5525 GLint wrapParm = stateLookup[WINELOOKUP_WARPPARAM][Value - minLookup[WINELOOKUP_WARPPARAM]];
5526 TRACE("Setting WRAP_R to %d for %x\n", wrapParm, This->stateBlock->textureDimensions[Stage]);
5527 glTexParameteri(This->stateBlock->textureDimensions[Stage], GL_TEXTURE_WRAP_R, wrapParm);
5528 checkGLcall("glTexParameteri(..., GL_TEXTURE_WRAP_R, wrapParm)");
5531 case WINED3DTSS_TEXCOORDINDEX :
5533 /* Values 0-7 are indexes into the FVF tex coords - See comments in DrawPrimitive */
5535 /* FIXME: From MSDN: The WINED3DTSS_TCI_* flags are mutually exclusive. If you include
5536 one flag, you can still specify an index value, which the system uses to
5537 determine the texture wrapping mode.
5538 eg. SetTextureStageState( 0, WINED3DTSS_TEXCOORDINDEX, WINED3DTSS_TCI_CAMERASPACEPOSITION | 1 );
5539 means use the vertex position (camera-space) as the input texture coordinates
5540 for this texture stage, and the wrap mode set in the WINED3DRS_WRAP1 render
5541 state. We do not (yet) support the WINED3DRENDERSTATE_WRAPx values, nor tie them up
5542 to the TEXCOORDINDEX value */
5545 * Be careful the value of the mask 0xF0000 come from d3d8types.h infos
5547 switch (Value & 0xFFFF0000) {
5548 case WINED3DTSS_TCI_PASSTHRU:
5549 /*Use the specified texture coordinates contained within the vertex format. This value resolves to zero.*/
5550 glDisable(GL_TEXTURE_GEN_S);
5551 glDisable(GL_TEXTURE_GEN_T);
5552 glDisable(GL_TEXTURE_GEN_R);
5553 glDisable(GL_TEXTURE_GEN_Q);
5554 checkGLcall("glDisable(GL_TEXTURE_GEN_S,T,R,Q)");
5557 case WINED3DTSS_TCI_CAMERASPACEPOSITION:
5558 /* CameraSpacePosition means use the vertex position, transformed to camera space,
5559 as the input texture coordinates for this stage's texture transformation. This
5560 equates roughly to EYE_LINEAR */
5562 float s_plane[] = { 1.0, 0.0, 0.0, 0.0 };
5563 float t_plane[] = { 0.0, 1.0, 0.0, 0.0 };
5564 float r_plane[] = { 0.0, 0.0, 1.0, 0.0 };
5565 float q_plane[] = { 0.0, 0.0, 0.0, 1.0 };
5566 TRACE("WINED3DTSS_TCI_CAMERASPACEPOSITION - Set eye plane\n");
5568 glMatrixMode(GL_MODELVIEW);
5571 glTexGenfv(GL_S, GL_EYE_PLANE, s_plane);
5572 glTexGenfv(GL_T, GL_EYE_PLANE, t_plane);
5573 glTexGenfv(GL_R, GL_EYE_PLANE, r_plane);
5574 glTexGenfv(GL_Q, GL_EYE_PLANE, q_plane);
5577 TRACE("WINED3DTSS_TCI_CAMERASPACEPOSITION - Set GL_TEXTURE_GEN_x and GL_x, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR\n");
5578 glEnable(GL_TEXTURE_GEN_S);
5579 checkGLcall("glEnable(GL_TEXTURE_GEN_S);");
5580 glTexGeni(GL_S, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR);
5581 checkGLcall("glTexGeni(GL_S, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR)");
5582 glEnable(GL_TEXTURE_GEN_T);
5583 checkGLcall("glEnable(GL_TEXTURE_GEN_T);");
5584 glTexGeni(GL_T, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR);
5585 checkGLcall("glTexGeni(GL_T, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR)");
5586 glEnable(GL_TEXTURE_GEN_R);
5587 checkGLcall("glEnable(GL_TEXTURE_GEN_R);");
5588 glTexGeni(GL_R, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR);
5589 checkGLcall("glTexGeni(GL_R, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR)");
5593 case WINED3DTSS_TCI_CAMERASPACENORMAL:
5595 if (GL_SUPPORT(NV_TEXGEN_REFLECTION)) {
5596 float s_plane[] = { 1.0, 0.0, 0.0, 0.0 };
5597 float t_plane[] = { 0.0, 1.0, 0.0, 0.0 };
5598 float r_plane[] = { 0.0, 0.0, 1.0, 0.0 };
5599 float q_plane[] = { 0.0, 0.0, 0.0, 1.0 };
5600 TRACE("WINED3DTSS_TCI_CAMERASPACENORMAL - Set eye plane\n");
5602 glMatrixMode(GL_MODELVIEW);
5605 glTexGenfv(GL_S, GL_EYE_PLANE, s_plane);
5606 glTexGenfv(GL_T, GL_EYE_PLANE, t_plane);
5607 glTexGenfv(GL_R, GL_EYE_PLANE, r_plane);
5608 glTexGenfv(GL_Q, GL_EYE_PLANE, q_plane);
5611 glEnable(GL_TEXTURE_GEN_S);
5612 checkGLcall("glEnable(GL_TEXTURE_GEN_S);");
5613 glTexGeni(GL_S, GL_TEXTURE_GEN_MODE, GL_NORMAL_MAP_NV);
5614 checkGLcall("glTexGeni(GL_S, GL_TEXTURE_GEN_MODE, GL_NORMAL_MAP_NV)");
5615 glEnable(GL_TEXTURE_GEN_T);
5616 checkGLcall("glEnable(GL_TEXTURE_GEN_T);");
5617 glTexGeni(GL_T, GL_TEXTURE_GEN_MODE, GL_NORMAL_MAP_NV);
5618 checkGLcall("glTexGeni(GL_T, GL_TEXTURE_GEN_MODE, GL_NORMAL_MAP_NV)");
5619 glEnable(GL_TEXTURE_GEN_R);
5620 checkGLcall("glEnable(GL_TEXTURE_GEN_R);");
5621 glTexGeni(GL_R, GL_TEXTURE_GEN_MODE, GL_NORMAL_MAP_NV);
5622 checkGLcall("glTexGeni(GL_R, GL_TEXTURE_GEN_MODE, GL_NORMAL_MAP_NV)");
5627 case WINED3DTSS_TCI_CAMERASPACEREFLECTIONVECTOR:
5629 if (GL_SUPPORT(NV_TEXGEN_REFLECTION)) {
5630 float s_plane[] = { 1.0, 0.0, 0.0, 0.0 };
5631 float t_plane[] = { 0.0, 1.0, 0.0, 0.0 };
5632 float r_plane[] = { 0.0, 0.0, 1.0, 0.0 };
5633 float q_plane[] = { 0.0, 0.0, 0.0, 1.0 };
5634 TRACE("WINED3DTSS_TCI_CAMERASPACEREFLECTIONVECTOR - Set eye plane\n");
5636 glMatrixMode(GL_MODELVIEW);
5639 glTexGenfv(GL_S, GL_EYE_PLANE, s_plane);
5640 glTexGenfv(GL_T, GL_EYE_PLANE, t_plane);
5641 glTexGenfv(GL_R, GL_EYE_PLANE, r_plane);
5642 glTexGenfv(GL_Q, GL_EYE_PLANE, q_plane);
5645 glEnable(GL_TEXTURE_GEN_S);
5646 checkGLcall("glEnable(GL_TEXTURE_GEN_S);");
5647 glTexGeni(GL_S, GL_TEXTURE_GEN_MODE, GL_REFLECTION_MAP_NV);
5648 checkGLcall("glTexGeni(GL_S, GL_TEXTURE_GEN_MODE, GL_REFLECTION_MAP_NV)");
5649 glEnable(GL_TEXTURE_GEN_T);
5650 checkGLcall("glEnable(GL_TEXTURE_GEN_T);");
5651 glTexGeni(GL_T, GL_TEXTURE_GEN_MODE, GL_REFLECTION_MAP_NV);
5652 checkGLcall("glTexGeni(GL_T, GL_TEXTURE_GEN_MODE, GL_REFLECTION_MAP_NV)");
5653 glEnable(GL_TEXTURE_GEN_R);
5654 checkGLcall("glEnable(GL_TEXTURE_GEN_R);");
5655 glTexGeni(GL_R, GL_TEXTURE_GEN_MODE, GL_REFLECTION_MAP_NV);
5656 checkGLcall("glTexGeni(GL_R, GL_TEXTURE_GEN_MODE, GL_REFLECTION_MAP_NV)");
5661 /* Unhandled types: */
5664 /* ? disable GL_TEXTURE_GEN_n ? */
5665 glDisable(GL_TEXTURE_GEN_S);
5666 glDisable(GL_TEXTURE_GEN_T);
5667 glDisable(GL_TEXTURE_GEN_R);
5668 glDisable(GL_TEXTURE_GEN_Q);
5669 FIXME("Unhandled WINED3DTSS_TEXCOORDINDEX %x\n", Value);
5676 case WINED3DTSS_TEXTURETRANSFORMFLAGS :
5677 set_texture_matrix((float *)&This->stateBlock->transforms[WINED3DTS_TEXTURE0 + Stage].u.m[0][0], Value, (This->stateBlock->textureState[Stage][WINED3DTSS_TEXCOORDINDEX] & 0xFFFF0000) != WINED3DTSS_TCI_PASSTHRU);
5680 case WINED3DTSS_BUMPENVMAT00 :
5681 case WINED3DTSS_BUMPENVMAT01 :
5682 TRACE("BUMPENVMAT0%u Stage=%d, Type=%d, Value =%d\n", Type - WINED3DTSS_BUMPENVMAT00, Stage, Type, Value);
5684 case WINED3DTSS_BUMPENVMAT10 :
5685 case WINED3DTSS_BUMPENVMAT11 :
5686 TRACE("BUMPENVMAT1%u Stage=%d, Type=%d, Value =%d\n", Type - WINED3DTSS_BUMPENVMAT10, Stage, Type, Value);
5689 case WINED3DTSS_BUMPENVLSCALE :
5690 TRACE("BUMPENVLSCALE Stage=%d, Type=%d, Value =%d\n", Stage, Type, Value);
5693 case WINED3DTSS_BUMPENVLOFFSET :
5694 TRACE("BUMPENVLOFFSET Stage=%d, Type=%d, Value =%d\n", Stage, Type, Value);
5697 case WINED3DTSS_RESULTARG :
5698 TRACE("RESULTARG Still a stub, Stage=%d, Type=%d, Value =%d\n", Stage, Type, Value);
5702 /* Put back later: FIXME("(%p) : stub, Stage=%d, Type=%d, Value =%d\n", This, Stage, Type, Value); */
5703 TRACE("Still a stub, Stage=%d, Type=%d, Value =%d\n", Stage, Type, Value);
5712 * Get / Set Texture Stage States
5713 * TODO: Verify against dx9 definitions
5715 static HRESULT WINAPI IWineD3DDeviceImpl_SetTextureStageState(IWineD3DDevice *iface, DWORD Stage, WINED3DTEXTURESTAGESTATETYPE Type, DWORD Value) {
5716 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5718 /* FIXME: Handle 3d textures? What if TSS value set before set texture? Need to reapply all values? */
5720 TRACE("(%p) : Stage=%d, Type=%s(%d), Value=%d\n", This, Stage, debug_d3dtexturestate(Type), Type, Value);
5722 /* Reject invalid texture units */
5723 if (Stage >= GL_LIMITS(texture_stages)) {
5724 TRACE("Attempt to access invalid texture rejected\n");
5725 return WINED3DERR_INVALIDCALL;
5728 This->updateStateBlock->changed.textureState[Stage][Type] = TRUE;
5729 This->updateStateBlock->set.textureState[Stage][Type] = TRUE;
5730 This->updateStateBlock->textureState[Stage][Type] = Value;
5735 static HRESULT WINAPI IWineD3DDeviceImpl_GetTextureStageState(IWineD3DDevice *iface, DWORD Stage, WINED3DTEXTURESTAGESTATETYPE Type, DWORD* pValue) {
5736 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5737 TRACE("(%p) : requesting Stage %d, Type %d getting %d\n", This, Stage, Type, This->updateStateBlock->textureState[Stage][Type]);
5738 *pValue = This->updateStateBlock->textureState[Stage][Type];
5745 static HRESULT WINAPI IWineD3DDeviceImpl_SetTexture(IWineD3DDevice *iface, DWORD Stage, IWineD3DBaseTexture* pTexture) {
5747 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5748 IWineD3DBaseTexture *oldTexture;
5750 oldTexture = This->updateStateBlock->textures[Stage];
5751 TRACE("(%p) : Stage(%d), Texture (%p)\n", This, Stage, pTexture);
5753 #if 0 /* TODO: check so vertex textures */
5754 if (Stage >= D3DVERTEXTEXTURESAMPLER && Stage <= D3DVERTEXTEXTURESAMPLER3){
5755 This->updateStateBlock->vertexTextures[Stage - D3DVERTEXTEXTURESAMPLER] = pTexture;
5760 /* Reject invalid texture units */
5761 if (Stage >= GL_LIMITS(sampler_stages) || Stage < 0) {
5762 WARN("Attempt to access invalid texture rejected\n");
5763 return WINED3DERR_INVALIDCALL;
5766 if(pTexture != NULL) {
5767 /* SetTexture isn't allowed on textures in WINED3DPOOL_SCRATCH;
5769 if(((IWineD3DTextureImpl*)pTexture)->resource.pool == WINED3DPOOL_SCRATCH) {
5770 WARN("(%p) Attempt to set scratch texture rejected\n", pTexture);
5771 return WINED3DERR_INVALIDCALL;
5775 oldTexture = This->updateStateBlock->textures[Stage];
5776 TRACE("GL_LIMITS %d\n",GL_LIMITS(sampler_stages));
5777 TRACE("(%p) : oldtexture(%p)\n", This,oldTexture);
5779 This->updateStateBlock->set.textures[Stage] = TRUE;
5780 This->updateStateBlock->changed.textures[Stage] = TRUE;
5781 TRACE("(%p) : setting new texture to %p\n", This, pTexture);
5782 This->updateStateBlock->textures[Stage] = pTexture;
5784 /* Handle recording of state blocks */
5785 if (This->isRecordingState) {
5786 TRACE("Recording... not performing anything\n");
5790 /** NOTE: MSDN says that setTexture increases the reference count,
5791 * and the the application nust set the texture back to null (or have a leaky application),
5792 * This means we should pass the refcount up to the parent
5793 *******************************/
5794 if (NULL != This->updateStateBlock->textures[Stage]) {
5795 IWineD3DBaseTexture_AddRef(This->updateStateBlock->textures[Stage]);
5798 if (NULL != oldTexture) {
5799 IWineD3DBaseTexture_Release(oldTexture);
5802 /* Reset color keying */
5803 if(Stage == 0 && This->stateBlock->renderState[WINED3DRS_COLORKEYENABLE]) {
5804 BOOL enable_ckey = FALSE;
5807 IWineD3DSurfaceImpl *surf = (IWineD3DSurfaceImpl *) ((IWineD3DTextureImpl *)pTexture)->surfaces[0];
5808 if(surf->CKeyFlags & DDSD_CKSRCBLT) enable_ckey = TRUE;
5812 glAlphaFunc(GL_NOTEQUAL, 0.0);
5813 checkGLcall("glAlphaFunc");
5820 static HRESULT WINAPI IWineD3DDeviceImpl_GetTexture(IWineD3DDevice *iface, DWORD Stage, IWineD3DBaseTexture** ppTexture) {
5821 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5822 TRACE("(%p) : (%d /* Stage */,%p /* ppTexture */)\n", This, Stage, ppTexture);
5824 /* Reject invalid texture units */
5825 if (Stage >= GL_LIMITS(sampler_stages)) {
5826 TRACE("Attempt to access invalid texture rejected\n");
5827 return WINED3DERR_INVALIDCALL;
5829 *ppTexture=This->stateBlock->textures[Stage];
5831 IWineD3DBaseTexture_AddRef(*ppTexture);
5839 static HRESULT WINAPI IWineD3DDeviceImpl_GetBackBuffer(IWineD3DDevice *iface, UINT iSwapChain, UINT BackBuffer, WINED3DBACKBUFFER_TYPE Type,
5840 IWineD3DSurface **ppBackBuffer) {
5841 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5842 IWineD3DSwapChain *swapChain;
5845 TRACE("(%p) : BackBuf %d Type %d SwapChain %d returning %p\n", This, BackBuffer, Type, iSwapChain, *ppBackBuffer);
5847 hr = IWineD3DDeviceImpl_GetSwapChain(iface, iSwapChain, &swapChain);
5848 if (hr == WINED3D_OK) {
5849 hr = IWineD3DSwapChain_GetBackBuffer(swapChain, BackBuffer, Type, ppBackBuffer);
5850 IWineD3DSwapChain_Release(swapChain);
5852 *ppBackBuffer = NULL;
5857 static HRESULT WINAPI IWineD3DDeviceImpl_GetDeviceCaps(IWineD3DDevice *iface, WINED3DCAPS* pCaps) {
5858 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5859 WARN("(%p) : stub, calling idirect3d for now\n", This);
5860 return IWineD3D_GetDeviceCaps(This->wineD3D, This->adapterNo, This->devType, pCaps);
5863 static HRESULT WINAPI IWineD3DDeviceImpl_GetDisplayMode(IWineD3DDevice *iface, UINT iSwapChain, WINED3DDISPLAYMODE* pMode) {
5864 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5865 IWineD3DSwapChain *swapChain;
5868 if(iSwapChain > 0) {
5869 hr = IWineD3DDeviceImpl_GetSwapChain(iface, iSwapChain, (IWineD3DSwapChain **)&swapChain);
5870 if (hr == WINED3D_OK) {
5871 hr = IWineD3DSwapChain_GetDisplayMode(swapChain, pMode);
5872 IWineD3DSwapChain_Release(swapChain);
5874 FIXME("(%p) Error getting display mode\n", This);
5877 /* Don't read the real display mode,
5878 but return the stored mode instead. X11 can't change the color
5879 depth, and some apps are pretty angry if they SetDisplayMode from
5880 24 to 16 bpp and find out that GetDisplayMode still returns 24 bpp
5882 Also don't relay to the swapchain because with ddraw it's possible
5883 that there isn't a swapchain at all */
5884 pMode->Width = This->ddraw_width;
5885 pMode->Height = This->ddraw_height;
5886 pMode->Format = This->ddraw_format;
5887 pMode->RefreshRate = 0;
5894 static HRESULT WINAPI IWineD3DDeviceImpl_SetHWND(IWineD3DDevice *iface, HWND hWnd) {
5895 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5896 TRACE("(%p)->(%p)\n", This, hWnd);
5898 This->ddraw_window = hWnd;
5902 static HRESULT WINAPI IWineD3DDeviceImpl_GetHWND(IWineD3DDevice *iface, HWND *hWnd) {
5903 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5904 TRACE("(%p)->(%p)\n", This, hWnd);
5906 *hWnd = This->ddraw_window;
5911 * Stateblock related functions
5914 static HRESULT WINAPI IWineD3DDeviceImpl_BeginStateBlock(IWineD3DDevice *iface) {
5915 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5916 IWineD3DStateBlockImpl *object;
5917 HRESULT temp_result;
5919 TRACE("(%p)\n", This);
5921 if (This->isRecordingState) {
5922 return WINED3DERR_INVALIDCALL;
5925 object = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(IWineD3DStateBlockImpl));
5926 if (NULL == object ) {
5927 FIXME("(%p)Error allocating memory for stateblock\n", This);
5928 return E_OUTOFMEMORY;
5930 TRACE("(%p) created object %p\n", This, object);
5931 object->wineD3DDevice= This;
5932 /** FIXME: object->parent = parent; **/
5933 object->parent = NULL;
5934 object->blockType = WINED3DSBT_ALL;
5936 object->lpVtbl = &IWineD3DStateBlock_Vtbl;
5938 temp_result = allocate_shader_constants(object);
5939 if (WINED3D_OK != temp_result)
5942 IWineD3DStateBlock_Release((IWineD3DStateBlock*)This->updateStateBlock);
5943 This->updateStateBlock = object;
5944 This->isRecordingState = TRUE;
5946 TRACE("(%p) recording stateblock %p\n",This , object);
5950 static HRESULT WINAPI IWineD3DDeviceImpl_EndStateBlock(IWineD3DDevice *iface, IWineD3DStateBlock** ppStateBlock) {
5951 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5953 if (!This->isRecordingState) {
5954 FIXME("(%p) not recording! returning error\n", This);
5955 *ppStateBlock = NULL;
5956 return WINED3DERR_INVALIDCALL;
5959 *ppStateBlock = (IWineD3DStateBlock*)This->updateStateBlock;
5960 This->isRecordingState = FALSE;
5961 This->updateStateBlock = This->stateBlock;
5962 IWineD3DStateBlock_AddRef((IWineD3DStateBlock*)This->updateStateBlock);
5963 /* IWineD3DStateBlock_AddRef(*ppStateBlock); don't need to do this, since we should really just release UpdateStateBlock first */
5964 TRACE("(%p) returning token (ptr to stateblock) of %p\n", This, *ppStateBlock);
5969 * Scene related functions
5971 static HRESULT WINAPI IWineD3DDeviceImpl_BeginScene(IWineD3DDevice *iface) {
5972 /* At the moment we have no need for any functionality at the beginning
5974 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5975 TRACE("(%p) : stub\n", This);
5979 static HRESULT WINAPI IWineD3DDeviceImpl_EndScene(IWineD3DDevice *iface) {
5980 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5981 TRACE("(%p)\n", This);
5983 /* We only have to do this if we need to read the, swapbuffers performs a flush for us */
5985 checkGLcall("glFlush");
5987 TRACE("End Scene\n");
5988 if(This->renderTarget != NULL) {
5990 /* If the container of the rendertarget is a texture then we need to save the data from the pbuffer */
5991 IUnknown *targetContainer = NULL;
5992 if (WINED3D_OK == IWineD3DSurface_GetContainer(This->renderTarget, &IID_IWineD3DBaseTexture, (void **)&targetContainer)
5993 || WINED3D_OK == IWineD3DSurface_GetContainer(This->renderTarget, &IID_IWineD3DDevice, (void **)&targetContainer)) {
5994 TRACE("(%p) : Texture rendertarget %p\n", This ,This->renderTarget);
5995 /** always dirtify for now. we must find a better way to see that surface have been modified
5996 (Modifications should will only occur via draw-primitive, but we do need better locking
5997 switching to render-to-texture should remove the overhead though.
5999 IWineD3DSurface_SetPBufferState(This->renderTarget, TRUE /* inPBuffer */, FALSE /* inTexture */);
6000 IWineD3DSurface_AddDirtyRect(This->renderTarget, NULL);
6001 IWineD3DSurface_PreLoad(This->renderTarget);
6002 IWineD3DSurface_SetPBufferState(This->renderTarget, FALSE /* inPBuffer */, FALSE /* inTexture */);
6003 IUnknown_Release(targetContainer);
6006 This->sceneEnded = TRUE;
6011 static HRESULT WINAPI IWineD3DDeviceImpl_Present(IWineD3DDevice *iface,
6012 CONST RECT* pSourceRect, CONST RECT* pDestRect,
6013 HWND hDestWindowOverride, CONST RGNDATA* pDirtyRegion) {
6014 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
6015 IWineD3DSwapChain *swapChain = NULL;
6017 int swapchains = IWineD3DDeviceImpl_GetNumberOfSwapChains(iface);
6019 TRACE("(%p) Presenting the frame\n", This);
6021 for(i = 0 ; i < swapchains ; i ++) {
6023 IWineD3DDeviceImpl_GetSwapChain(iface, i , (IWineD3DSwapChain **)&swapChain);
6024 TRACE("presentinng chain %d, %p\n", i, swapChain);
6025 IWineD3DSwapChain_Present(swapChain, pSourceRect, pDestRect, hDestWindowOverride, pDirtyRegion, 0);
6026 IWineD3DSwapChain_Release(swapChain);
6032 static HRESULT WINAPI IWineD3DDeviceImpl_Clear(IWineD3DDevice *iface, DWORD Count, CONST WINED3DRECT* pRects,
6033 DWORD Flags, WINED3DCOLOR Color, float Z, DWORD Stencil) {
6034 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
6036 /* TODO: From MSDN This method fails if you specify the WINED3DCLEAR_ZBUFFER or WINED3DCLEAR_STENCIL flags when the
6037 render target does not have an attached depth buffer. Similarly, if you specify the WINED3DCLEAR_STENCIL flag
6038 when the depth-buffer format does not contain stencil buffer information, this method fails. */
6039 GLbitfield glMask = 0;
6040 GLboolean old_ztest;
6041 GLfloat old_z_clear_value;
6042 GLint old_stencil_clear_value;
6043 GLfloat old_color_clear_value[4];
6045 CONST WINED3DRECT* curRect;
6047 TRACE("(%p) Count (%d), pRects (%p), Flags (%x), Z (%f), Stencil (%d)\n", This,
6048 Count, pRects, Flags, Z, Stencil);
6052 glEnable(GL_SCISSOR_TEST);
6053 checkGLcall("glEnable GL_SCISSOR_TEST");
6055 if (Count > 0 && pRects) {
6061 /* Only set the values up once, as they are not changing */
6062 if (Flags & WINED3DCLEAR_STENCIL) {
6063 glGetIntegerv(GL_STENCIL_CLEAR_VALUE, &old_stencil_clear_value);
6064 glClearStencil(Stencil);
6065 checkGLcall("glClearStencil");
6066 glMask = glMask | GL_STENCIL_BUFFER_BIT;
6067 glStencilMask(0xFFFFFFFF);
6070 if (Flags & WINED3DCLEAR_ZBUFFER) {
6071 glGetBooleanv(GL_DEPTH_WRITEMASK, &old_ztest);
6072 glDepthMask(GL_TRUE);
6073 glGetFloatv(GL_DEPTH_CLEAR_VALUE, &old_z_clear_value);
6075 checkGLcall("glClearDepth");
6076 glMask = glMask | GL_DEPTH_BUFFER_BIT;
6079 if (Flags & WINED3DCLEAR_TARGET) {
6080 TRACE("Clearing screen with glClear to color %x\n", Color);
6081 glGetFloatv(GL_COLOR_CLEAR_VALUE, old_color_clear_value);
6082 glClearColor(D3DCOLOR_R(Color),
6086 checkGLcall("glClearColor");
6088 /* Clear ALL colors! */
6089 glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
6090 glMask = glMask | GL_COLOR_BUFFER_BIT;
6093 /* Now process each rect in turn */
6094 for (i = 0; i < Count || i == 0; i++) {
6097 /* Note gl uses lower left, width/height */
6098 TRACE("(%p) %p Rect=(%d,%d)->(%d,%d) glRect=(%d,%d), len=%d, hei=%d\n", This, curRect,
6099 curRect->x1, curRect->y1, curRect->x2, curRect->y2,
6100 curRect->x1, (((IWineD3DSurfaceImpl *)This->renderTarget)->currentDesc.Height - curRect->y2),
6101 curRect->x2 - curRect->x1, curRect->y2 - curRect->y1);
6102 glScissor(curRect->x1, (((IWineD3DSurfaceImpl *)This->renderTarget)->currentDesc.Height - curRect->y2),
6103 curRect->x2 - curRect->x1, curRect->y2 - curRect->y1);
6104 checkGLcall("glScissor");
6106 glScissor(This->stateBlock->viewport.X,
6107 (((IWineD3DSurfaceImpl *)This->renderTarget)->currentDesc.Height -
6108 (This->stateBlock->viewport.Y + This->stateBlock->viewport.Height)),
6109 This->stateBlock->viewport.Width,
6110 This->stateBlock->viewport.Height);
6111 checkGLcall("glScissor");
6114 /* Clear the selected rectangle (or full screen) */
6116 checkGLcall("glClear");
6118 /* Step to the next rectangle */
6119 if (curRect) curRect = curRect + sizeof(WINED3DRECT);
6122 /* Restore the old values (why..?) */
6123 if (Flags & WINED3DCLEAR_STENCIL) {
6124 glClearStencil(old_stencil_clear_value);
6125 glStencilMask(This->stateBlock->renderState[WINED3DRS_STENCILWRITEMASK]);
6127 if (Flags & WINED3DCLEAR_ZBUFFER) {
6128 glDepthMask(old_ztest);
6129 glClearDepth(old_z_clear_value);
6131 if (Flags & WINED3DCLEAR_TARGET) {
6132 glClearColor(old_color_clear_value[0],
6133 old_color_clear_value[1],
6134 old_color_clear_value[2],
6135 old_color_clear_value[3]);
6136 glColorMask(This->stateBlock->renderState[WINED3DRS_COLORWRITEENABLE] & WINED3DCOLORWRITEENABLE_RED ? GL_TRUE : GL_FALSE,
6137 This->stateBlock->renderState[WINED3DRS_COLORWRITEENABLE] & WINED3DCOLORWRITEENABLE_GREEN ? GL_TRUE : GL_FALSE,
6138 This->stateBlock->renderState[WINED3DRS_COLORWRITEENABLE] & WINED3DCOLORWRITEENABLE_BLUE ? GL_TRUE : GL_FALSE,
6139 This->stateBlock->renderState[WINED3DRS_COLORWRITEENABLE] & WINED3DCOLORWRITEENABLE_ALPHA ? GL_TRUE : GL_FALSE);
6142 glDisable(GL_SCISSOR_TEST);
6143 checkGLcall("glDisable");
6152 static HRESULT WINAPI IWineD3DDeviceImpl_DrawPrimitive(IWineD3DDevice *iface, WINED3DPRIMITIVETYPE PrimitiveType, UINT StartVertex,
6153 UINT PrimitiveCount) {
6155 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
6156 This->stateBlock->streamIsUP = FALSE;
6158 TRACE("(%p) : Type=(%d,%s), Start=%d, Count=%d\n", This, PrimitiveType,
6159 debug_d3dprimitivetype(PrimitiveType),
6160 StartVertex, PrimitiveCount);
6161 drawPrimitive(iface, PrimitiveType, PrimitiveCount, StartVertex, 0/* NumVertices */, -1 /* indxStart */,
6162 0 /* indxSize */, NULL /* indxData */, 0 /* minIndex */, NULL);
6168 /* TODO: baseVIndex needs to be provided from This->stateBlock->baseVertexIndex when called from d3d8 */
6169 static HRESULT WINAPI IWineD3DDeviceImpl_DrawIndexedPrimitive(IWineD3DDevice *iface,
6170 WINED3DPRIMITIVETYPE PrimitiveType,
6171 INT baseVIndex, UINT minIndex,
6172 UINT NumVertices, UINT startIndex, UINT primCount) {
6174 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
6176 IWineD3DIndexBuffer *pIB;
6177 WINED3DINDEXBUFFER_DESC IdxBufDsc;
6179 pIB = This->stateBlock->pIndexData;
6180 This->stateBlock->streamIsUP = FALSE;
6182 TRACE("(%p) : Type=(%d,%s), min=%d, CountV=%d, startIdx=%d, baseVidx=%d, countP=%d\n", This,
6183 PrimitiveType, debug_d3dprimitivetype(PrimitiveType),
6184 minIndex, NumVertices, startIndex, baseVIndex, primCount);
6186 IWineD3DIndexBuffer_GetDesc(pIB, &IdxBufDsc);
6187 if (IdxBufDsc.Format == WINED3DFMT_INDEX16) {
6193 drawPrimitive(iface, PrimitiveType, primCount, baseVIndex, NumVertices, startIndex,
6194 idxStride, ((IWineD3DIndexBufferImpl *) pIB)->resource.allocatedMemory, minIndex, NULL);
6199 static HRESULT WINAPI IWineD3DDeviceImpl_DrawPrimitiveUP(IWineD3DDevice *iface, WINED3DPRIMITIVETYPE PrimitiveType,
6200 UINT PrimitiveCount, CONST void* pVertexStreamZeroData,
6201 UINT VertexStreamZeroStride) {
6202 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
6204 TRACE("(%p) : Type=(%d,%s), pCount=%d, pVtxData=%p, Stride=%d\n", This, PrimitiveType,
6205 debug_d3dprimitivetype(PrimitiveType),
6206 PrimitiveCount, pVertexStreamZeroData, VertexStreamZeroStride);
6208 /* release the stream source */
6209 if (This->stateBlock->streamSource[0] != NULL) {
6210 IWineD3DVertexBuffer_Release(This->stateBlock->streamSource[0]);
6213 /* Note in the following, it's not this type, but that's the purpose of streamIsUP */
6214 This->stateBlock->streamSource[0] = (IWineD3DVertexBuffer *)pVertexStreamZeroData;
6215 This->stateBlock->streamStride[0] = VertexStreamZeroStride;
6216 This->stateBlock->streamIsUP = TRUE;
6218 drawPrimitive(iface, PrimitiveType, PrimitiveCount, 0 /* start vertex */, 0 /* NumVertices */,
6219 0 /* indxStart*/, 0 /* indxSize*/, NULL /* indxData */, 0 /* indxMin */, NULL);
6221 /* MSDN specifies stream zero settings must be set to NULL */
6222 This->stateBlock->streamStride[0] = 0;
6223 This->stateBlock->streamSource[0] = NULL;
6225 /*stream zero settings set to null at end, as per the msdn */
6229 static HRESULT WINAPI IWineD3DDeviceImpl_DrawIndexedPrimitiveUP(IWineD3DDevice *iface, WINED3DPRIMITIVETYPE PrimitiveType,
6230 UINT MinVertexIndex, UINT NumVertices,
6231 UINT PrimitiveCount, CONST void* pIndexData,
6232 WINED3DFORMAT IndexDataFormat,CONST void* pVertexStreamZeroData,
6233 UINT VertexStreamZeroStride) {
6235 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
6237 TRACE("(%p) : Type=(%d,%s), MinVtxIdx=%d, NumVIdx=%d, PCount=%d, pidxdata=%p, IdxFmt=%d, pVtxdata=%p, stride=%d\n",
6238 This, PrimitiveType, debug_d3dprimitivetype(PrimitiveType),
6239 MinVertexIndex, NumVertices, PrimitiveCount, pIndexData,
6240 IndexDataFormat, pVertexStreamZeroData, VertexStreamZeroStride);
6242 if (IndexDataFormat == WINED3DFMT_INDEX16) {
6248 /* release the stream and index data */
6249 if (This->stateBlock->streamSource[0] != NULL) {
6250 IWineD3DVertexBuffer_Release(This->stateBlock->streamSource[0]);
6252 if (This->stateBlock->pIndexData) {
6253 IWineD3DIndexBuffer_Release(This->stateBlock->pIndexData);
6256 /* Note in the following, it's not this type, but that's the purpose of streamIsUP */
6257 This->stateBlock->streamSource[0] = (IWineD3DVertexBuffer *)pVertexStreamZeroData;
6258 This->stateBlock->streamIsUP = TRUE;
6259 This->stateBlock->streamStride[0] = VertexStreamZeroStride;
6261 drawPrimitive(iface, PrimitiveType, PrimitiveCount, 0 /* vertexStart */, NumVertices, 0 /* indxStart */, idxStride, pIndexData, MinVertexIndex, NULL);
6263 /* MSDN specifies stream zero settings and index buffer must be set to NULL */
6264 This->stateBlock->streamSource[0] = NULL;
6265 This->stateBlock->streamStride[0] = 0;
6266 This->stateBlock->pIndexData = NULL;
6271 static HRESULT WINAPI IWineD3DDeviceImpl_DrawPrimitiveStrided (IWineD3DDevice *iface, WINED3DPRIMITIVETYPE PrimitiveType, UINT PrimitiveCount, WineDirect3DVertexStridedData *DrawPrimStrideData) {
6273 drawPrimitive(iface, PrimitiveType, PrimitiveCount, 0, 0, 0, 0, NULL, 0, DrawPrimStrideData);
6276 /* Yet another way to update a texture, some apps use this to load default textures instead of using surface/texture lock/unlock */
6277 static HRESULT WINAPI IWineD3DDeviceImpl_UpdateTexture (IWineD3DDevice *iface, IWineD3DBaseTexture *pSourceTexture, IWineD3DBaseTexture *pDestinationTexture){
6278 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
6279 HRESULT hr = WINED3D_OK;
6280 WINED3DRESOURCETYPE sourceType;
6281 WINED3DRESOURCETYPE destinationType;
6284 /* TODO: think about moving the code into IWineD3DBaseTexture */
6286 TRACE("(%p) Source %p Destination %p\n", This, pSourceTexture, pDestinationTexture);
6288 /* verify that the source and destination textures aren't NULL */
6289 if (NULL == pSourceTexture || NULL == pDestinationTexture) {
6290 WARN("(%p) : source (%p) and destination (%p) textures must not be NULL, returning WINED3DERR_INVALIDCALL\n",
6291 This, pSourceTexture, pDestinationTexture);
6292 hr = WINED3DERR_INVALIDCALL;
6295 if (pSourceTexture == pDestinationTexture) {
6296 WARN("(%p) : source (%p) and destination (%p) textures must be different, returning WINED3DERR_INVALIDCALL\n",
6297 This, pSourceTexture, pDestinationTexture);
6298 hr = WINED3DERR_INVALIDCALL;
6300 /* Verify that the source and destination textures are the same type */
6301 sourceType = IWineD3DBaseTexture_GetType(pSourceTexture);
6302 destinationType = IWineD3DBaseTexture_GetType(pDestinationTexture);
6304 if (sourceType != destinationType) {
6305 WARN("(%p) Sorce and destination types must match, returning WINED3DERR_INVALIDCALL\n",
6307 hr = WINED3DERR_INVALIDCALL;
6310 /* check that both textures have the identical numbers of levels */
6311 if (IWineD3DBaseTexture_GetLevelCount(pDestinationTexture) != IWineD3DBaseTexture_GetLevelCount(pSourceTexture)) {
6312 WARN("(%p) : source (%p) and destination (%p) textures must have identicle numbers of levels, returning WINED3DERR_INVALIDCALL\n", This, pSourceTexture, pDestinationTexture);
6313 hr = WINED3DERR_INVALIDCALL;
6316 if (WINED3D_OK == hr) {
6318 /* Make sure that the destination texture is loaded */
6319 IWineD3DBaseTexture_PreLoad(pDestinationTexture);
6321 /* Update every surface level of the texture */
6322 levels = IWineD3DBaseTexture_GetLevelCount(pDestinationTexture);
6324 switch (sourceType) {
6325 case WINED3DRTYPE_TEXTURE:
6327 IWineD3DSurface *srcSurface;
6328 IWineD3DSurface *destSurface;
6330 for (i = 0 ; i < levels ; ++i) {
6331 IWineD3DTexture_GetSurfaceLevel((IWineD3DTexture *)pSourceTexture, i, &srcSurface);
6332 IWineD3DTexture_GetSurfaceLevel((IWineD3DTexture *)pDestinationTexture, i, &destSurface);
6333 hr = IWineD3DDevice_UpdateSurface(iface, srcSurface, NULL, destSurface, NULL);
6334 IWineD3DSurface_Release(srcSurface);
6335 IWineD3DSurface_Release(destSurface);
6336 if (WINED3D_OK != hr) {
6337 WARN("(%p) : Call to update surface failed\n", This);
6343 case WINED3DRTYPE_CUBETEXTURE:
6345 IWineD3DSurface *srcSurface;
6346 IWineD3DSurface *destSurface;
6347 WINED3DCUBEMAP_FACES faceType;
6349 for (i = 0 ; i < levels ; ++i) {
6350 /* Update each cube face */
6351 for (faceType = WINED3DCUBEMAP_FACE_POSITIVE_X; faceType <= WINED3DCUBEMAP_FACE_NEGATIVE_Z; ++faceType){
6352 hr = IWineD3DCubeTexture_GetCubeMapSurface((IWineD3DCubeTexture *)pSourceTexture, faceType, i, &srcSurface);
6353 if (WINED3D_OK != hr) {
6354 FIXME("(%p) : Failed to get src cube surface facetype %d, level %d\n", This, faceType, i);
6356 TRACE("Got srcSurface %p\n", srcSurface);
6358 hr = IWineD3DCubeTexture_GetCubeMapSurface((IWineD3DCubeTexture *)pDestinationTexture, faceType, i, &destSurface);
6359 if (WINED3D_OK != hr) {
6360 FIXME("(%p) : Failed to get src cube surface facetype %d, level %d\n", This, faceType, i);
6362 TRACE("Got desrSurface %p\n", destSurface);
6364 hr = IWineD3DDevice_UpdateSurface(iface, srcSurface, NULL, destSurface, NULL);
6365 IWineD3DSurface_Release(srcSurface);
6366 IWineD3DSurface_Release(destSurface);
6367 if (WINED3D_OK != hr) {
6368 WARN("(%p) : Call to update surface failed\n", This);
6375 #if 0 /* TODO: Add support for volume textures */
6376 case WINED3DRTYPE_VOLUMETEXTURE:
6378 IWineD3DVolume srcVolume = NULL;
6379 IWineD3DSurface destVolume = NULL;
6381 for (i = 0 ; i < levels ; ++i) {
6382 IWineD3DVolumeTexture_GetVolume((IWineD3DVolumeTexture *)pSourceTexture, i, &srcVolume);
6383 IWineD3DVolumeTexture_GetVolume((IWineD3DVolumeTexture *)pDestinationTexture, i, &destVolume);
6384 hr = IWineD3DFoo_UpdateVolume(iface, srcVolume, NULL, destVolume, NULL);
6385 IWineD3DVolume_Release(srcSurface);
6386 IWineD3DVolume_Release(destSurface);
6387 if (WINED3D_OK != hr) {
6388 WARN("(%p) : Call to update volume failed\n", This);
6396 FIXME("(%p) : Unsupported source and destination type\n", This);
6397 hr = WINED3DERR_INVALIDCALL;
6404 static HRESULT WINAPI IWineD3DDeviceImpl_StretchRect(IWineD3DDevice *iface, IWineD3DSurface *pSourceSurface,
6405 CONST RECT* pSourceRect, IWineD3DSurface *pDestinationSurface,
6406 CONST RECT* pDestRect, WINED3DTEXTUREFILTERTYPE Filter) {
6407 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
6409 TRACE("(%p) : stub\n", This);
6412 static HRESULT WINAPI IWineD3DDeviceImpl_GetRenderTargetData(IWineD3DDevice *iface, IWineD3DSurface *pRenderTarget, IWineD3DSurface *pSurface) {
6413 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
6414 /** TODO: remove remove casts to IWineD3DSurfaceImpl *
6415 * NOTE It may be best to move the code into surface to occomplish this
6416 ****************************************/
6418 WINED3DSURFACE_DESC surfaceDesc;
6419 unsigned int surfaceWidth, surfaceHeight;
6420 glDescriptor *targetGlDescription = NULL;
6421 glDescriptor *surfaceGlDescription = NULL;
6422 IWineD3DSwapChainImpl *container = NULL;
6424 IWineD3DSurface_GetGlDesc(pRenderTarget, &targetGlDescription);
6425 IWineD3DSurface_GetGlDesc(pSurface, &surfaceGlDescription);
6426 memset(&surfaceDesc, 0, sizeof(surfaceDesc));
6428 surfaceDesc.Width = &surfaceWidth;
6429 surfaceDesc.Height = &surfaceHeight;
6430 IWineD3DSurface_GetDesc(pSurface, &surfaceDesc);
6431 /* check to see if it's the backbuffer or the frontbuffer being requested (to make sure the data is up to date)*/
6433 /* Ok, I may need to setup some kind of active swapchain reference on the device */
6434 IWineD3DSurface_GetContainer(pRenderTarget, &IID_IWineD3DSwapChain, (void **)&container);
6436 /* TODO: opengl Context switching for swapchains etc... */
6437 if (NULL != container || pRenderTarget == This->renderTarget || pRenderTarget == This->depthStencilBuffer) {
6438 if (NULL != container && (pRenderTarget == container->backBuffer[0])) {
6439 glReadBuffer(GL_BACK);
6440 vcheckGLcall("glReadBuffer(GL_BACK)");
6441 } else if ((NULL != container && (pRenderTarget == container->frontBuffer)) || (pRenderTarget == This->renderTarget)) {
6442 glReadBuffer(GL_FRONT);
6443 vcheckGLcall("glReadBuffer(GL_FRONT)");
6444 } else if (pRenderTarget == This->depthStencilBuffer) {
6445 FIXME("Reading of depthstencil not yet supported\n");
6452 surfaceGlDescription->glFormat,
6453 surfaceGlDescription->glType,
6454 (void *)IWineD3DSurface_GetData(pSurface));
6455 vcheckGLcall("glReadPixels(...)");
6456 if(NULL != container ){
6457 IWineD3DSwapChain_Release((IWineD3DSwapChain*) container);
6460 IWineD3DBaseTexture *container;
6461 GLenum textureDimensions = GL_TEXTURE_2D;
6463 if (WINED3D_OK == IWineD3DSurface_GetContainer(pSurface, &IID_IWineD3DBaseTexture, (void **)&container)) {
6464 textureDimensions = IWineD3DBaseTexture_GetTextureDimensions(container);
6465 IWineD3DBaseTexture_Release(container);
6467 /* TODO: 2D -> Cube surface coppies etc.. */
6468 if (surfaceGlDescription->target != textureDimensions) {
6469 FIXME("(%p) : Texture dimension mismatch\n", This);
6471 glEnable(textureDimensions);
6472 vcheckGLcall("glEnable(GL_TEXTURE_...)");
6473 /* FIXME: this isn't correct, it need to add a dirty rect if nothing else... */
6474 glBindTexture(targetGlDescription->target, targetGlDescription->textureName);
6475 vcheckGLcall("glBindTexture");
6476 glGetTexImage(surfaceGlDescription->target,
6477 surfaceGlDescription->level,
6478 surfaceGlDescription->glFormat,
6479 surfaceGlDescription->glType,
6480 (void *)IWineD3DSurface_GetData(pSurface));
6481 glDisable(textureDimensions);
6482 vcheckGLcall("glDisable(GL_TEXTURE_...)");
6489 static HRESULT WINAPI IWineD3DDeviceImpl_GetFrontBufferData(IWineD3DDevice *iface,UINT iSwapChain, IWineD3DSurface *pDestSurface) {
6490 IWineD3DSwapChain *swapChain;
6492 hr = IWineD3DDeviceImpl_GetSwapChain(iface, iSwapChain, (IWineD3DSwapChain **)&swapChain);
6493 if(hr == WINED3D_OK) {
6494 hr = IWineD3DSwapChain_GetFrontBufferData(swapChain, pDestSurface);
6495 IWineD3DSwapChain_Release(swapChain);
6500 static HRESULT WINAPI IWineD3DDeviceImpl_ValidateDevice(IWineD3DDevice *iface, DWORD* pNumPasses) {
6501 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
6502 /* return a sensible default */
6504 /* TODO: If the window is minimized then validate device should return something other than WINED3D_OK */
6505 FIXME("(%p) : stub\n", This);
6509 static HRESULT WINAPI IWineD3DDeviceImpl_SetPaletteEntries(IWineD3DDevice *iface, UINT PaletteNumber, CONST PALETTEENTRY* pEntries) {
6510 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
6512 TRACE("(%p) : PaletteNumber %u\n", This, PaletteNumber);
6513 if ( PaletteNumber < 0 || PaletteNumber >= MAX_PALETTES) {
6514 WARN("(%p) : (%u) Out of range 0-%u, returning Invalid Call\n", This, PaletteNumber, MAX_PALETTES);
6515 return WINED3DERR_INVALIDCALL;
6517 for (j = 0; j < 256; ++j) {
6518 This->palettes[PaletteNumber][j].peRed = pEntries[j].peRed;
6519 This->palettes[PaletteNumber][j].peGreen = pEntries[j].peGreen;
6520 This->palettes[PaletteNumber][j].peBlue = pEntries[j].peBlue;
6521 This->palettes[PaletteNumber][j].peFlags = pEntries[j].peFlags;
6523 TRACE("(%p) : returning\n", This);
6527 static HRESULT WINAPI IWineD3DDeviceImpl_GetPaletteEntries(IWineD3DDevice *iface, UINT PaletteNumber, PALETTEENTRY* pEntries) {
6528 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
6530 TRACE("(%p) : PaletteNumber %u\n", This, PaletteNumber);
6531 if ( PaletteNumber < 0 || PaletteNumber >= MAX_PALETTES) {
6532 WARN("(%p) : (%u) Out of range 0-%u, returning Invalid Call\n", This, PaletteNumber, MAX_PALETTES);
6533 return WINED3DERR_INVALIDCALL;
6535 for (j = 0; j < 256; ++j) {
6536 pEntries[j].peRed = This->palettes[PaletteNumber][j].peRed;
6537 pEntries[j].peGreen = This->palettes[PaletteNumber][j].peGreen;
6538 pEntries[j].peBlue = This->palettes[PaletteNumber][j].peBlue;
6539 pEntries[j].peFlags = This->palettes[PaletteNumber][j].peFlags;
6541 TRACE("(%p) : returning\n", This);
6545 static HRESULT WINAPI IWineD3DDeviceImpl_SetCurrentTexturePalette(IWineD3DDevice *iface, UINT PaletteNumber) {
6546 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
6547 TRACE("(%p) : PaletteNumber %u\n", This, PaletteNumber);
6548 if ( PaletteNumber < 0 || PaletteNumber >= MAX_PALETTES) {
6549 WARN("(%p) : (%u) Out of range 0-%u, returning Invalid Call\n", This, PaletteNumber, MAX_PALETTES);
6550 return WINED3DERR_INVALIDCALL;
6552 /*TODO: stateblocks */
6553 This->currentPalette = PaletteNumber;
6554 TRACE("(%p) : returning\n", This);
6558 static HRESULT WINAPI IWineD3DDeviceImpl_GetCurrentTexturePalette(IWineD3DDevice *iface, UINT* PaletteNumber) {
6559 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
6560 if (PaletteNumber == NULL) {
6561 WARN("(%p) : returning Invalid Call\n", This);
6562 return WINED3DERR_INVALIDCALL;
6564 /*TODO: stateblocks */
6565 *PaletteNumber = This->currentPalette;
6566 TRACE("(%p) : returning %u\n", This, *PaletteNumber);
6570 static HRESULT WINAPI IWineD3DDeviceImpl_SetSoftwareVertexProcessing(IWineD3DDevice *iface, BOOL bSoftware) {
6571 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
6572 static BOOL showFixmes = TRUE;
6574 FIXME("(%p) : stub\n", This);
6578 This->softwareVertexProcessing = bSoftware;
6583 static BOOL WINAPI IWineD3DDeviceImpl_GetSoftwareVertexProcessing(IWineD3DDevice *iface) {
6584 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
6585 static BOOL showFixmes = TRUE;
6587 FIXME("(%p) : stub\n", This);
6590 return This->softwareVertexProcessing;
6594 static HRESULT WINAPI IWineD3DDeviceImpl_GetRasterStatus(IWineD3DDevice *iface, UINT iSwapChain, WINED3DRASTER_STATUS* pRasterStatus) {
6595 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
6596 IWineD3DSwapChain *swapChain;
6599 TRACE("(%p) : SwapChain %d returning %p\n", This, iSwapChain, pRasterStatus);
6601 hr = IWineD3DDeviceImpl_GetSwapChain(iface, iSwapChain, (IWineD3DSwapChain **)&swapChain);
6602 if(hr == WINED3D_OK){
6603 hr = IWineD3DSwapChain_GetRasterStatus(swapChain, pRasterStatus);
6604 IWineD3DSwapChain_Release(swapChain);
6606 FIXME("(%p) IWineD3DSwapChain_GetRasterStatus returned in error\n", This);
6612 static HRESULT WINAPI IWineD3DDeviceImpl_SetNPatchMode(IWineD3DDevice *iface, float nSegments) {
6613 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
6614 static BOOL showfixmes = TRUE;
6615 if(nSegments != 0.0f) {
6617 FIXME("(%p) : stub nSegments(%f)\n", This, nSegments);
6624 static float WINAPI IWineD3DDeviceImpl_GetNPatchMode(IWineD3DDevice *iface) {
6625 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
6626 static BOOL showfixmes = TRUE;
6628 FIXME("(%p) : stub returning(%f)\n", This, 0.0f);
6634 static HRESULT WINAPI IWineD3DDeviceImpl_UpdateSurface(IWineD3DDevice *iface, IWineD3DSurface *pSourceSurface, CONST RECT* pSourceRect, IWineD3DSurface *pDestinationSurface, CONST POINT* pDestPoint) {
6635 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *) iface;
6636 /** TODO: remove casts to IWineD3DSurfaceImpl
6637 * NOTE: move code to surface to accomplish this
6638 ****************************************/
6639 IWineD3DSurfaceImpl *pSrcSurface = (IWineD3DSurfaceImpl *)pSourceSurface;
6640 int srcWidth, srcHeight;
6641 unsigned int srcSurfaceWidth, srcSurfaceHeight, destSurfaceWidth, destSurfaceHeight;
6642 WINED3DFORMAT destFormat, srcFormat;
6644 int destLeft, destTop;
6645 WINED3DPOOL srcPool, destPool;
6647 int rowoffset = 0; /* how many bytes to add onto the end of a row to wraparound to the beginning of the next */
6648 glDescriptor *glDescription = NULL;
6649 GLenum textureDimensions = GL_TEXTURE_2D;
6650 IWineD3DBaseTexture *baseTexture;
6652 WINED3DSURFACE_DESC winedesc;
6654 TRACE("(%p) : Source (%p) Rect (%p) Destination (%p) Point(%p)\n", This, pSourceSurface, pSourceRect, pDestinationSurface, pDestPoint);
6655 memset(&winedesc, 0, sizeof(winedesc));
6656 winedesc.Width = &srcSurfaceWidth;
6657 winedesc.Height = &srcSurfaceHeight;
6658 winedesc.Pool = &srcPool;
6659 winedesc.Format = &srcFormat;
6661 IWineD3DSurface_GetDesc(pSourceSurface, &winedesc);
6663 winedesc.Width = &destSurfaceWidth;
6664 winedesc.Height = &destSurfaceHeight;
6665 winedesc.Pool = &destPool;
6666 winedesc.Format = &destFormat;
6667 winedesc.Size = &destSize;
6669 IWineD3DSurface_GetDesc(pDestinationSurface, &winedesc);
6671 if(srcPool != WINED3DPOOL_SYSTEMMEM || destPool != WINED3DPOOL_DEFAULT){
6672 WARN("source %p must be SYSTEMMEM and dest %p must be DEFAULT, returning WINED3DERR_INVALIDCALL\n", pSourceSurface, pDestinationSurface);
6673 return WINED3DERR_INVALIDCALL;
6676 if (destFormat == WINED3DFMT_UNKNOWN) {
6677 TRACE("(%p) : Converting destination surface from WINED3DFMT_UNKNOWN to the source format\n", This);
6678 IWineD3DSurface_SetFormat(pDestinationSurface, srcFormat);
6680 /* Get the update surface description */
6681 IWineD3DSurface_GetDesc(pDestinationSurface, &winedesc);
6684 /* Make sure the surface is loaded and up to date */
6685 IWineD3DSurface_PreLoad(pDestinationSurface);
6687 IWineD3DSurface_GetGlDesc(pDestinationSurface, &glDescription);
6691 /* this needs to be done in lines if the sourceRect != the sourceWidth */
6692 srcWidth = pSourceRect ? pSourceRect->right - pSourceRect->left : srcSurfaceWidth;
6693 srcHeight = pSourceRect ? pSourceRect->top - pSourceRect->bottom : srcSurfaceHeight;
6694 destLeft = pDestPoint ? pDestPoint->x : 0;
6695 destTop = pDestPoint ? pDestPoint->y : 0;
6698 /* This function doesn't support compressed textures
6699 the pitch is just bytesPerPixel * width */
6700 if(srcWidth != srcSurfaceWidth || (pSourceRect != NULL && pSourceRect->left != 0) ){
6701 rowoffset = (srcSurfaceWidth - srcWidth) * pSrcSurface->bytesPerPixel;
6702 offset += pSourceRect->left * pSrcSurface->bytesPerPixel;
6703 /* TODO: do we ever get 3bpp?, would a shift and an add be quicker than a mul (well maybe a cycle or two) */
6705 /* TODO DXT formats */
6707 if(pSourceRect != NULL && pSourceRect->top != 0){
6708 offset += pSourceRect->top * srcWidth * pSrcSurface->bytesPerPixel;
6710 TRACE("(%p) glTexSubImage2D, Level %d, left %d, top %d, width %d, height %d , ftm %d, type %d, memory %p\n"
6712 ,glDescription->level
6717 ,glDescription->glFormat
6718 ,glDescription->glType
6719 ,IWineD3DSurface_GetData(pSourceSurface)
6723 if (IWineD3DSurface_GetData(pSourceSurface) == NULL) {
6725 /* need to lock the surface to get the data */
6726 FIXME("Surfaces has no allocated memory, but should be an in memory only surface\n");
6729 /* TODO: Cube and volume support */
6731 /* not a whole row so we have to do it a line at a time */
6734 /* hopefully using pointer addtion will be quicker than using a point + j * rowoffset */
6735 unsigned char* data =((unsigned char *)IWineD3DSurface_GetData(pSourceSurface)) + offset;
6737 for(j = destTop ; j < (srcHeight + destTop) ; j++){
6739 glTexSubImage2D(glDescription->target
6740 ,glDescription->level
6745 ,glDescription->glFormat
6746 ,glDescription->glType
6747 ,data /* could be quicker using */
6752 } else { /* Full width, so just write out the whole texture */
6754 if (WINED3DFMT_DXT1 == destFormat ||
6755 WINED3DFMT_DXT2 == destFormat ||
6756 WINED3DFMT_DXT3 == destFormat ||
6757 WINED3DFMT_DXT4 == destFormat ||
6758 WINED3DFMT_DXT5 == destFormat) {
6759 if (GL_SUPPORT(EXT_TEXTURE_COMPRESSION_S3TC)) {
6760 if (destSurfaceHeight != srcHeight || destSurfaceWidth != srcWidth) {
6761 /* FIXME: The easy way to do this is to lock the destination, and copy the bits across */
6762 FIXME("Updating part of a compressed texture is not supported at the moment\n");
6763 } if (destFormat != srcFormat) {
6764 FIXME("Updating mixed format compressed texture is not curretly support\n");
6766 GL_EXTCALL(glCompressedTexImage2DARB)(glDescription->target,
6767 glDescription->level,
6768 glDescription->glFormatInternal,
6773 IWineD3DSurface_GetData(pSourceSurface));
6776 FIXME("Attempting to update a DXT compressed texture without hardware support\n");
6781 if (NP2_REPACK == wined3d_settings.nonpower2_mode) {
6783 /* some applications cannot handle odd pitches returned by soft non-power2, so we have
6784 to repack the data from pow2Width/Height to expected Width,Height, this makes the
6785 data returned by GetData non-power2 width/height with hardware non-power2
6786 pow2Width/height are set to surface width height, repacking isn't needed so it
6787 doesn't matter which function gets called. */
6788 glTexSubImage2D(glDescription->target
6789 ,glDescription->level
6794 ,glDescription->glFormat
6795 ,glDescription->glType
6796 ,IWineD3DSurface_GetData(pSourceSurface)
6800 /* not repacked, the data returned by IWineD3DSurface_GetData is pow2Width x pow2Height */
6801 glTexSubImage2D(glDescription->target
6802 ,glDescription->level
6805 ,((IWineD3DSurfaceImpl *)pSourceSurface)->pow2Width
6806 ,((IWineD3DSurfaceImpl *)pSourceSurface)->pow2Height
6807 ,glDescription->glFormat
6808 ,glDescription->glType
6809 ,IWineD3DSurface_GetData(pSourceSurface)
6815 checkGLcall("glTexSubImage2D");
6816 ((IWineD3DSurfaceImpl *)pDestinationSurface)->Flags |= SFLAG_GLDIRTY;
6818 /* I only need to look up baseTexture here, so it may be a good idea to hava a GL_TARGET ->
6819 * GL_DIMENSIONS lookup, or maybe store the dimensions on the surface (but that's making the
6820 * surface bigger than it needs to be hmm.. */
6821 if (WINED3D_OK == IWineD3DSurface_GetContainer(pDestinationSurface, &IID_IWineD3DBaseTexture, (void **)&baseTexture)) {
6822 textureDimensions = IWineD3DBaseTexture_GetTextureDimensions(baseTexture);
6823 IWineD3DBaseTexture_Release(baseTexture);
6826 glDisable(textureDimensions); /* This needs to be managed better.... */
6832 /* Implementation details at http://developer.nvidia.com/attach/6494
6834 http://oss.sgi.com/projects/ogl-sample/registry/NV/evaluators.txt
6835 hmm.. no longer supported use
6836 OpenGL evaluators or tessellate surfaces within your application.
6839 /* http://msdn.microsoft.com/library/default.asp?url=/library/en-us/directx9_c/directx/graphics/reference/d3d/interfaces/idirect3ddevice9/DrawRectPatch.asp */
6840 static HRESULT WINAPI IWineD3DDeviceImpl_DrawRectPatch(IWineD3DDevice *iface, UINT Handle, CONST float* pNumSegs, CONST WINED3DRECTPATCH_INFO* pRectPatchInfo) {
6841 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
6842 TRACE("(%p) Handle(%d) noSegs(%p) rectpatch(%p)\n", This, Handle, pNumSegs, pRectPatchInfo);
6843 FIXME("(%p) : Stub\n", This);
6848 /* http://msdn.microsoft.com/library/default.asp?url=/library/en-us/directx9_c/directx/graphics/reference/d3d/interfaces/idirect3ddevice9/DrawTriPatch.asp */
6849 static HRESULT WINAPI IWineD3DDeviceImpl_DrawTriPatch(IWineD3DDevice *iface, UINT Handle, CONST float* pNumSegs, CONST WINED3DTRIPATCH_INFO* pTriPatchInfo) {
6850 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
6851 TRACE("(%p) Handle(%d) noSegs(%p) tripatch(%p)\n", This, Handle, pNumSegs, pTriPatchInfo);
6852 FIXME("(%p) : Stub\n", This);
6856 static HRESULT WINAPI IWineD3DDeviceImpl_DeletePatch(IWineD3DDevice *iface, UINT Handle) {
6857 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
6858 TRACE("(%p) Handle(%d)\n", This, Handle);
6859 FIXME("(%p) : Stub\n", This);
6863 static HRESULT WINAPI IWineD3DDeviceImpl_ColorFill(IWineD3DDevice *iface, IWineD3DSurface *pSurface, CONST WINED3DRECT* pRect, WINED3DCOLOR color) {
6864 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *) iface;
6865 IWineD3DSurfaceImpl *surface = (IWineD3DSurfaceImpl *) pSurface;
6867 TRACE("(%p) Colour fill Surface: %p rect: %p color: %d\n", This, pSurface, pRect, color);
6869 if (surface->resource.pool != WINED3DPOOL_DEFAULT && surface->resource.pool != WINED3DPOOL_SYSTEMMEM) {
6870 FIXME("call to colorfill with non WINED3DPOOL_DEFAULT or WINED3DPOOL_SYSTEMMEM surface\n");
6871 return WINED3DERR_INVALIDCALL;
6874 /* Just forward this to the DirectDraw blitting engine */
6875 memset(&BltFx, 0, sizeof(BltFx));
6876 BltFx.dwSize = sizeof(BltFx);
6877 BltFx.u5.dwFillColor = color;
6878 return IWineD3DSurface_Blt(pSurface, (RECT *) pRect, NULL, NULL, DDBLT_COLORFILL, &BltFx);
6881 /* rendertarget and deptth stencil functions */
6882 static HRESULT WINAPI IWineD3DDeviceImpl_GetRenderTarget(IWineD3DDevice* iface,DWORD RenderTargetIndex, IWineD3DSurface **ppRenderTarget) {
6883 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
6885 /* FIXME: Implelent RenderTargetIndex >0 */
6886 if(RenderTargetIndex > 0)
6887 FIXME("(%p) : RenderTargetIndex %d >0 not currently supported\n", This, RenderTargetIndex);
6889 *ppRenderTarget = This->renderTarget;
6890 TRACE("(%p) : RenderTarget %d Index returning %p\n", This, RenderTargetIndex, *ppRenderTarget);
6891 /* Note inc ref on returned surface */
6892 if(*ppRenderTarget != NULL)
6893 IWineD3DSurface_AddRef(*ppRenderTarget);
6897 static HRESULT WINAPI IWineD3DDeviceImpl_SetFrontBackBuffers(IWineD3DDevice *iface, IWineD3DSurface *Front, IWineD3DSurface *Back) {
6898 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
6899 IWineD3DSurfaceImpl *FrontImpl = (IWineD3DSurfaceImpl *) Front;
6900 IWineD3DSurfaceImpl *BackImpl = (IWineD3DSurfaceImpl *) Back;
6901 IWineD3DSwapChainImpl *Swapchain;
6904 TRACE("(%p)->(%p,%p)\n", This, FrontImpl, BackImpl);
6906 hr = IWineD3DDevice_GetSwapChain(iface, 0, (IWineD3DSwapChain **) &Swapchain);
6907 if(hr != WINED3D_OK) {
6908 ERR("Can't get the swapchain\n");
6912 /* Make sure to release the swapchain */
6913 IWineD3DSwapChain_Release((IWineD3DSwapChain *) Swapchain);
6915 if(FrontImpl && !(FrontImpl->resource.usage & WINED3DUSAGE_RENDERTARGET) ) {
6916 ERR("Trying to set a front buffer which doesn't have WINED3DUSAGE_RENDERTARGET usage\n");
6917 return WINED3DERR_INVALIDCALL;
6919 else if(BackImpl && !(BackImpl->resource.usage & WINED3DUSAGE_RENDERTARGET)) {
6920 ERR("Trying to set a back buffer which doesn't have WINED3DUSAGE_RENDERTARGET usage\n");
6921 return WINED3DERR_INVALIDCALL;
6924 if(Swapchain->frontBuffer != Front) {
6925 TRACE("Changing the front buffer from %p to %p\n", Swapchain->frontBuffer, Front);
6927 if(Swapchain->frontBuffer)
6928 IWineD3DSurface_SetContainer(Swapchain->frontBuffer, NULL);
6929 Swapchain->frontBuffer = Front;
6931 if(Swapchain->frontBuffer) {
6932 IWineD3DSurface_SetContainer(Swapchain->frontBuffer, (IWineD3DBase *) Swapchain);
6936 if(Back && !Swapchain->backBuffer) {
6937 /* We need memory for the back buffer array - only one back buffer this way */
6938 Swapchain->backBuffer = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(IWineD3DSurface *));
6939 if(!Swapchain->backBuffer) {
6940 ERR("Out of memory\n");
6941 return E_OUTOFMEMORY;
6945 if(Swapchain->backBuffer[0] != Back) {
6946 TRACE("Changing the back buffer from %p to %p\n", Swapchain->backBuffer, Back);
6948 if(!Swapchain->backBuffer[0]) {
6949 /* GL was told to draw to the front buffer at creation,
6952 glDrawBuffer(GL_BACK);
6953 checkGLcall("glDrawBuffer(GL_BACK)");
6954 /* Set the backbuffer count to 1 because other code uses it to fing the back buffers */
6955 Swapchain->presentParms.BackBufferCount = 1;
6957 /* That makes problems - disable for now */
6958 /* glDrawBuffer(GL_FRONT); */
6959 checkGLcall("glDrawBuffer(GL_FRONT)");
6960 /* We have lost our back buffer, set this to 0 to avoid confusing other code */
6961 Swapchain->presentParms.BackBufferCount = 0;
6965 if(Swapchain->backBuffer[0])
6966 IWineD3DSurface_SetContainer(Swapchain->backBuffer[0], NULL);
6967 Swapchain->backBuffer[0] = Back;
6969 if(Swapchain->backBuffer[0]) {
6970 IWineD3DSurface_SetContainer(Swapchain->backBuffer[0], (IWineD3DBase *) Swapchain);
6972 HeapFree(GetProcessHeap(), 0, Swapchain->backBuffer);
6980 static HRESULT WINAPI IWineD3DDeviceImpl_GetDepthStencilSurface(IWineD3DDevice* iface, IWineD3DSurface **ppZStencilSurface) {
6981 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
6982 *ppZStencilSurface = This->depthStencilBuffer;
6983 TRACE("(%p) : zStencilSurface returning %p\n", This, *ppZStencilSurface);
6985 if(*ppZStencilSurface != NULL) {
6986 /* Note inc ref on returned surface */
6987 IWineD3DSurface_AddRef(*ppZStencilSurface);
6992 /* internal static helper functions */
6993 static HRESULT WINAPI IWineD3DDeviceImpl_ActiveRender(IWineD3DDevice* iface,
6994 IWineD3DSurface *RenderSurface);
6996 static HRESULT WINAPI IWineD3DDeviceImpl_SetRenderTarget(IWineD3DDevice *iface, DWORD RenderTargetIndex, IWineD3DSurface *pRenderTarget) {
6997 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
6998 HRESULT hr = WINED3D_OK;
6999 WINED3DVIEWPORT viewport;
7001 TRACE("(%p) Swapping rendertarget\n",This);
7002 if (RenderTargetIndex > 0) {
7003 FIXME("(%p) Render targets other than the first are not supported\n",This);
7004 RenderTargetIndex = 0;
7007 /* MSDN says that null disables the render target
7008 but a device must always be associated with a render target
7009 nope MSDN says that we return invalid call to a null rendertarget with an index of 0
7011 see http://msdn.microsoft.com/library/default.asp?url=/library/en-us/directx9_c/directx/graphics/programmingguide/AdvancedTopics/PixelPipe/MultipleRenderTarget.asp
7014 if (RenderTargetIndex == 0 && pRenderTarget == NULL) {
7015 FIXME("Trying to set render target 0 to NULL\n");
7016 return WINED3DERR_INVALIDCALL;
7018 /* TODO: replace Impl* usage with interface usage */
7019 if (!((IWineD3DSurfaceImpl *)pRenderTarget)->resource.usage & WINED3DUSAGE_RENDERTARGET) {
7020 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);
7021 return WINED3DERR_INVALIDCALL;
7023 /** TODO: check that the depth stencil format matches the render target, this is only done in debug
7024 * builds, but I think wine counts as a 'debug' build for now.
7025 ******************************/
7026 /* If we are trying to set what we already have, don't bother */
7027 if (pRenderTarget == This->renderTarget) {
7028 TRACE("Trying to do a NOP SetRenderTarget operation\n");
7030 /* Otherwise, set the render target up */
7032 if (!This->sceneEnded) {
7033 IWineD3DDevice_EndScene(iface);
7035 TRACE("clearing renderer\n");
7036 /* IWineD3DDeviceImpl_CleanRender(iface); */
7037 /* OpenGL doesn't support 'sharing' of the stencilBuffer so we may incure an extra memory overhead
7038 depending on the renter target implementation being used.
7039 A shared context implementation will share all buffers between all rendertargets (including swapchains),
7040 implementations that use separate pbuffers for different swapchains or rendertargets will have to duplicate the
7041 stencil buffer and incure an extra memory overhead */
7042 hr = IWineD3DDeviceImpl_ActiveRender(iface, pRenderTarget);
7045 if (SUCCEEDED(hr)) {
7046 /* Finally, reset the viewport as the MSDN states. */
7047 /* TODO: Replace impl usage */
7048 viewport.Height = ((IWineD3DSurfaceImpl *)This->renderTarget)->currentDesc.Height;
7049 viewport.Width = ((IWineD3DSurfaceImpl *)This->renderTarget)->currentDesc.Width;
7052 viewport.MaxZ = 1.0f;
7053 viewport.MinZ = 0.0f;
7054 IWineD3DDeviceImpl_SetViewport(iface, &viewport);
7056 FIXME("Unknown error setting the render target\n");
7058 This->sceneEnded = FALSE;
7062 static HRESULT WINAPI IWineD3DDeviceImpl_SetDepthStencilSurface(IWineD3DDevice *iface, IWineD3DSurface *pNewZStencil) {
7063 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
7064 HRESULT hr = WINED3D_OK;
7065 IWineD3DSurface *tmp;
7067 TRACE("(%p) Swapping z-buffer\n",This);
7069 if (pNewZStencil == This->stencilBufferTarget) {
7070 TRACE("Trying to do a NOP SetRenderTarget operation\n");
7072 /** OpenGL doesn't support 'sharing' of the stencilBuffer so we may incure an extra memory overhead
7073 * depending on the renter target implementation being used.
7074 * A shared context implementation will share all buffers between all rendertargets (including swapchains),
7075 * implementations that use separate pbuffers for different swapchains or rendertargets will have to duplicate the
7076 * stencil buffer and incure an extra memory overhead
7077 ******************************************************/
7080 tmp = This->stencilBufferTarget;
7081 This->stencilBufferTarget = pNewZStencil;
7082 /* should we be calling the parent or the wined3d surface? */
7083 if (NULL != This->stencilBufferTarget) IWineD3DSurface_AddRef(This->stencilBufferTarget);
7084 if (NULL != tmp) IWineD3DSurface_Release(tmp);
7086 /** TODO: glEnable/glDisable on depth/stencil depending on
7087 * pNewZStencil is NULL and the depth/stencil is enabled in d3d
7088 **********************************************************/
7095 #ifdef GL_VERSION_1_3
7096 /* Internal functions not in DirectX */
7097 /** TODO: move this off to the opengl context manager
7098 *(the swapchain doesn't need to know anything about offscreen rendering!)
7099 ****************************************************/
7101 static HRESULT WINAPI IWineD3DDeviceImpl_CleanRender(IWineD3DDevice* iface, IWineD3DSwapChainImpl *swapchain)
7103 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
7105 TRACE("(%p), %p\n", This, swapchain);
7107 if (swapchain->win != swapchain->drawable) {
7108 /* Set everything back the way it ws */
7109 swapchain->render_ctx = swapchain->glCtx;
7110 swapchain->drawable = swapchain->win;
7115 /* TODO: move this off into a context manager so that GLX_ATI_render_texture and other types of surface can be used. */
7116 static HRESULT WINAPI IWineD3DDeviceImpl_FindGLContext(IWineD3DDevice *iface, IWineD3DSurface *pSurface, glContext **context) {
7117 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
7120 unsigned int height;
7121 WINED3DFORMAT format;
7122 WINED3DSURFACE_DESC surfaceDesc;
7123 memset(&surfaceDesc, 0, sizeof(surfaceDesc));
7124 surfaceDesc.Width = &width;
7125 surfaceDesc.Height = &height;
7126 surfaceDesc.Format = &format;
7127 IWineD3DSurface_GetDesc(pSurface, &surfaceDesc);
7129 /* I need a get width/height function (and should do something with the format) */
7130 for (i = 0; i < CONTEXT_CACHE; ++i) {
7131 /** NOTE: the contextCache[i].pSurface == pSurface check ceates onepbuffer per surface
7132 ATI cards don't destroy pbuffers, but as soon as resource releasing callbacks are inplace
7133 the pSurface can be set to 0 allowing it to be reused from cache **/
7134 if (This->contextCache[i].Width == width && This->contextCache[i].Height == height
7135 && (!pbuffer_per_surface || This->contextCache[i].pSurface == pSurface || This->contextCache[i].pSurface == NULL)) {
7136 *context = &This->contextCache[i];
7139 if (This->contextCache[i].Width == 0) {
7140 This->contextCache[i].pSurface = pSurface;
7141 This->contextCache[i].Width = width;
7142 This->contextCache[i].Height = height;
7143 *context = &This->contextCache[i];
7147 if (i == CONTEXT_CACHE) {
7148 int minUsage = 0x7FFFFFFF; /* MAX_INT */
7149 glContext *dropContext = 0;
7150 for (i = 0; i < CONTEXT_CACHE; i++) {
7151 if (This->contextCache[i].usedcount < minUsage) {
7152 dropContext = &This->contextCache[i];
7153 minUsage = This->contextCache[i].usedcount;
7156 /* clean up the context (this doesn't work for ATI at the moment */
7158 glXDestroyContext(swapchain->display, dropContext->context);
7159 glXDestroyPbuffer(swapchain->display, dropContext->drawable);
7162 dropContext->Width = 0;
7163 dropContext->pSurface = pSurface;
7164 *context = dropContext;
7166 if (++This->contextCache[i].usedcount == 0x7FFFFFFF /* MAX_INT */ - 1 ) {
7167 for (i = 0; i < CONTEXT_CACHE; i++) {
7168 This->contextCache[i].usedcount = max(0, This->contextCache[i].usedcount - (0x7FFFFFFF /* MAX_INT */ >> 1));
7172 if (*context != NULL)
7175 return E_OUTOFMEMORY;
7179 /* Reapply the device stateblock */
7180 static void device_reapply_stateblock(IWineD3DDeviceImpl* This) {
7183 IWineD3DStateBlockImpl *oldUpdateStateBlock;
7185 /* Disable recording */
7186 oldUpdateStateBlock = This->updateStateBlock;
7187 oldRecording= This->isRecordingState;
7188 This->isRecordingState = FALSE;
7189 This->updateStateBlock = This->stateBlock;
7191 /* Reapply the state block */
7192 IWineD3DStateBlock_Apply((IWineD3DStateBlock *)This->stateBlock);
7194 /* Restore recording */
7195 This->isRecordingState = oldRecording;
7196 This->updateStateBlock = oldUpdateStateBlock;
7199 /* Set offscreen rendering. When rendering offscreen the surface will be
7200 * rendered upside down to compensate for the fact that D3D texture coordinates
7201 * are flipped compared to GL texture coordinates. The cullmode is affected by
7202 * this, so it must be updated. To update the cullmode stateblock recording has
7203 * to be temporarily disabled. The new state management code will hopefully
7204 * make this unnecessary */
7205 static void device_render_to_texture(IWineD3DDeviceImpl* This, BOOL isTexture) {
7209 IWineD3DStateBlockImpl *oldUpdateStateBlock;
7211 /* Disable recording */
7212 oldUpdateStateBlock = This->updateStateBlock;
7213 oldRecording= This->isRecordingState;
7214 This->isRecordingState = FALSE;
7215 This->updateStateBlock = This->stateBlock;
7217 This->render_offscreen = isTexture;
7218 This->last_was_rhw = FALSE;
7219 This->proj_valid = FALSE;
7220 IWineD3DDevice_GetRenderState((IWineD3DDevice*) This, WINED3DRS_CULLMODE, &cullMode);
7221 IWineD3DDevice_SetRenderState((IWineD3DDevice*) This, WINED3DRS_CULLMODE, cullMode);
7223 /* Restore recording */
7224 This->isRecordingState = oldRecording;
7225 This->updateStateBlock = oldUpdateStateBlock;
7228 /* Returns an array of compatible FBconfig(s).
7229 * The array must be freed with XFree. Requires ENTER_GL() */
7231 static GLXFBConfig* device_find_fbconfigs(
7232 IWineD3DDeviceImpl* This,
7233 IWineD3DSwapChainImpl* implicitSwapchainImpl,
7234 IWineD3DSurface* RenderSurface) {
7236 GLXFBConfig* cfgs = NULL;
7241 IWineD3DSurface *StencilSurface = This->stencilBufferTarget;
7242 WINED3DFORMAT BackBufferFormat = ((IWineD3DSurfaceImpl *) RenderSurface)->resource.format;
7243 WINED3DFORMAT StencilBufferFormat = (NULL != StencilSurface) ? ((IWineD3DSurfaceImpl *) StencilSurface)->resource.format : 0;
7246 if StencilSurface == NULL && zBufferTarget != NULL then switch the zbuffer off,
7247 it StencilSurface != NULL && zBufferTarget == NULL switch it on
7250 #define PUSH1(att) attribs[nAttribs++] = (att);
7251 #define PUSH2(att,value) attribs[nAttribs++] = (att); attribs[nAttribs++] = (value);
7253 /* PUSH2(GLX_BIND_TO_TEXTURE_RGBA_ATI, True); examples of this are few and far between (but I've got a nice working one!)*/
7255 PUSH2(GLX_DRAWABLE_TYPE, GLX_PBUFFER_BIT);
7256 PUSH2(GLX_X_RENDERABLE, TRUE);
7257 PUSH2(GLX_DOUBLEBUFFER, TRUE);
7258 TRACE("calling makeglcfg\n");
7259 D3DFmtMakeGlCfg(BackBufferFormat, StencilBufferFormat, attribs, &nAttribs, FALSE /* alternate */);
7261 TRACE("calling chooseFGConfig\n");
7262 cfgs = glXChooseFBConfig(implicitSwapchainImpl->display,
7263 DefaultScreen(implicitSwapchainImpl->display),
7266 /* OK we didn't find the exact config, so use any reasonable match */
7267 /* TODO: fill in the 'requested' and 'current' depths, and make sure that's
7269 static BOOL show_message = TRUE;
7271 ERR("Failed to find exact match, finding alternative but you may "
7272 "suffer performance issues, try changing xfree's depth to match the requested depth\n");
7273 show_message = FALSE;
7276 PUSH2(GLX_DRAWABLE_TYPE, GLX_PBUFFER_BIT | GLX_WINDOW_BIT);
7277 /* PUSH2(GLX_X_RENDERABLE, TRUE); */
7278 PUSH2(GLX_RENDER_TYPE, GLX_RGBA_BIT);
7279 PUSH2(GLX_DOUBLEBUFFER, FALSE);
7280 TRACE("calling makeglcfg\n");
7281 D3DFmtMakeGlCfg(BackBufferFormat, StencilBufferFormat, attribs, &nAttribs, TRUE /* alternate */);
7283 cfgs = glXChooseFBConfig(implicitSwapchainImpl->display,
7284 DefaultScreen(implicitSwapchainImpl->display),
7289 ERR("Could not get a valid FBConfig for (%u,%s)/(%u,%s)\n",
7290 BackBufferFormat, debug_d3dformat(BackBufferFormat),
7291 StencilBufferFormat, debug_d3dformat(StencilBufferFormat));
7295 for (i = 0; i < nCfgs; ++i) {
7296 TRACE("for (%u,%s)/(%u,%s) found config[%d]@%p\n", BackBufferFormat,
7297 debug_d3dformat(BackBufferFormat), StencilBufferFormat,
7298 debug_d3dformat(StencilBufferFormat), i, cfgs[i]);
7300 if (NULL != This->renderTarget) {
7302 vcheckGLcall("glFlush");
7303 /** This is only useful if the old render target was a swapchain,
7304 * we need to supercede this with a function that displays
7305 * the current buffer on the screen. This is easy to do in glx1.3 but
7306 * we need to do copy-write pixels in glx 1.2.
7307 ************************************************/
7308 glXSwapBuffers(implicitSwapChainImpl->display,
7309 implicitSwapChainImpl->drawable);
7310 printf("Hit Enter to get next frame ...\n");
7321 /** FIXME: This is currently used called whenever SetRenderTarget or SetStencilBuffer are called
7322 * the functionality needs splitting up so that we don't do more than we should do.
7323 * this only seems to impact performance a little.
7324 ******************************/
7325 static HRESULT WINAPI IWineD3DDeviceImpl_ActiveRender(IWineD3DDevice* iface,
7326 IWineD3DSurface *RenderSurface) {
7329 * Currently only active for GLX >= 1.3
7330 * for others versions we'll have to use GLXPixmaps
7332 * normally we must test GLX_VERSION_1_3 but nvidia headers are not correct
7333 * as they implement GLX 1.3 but only define GLX_VERSION_1_2
7334 * so only check OpenGL version
7335 * ..........................
7336 * I don't believe that it is a problem with NVidia headers,
7337 * XFree only supports GLX1.2, nVidia (and ATI to some extent) provide 1.3 functions
7338 * in GLX 1.2, there is no mention of the correct way to tell if the extensions are provided.
7340 * Your application will report GLX version 1.2 on glXQueryVersion.
7341 * However, it is safe to call the GLX 1.3 functions as described below.
7343 #if defined(GL_VERSION_1_3)
7345 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
7346 GLXFBConfig* cfgs = NULL;
7347 IWineD3DSwapChain *currentSwapchain;
7348 IWineD3DSwapChainImpl *currentSwapchainImpl;
7349 IWineD3DSwapChain *implicitSwapchain;
7350 IWineD3DSwapChainImpl *implicitSwapchainImpl;
7351 IWineD3DSwapChain *renderSurfaceSwapchain;
7352 IWineD3DSwapChainImpl *renderSurfaceSwapchainImpl;
7354 /* Obtain a reference to the device implicit swapchain,
7355 * the swapchain of the current render target,
7356 * and the swapchain of the new render target.
7357 * Fallback to device implicit swapchain if the current render target doesn't have one */
7358 IWineD3DDevice_GetSwapChain(iface, 0, &implicitSwapchain);
7359 IWineD3DSurface_GetContainer(RenderSurface, &IID_IWineD3DSwapChain, (void**) &renderSurfaceSwapchain);
7360 IWineD3DSurface_GetContainer(This->renderTarget, &IID_IWineD3DSwapChain, (void **)¤tSwapchain);
7361 if (currentSwapchain == NULL)
7362 IWineD3DDevice_GetSwapChain(iface, 0, ¤tSwapchain);
7364 currentSwapchainImpl = (IWineD3DSwapChainImpl*) currentSwapchain;
7365 implicitSwapchainImpl = (IWineD3DSwapChainImpl*) implicitSwapchain;
7366 renderSurfaceSwapchainImpl = (IWineD3DSwapChainImpl*) renderSurfaceSwapchain;
7371 * TODO: remove the use of IWineD3DSwapChainImpl, a context manager will help since it will replace the
7372 * renderTarget = swapchain->backBuffer[i] bit and anything to do with *glContexts
7373 **********************************************************************/
7374 if (renderSurfaceSwapchain != NULL) {
7376 /* We also need to make sure that the lights &co are also in the context of the swapchains */
7377 /* FIXME: If the render target gets sent to the frontBuffer, should we be presenting it raw? */
7378 TRACE("making swapchain active\n");
7379 if (RenderSurface != This->renderTarget) {
7380 BOOL backbuf = FALSE;
7383 for(i = 0; i < renderSurfaceSwapchainImpl->presentParms.BackBufferCount; i++) {
7384 if(RenderSurface == renderSurfaceSwapchainImpl->backBuffer[i]) {
7392 /* This could be flagged so that some operations work directly with the front buffer */
7393 FIXME("Attempting to set the renderTarget to the frontBuffer\n");
7395 if (glXMakeCurrent(renderSurfaceSwapchainImpl->display,
7396 renderSurfaceSwapchainImpl->win,
7397 renderSurfaceSwapchainImpl->glCtx) == False) {
7399 TRACE("Error in setting current context: context %p drawable %ld !\n",
7400 implicitSwapchainImpl->glCtx, implicitSwapchainImpl->win);
7402 checkGLcall("glXMakeContextCurrent");
7404 /* Clean up the old context */
7405 IWineD3DDeviceImpl_CleanRender(iface, currentSwapchainImpl);
7407 /* Reapply the stateblock, and set the device not to render to texture */
7408 device_reapply_stateblock(This);
7409 device_render_to_texture(This, FALSE);
7412 /* Offscreen rendering: PBuffers (currently disabled).
7413 * Also note that this path is never reached if FBOs are supported */
7414 } else if (wined3d_settings.offscreen_rendering_mode == ORM_PBUFFER &&
7415 (cfgs = device_find_fbconfigs(This, implicitSwapchainImpl, RenderSurface)) != NULL) {
7417 /** ********************************************************************
7418 * This is a quickly hacked out implementation of offscreen textures.
7419 * It will work in most cases but there may be problems if the client
7420 * modifies the texture directly, or expects the contents of the rendertarget
7423 * There are some real speed vs compatibility issues here:
7424 * we should really use a new context for every texture, but that eats ram.
7425 * we should also be restoring the texture to the pbuffer but that eats CPU
7426 * we can also 'reuse' the current pbuffer if the size is larger than the requested buffer,
7427 * but if this means reusing the display backbuffer then we need to make sure that
7428 * states are correctly preserved.
7429 * In many cases I would expect that we can 'skip' some functions, such as preserving states,
7430 * and gain a good performance increase at the cost of compatibility.
7431 * I would suggest that, when this is the case, a user configurable flag be made
7432 * available, allowing the user to choose the best emulated experience for them.
7433 *********************************************************************/
7435 XVisualInfo *visinfo;
7436 glContext *newContext;
7438 /* Here were using a shared context model */
7439 if (WINED3D_OK != IWineD3DDeviceImpl_FindGLContext(iface, RenderSurface, &newContext)) {
7440 FIXME("(%p) : Failed to find a context for surface %p\n", iface, RenderSurface);
7443 /* If the context doesn't exist then create a new one */
7444 /* TODO: This should really be part of findGlContext */
7445 if (NULL == newContext->context) {
7450 TRACE("making new buffer\n");
7451 attribs[nAttribs++] = GLX_PBUFFER_WIDTH;
7452 attribs[nAttribs++] = newContext->Width;
7453 attribs[nAttribs++] = GLX_PBUFFER_HEIGHT;
7454 attribs[nAttribs++] = newContext->Height;
7455 attribs[nAttribs++] = None;
7457 newContext->drawable = glXCreatePbuffer(implicitSwapchainImpl->display, cfgs[0], attribs);
7459 /** ****************************************
7460 *GLX1.3 isn't supported by XFree 'yet' until that point ATI emulates pBuffers
7462 * In future releases, we may provide the calls glXCreateNewContext,
7463 * glXQueryDrawable and glXMakeContextCurrent.
7464 * so until then we have to use glXGetVisualFromFBConfig &co..
7465 ********************************************/
7467 visinfo = glXGetVisualFromFBConfig(implicitSwapchainImpl->display, cfgs[0]);
7469 ERR("Error: couldn't get an RGBA, double-buffered visual\n");
7471 newContext->context = glXCreateContext(
7472 implicitSwapchainImpl->display, visinfo,
7473 implicitSwapchainImpl->glCtx, GL_TRUE);
7478 if (NULL == newContext || NULL == newContext->context) {
7479 ERR("(%p) : Failed to find a context for surface %p\n", iface, RenderSurface);
7481 /* Debug logging, (this function leaks), change to a TRACE when the leak is plugged */
7482 if (glXMakeCurrent(implicitSwapchainImpl->display,
7483 newContext->drawable, newContext->context) == False) {
7485 TRACE("Error in setting current context: context %p drawable %ld\n",
7486 newContext->context, newContext->drawable);
7488 checkGLcall("glXMakeContextCurrent");
7490 /* Clean up the old context */
7491 IWineD3DDeviceImpl_CleanRender(iface, currentSwapchainImpl);
7493 /* Reapply stateblock, and set device to render to a texture */
7494 device_reapply_stateblock(This);
7495 device_render_to_texture(This, TRUE);
7497 /* Set the current context of the swapchain to the new context */
7498 implicitSwapchainImpl->drawable = newContext->drawable;
7499 implicitSwapchainImpl->render_ctx = newContext->context;
7502 /* Same context, but update render_offscreen and cull mode */
7503 device_render_to_texture(This, TRUE);
7506 /* Replace the render target */
7507 if (This->renderTarget != RenderSurface) {
7508 IWineD3DSurface_Release(This->renderTarget);
7509 This->renderTarget = RenderSurface;
7510 IWineD3DSurface_AddRef(RenderSurface);
7513 if (cfgs != NULL) XFree(cfgs);
7514 if (implicitSwapchain != NULL) IWineD3DSwapChain_Release(implicitSwapchain);
7515 if (currentSwapchain != NULL) IWineD3DSwapChain_Release(currentSwapchain);
7516 if (renderSurfaceSwapchain != NULL) IWineD3DSwapChain_Release(renderSurfaceSwapchain);
7522 static HRESULT WINAPI IWineD3DDeviceImpl_SetCursorProperties(IWineD3DDevice* iface, UINT XHotSpot,
7523 UINT YHotSpot, IWineD3DSurface *pCursorBitmap) {
7524 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *) iface;
7525 /* TODO: the use of Impl is deprecated. */
7526 IWineD3DSurfaceImpl * pSur = (IWineD3DSurfaceImpl *) pCursorBitmap;
7528 TRACE("(%p) : Spot Pos(%u,%u)\n", This, XHotSpot, YHotSpot);
7530 /* some basic validation checks */
7531 if(This->cursorTexture) {
7533 glDeleteTextures(1, &This->cursorTexture);
7535 This->cursorTexture = 0;
7539 /* MSDN: Cursor must be A8R8G8B8 */
7540 if (WINED3DFMT_A8R8G8B8 != pSur->resource.format) {
7541 ERR("(%p) : surface(%p) has an invalid format\n", This, pCursorBitmap);
7542 return WINED3DERR_INVALIDCALL;
7545 /* MSDN: Cursor must be smaller than the display mode */
7546 if(pSur->currentDesc.Width > This->ddraw_width ||
7547 pSur->currentDesc.Height > This->ddraw_height) {
7548 ERR("(%p) : Surface(%p) is %dx%d pixels, but screen res is %dx%d\n", This, pSur, pSur->currentDesc.Width, pSur->currentDesc.Height, This->ddraw_width, This->ddraw_height);
7549 return WINED3DERR_INVALIDCALL;
7552 /* TODO: MSDN: Cursor sizes must be a power of 2 */
7553 /* This is to tell our texture code to load a SCRATCH surface. This allows us to use out
7554 * Texture and Blitting code to draw the cursor
7556 pSur->Flags |= SFLAG_FORCELOAD;
7557 IWineD3DSurface_PreLoad(pCursorBitmap);
7558 pSur->Flags &= ~SFLAG_FORCELOAD;
7559 /* Do not store the surface's pointer because the application may release
7560 * it after setting the cursor image. Windows doesn't addref the set surface, so we can't
7561 * do this either without creating circular refcount dependencies. Copy out the gl texture instead.
7563 This->cursorTexture = pSur->glDescription.textureName;
7564 This->cursorWidth = pSur->currentDesc.Width;
7565 This->cursorHeight = pSur->currentDesc.Height;
7566 pSur->glDescription.textureName = 0; /* Prevent the texture from being changed or deleted */
7569 This->xHotSpot = XHotSpot;
7570 This->yHotSpot = YHotSpot;
7574 static void WINAPI IWineD3DDeviceImpl_SetCursorPosition(IWineD3DDevice* iface, int XScreenSpace, int YScreenSpace, DWORD Flags) {
7575 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *) iface;
7576 TRACE("(%p) : SetPos to (%u,%u)\n", This, XScreenSpace, YScreenSpace);
7578 This->xScreenSpace = XScreenSpace;
7579 This->yScreenSpace = YScreenSpace;
7585 static BOOL WINAPI IWineD3DDeviceImpl_ShowCursor(IWineD3DDevice* iface, BOOL bShow) {
7586 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *) iface;
7587 BOOL oldVisible = This->bCursorVisible;
7588 TRACE("(%p) : visible(%d)\n", This, bShow);
7590 if(This->cursorTexture)
7591 This->bCursorVisible = bShow;
7596 static HRESULT WINAPI IWineD3DDeviceImpl_TestCooperativeLevel(IWineD3DDevice* iface) {
7597 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *) iface;
7598 TRACE("(%p) : state (%u)\n", This, This->state);
7599 /* TODO: Implement wrapping of the WndProc so that mimimize and maxamise can be monitored and the states adjusted. */
7600 switch (This->state) {
7603 case WINED3DERR_DEVICELOST:
7605 ResourceList *resourceList = This->resources;
7606 while (NULL != resourceList) {
7607 if (((IWineD3DResourceImpl *)resourceList->resource)->resource.pool == WINED3DPOOL_DEFAULT /* TODO: IWineD3DResource_GetPool(resourceList->resource)*/)
7608 return WINED3DERR_DEVICENOTRESET;
7609 resourceList = resourceList->next;
7611 return WINED3DERR_DEVICELOST;
7613 case WINED3DERR_DRIVERINTERNALERROR:
7614 return WINED3DERR_DRIVERINTERNALERROR;
7618 return WINED3DERR_DRIVERINTERNALERROR;
7622 static HRESULT WINAPI IWineD3DDeviceImpl_EvictManagedResources(IWineD3DDevice* iface) {
7623 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *) iface;
7624 /** FIXME: Resource tracking needs to be done,
7625 * The closes we can do to this is set the priorities of all managed textures low
7626 * and then reset them.
7627 ***********************************************************/
7628 FIXME("(%p) : stub\n", This);
7632 static HRESULT WINAPI IWineD3DDeviceImpl_Reset(IWineD3DDevice* iface, WINED3DPRESENT_PARAMETERS* pPresentationParameters) {
7633 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *) iface;
7634 /** FIXME: Resource trascking needs to be done.
7635 * in effect this pulls all non only default
7636 * textures out of video memory and deletes all glTextures (glDeleteTextures)
7637 * and should clear down the context and set it up according to pPresentationParameters
7638 ***********************************************************/
7639 FIXME("(%p) : stub\n", This);
7643 static HRESULT WINAPI IWineD3DDeviceImpl_SetDialogBoxMode(IWineD3DDevice *iface, BOOL bEnableDialogs) {
7644 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
7645 /** FIXME: always true at the moment **/
7646 if(!bEnableDialogs) {
7647 FIXME("(%p) Dialogs cannot be disabled yet\n", This);
7653 static HRESULT WINAPI IWineD3DDeviceImpl_GetCreationParameters(IWineD3DDevice *iface, WINED3DDEVICE_CREATION_PARAMETERS *pParameters) {
7654 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *) iface;
7655 TRACE("(%p) : pParameters %p\n", This, pParameters);
7657 *pParameters = This->createParms;
7661 static void WINAPI IWineD3DDeviceImpl_SetGammaRamp(IWineD3DDevice * iface, UINT iSwapChain, DWORD Flags, CONST WINED3DGAMMARAMP* pRamp) {
7662 IWineD3DSwapChain *swapchain;
7663 HRESULT hrc = WINED3D_OK;
7665 TRACE("Relaying to swapchain\n");
7667 if ((hrc = IWineD3DDeviceImpl_GetSwapChain(iface, iSwapChain, &swapchain)) == WINED3D_OK) {
7668 IWineD3DSwapChain_SetGammaRamp(swapchain, Flags, (WINED3DGAMMARAMP *)pRamp);
7669 IWineD3DSwapChain_Release(swapchain);
7674 static void WINAPI IWineD3DDeviceImpl_GetGammaRamp(IWineD3DDevice *iface, UINT iSwapChain, WINED3DGAMMARAMP* pRamp) {
7675 IWineD3DSwapChain *swapchain;
7676 HRESULT hrc = WINED3D_OK;
7678 TRACE("Relaying to swapchain\n");
7680 if ((hrc = IWineD3DDeviceImpl_GetSwapChain(iface, iSwapChain, &swapchain)) == WINED3D_OK) {
7681 hrc =IWineD3DSwapChain_GetGammaRamp(swapchain, pRamp);
7682 IWineD3DSwapChain_Release(swapchain);
7688 /** ********************************************************
7689 * Notification functions
7690 ** ********************************************************/
7691 /** This function must be called in the release of a resource when ref == 0,
7692 * the contents of resource must still be correct,
7693 * any handels to other resource held by the caller must be closed
7694 * (e.g. a texture should release all held surfaces because telling the device that it's been released.)
7695 *****************************************************/
7696 static void WINAPI IWineD3DDeviceImpl_AddResource(IWineD3DDevice *iface, IWineD3DResource *resource){
7697 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
7698 ResourceList* resourceList;
7700 TRACE("(%p) : resource %p\n", This, resource);
7702 EnterCriticalSection(&resourceStoreCriticalSection);
7704 /* add a new texture to the frot of the linked list */
7705 resourceList = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(ResourceList));
7706 resourceList->resource = resource;
7708 /* Get the old head */
7709 resourceList->next = This->resources;
7711 This->resources = resourceList;
7712 TRACE("Added resource %p with element %p pointing to %p\n", resource, resourceList, resourceList->next);
7715 LeaveCriticalSection(&resourceStoreCriticalSection);
7720 static void WINAPI IWineD3DDeviceImpl_RemoveResource(IWineD3DDevice *iface, IWineD3DResource *resource){
7721 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
7722 ResourceList* resourceList = NULL;
7723 ResourceList* previousResourceList = NULL;
7725 TRACE("(%p) : resource %p\n", This, resource);
7728 EnterCriticalSection(&resourceStoreCriticalSection);
7730 resourceList = This->resources;
7732 while (resourceList != NULL) {
7733 if(resourceList->resource == resource) break;
7734 previousResourceList = resourceList;
7735 resourceList = resourceList->next;
7738 if (resourceList == NULL) {
7739 FIXME("Attempted to remove resource %p that hasn't been stored\n", resource);
7741 LeaveCriticalSection(&resourceStoreCriticalSection);
7745 TRACE("Found resource %p with element %p pointing to %p (previous %p)\n", resourceList->resource, resourceList, resourceList->next, previousResourceList);
7747 /* make sure we don't leave a hole in the list */
7748 if (previousResourceList != NULL) {
7749 previousResourceList->next = resourceList->next;
7751 This->resources = resourceList->next;
7755 LeaveCriticalSection(&resourceStoreCriticalSection);
7761 static void WINAPI IWineD3DDeviceImpl_ResourceReleased(IWineD3DDevice *iface, IWineD3DResource *resource){
7762 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *) iface;
7765 TRACE("(%p) : resource %p\n", This, resource);
7766 switch(IWineD3DResource_GetType(resource)){
7767 case WINED3DRTYPE_SURFACE:
7768 /* TODO: check front and back buffers, rendertargets etc.. possibly swapchains? */
7770 case WINED3DRTYPE_TEXTURE:
7771 case WINED3DRTYPE_CUBETEXTURE:
7772 case WINED3DRTYPE_VOLUMETEXTURE:
7773 for (counter = 0; counter < GL_LIMITS(sampler_stages); counter++) {
7774 if (This->stateBlock != NULL && This->stateBlock->textures[counter] == (IWineD3DBaseTexture *)resource) {
7775 WARN("Texture being released is still by a stateblock, Stage = %u Texture = %p\n", counter, resource);
7776 This->stateBlock->textures[counter] = NULL;
7778 if (This->updateStateBlock != This->stateBlock ){
7779 if (This->updateStateBlock->textures[counter] == (IWineD3DBaseTexture *)resource) {
7780 WARN("Texture being released is still by a stateblock, Stage = %u Texture = %p\n", counter, resource);
7781 This->updateStateBlock->textures[counter] = NULL;
7786 case WINED3DRTYPE_VOLUME:
7787 /* TODO: nothing really? */
7789 case WINED3DRTYPE_VERTEXBUFFER:
7790 /* MSDN: When an application no longer holds a references to this interface, the interface will automatically be freed. */
7793 TRACE("Cleaning up stream pointers\n");
7795 for(streamNumber = 0; streamNumber < MAX_STREAMS; streamNumber ++){
7796 /* FINDOUT: should a warn be generated if were recording and updateStateBlock->streamSource is lost?
7797 FINDOUT: should changes.streamSource[StreamNumber] be set ?
7799 if (This->updateStateBlock != NULL ) { /* ==NULL when device is being destroyed */
7800 if ((IWineD3DResource *)This->updateStateBlock->streamSource[streamNumber] == resource) {
7801 FIXME("Vertex buffer released while bound to a state block, stream %d\n", streamNumber);
7802 This->updateStateBlock->streamSource[streamNumber] = 0;
7803 /* Set changed flag? */
7806 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) */
7807 if ((IWineD3DResource *)This->stateBlock->streamSource[streamNumber] == resource) {
7808 TRACE("Vertex buffer released while bound to a state block, stream %d\n", streamNumber);
7809 This->stateBlock->streamSource[streamNumber] = 0;
7812 #if 0 /* TODO: Manage internal tracking properly so that 'this shouldn't happen' */
7813 else { /* This shouldn't happen */
7814 FIXME("Calling application has released the device before relasing all the resources bound to the device\n");
7821 case WINED3DRTYPE_INDEXBUFFER:
7822 /* MSDN: When an application no longer holds a references to this interface, the interface will automatically be freed.*/
7823 if (This->updateStateBlock != NULL ) { /* ==NULL when device is being destroyed */
7824 if (This->updateStateBlock->pIndexData == (IWineD3DIndexBuffer *)resource) {
7825 This->updateStateBlock->pIndexData = NULL;
7828 if (This->stateBlock != NULL ) { /* ==NULL when device is being destroyed */
7829 if (This->stateBlock->pIndexData == (IWineD3DIndexBuffer *)resource) {
7830 This->stateBlock->pIndexData = NULL;
7836 FIXME("(%p) unknown resource type %p %u\n", This, resource, IWineD3DResource_GetType(resource));
7841 /* Remove the resoruce from the resourceStore */
7842 IWineD3DDeviceImpl_RemoveResource(iface, resource);
7844 TRACE("Resource released\n");
7848 /**********************************************************
7849 * IWineD3DDevice VTbl follows
7850 **********************************************************/
7852 const IWineD3DDeviceVtbl IWineD3DDevice_Vtbl =
7854 /*** IUnknown methods ***/
7855 IWineD3DDeviceImpl_QueryInterface,
7856 IWineD3DDeviceImpl_AddRef,
7857 IWineD3DDeviceImpl_Release,
7858 /*** IWineD3DDevice methods ***/
7859 IWineD3DDeviceImpl_GetParent,
7860 /*** Creation methods**/
7861 IWineD3DDeviceImpl_CreateVertexBuffer,
7862 IWineD3DDeviceImpl_CreateIndexBuffer,
7863 IWineD3DDeviceImpl_CreateStateBlock,
7864 IWineD3DDeviceImpl_CreateSurface,
7865 IWineD3DDeviceImpl_CreateTexture,
7866 IWineD3DDeviceImpl_CreateVolumeTexture,
7867 IWineD3DDeviceImpl_CreateVolume,
7868 IWineD3DDeviceImpl_CreateCubeTexture,
7869 IWineD3DDeviceImpl_CreateQuery,
7870 IWineD3DDeviceImpl_CreateAdditionalSwapChain,
7871 IWineD3DDeviceImpl_CreateVertexDeclaration,
7872 IWineD3DDeviceImpl_CreateVertexShader,
7873 IWineD3DDeviceImpl_CreatePixelShader,
7874 IWineD3DDeviceImpl_CreatePalette,
7875 /*** Odd functions **/
7876 IWineD3DDeviceImpl_Init3D,
7877 IWineD3DDeviceImpl_Uninit3D,
7878 IWineD3DDeviceImpl_SetFullscreen,
7879 IWineD3DDeviceImpl_EnumDisplayModes,
7880 IWineD3DDeviceImpl_EvictManagedResources,
7881 IWineD3DDeviceImpl_GetAvailableTextureMem,
7882 IWineD3DDeviceImpl_GetBackBuffer,
7883 IWineD3DDeviceImpl_GetCreationParameters,
7884 IWineD3DDeviceImpl_GetDeviceCaps,
7885 IWineD3DDeviceImpl_GetDirect3D,
7886 IWineD3DDeviceImpl_GetDisplayMode,
7887 IWineD3DDeviceImpl_SetDisplayMode,
7888 IWineD3DDeviceImpl_GetHWND,
7889 IWineD3DDeviceImpl_SetHWND,
7890 IWineD3DDeviceImpl_GetNumberOfSwapChains,
7891 IWineD3DDeviceImpl_GetRasterStatus,
7892 IWineD3DDeviceImpl_GetSwapChain,
7893 IWineD3DDeviceImpl_Reset,
7894 IWineD3DDeviceImpl_SetDialogBoxMode,
7895 IWineD3DDeviceImpl_SetCursorProperties,
7896 IWineD3DDeviceImpl_SetCursorPosition,
7897 IWineD3DDeviceImpl_ShowCursor,
7898 IWineD3DDeviceImpl_TestCooperativeLevel,
7899 /*** Getters and setters **/
7900 IWineD3DDeviceImpl_SetClipPlane,
7901 IWineD3DDeviceImpl_GetClipPlane,
7902 IWineD3DDeviceImpl_SetClipStatus,
7903 IWineD3DDeviceImpl_GetClipStatus,
7904 IWineD3DDeviceImpl_SetCurrentTexturePalette,
7905 IWineD3DDeviceImpl_GetCurrentTexturePalette,
7906 IWineD3DDeviceImpl_SetDepthStencilSurface,
7907 IWineD3DDeviceImpl_GetDepthStencilSurface,
7908 IWineD3DDeviceImpl_SetFVF,
7909 IWineD3DDeviceImpl_GetFVF,
7910 IWineD3DDeviceImpl_SetGammaRamp,
7911 IWineD3DDeviceImpl_GetGammaRamp,
7912 IWineD3DDeviceImpl_SetIndices,
7913 IWineD3DDeviceImpl_GetIndices,
7914 IWineD3DDeviceImpl_SetLight,
7915 IWineD3DDeviceImpl_GetLight,
7916 IWineD3DDeviceImpl_SetLightEnable,
7917 IWineD3DDeviceImpl_GetLightEnable,
7918 IWineD3DDeviceImpl_SetMaterial,
7919 IWineD3DDeviceImpl_GetMaterial,
7920 IWineD3DDeviceImpl_SetNPatchMode,
7921 IWineD3DDeviceImpl_GetNPatchMode,
7922 IWineD3DDeviceImpl_SetPaletteEntries,
7923 IWineD3DDeviceImpl_GetPaletteEntries,
7924 IWineD3DDeviceImpl_SetPixelShader,
7925 IWineD3DDeviceImpl_GetPixelShader,
7926 IWineD3DDeviceImpl_SetPixelShaderConstantB,
7927 IWineD3DDeviceImpl_GetPixelShaderConstantB,
7928 IWineD3DDeviceImpl_SetPixelShaderConstantI,
7929 IWineD3DDeviceImpl_GetPixelShaderConstantI,
7930 IWineD3DDeviceImpl_SetPixelShaderConstantF,
7931 IWineD3DDeviceImpl_GetPixelShaderConstantF,
7932 IWineD3DDeviceImpl_SetRenderState,
7933 IWineD3DDeviceImpl_GetRenderState,
7934 IWineD3DDeviceImpl_SetRenderTarget,
7935 IWineD3DDeviceImpl_GetRenderTarget,
7936 IWineD3DDeviceImpl_SetFrontBackBuffers,
7937 IWineD3DDeviceImpl_SetSamplerState,
7938 IWineD3DDeviceImpl_GetSamplerState,
7939 IWineD3DDeviceImpl_SetScissorRect,
7940 IWineD3DDeviceImpl_GetScissorRect,
7941 IWineD3DDeviceImpl_SetSoftwareVertexProcessing,
7942 IWineD3DDeviceImpl_GetSoftwareVertexProcessing,
7943 IWineD3DDeviceImpl_SetStreamSource,
7944 IWineD3DDeviceImpl_GetStreamSource,
7945 IWineD3DDeviceImpl_SetStreamSourceFreq,
7946 IWineD3DDeviceImpl_GetStreamSourceFreq,
7947 IWineD3DDeviceImpl_SetTexture,
7948 IWineD3DDeviceImpl_GetTexture,
7949 IWineD3DDeviceImpl_SetTextureStageState,
7950 IWineD3DDeviceImpl_GetTextureStageState,
7951 IWineD3DDeviceImpl_SetTransform,
7952 IWineD3DDeviceImpl_GetTransform,
7953 IWineD3DDeviceImpl_SetVertexDeclaration,
7954 IWineD3DDeviceImpl_GetVertexDeclaration,
7955 IWineD3DDeviceImpl_SetVertexShader,
7956 IWineD3DDeviceImpl_GetVertexShader,
7957 IWineD3DDeviceImpl_SetVertexShaderConstantB,
7958 IWineD3DDeviceImpl_GetVertexShaderConstantB,
7959 IWineD3DDeviceImpl_SetVertexShaderConstantI,
7960 IWineD3DDeviceImpl_GetVertexShaderConstantI,
7961 IWineD3DDeviceImpl_SetVertexShaderConstantF,
7962 IWineD3DDeviceImpl_GetVertexShaderConstantF,
7963 IWineD3DDeviceImpl_SetViewport,
7964 IWineD3DDeviceImpl_GetViewport,
7965 IWineD3DDeviceImpl_MultiplyTransform,
7966 IWineD3DDeviceImpl_ValidateDevice,
7967 IWineD3DDeviceImpl_ProcessVertices,
7968 /*** State block ***/
7969 IWineD3DDeviceImpl_BeginStateBlock,
7970 IWineD3DDeviceImpl_EndStateBlock,
7971 /*** Scene management ***/
7972 IWineD3DDeviceImpl_BeginScene,
7973 IWineD3DDeviceImpl_EndScene,
7974 IWineD3DDeviceImpl_Present,
7975 IWineD3DDeviceImpl_Clear,
7977 IWineD3DDeviceImpl_DrawPrimitive,
7978 IWineD3DDeviceImpl_DrawIndexedPrimitive,
7979 IWineD3DDeviceImpl_DrawPrimitiveUP,
7980 IWineD3DDeviceImpl_DrawIndexedPrimitiveUP,
7981 IWineD3DDeviceImpl_DrawPrimitiveStrided,
7982 IWineD3DDeviceImpl_DrawRectPatch,
7983 IWineD3DDeviceImpl_DrawTriPatch,
7984 IWineD3DDeviceImpl_DeletePatch,
7985 IWineD3DDeviceImpl_ColorFill,
7986 IWineD3DDeviceImpl_UpdateTexture,
7987 IWineD3DDeviceImpl_UpdateSurface,
7988 IWineD3DDeviceImpl_StretchRect,
7989 IWineD3DDeviceImpl_GetRenderTargetData,
7990 IWineD3DDeviceImpl_GetFrontBufferData,
7991 /*** Internal use IWineD3DDevice methods ***/
7992 IWineD3DDeviceImpl_SetupTextureStates,
7993 /*** object tracking ***/
7994 IWineD3DDeviceImpl_ResourceReleased
7998 const DWORD SavedPixelStates_R[NUM_SAVEDPIXELSTATES_R] = {
7999 WINED3DRS_ALPHABLENDENABLE ,
8000 WINED3DRS_ALPHAFUNC ,
8001 WINED3DRS_ALPHAREF ,
8002 WINED3DRS_ALPHATESTENABLE ,
8004 WINED3DRS_COLORWRITEENABLE ,
8005 WINED3DRS_DESTBLEND ,
8006 WINED3DRS_DITHERENABLE ,
8007 WINED3DRS_FILLMODE ,
8008 WINED3DRS_FOGDENSITY ,
8010 WINED3DRS_FOGSTART ,
8011 WINED3DRS_LASTPIXEL ,
8012 WINED3DRS_SHADEMODE ,
8013 WINED3DRS_SRCBLEND ,
8014 WINED3DRS_STENCILENABLE ,
8015 WINED3DRS_STENCILFAIL ,
8016 WINED3DRS_STENCILFUNC ,
8017 WINED3DRS_STENCILMASK ,
8018 WINED3DRS_STENCILPASS ,
8019 WINED3DRS_STENCILREF ,
8020 WINED3DRS_STENCILWRITEMASK ,
8021 WINED3DRS_STENCILZFAIL ,
8022 WINED3DRS_TEXTUREFACTOR ,
8033 WINED3DRS_ZWRITEENABLE
8036 const DWORD SavedPixelStates_T[NUM_SAVEDPIXELSTATES_T] = {
8037 WINED3DTSS_ADDRESSW ,
8038 WINED3DTSS_ALPHAARG0 ,
8039 WINED3DTSS_ALPHAARG1 ,
8040 WINED3DTSS_ALPHAARG2 ,
8041 WINED3DTSS_ALPHAOP ,
8042 WINED3DTSS_BUMPENVLOFFSET ,
8043 WINED3DTSS_BUMPENVLSCALE ,
8044 WINED3DTSS_BUMPENVMAT00 ,
8045 WINED3DTSS_BUMPENVMAT01 ,
8046 WINED3DTSS_BUMPENVMAT10 ,
8047 WINED3DTSS_BUMPENVMAT11 ,
8048 WINED3DTSS_COLORARG0 ,
8049 WINED3DTSS_COLORARG1 ,
8050 WINED3DTSS_COLORARG2 ,
8051 WINED3DTSS_COLOROP ,
8052 WINED3DTSS_RESULTARG ,
8053 WINED3DTSS_TEXCOORDINDEX ,
8054 WINED3DTSS_TEXTURETRANSFORMFLAGS
8057 const DWORD SavedPixelStates_S[NUM_SAVEDPIXELSTATES_S] = {
8058 WINED3DSAMP_ADDRESSU ,
8059 WINED3DSAMP_ADDRESSV ,
8060 WINED3DSAMP_ADDRESSW ,
8061 WINED3DSAMP_BORDERCOLOR ,
8062 WINED3DSAMP_MAGFILTER ,
8063 WINED3DSAMP_MINFILTER ,
8064 WINED3DSAMP_MIPFILTER ,
8065 WINED3DSAMP_MIPMAPLODBIAS ,
8066 WINED3DSAMP_MAXMIPLEVEL ,
8067 WINED3DSAMP_MAXANISOTROPY ,
8068 WINED3DSAMP_SRGBTEXTURE ,
8069 WINED3DSAMP_ELEMENTINDEX
8072 const DWORD SavedVertexStates_R[NUM_SAVEDVERTEXSTATES_R] = {
8074 WINED3DRS_AMBIENTMATERIALSOURCE ,
8075 WINED3DRS_CLIPPING ,
8076 WINED3DRS_CLIPPLANEENABLE ,
8077 WINED3DRS_COLORVERTEX ,
8078 WINED3DRS_DIFFUSEMATERIALSOURCE ,
8079 WINED3DRS_EMISSIVEMATERIALSOURCE ,
8080 WINED3DRS_FOGDENSITY ,
8082 WINED3DRS_FOGSTART ,
8083 WINED3DRS_FOGTABLEMODE ,
8084 WINED3DRS_FOGVERTEXMODE ,
8085 WINED3DRS_INDEXEDVERTEXBLENDENABLE ,
8086 WINED3DRS_LIGHTING ,
8087 WINED3DRS_LOCALVIEWER ,
8088 WINED3DRS_MULTISAMPLEANTIALIAS ,
8089 WINED3DRS_MULTISAMPLEMASK ,
8090 WINED3DRS_NORMALIZENORMALS ,
8091 WINED3DRS_PATCHEDGESTYLE ,
8092 WINED3DRS_POINTSCALE_A ,
8093 WINED3DRS_POINTSCALE_B ,
8094 WINED3DRS_POINTSCALE_C ,
8095 WINED3DRS_POINTSCALEENABLE ,
8096 WINED3DRS_POINTSIZE ,
8097 WINED3DRS_POINTSIZE_MAX ,
8098 WINED3DRS_POINTSIZE_MIN ,
8099 WINED3DRS_POINTSPRITEENABLE ,
8100 WINED3DRS_RANGEFOGENABLE ,
8101 WINED3DRS_SPECULARMATERIALSOURCE ,
8102 WINED3DRS_TWEENFACTOR ,
8103 WINED3DRS_VERTEXBLEND
8106 const DWORD SavedVertexStates_T[NUM_SAVEDVERTEXSTATES_T] = {
8107 WINED3DTSS_TEXCOORDINDEX ,
8108 WINED3DTSS_TEXTURETRANSFORMFLAGS
8111 const DWORD SavedVertexStates_S[NUM_SAVEDVERTEXSTATES_S] = {
8112 WINED3DSAMP_DMAPOFFSET