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);
1615 XFree(object->visInfo);
1616 object->visInfo = NULL;
1620 if (!object->glCtx) {
1621 ERR("Failed to create GLX context\n");
1622 return WINED3DERR_NOTAVAILABLE;
1624 TRACE("Context created (HWND=%p, glContext=%p, Window=%ld, VisInfo=%p)\n",
1625 object->win_handle, object->glCtx, object->win, object->visInfo);
1628 /*********************
1629 * Windowed / Fullscreen
1630 *******************/
1633 * TODO: MSDN says that we are only allowed one fullscreen swapchain per device,
1634 * so we should really check to see if there is a fullscreen swapchain already
1635 * I think Windows and X have different ideas about fullscreen, does a single head count as full screen?
1636 **************************************/
1638 if (!*(pPresentationParameters->Windowed)) {
1644 /* Get info on the current display setup */
1645 hdc = CreateDCA("DISPLAY", NULL, NULL, NULL);
1646 bpp = GetDeviceCaps(hdc, BITSPIXEL);
1649 /* Change the display settings */
1650 memset(&devmode, 0, sizeof(DEVMODEW));
1651 devmode.dmFields = DM_BITSPERPEL | DM_PELSWIDTH | DM_PELSHEIGHT;
1652 devmode.dmBitsPerPel = (bpp >= 24) ? 32 : bpp; /* Stupid XVidMode cannot change bpp */
1653 devmode.dmPelsWidth = *(pPresentationParameters->BackBufferWidth);
1654 devmode.dmPelsHeight = *(pPresentationParameters->BackBufferHeight);
1655 MultiByteToWideChar(CP_ACP, 0, "Gamers CG", -1, devmode.dmDeviceName, CCHDEVICENAME);
1656 ChangeDisplaySettingsExW(devmode.dmDeviceName, &devmode, object->win_handle, CDS_FULLSCREEN, NULL);
1658 /* Make popup window */
1659 SetWindowLongA(object->win_handle, GWL_STYLE, WS_POPUP);
1660 SetWindowPos(object->win_handle, HWND_TOP, 0, 0,
1661 *(pPresentationParameters->BackBufferWidth),
1662 *(pPresentationParameters->BackBufferHeight), SWP_SHOWWINDOW | SWP_FRAMECHANGED);
1664 /* For GetDisplayMode */
1665 This->ddraw_width = devmode.dmPelsWidth;
1666 This->ddraw_height = devmode.dmPelsHeight;
1667 This->ddraw_format = *(pPresentationParameters->BackBufferFormat);
1671 /** MSDN: If Windowed is TRUE and either of the BackBufferWidth/Height values is zero,
1672 * then the corresponding dimension of the client area of the hDeviceWindow
1673 * (or the focus window, if hDeviceWindow is NULL) is taken.
1674 **********************/
1676 if (*(pPresentationParameters->Windowed) &&
1677 ((*(pPresentationParameters->BackBufferWidth) == 0) ||
1678 (*(pPresentationParameters->BackBufferHeight) == 0))) {
1681 GetClientRect(object->win_handle, &Rect);
1683 if (*(pPresentationParameters->BackBufferWidth) == 0) {
1684 *(pPresentationParameters->BackBufferWidth) = Rect.right;
1685 TRACE("Updating width to %d\n", *(pPresentationParameters->BackBufferWidth));
1687 if (*(pPresentationParameters->BackBufferHeight) == 0) {
1688 *(pPresentationParameters->BackBufferHeight) = Rect.bottom;
1689 TRACE("Updating height to %d\n", *(pPresentationParameters->BackBufferHeight));
1693 /*********************
1694 * finish off parameter initialization
1695 *******************/
1697 /* Put the correct figures in the presentation parameters */
1698 TRACE("Copying across presentation parameters\n");
1699 object->presentParms.BackBufferWidth = *(pPresentationParameters->BackBufferWidth);
1700 object->presentParms.BackBufferHeight = *(pPresentationParameters->BackBufferHeight);
1701 object->presentParms.BackBufferFormat = *(pPresentationParameters->BackBufferFormat);
1702 object->presentParms.BackBufferCount = *(pPresentationParameters->BackBufferCount);
1703 object->presentParms.MultiSampleType = *(pPresentationParameters->MultiSampleType);
1704 object->presentParms.MultiSampleQuality = NULL == pPresentationParameters->MultiSampleQuality ? 0 : *(pPresentationParameters->MultiSampleQuality);
1705 object->presentParms.SwapEffect = *(pPresentationParameters->SwapEffect);
1706 object->presentParms.hDeviceWindow = *(pPresentationParameters->hDeviceWindow);
1707 object->presentParms.Windowed = *(pPresentationParameters->Windowed);
1708 object->presentParms.EnableAutoDepthStencil = *(pPresentationParameters->EnableAutoDepthStencil);
1709 object->presentParms.AutoDepthStencilFormat = *(pPresentationParameters->AutoDepthStencilFormat);
1710 object->presentParms.Flags = *(pPresentationParameters->Flags);
1711 object->presentParms.FullScreen_RefreshRateInHz = *(pPresentationParameters->FullScreen_RefreshRateInHz);
1712 object->presentParms.PresentationInterval = *(pPresentationParameters->PresentationInterval);
1715 /*********************
1716 * Create the back, front and stencil buffers
1717 *******************/
1719 TRACE("calling rendertarget CB\n");
1720 hr = D3DCB_CreateRenderTarget((IUnknown *) This->parent,
1721 object->presentParms.BackBufferWidth,
1722 object->presentParms.BackBufferHeight,
1723 object->presentParms.BackBufferFormat,
1724 object->presentParms.MultiSampleType,
1725 object->presentParms.MultiSampleQuality,
1726 TRUE /* Lockable */,
1727 &object->frontBuffer,
1728 NULL /* pShared (always null)*/);
1729 if (object->frontBuffer != NULL)
1730 IWineD3DSurface_SetContainer(object->frontBuffer, (IWineD3DBase *)object);
1732 if(object->presentParms.BackBufferCount > 0) {
1735 object->backBuffer = HeapAlloc(GetProcessHeap(), 0, sizeof(IWineD3DSurface *) * object->presentParms.BackBufferCount);
1736 if(!object->backBuffer) {
1737 ERR("Out of memory\n");
1739 if (object->frontBuffer) {
1740 IUnknown *bufferParent;
1741 IWineD3DSurface_GetParent(object->frontBuffer, &bufferParent);
1742 IUnknown_Release(bufferParent); /* once for the get parent */
1743 if (IUnknown_Release(bufferParent) > 0) {
1744 FIXME("(%p) Something's still holding the front buffer\n",This);
1747 HeapFree(GetProcessHeap(), 0, object);
1748 return E_OUTOFMEMORY;
1751 for(i = 0; i < object->presentParms.BackBufferCount; i++) {
1752 TRACE("calling rendertarget CB\n");
1753 hr = D3DCB_CreateRenderTarget((IUnknown *) This->parent,
1754 object->presentParms.BackBufferWidth,
1755 object->presentParms.BackBufferHeight,
1756 object->presentParms.BackBufferFormat,
1757 object->presentParms.MultiSampleType,
1758 object->presentParms.MultiSampleQuality,
1759 TRUE /* Lockable */,
1760 &object->backBuffer[i],
1761 NULL /* pShared (always null)*/);
1762 if(hr == WINED3D_OK && object->backBuffer[i]) {
1763 IWineD3DSurface_SetContainer(object->backBuffer[i], (IWineD3DBase *)object);
1769 object->backBuffer = NULL;
1772 if (object->backBuffer != NULL) {
1774 glDrawBuffer(GL_BACK);
1775 checkGLcall("glDrawBuffer(GL_BACK)");
1778 /* Single buffering - draw to front buffer */
1780 glDrawBuffer(GL_FRONT);
1781 checkGLcall("glDrawBuffer(GL_FRONT)");
1785 /* Under directX swapchains share the depth stencil, so only create one depth-stencil */
1786 if (*(pPresentationParameters->EnableAutoDepthStencil) && hr == WINED3D_OK) {
1787 TRACE("Creating depth stencil buffer\n");
1788 if (This->depthStencilBuffer == NULL ) {
1789 hr = D3DCB_CreateDepthStencil((IUnknown *) This->parent,
1790 object->presentParms.BackBufferWidth,
1791 object->presentParms.BackBufferHeight,
1792 object->presentParms.AutoDepthStencilFormat,
1793 object->presentParms.MultiSampleType,
1794 object->presentParms.MultiSampleQuality,
1795 FALSE /* FIXME: Discard */,
1796 &This->depthStencilBuffer,
1797 NULL /* pShared (always null)*/ );
1798 if (This->depthStencilBuffer != NULL)
1799 IWineD3DSurface_SetContainer(This->depthStencilBuffer, 0);
1802 /** TODO: A check on width, height and multisample types
1803 *(since the zbuffer must be at least as large as the render target and have the same multisample parameters)
1804 ****************************/
1805 object->wantsDepthStencilBuffer = TRUE;
1807 object->wantsDepthStencilBuffer = FALSE;
1810 TRACE("FrontBuf @ %p, BackBuf @ %p, DepthStencil %d\n",object->frontBuffer, object->backBuffer ? object->backBuffer[0] : NULL, object->wantsDepthStencilBuffer);
1813 /*********************
1814 * init the default renderTarget management
1815 *******************/
1816 object->drawable = object->win;
1817 object->render_ctx = object->glCtx;
1819 if (hr == WINED3D_OK) {
1820 /*********************
1821 * Setup some defaults and clear down the buffers
1822 *******************/
1824 /** save current context and drawable **/
1825 oldContext = glXGetCurrentContext();
1826 oldDrawable = glXGetCurrentDrawable();
1828 TRACE("Activating context (display %p context %p drawable %ld)!\n", object->display, object->glCtx, object->win);
1829 if (glXMakeCurrent(object->display, object->win, object->glCtx) == False) {
1830 ERR("Error in setting current context (display %p context %p drawable %ld)!\n", object->display, object->glCtx, object->win);
1832 checkGLcall("glXMakeCurrent");
1834 TRACE("Setting up the screen\n");
1835 /* Clear the screen */
1836 glClearColor(1.0, 0.0, 0.0, 0.0);
1837 checkGLcall("glClearColor");
1840 glClearStencil(0xffff);
1842 checkGLcall("glClear");
1844 glColor3f(1.0, 1.0, 1.0);
1845 checkGLcall("glColor3f");
1847 glEnable(GL_LIGHTING);
1848 checkGLcall("glEnable");
1850 glLightModeli(GL_LIGHT_MODEL_LOCAL_VIEWER, GL_TRUE);
1851 checkGLcall("glLightModeli(GL_LIGHT_MODEL_LOCAL_VIEWER, GL_TRUE);");
1853 glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE_EXT);
1854 checkGLcall("glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE_EXT);");
1856 glLightModeli(GL_LIGHT_MODEL_COLOR_CONTROL, GL_SEPARATE_SPECULAR_COLOR);
1857 checkGLcall("glLightModeli(GL_LIGHT_MODEL_COLOR_CONTROL, GL_SEPARATE_SPECULAR_COLOR);");
1859 /* switch back to the original context (if there was one)*/
1860 if (This->swapchains) {
1861 /** TODO: restore the context and drawable **/
1862 glXMakeCurrent(object->display, oldDrawable, oldContext);
1865 /* Set the surface alignment. This never changes, so we are safe to set it once per context*/
1866 glPixelStorei(GL_PACK_ALIGNMENT, SURFACE_ALIGNMENT);
1867 checkGLcall("glPixelStorei(GL_PACK_ALIGNMENT, SURFACE_ALIGNMENT);");
1868 glPixelStorei(GL_UNPACK_ALIGNMENT, SURFACE_ALIGNMENT);
1869 checkGLcall("glPixelStorei(GL_UNPACK_ALIGNMENT, SURFACE_ALIGNMENT);");
1873 TRACE("Set swapchain to %p\n", object);
1874 } else { /* something went wrong so clean up */
1875 IUnknown* bufferParent;
1876 if (object->frontBuffer) {
1878 IWineD3DSurface_GetParent(object->frontBuffer, &bufferParent);
1879 IUnknown_Release(bufferParent); /* once for the get parent */
1880 if (IUnknown_Release(bufferParent) > 0) {
1881 FIXME("(%p) Something's still holding the front buffer\n",This);
1884 if (object->backBuffer) {
1886 for(i = 0; i < object->presentParms.BackBufferCount; i++) {
1887 if(object->backBuffer[i]) {
1888 IWineD3DSurface_GetParent(object->backBuffer[i], &bufferParent);
1889 IUnknown_Release(bufferParent); /* once for the get parent */
1890 if (IUnknown_Release(bufferParent) > 0) {
1891 FIXME("(%p) Something's still holding the back buffer\n",This);
1895 HeapFree(GetProcessHeap(), 0, object->backBuffer);
1896 object->backBuffer = NULL;
1898 /* NOTE: don't clean up the depthstencil buffer because it belongs to the device */
1899 /* Clean up the context */
1900 /* check that we are the current context first (we shouldn't be though!) */
1901 if (object->glCtx != 0) {
1902 if(glXGetCurrentContext() == object->glCtx) {
1903 glXMakeCurrent(object->display, None, NULL);
1905 glXDestroyContext(object->display, object->glCtx);
1907 HeapFree(GetProcessHeap(), 0, object);
1914 /** NOTE: These are ahead of the other getters and setters to save using a forward declaration **/
1915 static UINT WINAPI IWineD3DDeviceImpl_GetNumberOfSwapChains(IWineD3DDevice *iface) {
1916 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
1917 TRACE("(%p)\n", This);
1919 return This->NumberOfSwapChains;
1922 static HRESULT WINAPI IWineD3DDeviceImpl_GetSwapChain(IWineD3DDevice *iface, UINT iSwapChain, IWineD3DSwapChain **pSwapChain) {
1923 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
1924 TRACE("(%p) : swapchain %d\n", This, iSwapChain);
1926 if(iSwapChain < This->NumberOfSwapChains) {
1927 *pSwapChain = This->swapchains[iSwapChain];
1928 TRACE("(%p) returning %p\n", This, *pSwapChain);
1931 TRACE("Swapchain out of range\n");
1933 return WINED3DERR_INVALIDCALL;
1938 * Vertex Declaration
1940 static HRESULT WINAPI IWineD3DDeviceImpl_CreateVertexDeclaration(IWineD3DDevice* iface, CONST VOID* pDeclaration, IWineD3DVertexDeclaration** ppVertexDeclaration, IUnknown *parent) {
1941 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
1942 IWineD3DVertexDeclarationImpl *object = NULL;
1943 HRESULT hr = WINED3D_OK;
1944 TRACE("(%p) : directXVersion=%u, pFunction=%p, ppDecl=%p\n", This, ((IWineD3DImpl *)This->wineD3D)->dxVersion, pDeclaration, ppVertexDeclaration);
1945 D3DCREATEOBJECTINSTANCE(object, VertexDeclaration)
1948 hr = IWineD3DVertexDeclaration_SetDeclaration((IWineD3DVertexDeclaration *)object, (void *)pDeclaration);
1953 /* http://msdn.microsoft.com/archive/default.asp?url=/archive/en-us/directx9_c/directx/graphics/programmingguide/programmable/vertexshaders/vscreate.asp */
1954 static HRESULT WINAPI IWineD3DDeviceImpl_CreateVertexShader(IWineD3DDevice *iface, CONST DWORD *pDeclaration, CONST DWORD *pFunction, IWineD3DVertexShader **ppVertexShader, IUnknown *parent) {
1955 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
1956 IWineD3DVertexShaderImpl *object; /* NOTE: impl usage is ok, this is a create */
1957 HRESULT hr = WINED3D_OK;
1958 D3DCREATESHADEROBJECTINSTANCE(object, VertexShader)
1959 object->baseShader.shader_ins = IWineD3DVertexShaderImpl_shader_ins;
1961 TRACE("(%p) : Created Vertex shader %p\n", This, *ppVertexShader);
1963 /* If a vertex declaration has been passed, save it to the vertex shader, this affects d3d8 only. */
1964 /* Further it needs to be set before calling SetFunction as SetFunction needs the declaration. */
1965 if (pDeclaration != NULL) {
1966 IWineD3DVertexDeclaration *vertexDeclaration;
1967 hr = IWineD3DDevice_CreateVertexDeclaration(iface, pDeclaration, &vertexDeclaration ,NULL);
1968 if (WINED3D_OK == hr) {
1969 TRACE("(%p) : Setting vertex declaration to %p\n", This, vertexDeclaration);
1970 object->vertexDeclaration = vertexDeclaration;
1972 FIXME("(%p) : Failed to set the declaration, returning WINED3DERR_INVALIDCALL\n", iface);
1973 IWineD3DVertexShader_Release(*ppVertexShader);
1974 return WINED3DERR_INVALIDCALL;
1978 hr = IWineD3DVertexShader_SetFunction(*ppVertexShader, pFunction);
1980 if (WINED3D_OK != hr) {
1981 FIXME("(%p) : Failed to set the function, returning WINED3DERR_INVALIDCALL\n", iface);
1982 IWineD3DVertexShader_Release(*ppVertexShader);
1983 return WINED3DERR_INVALIDCALL;
1986 #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. */
1987 if(Usage == WINED3DUSAGE_SOFTWAREVERTEXPROCESSING) {
1998 static HRESULT WINAPI IWineD3DDeviceImpl_CreatePixelShader(IWineD3DDevice *iface, CONST DWORD *pFunction, IWineD3DPixelShader **ppPixelShader, IUnknown *parent) {
1999 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2000 IWineD3DPixelShaderImpl *object; /* NOTE: impl allowed, this is a create */
2001 HRESULT hr = WINED3D_OK;
2003 D3DCREATESHADEROBJECTINSTANCE(object, PixelShader)
2004 object->baseShader.shader_ins = IWineD3DPixelShaderImpl_shader_ins;
2005 hr = IWineD3DPixelShader_SetFunction(*ppPixelShader, pFunction);
2006 if (WINED3D_OK == hr) {
2007 TRACE("(%p) : Created Pixel shader %p\n", This, *ppPixelShader);
2009 WARN("(%p) : Failed to create pixel shader\n", This);
2015 static HRESULT WINAPI IWineD3DDeviceImpl_CreatePalette(IWineD3DDevice *iface, DWORD Flags, PALETTEENTRY *PalEnt, IWineD3DPalette **Palette, IUnknown *Parent) {
2016 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *) iface;
2017 IWineD3DPaletteImpl *object;
2019 TRACE("(%p)->(%x, %p, %p, %p)\n", This, Flags, PalEnt, Palette, Parent);
2021 /* Create the new object */
2022 object = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(IWineD3DPaletteImpl));
2024 ERR("Out of memory when allocating memory for a IWineD3DPalette implementation\n");
2025 return E_OUTOFMEMORY;
2028 object->lpVtbl = &IWineD3DPalette_Vtbl;
2030 object->Flags = Flags;
2031 object->parent = Parent;
2032 object->wineD3DDevice = This;
2033 object->palNumEntries = IWineD3DPaletteImpl_Size(Flags);
2035 object->hpal = CreatePalette((const LOGPALETTE*)&(object->palVersion));
2038 HeapFree( GetProcessHeap(), 0, object);
2039 return E_OUTOFMEMORY;
2042 hr = IWineD3DPalette_SetEntries((IWineD3DPalette *) object, 0, 0, IWineD3DPaletteImpl_Size(Flags), PalEnt);
2044 IWineD3DPalette_Release((IWineD3DPalette *) object);
2048 *Palette = (IWineD3DPalette *) object;
2053 static HRESULT WINAPI IWineD3DDeviceImpl_Init3D(IWineD3DDevice *iface, WINED3DPRESENT_PARAMETERS* pPresentationParameters, D3DCB_CREATEADDITIONALSWAPCHAIN D3DCB_CreateAdditionalSwapChain) {
2054 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *) iface;
2055 IWineD3DSwapChainImpl *swapchain;
2057 TRACE("(%p)->(%p,%p)\n", This, pPresentationParameters, D3DCB_CreateAdditionalSwapChain);
2058 if(This->d3d_initialized) return WINED3DERR_INVALIDCALL;
2060 /* TODO: Test if OpenGL is compiled in and loaded */
2062 /* Setup the implicit swapchain */
2063 TRACE("Creating implicit swapchain\n");
2064 if (D3D_OK != D3DCB_CreateAdditionalSwapChain((IUnknown *) This->parent, pPresentationParameters, (IWineD3DSwapChain **)&swapchain) || swapchain == NULL) {
2065 WARN("Failed to create implicit swapchain\n");
2066 return WINED3DERR_INVALIDCALL;
2069 This->NumberOfSwapChains = 1;
2070 This->swapchains = HeapAlloc(GetProcessHeap(), 0, This->NumberOfSwapChains * sizeof(IWineD3DSwapChain *));
2071 if(!This->swapchains) {
2072 ERR("Out of memory!\n");
2073 IWineD3DSwapChain_Release( (IWineD3DSwapChain *) swapchain);
2074 return E_OUTOFMEMORY;
2076 This->swapchains[0] = (IWineD3DSwapChain *) swapchain;
2078 if(swapchain->backBuffer && swapchain->backBuffer[0]) {
2079 TRACE("Setting rendertarget to %p\n", swapchain->backBuffer);
2080 This->renderTarget = swapchain->backBuffer[0];
2083 TRACE("Setting rendertarget to %p\n", swapchain->frontBuffer);
2084 This->renderTarget = swapchain->frontBuffer;
2086 IWineD3DSurface_AddRef(This->renderTarget);
2087 /* Depth Stencil support */
2088 This->stencilBufferTarget = This->depthStencilBuffer;
2089 if (NULL != This->stencilBufferTarget) {
2090 IWineD3DSurface_AddRef(This->stencilBufferTarget);
2093 /* Set up some starting GL setup */
2096 * Initialize openGL extension related variables
2097 * with Default values
2100 ((IWineD3DImpl *) This->wineD3D)->isGLInfoValid = IWineD3DImpl_FillGLCaps( This->wineD3D, swapchain->display);
2101 /* Setup all the devices defaults */
2102 IWineD3DStateBlock_InitStartupStateBlock((IWineD3DStateBlock *)This->stateBlock);
2104 IWineD3DImpl_CheckGraphicsMemory();
2108 /* Initialize our list of GLSL programs */
2109 list_init(&This->glsl_shader_progs);
2111 { /* Set a default viewport */
2115 vp.Width = *(pPresentationParameters->BackBufferWidth);
2116 vp.Height = *(pPresentationParameters->BackBufferHeight);
2119 IWineD3DDevice_SetViewport((IWineD3DDevice *)This, &vp);
2122 /* Initialize the current view state */
2123 This->modelview_valid = 1;
2124 This->proj_valid = 0;
2125 This->view_ident = 1;
2126 This->last_was_rhw = 0;
2127 glGetIntegerv(GL_MAX_LIGHTS, &This->maxConcurrentLights);
2128 TRACE("(%p) All defaults now set up, leaving Init3D with %p\n", This, This);
2130 /* Clear the screen */
2131 IWineD3DDevice_Clear((IWineD3DDevice *) This, 0, NULL, WINED3DCLEAR_STENCIL|WINED3DCLEAR_ZBUFFER|WINED3DCLEAR_TARGET, 0x00, 1.0, 0);
2133 This->d3d_initialized = TRUE;
2137 static HRESULT WINAPI IWineD3DDeviceImpl_Uninit3D(IWineD3DDevice *iface) {
2138 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *) iface;
2140 IUnknown* stencilBufferParent;
2141 IUnknown* swapChainParent;
2143 TRACE("(%p)\n", This);
2145 if(!This->d3d_initialized) return WINED3DERR_INVALIDCALL;
2147 /* Delete the mouse cursor texture */
2148 if(This->cursorTexture) {
2150 glDeleteTextures(1, &This->cursorTexture);
2152 This->cursorTexture = 0;
2155 for(sampler = 0; sampler < GL_LIMITS(sampler_stages); ++sampler) {
2156 IWineD3DDevice_SetTexture(iface, sampler, NULL);
2159 /* Release the buffers (with sanity checks)*/
2160 TRACE("Releasing the depth stencil buffer at %p\n", This->stencilBufferTarget);
2161 if(This->stencilBufferTarget != NULL && (IWineD3DSurface_Release(This->stencilBufferTarget) >0)){
2162 if(This->depthStencilBuffer != This->stencilBufferTarget)
2163 FIXME("(%p) Something's still holding the depthStencilBuffer\n",This);
2165 This->stencilBufferTarget = NULL;
2167 TRACE("Releasing the render target at %p\n", This->renderTarget);
2168 if(IWineD3DSurface_Release(This->renderTarget) >0){
2169 /* This check is a bit silly, itshould be in swapchain_release FIXME("(%p) Something's still holding the renderTarget\n",This); */
2171 TRACE("Setting rendertarget to NULL\n");
2172 This->renderTarget = NULL;
2174 if (This->depthStencilBuffer) {
2175 IWineD3DSurface_GetParent(This->depthStencilBuffer, &stencilBufferParent);
2176 IUnknown_Release(stencilBufferParent); /* once for the get parent */
2177 if(IUnknown_Release(stencilBufferParent) >0){ /* the second time for when it was created */
2178 FIXME("(%p) Something's still holding the depthStencilBuffer\n",This);
2180 This->depthStencilBuffer = NULL;
2183 for(i=0; i < This->NumberOfSwapChains; i++) {
2184 TRACE("Releasing the implicit swapchain %d\n", i);
2185 /* Swapchain 0 is special because it's created in startup with a hanging parent, so we have to release its parent now */
2186 IWineD3DSwapChain_GetParent(This->swapchains[i], &swapChainParent);
2187 IUnknown_Release(swapChainParent); /* once for the get parent */
2188 if (IUnknown_Release(swapChainParent) > 0) { /* the second time for when it was created */
2189 FIXME("(%p) Something's still holding the implicit swapchain\n", This);
2193 HeapFree(GetProcessHeap(), 0, This->swapchains);
2194 This->swapchains = NULL;
2195 This->NumberOfSwapChains = 0;
2197 This->d3d_initialized = FALSE;
2201 static void WINAPI IWineD3DDeviceImpl_SetFullscreen(IWineD3DDevice *iface, BOOL fullscreen) {
2202 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *) iface;
2203 TRACE("(%p) Setting DDraw fullscreen mode to %s\n", This, fullscreen ? "true" : "false");
2205 /* DirectDraw apps can change between fullscreen and windowed mode after device creation with
2206 * IDirectDraw7::SetCooperativeLevel. The GDI surface implementation needs to know this.
2207 * DDraw doesn't necessarily have a swapchain, so we have to store the fullscreen flag
2210 This->ddraw_fullscreen = fullscreen;
2213 static HRESULT WINAPI IWineD3DDeviceImpl_EnumDisplayModes(IWineD3DDevice *iface, DWORD Flags, UINT Width, UINT Height, WINED3DFORMAT pixelformat, LPVOID context, D3DCB_ENUMDISPLAYMODESCALLBACK callback) {
2214 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2218 const PixelFormatDesc *formatDesc = getFormatDescEntry(pixelformat);
2220 TRACE("(%p)->(%x,%d,%d,%d,%p,%p)\n", This, Flags, Width, Height, pixelformat, context, callback);
2222 for (i = 0; EnumDisplaySettingsExW(NULL, i, &DevModeW, 0); i++) {
2223 /* Ignore some modes if a description was passed */
2224 if ( (Width > 0) && (Width != DevModeW.dmPelsWidth)) continue;
2225 if ( (Height > 0) && (Height != DevModeW.dmPelsHeight)) continue;
2226 if ( (pixelformat != WINED3DFMT_UNKNOWN) && ( formatDesc->bpp != DevModeW.dmBitsPerPel) ) continue;
2228 TRACE("Enumerating %dx%d@%s\n", DevModeW.dmPelsWidth, DevModeW.dmPelsHeight, debug_d3dformat(pixelformat_for_depth(DevModeW.dmBitsPerPel)));
2230 if (callback((IUnknown *) This, (UINT) DevModeW.dmPelsWidth, (UINT) DevModeW.dmPelsHeight, pixelformat_for_depth(DevModeW.dmBitsPerPel), 60.0, context) == DDENUMRET_CANCEL)
2237 static HRESULT WINAPI IWineD3DDeviceImpl_SetDisplayMode(IWineD3DDevice *iface, UINT iSwapChain, WINED3DDISPLAYMODE* pMode) {
2239 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2241 const PixelFormatDesc *formatDesc = getFormatDescEntry(pMode->Format);
2243 TRACE("(%p)->(%d,%p) Mode=%dx%dx@%d, %s\n", This, iSwapChain, pMode, pMode->Width, pMode->Height, pMode->RefreshRate, debug_d3dformat(pMode->Format));
2245 /* Resize the screen even without a window:
2246 * The app could have unset it with SetCooperativeLevel, but not called
2247 * RestoreDisplayMode first. Then the release will call RestoreDisplayMode,
2248 * but we don't have any hwnd
2251 devmode.dmFields = DM_BITSPERPEL | DM_PELSWIDTH | DM_PELSHEIGHT;
2252 devmode.dmBitsPerPel = formatDesc->bpp * 8;
2253 if(devmode.dmBitsPerPel == 24) devmode.dmBitsPerPel = 32;
2254 devmode.dmPelsWidth = pMode->Width;
2255 devmode.dmPelsHeight = pMode->Height;
2257 devmode.dmDisplayFrequency = pMode->RefreshRate;
2258 if (pMode->RefreshRate != 0) {
2259 devmode.dmFields |= DM_DISPLAYFREQUENCY;
2262 /* Only change the mode if necessary */
2263 if( (This->ddraw_width == pMode->Width) &&
2264 (This->ddraw_height == pMode->Height) &&
2265 (This->ddraw_format == pMode->Format) &&
2266 (pMode->RefreshRate == 0) ) {
2270 ret = ChangeDisplaySettingsExW(NULL, &devmode, NULL, CDS_FULLSCREEN, NULL);
2271 if (ret != DISP_CHANGE_SUCCESSFUL) {
2272 if(devmode.dmDisplayFrequency != 0) {
2273 WARN("ChangeDisplaySettingsExW failed, trying without the refresh rate\n");
2274 devmode.dmFields &= ~DM_DISPLAYFREQUENCY;
2275 devmode.dmDisplayFrequency = 0;
2276 ret = ChangeDisplaySettingsExW(NULL, &devmode, NULL, CDS_FULLSCREEN, NULL) != DISP_CHANGE_SUCCESSFUL;
2278 if(ret != DISP_CHANGE_SUCCESSFUL) {
2279 return DDERR_INVALIDMODE;
2283 /* Store the new values */
2284 This->ddraw_width = pMode->Width;
2285 This->ddraw_height = pMode->Height;
2286 This->ddraw_format = pMode->Format;
2288 /* Only do this with a window of course */
2289 if(This->ddraw_window)
2290 MoveWindow(This->ddraw_window, 0, 0, pMode->Width, pMode->Height, TRUE);
2295 static HRESULT WINAPI IWineD3DDeviceImpl_GetDirect3D(IWineD3DDevice *iface, IWineD3D **ppD3D) {
2296 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2297 *ppD3D= This->wineD3D;
2298 TRACE("(%p) : wineD3D returning %p\n", This, *ppD3D);
2302 static UINT WINAPI IWineD3DDeviceImpl_GetAvailableTextureMem(IWineD3DDevice *iface) {
2303 /** NOTE: There's a probably a hack-around for this one by putting as many pbuffers, VBOs (or whatever)
2304 * into the video ram as possible and seeing how many fit
2305 * you can also get the correct initial value from nvidia and ATI's driver via X
2306 * texture memory is video memory + AGP memory
2307 *******************/
2308 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2309 static BOOL showfixmes = TRUE;
2311 FIXME("(%p) : stub, simulating %dMB for now, returning %dMB left\n", This,
2312 (wined3d_settings.emulated_textureram/(1024*1024)),
2313 ((wined3d_settings.emulated_textureram - wineD3DGlobalStatistics->glsurfaceram) / (1024*1024)));
2316 TRACE("(%p) : simulating %dMB, returning %dMB left\n", This,
2317 (wined3d_settings.emulated_textureram/(1024*1024)),
2318 ((wined3d_settings.emulated_textureram - wineD3DGlobalStatistics->glsurfaceram) / (1024*1024)));
2319 /* return simulated texture memory left */
2320 return (wined3d_settings.emulated_textureram - wineD3DGlobalStatistics->glsurfaceram);
2328 static HRESULT WINAPI IWineD3DDeviceImpl_SetFVF(IWineD3DDevice *iface, DWORD fvf) {
2329 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2330 HRESULT hr = WINED3D_OK;
2332 /* Update the current state block */
2333 This->updateStateBlock->fvf = fvf;
2334 This->updateStateBlock->changed.fvf = TRUE;
2335 This->updateStateBlock->set.fvf = TRUE;
2337 TRACE("(%p) : FVF Shader FVF set to %x\n", This, fvf);
2342 static HRESULT WINAPI IWineD3DDeviceImpl_GetFVF(IWineD3DDevice *iface, DWORD *pfvf) {
2343 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2344 TRACE("(%p) : GetFVF returning %x\n", This, This->stateBlock->fvf);
2345 *pfvf = This->stateBlock->fvf;
2350 * Get / Set Stream Source
2352 static HRESULT WINAPI IWineD3DDeviceImpl_SetStreamSource(IWineD3DDevice *iface, UINT StreamNumber,IWineD3DVertexBuffer* pStreamData, UINT OffsetInBytes, UINT Stride) {
2353 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2354 IWineD3DVertexBuffer *oldSrc;
2356 /**TODO: instance and index data, see
2357 http://msdn.microsoft.com/library/default.asp?url=/library/en-us/directx9_c/directx/graphics/programmingguide/advancedtopics/DrawingMultipleInstances.asp
2359 http://msdn.microsoft.com/library/default.asp?url=/library/en-us/directx9_c/directx/graphics/reference/d3d/interfaces/idirect3ddevice9/SetStreamSourceFreq.asp
2362 /* D3d9 only, but shouldn't hurt d3d8 */
2365 streamFlags = StreamNumber &(WINED3DSTREAMSOURCE_INDEXEDDATA | WINED3DSTREAMSOURCE_INSTANCEDATA);
2367 if (streamFlags & WINED3DSTREAMSOURCE_INDEXEDDATA) {
2368 FIXME("stream index data not supported\n");
2370 if (streamFlags & WINED3DSTREAMSOURCE_INDEXEDDATA) {
2371 FIXME("stream instance data not supported\n");
2375 StreamNumber&= ~(WINED3DSTREAMSOURCE_INDEXEDDATA | WINED3DSTREAMSOURCE_INSTANCEDATA);
2377 if (StreamNumber >= MAX_STREAMS) {
2378 WARN("Stream out of range %d\n", StreamNumber);
2379 return WINED3DERR_INVALIDCALL;
2382 oldSrc = This->stateBlock->streamSource[StreamNumber];
2383 TRACE("(%p) : StreamNo: %d, OldStream (%p), NewStream (%p), NewStride %d\n", This, StreamNumber, oldSrc, pStreamData, Stride);
2385 This->updateStateBlock->changed.streamSource[StreamNumber] = TRUE;
2386 This->updateStateBlock->set.streamSource[StreamNumber] = TRUE;
2387 This->updateStateBlock->streamStride[StreamNumber] = Stride;
2388 This->updateStateBlock->streamSource[StreamNumber] = pStreamData;
2389 This->updateStateBlock->streamOffset[StreamNumber] = OffsetInBytes;
2390 This->updateStateBlock->streamFlags[StreamNumber] = streamFlags;
2392 /* Handle recording of state blocks */
2393 if (This->isRecordingState) {
2394 TRACE("Recording... not performing anything\n");
2398 /* Same stream object: no action */
2399 if (oldSrc == pStreamData)
2402 /* Need to do a getParent and pass the reffs up */
2403 /* MSDN says ..... When an application no longer holds a references to this interface, the interface will automatically be freed.
2404 which suggests that we shouldn't be ref counting? and do need a _release on the stream source to reset the stream source
2405 so for now, just count internally */
2406 if (pStreamData != NULL) {
2407 IWineD3DVertexBufferImpl *vbImpl = (IWineD3DVertexBufferImpl *) pStreamData;
2408 if( (vbImpl->Flags & VBFLAG_STREAM) && vbImpl->stream != StreamNumber) {
2409 WARN("Assigning a Vertex Buffer to stream %d which is already assigned to stream %d\n", StreamNumber, vbImpl->stream);
2411 vbImpl->stream = StreamNumber;
2412 vbImpl->Flags |= VBFLAG_STREAM;
2413 IWineD3DVertexBuffer_AddRef(pStreamData);
2415 if (oldSrc != NULL) {
2416 ((IWineD3DVertexBufferImpl *) oldSrc)->Flags &= ~VBFLAG_STREAM;
2417 IWineD3DVertexBuffer_Release(oldSrc);
2423 static HRESULT WINAPI IWineD3DDeviceImpl_GetStreamSource(IWineD3DDevice *iface, UINT StreamNumber,IWineD3DVertexBuffer** pStream, UINT *pOffset, UINT* pStride) {
2424 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2427 TRACE("(%p) : StreamNo: %d, Stream (%p), Stride %d\n", This, StreamNumber,
2428 This->stateBlock->streamSource[StreamNumber], This->stateBlock->streamStride[StreamNumber]);
2431 streamFlags = StreamNumber &(WINED3DSTREAMSOURCE_INDEXEDDATA | WINED3DSTREAMSOURCE_INSTANCEDATA);
2433 if (streamFlags & WINED3DSTREAMSOURCE_INDEXEDDATA) {
2434 FIXME("stream index data not supported\n");
2436 if (streamFlags & WINED3DSTREAMSOURCE_INDEXEDDATA) {
2437 FIXME("stream instance data not supported\n");
2441 StreamNumber&= ~(WINED3DSTREAMSOURCE_INDEXEDDATA | WINED3DSTREAMSOURCE_INSTANCEDATA);
2443 if (StreamNumber >= MAX_STREAMS) {
2444 WARN("Stream out of range %d\n", StreamNumber);
2445 return WINED3DERR_INVALIDCALL;
2447 *pStream = This->stateBlock->streamSource[StreamNumber];
2448 *pStride = This->stateBlock->streamStride[StreamNumber];
2450 *pOffset = This->stateBlock->streamOffset[StreamNumber];
2453 if (*pStream == NULL) {
2454 FIXME("Attempting to get an empty stream %d, returning WINED3DERR_INVALIDCALL\n", StreamNumber);
2455 return WINED3DERR_INVALIDCALL;
2461 /*Should be quite easy, just an extension of vertexdata
2463 http://msdn.microsoft.com/archive/default.asp?url=/archive/en-us/directx9_c_Summer_04/directx/graphics/programmingguide/advancedtopics/DrawingMultipleInstances.asp
2465 The divider is a bit odd though
2467 VertexOffset = StartVertex / Divider * StreamStride +
2468 VertexIndex / Divider * StreamStride + StreamOffset
2471 static HRESULT WINAPI IWineD3DDeviceImpl_SetStreamSourceFreq(IWineD3DDevice *iface, UINT StreamNumber, UINT Divider) {
2472 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2474 TRACE("(%p) StreamNumber(%d), Divider(%d)\n", This, StreamNumber, Divider);
2475 This->updateStateBlock->streamFlags[StreamNumber] = Divider & (WINED3DSTREAMSOURCE_INSTANCEDATA | WINED3DSTREAMSOURCE_INDEXEDDATA );
2477 This->updateStateBlock->changed.streamFreq[StreamNumber] = TRUE;
2478 This->updateStateBlock->set.streamFreq[StreamNumber] = TRUE;
2479 This->updateStateBlock->streamFreq[StreamNumber] = Divider & 0x7FFFFF;
2481 if (This->updateStateBlock->streamFlags[StreamNumber] || This->updateStateBlock->streamFreq[StreamNumber] != 1) {
2482 FIXME("Stream indexing not fully supported\n");
2488 static HRESULT WINAPI IWineD3DDeviceImpl_GetStreamSourceFreq(IWineD3DDevice *iface, UINT StreamNumber, UINT* Divider) {
2489 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2491 TRACE("(%p) StreamNumber(%d), Divider(%p)\n", This, StreamNumber, Divider);
2492 *Divider = This->updateStateBlock->streamFreq[StreamNumber] | This->updateStateBlock->streamFlags[StreamNumber];
2494 TRACE("(%p) : returning %d\n", This, *Divider);
2500 * Get / Set & Multiply Transform
2502 static HRESULT WINAPI IWineD3DDeviceImpl_SetTransform(IWineD3DDevice *iface, WINED3DTRANSFORMSTATETYPE d3dts, CONST WINED3DMATRIX* lpmatrix) {
2503 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2505 /* Most of this routine, comments included copied from ddraw tree initially: */
2506 TRACE("(%p) : Transform State=%s\n", This, debug_d3dtstype(d3dts));
2508 /* Handle recording of state blocks */
2509 if (This->isRecordingState) {
2510 TRACE("Recording... not performing anything\n");
2511 This->updateStateBlock->changed.transform[d3dts] = TRUE;
2512 This->updateStateBlock->set.transform[d3dts] = TRUE;
2513 memcpy(&This->updateStateBlock->transforms[d3dts], lpmatrix, sizeof(WINED3DMATRIX));
2518 * If the new matrix is the same as the current one,
2519 * we cut off any further processing. this seems to be a reasonable
2520 * optimization because as was noticed, some apps (warcraft3 for example)
2521 * tend towards setting the same matrix repeatedly for some reason.
2523 * From here on we assume that the new matrix is different, wherever it matters.
2525 if (!memcmp(&This->stateBlock->transforms[d3dts].u.m[0][0], lpmatrix, sizeof(WINED3DMATRIX))) {
2526 TRACE("The app is setting the same matrix over again\n");
2529 conv_mat(lpmatrix, &This->stateBlock->transforms[d3dts].u.m[0][0]);
2533 ScreenCoord = ProjectionMat * ViewMat * WorldMat * ObjectCoord
2534 where ViewMat = Camera space, WorldMat = world space.
2536 In OpenGL, camera and world space is combined into GL_MODELVIEW
2537 matrix. The Projection matrix stay projection matrix.
2540 /* Capture the times we can just ignore the change for now */
2541 if (d3dts == WINED3DTS_WORLDMATRIX(0)) {
2542 This->modelview_valid = FALSE;
2545 } else if (d3dts == WINED3DTS_PROJECTION) {
2546 This->proj_valid = FALSE;
2549 } else if (d3dts >= WINED3DTS_WORLDMATRIX(1) && d3dts <= WINED3DTS_WORLDMATRIX(255)) {
2550 /* Indexed Vertex Blending Matrices 256 -> 511 */
2551 /* Use arb_vertex_blend or NV_VERTEX_WEIGHTING? */
2552 FIXME("WINED3DTS_WORLDMATRIX(1..255) not handled\n");
2556 /* Now we really are going to have to change a matrix */
2559 if (d3dts >= WINED3DTS_TEXTURE0 && d3dts <= WINED3DTS_TEXTURE7) { /* handle texture matrices */
2560 /* This is now set with the texture unit states, it may be a good idea to flag the change though! */
2561 } else if (d3dts == WINED3DTS_VIEW) { /* handle the VIEW matrice */
2564 /* If we are changing the View matrix, reset the light and clipping planes to the new view
2565 * NOTE: We have to reset the positions even if the light/plane is not currently
2566 * enabled, since the call to enable it will not reset the position.
2567 * NOTE2: Apparently texture transforms do NOT need reapplying
2570 PLIGHTINFOEL *lightChain = NULL;
2571 This->modelview_valid = FALSE;
2572 This->view_ident = !memcmp(lpmatrix, identity, 16 * sizeof(float));
2574 glMatrixMode(GL_MODELVIEW);
2575 checkGLcall("glMatrixMode(GL_MODELVIEW)");
2577 glLoadMatrixf((const float *)lpmatrix);
2578 checkGLcall("glLoadMatrixf(...)");
2581 lightChain = This->stateBlock->lights;
2582 while (lightChain && lightChain->glIndex != -1) {
2583 glLightfv(GL_LIGHT0 + lightChain->glIndex, GL_POSITION, lightChain->lightPosn);
2584 checkGLcall("glLightfv posn");
2585 glLightfv(GL_LIGHT0 + lightChain->glIndex, GL_SPOT_DIRECTION, lightChain->lightDirn);
2586 checkGLcall("glLightfv dirn");
2587 lightChain = lightChain->next;
2590 /* Reset Clipping Planes if clipping is enabled */
2591 for (k = 0; k < GL_LIMITS(clipplanes); k++) {
2592 glClipPlane(GL_CLIP_PLANE0 + k, This->stateBlock->clipplane[k]);
2593 checkGLcall("glClipPlane");
2597 } else { /* What was requested!?? */
2598 WARN("invalid matrix specified: %i\n", d3dts);
2601 /* Release lock, all done */
2606 static HRESULT WINAPI IWineD3DDeviceImpl_GetTransform(IWineD3DDevice *iface, WINED3DTRANSFORMSTATETYPE State, WINED3DMATRIX* pMatrix) {
2607 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2608 TRACE("(%p) : for Transform State %s\n", This, debug_d3dtstype(State));
2609 memcpy(pMatrix, &This->stateBlock->transforms[State], sizeof(WINED3DMATRIX));
2613 static HRESULT WINAPI IWineD3DDeviceImpl_MultiplyTransform(IWineD3DDevice *iface, WINED3DTRANSFORMSTATETYPE State, CONST WINED3DMATRIX* pMatrix) {
2614 WINED3DMATRIX *mat = NULL;
2617 /* Note: Using 'updateStateBlock' rather than 'stateblock' in the code
2618 * below means it will be recorded in a state block change, but it
2619 * works regardless where it is recorded.
2620 * If this is found to be wrong, change to StateBlock.
2622 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2623 TRACE("(%p) : For state %s\n", This, debug_d3dtstype(State));
2625 if (State < HIGHEST_TRANSFORMSTATE)
2627 mat = &This->updateStateBlock->transforms[State];
2629 FIXME("Unhandled transform state!!\n");
2632 multiply_matrix(&temp, mat, (const WINED3DMATRIX *) pMatrix);
2634 /* Apply change via set transform - will reapply to eg. lights this way */
2635 return IWineD3DDeviceImpl_SetTransform(iface, State, &temp);
2641 /* Note lights are real special cases. Although the device caps state only eg. 8 are supported,
2642 you can reference any indexes you want as long as that number max are enabled at any
2643 one point in time! Therefore since the indexes can be anything, we need a linked list of them.
2644 However, this causes stateblock problems. When capturing the state block, I duplicate the list,
2645 but when recording, just build a chain pretty much of commands to be replayed. */
2647 static HRESULT WINAPI IWineD3DDeviceImpl_SetLight(IWineD3DDevice *iface, DWORD Index, CONST WINED3DLIGHT* pLight) {
2649 PLIGHTINFOEL *object, *temp;
2651 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2652 TRACE("(%p) : Idx(%d), pLight(%p)\n", This, Index, pLight);
2654 /* If recording state block, just add to end of lights chain */
2655 if (This->isRecordingState) {
2656 object = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(PLIGHTINFOEL));
2657 if (NULL == object) {
2658 return WINED3DERR_OUTOFVIDEOMEMORY;
2660 memcpy(&object->OriginalParms, pLight, sizeof(WINED3DLIGHT));
2661 object->OriginalIndex = Index;
2662 object->glIndex = -1;
2663 object->changed = TRUE;
2665 /* Add to the END of the chain of lights changes to be replayed */
2666 if (This->updateStateBlock->lights == NULL) {
2667 This->updateStateBlock->lights = object;
2669 temp = This->updateStateBlock->lights;
2670 while (temp->next != NULL) temp=temp->next;
2671 temp->next = object;
2673 TRACE("Recording... not performing anything more\n");
2677 /* Ok, not recording any longer so do real work */
2678 object = This->stateBlock->lights;
2679 while (object != NULL && object->OriginalIndex != Index) object = object->next;
2681 /* If we didn't find it in the list of lights, time to add it */
2682 if (object == NULL) {
2683 PLIGHTINFOEL *insertAt,*prevPos;
2685 object = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(PLIGHTINFOEL));
2686 if (NULL == object) {
2687 return WINED3DERR_OUTOFVIDEOMEMORY;
2689 object->OriginalIndex = Index;
2690 object->glIndex = -1;
2692 /* Add it to the front of list with the idea that lights will be changed as needed
2693 BUT after any lights currently assigned GL indexes */
2694 insertAt = This->stateBlock->lights;
2696 while (insertAt != NULL && insertAt->glIndex != -1) {
2698 insertAt = insertAt->next;
2701 if (insertAt == NULL && prevPos == NULL) { /* Start of list */
2702 This->stateBlock->lights = object;
2703 } else if (insertAt == NULL) { /* End of list */
2704 prevPos->next = object;
2705 object->prev = prevPos;
2706 } else { /* Middle of chain */
2707 if (prevPos == NULL) {
2708 This->stateBlock->lights = object;
2710 prevPos->next = object;
2712 object->prev = prevPos;
2713 object->next = insertAt;
2714 insertAt->prev = object;
2718 /* Initialize the object */
2719 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,
2720 pLight->Diffuse.r, pLight->Diffuse.g, pLight->Diffuse.b, pLight->Diffuse.a,
2721 pLight->Specular.r, pLight->Specular.g, pLight->Specular.b, pLight->Specular.a,
2722 pLight->Ambient.r, pLight->Ambient.g, pLight->Ambient.b, pLight->Ambient.a);
2723 TRACE("... Pos(%f,%f,%f), Dirn(%f,%f,%f)\n", pLight->Position.x, pLight->Position.y, pLight->Position.z,
2724 pLight->Direction.x, pLight->Direction.y, pLight->Direction.z);
2725 TRACE("... Range(%f), Falloff(%f), Theta(%f), Phi(%f)\n", pLight->Range, pLight->Falloff, pLight->Theta, pLight->Phi);
2727 /* Save away the information */
2728 memcpy(&object->OriginalParms, pLight, sizeof(WINED3DLIGHT));
2730 switch (pLight->Type) {
2731 case WINED3DLIGHT_POINT:
2733 object->lightPosn[0] = pLight->Position.x;
2734 object->lightPosn[1] = pLight->Position.y;
2735 object->lightPosn[2] = pLight->Position.z;
2736 object->lightPosn[3] = 1.0f;
2737 object->cutoff = 180.0f;
2741 case WINED3DLIGHT_DIRECTIONAL:
2743 object->lightPosn[0] = -pLight->Direction.x;
2744 object->lightPosn[1] = -pLight->Direction.y;
2745 object->lightPosn[2] = -pLight->Direction.z;
2746 object->lightPosn[3] = 0.0;
2747 object->exponent = 0.0f;
2748 object->cutoff = 180.0f;
2751 case WINED3DLIGHT_SPOT:
2753 object->lightPosn[0] = pLight->Position.x;
2754 object->lightPosn[1] = pLight->Position.y;
2755 object->lightPosn[2] = pLight->Position.z;
2756 object->lightPosn[3] = 1.0;
2759 object->lightDirn[0] = pLight->Direction.x;
2760 object->lightDirn[1] = pLight->Direction.y;
2761 object->lightDirn[2] = pLight->Direction.z;
2762 object->lightDirn[3] = 1.0;
2765 * opengl-ish and d3d-ish spot lights use too different models for the
2766 * light "intensity" as a function of the angle towards the main light direction,
2767 * so we only can approximate very roughly.
2768 * however spot lights are rather rarely used in games (if ever used at all).
2769 * furthermore if still used, probably nobody pays attention to such details.
2771 if (pLight->Falloff == 0) {
2774 rho = pLight->Theta + (pLight->Phi - pLight->Theta)/(2*pLight->Falloff);
2776 if (rho < 0.0001) rho = 0.0001f;
2777 object->exponent = -0.3/log(cos(rho/2));
2778 if (object->exponent > 128.0) {
2779 object->exponent = 128.0;
2781 object->cutoff = pLight->Phi*90/M_PI;
2787 FIXME("Unrecognized light type %d\n", pLight->Type);
2790 /* Update the live definitions if the light is currently assigned a glIndex */
2791 if (object->glIndex != -1) {
2792 setup_light(iface, object->glIndex, object);
2797 static HRESULT WINAPI IWineD3DDeviceImpl_GetLight(IWineD3DDevice *iface, DWORD Index, WINED3DLIGHT* pLight) {
2798 PLIGHTINFOEL *lightInfo = NULL;
2799 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2800 TRACE("(%p) : Idx(%d), pLight(%p)\n", This, Index, pLight);
2802 /* Locate the light in the live lights */
2803 lightInfo = This->stateBlock->lights;
2804 while (lightInfo != NULL && lightInfo->OriginalIndex != Index) lightInfo = lightInfo->next;
2806 if (lightInfo == NULL) {
2807 TRACE("Light information requested but light not defined\n");
2808 return WINED3DERR_INVALIDCALL;
2811 memcpy(pLight, &lightInfo->OriginalParms, sizeof(WINED3DLIGHT));
2816 * Get / Set Light Enable
2817 * (Note for consistency, renamed d3dx function by adding the 'set' prefix)
2819 static HRESULT WINAPI IWineD3DDeviceImpl_SetLightEnable(IWineD3DDevice *iface, DWORD Index, BOOL Enable) {
2820 PLIGHTINFOEL *lightInfo = NULL;
2821 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2822 TRACE("(%p) : Idx(%d), enable? %d\n", This, Index, Enable);
2824 /* Tests show true = 128...not clear why */
2826 Enable = Enable? 128: 0;
2828 /* If recording state block, just add to end of lights chain with changedEnable set to true */
2829 if (This->isRecordingState) {
2830 lightInfo = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(PLIGHTINFOEL));
2831 if (NULL == lightInfo) {
2832 return WINED3DERR_OUTOFVIDEOMEMORY;
2834 lightInfo->OriginalIndex = Index;
2835 lightInfo->glIndex = -1;
2836 lightInfo->enabledChanged = TRUE;
2837 lightInfo->lightEnabled = Enable;
2839 /* Add to the END of the chain of lights changes to be replayed */
2840 if (This->updateStateBlock->lights == NULL) {
2841 This->updateStateBlock->lights = lightInfo;
2843 PLIGHTINFOEL *temp = This->updateStateBlock->lights;
2844 while (temp->next != NULL) temp=temp->next;
2845 temp->next = lightInfo;
2847 TRACE("Recording... not performing anything more\n");
2851 /* Not recording... So, locate the light in the live lights */
2852 lightInfo = This->stateBlock->lights;
2853 while (lightInfo != NULL && lightInfo->OriginalIndex != Index) lightInfo = lightInfo->next;
2855 /* Special case - enabling an undefined light creates one with a strict set of parms! */
2856 if (lightInfo == NULL) {
2858 TRACE("Light enabled requested but light not defined, so defining one!\n");
2859 IWineD3DDeviceImpl_SetLight(iface, Index, &WINED3D_default_light);
2861 /* Search for it again! Should be fairly quick as near head of list */
2862 lightInfo = This->stateBlock->lights;
2863 while (lightInfo != NULL && lightInfo->OriginalIndex != Index) lightInfo = lightInfo->next;
2864 if (lightInfo == NULL) {
2865 FIXME("Adding default lights has failed dismally\n");
2866 return WINED3DERR_INVALIDCALL;
2870 /* OK, we now have a light... */
2873 /* If we are disabling it, check it was enabled, and
2874 still only do something if it has assigned a glIndex (which it should have!) */
2875 if ((lightInfo->lightEnabled) && (lightInfo->glIndex != -1)) {
2876 TRACE("Disabling light set up at gl idx %d\n", lightInfo->glIndex);
2878 glDisable(GL_LIGHT0 + lightInfo->glIndex);
2879 checkGLcall("glDisable GL_LIGHT0+Index");
2882 TRACE("Nothing to do as light was not enabled\n");
2884 lightInfo->lightEnabled = Enable;
2887 /* We are enabling it. If it is enabled, it's really simple */
2888 if (lightInfo->lightEnabled) {
2890 TRACE("Nothing to do as light was enabled\n");
2892 /* If it already has a glIndex, it's still simple */
2893 } else if (lightInfo->glIndex != -1) {
2894 TRACE("Reusing light as already set up at gl idx %d\n", lightInfo->glIndex);
2895 lightInfo->lightEnabled = Enable;
2897 glEnable(GL_LIGHT0 + lightInfo->glIndex);
2898 checkGLcall("glEnable GL_LIGHT0+Index already setup");
2901 /* Otherwise got to find space - lights are ordered gl indexes first */
2903 PLIGHTINFOEL *bsf = NULL;
2904 PLIGHTINFOEL *pos = This->stateBlock->lights;
2905 PLIGHTINFOEL *prev = NULL;
2909 /* Try to minimize changes as much as possible */
2910 while (pos != NULL && pos->glIndex != -1 && Index < This->maxConcurrentLights) {
2912 /* Try to remember which index can be replaced if necessary */
2913 if (bsf==NULL && !pos->lightEnabled) {
2914 /* Found a light we can replace, save as best replacement */
2918 /* Step to next space */
2924 /* If we have too many active lights, fail the call */
2925 if ((Index == This->maxConcurrentLights) && (bsf == NULL)) {
2926 FIXME("Program requests too many concurrent lights\n");
2927 return WINED3DERR_INVALIDCALL;
2929 /* If we have allocated all lights, but not all are enabled,
2930 reuse one which is not enabled */
2931 } else if (Index == This->maxConcurrentLights) {
2932 /* use bsf - Simply swap the new light and the BSF one */
2933 PLIGHTINFOEL *bsfNext = bsf->next;
2934 PLIGHTINFOEL *bsfPrev = bsf->prev;
2937 if (lightInfo->next != NULL) lightInfo->next->prev = bsf;
2938 if (bsf->prev != NULL) {
2939 bsf->prev->next = lightInfo;
2941 This->stateBlock->lights = lightInfo;
2944 /* If not side by side, lots of chains to update */
2945 if (bsf->next != lightInfo) {
2946 lightInfo->prev->next = bsf;
2947 bsf->next->prev = lightInfo;
2948 bsf->next = lightInfo->next;
2949 bsf->prev = lightInfo->prev;
2950 lightInfo->next = bsfNext;
2951 lightInfo->prev = bsfPrev;
2955 bsf->prev = lightInfo;
2956 bsf->next = lightInfo->next;
2957 lightInfo->next = bsf;
2958 lightInfo->prev = bsfPrev;
2963 glIndex = bsf->glIndex;
2965 lightInfo->glIndex = glIndex;
2966 lightInfo->lightEnabled = Enable;
2968 /* Finally set up the light in gl itself */
2969 TRACE("Replacing light which was set up at gl idx %d\n", lightInfo->glIndex);
2971 setup_light(iface, glIndex, lightInfo);
2972 glEnable(GL_LIGHT0 + glIndex);
2973 checkGLcall("glEnable GL_LIGHT0 new setup");
2976 /* If we reached the end of the allocated lights, with space in the
2977 gl lights, setup a new light */
2978 } else if (pos->glIndex == -1) {
2980 /* We reached the end of the allocated gl lights, so already
2981 know the index of the next one! */
2983 lightInfo->glIndex = glIndex;
2984 lightInfo->lightEnabled = Enable;
2986 /* In an ideal world, it's already in the right place */
2987 if (lightInfo->prev == NULL || lightInfo->prev->glIndex!=-1) {
2988 /* No need to move it */
2990 /* Remove this light from the list */
2991 lightInfo->prev->next = lightInfo->next;
2992 if (lightInfo->next != NULL) {
2993 lightInfo->next->prev = lightInfo->prev;
2996 /* Add in at appropriate place (inbetween prev and pos) */
2997 lightInfo->prev = prev;
2998 lightInfo->next = pos;
3000 This->stateBlock->lights = lightInfo;
3002 prev->next = lightInfo;
3005 pos->prev = lightInfo;
3009 /* Finally set up the light in gl itself */
3010 TRACE("Defining new light at gl idx %d\n", lightInfo->glIndex);
3012 setup_light(iface, glIndex, lightInfo);
3013 glEnable(GL_LIGHT0 + glIndex);
3014 checkGLcall("glEnable GL_LIGHT0 new setup");
3023 static HRESULT WINAPI IWineD3DDeviceImpl_GetLightEnable(IWineD3DDevice *iface, DWORD Index,BOOL* pEnable) {
3025 PLIGHTINFOEL *lightInfo = NULL;
3026 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3027 TRACE("(%p) : for idx(%d)\n", This, Index);
3029 /* Locate the light in the live lights */
3030 lightInfo = This->stateBlock->lights;
3031 while (lightInfo != NULL && lightInfo->OriginalIndex != Index) lightInfo = lightInfo->next;
3033 if (lightInfo == NULL) {
3034 TRACE("Light enabled state requested but light not defined\n");
3035 return WINED3DERR_INVALIDCALL;
3037 *pEnable = lightInfo->lightEnabled;
3042 * Get / Set Clip Planes
3044 static HRESULT WINAPI IWineD3DDeviceImpl_SetClipPlane(IWineD3DDevice *iface, DWORD Index, CONST float *pPlane) {
3045 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3046 TRACE("(%p) : for idx %d, %p\n", This, Index, pPlane);
3048 /* Validate Index */
3049 if (Index >= GL_LIMITS(clipplanes)) {
3050 TRACE("Application has requested clipplane this device doesn't support\n");
3051 return WINED3DERR_INVALIDCALL;
3054 This->updateStateBlock->changed.clipplane[Index] = TRUE;
3055 This->updateStateBlock->set.clipplane[Index] = TRUE;
3056 This->updateStateBlock->clipplane[Index][0] = pPlane[0];
3057 This->updateStateBlock->clipplane[Index][1] = pPlane[1];
3058 This->updateStateBlock->clipplane[Index][2] = pPlane[2];
3059 This->updateStateBlock->clipplane[Index][3] = pPlane[3];
3061 /* Handle recording of state blocks */
3062 if (This->isRecordingState) {
3063 TRACE("Recording... not performing anything\n");
3071 /* Clip Plane settings are affected by the model view in OpenGL, the View transform in direct3d */
3072 glMatrixMode(GL_MODELVIEW);
3074 glLoadMatrixf((float *) &This->stateBlock->transforms[WINED3DTS_VIEW].u.m[0][0]);
3076 TRACE("Clipplane [%f,%f,%f,%f]\n",
3077 This->updateStateBlock->clipplane[Index][0],
3078 This->updateStateBlock->clipplane[Index][1],
3079 This->updateStateBlock->clipplane[Index][2],
3080 This->updateStateBlock->clipplane[Index][3]);
3081 glClipPlane(GL_CLIP_PLANE0 + Index, This->updateStateBlock->clipplane[Index]);
3082 checkGLcall("glClipPlane");
3090 static HRESULT WINAPI IWineD3DDeviceImpl_GetClipPlane(IWineD3DDevice *iface, DWORD Index, float *pPlane) {
3091 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3092 TRACE("(%p) : for idx %d\n", This, Index);
3094 /* Validate Index */
3095 if (Index >= GL_LIMITS(clipplanes)) {
3096 TRACE("Application has requested clipplane this device doesn't support\n");
3097 return WINED3DERR_INVALIDCALL;
3100 pPlane[0] = This->stateBlock->clipplane[Index][0];
3101 pPlane[1] = This->stateBlock->clipplane[Index][1];
3102 pPlane[2] = This->stateBlock->clipplane[Index][2];
3103 pPlane[3] = This->stateBlock->clipplane[Index][3];
3108 * Get / Set Clip Plane Status
3109 * WARNING: This code relies on the fact that D3DCLIPSTATUS8 == D3DCLIPSTATUS9
3111 static HRESULT WINAPI IWineD3DDeviceImpl_SetClipStatus(IWineD3DDevice *iface, CONST WINED3DCLIPSTATUS* pClipStatus) {
3112 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3113 FIXME("(%p) : stub\n", This);
3114 if (NULL == pClipStatus) {
3115 return WINED3DERR_INVALIDCALL;
3117 This->updateStateBlock->clip_status.ClipUnion = pClipStatus->ClipUnion;
3118 This->updateStateBlock->clip_status.ClipIntersection = pClipStatus->ClipIntersection;
3122 static HRESULT WINAPI IWineD3DDeviceImpl_GetClipStatus(IWineD3DDevice *iface, WINED3DCLIPSTATUS* pClipStatus) {
3123 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3124 FIXME("(%p) : stub\n", This);
3125 if (NULL == pClipStatus) {
3126 return WINED3DERR_INVALIDCALL;
3128 pClipStatus->ClipUnion = This->updateStateBlock->clip_status.ClipUnion;
3129 pClipStatus->ClipIntersection = This->updateStateBlock->clip_status.ClipIntersection;
3134 * Get / Set Material
3136 static HRESULT WINAPI IWineD3DDeviceImpl_SetMaterial(IWineD3DDevice *iface, CONST WINED3DMATERIAL* pMaterial) {
3137 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3139 This->updateStateBlock->changed.material = TRUE;
3140 This->updateStateBlock->set.material = TRUE;
3141 memcpy(&This->updateStateBlock->material, pMaterial, sizeof(WINED3DMATERIAL));
3143 /* Handle recording of state blocks */
3144 if (This->isRecordingState) {
3145 TRACE("Recording... not performing anything\n");
3150 TRACE("(%p) : Diffuse (%f,%f,%f,%f)\n", This, pMaterial->Diffuse.r, pMaterial->Diffuse.g,
3151 pMaterial->Diffuse.b, pMaterial->Diffuse.a);
3152 TRACE("(%p) : Ambient (%f,%f,%f,%f)\n", This, pMaterial->Ambient.r, pMaterial->Ambient.g,
3153 pMaterial->Ambient.b, pMaterial->Ambient.a);
3154 TRACE("(%p) : Specular (%f,%f,%f,%f)\n", This, pMaterial->Specular.r, pMaterial->Specular.g,
3155 pMaterial->Specular.b, pMaterial->Specular.a);
3156 TRACE("(%p) : Emissive (%f,%f,%f,%f)\n", This, pMaterial->Emissive.r, pMaterial->Emissive.g,
3157 pMaterial->Emissive.b, pMaterial->Emissive.a);
3158 TRACE("(%p) : Power (%f)\n", This, pMaterial->Power);
3160 glMaterialfv(GL_FRONT_AND_BACK, GL_AMBIENT, (float*) &This->updateStateBlock->material.Ambient);
3161 checkGLcall("glMaterialfv(GL_AMBIENT)");
3162 glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, (float*) &This->updateStateBlock->material.Diffuse);
3163 checkGLcall("glMaterialfv(GL_DIFFUSE)");
3165 /* Only change material color if specular is enabled, otherwise it is set to black */
3166 if (This->stateBlock->renderState[WINED3DRS_SPECULARENABLE]) {
3167 glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, (float*) &This->updateStateBlock->material.Specular);
3168 checkGLcall("glMaterialfv(GL_SPECULAR");
3170 float black[4] = {0.0f, 0.0f, 0.0f, 0.0f};
3171 glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, &black[0]);
3172 checkGLcall("glMaterialfv(GL_SPECULAR");
3174 glMaterialfv(GL_FRONT_AND_BACK, GL_EMISSION, (float*) &This->updateStateBlock->material.Emissive);
3175 checkGLcall("glMaterialfv(GL_EMISSION)");
3176 glMaterialf(GL_FRONT_AND_BACK, GL_SHININESS, This->updateStateBlock->material.Power);
3177 checkGLcall("glMaterialf(GL_SHININESS");
3183 static HRESULT WINAPI IWineD3DDeviceImpl_GetMaterial(IWineD3DDevice *iface, WINED3DMATERIAL* pMaterial) {
3184 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3185 memcpy(pMaterial, &This->updateStateBlock->material, sizeof (WINED3DMATERIAL));
3186 TRACE("(%p) : Diffuse (%f,%f,%f,%f)\n", This, pMaterial->Diffuse.r, pMaterial->Diffuse.g,
3187 pMaterial->Diffuse.b, pMaterial->Diffuse.a);
3188 TRACE("(%p) : Ambient (%f,%f,%f,%f)\n", This, pMaterial->Ambient.r, pMaterial->Ambient.g,
3189 pMaterial->Ambient.b, pMaterial->Ambient.a);
3190 TRACE("(%p) : Specular (%f,%f,%f,%f)\n", This, pMaterial->Specular.r, pMaterial->Specular.g,
3191 pMaterial->Specular.b, pMaterial->Specular.a);
3192 TRACE("(%p) : Emissive (%f,%f,%f,%f)\n", This, pMaterial->Emissive.r, pMaterial->Emissive.g,
3193 pMaterial->Emissive.b, pMaterial->Emissive.a);
3194 TRACE("(%p) : Power (%f)\n", This, pMaterial->Power);
3202 static HRESULT WINAPI IWineD3DDeviceImpl_SetIndices(IWineD3DDevice *iface, IWineD3DIndexBuffer* pIndexData,
3203 UINT BaseVertexIndex) {
3204 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3205 IWineD3DIndexBuffer *oldIdxs;
3207 TRACE("(%p) : Setting to %p, base %d\n", This, pIndexData, BaseVertexIndex);
3208 oldIdxs = This->updateStateBlock->pIndexData;
3210 This->updateStateBlock->changed.indices = TRUE;
3211 This->updateStateBlock->set.indices = TRUE;
3212 This->updateStateBlock->pIndexData = pIndexData;
3213 This->updateStateBlock->baseVertexIndex = BaseVertexIndex;
3215 /* Handle recording of state blocks */
3216 if (This->isRecordingState) {
3217 TRACE("Recording... not performing anything\n");
3221 if (NULL != pIndexData) {
3222 IWineD3DIndexBuffer_AddRef(pIndexData);
3224 if (NULL != oldIdxs) {
3225 IWineD3DIndexBuffer_Release(oldIdxs);
3230 static HRESULT WINAPI IWineD3DDeviceImpl_GetIndices(IWineD3DDevice *iface, IWineD3DIndexBuffer** ppIndexData, UINT* pBaseVertexIndex) {
3231 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3233 *ppIndexData = This->stateBlock->pIndexData;
3236 *pBaseVertexIndex = This->stateBlock->baseVertexIndex;
3237 TRACE("(%p) index data set to %p + %u\n", This, ppIndexData, This->stateBlock->baseVertexIndex);
3239 TRACE("(%p) No index data set\n", This);
3241 TRACE("Returning %p %d\n", *ppIndexData, *pBaseVertexIndex);
3247 * Get / Set Viewports
3249 static HRESULT WINAPI IWineD3DDeviceImpl_SetViewport(IWineD3DDevice *iface, CONST WINED3DVIEWPORT* pViewport) {
3250 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3252 TRACE("(%p)\n", This);
3253 This->updateStateBlock->changed.viewport = TRUE;
3254 This->updateStateBlock->set.viewport = TRUE;
3255 memcpy(&This->updateStateBlock->viewport, pViewport, sizeof(WINED3DVIEWPORT));
3257 /* Handle recording of state blocks */
3258 if (This->isRecordingState) {
3259 TRACE("Recording... not performing anything\n");
3262 This->viewport_changed = TRUE;
3266 TRACE("(%p) : x=%d, y=%d, wid=%d, hei=%d, minz=%f, maxz=%f\n", This,
3267 pViewport->X, pViewport->Y, pViewport->Width, pViewport->Height, pViewport->MinZ, pViewport->MaxZ);
3269 glDepthRange(pViewport->MinZ, pViewport->MaxZ);
3270 checkGLcall("glDepthRange");
3271 /* Note: GL requires lower left, DirectX supplies upper left */
3272 /* TODO: replace usage of renderTarget with context management */
3273 glViewport(pViewport->X,
3274 (((IWineD3DSurfaceImpl *)This->renderTarget)->currentDesc.Height - (pViewport->Y + pViewport->Height)),
3275 pViewport->Width, pViewport->Height);
3277 checkGLcall("glViewport");
3285 static HRESULT WINAPI IWineD3DDeviceImpl_GetViewport(IWineD3DDevice *iface, WINED3DVIEWPORT* pViewport) {
3286 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3287 TRACE("(%p)\n", This);
3288 memcpy(pViewport, &This->stateBlock->viewport, sizeof(WINED3DVIEWPORT));
3292 static void renderstate_stencil_twosided(
3293 IWineD3DDeviceImpl *This,
3300 GLint stencilPass ) {
3301 #if 0 /* Don't use OpenGL 2.0 calls for now */
3302 if(GL_EXTCALL(glStencilFuncSeparate) && GL_EXTCALL(glStencilOpSeparate)) {
3303 GL_EXTCALL(glStencilFuncSeparate(face, func, ref, mask));
3304 checkGLcall("glStencilFuncSeparate(...)");
3305 GL_EXTCALL(glStencilOpSeparate(face, stencilFail, depthFail, stencilPass));
3306 checkGLcall("glStencilOpSeparate(...)");
3310 if(GL_SUPPORT(EXT_STENCIL_TWO_SIDE)) {
3311 glEnable(GL_STENCIL_TEST_TWO_SIDE_EXT);
3312 checkGLcall("glEnable(GL_STENCIL_TEST_TWO_SIDE_EXT)");
3313 GL_EXTCALL(glActiveStencilFaceEXT(face));
3314 checkGLcall("glActiveStencilFaceEXT(...)");
3315 glStencilFunc(func, ref, mask);
3316 checkGLcall("glStencilFunc(...)");
3317 glStencilOp(stencilFail, depthFail, stencilPass);
3318 checkGLcall("glStencilOp(...)");
3319 } else if(GL_SUPPORT(ATI_SEPARATE_STENCIL)) {
3320 GL_EXTCALL(glStencilFuncSeparateATI(face, func, ref, mask));
3321 checkGLcall("glStencilFuncSeparateATI(...)");
3322 GL_EXTCALL(glStencilOpSeparateATI(face, stencilFail, depthFail, stencilPass));
3323 checkGLcall("glStencilOpSeparateATI(...)");
3325 ERR("Separate (two sided) stencil not supported on this version of opengl. Caps weren't honored?\n");
3329 static void renderstate_stencil(IWineD3DDeviceImpl *This, WINED3DRENDERSTATETYPE State, DWORD Value) {
3330 DWORD onesided_enable = FALSE;
3331 DWORD twosided_enable = FALSE;
3332 GLint func = GL_ALWAYS;
3333 GLint func_ccw = GL_ALWAYS;
3336 GLint stencilFail = GL_KEEP;
3337 GLint depthFail = GL_KEEP;
3338 GLint stencilPass = GL_KEEP;
3339 GLint stencilFail_ccw = GL_KEEP;
3340 GLint depthFail_ccw = GL_KEEP;
3341 GLint stencilPass_ccw = GL_KEEP;
3343 if( This->stateBlock->set.renderState[WINED3DRS_STENCILENABLE] )
3344 onesided_enable = This->stateBlock->renderState[WINED3DRS_STENCILENABLE];
3345 if( This->stateBlock->set.renderState[WINED3DRS_TWOSIDEDSTENCILMODE] )
3346 twosided_enable = This->stateBlock->renderState[WINED3DRS_TWOSIDEDSTENCILMODE];
3347 if( This->stateBlock->set.renderState[WINED3DRS_STENCILFUNC] )
3348 if( !( func = CompareFunc(This->stateBlock->renderState[WINED3DRS_STENCILFUNC]) ) )
3350 if( This->stateBlock->set.renderState[WINED3DRS_CCW_STENCILFUNC] )
3351 if( !( func_ccw = CompareFunc(This->stateBlock->renderState[WINED3DRS_CCW_STENCILFUNC]) ) )
3353 if( This->stateBlock->set.renderState[WINED3DRS_STENCILREF] )
3354 ref = This->stateBlock->renderState[WINED3DRS_STENCILREF];
3355 if( This->stateBlock->set.renderState[WINED3DRS_STENCILMASK] )
3356 mask = This->stateBlock->renderState[WINED3DRS_STENCILMASK];
3357 if( This->stateBlock->set.renderState[WINED3DRS_STENCILFAIL] )
3358 stencilFail = StencilOp(This->stateBlock->renderState[WINED3DRS_STENCILFAIL]);
3359 if( This->stateBlock->set.renderState[WINED3DRS_STENCILZFAIL] )
3360 depthFail = StencilOp(This->stateBlock->renderState[WINED3DRS_STENCILZFAIL]);
3361 if( This->stateBlock->set.renderState[WINED3DRS_STENCILPASS] )
3362 stencilPass = StencilOp(This->stateBlock->renderState[WINED3DRS_STENCILPASS]);
3363 if( This->stateBlock->set.renderState[WINED3DRS_CCW_STENCILFAIL] )
3364 stencilFail_ccw = StencilOp(This->stateBlock->renderState[WINED3DRS_CCW_STENCILFAIL]);
3365 if( This->stateBlock->set.renderState[WINED3DRS_CCW_STENCILZFAIL] )
3366 depthFail_ccw = StencilOp(This->stateBlock->renderState[WINED3DRS_CCW_STENCILZFAIL]);
3367 if( This->stateBlock->set.renderState[WINED3DRS_CCW_STENCILPASS] )
3368 stencilPass_ccw = StencilOp(This->stateBlock->renderState[WINED3DRS_CCW_STENCILPASS]);
3370 TRACE("(onesided %d, twosided %d, ref %x, mask %x, \
3371 GL_FRONT: func: %x, fail %x, zfail %x, zpass %x \
3372 GL_BACK: func: %x, fail %x, zfail %x, zpass %x )\n",
3373 onesided_enable, twosided_enable, ref, mask,
3374 func, stencilFail, depthFail, stencilPass,
3375 func_ccw, stencilFail_ccw, depthFail_ccw, stencilPass_ccw);
3377 if (twosided_enable) {
3378 renderstate_stencil_twosided(This, GL_FRONT, func, ref, mask, stencilFail, depthFail, stencilPass);
3379 renderstate_stencil_twosided(This, GL_BACK, func_ccw, ref, mask, stencilFail_ccw, depthFail_ccw, stencilPass_ccw);
3381 if (onesided_enable) {
3382 glEnable(GL_STENCIL_TEST);
3383 checkGLcall("glEnable GL_STENCIL_TEST");
3384 glStencilFunc(func, ref, mask);
3385 checkGLcall("glStencilFunc(...)");
3386 glStencilOp(stencilFail, depthFail, stencilPass);
3387 checkGLcall("glStencilOp(...)");
3389 glDisable(GL_STENCIL_TEST);
3390 checkGLcall("glDisable GL_STENCIL_TEST");
3396 * Get / Set Render States
3397 * TODO: Verify against dx9 definitions
3399 static HRESULT WINAPI IWineD3DDeviceImpl_SetRenderState(IWineD3DDevice *iface, WINED3DRENDERSTATETYPE State, DWORD Value) {
3401 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3402 DWORD OldValue = This->stateBlock->renderState[State];
3404 /* Simple way of referring to either a DWORD or a 4 byte float */
3410 TRACE("(%p)->state = %s(%d), value = %d\n", This, debug_d3drenderstate(State), State, Value);
3411 This->updateStateBlock->changed.renderState[State] = TRUE;
3412 This->updateStateBlock->set.renderState[State] = TRUE;
3413 This->updateStateBlock->renderState[State] = Value;
3415 /* Handle recording of state blocks */
3416 if (This->isRecordingState) {
3417 TRACE("Recording... not performing anything\n");
3424 case WINED3DRS_FILLMODE :
3425 switch ((WINED3DFILLMODE) Value) {
3426 case WINED3DFILL_POINT : glPolygonMode(GL_FRONT_AND_BACK, GL_POINT); break;
3427 case WINED3DFILL_WIREFRAME : glPolygonMode(GL_FRONT_AND_BACK, GL_LINE); break;
3428 case WINED3DFILL_SOLID : glPolygonMode(GL_FRONT_AND_BACK, GL_FILL); break;
3430 FIXME("Unrecognized WINED3DRS_FILLMODE value %d\n", Value);
3432 checkGLcall("glPolygonMode (fillmode)");
3435 case WINED3DRS_LIGHTING :
3437 glEnable(GL_LIGHTING);
3438 checkGLcall("glEnable GL_LIGHTING");
3440 glDisable(GL_LIGHTING);
3441 checkGLcall("glDisable GL_LIGHTING");
3445 case WINED3DRS_ZENABLE :
3446 switch ((WINED3DZBUFFERTYPE) Value) {
3447 case WINED3DZB_FALSE:
3448 glDisable(GL_DEPTH_TEST);
3449 checkGLcall("glDisable GL_DEPTH_TEST");
3451 case WINED3DZB_TRUE:
3452 glEnable(GL_DEPTH_TEST);
3453 checkGLcall("glEnable GL_DEPTH_TEST");
3455 case WINED3DZB_USEW:
3456 glEnable(GL_DEPTH_TEST);
3457 checkGLcall("glEnable GL_DEPTH_TEST");
3458 FIXME("W buffer is not well handled\n");
3461 FIXME("Unrecognized WINED3DZBUFFERTYPE value %d\n", Value);
3465 case WINED3DRS_CULLMODE :
3467 /* If we are culling "back faces with clockwise vertices" then
3468 set front faces to be counter clockwise and enable culling
3470 switch ((WINED3DCULL) Value) {
3471 case WINED3DCULL_NONE:
3472 glDisable(GL_CULL_FACE);
3473 checkGLcall("glDisable GL_CULL_FACE");
3475 case WINED3DCULL_CW:
3476 glEnable(GL_CULL_FACE);
3477 checkGLcall("glEnable GL_CULL_FACE");
3478 if (This->render_offscreen) {
3480 checkGLcall("glFrontFace GL_CW");
3482 glFrontFace(GL_CCW);
3483 checkGLcall("glFrontFace GL_CCW");
3485 glCullFace(GL_BACK);
3487 case WINED3DCULL_CCW:
3488 glEnable(GL_CULL_FACE);
3489 checkGLcall("glEnable GL_CULL_FACE");
3490 if (This->render_offscreen) {
3491 glFrontFace(GL_CCW);
3492 checkGLcall("glFrontFace GL_CCW");
3495 checkGLcall("glFrontFace GL_CW");
3497 glCullFace(GL_BACK);
3500 FIXME("Unrecognized/Unhandled WINED3DCULL value %d\n", Value);
3504 case WINED3DRS_SHADEMODE :
3505 switch ((WINED3DSHADEMODE) Value) {
3506 case WINED3DSHADE_FLAT:
3507 glShadeModel(GL_FLAT);
3508 checkGLcall("glShadeModel");
3510 case WINED3DSHADE_GOURAUD:
3511 glShadeModel(GL_SMOOTH);
3512 checkGLcall("glShadeModel");
3514 case WINED3DSHADE_PHONG:
3515 FIXME("WINED3DSHADE_PHONG isn't supported\n");
3518 FIXME("Unrecognized/Unhandled WINED3DSHADEMODE value %d\n", Value);
3522 case WINED3DRS_DITHERENABLE :
3524 glEnable(GL_DITHER);
3525 checkGLcall("glEnable GL_DITHER");
3527 glDisable(GL_DITHER);
3528 checkGLcall("glDisable GL_DITHER");
3532 case WINED3DRS_ZWRITEENABLE :
3535 checkGLcall("glDepthMask");
3538 checkGLcall("glDepthMask");
3542 case WINED3DRS_ZFUNC :
3544 int glParm = CompareFunc(Value);
3547 glDepthFunc(glParm);
3548 checkGLcall("glDepthFunc");
3553 case WINED3DRS_AMBIENT :
3556 D3DCOLORTOGLFLOAT4(Value, col);
3557 TRACE("Setting ambient to (%f,%f,%f,%f)\n", col[0], col[1], col[2], col[3]);
3558 glLightModelfv(GL_LIGHT_MODEL_AMBIENT, col);
3559 checkGLcall("glLightModel for MODEL_AMBIENT");
3564 case WINED3DRS_ALPHABLENDENABLE :
3567 checkGLcall("glEnable GL_BLEND");
3569 glDisable(GL_BLEND);
3570 checkGLcall("glDisable GL_BLEND");
3574 case WINED3DRS_SRCBLEND :
3575 case WINED3DRS_DESTBLEND :
3577 int newVal = GL_ZERO;
3579 case WINED3DBLEND_ZERO : newVal = GL_ZERO; break;
3580 case WINED3DBLEND_ONE : newVal = GL_ONE; break;
3581 case WINED3DBLEND_SRCCOLOR : newVal = GL_SRC_COLOR; break;
3582 case WINED3DBLEND_INVSRCCOLOR : newVal = GL_ONE_MINUS_SRC_COLOR; break;
3583 case WINED3DBLEND_SRCALPHA : newVal = GL_SRC_ALPHA; break;
3584 case WINED3DBLEND_INVSRCALPHA : newVal = GL_ONE_MINUS_SRC_ALPHA; break;
3585 case WINED3DBLEND_DESTALPHA : newVal = GL_DST_ALPHA; break;
3586 case WINED3DBLEND_INVDESTALPHA : newVal = GL_ONE_MINUS_DST_ALPHA; break;
3587 case WINED3DBLEND_DESTCOLOR : newVal = GL_DST_COLOR; break;
3588 case WINED3DBLEND_INVDESTCOLOR : newVal = GL_ONE_MINUS_DST_COLOR; break;
3589 case WINED3DBLEND_SRCALPHASAT : newVal = GL_SRC_ALPHA_SATURATE; break;
3591 case WINED3DBLEND_BOTHSRCALPHA : newVal = GL_SRC_ALPHA;
3592 This->srcBlend = newVal;
3593 This->dstBlend = newVal;
3596 case WINED3DBLEND_BOTHINVSRCALPHA : newVal = GL_ONE_MINUS_SRC_ALPHA;
3597 This->srcBlend = newVal;
3598 This->dstBlend = newVal;
3600 case WINED3DBLEND_BLENDFACTOR : newVal = GL_CONSTANT_COLOR; break;
3601 case WINED3DBLEND_INVBLENDFACTOR : newVal = GL_ONE_MINUS_CONSTANT_COLOR; break;
3603 FIXME("Unrecognized src/dest blend value %d (%d)\n", Value, State);
3606 if (State == WINED3DRS_SRCBLEND) This->srcBlend = newVal;
3607 if (State == WINED3DRS_DESTBLEND) This->dstBlend = newVal;
3608 TRACE("glBlendFunc src=%x, dst=%x\n", This->srcBlend, This->dstBlend);
3609 glBlendFunc(This->srcBlend, This->dstBlend);
3611 checkGLcall("glBlendFunc");
3615 case WINED3DRS_ALPHATESTENABLE :
3616 case WINED3DRS_ALPHAFUNC :
3617 case WINED3DRS_ALPHAREF :
3618 case WINED3DRS_COLORKEYENABLE :
3622 BOOL enable_ckey = FALSE;
3624 IWineD3DSurfaceImpl *surf;
3626 /* Find out if the texture on the first stage has a ckey set */
3627 if(This->stateBlock->textures[0]) {
3628 surf = (IWineD3DSurfaceImpl *) ((IWineD3DTextureImpl *)This->stateBlock->textures[0])->surfaces[0];
3629 if(surf->CKeyFlags & DDSD_CKSRCBLT) enable_ckey = TRUE;
3632 if (This->stateBlock->renderState[WINED3DRS_ALPHATESTENABLE] ||
3633 (This->stateBlock->renderState[WINED3DRS_COLORKEYENABLE] && enable_ckey)) {
3634 glEnable(GL_ALPHA_TEST);
3635 checkGLcall("glEnable GL_ALPHA_TEST");
3637 glDisable(GL_ALPHA_TEST);
3638 checkGLcall("glDisable GL_ALPHA_TEST");
3639 /* Alpha test is disabled, don't bother setting the params - it will happen on the next
3645 if(This->stateBlock->renderState[WINED3DRS_COLORKEYENABLE] && enable_ckey) {
3646 glParm = GL_NOTEQUAL;
3649 ref = ((float) This->stateBlock->renderState[WINED3DRS_ALPHAREF]) / 255.0f;
3650 glParm = CompareFunc(This->stateBlock->renderState[WINED3DRS_ALPHAFUNC]);
3653 This->alphafunc = glParm;
3654 glAlphaFunc(glParm, ref);
3655 checkGLcall("glAlphaFunc");
3660 case WINED3DRS_CLIPPLANEENABLE :
3661 case WINED3DRS_CLIPPING :
3663 /* Ensure we only do the changed clip planes */
3664 DWORD enable = 0xFFFFFFFF;
3665 DWORD disable = 0x00000000;
3667 /* If enabling / disabling all */
3668 if (State == WINED3DRS_CLIPPING) {
3670 enable = This->stateBlock->renderState[WINED3DRS_CLIPPLANEENABLE];
3673 disable = This->stateBlock->renderState[WINED3DRS_CLIPPLANEENABLE];
3677 enable = Value & ~OldValue;
3678 disable = ~Value & OldValue;
3681 if (enable & WINED3DCLIPPLANE0) { glEnable(GL_CLIP_PLANE0); checkGLcall("glEnable(clip plane 0)"); }
3682 if (enable & WINED3DCLIPPLANE1) { glEnable(GL_CLIP_PLANE1); checkGLcall("glEnable(clip plane 1)"); }
3683 if (enable & WINED3DCLIPPLANE2) { glEnable(GL_CLIP_PLANE2); checkGLcall("glEnable(clip plane 2)"); }
3684 if (enable & WINED3DCLIPPLANE3) { glEnable(GL_CLIP_PLANE3); checkGLcall("glEnable(clip plane 3)"); }
3685 if (enable & WINED3DCLIPPLANE4) { glEnable(GL_CLIP_PLANE4); checkGLcall("glEnable(clip plane 4)"); }
3686 if (enable & WINED3DCLIPPLANE5) { glEnable(GL_CLIP_PLANE5); checkGLcall("glEnable(clip plane 5)"); }
3688 if (disable & WINED3DCLIPPLANE0) { glDisable(GL_CLIP_PLANE0); checkGLcall("glDisable(clip plane 0)"); }
3689 if (disable & WINED3DCLIPPLANE1) { glDisable(GL_CLIP_PLANE1); checkGLcall("glDisable(clip plane 1)"); }
3690 if (disable & WINED3DCLIPPLANE2) { glDisable(GL_CLIP_PLANE2); checkGLcall("glDisable(clip plane 2)"); }
3691 if (disable & WINED3DCLIPPLANE3) { glDisable(GL_CLIP_PLANE3); checkGLcall("glDisable(clip plane 3)"); }
3692 if (disable & WINED3DCLIPPLANE4) { glDisable(GL_CLIP_PLANE4); checkGLcall("glDisable(clip plane 4)"); }
3693 if (disable & WINED3DCLIPPLANE5) { glDisable(GL_CLIP_PLANE5); checkGLcall("glDisable(clip plane 5)"); }
3695 /** update clipping status */
3697 This->stateBlock->clip_status.ClipUnion = 0;
3698 This->stateBlock->clip_status.ClipIntersection = 0xFFFFFFFF;
3700 This->stateBlock->clip_status.ClipUnion = 0;
3701 This->stateBlock->clip_status.ClipIntersection = 0;
3706 case WINED3DRS_BLENDOP :
3708 int glParm = GL_FUNC_ADD;
3710 switch ((WINED3DBLENDOP) Value) {
3711 case WINED3DBLENDOP_ADD : glParm = GL_FUNC_ADD; break;
3712 case WINED3DBLENDOP_SUBTRACT : glParm = GL_FUNC_SUBTRACT; break;
3713 case WINED3DBLENDOP_REVSUBTRACT : glParm = GL_FUNC_REVERSE_SUBTRACT; break;
3714 case WINED3DBLENDOP_MIN : glParm = GL_MIN; break;
3715 case WINED3DBLENDOP_MAX : glParm = GL_MAX; break;
3717 FIXME("Unrecognized/Unhandled WINED3DBLENDOP value %d\n", Value);
3720 if(GL_SUPPORT(EXT_BLEND_MINMAX)) {
3721 TRACE("glBlendEquation(%x)\n", glParm);
3722 GL_EXTCALL(glBlendEquation(glParm));
3723 checkGLcall("glBlendEquation");
3725 WARN("Unsupported in local OpenGL implementation: glBlendEquation\n");
3730 case WINED3DRS_TEXTUREFACTOR :
3734 /* Note the texture color applies to all textures whereas
3735 GL_TEXTURE_ENV_COLOR applies to active only */
3737 D3DCOLORTOGLFLOAT4(Value, col);
3739 if (!GL_SUPPORT(NV_REGISTER_COMBINERS)) {
3740 /* And now the default texture color as well */
3741 for (i = 0; i < GL_LIMITS(texture_stages); i++) {
3742 /* Note the WINED3DRS value applies to all textures, but GL has one
3743 per texture, so apply it now ready to be used! */
3744 if (GL_SUPPORT(ARB_MULTITEXTURE)) {
3745 GL_EXTCALL(glActiveTextureARB(GL_TEXTURE0_ARB + i));
3746 checkGLcall("glActiveTextureARB");
3748 FIXME("Program using multiple concurrent textures which this opengl implementation doesn't support\n");
3751 glTexEnvfv(GL_TEXTURE_ENV, GL_TEXTURE_ENV_COLOR, &col[0]);
3752 checkGLcall("glTexEnvfv(GL_TEXTURE_ENV, GL_TEXTURE_ENV_COLOR, color);");
3758 case WINED3DRS_SPECULARENABLE :
3760 /* Originally this used glLightModeli(GL_LIGHT_MODEL_COLOR_CONTROL,GL_SEPARATE_SPECULAR_COLOR)
3761 and (GL_LIGHT_MODEL_COLOR_CONTROL,GL_SINGLE_COLOR) to swap between enabled/disabled
3762 specular color. This is wrong:
3763 Separate specular color means the specular colour is maintained separately, whereas
3764 single color means it is merged in. However in both cases they are being used to
3766 To disable specular color, set it explicitly to black and turn off GL_COLOR_SUM_EXT
3767 NOTE: If not supported don't give FIXMEs the impact is really minimal and very few people are
3771 * If register combiners are enabled, enabling / disabling GL_COLOR_SUM has no effect.
3772 * Instead, we need to setup the FinalCombiner properly.
3774 * The default setup for the FinalCombiner is:
3776 * <variable> <input> <mapping> <usage>
3777 * GL_VARIABLE_A_NV GL_FOG, GL_UNSIGNED_IDENTITY_NV GL_ALPHA
3778 * GL_VARIABLE_B_NV GL_SPARE0_PLUS_SECONDARY_COLOR_NV GL_UNSIGNED_IDENTITY_NV GL_RGB
3779 * GL_VARIABLE_C_NV GL_FOG GL_UNSIGNED_IDENTITY_NV GL_RGB
3780 * GL_VARIABLE_D_NV GL_ZERO GL_UNSIGNED_IDENTITY_NV GL_RGB
3781 * GL_VARIABLE_E_NV GL_ZERO GL_UNSIGNED_IDENTITY_NV GL_RGB
3782 * GL_VARIABLE_F_NV GL_ZERO GL_UNSIGNED_IDENTITY_NV GL_RGB
3783 * GL_VARIABLE_G_NV GL_SPARE0_NV GL_UNSIGNED_IDENTITY_NV GL_ALPHA
3785 * That's pretty much fine as it is, except for variable B, which needs to take
3786 * either GL_SPARE0_PLUS_SECONDARY_COLOR_NV or GL_SPARE0_NV, depending on
3787 * whether WINED3DRS_SPECULARENABLE is enabled or not.
3791 glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, (float*) &This->updateStateBlock->material.Specular);
3792 checkGLcall("glMaterialfv");
3793 if (GL_SUPPORT(EXT_SECONDARY_COLOR)) {
3794 glEnable(GL_COLOR_SUM_EXT);
3796 TRACE("Specular colors cannot be enabled in this version of opengl\n");
3798 checkGLcall("glEnable(GL_COLOR_SUM)");
3800 if (GL_SUPPORT(NV_REGISTER_COMBINERS)) {
3801 GL_EXTCALL(glFinalCombinerInputNV(GL_VARIABLE_B_NV, GL_SPARE0_PLUS_SECONDARY_COLOR_NV, GL_UNSIGNED_IDENTITY_NV, GL_RGB));
3802 checkGLcall("glFinalCombinerInputNV()");
3805 float black[4] = {0.0f, 0.0f, 0.0f, 0.0f};
3807 /* for the case of enabled lighting: */
3808 glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, &black[0]);
3809 checkGLcall("glMaterialfv");
3811 /* for the case of disabled lighting: */
3812 if (GL_SUPPORT(EXT_SECONDARY_COLOR)) {
3813 glDisable(GL_COLOR_SUM_EXT);
3815 TRACE("Specular colors cannot be disabled in this version of opengl\n");
3817 checkGLcall("glDisable(GL_COLOR_SUM)");
3819 if (GL_SUPPORT(NV_REGISTER_COMBINERS)) {
3820 GL_EXTCALL(glFinalCombinerInputNV(GL_VARIABLE_B_NV, GL_SPARE0_NV, GL_UNSIGNED_IDENTITY_NV, GL_RGB));
3821 checkGLcall("glFinalCombinerInputNV()");
3827 case WINED3DRS_STENCILENABLE :
3828 case WINED3DRS_TWOSIDEDSTENCILMODE :
3829 case WINED3DRS_STENCILFUNC :
3830 case WINED3DRS_CCW_STENCILFUNC :
3831 case WINED3DRS_STENCILREF :
3832 case WINED3DRS_STENCILMASK :
3833 case WINED3DRS_STENCILFAIL :
3834 case WINED3DRS_STENCILZFAIL :
3835 case WINED3DRS_STENCILPASS :
3836 case WINED3DRS_CCW_STENCILFAIL :
3837 case WINED3DRS_CCW_STENCILZFAIL :
3838 case WINED3DRS_CCW_STENCILPASS :
3839 renderstate_stencil(This, State, Value);
3841 case WINED3DRS_STENCILWRITEMASK :
3843 glStencilMask(Value);
3844 TRACE("glStencilMask(%u)\n", Value);
3845 checkGLcall("glStencilMask");
3849 case WINED3DRS_FOGENABLE :
3853 checkGLcall("glEnable GL_FOG");
3856 checkGLcall("glDisable GL_FOG");
3861 case WINED3DRS_RANGEFOGENABLE :
3864 TRACE("Enabled RANGEFOG\n");
3866 TRACE("Disabled RANGEFOG\n");
3871 case WINED3DRS_FOGCOLOR :
3874 D3DCOLORTOGLFLOAT4(Value, col);
3875 /* Set the default alpha blend color */
3876 glFogfv(GL_FOG_COLOR, &col[0]);
3877 checkGLcall("glFog GL_FOG_COLOR");
3881 case WINED3DRS_FOGTABLEMODE :
3882 case WINED3DRS_FOGVERTEXMODE :
3884 /* 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." */
3885 if(This->stateBlock->renderState[WINED3DRS_FOGTABLEMODE] == WINED3DFOG_NONE) {
3886 glHint(GL_FOG_HINT, GL_FASTEST);
3887 checkGLcall("glHint(GL_FOG_HINT, GL_FASTEST)");
3888 switch (This->stateBlock->renderState[WINED3DRS_FOGVERTEXMODE]) {
3889 /* Processed vertices have their fog factor stored in the specular value. Fall too the none case.
3890 * If we are drawing untransformed vertices atm, d3ddevice_set_ortho will update the fog
3892 case WINED3DFOG_EXP: {
3893 if(!This->last_was_rhw) {
3894 glFogi(GL_FOG_MODE, GL_EXP);
3895 checkGLcall("glFogi(GL_FOG_MODE, GL_EXP");
3896 if(GL_SUPPORT(EXT_FOG_COORD)) {
3897 glFogi(GL_FOG_COORDINATE_SOURCE_EXT, GL_FRAGMENT_DEPTH_EXT);
3898 checkGLcall("glFogi(GL_FOG_COORDINATE_SOURCE_EXT, GL_FRAGMENT_DEPTH_EXT");
3899 IWineD3DDevice_SetRenderState(iface, WINED3DRS_FOGSTART, This->stateBlock->renderState[WINED3DRS_FOGSTART]);
3900 IWineD3DDevice_SetRenderState(iface, WINED3DRS_FOGEND, This->stateBlock->renderState[WINED3DRS_FOGEND]);
3905 case WINED3DFOG_EXP2: {
3906 if(!This->last_was_rhw) {
3907 glFogi(GL_FOG_MODE, GL_EXP2);
3908 checkGLcall("glFogi(GL_FOG_MODE, GL_EXP2");
3909 if(GL_SUPPORT(EXT_FOG_COORD)) {
3910 glFogi(GL_FOG_COORDINATE_SOURCE_EXT, GL_FRAGMENT_DEPTH_EXT);
3911 checkGLcall("glFogi(GL_FOG_COORDINATE_SOURCE_EXT, GL_FRAGMENT_DEPTH_EXT");
3912 IWineD3DDevice_SetRenderState(iface, WINED3DRS_FOGSTART, This->stateBlock->renderState[WINED3DRS_FOGSTART]);
3913 IWineD3DDevice_SetRenderState(iface, WINED3DRS_FOGEND, This->stateBlock->renderState[WINED3DRS_FOGEND]);
3918 case WINED3DFOG_LINEAR: {
3919 if(!This->last_was_rhw) {
3920 glFogi(GL_FOG_MODE, GL_LINEAR);
3921 checkGLcall("glFogi(GL_FOG_MODE, GL_LINEAR");
3922 if(GL_SUPPORT(EXT_FOG_COORD)) {
3923 glFogi(GL_FOG_COORDINATE_SOURCE_EXT, GL_FRAGMENT_DEPTH_EXT);
3924 checkGLcall("glFogi(GL_FOG_COORDINATE_SOURCE_EXT, GL_FRAGMENT_DEPTH_EXT");
3925 IWineD3DDevice_SetRenderState(iface, WINED3DRS_FOGSTART, This->stateBlock->renderState[WINED3DRS_FOGSTART]);
3926 IWineD3DDevice_SetRenderState(iface, WINED3DRS_FOGEND, This->stateBlock->renderState[WINED3DRS_FOGEND]);
3931 case WINED3DFOG_NONE: {
3932 /* Both are none? According to msdn the alpha channel of the specular
3933 * color contains a fog factor. Set it in drawStridedSlow.
3934 * Same happens with Vertexfog on transformed vertices
3936 if(GL_SUPPORT(EXT_FOG_COORD)) {
3937 glFogi(GL_FOG_COORDINATE_SOURCE_EXT, GL_FOG_COORDINATE_EXT);
3938 checkGLcall("glFogi(GL_FOG_COORDINATE_SOURCE_EXT, GL_FOG_COORDINATE_EXT)\n");
3939 glFogi(GL_FOG_MODE, GL_LINEAR);
3940 checkGLcall("glFogi(GL_FOG_MODE, GL_LINEAR)");
3941 glFogf(GL_FOG_START, (float) 0xff);
3942 checkGLcall("glFogfv GL_FOG_START");
3943 glFogf(GL_FOG_END, 0.0);
3944 checkGLcall("glFogfv GL_FOG_END");
3946 /* Disable GL fog, handle this in software in drawStridedSlow */
3948 checkGLcall("glDisable(GL_FOG)");
3952 default: FIXME("Unexpected WINED3DRS_FOGVERTEXMODE %d\n", This->stateBlock->renderState[WINED3DRS_FOGVERTEXMODE]);
3955 glHint(GL_FOG_HINT, GL_NICEST);
3956 checkGLcall("glHint(GL_FOG_HINT, GL_NICEST)");
3957 switch (This->stateBlock->renderState[WINED3DRS_FOGTABLEMODE]) {
3958 case WINED3DFOG_EXP:
3959 glFogi(GL_FOG_MODE, GL_EXP);
3960 checkGLcall("glFogi(GL_FOG_MODE, GL_EXP");
3961 if(GL_SUPPORT(EXT_FOG_COORD)) {
3962 glFogi(GL_FOG_COORDINATE_SOURCE_EXT, GL_FRAGMENT_DEPTH_EXT);
3963 checkGLcall("glFogi(GL_FOG_COORDINATE_SOURCE_EXT, GL_FRAGMENT_DEPTH_EXT");
3964 IWineD3DDevice_SetRenderState(iface, WINED3DRS_FOGSTART, This->stateBlock->renderState[WINED3DRS_FOGSTART]);
3965 IWineD3DDevice_SetRenderState(iface, WINED3DRS_FOGEND, This->stateBlock->renderState[WINED3DRS_FOGEND]);
3968 case WINED3DFOG_EXP2:
3969 glFogi(GL_FOG_MODE, GL_EXP2);
3970 checkGLcall("glFogi(GL_FOG_MODE, GL_EXP2");
3971 if(GL_SUPPORT(EXT_FOG_COORD)) {
3972 glFogi(GL_FOG_COORDINATE_SOURCE_EXT, GL_FRAGMENT_DEPTH_EXT);
3973 checkGLcall("glFogi(GL_FOG_COORDINATE_SOURCE_EXT, GL_FRAGMENT_DEPTH_EXT");
3974 IWineD3DDevice_SetRenderState(iface, WINED3DRS_FOGSTART, This->stateBlock->renderState[WINED3DRS_FOGSTART]);
3975 IWineD3DDevice_SetRenderState(iface, WINED3DRS_FOGEND, This->stateBlock->renderState[WINED3DRS_FOGEND]);
3978 case WINED3DFOG_LINEAR:
3979 glFogi(GL_FOG_MODE, GL_LINEAR);
3980 checkGLcall("glFogi(GL_FOG_MODE, GL_LINEAR");
3981 if(GL_SUPPORT(EXT_FOG_COORD)) {
3982 glFogi(GL_FOG_COORDINATE_SOURCE_EXT, GL_FRAGMENT_DEPTH_EXT);
3983 checkGLcall("glFogi(GL_FOG_COORDINATE_SOURCE_EXT, GL_FRAGMENT_DEPTH_EXT");
3984 IWineD3DDevice_SetRenderState(iface, WINED3DRS_FOGSTART, This->stateBlock->renderState[WINED3DRS_FOGSTART]);
3985 IWineD3DDevice_SetRenderState(iface, WINED3DRS_FOGEND, This->stateBlock->renderState[WINED3DRS_FOGEND]);
3988 case WINED3DFOG_NONE:
3989 default: /* Won't happen */
3990 FIXME("Unexpected WINED3DRS_FOGTABLEMODE %d\n", This->stateBlock->renderState[WINED3DRS_FOGTABLEMODE]);
3993 if (GL_SUPPORT(NV_FOG_DISTANCE)) {
3994 glFogi(GL_FOG_DISTANCE_MODE_NV, GL_EYE_PLANE_ABSOLUTE_NV);
3999 case WINED3DRS_FOGSTART :
4002 glFogfv(GL_FOG_START, &tmpvalue.f);
4003 checkGLcall("glFogf(GL_FOG_START, (float) Value)");
4004 TRACE("Fog Start == %f\n", tmpvalue.f);
4008 case WINED3DRS_FOGEND :
4011 glFogfv(GL_FOG_END, &tmpvalue.f);
4012 checkGLcall("glFogf(GL_FOG_END, (float) Value)");
4013 TRACE("Fog End == %f\n", tmpvalue.f);
4017 case WINED3DRS_FOGDENSITY :
4020 glFogfv(GL_FOG_DENSITY, &tmpvalue.f);
4021 checkGLcall("glFogf(GL_FOG_DENSITY, (float) Value)");
4025 case WINED3DRS_VERTEXBLEND :
4027 This->updateStateBlock->vertex_blend = (WINED3DVERTEXBLENDFLAGS) Value;
4028 TRACE("Vertex Blending state to %d\n", Value);
4032 case WINED3DRS_TWEENFACTOR :
4035 This->updateStateBlock->tween_factor = tmpvalue.f;
4036 TRACE("Vertex Blending Tween Factor to %f\n", This->updateStateBlock->tween_factor);
4040 case WINED3DRS_INDEXEDVERTEXBLENDENABLE :
4042 TRACE("Indexed Vertex Blend Enable to %u\n", (BOOL) Value);
4046 case WINED3DRS_COLORVERTEX :
4047 case WINED3DRS_DIFFUSEMATERIALSOURCE :
4048 case WINED3DRS_SPECULARMATERIALSOURCE :
4049 case WINED3DRS_AMBIENTMATERIALSOURCE :
4050 case WINED3DRS_EMISSIVEMATERIALSOURCE :
4052 GLenum Parm = GL_AMBIENT_AND_DIFFUSE;
4054 if (This->stateBlock->renderState[WINED3DRS_COLORVERTEX]) {
4055 TRACE("diff %d, amb %d, emis %d, spec %d\n",
4056 This->stateBlock->renderState[WINED3DRS_DIFFUSEMATERIALSOURCE],
4057 This->stateBlock->renderState[WINED3DRS_AMBIENTMATERIALSOURCE],
4058 This->stateBlock->renderState[WINED3DRS_EMISSIVEMATERIALSOURCE],
4059 This->stateBlock->renderState[WINED3DRS_SPECULARMATERIALSOURCE]);
4061 if (This->stateBlock->renderState[WINED3DRS_DIFFUSEMATERIALSOURCE] == WINED3DMCS_COLOR1) {
4062 if (This->stateBlock->renderState[WINED3DRS_AMBIENTMATERIALSOURCE] == WINED3DMCS_COLOR1) {
4063 Parm = GL_AMBIENT_AND_DIFFUSE;
4067 } else if (This->stateBlock->renderState[WINED3DRS_AMBIENTMATERIALSOURCE] == WINED3DMCS_COLOR1) {
4069 } else if (This->stateBlock->renderState[WINED3DRS_EMISSIVEMATERIALSOURCE] == WINED3DMCS_COLOR1) {
4071 } else if (This->stateBlock->renderState[WINED3DRS_SPECULARMATERIALSOURCE] == WINED3DMCS_COLOR1) {
4078 if (This->tracking_color != DISABLED_TRACKING) This->tracking_color = NEEDS_DISABLE;
4080 This->tracking_color = NEEDS_TRACKING;
4081 This->tracking_parm = Parm;
4085 if (This->tracking_color != DISABLED_TRACKING) This->tracking_color = NEEDS_DISABLE;
4090 case WINED3DRS_LINEPATTERN :
4094 WINED3DLINEPATTERN lp;
4096 tmppattern.d = Value;
4098 TRACE("Line pattern: repeat %d bits %x\n", tmppattern.lp.wRepeatFactor, tmppattern.lp.wLinePattern);
4100 if (tmppattern.lp.wRepeatFactor) {
4101 glLineStipple(tmppattern.lp.wRepeatFactor, tmppattern.lp.wLinePattern);
4102 checkGLcall("glLineStipple(repeat, linepattern)");
4103 glEnable(GL_LINE_STIPPLE);
4104 checkGLcall("glEnable(GL_LINE_STIPPLE);");
4106 glDisable(GL_LINE_STIPPLE);
4107 checkGLcall("glDisable(GL_LINE_STIPPLE);");
4112 case WINED3DRS_ZBIAS : /* D3D8 only */
4116 TRACE("ZBias value %f\n", tmpvalue.f);
4117 glPolygonOffset(0, -tmpvalue.f);
4118 checkGLcall("glPolygonOffset(0, -Value)");
4119 glEnable(GL_POLYGON_OFFSET_FILL);
4120 checkGLcall("glEnable(GL_POLYGON_OFFSET_FILL);");
4121 glEnable(GL_POLYGON_OFFSET_LINE);
4122 checkGLcall("glEnable(GL_POLYGON_OFFSET_LINE);");
4123 glEnable(GL_POLYGON_OFFSET_POINT);
4124 checkGLcall("glEnable(GL_POLYGON_OFFSET_POINT);");
4126 glDisable(GL_POLYGON_OFFSET_FILL);
4127 checkGLcall("glDisable(GL_POLYGON_OFFSET_FILL);");
4128 glDisable(GL_POLYGON_OFFSET_LINE);
4129 checkGLcall("glDisable(GL_POLYGON_OFFSET_LINE);");
4130 glDisable(GL_POLYGON_OFFSET_POINT);
4131 checkGLcall("glDisable(GL_POLYGON_OFFSET_POINT);");
4136 case WINED3DRS_NORMALIZENORMALS :
4138 glEnable(GL_NORMALIZE);
4139 checkGLcall("glEnable(GL_NORMALIZE);");
4141 glDisable(GL_NORMALIZE);
4142 checkGLcall("glDisable(GL_NORMALIZE);");
4146 case WINED3DRS_POINTSIZE :
4147 /* FIXME: check that pointSize isn't outside glGetFloatv( GL_POINT_SIZE_MAX_ARB, &maxSize ); or -ve */
4149 TRACE("Set point size to %f\n", tmpvalue.f);
4150 glPointSize(tmpvalue.f);
4151 checkGLcall("glPointSize(...);");
4154 case WINED3DRS_POINTSIZE_MIN :
4155 if (GL_SUPPORT(EXT_POINT_PARAMETERS)) {
4157 GL_EXTCALL(glPointParameterfEXT)(GL_POINT_SIZE_MIN_EXT, tmpvalue.f);
4158 checkGLcall("glPointParameterfEXT(...);");
4160 FIXME("WINED3DRS_POINTSIZE_MIN not supported on this opengl\n");
4164 case WINED3DRS_POINTSIZE_MAX :
4165 if (GL_SUPPORT(EXT_POINT_PARAMETERS)) {
4167 GL_EXTCALL(glPointParameterfEXT)(GL_POINT_SIZE_MAX_EXT, tmpvalue.f);
4168 checkGLcall("glPointParameterfEXT(...);");
4170 FIXME("WINED3DRS_POINTSIZE_MAX not supported on this opengl\n");
4174 case WINED3DRS_POINTSCALE_A :
4175 case WINED3DRS_POINTSCALE_B :
4176 case WINED3DRS_POINTSCALE_C :
4177 case WINED3DRS_POINTSCALEENABLE :
4180 * POINTSCALEENABLE controls how point size value is treated. If set to
4181 * true, the point size is scaled with respect to height of viewport.
4182 * When set to false point size is in pixels.
4184 * http://msdn.microsoft.com/library/en-us/directx9_c/point_sprites.asp
4187 /* Default values */
4188 GLfloat att[3] = {1.0f, 0.0f, 0.0f};
4191 * Minimum valid point size for OpenGL is 1.0f. For Direct3D it is 0.0f.
4192 * This means that OpenGL will clamp really small point sizes to 1.0f.
4193 * To correct for this we need to multiply by the scale factor when sizes
4194 * are less than 1.0f. scale_factor = 1.0f / point_size.
4196 GLfloat pointSize = *((float*)&This->stateBlock->renderState[WINED3DRS_POINTSIZE]);
4197 if(pointSize > 0.0f) {
4198 GLfloat scaleFactor;
4200 if(pointSize < 1.0f) {
4201 scaleFactor = pointSize * pointSize;
4206 if(This->stateBlock->renderState[WINED3DRS_POINTSCALEENABLE]) {
4207 att[0] = *((float*)&This->stateBlock->renderState[WINED3DRS_POINTSCALE_A]) /
4208 (This->stateBlock->viewport.Height * This->stateBlock->viewport.Height * scaleFactor);
4209 att[1] = *((float*)&This->stateBlock->renderState[WINED3DRS_POINTSCALE_B]) /
4210 (This->stateBlock->viewport.Height * This->stateBlock->viewport.Height * scaleFactor);
4211 att[2] = *((float*)&This->stateBlock->renderState[WINED3DRS_POINTSCALE_C]) /
4212 (This->stateBlock->viewport.Height * This->stateBlock->viewport.Height * scaleFactor);
4216 if(GL_SUPPORT(ARB_POINT_PARAMETERS)) {
4217 GL_EXTCALL(glPointParameterfvARB)(GL_POINT_DISTANCE_ATTENUATION_ARB, att);
4218 checkGLcall("glPointParameterfvARB(GL_DISTANCE_ATTENUATION_ARB, ...");
4220 else if(GL_SUPPORT(EXT_POINT_PARAMETERS)) {
4221 GL_EXTCALL(glPointParameterfvEXT)(GL_DISTANCE_ATTENUATION_EXT, att);
4222 checkGLcall("glPointParameterfvEXT(GL_DISTANCE_ATTENUATION_EXT, ...");
4224 TRACE("POINT_PARAMETERS not supported in this version of opengl\n");
4228 case WINED3DRS_COLORWRITEENABLE :
4230 TRACE("Color mask: r(%d) g(%d) b(%d) a(%d)\n",
4231 Value & WINED3DCOLORWRITEENABLE_RED ? 1 : 0,
4232 Value & WINED3DCOLORWRITEENABLE_GREEN ? 1 : 0,
4233 Value & WINED3DCOLORWRITEENABLE_BLUE ? 1 : 0,
4234 Value & WINED3DCOLORWRITEENABLE_ALPHA ? 1 : 0);
4235 glColorMask(Value & WINED3DCOLORWRITEENABLE_RED ? GL_TRUE : GL_FALSE,
4236 Value & WINED3DCOLORWRITEENABLE_GREEN ? GL_TRUE : GL_FALSE,
4237 Value & WINED3DCOLORWRITEENABLE_BLUE ? GL_TRUE : GL_FALSE,
4238 Value & WINED3DCOLORWRITEENABLE_ALPHA ? GL_TRUE : GL_FALSE);
4239 checkGLcall("glColorMask(...)");
4243 case WINED3DRS_LOCALVIEWER :
4245 GLint state = (Value) ? 1 : 0;
4246 TRACE("Local Viewer Enable to %ul\n", (BOOL) Value);
4247 glLightModeli(GL_LIGHT_MODEL_LOCAL_VIEWER, state);
4251 case WINED3DRS_LASTPIXEL :
4254 TRACE("Last Pixel Drawing Enabled\n");
4256 FIXME("Last Pixel Drawing Disabled, not handled yet\n");
4261 case WINED3DRS_SOFTWAREVERTEXPROCESSING :
4264 TRACE("Software Processing Enabled\n");
4266 TRACE("Software Processing Disabled\n");
4271 /** not supported */
4272 case WINED3DRS_ZVISIBLE :
4275 return WINED3DERR_INVALIDCALL;
4277 case WINED3DRS_POINTSPRITEENABLE :
4279 /* TODO: NV_POINT_SPRITE */
4280 if (!GL_SUPPORT(ARB_POINT_SPRITE)) {
4281 TRACE("Point sprites not supported\n");
4286 * Point sprites are always enabled. Value controls texture coordinate
4287 * replacement mode. Must be set true for point sprites to use
4290 glEnable(GL_POINT_SPRITE_ARB);
4291 checkGLcall("glEnable(GL_POINT_SPRITE_ARB)");
4294 glTexEnvf(GL_POINT_SPRITE_ARB, GL_COORD_REPLACE_ARB, TRUE);
4295 checkGLcall("glTexEnvf(GL_POINT_SPRITE, GL_COORD_REPLACE, TRUE)");
4297 glTexEnvf(GL_POINT_SPRITE_ARB, GL_COORD_REPLACE_ARB, FALSE);
4298 checkGLcall("glTexEnvf(GL_POINT_SPRITE, GL_COORD_REPLACE, FALSE)");
4302 case WINED3DRS_EDGEANTIALIAS :
4305 glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
4307 checkGLcall("glEnable(GL_BLEND)");
4308 glEnable(GL_LINE_SMOOTH);
4309 checkGLcall("glEnable(GL_LINE_SMOOTH)");
4311 if(!This->stateBlock->renderState[WINED3DRS_ALPHABLENDENABLE]) {
4312 glDisable(GL_BLEND);
4313 checkGLcall("glDisable(GL_BLEND)");
4315 glDisable(GL_LINE_SMOOTH);
4316 checkGLcall("glDisable(GL_LINE_SMOOTH)");
4320 case WINED3DRS_WRAP0 :
4321 case WINED3DRS_WRAP1 :
4322 case WINED3DRS_WRAP2 :
4323 case WINED3DRS_WRAP3 :
4324 case WINED3DRS_WRAP4 :
4325 case WINED3DRS_WRAP5 :
4326 case WINED3DRS_WRAP6 :
4327 case WINED3DRS_WRAP7 :
4328 case WINED3DRS_WRAP8 :
4329 case WINED3DRS_WRAP9 :
4330 case WINED3DRS_WRAP10 :
4331 case WINED3DRS_WRAP11 :
4332 case WINED3DRS_WRAP12 :
4333 case WINED3DRS_WRAP13 :
4334 case WINED3DRS_WRAP14 :
4335 case WINED3DRS_WRAP15 :
4337 http://www.cosc.brocku.ca/Offerings/3P98/course/lectures/texture/
4338 http://msdn.microsoft.com/archive/default.asp?url=/archive/en-us/directx9_c/directx/graphics/programmingguide/FixedFunction/Textures/texturewrapping.asp
4339 http://www.gamedev.net/reference/programming/features/rendererdll3/page2.asp
4340 Descussion that ways to turn on WRAPing to solve an opengl conversion problem.
4341 http://www.flipcode.org/cgi-bin/fcmsg.cgi?thread_show=10248
4343 so far as I can tell, wrapping and texture-coordinate generate go hand in hand,
4347 ERR("(%p)->(%s,%d) Texture wraping not yet supported\n",This, debug_d3drenderstate(State), Value);
4352 case WINED3DRS_MULTISAMPLEANTIALIAS :
4354 if( GL_SUPPORT(ARB_MULTISAMPLE) ) {
4356 glEnable(GL_MULTISAMPLE_ARB);
4357 checkGLcall("glEnable(GL_MULTISAMPLE_ARB)");
4359 glDisable(GL_MULTISAMPLE_ARB);
4360 checkGLcall("glDisable(GL_MULTISAMPLE_ARB)");
4364 ERR("Multisample antialiasing not supported by gl\n");
4370 case WINED3DRS_SCISSORTESTENABLE :
4373 glEnable(GL_SCISSOR_TEST);
4374 checkGLcall("glEnable(GL_SCISSOR_TEST)");
4376 glDisable(GL_SCISSOR_TEST);
4377 checkGLcall("glDisable(GL_SCISSOR_TEST)");
4381 case WINED3DRS_SLOPESCALEDEPTHBIAS :
4385 glEnable(GL_POLYGON_OFFSET_FILL);
4386 checkGLcall("glEnable(GL_POLYGON_OFFSET_FILL)");
4387 glPolygonOffset(tmpvalue.f, *((float*)&This->stateBlock->renderState[WINED3DRS_DEPTHBIAS]));
4388 checkGLcall("glPolygonOffset(...)");
4390 glDisable(GL_POLYGON_OFFSET_FILL);
4391 checkGLcall("glDisable(GL_POLYGON_OFFSET_FILL)");
4395 case WINED3DRS_ANTIALIASEDLINEENABLE :
4398 glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
4400 checkGLcall("glEnable(GL_BLEND)");
4401 glEnable(GL_LINE_SMOOTH);
4402 checkGLcall("glEnable(GL_LINE_SMOOTH)");
4404 glDisable(GL_BLEND);
4405 checkGLcall("glDisable(GL_BLEND)");
4406 glDisable(GL_LINE_SMOOTH);
4407 checkGLcall("glDisable(GL_LINE_SMOOTH)");
4411 case WINED3DRS_DEPTHBIAS :
4415 glEnable(GL_POLYGON_OFFSET_FILL);
4416 checkGLcall("glEnable(GL_POLYGON_OFFSET_FILL)");
4417 glPolygonOffset(*((float*)&This->stateBlock->renderState[WINED3DRS_SLOPESCALEDEPTHBIAS]), tmpvalue.f);
4418 checkGLcall("glPolygonOffset(...)");
4420 glDisable(GL_POLYGON_OFFSET_FILL);
4421 checkGLcall("glDisable(GL_POLYGON_OFFSET_FILL)");
4426 case WINED3DRS_TEXTUREPERSPECTIVE :
4429 glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST);
4431 glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_FASTEST);
4435 case WINED3DRS_STIPPLEDALPHA :
4438 ERR(" Stippled Alpha not supported yet.\n");
4441 case WINED3DRS_ANTIALIAS :
4444 ERR(" Antialias not supported yet.\n");
4448 case WINED3DRS_MULTISAMPLEMASK :
4450 if(0xFFFFFFFF != Value)
4451 ERR("(%p)->(%s,%d) not yet implemented\n", This, debug_d3drenderstate(State), Value);
4455 case WINED3DRS_PATCHEDGESTYLE :
4457 if(WINED3DPATCHEDGE_DISCRETE != Value)
4458 ERR("(%p)->(%s,%d) not yet implemented\n", This, debug_d3drenderstate(State), Value);
4462 case WINED3DRS_PATCHSEGMENTS :
4464 /* available in d3d8 but in d3d9 it was replaced by IDirect3DDevice9::SetNPatchMode */
4466 if(tmpvalue.d != Value)
4467 ERR("(%p)->(%s,%d) not yet implemented\n", This, debug_d3drenderstate(State), Value);
4471 case WINED3DRS_DEBUGMONITORTOKEN :
4473 /* Only useful for "debug builds". */
4474 if(0xbaadcafe != Value) {
4475 /* MSDN says the default is D3DDMT_ENABLE but our tests confirm 0xbaadcafe is the default. */
4476 /* MSDN says anything other than D3DDMT_ENABLE or DISABLE does not change the state,
4477 * but our tests disagree.
4478 * We do not claim to implement a debugging lib, so do not write an ERR
4480 WARN("(%p)->(%s,%d) not yet implemented\n", This, debug_d3drenderstate(State), Value);
4485 case WINED3DRS_POSITIONDEGREE :
4487 if(WINED3DDEGREE_CUBIC != Value)
4488 ERR("(%p)->(%s,%d) not yet implemented\n", This, debug_d3drenderstate(State), Value);
4492 case WINED3DRS_NORMALDEGREE :
4494 if(WINED3DDEGREE_LINEAR != Value)
4495 ERR("(%p)->(%s,%d) not yet implemented\n", This, debug_d3drenderstate(State), Value);
4499 case WINED3DRS_MINTESSELLATIONLEVEL :
4500 case WINED3DRS_MAXTESSELLATIONLEVEL :
4501 case WINED3DRS_ADAPTIVETESS_X :
4502 case WINED3DRS_ADAPTIVETESS_Y :
4503 case WINED3DRS_ADAPTIVETESS_Z :
4504 case WINED3DRS_ADAPTIVETESS_W :
4506 if(This->stateBlock->renderState[WINED3DRS_ENABLEADAPTIVETESSELLATION])
4507 FIXME("(%p)->(%s,%d) not yet implemented\n", This, debug_d3drenderstate(State), Value);
4509 TRACE("(%p)->(%s,%d): recording state but WINED3DRS_ENABLEADAPTIVETESSELLATION is not enabled\n", This, debug_d3drenderstate(State), Value);
4513 case WINED3DRS_ENABLEADAPTIVETESSELLATION:
4516 ERR("(%p)->(%s,%d) not yet implemented\n", This, debug_d3drenderstate(State), Value);
4520 case WINED3DRS_COLORWRITEENABLE1 :
4521 case WINED3DRS_COLORWRITEENABLE2 :
4522 case WINED3DRS_COLORWRITEENABLE3 :
4524 /* depends on WINED3DRS_COLORWRITEENABLE. */
4525 if(0x0000000F != Value)
4526 ERR("(%p)->(%s,%d) not yet implemented. Missing of cap D3DPMISCCAPS_INDEPENDENTWRITEMASKS wasn't honored?\n", This, debug_d3drenderstate(State), Value);
4530 case WINED3DRS_BLENDFACTOR :
4534 TRACE("Setting BlendFactor to %d\n", Value);
4536 D3DCOLORTOGLFLOAT4(Value, col);
4537 if (0xFFFFFFFF != Value) {
4539 checkGLcall("glEnable(GL_BLEND)");
4542 glDisable(GL_BLEND);
4543 checkGLcall("glDisable(GL_BLEND)");
4545 glBlendColor (col[0],col[1],col[2],col[3]);
4549 case WINED3DRS_SRGBWRITEENABLE :
4552 ERR("(%p)->(%s,%d) not yet implemented\n", This, debug_d3drenderstate(State), Value);
4556 case WINED3DRS_SEPARATEALPHABLENDENABLE :
4559 ERR("(%p)->(%s,%d) not yet implemented. Missing of cap D3DPMISCCAPS_SEPARATEALPHABLEND wasn't honored?\n", This, debug_d3drenderstate(State), Value);
4563 case WINED3DRS_SRCBLENDALPHA :
4564 case WINED3DRS_DESTBLENDALPHA :
4565 case WINED3DRS_BLENDOPALPHA :
4567 if(This->stateBlock->renderState[WINED3DRS_SEPARATEALPHABLENDENABLE])
4568 FIXME("(%p)->(%s,%d) not yet implemented\n", This, debug_d3drenderstate(State), Value);
4570 TRACE("(%p)->(%s,%d): recording state but WINED3DRS_SEPARATEALPHABLENDENABLE is not enabled\n", This, debug_d3drenderstate(State), Value);
4575 FIXME("(%p)->(%s,%d) unknown state\n", This, debug_d3drenderstate(State), Value);
4583 static HRESULT WINAPI IWineD3DDeviceImpl_GetRenderState(IWineD3DDevice *iface, WINED3DRENDERSTATETYPE State, DWORD *pValue) {
4584 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4585 TRACE("(%p) for State %d = %d\n", This, State, This->stateBlock->renderState[State]);
4586 *pValue = This->stateBlock->renderState[State];
4591 * Get / Set Sampler States
4592 * TODO: Verify against dx9 definitions
4595 static HRESULT WINAPI IWineD3DDeviceImpl_SetSamplerState(IWineD3DDevice *iface, DWORD Sampler, WINED3DSAMPLERSTATETYPE Type, DWORD Value) {
4596 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4598 * SetSampler is designed to allow for more than the standard up to 8 textures
4599 * and Geforce has stopped supporting more than 6 standard textures in openGL.
4600 * So I have to use ARB for Gforce. (maybe if the sampler > 4 then use ARB?)
4602 * http://developer.nvidia.com/object/General_FAQ.html#t6
4604 * There are two new settings for GForce
4606 * GL_MAX_TEXTURE_IMAGE_UNITS_ARB
4607 * and the texture one:
4608 * GL_MAX_TEXTURE_COORDS_ARB.
4609 * Ok GForce say it's ok to use glTexParameter/glGetTexParameter(...).
4611 /** NOTE: States are appled in IWineD3DBaseTextre ApplyStateChanges and IWineD3DDevice SetupTextureStates**/
4612 if(Sampler > GL_LIMITS(sampler_stages) || Sampler < 0 || Type > WINED3D_HIGHEST_SAMPLER_STATE || Type < 0) {
4613 FIXME("sampler %d type %s(%u) is out of range [max_samplers=%d, highest_state=%d]\n",
4614 Sampler, debug_d3dsamplerstate(Type), Type, GL_LIMITS(sampler_stages), WINED3D_HIGHEST_SAMPLER_STATE);
4615 return WINED3DERR_INVALIDCALL;
4618 TRACE("(%p) : Sampler=%d, Type=%s(%d), Value=%d\n", This, Sampler,
4619 debug_d3dsamplerstate(Type), Type, Value);
4620 This->updateStateBlock->samplerState[Sampler][Type] = Value;
4621 This->updateStateBlock->set.samplerState[Sampler][Type] = Value;
4622 This->updateStateBlock->changed.samplerState[Sampler][Type] = Value;
4624 /* Handle recording of state blocks */
4625 if (This->isRecordingState) {
4626 TRACE("Recording... not performing anything\n");
4633 static HRESULT WINAPI IWineD3DDeviceImpl_GetSamplerState(IWineD3DDevice *iface, DWORD Sampler, WINED3DSAMPLERSTATETYPE Type, DWORD* Value) {
4634 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4635 /** TODO: check that sampler is in range **/
4636 *Value = This->stateBlock->samplerState[Sampler][Type];
4637 TRACE("(%p) : Sampler %d Type %u Returning %d\n", This, Sampler, Type, *Value);
4642 static HRESULT WINAPI IWineD3DDeviceImpl_SetScissorRect(IWineD3DDevice *iface, CONST RECT* pRect) {
4643 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4647 GetClientRect(((IWineD3DSwapChainImpl *)This->swapchains[0])->win_handle, &windowRect);
4648 /* Warning: glScissor uses window coordinates, not viewport coordinates, so our viewport correction does not apply
4649 * Warning2: Even in windowed mode the coords are relative to the window, not the screen
4651 winHeight = windowRect.bottom - windowRect.top;
4652 TRACE("(%p)Setting new Scissor Rect to %d:%d-%d:%d\n", This, pRect->left, pRect->bottom - winHeight,
4653 pRect->right - pRect->left, pRect->bottom - pRect->top);
4655 glScissor(pRect->left, winHeight - pRect->bottom, pRect->right - pRect->left, pRect->bottom - pRect->top);
4656 checkGLcall("glScissor");
4662 static HRESULT WINAPI IWineD3DDeviceImpl_GetScissorRect(IWineD3DDevice *iface, RECT* pRect) {
4663 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4664 GLint scissorBox[4];
4667 /** FIXME: Windows uses a top,left origin openGL uses a bottom Right? **/
4668 glGetIntegerv(GL_SCISSOR_BOX, scissorBox);
4669 pRect->left = scissorBox[0];
4670 pRect->top = scissorBox[1];
4671 pRect->right = scissorBox[0] + scissorBox[2];
4672 pRect->bottom = scissorBox[1] + scissorBox[3];
4673 TRACE("(%p)Returning a Scissor Rect of %d:%d-%d:%d\n", This, pRect->left, pRect->top, pRect->right, pRect->bottom);
4678 static HRESULT WINAPI IWineD3DDeviceImpl_SetVertexDeclaration(IWineD3DDevice* iface, IWineD3DVertexDeclaration* pDecl) {
4679 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *) iface;
4680 IWineD3DVertexDeclaration *oldDecl = This->updateStateBlock->vertexDecl;
4682 TRACE("(%p) : pDecl=%p\n", This, pDecl);
4684 This->updateStateBlock->vertexDecl = pDecl;
4685 This->updateStateBlock->changed.vertexDecl = TRUE;
4686 This->updateStateBlock->set.vertexDecl = TRUE;
4688 if (This->isRecordingState) {
4689 TRACE("Recording... not performing anything\n");
4692 if (NULL != pDecl) {
4693 IWineD3DVertexDeclaration_AddRef(pDecl);
4695 if (NULL != oldDecl) {
4696 IWineD3DVertexDeclaration_Release(oldDecl);
4701 static HRESULT WINAPI IWineD3DDeviceImpl_GetVertexDeclaration(IWineD3DDevice* iface, IWineD3DVertexDeclaration** ppDecl) {
4702 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4704 TRACE("(%p) : ppDecl=%p\n", This, ppDecl);
4706 *ppDecl = This->stateBlock->vertexDecl;
4707 if (NULL != *ppDecl) IWineD3DVertexDeclaration_AddRef(*ppDecl);
4711 static HRESULT WINAPI IWineD3DDeviceImpl_SetVertexShader(IWineD3DDevice *iface, IWineD3DVertexShader* pShader) {
4712 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4713 IWineD3DVertexShader* oldShader = This->updateStateBlock->vertexShader;
4715 This->updateStateBlock->vertexShader = pShader;
4716 This->updateStateBlock->changed.vertexShader = TRUE;
4717 This->updateStateBlock->set.vertexShader = TRUE;
4719 if (This->isRecordingState) {
4720 TRACE("Recording... not performing anything\n");
4723 if (NULL != pShader) {
4724 IWineD3DVertexShader_AddRef(pShader);
4726 if (NULL != oldShader) {
4727 IWineD3DVertexShader_Release(oldShader);
4730 TRACE("(%p) : setting pShader(%p)\n", This, pShader);
4732 * TODO: merge HAL shaders context switching from prototype
4737 static HRESULT WINAPI IWineD3DDeviceImpl_GetVertexShader(IWineD3DDevice *iface, IWineD3DVertexShader** ppShader) {
4738 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4740 if (NULL == ppShader) {
4741 return WINED3DERR_INVALIDCALL;
4743 *ppShader = This->stateBlock->vertexShader;
4744 if( NULL != *ppShader)
4745 IWineD3DVertexShader_AddRef(*ppShader);
4747 TRACE("(%p) : returning %p\n", This, *ppShader);
4751 static HRESULT WINAPI IWineD3DDeviceImpl_SetVertexShaderConstantB(
4752 IWineD3DDevice *iface,
4754 CONST BOOL *srcData,
4757 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4758 int i, cnt = min(count, MAX_CONST_B - start);
4760 TRACE("(iface %p, srcData %p, start %d, count %d)\n",
4761 iface, srcData, start, count);
4763 if (srcData == NULL || cnt < 0)
4764 return WINED3DERR_INVALIDCALL;
4766 memcpy(&This->updateStateBlock->vertexShaderConstantB[start], srcData, cnt * sizeof(BOOL));
4767 for (i = 0; i < cnt; i++)
4768 TRACE("Set BOOL constant %u to %s\n", start + i, srcData[i]? "true":"false");
4770 for (i = start; i < cnt + start; ++i) {
4771 This->updateStateBlock->changed.vertexShaderConstantsB[i] = TRUE;
4772 This->updateStateBlock->set.vertexShaderConstantsB[i] = TRUE;
4778 static HRESULT WINAPI IWineD3DDeviceImpl_GetVertexShaderConstantB(
4779 IWineD3DDevice *iface,
4784 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4785 int cnt = min(count, MAX_CONST_B - start);
4787 TRACE("(iface %p, dstData %p, start %d, count %d)\n",
4788 iface, dstData, start, count);
4790 if (dstData == NULL || cnt < 0)
4791 return WINED3DERR_INVALIDCALL;
4793 memcpy(dstData, &This->stateBlock->vertexShaderConstantB[start], cnt * sizeof(BOOL));
4797 static HRESULT WINAPI IWineD3DDeviceImpl_SetVertexShaderConstantI(
4798 IWineD3DDevice *iface,
4803 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4804 int i, cnt = min(count, MAX_CONST_I - start);
4806 TRACE("(iface %p, srcData %p, start %d, count %d)\n",
4807 iface, srcData, start, count);
4809 if (srcData == NULL || cnt < 0)
4810 return WINED3DERR_INVALIDCALL;
4812 memcpy(&This->updateStateBlock->vertexShaderConstantI[start * 4], srcData, cnt * sizeof(int) * 4);
4813 for (i = 0; i < cnt; i++)
4814 TRACE("Set INT constant %u to { %d, %d, %d, %d }\n", start + i,
4815 srcData[i*4], srcData[i*4+1], srcData[i*4+2], srcData[i*4+3]);
4817 for (i = start; i < cnt + start; ++i) {
4818 This->updateStateBlock->changed.vertexShaderConstantsI[i] = TRUE;
4819 This->updateStateBlock->set.vertexShaderConstantsI[i] = TRUE;
4825 static HRESULT WINAPI IWineD3DDeviceImpl_GetVertexShaderConstantI(
4826 IWineD3DDevice *iface,
4831 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4832 int cnt = min(count, MAX_CONST_I - start);
4834 TRACE("(iface %p, dstData %p, start %d, count %d)\n",
4835 iface, dstData, start, count);
4837 if (dstData == NULL || ((signed int) MAX_CONST_I - (signed int) start) <= (signed int) 0)
4838 return WINED3DERR_INVALIDCALL;
4840 memcpy(dstData, &This->stateBlock->vertexShaderConstantI[start * 4], cnt * sizeof(int) * 4);
4844 static HRESULT WINAPI IWineD3DDeviceImpl_SetVertexShaderConstantF(
4845 IWineD3DDevice *iface,
4847 CONST float *srcData,
4850 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4851 int i, cnt = min(count, GL_LIMITS(vshader_constantsF) - start);
4853 TRACE("(iface %p, srcData %p, start %d, count %d)\n",
4854 iface, srcData, start, count);
4856 if (srcData == NULL || ((signed int) GL_LIMITS(vshader_constantsF) - (signed int) start) <= (signed int) 0)
4857 return WINED3DERR_INVALIDCALL;
4859 memcpy(&This->updateStateBlock->vertexShaderConstantF[start * 4], srcData, cnt * sizeof(float) * 4);
4860 for (i = 0; i < cnt; i++)
4861 TRACE("Set FLOAT constant %u to { %f, %f, %f, %f }\n", start + i,
4862 srcData[i*4], srcData[i*4+1], srcData[i*4+2], srcData[i*4+3]);
4864 for (i = start; i < cnt + start; ++i) {
4865 if (!This->updateStateBlock->set.vertexShaderConstantsF[i]) {
4866 constant_entry *ptr = HeapAlloc(GetProcessHeap(), 0, sizeof(constant_entry));
4868 list_add_head(&This->updateStateBlock->set_vconstantsF, &ptr->entry);
4869 This->updateStateBlock->set.vertexShaderConstantsF[i] = TRUE;
4871 This->updateStateBlock->changed.vertexShaderConstantsF[i] = TRUE;
4877 static HRESULT WINAPI IWineD3DDeviceImpl_GetVertexShaderConstantF(
4878 IWineD3DDevice *iface,
4883 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4884 int cnt = min(count, GL_LIMITS(vshader_constantsF) - start);
4886 TRACE("(iface %p, dstData %p, start %d, count %d)\n",
4887 iface, dstData, start, count);
4889 if (dstData == NULL || cnt < 0)
4890 return WINED3DERR_INVALIDCALL;
4892 memcpy(dstData, &This->stateBlock->vertexShaderConstantF[start * 4], cnt * sizeof(float) * 4);
4896 static HRESULT WINAPI IWineD3DDeviceImpl_SetPixelShader(IWineD3DDevice *iface, IWineD3DPixelShader *pShader) {
4897 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4898 IWineD3DPixelShader *oldShader = This->updateStateBlock->pixelShader;
4899 This->updateStateBlock->pixelShader = pShader;
4900 This->updateStateBlock->changed.pixelShader = TRUE;
4901 This->updateStateBlock->set.pixelShader = TRUE;
4903 /* Handle recording of state blocks */
4904 if (This->isRecordingState) {
4905 TRACE("Recording... not performing anything\n");
4908 if (NULL != pShader) {
4909 IWineD3DPixelShader_AddRef(pShader);
4911 if (NULL != oldShader) {
4912 IWineD3DPixelShader_Release(oldShader);
4915 TRACE("(%p) : setting pShader(%p)\n", This, pShader);
4917 * TODO: merge HAL shaders context switching from prototype
4922 static HRESULT WINAPI IWineD3DDeviceImpl_GetPixelShader(IWineD3DDevice *iface, IWineD3DPixelShader **ppShader) {
4923 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4925 if (NULL == ppShader) {
4926 WARN("(%p) : PShader is NULL, returning INVALIDCALL\n", This);
4927 return WINED3DERR_INVALIDCALL;
4930 *ppShader = This->stateBlock->pixelShader;
4931 if (NULL != *ppShader) {
4932 IWineD3DPixelShader_AddRef(*ppShader);
4934 TRACE("(%p) : returning %p\n", This, *ppShader);
4938 static HRESULT WINAPI IWineD3DDeviceImpl_SetPixelShaderConstantB(
4939 IWineD3DDevice *iface,
4941 CONST BOOL *srcData,
4944 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4945 int i, cnt = min(count, MAX_CONST_B - start);
4947 TRACE("(iface %p, srcData %p, start %d, count %d)\n",
4948 iface, srcData, start, count);
4950 if (srcData == NULL || cnt < 0)
4951 return WINED3DERR_INVALIDCALL;
4953 memcpy(&This->updateStateBlock->pixelShaderConstantB[start], srcData, cnt * sizeof(BOOL));
4954 for (i = 0; i < cnt; i++)
4955 TRACE("Set BOOL constant %u to %s\n", start + i, srcData[i]? "true":"false");
4957 for (i = start; i < cnt + start; ++i) {
4958 This->updateStateBlock->changed.pixelShaderConstantsB[i] = TRUE;
4959 This->updateStateBlock->set.pixelShaderConstantsB[i] = TRUE;
4965 static HRESULT WINAPI IWineD3DDeviceImpl_GetPixelShaderConstantB(
4966 IWineD3DDevice *iface,
4971 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4972 int cnt = min(count, MAX_CONST_B - start);
4974 TRACE("(iface %p, dstData %p, start %d, count %d)\n",
4975 iface, dstData, start, count);
4977 if (dstData == NULL || cnt < 0)
4978 return WINED3DERR_INVALIDCALL;
4980 memcpy(dstData, &This->stateBlock->pixelShaderConstantB[start], cnt * sizeof(BOOL));
4984 static HRESULT WINAPI IWineD3DDeviceImpl_SetPixelShaderConstantI(
4985 IWineD3DDevice *iface,
4990 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4991 int i, cnt = min(count, MAX_CONST_I - start);
4993 TRACE("(iface %p, srcData %p, start %d, count %d)\n",
4994 iface, srcData, start, count);
4996 if (srcData == NULL || cnt < 0)
4997 return WINED3DERR_INVALIDCALL;
4999 memcpy(&This->updateStateBlock->pixelShaderConstantI[start * 4], srcData, cnt * sizeof(int) * 4);
5000 for (i = 0; i < cnt; i++)
5001 TRACE("Set INT constant %u to { %d, %d, %d, %d }\n", start + i,
5002 srcData[i*4], srcData[i*4+1], srcData[i*4+2], srcData[i*4+3]);
5004 for (i = start; i < cnt + start; ++i) {
5005 This->updateStateBlock->changed.pixelShaderConstantsI[i] = TRUE;
5006 This->updateStateBlock->set.pixelShaderConstantsI[i] = TRUE;
5012 static HRESULT WINAPI IWineD3DDeviceImpl_GetPixelShaderConstantI(
5013 IWineD3DDevice *iface,
5018 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5019 int cnt = min(count, MAX_CONST_I - start);
5021 TRACE("(iface %p, dstData %p, start %d, count %d)\n",
5022 iface, dstData, start, count);
5024 if (dstData == NULL || cnt < 0)
5025 return WINED3DERR_INVALIDCALL;
5027 memcpy(dstData, &This->stateBlock->pixelShaderConstantI[start * 4], cnt * sizeof(int) * 4);
5031 static HRESULT WINAPI IWineD3DDeviceImpl_SetPixelShaderConstantF(
5032 IWineD3DDevice *iface,
5034 CONST float *srcData,
5037 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5038 int i, cnt = min(count, GL_LIMITS(pshader_constantsF) - start);
5040 TRACE("(iface %p, srcData %p, start %d, count %d)\n",
5041 iface, srcData, start, count);
5043 if (srcData == NULL || cnt < 0)
5044 return WINED3DERR_INVALIDCALL;
5046 memcpy(&This->updateStateBlock->pixelShaderConstantF[start * 4], srcData, cnt * sizeof(float) * 4);
5047 for (i = 0; i < cnt; i++)
5048 TRACE("Set FLOAT constant %u to { %f, %f, %f, %f }\n", start + i,
5049 srcData[i*4], srcData[i*4+1], srcData[i*4+2], srcData[i*4+3]);
5051 for (i = start; i < cnt + start; ++i) {
5052 if (!This->updateStateBlock->set.pixelShaderConstantsF[i]) {
5053 constant_entry *ptr = HeapAlloc(GetProcessHeap(), 0, sizeof(constant_entry));
5055 list_add_head(&This->updateStateBlock->set_pconstantsF, &ptr->entry);
5056 This->updateStateBlock->set.pixelShaderConstantsF[i] = TRUE;
5058 This->updateStateBlock->changed.pixelShaderConstantsF[i] = TRUE;
5064 static HRESULT WINAPI IWineD3DDeviceImpl_GetPixelShaderConstantF(
5065 IWineD3DDevice *iface,
5070 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5071 int cnt = min(count, GL_LIMITS(pshader_constantsF) - start);
5073 TRACE("(iface %p, dstData %p, start %d, count %d)\n",
5074 iface, dstData, start, count);
5076 if (dstData == NULL || cnt < 0)
5077 return WINED3DERR_INVALIDCALL;
5079 memcpy(dstData, &This->stateBlock->pixelShaderConstantF[start * 4], cnt * sizeof(float) * 4);
5083 #define copy_and_next(dest, src, size) memcpy(dest, src, size); dest += (size)
5085 process_vertices_strided(IWineD3DDeviceImpl *This, DWORD dwDestIndex, DWORD dwCount, WineDirect3DVertexStridedData *lpStrideData, DWORD SrcFVF, IWineD3DVertexBufferImpl *dest, DWORD dwFlags) {
5086 char *dest_ptr, *dest_conv = NULL;
5088 DWORD DestFVF = dest->fvf;
5090 WINED3DMATRIX mat, proj_mat, view_mat, world_mat;
5094 if (SrcFVF & WINED3DFVF_NORMAL) {
5095 WARN(" lighting state not saved yet... Some strange stuff may happen !\n");
5098 if ( (SrcFVF & WINED3DFVF_POSITION_MASK) != WINED3DFVF_XYZ) {
5099 ERR("Source has no position mask\n");
5100 return WINED3DERR_INVALIDCALL;
5103 /* We might access VBOs from this code, so hold the lock */
5106 if (dest->resource.allocatedMemory == NULL) {
5107 /* This may happen if we do direct locking into a vbo. Unlikely,
5108 * but theoretically possible(ddraw processvertices test)
5110 dest->resource.allocatedMemory = HeapAlloc(GetProcessHeap(), 0, dest->resource.size);
5111 if(!dest->resource.allocatedMemory) {
5113 ERR("Out of memory\n");
5114 return E_OUTOFMEMORY;
5118 GL_EXTCALL(glBindBufferARB(GL_ARRAY_BUFFER_ARB, dest->vbo));
5119 checkGLcall("glBindBufferARB");
5120 src = GL_EXTCALL(glMapBufferARB(GL_ARRAY_BUFFER_ARB, GL_READ_ONLY_ARB));
5122 memcpy(dest->resource.allocatedMemory, src, dest->resource.size);
5124 GL_EXTCALL(glUnmapBufferARB(GL_ARRAY_BUFFER_ARB));
5125 checkGLcall("glUnmapBufferARB");
5129 /* Get a pointer into the destination vbo(create one if none exists) and
5130 * write correct opengl data into it. It's cheap and allows us to run drawStridedFast
5132 if(!dest->vbo && GL_SUPPORT(ARB_VERTEX_BUFFER_OBJECT)) {
5137 GL_EXTCALL(glBindBufferARB(GL_ARRAY_BUFFER_ARB, dest->vbo));
5138 dest_conv = GL_EXTCALL(glMapBufferARB(GL_ARRAY_BUFFER_ARB, GL_WRITE_ONLY_ARB));
5140 ERR("glMapBuffer failed\n");
5141 /* Continue without storing converted vertices */
5146 * a) WINED3DRS_CLIPPING is enabled
5147 * b) WINED3DVOP_CLIP is passed
5149 if(This->stateBlock->renderState[WINED3DRS_CLIPPING]) {
5150 static BOOL warned = FALSE;
5152 * The clipping code is not quite correct. Some things need
5153 * to be checked against IDirect3DDevice3 (!), d3d8 and d3d9,
5154 * so disable clipping for now.
5155 * (The graphics in Half-Life are broken, and my processvertices
5156 * test crashes with IDirect3DDevice3)
5162 FIXME("Clipping is broken and disabled for now\n");
5164 } else doClip = FALSE;
5165 dest_ptr = ((char *) dest->resource.allocatedMemory) + dwDestIndex * get_flexible_vertex_size(DestFVF);
5167 dest_conv = ((char *) dest_conv) + dwDestIndex * get_flexible_vertex_size(DestFVF);
5170 IWineD3DDevice_GetTransform( (IWineD3DDevice *) This,
5173 IWineD3DDevice_GetTransform( (IWineD3DDevice *) This,
5174 WINED3DTS_PROJECTION,
5176 IWineD3DDevice_GetTransform( (IWineD3DDevice *) This,
5177 WINED3DTS_WORLDMATRIX(0),
5180 TRACE("View mat:\n");
5181 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); \
5182 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); \
5183 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); \
5184 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); \
5186 TRACE("Proj mat:\n");
5187 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); \
5188 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); \
5189 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); \
5190 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); \
5192 TRACE("World mat:\n");
5193 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); \
5194 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); \
5195 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); \
5196 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); \
5198 /* Get the viewport */
5199 IWineD3DDevice_GetViewport( (IWineD3DDevice *) This, &vp);
5200 TRACE("Viewport: X=%d, Y=%d, Width=%d, Height=%d, MinZ=%f, MaxZ=%f\n",
5201 vp.X, vp.Y, vp.Width, vp.Height, vp.MinZ, vp.MaxZ);
5203 multiply_matrix(&mat,&view_mat,&world_mat);
5204 multiply_matrix(&mat,&proj_mat,&mat);
5206 numTextures = (DestFVF & WINED3DFVF_TEXCOUNT_MASK) >> WINED3DFVF_TEXCOUNT_SHIFT;
5208 for (i = 0; i < dwCount; i+= 1) {
5209 unsigned int tex_index;
5211 if ( ((DestFVF & WINED3DFVF_POSITION_MASK) == WINED3DFVF_XYZ ) ||
5212 ((DestFVF & WINED3DFVF_POSITION_MASK) == WINED3DFVF_XYZRHW ) ) {
5213 /* The position first */
5215 (float *) (((char *) lpStrideData->u.s.position.lpData) + i * lpStrideData->u.s.position.dwStride);
5217 TRACE("In: ( %06.2f %06.2f %06.2f )\n", p[0], p[1], p[2]);
5219 /* Multiplication with world, view and projection matrix */
5220 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);
5221 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);
5222 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);
5223 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);
5225 TRACE("x=%f y=%f z=%f rhw=%f\n", x, y, z, rhw);
5227 /* WARNING: The following things are taken from d3d7 and were not yet checked
5228 * against d3d8 or d3d9!
5231 /* Clipping conditions: From
5232 * http://msdn.microsoft.com/archive/default.asp?url=/archive/en-us/directx9_c/directx/graphics/programmingguide/fixedfunction/viewportsclipping/clippingvolumes.asp
5234 * A vertex is clipped if it does not match the following requirements
5238 * 0 < rhw ( Not in d3d7, but tested in d3d7)
5240 * If clipping is on is determined by the D3DVOP_CLIP flag in D3D7, and
5241 * by the D3DRS_CLIPPING in D3D9(according to the msdn, not checked)
5246 ( (-rhw -eps < x) && (-rhw -eps < y) && ( -eps < z) &&
5247 (x <= rhw + eps) && (y <= rhw + eps ) && (z <= rhw + eps) &&
5250 /* "Normal" viewport transformation (not clipped)
5251 * 1) The values are divided by rhw
5252 * 2) The y axis is negative, so multiply it with -1
5253 * 3) Screen coordinates go from -(Width/2) to +(Width/2) and
5254 * -(Height/2) to +(Height/2). The z range is MinZ to MaxZ
5255 * 4) Multiply x with Width/2 and add Width/2
5256 * 5) The same for the height
5257 * 6) Add the viewpoint X and Y to the 2D coordinates and
5258 * The minimum Z value to z
5259 * 7) rhw = 1 / rhw Reciprocal of Homogeneous W....
5261 * Well, basically it's simply a linear transformation into viewport
5273 z *= vp.MaxZ - vp.MinZ;
5275 x += vp.Width / 2 + vp.X;
5276 y += vp.Height / 2 + vp.Y;
5281 /* That vertex got clipped
5282 * Contrary to OpenGL it is not dropped completely, it just
5283 * undergoes a different calculation.
5285 TRACE("Vertex got clipped\n");
5292 /* Msdn mentions that Direct3D9 keeps a list of clipped vertices
5293 * outside of the main vertex buffer memory. That needs some more
5298 TRACE("Writing (%f %f %f) %f\n", x, y, z, rhw);
5301 ( (float *) dest_ptr)[0] = x;
5302 ( (float *) dest_ptr)[1] = y;
5303 ( (float *) dest_ptr)[2] = z;
5304 ( (float *) dest_ptr)[3] = rhw; /* SIC, see ddraw test! */
5306 dest_ptr += 3 * sizeof(float);
5308 if((DestFVF & WINED3DFVF_POSITION_MASK) == WINED3DFVF_XYZRHW) {
5309 dest_ptr += sizeof(float);
5314 ( (float *) dest_conv)[0] = x * w;
5315 ( (float *) dest_conv)[1] = y * w;
5316 ( (float *) dest_conv)[2] = z * w;
5317 ( (float *) dest_conv)[3] = w;
5319 dest_conv += 3 * sizeof(float);
5321 if((DestFVF & WINED3DFVF_POSITION_MASK) == WINED3DFVF_XYZRHW) {
5322 dest_conv += sizeof(float);
5326 if (DestFVF & WINED3DFVF_PSIZE) {
5327 dest_ptr += sizeof(DWORD);
5328 if(dest_conv) dest_conv += sizeof(DWORD);
5330 if (DestFVF & WINED3DFVF_NORMAL) {
5332 (float *) (((float *) lpStrideData->u.s.normal.lpData) + i * lpStrideData->u.s.normal.dwStride);
5333 /* AFAIK this should go into the lighting information */
5334 FIXME("Didn't expect the destination to have a normal\n");
5335 copy_and_next(dest_ptr, normal, 3 * sizeof(float));
5337 copy_and_next(dest_conv, normal, 3 * sizeof(float));
5341 if (DestFVF & WINED3DFVF_DIFFUSE) {
5343 (DWORD *) (((char *) lpStrideData->u.s.diffuse.lpData) + i * lpStrideData->u.s.diffuse.dwStride);
5345 static BOOL warned = FALSE;
5348 ERR("No diffuse color in source, but destination has one\n");
5352 *( (DWORD *) dest_ptr) = 0xffffffff;
5353 dest_ptr += sizeof(DWORD);
5356 *( (DWORD *) dest_conv) = 0xffffffff;
5357 dest_conv += sizeof(DWORD);
5361 copy_and_next(dest_ptr, color_d, sizeof(DWORD));
5363 *( (DWORD *) dest_conv) = (*color_d & 0xff00ff00) ; /* Alpha + green */
5364 *( (DWORD *) dest_conv) |= (*color_d & 0x00ff0000) >> 16; /* Red */
5365 *( (DWORD *) dest_conv) |= (*color_d & 0xff0000ff) << 16; /* Blue */
5366 dest_conv += sizeof(DWORD);
5371 if (DestFVF & WINED3DFVF_SPECULAR) {
5372 /* What's the color value in the feedback buffer? */
5374 (DWORD *) (((char *) lpStrideData->u.s.specular.lpData) + i * lpStrideData->u.s.specular.dwStride);
5376 static BOOL warned = FALSE;
5379 ERR("No specular color in source, but destination has one\n");
5383 *( (DWORD *) dest_ptr) = 0xFF000000;
5384 dest_ptr += sizeof(DWORD);
5387 *( (DWORD *) dest_conv) = 0xFF000000;
5388 dest_conv += sizeof(DWORD);
5392 copy_and_next(dest_ptr, color_s, sizeof(DWORD));
5394 *( (DWORD *) dest_conv) = (*color_s & 0xff00ff00) ; /* Alpha + green */
5395 *( (DWORD *) dest_conv) |= (*color_s & 0x00ff0000) >> 16; /* Red */
5396 *( (DWORD *) dest_conv) |= (*color_s & 0xff0000ff) << 16; /* Blue */
5397 dest_conv += sizeof(DWORD);
5402 for (tex_index = 0; tex_index < numTextures; tex_index++) {
5404 (float *) (((char *) lpStrideData->u.s.texCoords[tex_index].lpData) +
5405 i * lpStrideData->u.s.texCoords[tex_index].dwStride);
5407 ERR("No source texture, but destination requests one\n");
5408 dest_ptr+=GET_TEXCOORD_SIZE_FROM_FVF(DestFVF, tex_index) * sizeof(float);
5409 if(dest_conv) dest_conv += GET_TEXCOORD_SIZE_FROM_FVF(DestFVF, tex_index) * sizeof(float);
5412 copy_and_next(dest_ptr, tex_coord, GET_TEXCOORD_SIZE_FROM_FVF(DestFVF, tex_index) * sizeof(float));
5414 copy_and_next(dest_conv, tex_coord, GET_TEXCOORD_SIZE_FROM_FVF(DestFVF, tex_index) * sizeof(float));
5421 GL_EXTCALL(glUnmapBufferARB(GL_ARRAY_BUFFER_ARB));
5422 checkGLcall("glUnmapBufferARB(GL_ARRAY_BUFFER_ARB)");
5429 #undef copy_and_next
5431 static HRESULT WINAPI IWineD3DDeviceImpl_ProcessVertices(IWineD3DDevice *iface, UINT SrcStartIndex, UINT DestIndex, UINT VertexCount, IWineD3DVertexBuffer* pDestBuffer, IWineD3DVertexBuffer* pVertexDecl, DWORD Flags) {
5432 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5433 IWineD3DVertexBufferImpl *SrcImpl = (IWineD3DVertexBufferImpl *) pVertexDecl;
5434 WineDirect3DVertexStridedData strided;
5435 TRACE("(%p)->(%d,%d,%d,%p,%p,%d\n", This, SrcStartIndex, DestIndex, VertexCount, pDestBuffer, pVertexDecl, Flags);
5438 WARN("NULL source vertex buffer\n");
5439 return WINED3DERR_INVALIDCALL;
5441 /* We don't need the source vbo because this buffer is only used as
5442 * a source for ProcessVertices. Avoid wasting resources by converting the
5443 * buffer and loading the VBO
5446 TRACE("Releasing the source vbo, it won't be needed\n");
5448 if(!SrcImpl->resource.allocatedMemory) {
5449 /* Rescue the data from the buffer */
5451 SrcImpl->resource.allocatedMemory = HeapAlloc(GetProcessHeap(), 0, SrcImpl->resource.size);
5452 if(!SrcImpl->resource.allocatedMemory) {
5453 ERR("Out of memory\n");
5454 return E_OUTOFMEMORY;
5458 GL_EXTCALL(glBindBufferARB(GL_ARRAY_BUFFER_ARB, SrcImpl->vbo));
5459 checkGLcall("glBindBufferARB");
5461 src = GL_EXTCALL(glMapBufferARB(GL_ARRAY_BUFFER_ARB, GL_READ_ONLY_ARB));
5463 memcpy(SrcImpl->resource.allocatedMemory, src, SrcImpl->resource.size);
5466 GL_EXTCALL(glUnmapBufferARB(GL_ARRAY_BUFFER_ARB));
5467 checkGLcall("glUnmapBufferARB");
5472 GL_EXTCALL(glBindBufferARB(GL_ARRAY_BUFFER_ARB, 0));
5473 checkGLcall("glBindBufferARB");
5474 GL_EXTCALL(glDeleteBuffersARB(1, &SrcImpl->vbo));
5475 checkGLcall("glDeleteBuffersARB");
5481 memset(&strided, 0, sizeof(strided));
5482 primitiveConvertFVFtoOffset(SrcImpl->fvf, get_flexible_vertex_size(SrcImpl->fvf), SrcImpl->resource.allocatedMemory + get_flexible_vertex_size(SrcImpl->fvf) * SrcStartIndex, &strided, 0);
5484 return process_vertices_strided(This, DestIndex, VertexCount, &strided, SrcImpl->fvf, (IWineD3DVertexBufferImpl *) pDestBuffer, Flags);
5488 * Apply / Get / Set Texture Stage States
5489 * TODO: Verify against dx9 definitions
5492 /* 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 */
5493 static void WINAPI IWineD3DDeviceImpl_ApplyTextureUnitState(IWineD3DDevice *iface, DWORD Stage, WINED3DTEXTURESTAGESTATETYPE Type) {
5494 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5495 DWORD Value = This->updateStateBlock->textureState[Stage][Type];
5496 /* FIXME: Handle 3d textures? What if TSS value set before set texture? Need to reapply all values? */
5498 TRACE("(%p) : Stage=%d, Type=%s(%d), Value=%d\n", This, Stage, debug_d3dtexturestate(Type), Type, Value);
5500 /* Check that the stage is within limits */
5501 if (Stage >= GL_LIMITS(texture_stages) || Stage < 0) {
5502 TRACE("Attempt to access invalid texture rejected\n");
5509 case WINED3DTSS_ALPHAOP :
5510 case WINED3DTSS_COLOROP :
5511 /* nothing to do as moved to drawprim for now */
5513 case WINED3DTSS_ADDRESSW :
5514 #if 0 /* I'm not sure what D3D does about ADDRESSW appearing twice */
5515 if (Value < minLookup[WINELOOKUP_WARPPARAM] || Value > maxLookup[WINELOOKUP_WARPPARAM]) {
5516 FIXME("Unrecognized or unsupported WINED3DTADDRESS_* value %d, state %d\n", Value, Type);
5519 GLint wrapParm = stateLookup[WINELOOKUP_WARPPARAM][Value - minLookup[WINELOOKUP_WARPPARAM]];
5520 TRACE("Setting WRAP_R to %d for %x\n", wrapParm, This->stateBlock->textureDimensions[Stage]);
5521 glTexParameteri(This->stateBlock->textureDimensions[Stage], GL_TEXTURE_WRAP_R, wrapParm);
5522 checkGLcall("glTexParameteri(..., GL_TEXTURE_WRAP_R, wrapParm)");
5525 case WINED3DTSS_TEXCOORDINDEX :
5527 /* Values 0-7 are indexes into the FVF tex coords - See comments in DrawPrimitive */
5529 /* FIXME: From MSDN: The WINED3DTSS_TCI_* flags are mutually exclusive. If you include
5530 one flag, you can still specify an index value, which the system uses to
5531 determine the texture wrapping mode.
5532 eg. SetTextureStageState( 0, WINED3DTSS_TEXCOORDINDEX, WINED3DTSS_TCI_CAMERASPACEPOSITION | 1 );
5533 means use the vertex position (camera-space) as the input texture coordinates
5534 for this texture stage, and the wrap mode set in the WINED3DRS_WRAP1 render
5535 state. We do not (yet) support the WINED3DRENDERSTATE_WRAPx values, nor tie them up
5536 to the TEXCOORDINDEX value */
5539 * Be careful the value of the mask 0xF0000 come from d3d8types.h infos
5541 switch (Value & 0xFFFF0000) {
5542 case WINED3DTSS_TCI_PASSTHRU:
5543 /*Use the specified texture coordinates contained within the vertex format. This value resolves to zero.*/
5544 glDisable(GL_TEXTURE_GEN_S);
5545 glDisable(GL_TEXTURE_GEN_T);
5546 glDisable(GL_TEXTURE_GEN_R);
5547 glDisable(GL_TEXTURE_GEN_Q);
5548 checkGLcall("glDisable(GL_TEXTURE_GEN_S,T,R,Q)");
5551 case WINED3DTSS_TCI_CAMERASPACEPOSITION:
5552 /* CameraSpacePosition means use the vertex position, transformed to camera space,
5553 as the input texture coordinates for this stage's texture transformation. This
5554 equates roughly to EYE_LINEAR */
5556 float s_plane[] = { 1.0, 0.0, 0.0, 0.0 };
5557 float t_plane[] = { 0.0, 1.0, 0.0, 0.0 };
5558 float r_plane[] = { 0.0, 0.0, 1.0, 0.0 };
5559 float q_plane[] = { 0.0, 0.0, 0.0, 1.0 };
5560 TRACE("WINED3DTSS_TCI_CAMERASPACEPOSITION - Set eye plane\n");
5562 glMatrixMode(GL_MODELVIEW);
5565 glTexGenfv(GL_S, GL_EYE_PLANE, s_plane);
5566 glTexGenfv(GL_T, GL_EYE_PLANE, t_plane);
5567 glTexGenfv(GL_R, GL_EYE_PLANE, r_plane);
5568 glTexGenfv(GL_Q, GL_EYE_PLANE, q_plane);
5571 TRACE("WINED3DTSS_TCI_CAMERASPACEPOSITION - Set GL_TEXTURE_GEN_x and GL_x, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR\n");
5572 glEnable(GL_TEXTURE_GEN_S);
5573 checkGLcall("glEnable(GL_TEXTURE_GEN_S);");
5574 glTexGeni(GL_S, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR);
5575 checkGLcall("glTexGeni(GL_S, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR)");
5576 glEnable(GL_TEXTURE_GEN_T);
5577 checkGLcall("glEnable(GL_TEXTURE_GEN_T);");
5578 glTexGeni(GL_T, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR);
5579 checkGLcall("glTexGeni(GL_T, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR)");
5580 glEnable(GL_TEXTURE_GEN_R);
5581 checkGLcall("glEnable(GL_TEXTURE_GEN_R);");
5582 glTexGeni(GL_R, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR);
5583 checkGLcall("glTexGeni(GL_R, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR)");
5587 case WINED3DTSS_TCI_CAMERASPACENORMAL:
5589 if (GL_SUPPORT(NV_TEXGEN_REFLECTION)) {
5590 float s_plane[] = { 1.0, 0.0, 0.0, 0.0 };
5591 float t_plane[] = { 0.0, 1.0, 0.0, 0.0 };
5592 float r_plane[] = { 0.0, 0.0, 1.0, 0.0 };
5593 float q_plane[] = { 0.0, 0.0, 0.0, 1.0 };
5594 TRACE("WINED3DTSS_TCI_CAMERASPACENORMAL - Set eye plane\n");
5596 glMatrixMode(GL_MODELVIEW);
5599 glTexGenfv(GL_S, GL_EYE_PLANE, s_plane);
5600 glTexGenfv(GL_T, GL_EYE_PLANE, t_plane);
5601 glTexGenfv(GL_R, GL_EYE_PLANE, r_plane);
5602 glTexGenfv(GL_Q, GL_EYE_PLANE, q_plane);
5605 glEnable(GL_TEXTURE_GEN_S);
5606 checkGLcall("glEnable(GL_TEXTURE_GEN_S);");
5607 glTexGeni(GL_S, GL_TEXTURE_GEN_MODE, GL_NORMAL_MAP_NV);
5608 checkGLcall("glTexGeni(GL_S, GL_TEXTURE_GEN_MODE, GL_NORMAL_MAP_NV)");
5609 glEnable(GL_TEXTURE_GEN_T);
5610 checkGLcall("glEnable(GL_TEXTURE_GEN_T);");
5611 glTexGeni(GL_T, GL_TEXTURE_GEN_MODE, GL_NORMAL_MAP_NV);
5612 checkGLcall("glTexGeni(GL_T, GL_TEXTURE_GEN_MODE, GL_NORMAL_MAP_NV)");
5613 glEnable(GL_TEXTURE_GEN_R);
5614 checkGLcall("glEnable(GL_TEXTURE_GEN_R);");
5615 glTexGeni(GL_R, GL_TEXTURE_GEN_MODE, GL_NORMAL_MAP_NV);
5616 checkGLcall("glTexGeni(GL_R, GL_TEXTURE_GEN_MODE, GL_NORMAL_MAP_NV)");
5621 case WINED3DTSS_TCI_CAMERASPACEREFLECTIONVECTOR:
5623 if (GL_SUPPORT(NV_TEXGEN_REFLECTION)) {
5624 float s_plane[] = { 1.0, 0.0, 0.0, 0.0 };
5625 float t_plane[] = { 0.0, 1.0, 0.0, 0.0 };
5626 float r_plane[] = { 0.0, 0.0, 1.0, 0.0 };
5627 float q_plane[] = { 0.0, 0.0, 0.0, 1.0 };
5628 TRACE("WINED3DTSS_TCI_CAMERASPACEREFLECTIONVECTOR - Set eye plane\n");
5630 glMatrixMode(GL_MODELVIEW);
5633 glTexGenfv(GL_S, GL_EYE_PLANE, s_plane);
5634 glTexGenfv(GL_T, GL_EYE_PLANE, t_plane);
5635 glTexGenfv(GL_R, GL_EYE_PLANE, r_plane);
5636 glTexGenfv(GL_Q, GL_EYE_PLANE, q_plane);
5639 glEnable(GL_TEXTURE_GEN_S);
5640 checkGLcall("glEnable(GL_TEXTURE_GEN_S);");
5641 glTexGeni(GL_S, GL_TEXTURE_GEN_MODE, GL_REFLECTION_MAP_NV);
5642 checkGLcall("glTexGeni(GL_S, GL_TEXTURE_GEN_MODE, GL_REFLECTION_MAP_NV)");
5643 glEnable(GL_TEXTURE_GEN_T);
5644 checkGLcall("glEnable(GL_TEXTURE_GEN_T);");
5645 glTexGeni(GL_T, GL_TEXTURE_GEN_MODE, GL_REFLECTION_MAP_NV);
5646 checkGLcall("glTexGeni(GL_T, GL_TEXTURE_GEN_MODE, GL_REFLECTION_MAP_NV)");
5647 glEnable(GL_TEXTURE_GEN_R);
5648 checkGLcall("glEnable(GL_TEXTURE_GEN_R);");
5649 glTexGeni(GL_R, GL_TEXTURE_GEN_MODE, GL_REFLECTION_MAP_NV);
5650 checkGLcall("glTexGeni(GL_R, GL_TEXTURE_GEN_MODE, GL_REFLECTION_MAP_NV)");
5655 /* Unhandled types: */
5658 /* ? disable GL_TEXTURE_GEN_n ? */
5659 glDisable(GL_TEXTURE_GEN_S);
5660 glDisable(GL_TEXTURE_GEN_T);
5661 glDisable(GL_TEXTURE_GEN_R);
5662 glDisable(GL_TEXTURE_GEN_Q);
5663 FIXME("Unhandled WINED3DTSS_TEXCOORDINDEX %x\n", Value);
5670 case WINED3DTSS_TEXTURETRANSFORMFLAGS :
5671 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);
5674 case WINED3DTSS_BUMPENVMAT00 :
5675 case WINED3DTSS_BUMPENVMAT01 :
5676 TRACE("BUMPENVMAT0%u Stage=%d, Type=%d, Value =%d\n", Type - WINED3DTSS_BUMPENVMAT00, Stage, Type, Value);
5678 case WINED3DTSS_BUMPENVMAT10 :
5679 case WINED3DTSS_BUMPENVMAT11 :
5680 TRACE("BUMPENVMAT1%u Stage=%d, Type=%d, Value =%d\n", Type - WINED3DTSS_BUMPENVMAT10, Stage, Type, Value);
5683 case WINED3DTSS_BUMPENVLSCALE :
5684 TRACE("BUMPENVLSCALE Stage=%d, Type=%d, Value =%d\n", Stage, Type, Value);
5687 case WINED3DTSS_BUMPENVLOFFSET :
5688 TRACE("BUMPENVLOFFSET Stage=%d, Type=%d, Value =%d\n", Stage, Type, Value);
5691 case WINED3DTSS_RESULTARG :
5692 TRACE("RESULTARG Still a stub, Stage=%d, Type=%d, Value =%d\n", Stage, Type, Value);
5696 /* Put back later: FIXME("(%p) : stub, Stage=%d, Type=%d, Value =%d\n", This, Stage, Type, Value); */
5697 TRACE("Still a stub, Stage=%d, Type=%d, Value =%d\n", Stage, Type, Value);
5706 * Get / Set Texture Stage States
5707 * TODO: Verify against dx9 definitions
5709 static HRESULT WINAPI IWineD3DDeviceImpl_SetTextureStageState(IWineD3DDevice *iface, DWORD Stage, WINED3DTEXTURESTAGESTATETYPE Type, DWORD Value) {
5710 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5712 /* FIXME: Handle 3d textures? What if TSS value set before set texture? Need to reapply all values? */
5714 TRACE("(%p) : Stage=%d, Type=%s(%d), Value=%d\n", This, Stage, debug_d3dtexturestate(Type), Type, Value);
5716 /* Reject invalid texture units */
5717 if (Stage >= GL_LIMITS(texture_stages)) {
5718 TRACE("Attempt to access invalid texture rejected\n");
5719 return WINED3DERR_INVALIDCALL;
5722 This->updateStateBlock->changed.textureState[Stage][Type] = TRUE;
5723 This->updateStateBlock->set.textureState[Stage][Type] = TRUE;
5724 This->updateStateBlock->textureState[Stage][Type] = Value;
5729 static HRESULT WINAPI IWineD3DDeviceImpl_GetTextureStageState(IWineD3DDevice *iface, DWORD Stage, WINED3DTEXTURESTAGESTATETYPE Type, DWORD* pValue) {
5730 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5731 TRACE("(%p) : requesting Stage %d, Type %d getting %d\n", This, Stage, Type, This->updateStateBlock->textureState[Stage][Type]);
5732 *pValue = This->updateStateBlock->textureState[Stage][Type];
5739 static HRESULT WINAPI IWineD3DDeviceImpl_SetTexture(IWineD3DDevice *iface, DWORD Stage, IWineD3DBaseTexture* pTexture) {
5741 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5742 IWineD3DBaseTexture *oldTexture;
5744 oldTexture = This->updateStateBlock->textures[Stage];
5745 TRACE("(%p) : Stage(%d), Texture (%p)\n", This, Stage, pTexture);
5747 #if 0 /* TODO: check so vertex textures */
5748 if (Stage >= D3DVERTEXTEXTURESAMPLER && Stage <= D3DVERTEXTEXTURESAMPLER3){
5749 This->updateStateBlock->vertexTextures[Stage - D3DVERTEXTEXTURESAMPLER] = pTexture;
5754 /* Reject invalid texture units */
5755 if (Stage >= GL_LIMITS(sampler_stages) || Stage < 0) {
5756 WARN("Attempt to access invalid texture rejected\n");
5757 return WINED3DERR_INVALIDCALL;
5760 if(pTexture != NULL) {
5761 /* SetTexture isn't allowed on textures in WINED3DPOOL_SCRATCH;
5763 if(((IWineD3DTextureImpl*)pTexture)->resource.pool == WINED3DPOOL_SCRATCH) {
5764 WARN("(%p) Attempt to set scratch texture rejected\n", pTexture);
5765 return WINED3DERR_INVALIDCALL;
5769 oldTexture = This->updateStateBlock->textures[Stage];
5770 TRACE("GL_LIMITS %d\n",GL_LIMITS(sampler_stages));
5771 TRACE("(%p) : oldtexture(%p)\n", This,oldTexture);
5773 This->updateStateBlock->set.textures[Stage] = TRUE;
5774 This->updateStateBlock->changed.textures[Stage] = TRUE;
5775 TRACE("(%p) : setting new texture to %p\n", This, pTexture);
5776 This->updateStateBlock->textures[Stage] = pTexture;
5778 /* Handle recording of state blocks */
5779 if (This->isRecordingState) {
5780 TRACE("Recording... not performing anything\n");
5784 /** NOTE: MSDN says that setTexture increases the reference count,
5785 * and the the application nust set the texture back to null (or have a leaky application),
5786 * This means we should pass the refcount up to the parent
5787 *******************************/
5788 if (NULL != This->updateStateBlock->textures[Stage]) {
5789 IWineD3DBaseTexture_AddRef(This->updateStateBlock->textures[Stage]);
5792 if (NULL != oldTexture) {
5793 IWineD3DBaseTexture_Release(oldTexture);
5796 /* Reset color keying */
5797 if(Stage == 0 && This->stateBlock->renderState[WINED3DRS_COLORKEYENABLE]) {
5798 BOOL enable_ckey = FALSE;
5801 IWineD3DSurfaceImpl *surf = (IWineD3DSurfaceImpl *) ((IWineD3DTextureImpl *)pTexture)->surfaces[0];
5802 if(surf->CKeyFlags & DDSD_CKSRCBLT) enable_ckey = TRUE;
5806 glAlphaFunc(GL_NOTEQUAL, 0.0);
5807 checkGLcall("glAlphaFunc");
5814 static HRESULT WINAPI IWineD3DDeviceImpl_GetTexture(IWineD3DDevice *iface, DWORD Stage, IWineD3DBaseTexture** ppTexture) {
5815 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5816 TRACE("(%p) : (%d /* Stage */,%p /* ppTexture */)\n", This, Stage, ppTexture);
5818 /* Reject invalid texture units */
5819 if (Stage >= GL_LIMITS(sampler_stages)) {
5820 TRACE("Attempt to access invalid texture rejected\n");
5821 return WINED3DERR_INVALIDCALL;
5823 *ppTexture=This->stateBlock->textures[Stage];
5831 static HRESULT WINAPI IWineD3DDeviceImpl_GetBackBuffer(IWineD3DDevice *iface, UINT iSwapChain, UINT BackBuffer, WINED3DBACKBUFFER_TYPE Type,
5832 IWineD3DSurface **ppBackBuffer) {
5833 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5834 IWineD3DSwapChain *swapChain;
5837 TRACE("(%p) : BackBuf %d Type %d SwapChain %d returning %p\n", This, BackBuffer, Type, iSwapChain, *ppBackBuffer);
5839 hr = IWineD3DDeviceImpl_GetSwapChain(iface, iSwapChain, &swapChain);
5840 if (hr == WINED3D_OK) {
5841 hr = IWineD3DSwapChain_GetBackBuffer(swapChain, BackBuffer, Type, ppBackBuffer);
5843 *ppBackBuffer = NULL;
5848 static HRESULT WINAPI IWineD3DDeviceImpl_GetDeviceCaps(IWineD3DDevice *iface, WINED3DCAPS* pCaps) {
5849 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5850 WARN("(%p) : stub, calling idirect3d for now\n", This);
5851 return IWineD3D_GetDeviceCaps(This->wineD3D, This->adapterNo, This->devType, pCaps);
5854 static HRESULT WINAPI IWineD3DDeviceImpl_GetDisplayMode(IWineD3DDevice *iface, UINT iSwapChain, WINED3DDISPLAYMODE* pMode) {
5855 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5856 IWineD3DSwapChain *swapChain;
5859 if(iSwapChain > 0) {
5860 hr = IWineD3DDeviceImpl_GetSwapChain(iface, iSwapChain, (IWineD3DSwapChain **)&swapChain);
5861 if (hr == WINED3D_OK) {
5862 hr = IWineD3DSwapChain_GetDisplayMode(swapChain, pMode);
5864 FIXME("(%p) Error getting display mode\n", This);
5867 /* Don't read the real display mode,
5868 but return the stored mode instead. X11 can't change the color
5869 depth, and some apps are pretty angry if they SetDisplayMode from
5870 24 to 16 bpp and find out that GetDisplayMode still returns 24 bpp
5872 Also don't relay to the swapchain because with ddraw it's possible
5873 that there isn't a swapchain at all */
5874 pMode->Width = This->ddraw_width;
5875 pMode->Height = This->ddraw_height;
5876 pMode->Format = This->ddraw_format;
5877 pMode->RefreshRate = 0;
5884 static HRESULT WINAPI IWineD3DDeviceImpl_SetHWND(IWineD3DDevice *iface, HWND hWnd) {
5885 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5886 TRACE("(%p)->(%p)\n", This, hWnd);
5888 This->ddraw_window = hWnd;
5892 static HRESULT WINAPI IWineD3DDeviceImpl_GetHWND(IWineD3DDevice *iface, HWND *hWnd) {
5893 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5894 TRACE("(%p)->(%p)\n", This, hWnd);
5896 *hWnd = This->ddraw_window;
5901 * Stateblock related functions
5904 static HRESULT WINAPI IWineD3DDeviceImpl_BeginStateBlock(IWineD3DDevice *iface) {
5905 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5906 IWineD3DStateBlockImpl *object;
5907 HRESULT temp_result;
5909 TRACE("(%p)\n", This);
5911 if (This->isRecordingState) {
5912 return WINED3DERR_INVALIDCALL;
5915 object = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(IWineD3DStateBlockImpl));
5916 if (NULL == object ) {
5917 FIXME("(%p)Error allocating memory for stateblock\n", This);
5918 return E_OUTOFMEMORY;
5920 TRACE("(%p) created object %p\n", This, object);
5921 object->wineD3DDevice= This;
5922 /** FIXME: object->parent = parent; **/
5923 object->parent = NULL;
5924 object->blockType = WINED3DSBT_ALL;
5926 object->lpVtbl = &IWineD3DStateBlock_Vtbl;
5928 temp_result = allocate_shader_constants(object);
5929 if (WINED3D_OK != temp_result)
5932 IWineD3DStateBlock_Release((IWineD3DStateBlock*)This->updateStateBlock);
5933 This->updateStateBlock = object;
5934 This->isRecordingState = TRUE;
5936 TRACE("(%p) recording stateblock %p\n",This , object);
5940 static HRESULT WINAPI IWineD3DDeviceImpl_EndStateBlock(IWineD3DDevice *iface, IWineD3DStateBlock** ppStateBlock) {
5941 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5943 if (!This->isRecordingState) {
5944 FIXME("(%p) not recording! returning error\n", This);
5945 *ppStateBlock = NULL;
5946 return WINED3DERR_INVALIDCALL;
5949 *ppStateBlock = (IWineD3DStateBlock*)This->updateStateBlock;
5950 This->isRecordingState = FALSE;
5951 This->updateStateBlock = This->stateBlock;
5952 IWineD3DStateBlock_AddRef((IWineD3DStateBlock*)This->updateStateBlock);
5953 /* IWineD3DStateBlock_AddRef(*ppStateBlock); don't need to do this, since we should really just release UpdateStateBlock first */
5954 TRACE("(%p) returning token (ptr to stateblock) of %p\n", This, *ppStateBlock);
5959 * Scene related functions
5961 static HRESULT WINAPI IWineD3DDeviceImpl_BeginScene(IWineD3DDevice *iface) {
5962 /* At the moment we have no need for any functionality at the beginning
5964 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5965 TRACE("(%p) : stub\n", This);
5969 static HRESULT WINAPI IWineD3DDeviceImpl_EndScene(IWineD3DDevice *iface) {
5970 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5971 TRACE("(%p)\n", This);
5973 /* We only have to do this if we need to read the, swapbuffers performs a flush for us */
5975 checkGLcall("glFlush");
5977 TRACE("End Scene\n");
5978 /* If we're using FBOs this isn't needed */
5979 if (wined3d_settings.offscreen_rendering_mode != ORM_FBO && This->renderTarget != NULL) {
5981 /* If the container of the rendertarget is a texture then we need to save the data from the pbuffer */
5982 IUnknown *targetContainer = NULL;
5983 if (WINED3D_OK == IWineD3DSurface_GetContainer(This->renderTarget, &IID_IWineD3DBaseTexture, (void **)&targetContainer)
5984 || WINED3D_OK == IWineD3DSurface_GetContainer(This->renderTarget, &IID_IWineD3DDevice, (void **)&targetContainer)) {
5985 TRACE("(%p) : Texture rendertarget %p\n", This ,This->renderTarget);
5986 /** always dirtify for now. we must find a better way to see that surface have been modified
5987 (Modifications should will only occur via draw-primitive, but we do need better locking
5988 switching to render-to-texture should remove the overhead though.
5990 IWineD3DSurface_SetPBufferState(This->renderTarget, TRUE /* inPBuffer */, FALSE /* inTexture */);
5991 IWineD3DSurface_AddDirtyRect(This->renderTarget, NULL);
5992 IWineD3DSurface_PreLoad(This->renderTarget);
5993 IWineD3DSurface_SetPBufferState(This->renderTarget, FALSE /* inPBuffer */, FALSE /* inTexture */);
5994 IUnknown_Release(targetContainer);
5997 This->sceneEnded = TRUE;
6002 static HRESULT WINAPI IWineD3DDeviceImpl_Present(IWineD3DDevice *iface,
6003 CONST RECT* pSourceRect, CONST RECT* pDestRect,
6004 HWND hDestWindowOverride, CONST RGNDATA* pDirtyRegion) {
6005 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
6006 IWineD3DSwapChain *swapChain = NULL;
6008 int swapchains = IWineD3DDeviceImpl_GetNumberOfSwapChains(iface);
6010 TRACE("(%p) Presenting the frame\n", This);
6012 for(i = 0 ; i < swapchains ; i ++) {
6014 IWineD3DDeviceImpl_GetSwapChain(iface, i , (IWineD3DSwapChain **)&swapChain);
6015 TRACE("presentinng chain %d, %p\n", i, swapChain);
6016 IWineD3DSwapChain_Present(swapChain, pSourceRect, pDestRect, hDestWindowOverride, pDirtyRegion, 0);
6022 static HRESULT WINAPI IWineD3DDeviceImpl_Clear(IWineD3DDevice *iface, DWORD Count, CONST WINED3DRECT* pRects,
6023 DWORD Flags, WINED3DCOLOR Color, float Z, DWORD Stencil) {
6024 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
6026 /* TODO: From MSDN This method fails if you specify the WINED3DCLEAR_ZBUFFER or WINED3DCLEAR_STENCIL flags when the
6027 render target does not have an attached depth buffer. Similarly, if you specify the WINED3DCLEAR_STENCIL flag
6028 when the depth-buffer format does not contain stencil buffer information, this method fails. */
6029 GLbitfield glMask = 0;
6030 GLboolean old_ztest;
6031 GLfloat old_z_clear_value;
6032 GLint old_stencil_clear_value;
6033 GLfloat old_color_clear_value[4];
6035 CONST WINED3DRECT* curRect;
6037 TRACE("(%p) Count (%d), pRects (%p), Flags (%x), Z (%f), Stencil (%d)\n", This,
6038 Count, pRects, Flags, Z, Stencil);
6042 glEnable(GL_SCISSOR_TEST);
6043 checkGLcall("glEnable GL_SCISSOR_TEST");
6045 if (Count > 0 && pRects) {
6051 /* Only set the values up once, as they are not changing */
6052 if (Flags & WINED3DCLEAR_STENCIL) {
6053 glGetIntegerv(GL_STENCIL_CLEAR_VALUE, &old_stencil_clear_value);
6054 glClearStencil(Stencil);
6055 checkGLcall("glClearStencil");
6056 glMask = glMask | GL_STENCIL_BUFFER_BIT;
6057 glStencilMask(0xFFFFFFFF);
6060 if (Flags & WINED3DCLEAR_ZBUFFER) {
6061 glGetBooleanv(GL_DEPTH_WRITEMASK, &old_ztest);
6062 glDepthMask(GL_TRUE);
6063 glGetFloatv(GL_DEPTH_CLEAR_VALUE, &old_z_clear_value);
6065 checkGLcall("glClearDepth");
6066 glMask = glMask | GL_DEPTH_BUFFER_BIT;
6069 if (Flags & WINED3DCLEAR_TARGET) {
6070 TRACE("Clearing screen with glClear to color %x\n", Color);
6071 glGetFloatv(GL_COLOR_CLEAR_VALUE, old_color_clear_value);
6072 glClearColor(D3DCOLOR_R(Color),
6076 checkGLcall("glClearColor");
6078 /* Clear ALL colors! */
6079 glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
6080 glMask = glMask | GL_COLOR_BUFFER_BIT;
6083 /* Now process each rect in turn */
6084 for (i = 0; i < Count || i == 0; i++) {
6087 /* Note gl uses lower left, width/height */
6088 TRACE("(%p) %p Rect=(%d,%d)->(%d,%d) glRect=(%d,%d), len=%d, hei=%d\n", This, curRect,
6089 curRect->x1, curRect->y1, curRect->x2, curRect->y2,
6090 curRect->x1, (((IWineD3DSurfaceImpl *)This->renderTarget)->currentDesc.Height - curRect->y2),
6091 curRect->x2 - curRect->x1, curRect->y2 - curRect->y1);
6092 glScissor(curRect->x1, (((IWineD3DSurfaceImpl *)This->renderTarget)->currentDesc.Height - curRect->y2),
6093 curRect->x2 - curRect->x1, curRect->y2 - curRect->y1);
6094 checkGLcall("glScissor");
6096 glScissor(This->stateBlock->viewport.X,
6097 (((IWineD3DSurfaceImpl *)This->renderTarget)->currentDesc.Height -
6098 (This->stateBlock->viewport.Y + This->stateBlock->viewport.Height)),
6099 This->stateBlock->viewport.Width,
6100 This->stateBlock->viewport.Height);
6101 checkGLcall("glScissor");
6104 /* Clear the selected rectangle (or full screen) */
6106 checkGLcall("glClear");
6108 /* Step to the next rectangle */
6109 if (curRect) curRect = curRect + sizeof(WINED3DRECT);
6112 /* Restore the old values (why..?) */
6113 if (Flags & WINED3DCLEAR_STENCIL) {
6114 glClearStencil(old_stencil_clear_value);
6115 glStencilMask(This->stateBlock->renderState[WINED3DRS_STENCILWRITEMASK]);
6117 if (Flags & WINED3DCLEAR_ZBUFFER) {
6118 glDepthMask(old_ztest);
6119 glClearDepth(old_z_clear_value);
6121 if (Flags & WINED3DCLEAR_TARGET) {
6122 glClearColor(old_color_clear_value[0],
6123 old_color_clear_value[1],
6124 old_color_clear_value[2],
6125 old_color_clear_value[3]);
6126 glColorMask(This->stateBlock->renderState[WINED3DRS_COLORWRITEENABLE] & WINED3DCOLORWRITEENABLE_RED ? GL_TRUE : GL_FALSE,
6127 This->stateBlock->renderState[WINED3DRS_COLORWRITEENABLE] & WINED3DCOLORWRITEENABLE_GREEN ? GL_TRUE : GL_FALSE,
6128 This->stateBlock->renderState[WINED3DRS_COLORWRITEENABLE] & WINED3DCOLORWRITEENABLE_BLUE ? GL_TRUE : GL_FALSE,
6129 This->stateBlock->renderState[WINED3DRS_COLORWRITEENABLE] & WINED3DCOLORWRITEENABLE_ALPHA ? GL_TRUE : GL_FALSE);
6132 glDisable(GL_SCISSOR_TEST);
6133 checkGLcall("glDisable");
6142 static HRESULT WINAPI IWineD3DDeviceImpl_DrawPrimitive(IWineD3DDevice *iface, WINED3DPRIMITIVETYPE PrimitiveType, UINT StartVertex,
6143 UINT PrimitiveCount) {
6145 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
6146 This->stateBlock->streamIsUP = FALSE;
6148 TRACE("(%p) : Type=(%d,%s), Start=%d, Count=%d\n", This, PrimitiveType,
6149 debug_d3dprimitivetype(PrimitiveType),
6150 StartVertex, PrimitiveCount);
6151 drawPrimitive(iface, PrimitiveType, PrimitiveCount, StartVertex, 0/* NumVertices */, -1 /* indxStart */,
6152 0 /* indxSize */, NULL /* indxData */, 0 /* minIndex */, NULL);
6158 /* TODO: baseVIndex needs to be provided from This->stateBlock->baseVertexIndex when called from d3d8 */
6159 static HRESULT WINAPI IWineD3DDeviceImpl_DrawIndexedPrimitive(IWineD3DDevice *iface,
6160 WINED3DPRIMITIVETYPE PrimitiveType,
6161 INT baseVIndex, UINT minIndex,
6162 UINT NumVertices, UINT startIndex, UINT primCount) {
6164 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
6166 IWineD3DIndexBuffer *pIB;
6167 WINED3DINDEXBUFFER_DESC IdxBufDsc;
6169 pIB = This->stateBlock->pIndexData;
6170 This->stateBlock->streamIsUP = FALSE;
6172 TRACE("(%p) : Type=(%d,%s), min=%d, CountV=%d, startIdx=%d, baseVidx=%d, countP=%d\n", This,
6173 PrimitiveType, debug_d3dprimitivetype(PrimitiveType),
6174 minIndex, NumVertices, startIndex, baseVIndex, primCount);
6176 IWineD3DIndexBuffer_GetDesc(pIB, &IdxBufDsc);
6177 if (IdxBufDsc.Format == WINED3DFMT_INDEX16) {
6183 drawPrimitive(iface, PrimitiveType, primCount, baseVIndex, NumVertices, startIndex,
6184 idxStride, ((IWineD3DIndexBufferImpl *) pIB)->resource.allocatedMemory, minIndex, NULL);
6189 static HRESULT WINAPI IWineD3DDeviceImpl_DrawPrimitiveUP(IWineD3DDevice *iface, WINED3DPRIMITIVETYPE PrimitiveType,
6190 UINT PrimitiveCount, CONST void* pVertexStreamZeroData,
6191 UINT VertexStreamZeroStride) {
6192 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
6194 TRACE("(%p) : Type=(%d,%s), pCount=%d, pVtxData=%p, Stride=%d\n", This, PrimitiveType,
6195 debug_d3dprimitivetype(PrimitiveType),
6196 PrimitiveCount, pVertexStreamZeroData, VertexStreamZeroStride);
6198 /* release the stream source */
6199 if (This->stateBlock->streamSource[0] != NULL) {
6200 IWineD3DVertexBuffer_Release(This->stateBlock->streamSource[0]);
6203 /* Note in the following, it's not this type, but that's the purpose of streamIsUP */
6204 This->stateBlock->streamSource[0] = (IWineD3DVertexBuffer *)pVertexStreamZeroData;
6205 This->stateBlock->streamStride[0] = VertexStreamZeroStride;
6206 This->stateBlock->streamIsUP = TRUE;
6208 drawPrimitive(iface, PrimitiveType, PrimitiveCount, 0 /* start vertex */, 0 /* NumVertices */,
6209 0 /* indxStart*/, 0 /* indxSize*/, NULL /* indxData */, 0 /* indxMin */, NULL);
6211 /* MSDN specifies stream zero settings must be set to NULL */
6212 This->stateBlock->streamStride[0] = 0;
6213 This->stateBlock->streamSource[0] = NULL;
6215 /*stream zero settings set to null at end, as per the msdn */
6219 static HRESULT WINAPI IWineD3DDeviceImpl_DrawIndexedPrimitiveUP(IWineD3DDevice *iface, WINED3DPRIMITIVETYPE PrimitiveType,
6220 UINT MinVertexIndex, UINT NumVertices,
6221 UINT PrimitiveCount, CONST void* pIndexData,
6222 WINED3DFORMAT IndexDataFormat,CONST void* pVertexStreamZeroData,
6223 UINT VertexStreamZeroStride) {
6225 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
6227 TRACE("(%p) : Type=(%d,%s), MinVtxIdx=%d, NumVIdx=%d, PCount=%d, pidxdata=%p, IdxFmt=%d, pVtxdata=%p, stride=%d\n",
6228 This, PrimitiveType, debug_d3dprimitivetype(PrimitiveType),
6229 MinVertexIndex, NumVertices, PrimitiveCount, pIndexData,
6230 IndexDataFormat, pVertexStreamZeroData, VertexStreamZeroStride);
6232 if (IndexDataFormat == WINED3DFMT_INDEX16) {
6238 /* release the stream and index data */
6239 if (This->stateBlock->streamSource[0] != NULL) {
6240 IWineD3DVertexBuffer_Release(This->stateBlock->streamSource[0]);
6242 if (This->stateBlock->pIndexData) {
6243 IWineD3DIndexBuffer_Release(This->stateBlock->pIndexData);
6246 /* Note in the following, it's not this type, but that's the purpose of streamIsUP */
6247 This->stateBlock->streamSource[0] = (IWineD3DVertexBuffer *)pVertexStreamZeroData;
6248 This->stateBlock->streamIsUP = TRUE;
6249 This->stateBlock->streamStride[0] = VertexStreamZeroStride;
6251 drawPrimitive(iface, PrimitiveType, PrimitiveCount, 0 /* vertexStart */, NumVertices, 0 /* indxStart */, idxStride, pIndexData, MinVertexIndex, NULL);
6253 /* MSDN specifies stream zero settings and index buffer must be set to NULL */
6254 This->stateBlock->streamSource[0] = NULL;
6255 This->stateBlock->streamStride[0] = 0;
6256 This->stateBlock->pIndexData = NULL;
6261 static HRESULT WINAPI IWineD3DDeviceImpl_DrawPrimitiveStrided (IWineD3DDevice *iface, WINED3DPRIMITIVETYPE PrimitiveType, UINT PrimitiveCount, WineDirect3DVertexStridedData *DrawPrimStrideData) {
6263 drawPrimitive(iface, PrimitiveType, PrimitiveCount, 0, 0, 0, 0, NULL, 0, DrawPrimStrideData);
6266 /* Yet another way to update a texture, some apps use this to load default textures instead of using surface/texture lock/unlock */
6267 static HRESULT WINAPI IWineD3DDeviceImpl_UpdateTexture (IWineD3DDevice *iface, IWineD3DBaseTexture *pSourceTexture, IWineD3DBaseTexture *pDestinationTexture){
6268 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
6269 HRESULT hr = WINED3D_OK;
6270 WINED3DRESOURCETYPE sourceType;
6271 WINED3DRESOURCETYPE destinationType;
6274 /* TODO: think about moving the code into IWineD3DBaseTexture */
6276 TRACE("(%p) Source %p Destination %p\n", This, pSourceTexture, pDestinationTexture);
6278 /* verify that the source and destination textures aren't NULL */
6279 if (NULL == pSourceTexture || NULL == pDestinationTexture) {
6280 WARN("(%p) : source (%p) and destination (%p) textures must not be NULL, returning WINED3DERR_INVALIDCALL\n",
6281 This, pSourceTexture, pDestinationTexture);
6282 hr = WINED3DERR_INVALIDCALL;
6285 if (pSourceTexture == pDestinationTexture) {
6286 WARN("(%p) : source (%p) and destination (%p) textures must be different, returning WINED3DERR_INVALIDCALL\n",
6287 This, pSourceTexture, pDestinationTexture);
6288 hr = WINED3DERR_INVALIDCALL;
6290 /* Verify that the source and destination textures are the same type */
6291 sourceType = IWineD3DBaseTexture_GetType(pSourceTexture);
6292 destinationType = IWineD3DBaseTexture_GetType(pDestinationTexture);
6294 if (sourceType != destinationType) {
6295 WARN("(%p) Sorce and destination types must match, returning WINED3DERR_INVALIDCALL\n",
6297 hr = WINED3DERR_INVALIDCALL;
6300 /* check that both textures have the identical numbers of levels */
6301 if (IWineD3DBaseTexture_GetLevelCount(pDestinationTexture) != IWineD3DBaseTexture_GetLevelCount(pSourceTexture)) {
6302 WARN("(%p) : source (%p) and destination (%p) textures must have identicle numbers of levels, returning WINED3DERR_INVALIDCALL\n", This, pSourceTexture, pDestinationTexture);
6303 hr = WINED3DERR_INVALIDCALL;
6306 if (WINED3D_OK == hr) {
6308 /* Make sure that the destination texture is loaded */
6309 IWineD3DBaseTexture_PreLoad(pDestinationTexture);
6311 /* Update every surface level of the texture */
6312 levels = IWineD3DBaseTexture_GetLevelCount(pDestinationTexture);
6314 switch (sourceType) {
6315 case WINED3DRTYPE_TEXTURE:
6317 IWineD3DSurface *srcSurface;
6318 IWineD3DSurface *destSurface;
6320 for (i = 0 ; i < levels ; ++i) {
6321 IWineD3DTexture_GetSurfaceLevel((IWineD3DTexture *)pSourceTexture, i, &srcSurface);
6322 IWineD3DTexture_GetSurfaceLevel((IWineD3DTexture *)pDestinationTexture, i, &destSurface);
6323 hr = IWineD3DDevice_UpdateSurface(iface, srcSurface, NULL, destSurface, NULL);
6324 IWineD3DSurface_Release(srcSurface);
6325 IWineD3DSurface_Release(destSurface);
6326 if (WINED3D_OK != hr) {
6327 WARN("(%p) : Call to update surface failed\n", This);
6333 case WINED3DRTYPE_CUBETEXTURE:
6335 IWineD3DSurface *srcSurface;
6336 IWineD3DSurface *destSurface;
6337 WINED3DCUBEMAP_FACES faceType;
6339 for (i = 0 ; i < levels ; ++i) {
6340 /* Update each cube face */
6341 for (faceType = WINED3DCUBEMAP_FACE_POSITIVE_X; faceType <= WINED3DCUBEMAP_FACE_NEGATIVE_Z; ++faceType){
6342 hr = IWineD3DCubeTexture_GetCubeMapSurface((IWineD3DCubeTexture *)pSourceTexture, faceType, i, &srcSurface);
6343 if (WINED3D_OK != hr) {
6344 FIXME("(%p) : Failed to get src cube surface facetype %d, level %d\n", This, faceType, i);
6346 TRACE("Got srcSurface %p\n", srcSurface);
6348 hr = IWineD3DCubeTexture_GetCubeMapSurface((IWineD3DCubeTexture *)pDestinationTexture, faceType, i, &destSurface);
6349 if (WINED3D_OK != hr) {
6350 FIXME("(%p) : Failed to get src cube surface facetype %d, level %d\n", This, faceType, i);
6352 TRACE("Got desrSurface %p\n", destSurface);
6354 hr = IWineD3DDevice_UpdateSurface(iface, srcSurface, NULL, destSurface, NULL);
6355 IWineD3DSurface_Release(srcSurface);
6356 IWineD3DSurface_Release(destSurface);
6357 if (WINED3D_OK != hr) {
6358 WARN("(%p) : Call to update surface failed\n", This);
6365 #if 0 /* TODO: Add support for volume textures */
6366 case WINED3DRTYPE_VOLUMETEXTURE:
6368 IWineD3DVolume srcVolume = NULL;
6369 IWineD3DSurface destVolume = NULL;
6371 for (i = 0 ; i < levels ; ++i) {
6372 IWineD3DVolumeTexture_GetVolume((IWineD3DVolumeTexture *)pSourceTexture, i, &srcVolume);
6373 IWineD3DVolumeTexture_GetVolume((IWineD3DVolumeTexture *)pDestinationTexture, i, &destVolume);
6374 hr = IWineD3DFoo_UpdateVolume(iface, srcVolume, NULL, destVolume, NULL);
6375 IWineD3DVolume_Release(srcSurface);
6376 IWineD3DVolume_Release(destSurface);
6377 if (WINED3D_OK != hr) {
6378 WARN("(%p) : Call to update volume failed\n", This);
6386 FIXME("(%p) : Unsupported source and destination type\n", This);
6387 hr = WINED3DERR_INVALIDCALL;
6394 static HRESULT WINAPI IWineD3DDeviceImpl_StretchRect(IWineD3DDevice *iface, IWineD3DSurface *pSourceSurface,
6395 CONST RECT* pSourceRect, IWineD3DSurface *pDestinationSurface,
6396 CONST RECT* pDestRect, WINED3DTEXTUREFILTERTYPE Filter) {
6397 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
6399 TRACE("(%p) : stub\n", This);
6402 static HRESULT WINAPI IWineD3DDeviceImpl_GetRenderTargetData(IWineD3DDevice *iface, IWineD3DSurface *pRenderTarget, IWineD3DSurface *pSurface) {
6403 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
6404 /** TODO: remove remove casts to IWineD3DSurfaceImpl *
6405 * NOTE It may be best to move the code into surface to occomplish this
6406 ****************************************/
6408 WINED3DSURFACE_DESC surfaceDesc;
6409 unsigned int surfaceWidth, surfaceHeight;
6410 glDescriptor *targetGlDescription = NULL;
6411 glDescriptor *surfaceGlDescription = NULL;
6412 IWineD3DSwapChainImpl *container = NULL;
6414 IWineD3DSurface_GetGlDesc(pRenderTarget, &targetGlDescription);
6415 IWineD3DSurface_GetGlDesc(pSurface, &surfaceGlDescription);
6416 memset(&surfaceDesc, 0, sizeof(surfaceDesc));
6418 surfaceDesc.Width = &surfaceWidth;
6419 surfaceDesc.Height = &surfaceHeight;
6420 IWineD3DSurface_GetDesc(pSurface, &surfaceDesc);
6421 /* check to see if it's the backbuffer or the frontbuffer being requested (to make sure the data is up to date)*/
6423 /* Ok, I may need to setup some kind of active swapchain reference on the device */
6424 IWineD3DSurface_GetContainer(pRenderTarget, &IID_IWineD3DSwapChain, (void **)&container);
6426 /* TODO: opengl Context switching for swapchains etc... */
6427 if (NULL != container || pRenderTarget == This->renderTarget || pRenderTarget == This->depthStencilBuffer) {
6428 if (NULL != container && (pRenderTarget == container->backBuffer[0])) {
6429 glReadBuffer(GL_BACK);
6430 vcheckGLcall("glReadBuffer(GL_BACK)");
6431 } else if ((NULL != container && (pRenderTarget == container->frontBuffer)) || (pRenderTarget == This->renderTarget)) {
6432 glReadBuffer(GL_FRONT);
6433 vcheckGLcall("glReadBuffer(GL_FRONT)");
6434 } else if (pRenderTarget == This->depthStencilBuffer) {
6435 FIXME("Reading of depthstencil not yet supported\n");
6442 surfaceGlDescription->glFormat,
6443 surfaceGlDescription->glType,
6444 (void *)IWineD3DSurface_GetData(pSurface));
6445 vcheckGLcall("glReadPixels(...)");
6446 if(NULL != container ){
6447 IWineD3DSwapChain_Release((IWineD3DSwapChain*) container);
6450 IWineD3DBaseTexture *container;
6451 GLenum textureDimensions = GL_TEXTURE_2D;
6453 if (WINED3D_OK == IWineD3DSurface_GetContainer(pSurface, &IID_IWineD3DBaseTexture, (void **)&container)) {
6454 textureDimensions = IWineD3DBaseTexture_GetTextureDimensions(container);
6455 IWineD3DBaseTexture_Release(container);
6457 /* TODO: 2D -> Cube surface coppies etc.. */
6458 if (surfaceGlDescription->target != textureDimensions) {
6459 FIXME("(%p) : Texture dimension mismatch\n", This);
6461 glEnable(textureDimensions);
6462 vcheckGLcall("glEnable(GL_TEXTURE_...)");
6463 /* FIXME: this isn't correct, it need to add a dirty rect if nothing else... */
6464 glBindTexture(targetGlDescription->target, targetGlDescription->textureName);
6465 vcheckGLcall("glBindTexture");
6466 glGetTexImage(surfaceGlDescription->target,
6467 surfaceGlDescription->level,
6468 surfaceGlDescription->glFormat,
6469 surfaceGlDescription->glType,
6470 (void *)IWineD3DSurface_GetData(pSurface));
6471 glDisable(textureDimensions);
6472 vcheckGLcall("glDisable(GL_TEXTURE_...)");
6479 static HRESULT WINAPI IWineD3DDeviceImpl_GetFrontBufferData(IWineD3DDevice *iface,UINT iSwapChain, IWineD3DSurface *pDestSurface) {
6480 IWineD3DSwapChain *swapChain;
6482 hr = IWineD3DDeviceImpl_GetSwapChain(iface, iSwapChain, (IWineD3DSwapChain **)&swapChain);
6483 if(hr == WINED3D_OK) {
6484 hr = IWineD3DSwapChain_GetFrontBufferData(swapChain, pDestSurface);
6489 static HRESULT WINAPI IWineD3DDeviceImpl_ValidateDevice(IWineD3DDevice *iface, DWORD* pNumPasses) {
6490 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
6491 /* return a sensible default */
6493 /* TODO: If the window is minimized then validate device should return something other than WINED3D_OK */
6494 FIXME("(%p) : stub\n", This);
6498 static HRESULT WINAPI IWineD3DDeviceImpl_SetPaletteEntries(IWineD3DDevice *iface, UINT PaletteNumber, CONST PALETTEENTRY* pEntries) {
6499 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
6501 TRACE("(%p) : PaletteNumber %u\n", This, PaletteNumber);
6502 if ( PaletteNumber < 0 || PaletteNumber >= MAX_PALETTES) {
6503 WARN("(%p) : (%u) Out of range 0-%u, returning Invalid Call\n", This, PaletteNumber, MAX_PALETTES);
6504 return WINED3DERR_INVALIDCALL;
6506 for (j = 0; j < 256; ++j) {
6507 This->palettes[PaletteNumber][j].peRed = pEntries[j].peRed;
6508 This->palettes[PaletteNumber][j].peGreen = pEntries[j].peGreen;
6509 This->palettes[PaletteNumber][j].peBlue = pEntries[j].peBlue;
6510 This->palettes[PaletteNumber][j].peFlags = pEntries[j].peFlags;
6512 TRACE("(%p) : returning\n", This);
6516 static HRESULT WINAPI IWineD3DDeviceImpl_GetPaletteEntries(IWineD3DDevice *iface, UINT PaletteNumber, PALETTEENTRY* pEntries) {
6517 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
6519 TRACE("(%p) : PaletteNumber %u\n", This, PaletteNumber);
6520 if ( PaletteNumber < 0 || PaletteNumber >= MAX_PALETTES) {
6521 WARN("(%p) : (%u) Out of range 0-%u, returning Invalid Call\n", This, PaletteNumber, MAX_PALETTES);
6522 return WINED3DERR_INVALIDCALL;
6524 for (j = 0; j < 256; ++j) {
6525 pEntries[j].peRed = This->palettes[PaletteNumber][j].peRed;
6526 pEntries[j].peGreen = This->palettes[PaletteNumber][j].peGreen;
6527 pEntries[j].peBlue = This->palettes[PaletteNumber][j].peBlue;
6528 pEntries[j].peFlags = This->palettes[PaletteNumber][j].peFlags;
6530 TRACE("(%p) : returning\n", This);
6534 static HRESULT WINAPI IWineD3DDeviceImpl_SetCurrentTexturePalette(IWineD3DDevice *iface, UINT PaletteNumber) {
6535 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
6536 TRACE("(%p) : PaletteNumber %u\n", This, PaletteNumber);
6537 if ( PaletteNumber < 0 || PaletteNumber >= MAX_PALETTES) {
6538 WARN("(%p) : (%u) Out of range 0-%u, returning Invalid Call\n", This, PaletteNumber, MAX_PALETTES);
6539 return WINED3DERR_INVALIDCALL;
6541 /*TODO: stateblocks */
6542 This->currentPalette = PaletteNumber;
6543 TRACE("(%p) : returning\n", This);
6547 static HRESULT WINAPI IWineD3DDeviceImpl_GetCurrentTexturePalette(IWineD3DDevice *iface, UINT* PaletteNumber) {
6548 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
6549 if (PaletteNumber == NULL) {
6550 WARN("(%p) : returning Invalid Call\n", This);
6551 return WINED3DERR_INVALIDCALL;
6553 /*TODO: stateblocks */
6554 *PaletteNumber = This->currentPalette;
6555 TRACE("(%p) : returning %u\n", This, *PaletteNumber);
6559 static HRESULT WINAPI IWineD3DDeviceImpl_SetSoftwareVertexProcessing(IWineD3DDevice *iface, BOOL bSoftware) {
6560 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
6561 static BOOL showFixmes = TRUE;
6563 FIXME("(%p) : stub\n", This);
6567 This->softwareVertexProcessing = bSoftware;
6572 static BOOL WINAPI IWineD3DDeviceImpl_GetSoftwareVertexProcessing(IWineD3DDevice *iface) {
6573 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
6574 static BOOL showFixmes = TRUE;
6576 FIXME("(%p) : stub\n", This);
6579 return This->softwareVertexProcessing;
6583 static HRESULT WINAPI IWineD3DDeviceImpl_GetRasterStatus(IWineD3DDevice *iface, UINT iSwapChain, WINED3DRASTER_STATUS* pRasterStatus) {
6584 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
6585 IWineD3DSwapChain *swapChain;
6588 TRACE("(%p) : SwapChain %d returning %p\n", This, iSwapChain, pRasterStatus);
6590 hr = IWineD3DDeviceImpl_GetSwapChain(iface, iSwapChain, (IWineD3DSwapChain **)&swapChain);
6591 if(hr == WINED3D_OK){
6592 hr = IWineD3DSwapChain_GetRasterStatus(swapChain, pRasterStatus);
6594 FIXME("(%p) IWineD3DSwapChain_GetRasterStatus returned in error\n", This);
6600 static HRESULT WINAPI IWineD3DDeviceImpl_SetNPatchMode(IWineD3DDevice *iface, float nSegments) {
6601 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
6602 static BOOL showfixmes = TRUE;
6603 if(nSegments != 0.0f) {
6605 FIXME("(%p) : stub nSegments(%f)\n", This, nSegments);
6612 static float WINAPI IWineD3DDeviceImpl_GetNPatchMode(IWineD3DDevice *iface) {
6613 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
6614 static BOOL showfixmes = TRUE;
6616 FIXME("(%p) : stub returning(%f)\n", This, 0.0f);
6622 static HRESULT WINAPI IWineD3DDeviceImpl_UpdateSurface(IWineD3DDevice *iface, IWineD3DSurface *pSourceSurface, CONST RECT* pSourceRect, IWineD3DSurface *pDestinationSurface, CONST POINT* pDestPoint) {
6623 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *) iface;
6624 /** TODO: remove casts to IWineD3DSurfaceImpl
6625 * NOTE: move code to surface to accomplish this
6626 ****************************************/
6627 IWineD3DSurfaceImpl *pSrcSurface = (IWineD3DSurfaceImpl *)pSourceSurface;
6628 int srcWidth, srcHeight;
6629 unsigned int srcSurfaceWidth, srcSurfaceHeight, destSurfaceWidth, destSurfaceHeight;
6630 WINED3DFORMAT destFormat, srcFormat;
6632 int destLeft, destTop;
6633 WINED3DPOOL srcPool, destPool;
6635 int rowoffset = 0; /* how many bytes to add onto the end of a row to wraparound to the beginning of the next */
6636 glDescriptor *glDescription = NULL;
6637 GLenum textureDimensions = GL_TEXTURE_2D;
6638 IWineD3DBaseTexture *baseTexture;
6640 WINED3DSURFACE_DESC winedesc;
6642 TRACE("(%p) : Source (%p) Rect (%p) Destination (%p) Point(%p)\n", This, pSourceSurface, pSourceRect, pDestinationSurface, pDestPoint);
6643 memset(&winedesc, 0, sizeof(winedesc));
6644 winedesc.Width = &srcSurfaceWidth;
6645 winedesc.Height = &srcSurfaceHeight;
6646 winedesc.Pool = &srcPool;
6647 winedesc.Format = &srcFormat;
6649 IWineD3DSurface_GetDesc(pSourceSurface, &winedesc);
6651 winedesc.Width = &destSurfaceWidth;
6652 winedesc.Height = &destSurfaceHeight;
6653 winedesc.Pool = &destPool;
6654 winedesc.Format = &destFormat;
6655 winedesc.Size = &destSize;
6657 IWineD3DSurface_GetDesc(pDestinationSurface, &winedesc);
6659 if(srcPool != WINED3DPOOL_SYSTEMMEM || destPool != WINED3DPOOL_DEFAULT){
6660 WARN("source %p must be SYSTEMMEM and dest %p must be DEFAULT, returning WINED3DERR_INVALIDCALL\n", pSourceSurface, pDestinationSurface);
6661 return WINED3DERR_INVALIDCALL;
6664 if (destFormat == WINED3DFMT_UNKNOWN) {
6665 TRACE("(%p) : Converting destination surface from WINED3DFMT_UNKNOWN to the source format\n", This);
6666 IWineD3DSurface_SetFormat(pDestinationSurface, srcFormat);
6668 /* Get the update surface description */
6669 IWineD3DSurface_GetDesc(pDestinationSurface, &winedesc);
6672 /* Make sure the surface is loaded and up to date */
6673 IWineD3DSurface_PreLoad(pDestinationSurface);
6675 IWineD3DSurface_GetGlDesc(pDestinationSurface, &glDescription);
6679 /* this needs to be done in lines if the sourceRect != the sourceWidth */
6680 srcWidth = pSourceRect ? pSourceRect->right - pSourceRect->left : srcSurfaceWidth;
6681 srcHeight = pSourceRect ? pSourceRect->top - pSourceRect->bottom : srcSurfaceHeight;
6682 destLeft = pDestPoint ? pDestPoint->x : 0;
6683 destTop = pDestPoint ? pDestPoint->y : 0;
6686 /* This function doesn't support compressed textures
6687 the pitch is just bytesPerPixel * width */
6688 if(srcWidth != srcSurfaceWidth || (pSourceRect != NULL && pSourceRect->left != 0) ){
6689 rowoffset = (srcSurfaceWidth - srcWidth) * pSrcSurface->bytesPerPixel;
6690 offset += pSourceRect->left * pSrcSurface->bytesPerPixel;
6691 /* TODO: do we ever get 3bpp?, would a shift and an add be quicker than a mul (well maybe a cycle or two) */
6693 /* TODO DXT formats */
6695 if(pSourceRect != NULL && pSourceRect->top != 0){
6696 offset += pSourceRect->top * srcWidth * pSrcSurface->bytesPerPixel;
6698 TRACE("(%p) glTexSubImage2D, Level %d, left %d, top %d, width %d, height %d , ftm %d, type %d, memory %p\n"
6700 ,glDescription->level
6705 ,glDescription->glFormat
6706 ,glDescription->glType
6707 ,IWineD3DSurface_GetData(pSourceSurface)
6711 if (IWineD3DSurface_GetData(pSourceSurface) == NULL) {
6713 /* need to lock the surface to get the data */
6714 FIXME("Surfaces has no allocated memory, but should be an in memory only surface\n");
6717 /* TODO: Cube and volume support */
6719 /* not a whole row so we have to do it a line at a time */
6722 /* hopefully using pointer addtion will be quicker than using a point + j * rowoffset */
6723 const unsigned char* data =((const unsigned char *)IWineD3DSurface_GetData(pSourceSurface)) + offset;
6725 for(j = destTop ; j < (srcHeight + destTop) ; j++){
6727 glTexSubImage2D(glDescription->target
6728 ,glDescription->level
6733 ,glDescription->glFormat
6734 ,glDescription->glType
6735 ,data /* could be quicker using */
6740 } else { /* Full width, so just write out the whole texture */
6742 if (WINED3DFMT_DXT1 == destFormat ||
6743 WINED3DFMT_DXT2 == destFormat ||
6744 WINED3DFMT_DXT3 == destFormat ||
6745 WINED3DFMT_DXT4 == destFormat ||
6746 WINED3DFMT_DXT5 == destFormat) {
6747 if (GL_SUPPORT(EXT_TEXTURE_COMPRESSION_S3TC)) {
6748 if (destSurfaceHeight != srcHeight || destSurfaceWidth != srcWidth) {
6749 /* FIXME: The easy way to do this is to lock the destination, and copy the bits across */
6750 FIXME("Updating part of a compressed texture is not supported at the moment\n");
6751 } if (destFormat != srcFormat) {
6752 FIXME("Updating mixed format compressed texture is not curretly support\n");
6754 GL_EXTCALL(glCompressedTexImage2DARB)(glDescription->target,
6755 glDescription->level,
6756 glDescription->glFormatInternal,
6761 IWineD3DSurface_GetData(pSourceSurface));
6764 FIXME("Attempting to update a DXT compressed texture without hardware support\n");
6769 if (NP2_REPACK == wined3d_settings.nonpower2_mode) {
6771 /* some applications cannot handle odd pitches returned by soft non-power2, so we have
6772 to repack the data from pow2Width/Height to expected Width,Height, this makes the
6773 data returned by GetData non-power2 width/height with hardware non-power2
6774 pow2Width/height are set to surface width height, repacking isn't needed so it
6775 doesn't matter which function gets called. */
6776 glTexSubImage2D(glDescription->target
6777 ,glDescription->level
6782 ,glDescription->glFormat
6783 ,glDescription->glType
6784 ,IWineD3DSurface_GetData(pSourceSurface)
6788 /* not repacked, the data returned by IWineD3DSurface_GetData is pow2Width x pow2Height */
6789 glTexSubImage2D(glDescription->target
6790 ,glDescription->level
6793 ,((IWineD3DSurfaceImpl *)pSourceSurface)->pow2Width
6794 ,((IWineD3DSurfaceImpl *)pSourceSurface)->pow2Height
6795 ,glDescription->glFormat
6796 ,glDescription->glType
6797 ,IWineD3DSurface_GetData(pSourceSurface)
6803 checkGLcall("glTexSubImage2D");
6804 ((IWineD3DSurfaceImpl *)pDestinationSurface)->Flags |= SFLAG_GLDIRTY;
6806 /* I only need to look up baseTexture here, so it may be a good idea to hava a GL_TARGET ->
6807 * GL_DIMENSIONS lookup, or maybe store the dimensions on the surface (but that's making the
6808 * surface bigger than it needs to be hmm.. */
6809 if (WINED3D_OK == IWineD3DSurface_GetContainer(pDestinationSurface, &IID_IWineD3DBaseTexture, (void **)&baseTexture)) {
6810 textureDimensions = IWineD3DBaseTexture_GetTextureDimensions(baseTexture);
6811 IWineD3DBaseTexture_Release(baseTexture);
6814 glDisable(textureDimensions); /* This needs to be managed better.... */
6820 /* Implementation details at http://developer.nvidia.com/attach/6494
6822 http://oss.sgi.com/projects/ogl-sample/registry/NV/evaluators.txt
6823 hmm.. no longer supported use
6824 OpenGL evaluators or tessellate surfaces within your application.
6827 /* http://msdn.microsoft.com/library/default.asp?url=/library/en-us/directx9_c/directx/graphics/reference/d3d/interfaces/idirect3ddevice9/DrawRectPatch.asp */
6828 static HRESULT WINAPI IWineD3DDeviceImpl_DrawRectPatch(IWineD3DDevice *iface, UINT Handle, CONST float* pNumSegs, CONST WINED3DRECTPATCH_INFO* pRectPatchInfo) {
6829 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
6830 TRACE("(%p) Handle(%d) noSegs(%p) rectpatch(%p)\n", This, Handle, pNumSegs, pRectPatchInfo);
6831 FIXME("(%p) : Stub\n", This);
6836 /* http://msdn.microsoft.com/library/default.asp?url=/library/en-us/directx9_c/directx/graphics/reference/d3d/interfaces/idirect3ddevice9/DrawTriPatch.asp */
6837 static HRESULT WINAPI IWineD3DDeviceImpl_DrawTriPatch(IWineD3DDevice *iface, UINT Handle, CONST float* pNumSegs, CONST WINED3DTRIPATCH_INFO* pTriPatchInfo) {
6838 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
6839 TRACE("(%p) Handle(%d) noSegs(%p) tripatch(%p)\n", This, Handle, pNumSegs, pTriPatchInfo);
6840 FIXME("(%p) : Stub\n", This);
6844 static HRESULT WINAPI IWineD3DDeviceImpl_DeletePatch(IWineD3DDevice *iface, UINT Handle) {
6845 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
6846 TRACE("(%p) Handle(%d)\n", This, Handle);
6847 FIXME("(%p) : Stub\n", This);
6851 static HRESULT WINAPI IWineD3DDeviceImpl_ColorFill(IWineD3DDevice *iface, IWineD3DSurface *pSurface, CONST WINED3DRECT* pRect, WINED3DCOLOR color) {
6852 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *) iface;
6853 IWineD3DSurfaceImpl *surface = (IWineD3DSurfaceImpl *) pSurface;
6855 TRACE("(%p) Colour fill Surface: %p rect: %p color: %d\n", This, pSurface, pRect, color);
6857 if (surface->resource.pool != WINED3DPOOL_DEFAULT && surface->resource.pool != WINED3DPOOL_SYSTEMMEM) {
6858 FIXME("call to colorfill with non WINED3DPOOL_DEFAULT or WINED3DPOOL_SYSTEMMEM surface\n");
6859 return WINED3DERR_INVALIDCALL;
6862 /* Just forward this to the DirectDraw blitting engine */
6863 memset(&BltFx, 0, sizeof(BltFx));
6864 BltFx.dwSize = sizeof(BltFx);
6865 BltFx.u5.dwFillColor = color;
6866 return IWineD3DSurface_Blt(pSurface, (RECT *) pRect, NULL, NULL, DDBLT_COLORFILL, &BltFx);
6869 /* rendertarget and deptth stencil functions */
6870 static HRESULT WINAPI IWineD3DDeviceImpl_GetRenderTarget(IWineD3DDevice* iface,DWORD RenderTargetIndex, IWineD3DSurface **ppRenderTarget) {
6871 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
6873 /* FIXME: Implelent RenderTargetIndex >0 */
6874 if(RenderTargetIndex > 0)
6875 FIXME("(%p) : RenderTargetIndex %d >0 not currently supported\n", This, RenderTargetIndex);
6877 *ppRenderTarget = This->renderTarget;
6878 TRACE("(%p) : RenderTarget %d Index returning %p\n", This, RenderTargetIndex, *ppRenderTarget);
6883 static HRESULT WINAPI IWineD3DDeviceImpl_SetFrontBackBuffers(IWineD3DDevice *iface, IWineD3DSurface *Front, IWineD3DSurface *Back) {
6884 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
6885 IWineD3DSurfaceImpl *FrontImpl = (IWineD3DSurfaceImpl *) Front;
6886 IWineD3DSurfaceImpl *BackImpl = (IWineD3DSurfaceImpl *) Back;
6887 IWineD3DSwapChainImpl *Swapchain;
6890 TRACE("(%p)->(%p,%p)\n", This, FrontImpl, BackImpl);
6892 hr = IWineD3DDevice_GetSwapChain(iface, 0, (IWineD3DSwapChain **) &Swapchain);
6893 if(hr != WINED3D_OK) {
6894 ERR("Can't get the swapchain\n");
6898 if(FrontImpl && !(FrontImpl->resource.usage & WINED3DUSAGE_RENDERTARGET) ) {
6899 ERR("Trying to set a front buffer which doesn't have WINED3DUSAGE_RENDERTARGET usage\n");
6900 return WINED3DERR_INVALIDCALL;
6902 else if(BackImpl && !(BackImpl->resource.usage & WINED3DUSAGE_RENDERTARGET)) {
6903 ERR("Trying to set a back buffer which doesn't have WINED3DUSAGE_RENDERTARGET usage\n");
6904 return WINED3DERR_INVALIDCALL;
6907 if(Swapchain->frontBuffer != Front) {
6908 TRACE("Changing the front buffer from %p to %p\n", Swapchain->frontBuffer, Front);
6910 if(Swapchain->frontBuffer)
6911 IWineD3DSurface_SetContainer(Swapchain->frontBuffer, NULL);
6912 Swapchain->frontBuffer = Front;
6914 if(Swapchain->frontBuffer) {
6915 IWineD3DSurface_SetContainer(Swapchain->frontBuffer, (IWineD3DBase *) Swapchain);
6919 if(Back && !Swapchain->backBuffer) {
6920 /* We need memory for the back buffer array - only one back buffer this way */
6921 Swapchain->backBuffer = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(IWineD3DSurface *));
6922 if(!Swapchain->backBuffer) {
6923 ERR("Out of memory\n");
6924 return E_OUTOFMEMORY;
6928 if(Swapchain->backBuffer[0] != Back) {
6929 TRACE("Changing the back buffer from %p to %p\n", Swapchain->backBuffer, Back);
6931 if(!Swapchain->backBuffer[0]) {
6932 /* GL was told to draw to the front buffer at creation,
6935 glDrawBuffer(GL_BACK);
6936 checkGLcall("glDrawBuffer(GL_BACK)");
6937 /* Set the backbuffer count to 1 because other code uses it to fing the back buffers */
6938 Swapchain->presentParms.BackBufferCount = 1;
6940 /* That makes problems - disable for now */
6941 /* glDrawBuffer(GL_FRONT); */
6942 checkGLcall("glDrawBuffer(GL_FRONT)");
6943 /* We have lost our back buffer, set this to 0 to avoid confusing other code */
6944 Swapchain->presentParms.BackBufferCount = 0;
6948 if(Swapchain->backBuffer[0])
6949 IWineD3DSurface_SetContainer(Swapchain->backBuffer[0], NULL);
6950 Swapchain->backBuffer[0] = Back;
6952 if(Swapchain->backBuffer[0]) {
6953 IWineD3DSurface_SetContainer(Swapchain->backBuffer[0], (IWineD3DBase *) Swapchain);
6955 HeapFree(GetProcessHeap(), 0, Swapchain->backBuffer);
6963 static HRESULT WINAPI IWineD3DDeviceImpl_GetDepthStencilSurface(IWineD3DDevice* iface, IWineD3DSurface **ppZStencilSurface) {
6964 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
6965 *ppZStencilSurface = This->depthStencilBuffer;
6966 TRACE("(%p) : zStencilSurface returning %p\n", This, *ppZStencilSurface);
6971 static void bind_fbo(IWineD3DDevice *iface) {
6972 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
6975 GL_EXTCALL(glGenFramebuffersEXT(1, &This->fbo));
6976 checkGLcall("glGenFramebuffersEXT()");
6978 GL_EXTCALL(glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, This->fbo));
6979 checkGLcall("glBindFramebuffer()");
6982 /* TODO: Handle stencil attachments */
6983 static void set_depth_stencil_fbo(IWineD3DDevice *iface, IWineD3DSurface *depth_stencil) {
6984 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
6985 IWineD3DSurfaceImpl *depth_stencil_impl = (IWineD3DSurfaceImpl *)depth_stencil;
6987 This->depth_copy_state = WINED3D_DCS_NO_COPY;
6991 if (depth_stencil_impl) {
6992 GLenum texttarget, target;
6994 IWineD3DSurface_PreLoad(depth_stencil);
6995 texttarget = depth_stencil_impl->glDescription.target;
6996 target = texttarget == GL_TEXTURE_2D ? GL_TEXTURE_2D : GL_TEXTURE_CUBE_MAP_ARB;
6998 glBindTexture(target, depth_stencil_impl->glDescription.textureName);
6999 glTexParameteri(target, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
7000 glTexParameteri(target, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
7001 glTexParameteri(target, GL_DEPTH_TEXTURE_MODE_ARB, GL_LUMINANCE);
7002 glBindTexture(target, 0);
7004 GL_EXTCALL(glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_DEPTH_ATTACHMENT_EXT, texttarget, depth_stencil_impl->glDescription.textureName, 0));
7005 checkGLcall("glFramebufferTexture2DEXT()");
7007 GL_EXTCALL(glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_DEPTH_ATTACHMENT_EXT, GL_TEXTURE_2D, 0, 0));
7008 checkGLcall("glFramebufferTexture2DEXT()");
7011 if (!This->render_offscreen) {
7012 GL_EXTCALL(glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0));
7013 checkGLcall("glBindFramebuffer()");
7017 static void set_render_target_fbo(IWineD3DDevice *iface, IWineD3DSurface *render_target) {
7018 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
7019 IWineD3DSurfaceImpl *rtimpl = (IWineD3DSurfaceImpl *)render_target;
7021 if (This->render_offscreen) {
7022 GLenum texttarget, target;
7026 IWineD3DSurface_PreLoad(render_target);
7027 texttarget = rtimpl->glDescription.target;
7028 target = texttarget == GL_TEXTURE_2D ? GL_TEXTURE_2D : GL_TEXTURE_CUBE_MAP_ARB;
7030 glBindTexture(target, rtimpl->glDescription.textureName);
7031 glTexParameteri(target, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
7032 glTexParameteri(target, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
7033 glBindTexture(target, 0);
7035 GL_EXTCALL(glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT, texttarget, rtimpl->glDescription.textureName, 0));
7036 checkGLcall("glFramebufferTexture2DEXT()");
7038 GL_EXTCALL(glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0));
7039 checkGLcall("glBindFramebuffer()");
7043 /* internal static helper functions */
7044 static HRESULT WINAPI IWineD3DDeviceImpl_ActiveRender(IWineD3DDevice* iface,
7045 IWineD3DSurface *RenderSurface);
7047 static HRESULT WINAPI IWineD3DDeviceImpl_SetRenderTarget(IWineD3DDevice *iface, DWORD RenderTargetIndex, IWineD3DSurface *pRenderTarget) {
7048 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
7049 HRESULT hr = WINED3D_OK;
7050 WINED3DVIEWPORT viewport;
7052 TRACE("(%p) Swapping rendertarget\n",This);
7053 if (RenderTargetIndex > 0) {
7054 FIXME("(%p) Render targets other than the first are not supported\n",This);
7055 RenderTargetIndex = 0;
7058 /* MSDN says that null disables the render target
7059 but a device must always be associated with a render target
7060 nope MSDN says that we return invalid call to a null rendertarget with an index of 0
7062 see http://msdn.microsoft.com/library/default.asp?url=/library/en-us/directx9_c/directx/graphics/programmingguide/AdvancedTopics/PixelPipe/MultipleRenderTarget.asp
7065 if (RenderTargetIndex == 0 && pRenderTarget == NULL) {
7066 FIXME("Trying to set render target 0 to NULL\n");
7067 return WINED3DERR_INVALIDCALL;
7069 /* TODO: replace Impl* usage with interface usage */
7070 if (!((IWineD3DSurfaceImpl *)pRenderTarget)->resource.usage & WINED3DUSAGE_RENDERTARGET) {
7071 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);
7072 return WINED3DERR_INVALIDCALL;
7074 /** TODO: check that the depth stencil format matches the render target, this is only done in debug
7075 * builds, but I think wine counts as a 'debug' build for now.
7076 ******************************/
7077 /* If we are trying to set what we already have, don't bother */
7078 if (pRenderTarget == This->renderTarget) {
7079 TRACE("Trying to do a NOP SetRenderTarget operation\n");
7081 /* Otherwise, set the render target up */
7083 if (!This->sceneEnded) {
7084 IWineD3DDevice_EndScene(iface);
7086 TRACE("clearing renderer\n");
7087 /* IWineD3DDeviceImpl_CleanRender(iface); */
7088 /* OpenGL doesn't support 'sharing' of the stencilBuffer so we may incure an extra memory overhead
7089 depending on the renter target implementation being used.
7090 A shared context implementation will share all buffers between all rendertargets (including swapchains),
7091 implementations that use separate pbuffers for different swapchains or rendertargets will have to duplicate the
7092 stencil buffer and incure an extra memory overhead */
7093 hr = IWineD3DDeviceImpl_ActiveRender(iface, pRenderTarget);
7094 if (wined3d_settings.offscreen_rendering_mode == ORM_FBO) {
7095 set_render_target_fbo(iface, pRenderTarget);
7099 if (SUCCEEDED(hr)) {
7100 /* Finally, reset the viewport as the MSDN states. */
7101 /* TODO: Replace impl usage */
7102 viewport.Height = ((IWineD3DSurfaceImpl *)This->renderTarget)->currentDesc.Height;
7103 viewport.Width = ((IWineD3DSurfaceImpl *)This->renderTarget)->currentDesc.Width;
7106 viewport.MaxZ = 1.0f;
7107 viewport.MinZ = 0.0f;
7108 IWineD3DDeviceImpl_SetViewport(iface, &viewport);
7110 FIXME("Unknown error setting the render target\n");
7112 This->sceneEnded = FALSE;
7116 static HRESULT WINAPI IWineD3DDeviceImpl_SetDepthStencilSurface(IWineD3DDevice *iface, IWineD3DSurface *pNewZStencil) {
7117 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
7118 HRESULT hr = WINED3D_OK;
7119 IWineD3DSurface *tmp;
7121 TRACE("(%p) Swapping z-buffer\n",This);
7123 if (pNewZStencil == This->stencilBufferTarget) {
7124 TRACE("Trying to do a NOP SetRenderTarget operation\n");
7126 /** OpenGL doesn't support 'sharing' of the stencilBuffer so we may incure an extra memory overhead
7127 * depending on the renter target implementation being used.
7128 * A shared context implementation will share all buffers between all rendertargets (including swapchains),
7129 * implementations that use separate pbuffers for different swapchains or rendertargets will have to duplicate the
7130 * stencil buffer and incure an extra memory overhead
7131 ******************************************************/
7134 tmp = This->stencilBufferTarget;
7135 This->stencilBufferTarget = pNewZStencil;
7136 /* should we be calling the parent or the wined3d surface? */
7137 if (NULL != This->stencilBufferTarget) IWineD3DSurface_AddRef(This->stencilBufferTarget);
7138 if (NULL != tmp) IWineD3DSurface_Release(tmp);
7140 /** TODO: glEnable/glDisable on depth/stencil depending on
7141 * pNewZStencil is NULL and the depth/stencil is enabled in d3d
7142 **********************************************************/
7143 if (wined3d_settings.offscreen_rendering_mode == ORM_FBO) {
7144 set_depth_stencil_fbo(iface, pNewZStencil);
7152 #ifdef GL_VERSION_1_3
7153 /* Internal functions not in DirectX */
7154 /** TODO: move this off to the opengl context manager
7155 *(the swapchain doesn't need to know anything about offscreen rendering!)
7156 ****************************************************/
7158 static HRESULT WINAPI IWineD3DDeviceImpl_CleanRender(IWineD3DDevice* iface, IWineD3DSwapChainImpl *swapchain)
7160 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
7162 TRACE("(%p), %p\n", This, swapchain);
7164 if (swapchain->win != swapchain->drawable) {
7165 /* Set everything back the way it ws */
7166 swapchain->render_ctx = swapchain->glCtx;
7167 swapchain->drawable = swapchain->win;
7172 /* TODO: move this off into a context manager so that GLX_ATI_render_texture and other types of surface can be used. */
7173 static HRESULT WINAPI IWineD3DDeviceImpl_FindGLContext(IWineD3DDevice *iface, IWineD3DSurface *pSurface, glContext **context) {
7174 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
7177 unsigned int height;
7178 WINED3DFORMAT format;
7179 WINED3DSURFACE_DESC surfaceDesc;
7180 memset(&surfaceDesc, 0, sizeof(surfaceDesc));
7181 surfaceDesc.Width = &width;
7182 surfaceDesc.Height = &height;
7183 surfaceDesc.Format = &format;
7184 IWineD3DSurface_GetDesc(pSurface, &surfaceDesc);
7186 /* I need a get width/height function (and should do something with the format) */
7187 for (i = 0; i < CONTEXT_CACHE; ++i) {
7188 /** NOTE: the contextCache[i].pSurface == pSurface check ceates onepbuffer per surface
7189 ATI cards don't destroy pbuffers, but as soon as resource releasing callbacks are inplace
7190 the pSurface can be set to 0 allowing it to be reused from cache **/
7191 if (This->contextCache[i].Width == width && This->contextCache[i].Height == height
7192 && (!pbuffer_per_surface || This->contextCache[i].pSurface == pSurface || This->contextCache[i].pSurface == NULL)) {
7193 *context = &This->contextCache[i];
7196 if (This->contextCache[i].Width == 0) {
7197 This->contextCache[i].pSurface = pSurface;
7198 This->contextCache[i].Width = width;
7199 This->contextCache[i].Height = height;
7200 *context = &This->contextCache[i];
7204 if (i == CONTEXT_CACHE) {
7205 int minUsage = 0x7FFFFFFF; /* MAX_INT */
7206 glContext *dropContext = 0;
7207 for (i = 0; i < CONTEXT_CACHE; i++) {
7208 if (This->contextCache[i].usedcount < minUsage) {
7209 dropContext = &This->contextCache[i];
7210 minUsage = This->contextCache[i].usedcount;
7213 /* clean up the context (this doesn't work for ATI at the moment */
7215 glXDestroyContext(swapchain->display, dropContext->context);
7216 glXDestroyPbuffer(swapchain->display, dropContext->drawable);
7219 dropContext->Width = 0;
7220 dropContext->pSurface = pSurface;
7221 *context = dropContext;
7223 if (++This->contextCache[i].usedcount == 0x7FFFFFFF /* MAX_INT */ - 1 ) {
7224 for (i = 0; i < CONTEXT_CACHE; i++) {
7225 This->contextCache[i].usedcount = max(0, This->contextCache[i].usedcount - (0x7FFFFFFF /* MAX_INT */ >> 1));
7229 if (*context != NULL)
7232 return E_OUTOFMEMORY;
7236 /* Reapply the device stateblock */
7237 static void device_reapply_stateblock(IWineD3DDeviceImpl* This) {
7240 IWineD3DStateBlockImpl *oldUpdateStateBlock;
7242 /* Disable recording */
7243 oldUpdateStateBlock = This->updateStateBlock;
7244 oldRecording= This->isRecordingState;
7245 This->isRecordingState = FALSE;
7246 This->updateStateBlock = This->stateBlock;
7248 /* Reapply the state block */
7249 IWineD3DStateBlock_Apply((IWineD3DStateBlock *)This->stateBlock);
7251 /* Restore recording */
7252 This->isRecordingState = oldRecording;
7253 This->updateStateBlock = oldUpdateStateBlock;
7256 /* Set offscreen rendering. When rendering offscreen the surface will be
7257 * rendered upside down to compensate for the fact that D3D texture coordinates
7258 * are flipped compared to GL texture coordinates. The cullmode is affected by
7259 * this, so it must be updated. To update the cullmode stateblock recording has
7260 * to be temporarily disabled. The new state management code will hopefully
7261 * make this unnecessary */
7262 static void device_render_to_texture(IWineD3DDeviceImpl* This, BOOL isTexture) {
7266 IWineD3DStateBlockImpl *oldUpdateStateBlock;
7268 /* Nothing to update, return. */
7269 if (This->render_offscreen == isTexture) return;
7271 /* Disable recording */
7272 oldUpdateStateBlock = This->updateStateBlock;
7273 oldRecording= This->isRecordingState;
7274 This->isRecordingState = FALSE;
7275 This->updateStateBlock = This->stateBlock;
7277 This->render_offscreen = isTexture;
7278 if (This->depth_copy_state != WINED3D_DCS_NO_COPY) {
7279 This->depth_copy_state = WINED3D_DCS_COPY;
7281 This->last_was_rhw = FALSE;
7282 This->proj_valid = FALSE;
7283 IWineD3DDevice_GetRenderState((IWineD3DDevice*) This, WINED3DRS_CULLMODE, &cullMode);
7284 IWineD3DDevice_SetRenderState((IWineD3DDevice*) This, WINED3DRS_CULLMODE, cullMode);
7286 /* Restore recording */
7287 This->isRecordingState = oldRecording;
7288 This->updateStateBlock = oldUpdateStateBlock;
7291 /* Returns an array of compatible FBconfig(s).
7292 * The array must be freed with XFree. Requires ENTER_GL() */
7294 static GLXFBConfig* device_find_fbconfigs(
7295 IWineD3DDeviceImpl* This,
7296 IWineD3DSwapChainImpl* implicitSwapchainImpl,
7297 IWineD3DSurface* RenderSurface) {
7299 GLXFBConfig* cfgs = NULL;
7304 IWineD3DSurface *StencilSurface = This->stencilBufferTarget;
7305 WINED3DFORMAT BackBufferFormat = ((IWineD3DSurfaceImpl *) RenderSurface)->resource.format;
7306 WINED3DFORMAT StencilBufferFormat = (NULL != StencilSurface) ? ((IWineD3DSurfaceImpl *) StencilSurface)->resource.format : 0;
7309 if StencilSurface == NULL && zBufferTarget != NULL then switch the zbuffer off,
7310 it StencilSurface != NULL && zBufferTarget == NULL switch it on
7313 #define PUSH1(att) attribs[nAttribs++] = (att);
7314 #define PUSH2(att,value) attribs[nAttribs++] = (att); attribs[nAttribs++] = (value);
7316 /* PUSH2(GLX_BIND_TO_TEXTURE_RGBA_ATI, True); examples of this are few and far between (but I've got a nice working one!)*/
7318 PUSH2(GLX_DRAWABLE_TYPE, GLX_PBUFFER_BIT);
7319 PUSH2(GLX_X_RENDERABLE, TRUE);
7320 PUSH2(GLX_DOUBLEBUFFER, TRUE);
7321 TRACE("calling makeglcfg\n");
7322 D3DFmtMakeGlCfg(BackBufferFormat, StencilBufferFormat, attribs, &nAttribs, FALSE /* alternate */);
7324 TRACE("calling chooseFGConfig\n");
7325 cfgs = glXChooseFBConfig(implicitSwapchainImpl->display,
7326 DefaultScreen(implicitSwapchainImpl->display),
7329 /* OK we didn't find the exact config, so use any reasonable match */
7330 /* TODO: fill in the 'requested' and 'current' depths, and make sure that's
7332 static BOOL show_message = TRUE;
7334 ERR("Failed to find exact match, finding alternative but you may "
7335 "suffer performance issues, try changing xfree's depth to match the requested depth\n");
7336 show_message = FALSE;
7339 PUSH2(GLX_DRAWABLE_TYPE, GLX_PBUFFER_BIT | GLX_WINDOW_BIT);
7340 /* PUSH2(GLX_X_RENDERABLE, TRUE); */
7341 PUSH2(GLX_RENDER_TYPE, GLX_RGBA_BIT);
7342 PUSH2(GLX_DOUBLEBUFFER, FALSE);
7343 TRACE("calling makeglcfg\n");
7344 D3DFmtMakeGlCfg(BackBufferFormat, StencilBufferFormat, attribs, &nAttribs, TRUE /* alternate */);
7346 cfgs = glXChooseFBConfig(implicitSwapchainImpl->display,
7347 DefaultScreen(implicitSwapchainImpl->display),
7352 ERR("Could not get a valid FBConfig for (%u,%s)/(%u,%s)\n",
7353 BackBufferFormat, debug_d3dformat(BackBufferFormat),
7354 StencilBufferFormat, debug_d3dformat(StencilBufferFormat));
7358 for (i = 0; i < nCfgs; ++i) {
7359 TRACE("for (%u,%s)/(%u,%s) found config[%d]@%p\n", BackBufferFormat,
7360 debug_d3dformat(BackBufferFormat), StencilBufferFormat,
7361 debug_d3dformat(StencilBufferFormat), i, cfgs[i]);
7363 if (NULL != This->renderTarget) {
7365 vcheckGLcall("glFlush");
7366 /** This is only useful if the old render target was a swapchain,
7367 * we need to supercede this with a function that displays
7368 * the current buffer on the screen. This is easy to do in glx1.3 but
7369 * we need to do copy-write pixels in glx 1.2.
7370 ************************************************/
7371 glXSwapBuffers(implicitSwapChainImpl->display,
7372 implicitSwapChainImpl->drawable);
7373 printf("Hit Enter to get next frame ...\n");
7384 /** FIXME: This is currently used called whenever SetRenderTarget or SetStencilBuffer are called
7385 * the functionality needs splitting up so that we don't do more than we should do.
7386 * this only seems to impact performance a little.
7387 ******************************/
7388 static HRESULT WINAPI IWineD3DDeviceImpl_ActiveRender(IWineD3DDevice* iface,
7389 IWineD3DSurface *RenderSurface) {
7392 * Currently only active for GLX >= 1.3
7393 * for others versions we'll have to use GLXPixmaps
7395 * normally we must test GLX_VERSION_1_3 but nvidia headers are not correct
7396 * as they implement GLX 1.3 but only define GLX_VERSION_1_2
7397 * so only check OpenGL version
7398 * ..........................
7399 * I don't believe that it is a problem with NVidia headers,
7400 * XFree only supports GLX1.2, nVidia (and ATI to some extent) provide 1.3 functions
7401 * in GLX 1.2, there is no mention of the correct way to tell if the extensions are provided.
7403 * Your application will report GLX version 1.2 on glXQueryVersion.
7404 * However, it is safe to call the GLX 1.3 functions as described below.
7406 #if defined(GL_VERSION_1_3)
7408 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
7409 GLXFBConfig* cfgs = NULL;
7410 IWineD3DSwapChain *currentSwapchain;
7411 IWineD3DSwapChainImpl *currentSwapchainImpl;
7412 IWineD3DSwapChain *implicitSwapchain;
7413 IWineD3DSwapChainImpl *implicitSwapchainImpl;
7414 IWineD3DSwapChain *renderSurfaceSwapchain;
7415 IWineD3DSwapChainImpl *renderSurfaceSwapchainImpl;
7417 /* Obtain a reference to the device implicit swapchain,
7418 * the swapchain of the current render target,
7419 * and the swapchain of the new render target.
7420 * Fallback to device implicit swapchain if the current render target doesn't have one */
7421 IWineD3DDevice_GetSwapChain(iface, 0, &implicitSwapchain);
7422 IWineD3DSurface_GetContainer(RenderSurface, &IID_IWineD3DSwapChain, (void**) &renderSurfaceSwapchain);
7423 IWineD3DSurface_GetContainer(This->renderTarget, &IID_IWineD3DSwapChain, (void **)¤tSwapchain);
7424 if (currentSwapchain == NULL) {
7425 IWineD3DDevice_GetSwapChain(iface, 0, ¤tSwapchain);
7426 /* GetContainer currently AddRefs, but GetSwapChain doesn't.
7427 * Like this the release code for both is the same. */
7428 IWineD3DDevice_AddRef(currentSwapchain);
7431 currentSwapchainImpl = (IWineD3DSwapChainImpl*) currentSwapchain;
7432 implicitSwapchainImpl = (IWineD3DSwapChainImpl*) implicitSwapchain;
7433 renderSurfaceSwapchainImpl = (IWineD3DSwapChainImpl*) renderSurfaceSwapchain;
7438 * TODO: remove the use of IWineD3DSwapChainImpl, a context manager will help since it will replace the
7439 * renderTarget = swapchain->backBuffer[i] bit and anything to do with *glContexts
7440 **********************************************************************/
7441 if (renderSurfaceSwapchain != NULL) {
7443 /* We also need to make sure that the lights &co are also in the context of the swapchains */
7444 /* FIXME: If the render target gets sent to the frontBuffer, should we be presenting it raw? */
7445 TRACE("making swapchain active\n");
7446 if (RenderSurface != This->renderTarget) {
7447 BOOL backbuf = FALSE;
7450 for(i = 0; i < renderSurfaceSwapchainImpl->presentParms.BackBufferCount; i++) {
7451 if(RenderSurface == renderSurfaceSwapchainImpl->backBuffer[i]) {
7459 /* This could be flagged so that some operations work directly with the front buffer */
7460 FIXME("Attempting to set the renderTarget to the frontBuffer\n");
7462 if (glXMakeCurrent(renderSurfaceSwapchainImpl->display,
7463 renderSurfaceSwapchainImpl->win,
7464 renderSurfaceSwapchainImpl->glCtx) == False) {
7466 TRACE("Error in setting current context: context %p drawable %ld !\n",
7467 implicitSwapchainImpl->glCtx, implicitSwapchainImpl->win);
7469 checkGLcall("glXMakeContextCurrent");
7471 /* Clean up the old context */
7472 IWineD3DDeviceImpl_CleanRender(iface, currentSwapchainImpl);
7474 /* Reapply the stateblock, and set the device not to render to texture */
7475 device_reapply_stateblock(This);
7476 device_render_to_texture(This, FALSE);
7479 /* Offscreen rendering: PBuffers (currently disabled).
7480 * Also note that this path is never reached if FBOs are supported */
7481 } else if (wined3d_settings.offscreen_rendering_mode == ORM_PBUFFER &&
7482 (cfgs = device_find_fbconfigs(This, implicitSwapchainImpl, RenderSurface)) != NULL) {
7484 /** ********************************************************************
7485 * This is a quickly hacked out implementation of offscreen textures.
7486 * It will work in most cases but there may be problems if the client
7487 * modifies the texture directly, or expects the contents of the rendertarget
7490 * There are some real speed vs compatibility issues here:
7491 * we should really use a new context for every texture, but that eats ram.
7492 * we should also be restoring the texture to the pbuffer but that eats CPU
7493 * we can also 'reuse' the current pbuffer if the size is larger than the requested buffer,
7494 * but if this means reusing the display backbuffer then we need to make sure that
7495 * states are correctly preserved.
7496 * In many cases I would expect that we can 'skip' some functions, such as preserving states,
7497 * and gain a good performance increase at the cost of compatibility.
7498 * I would suggest that, when this is the case, a user configurable flag be made
7499 * available, allowing the user to choose the best emulated experience for them.
7500 *********************************************************************/
7502 XVisualInfo *visinfo;
7503 glContext *newContext;
7505 /* Here were using a shared context model */
7506 if (WINED3D_OK != IWineD3DDeviceImpl_FindGLContext(iface, RenderSurface, &newContext)) {
7507 FIXME("(%p) : Failed to find a context for surface %p\n", iface, RenderSurface);
7510 /* If the context doesn't exist then create a new one */
7511 /* TODO: This should really be part of findGlContext */
7512 if (NULL == newContext->context) {
7517 TRACE("making new buffer\n");
7518 attribs[nAttribs++] = GLX_PBUFFER_WIDTH;
7519 attribs[nAttribs++] = newContext->Width;
7520 attribs[nAttribs++] = GLX_PBUFFER_HEIGHT;
7521 attribs[nAttribs++] = newContext->Height;
7522 attribs[nAttribs++] = None;
7524 newContext->drawable = glXCreatePbuffer(implicitSwapchainImpl->display, cfgs[0], attribs);
7526 /** ****************************************
7527 *GLX1.3 isn't supported by XFree 'yet' until that point ATI emulates pBuffers
7529 * In future releases, we may provide the calls glXCreateNewContext,
7530 * glXQueryDrawable and glXMakeContextCurrent.
7531 * so until then we have to use glXGetVisualFromFBConfig &co..
7532 ********************************************/
7534 visinfo = glXGetVisualFromFBConfig(implicitSwapchainImpl->display, cfgs[0]);
7536 ERR("Error: couldn't get an RGBA, double-buffered visual\n");
7538 newContext->context = glXCreateContext(
7539 implicitSwapchainImpl->display, visinfo,
7540 implicitSwapchainImpl->glCtx, GL_TRUE);
7545 if (NULL == newContext || NULL == newContext->context) {
7546 ERR("(%p) : Failed to find a context for surface %p\n", iface, RenderSurface);
7548 /* Debug logging, (this function leaks), change to a TRACE when the leak is plugged */
7549 if (glXMakeCurrent(implicitSwapchainImpl->display,
7550 newContext->drawable, newContext->context) == False) {
7552 TRACE("Error in setting current context: context %p drawable %ld\n",
7553 newContext->context, newContext->drawable);
7555 checkGLcall("glXMakeContextCurrent");
7557 /* Clean up the old context */
7558 IWineD3DDeviceImpl_CleanRender(iface, currentSwapchainImpl);
7560 /* Reapply stateblock, and set device to render to a texture */
7561 device_reapply_stateblock(This);
7562 device_render_to_texture(This, TRUE);
7564 /* Set the current context of the swapchain to the new context */
7565 implicitSwapchainImpl->drawable = newContext->drawable;
7566 implicitSwapchainImpl->render_ctx = newContext->context;
7569 /* Same context, but update render_offscreen and cull mode */
7570 device_render_to_texture(This, TRUE);
7573 /* Replace the render target */
7574 if (This->renderTarget != RenderSurface) {
7575 IWineD3DSurface_Release(This->renderTarget);
7576 This->renderTarget = RenderSurface;
7577 IWineD3DSurface_AddRef(RenderSurface);
7580 if (cfgs != NULL) XFree(cfgs);
7581 if (currentSwapchain != NULL) IWineD3DSwapChain_Release(currentSwapchain);
7582 if (renderSurfaceSwapchain != NULL) IWineD3DSwapChain_Release(renderSurfaceSwapchain);
7588 static HRESULT WINAPI IWineD3DDeviceImpl_SetCursorProperties(IWineD3DDevice* iface, UINT XHotSpot,
7589 UINT YHotSpot, IWineD3DSurface *pCursorBitmap) {
7590 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *) iface;
7591 /* TODO: the use of Impl is deprecated. */
7592 IWineD3DSurfaceImpl * pSur = (IWineD3DSurfaceImpl *) pCursorBitmap;
7594 TRACE("(%p) : Spot Pos(%u,%u)\n", This, XHotSpot, YHotSpot);
7596 /* some basic validation checks */
7597 if(This->cursorTexture) {
7599 glDeleteTextures(1, &This->cursorTexture);
7601 This->cursorTexture = 0;
7605 /* MSDN: Cursor must be A8R8G8B8 */
7606 if (WINED3DFMT_A8R8G8B8 != pSur->resource.format) {
7607 ERR("(%p) : surface(%p) has an invalid format\n", This, pCursorBitmap);
7608 return WINED3DERR_INVALIDCALL;
7611 /* MSDN: Cursor must be smaller than the display mode */
7612 if(pSur->currentDesc.Width > This->ddraw_width ||
7613 pSur->currentDesc.Height > This->ddraw_height) {
7614 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);
7615 return WINED3DERR_INVALIDCALL;
7618 /* TODO: MSDN: Cursor sizes must be a power of 2 */
7619 /* This is to tell our texture code to load a SCRATCH surface. This allows us to use out
7620 * Texture and Blitting code to draw the cursor
7622 pSur->Flags |= SFLAG_FORCELOAD;
7623 IWineD3DSurface_PreLoad(pCursorBitmap);
7624 pSur->Flags &= ~SFLAG_FORCELOAD;
7625 /* Do not store the surface's pointer because the application may release
7626 * it after setting the cursor image. Windows doesn't addref the set surface, so we can't
7627 * do this either without creating circular refcount dependencies. Copy out the gl texture instead.
7629 This->cursorTexture = pSur->glDescription.textureName;
7630 This->cursorWidth = pSur->currentDesc.Width;
7631 This->cursorHeight = pSur->currentDesc.Height;
7632 pSur->glDescription.textureName = 0; /* Prevent the texture from being changed or deleted */
7635 This->xHotSpot = XHotSpot;
7636 This->yHotSpot = YHotSpot;
7640 static void WINAPI IWineD3DDeviceImpl_SetCursorPosition(IWineD3DDevice* iface, int XScreenSpace, int YScreenSpace, DWORD Flags) {
7641 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *) iface;
7642 TRACE("(%p) : SetPos to (%u,%u)\n", This, XScreenSpace, YScreenSpace);
7644 This->xScreenSpace = XScreenSpace;
7645 This->yScreenSpace = YScreenSpace;
7651 static BOOL WINAPI IWineD3DDeviceImpl_ShowCursor(IWineD3DDevice* iface, BOOL bShow) {
7652 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *) iface;
7653 BOOL oldVisible = This->bCursorVisible;
7654 TRACE("(%p) : visible(%d)\n", This, bShow);
7656 if(This->cursorTexture)
7657 This->bCursorVisible = bShow;
7662 static HRESULT WINAPI IWineD3DDeviceImpl_TestCooperativeLevel(IWineD3DDevice* iface) {
7663 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *) iface;
7664 TRACE("(%p) : state (%u)\n", This, This->state);
7665 /* TODO: Implement wrapping of the WndProc so that mimimize and maxamise can be monitored and the states adjusted. */
7666 switch (This->state) {
7669 case WINED3DERR_DEVICELOST:
7671 ResourceList *resourceList = This->resources;
7672 while (NULL != resourceList) {
7673 if (((IWineD3DResourceImpl *)resourceList->resource)->resource.pool == WINED3DPOOL_DEFAULT /* TODO: IWineD3DResource_GetPool(resourceList->resource)*/)
7674 return WINED3DERR_DEVICENOTRESET;
7675 resourceList = resourceList->next;
7677 return WINED3DERR_DEVICELOST;
7679 case WINED3DERR_DRIVERINTERNALERROR:
7680 return WINED3DERR_DRIVERINTERNALERROR;
7684 return WINED3DERR_DRIVERINTERNALERROR;
7688 static HRESULT WINAPI IWineD3DDeviceImpl_EvictManagedResources(IWineD3DDevice* iface) {
7689 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *) iface;
7690 /** FIXME: Resource tracking needs to be done,
7691 * The closes we can do to this is set the priorities of all managed textures low
7692 * and then reset them.
7693 ***********************************************************/
7694 FIXME("(%p) : stub\n", This);
7698 static HRESULT WINAPI IWineD3DDeviceImpl_Reset(IWineD3DDevice* iface, WINED3DPRESENT_PARAMETERS* pPresentationParameters) {
7699 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *) iface;
7700 /** FIXME: Resource trascking needs to be done.
7701 * in effect this pulls all non only default
7702 * textures out of video memory and deletes all glTextures (glDeleteTextures)
7703 * and should clear down the context and set it up according to pPresentationParameters
7704 ***********************************************************/
7705 FIXME("(%p) : stub\n", This);
7709 static HRESULT WINAPI IWineD3DDeviceImpl_SetDialogBoxMode(IWineD3DDevice *iface, BOOL bEnableDialogs) {
7710 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
7711 /** FIXME: always true at the moment **/
7712 if(!bEnableDialogs) {
7713 FIXME("(%p) Dialogs cannot be disabled yet\n", This);
7719 static HRESULT WINAPI IWineD3DDeviceImpl_GetCreationParameters(IWineD3DDevice *iface, WINED3DDEVICE_CREATION_PARAMETERS *pParameters) {
7720 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *) iface;
7721 TRACE("(%p) : pParameters %p\n", This, pParameters);
7723 *pParameters = This->createParms;
7727 static void WINAPI IWineD3DDeviceImpl_SetGammaRamp(IWineD3DDevice * iface, UINT iSwapChain, DWORD Flags, CONST WINED3DGAMMARAMP* pRamp) {
7728 IWineD3DSwapChain *swapchain;
7729 HRESULT hrc = WINED3D_OK;
7731 TRACE("Relaying to swapchain\n");
7733 if ((hrc = IWineD3DDeviceImpl_GetSwapChain(iface, iSwapChain, &swapchain)) == WINED3D_OK) {
7734 IWineD3DSwapChain_SetGammaRamp(swapchain, Flags, (WINED3DGAMMARAMP *)pRamp);
7739 static void WINAPI IWineD3DDeviceImpl_GetGammaRamp(IWineD3DDevice *iface, UINT iSwapChain, WINED3DGAMMARAMP* pRamp) {
7740 IWineD3DSwapChain *swapchain;
7741 HRESULT hrc = WINED3D_OK;
7743 TRACE("Relaying to swapchain\n");
7745 if ((hrc = IWineD3DDeviceImpl_GetSwapChain(iface, iSwapChain, &swapchain)) == WINED3D_OK) {
7746 hrc =IWineD3DSwapChain_GetGammaRamp(swapchain, pRamp);
7752 /** ********************************************************
7753 * Notification functions
7754 ** ********************************************************/
7755 /** This function must be called in the release of a resource when ref == 0,
7756 * the contents of resource must still be correct,
7757 * any handels to other resource held by the caller must be closed
7758 * (e.g. a texture should release all held surfaces because telling the device that it's been released.)
7759 *****************************************************/
7760 static void WINAPI IWineD3DDeviceImpl_AddResource(IWineD3DDevice *iface, IWineD3DResource *resource){
7761 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
7762 ResourceList* resourceList;
7764 TRACE("(%p) : resource %p\n", This, resource);
7766 EnterCriticalSection(&resourceStoreCriticalSection);
7768 /* add a new texture to the frot of the linked list */
7769 resourceList = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(ResourceList));
7770 resourceList->resource = resource;
7772 /* Get the old head */
7773 resourceList->next = This->resources;
7775 This->resources = resourceList;
7776 TRACE("Added resource %p with element %p pointing to %p\n", resource, resourceList, resourceList->next);
7779 LeaveCriticalSection(&resourceStoreCriticalSection);
7784 static void WINAPI IWineD3DDeviceImpl_RemoveResource(IWineD3DDevice *iface, IWineD3DResource *resource){
7785 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
7786 ResourceList* resourceList = NULL;
7787 ResourceList* previousResourceList = NULL;
7789 TRACE("(%p) : resource %p\n", This, resource);
7792 EnterCriticalSection(&resourceStoreCriticalSection);
7794 resourceList = This->resources;
7796 while (resourceList != NULL) {
7797 if(resourceList->resource == resource) break;
7798 previousResourceList = resourceList;
7799 resourceList = resourceList->next;
7802 if (resourceList == NULL) {
7803 FIXME("Attempted to remove resource %p that hasn't been stored\n", resource);
7805 LeaveCriticalSection(&resourceStoreCriticalSection);
7809 TRACE("Found resource %p with element %p pointing to %p (previous %p)\n", resourceList->resource, resourceList, resourceList->next, previousResourceList);
7811 /* make sure we don't leave a hole in the list */
7812 if (previousResourceList != NULL) {
7813 previousResourceList->next = resourceList->next;
7815 This->resources = resourceList->next;
7819 LeaveCriticalSection(&resourceStoreCriticalSection);
7825 static void WINAPI IWineD3DDeviceImpl_ResourceReleased(IWineD3DDevice *iface, IWineD3DResource *resource){
7826 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *) iface;
7829 TRACE("(%p) : resource %p\n", This, resource);
7830 switch(IWineD3DResource_GetType(resource)){
7831 case WINED3DRTYPE_SURFACE:
7832 /* TODO: check front and back buffers, rendertargets etc.. possibly swapchains? */
7834 case WINED3DRTYPE_TEXTURE:
7835 case WINED3DRTYPE_CUBETEXTURE:
7836 case WINED3DRTYPE_VOLUMETEXTURE:
7837 for (counter = 0; counter < GL_LIMITS(sampler_stages); counter++) {
7838 if (This->stateBlock != NULL && This->stateBlock->textures[counter] == (IWineD3DBaseTexture *)resource) {
7839 WARN("Texture being released is still by a stateblock, Stage = %u Texture = %p\n", counter, resource);
7840 This->stateBlock->textures[counter] = NULL;
7842 if (This->updateStateBlock != This->stateBlock ){
7843 if (This->updateStateBlock->textures[counter] == (IWineD3DBaseTexture *)resource) {
7844 WARN("Texture being released is still by a stateblock, Stage = %u Texture = %p\n", counter, resource);
7845 This->updateStateBlock->textures[counter] = NULL;
7850 case WINED3DRTYPE_VOLUME:
7851 /* TODO: nothing really? */
7853 case WINED3DRTYPE_VERTEXBUFFER:
7854 /* MSDN: When an application no longer holds a references to this interface, the interface will automatically be freed. */
7857 TRACE("Cleaning up stream pointers\n");
7859 for(streamNumber = 0; streamNumber < MAX_STREAMS; streamNumber ++){
7860 /* FINDOUT: should a warn be generated if were recording and updateStateBlock->streamSource is lost?
7861 FINDOUT: should changes.streamSource[StreamNumber] be set ?
7863 if (This->updateStateBlock != NULL ) { /* ==NULL when device is being destroyed */
7864 if ((IWineD3DResource *)This->updateStateBlock->streamSource[streamNumber] == resource) {
7865 FIXME("Vertex buffer released while bound to a state block, stream %d\n", streamNumber);
7866 This->updateStateBlock->streamSource[streamNumber] = 0;
7867 /* Set changed flag? */
7870 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) */
7871 if ((IWineD3DResource *)This->stateBlock->streamSource[streamNumber] == resource) {
7872 TRACE("Vertex buffer released while bound to a state block, stream %d\n", streamNumber);
7873 This->stateBlock->streamSource[streamNumber] = 0;
7876 #if 0 /* TODO: Manage internal tracking properly so that 'this shouldn't happen' */
7877 else { /* This shouldn't happen */
7878 FIXME("Calling application has released the device before relasing all the resources bound to the device\n");
7885 case WINED3DRTYPE_INDEXBUFFER:
7886 /* MSDN: When an application no longer holds a references to this interface, the interface will automatically be freed.*/
7887 if (This->updateStateBlock != NULL ) { /* ==NULL when device is being destroyed */
7888 if (This->updateStateBlock->pIndexData == (IWineD3DIndexBuffer *)resource) {
7889 This->updateStateBlock->pIndexData = NULL;
7892 if (This->stateBlock != NULL ) { /* ==NULL when device is being destroyed */
7893 if (This->stateBlock->pIndexData == (IWineD3DIndexBuffer *)resource) {
7894 This->stateBlock->pIndexData = NULL;
7900 FIXME("(%p) unknown resource type %p %u\n", This, resource, IWineD3DResource_GetType(resource));
7905 /* Remove the resoruce from the resourceStore */
7906 IWineD3DDeviceImpl_RemoveResource(iface, resource);
7908 TRACE("Resource released\n");
7912 /**********************************************************
7913 * IWineD3DDevice VTbl follows
7914 **********************************************************/
7916 const IWineD3DDeviceVtbl IWineD3DDevice_Vtbl =
7918 /*** IUnknown methods ***/
7919 IWineD3DDeviceImpl_QueryInterface,
7920 IWineD3DDeviceImpl_AddRef,
7921 IWineD3DDeviceImpl_Release,
7922 /*** IWineD3DDevice methods ***/
7923 IWineD3DDeviceImpl_GetParent,
7924 /*** Creation methods**/
7925 IWineD3DDeviceImpl_CreateVertexBuffer,
7926 IWineD3DDeviceImpl_CreateIndexBuffer,
7927 IWineD3DDeviceImpl_CreateStateBlock,
7928 IWineD3DDeviceImpl_CreateSurface,
7929 IWineD3DDeviceImpl_CreateTexture,
7930 IWineD3DDeviceImpl_CreateVolumeTexture,
7931 IWineD3DDeviceImpl_CreateVolume,
7932 IWineD3DDeviceImpl_CreateCubeTexture,
7933 IWineD3DDeviceImpl_CreateQuery,
7934 IWineD3DDeviceImpl_CreateAdditionalSwapChain,
7935 IWineD3DDeviceImpl_CreateVertexDeclaration,
7936 IWineD3DDeviceImpl_CreateVertexShader,
7937 IWineD3DDeviceImpl_CreatePixelShader,
7938 IWineD3DDeviceImpl_CreatePalette,
7939 /*** Odd functions **/
7940 IWineD3DDeviceImpl_Init3D,
7941 IWineD3DDeviceImpl_Uninit3D,
7942 IWineD3DDeviceImpl_SetFullscreen,
7943 IWineD3DDeviceImpl_EnumDisplayModes,
7944 IWineD3DDeviceImpl_EvictManagedResources,
7945 IWineD3DDeviceImpl_GetAvailableTextureMem,
7946 IWineD3DDeviceImpl_GetBackBuffer,
7947 IWineD3DDeviceImpl_GetCreationParameters,
7948 IWineD3DDeviceImpl_GetDeviceCaps,
7949 IWineD3DDeviceImpl_GetDirect3D,
7950 IWineD3DDeviceImpl_GetDisplayMode,
7951 IWineD3DDeviceImpl_SetDisplayMode,
7952 IWineD3DDeviceImpl_GetHWND,
7953 IWineD3DDeviceImpl_SetHWND,
7954 IWineD3DDeviceImpl_GetNumberOfSwapChains,
7955 IWineD3DDeviceImpl_GetRasterStatus,
7956 IWineD3DDeviceImpl_GetSwapChain,
7957 IWineD3DDeviceImpl_Reset,
7958 IWineD3DDeviceImpl_SetDialogBoxMode,
7959 IWineD3DDeviceImpl_SetCursorProperties,
7960 IWineD3DDeviceImpl_SetCursorPosition,
7961 IWineD3DDeviceImpl_ShowCursor,
7962 IWineD3DDeviceImpl_TestCooperativeLevel,
7963 /*** Getters and setters **/
7964 IWineD3DDeviceImpl_SetClipPlane,
7965 IWineD3DDeviceImpl_GetClipPlane,
7966 IWineD3DDeviceImpl_SetClipStatus,
7967 IWineD3DDeviceImpl_GetClipStatus,
7968 IWineD3DDeviceImpl_SetCurrentTexturePalette,
7969 IWineD3DDeviceImpl_GetCurrentTexturePalette,
7970 IWineD3DDeviceImpl_SetDepthStencilSurface,
7971 IWineD3DDeviceImpl_GetDepthStencilSurface,
7972 IWineD3DDeviceImpl_SetFVF,
7973 IWineD3DDeviceImpl_GetFVF,
7974 IWineD3DDeviceImpl_SetGammaRamp,
7975 IWineD3DDeviceImpl_GetGammaRamp,
7976 IWineD3DDeviceImpl_SetIndices,
7977 IWineD3DDeviceImpl_GetIndices,
7978 IWineD3DDeviceImpl_SetLight,
7979 IWineD3DDeviceImpl_GetLight,
7980 IWineD3DDeviceImpl_SetLightEnable,
7981 IWineD3DDeviceImpl_GetLightEnable,
7982 IWineD3DDeviceImpl_SetMaterial,
7983 IWineD3DDeviceImpl_GetMaterial,
7984 IWineD3DDeviceImpl_SetNPatchMode,
7985 IWineD3DDeviceImpl_GetNPatchMode,
7986 IWineD3DDeviceImpl_SetPaletteEntries,
7987 IWineD3DDeviceImpl_GetPaletteEntries,
7988 IWineD3DDeviceImpl_SetPixelShader,
7989 IWineD3DDeviceImpl_GetPixelShader,
7990 IWineD3DDeviceImpl_SetPixelShaderConstantB,
7991 IWineD3DDeviceImpl_GetPixelShaderConstantB,
7992 IWineD3DDeviceImpl_SetPixelShaderConstantI,
7993 IWineD3DDeviceImpl_GetPixelShaderConstantI,
7994 IWineD3DDeviceImpl_SetPixelShaderConstantF,
7995 IWineD3DDeviceImpl_GetPixelShaderConstantF,
7996 IWineD3DDeviceImpl_SetRenderState,
7997 IWineD3DDeviceImpl_GetRenderState,
7998 IWineD3DDeviceImpl_SetRenderTarget,
7999 IWineD3DDeviceImpl_GetRenderTarget,
8000 IWineD3DDeviceImpl_SetFrontBackBuffers,
8001 IWineD3DDeviceImpl_SetSamplerState,
8002 IWineD3DDeviceImpl_GetSamplerState,
8003 IWineD3DDeviceImpl_SetScissorRect,
8004 IWineD3DDeviceImpl_GetScissorRect,
8005 IWineD3DDeviceImpl_SetSoftwareVertexProcessing,
8006 IWineD3DDeviceImpl_GetSoftwareVertexProcessing,
8007 IWineD3DDeviceImpl_SetStreamSource,
8008 IWineD3DDeviceImpl_GetStreamSource,
8009 IWineD3DDeviceImpl_SetStreamSourceFreq,
8010 IWineD3DDeviceImpl_GetStreamSourceFreq,
8011 IWineD3DDeviceImpl_SetTexture,
8012 IWineD3DDeviceImpl_GetTexture,
8013 IWineD3DDeviceImpl_SetTextureStageState,
8014 IWineD3DDeviceImpl_GetTextureStageState,
8015 IWineD3DDeviceImpl_SetTransform,
8016 IWineD3DDeviceImpl_GetTransform,
8017 IWineD3DDeviceImpl_SetVertexDeclaration,
8018 IWineD3DDeviceImpl_GetVertexDeclaration,
8019 IWineD3DDeviceImpl_SetVertexShader,
8020 IWineD3DDeviceImpl_GetVertexShader,
8021 IWineD3DDeviceImpl_SetVertexShaderConstantB,
8022 IWineD3DDeviceImpl_GetVertexShaderConstantB,
8023 IWineD3DDeviceImpl_SetVertexShaderConstantI,
8024 IWineD3DDeviceImpl_GetVertexShaderConstantI,
8025 IWineD3DDeviceImpl_SetVertexShaderConstantF,
8026 IWineD3DDeviceImpl_GetVertexShaderConstantF,
8027 IWineD3DDeviceImpl_SetViewport,
8028 IWineD3DDeviceImpl_GetViewport,
8029 IWineD3DDeviceImpl_MultiplyTransform,
8030 IWineD3DDeviceImpl_ValidateDevice,
8031 IWineD3DDeviceImpl_ProcessVertices,
8032 /*** State block ***/
8033 IWineD3DDeviceImpl_BeginStateBlock,
8034 IWineD3DDeviceImpl_EndStateBlock,
8035 /*** Scene management ***/
8036 IWineD3DDeviceImpl_BeginScene,
8037 IWineD3DDeviceImpl_EndScene,
8038 IWineD3DDeviceImpl_Present,
8039 IWineD3DDeviceImpl_Clear,
8041 IWineD3DDeviceImpl_DrawPrimitive,
8042 IWineD3DDeviceImpl_DrawIndexedPrimitive,
8043 IWineD3DDeviceImpl_DrawPrimitiveUP,
8044 IWineD3DDeviceImpl_DrawIndexedPrimitiveUP,
8045 IWineD3DDeviceImpl_DrawPrimitiveStrided,
8046 IWineD3DDeviceImpl_DrawRectPatch,
8047 IWineD3DDeviceImpl_DrawTriPatch,
8048 IWineD3DDeviceImpl_DeletePatch,
8049 IWineD3DDeviceImpl_ColorFill,
8050 IWineD3DDeviceImpl_UpdateTexture,
8051 IWineD3DDeviceImpl_UpdateSurface,
8052 IWineD3DDeviceImpl_StretchRect,
8053 IWineD3DDeviceImpl_GetRenderTargetData,
8054 IWineD3DDeviceImpl_GetFrontBufferData,
8055 /*** Internal use IWineD3DDevice methods ***/
8056 IWineD3DDeviceImpl_SetupTextureStates,
8057 /*** object tracking ***/
8058 IWineD3DDeviceImpl_ResourceReleased
8062 const DWORD SavedPixelStates_R[NUM_SAVEDPIXELSTATES_R] = {
8063 WINED3DRS_ALPHABLENDENABLE ,
8064 WINED3DRS_ALPHAFUNC ,
8065 WINED3DRS_ALPHAREF ,
8066 WINED3DRS_ALPHATESTENABLE ,
8068 WINED3DRS_COLORWRITEENABLE ,
8069 WINED3DRS_DESTBLEND ,
8070 WINED3DRS_DITHERENABLE ,
8071 WINED3DRS_FILLMODE ,
8072 WINED3DRS_FOGDENSITY ,
8074 WINED3DRS_FOGSTART ,
8075 WINED3DRS_LASTPIXEL ,
8076 WINED3DRS_SHADEMODE ,
8077 WINED3DRS_SRCBLEND ,
8078 WINED3DRS_STENCILENABLE ,
8079 WINED3DRS_STENCILFAIL ,
8080 WINED3DRS_STENCILFUNC ,
8081 WINED3DRS_STENCILMASK ,
8082 WINED3DRS_STENCILPASS ,
8083 WINED3DRS_STENCILREF ,
8084 WINED3DRS_STENCILWRITEMASK ,
8085 WINED3DRS_STENCILZFAIL ,
8086 WINED3DRS_TEXTUREFACTOR ,
8097 WINED3DRS_ZWRITEENABLE
8100 const DWORD SavedPixelStates_T[NUM_SAVEDPIXELSTATES_T] = {
8101 WINED3DTSS_ADDRESSW ,
8102 WINED3DTSS_ALPHAARG0 ,
8103 WINED3DTSS_ALPHAARG1 ,
8104 WINED3DTSS_ALPHAARG2 ,
8105 WINED3DTSS_ALPHAOP ,
8106 WINED3DTSS_BUMPENVLOFFSET ,
8107 WINED3DTSS_BUMPENVLSCALE ,
8108 WINED3DTSS_BUMPENVMAT00 ,
8109 WINED3DTSS_BUMPENVMAT01 ,
8110 WINED3DTSS_BUMPENVMAT10 ,
8111 WINED3DTSS_BUMPENVMAT11 ,
8112 WINED3DTSS_COLORARG0 ,
8113 WINED3DTSS_COLORARG1 ,
8114 WINED3DTSS_COLORARG2 ,
8115 WINED3DTSS_COLOROP ,
8116 WINED3DTSS_RESULTARG ,
8117 WINED3DTSS_TEXCOORDINDEX ,
8118 WINED3DTSS_TEXTURETRANSFORMFLAGS
8121 const DWORD SavedPixelStates_S[NUM_SAVEDPIXELSTATES_S] = {
8122 WINED3DSAMP_ADDRESSU ,
8123 WINED3DSAMP_ADDRESSV ,
8124 WINED3DSAMP_ADDRESSW ,
8125 WINED3DSAMP_BORDERCOLOR ,
8126 WINED3DSAMP_MAGFILTER ,
8127 WINED3DSAMP_MINFILTER ,
8128 WINED3DSAMP_MIPFILTER ,
8129 WINED3DSAMP_MIPMAPLODBIAS ,
8130 WINED3DSAMP_MAXMIPLEVEL ,
8131 WINED3DSAMP_MAXANISOTROPY ,
8132 WINED3DSAMP_SRGBTEXTURE ,
8133 WINED3DSAMP_ELEMENTINDEX
8136 const DWORD SavedVertexStates_R[NUM_SAVEDVERTEXSTATES_R] = {
8138 WINED3DRS_AMBIENTMATERIALSOURCE ,
8139 WINED3DRS_CLIPPING ,
8140 WINED3DRS_CLIPPLANEENABLE ,
8141 WINED3DRS_COLORVERTEX ,
8142 WINED3DRS_DIFFUSEMATERIALSOURCE ,
8143 WINED3DRS_EMISSIVEMATERIALSOURCE ,
8144 WINED3DRS_FOGDENSITY ,
8146 WINED3DRS_FOGSTART ,
8147 WINED3DRS_FOGTABLEMODE ,
8148 WINED3DRS_FOGVERTEXMODE ,
8149 WINED3DRS_INDEXEDVERTEXBLENDENABLE ,
8150 WINED3DRS_LIGHTING ,
8151 WINED3DRS_LOCALVIEWER ,
8152 WINED3DRS_MULTISAMPLEANTIALIAS ,
8153 WINED3DRS_MULTISAMPLEMASK ,
8154 WINED3DRS_NORMALIZENORMALS ,
8155 WINED3DRS_PATCHEDGESTYLE ,
8156 WINED3DRS_POINTSCALE_A ,
8157 WINED3DRS_POINTSCALE_B ,
8158 WINED3DRS_POINTSCALE_C ,
8159 WINED3DRS_POINTSCALEENABLE ,
8160 WINED3DRS_POINTSIZE ,
8161 WINED3DRS_POINTSIZE_MAX ,
8162 WINED3DRS_POINTSIZE_MIN ,
8163 WINED3DRS_POINTSPRITEENABLE ,
8164 WINED3DRS_RANGEFOGENABLE ,
8165 WINED3DRS_SPECULARMATERIALSOURCE ,
8166 WINED3DRS_TWEENFACTOR ,
8167 WINED3DRS_VERTEXBLEND
8170 const DWORD SavedVertexStates_T[NUM_SAVEDVERTEXSTATES_T] = {
8171 WINED3DTSS_TEXCOORDINDEX ,
8172 WINED3DTSS_TEXTURETRANSFORMFLAGS
8175 const DWORD SavedVertexStates_S[NUM_SAVEDVERTEXSTATES_S] = {
8176 WINED3DSAMP_DMAPOFFSET