2 * IWineD3DDevice implementation
4 * Copyright 2002 Lionel Ulmer
5 * Copyright 2002-2005 Jason Edmeades
6 * Copyright 2003-2004 Raphael Junqueira
7 * Copyright 2004 Christian Costa
8 * Copyright 2005 Oliver Stieber
9 * Copyright 2006 Stefan Dösinger for CodeWeavers
10 * Copyright 2006 Henri Verbeet
12 * This library is free software; you can redistribute it and/or
13 * modify it under the terms of the GNU Lesser General Public
14 * License as published by the Free Software Foundation; either
15 * version 2.1 of the License, or (at your option) any later version.
17 * This library is distributed in the hope that it will be useful,
18 * but WITHOUT ANY WARRANTY; without even the implied warranty of
19 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
20 * Lesser General Public License for more details.
22 * You should have received a copy of the GNU Lesser General Public
23 * License along with this library; if not, write to the Free Software
24 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
32 #include "wined3d_private.h"
34 WINE_DEFAULT_DEBUG_CHANNEL(d3d);
35 WINE_DECLARE_DEBUG_CHANNEL(d3d_shader);
36 #define GLINFO_LOCATION ((IWineD3DImpl *)(This->wineD3D))->gl_info
38 /* Define the default light parameters as specified by MSDN */
39 const WINED3DLIGHT WINED3D_default_light = {
41 WINED3DLIGHT_DIRECTIONAL, /* Type */
42 { 1.0, 1.0, 1.0, 0.0 }, /* Diffuse r,g,b,a */
43 { 0.0, 0.0, 0.0, 0.0 }, /* Specular r,g,b,a */
44 { 0.0, 0.0, 0.0, 0.0 }, /* Ambient r,g,b,a, */
45 { 0.0, 0.0, 0.0 }, /* Position x,y,z */
46 { 0.0, 0.0, 1.0 }, /* Direction x,y,z */
49 0.0, 0.0, 0.0, /* Attenuation 0,1,2 */
54 /* x11drv GDI escapes */
55 #define X11DRV_ESCAPE 6789
56 enum x11drv_escape_codes
58 X11DRV_GET_DISPLAY, /* get X11 display for a DC */
59 X11DRV_GET_DRAWABLE, /* get current drawable for a DC */
60 X11DRV_GET_FONT, /* get current X font for a DC */
63 /* retrieve the X display to use on a given DC */
64 inline static Display *get_display( HDC hdc )
67 enum x11drv_escape_codes escape = X11DRV_GET_DISPLAY;
69 if (!ExtEscape( hdc, X11DRV_ESCAPE, sizeof(escape), (LPCSTR)&escape,
70 sizeof(display), (LPSTR)&display )) display = NULL;
74 /* allocate one pbuffer per surface */
75 BOOL pbuffer_per_surface = FALSE;
77 /* static function declarations */
78 static void WINAPI IWineD3DDeviceImpl_AddResource(IWineD3DDevice *iface, IWineD3DResource *resource);
80 static void WINAPI IWineD3DDeviceImpl_ApplyTextureUnitState(IWineD3DDevice *iface, DWORD Stage, WINED3DTEXTURESTAGESTATETYPE Type);
83 #define D3DMEMCHECK(object, ppResult) if(NULL == object) { *ppResult = NULL; WARN("Out of memory\n"); return WINED3DERR_OUTOFVIDEOMEMORY;}
85 #define D3DCREATEOBJECTINSTANCE(object, type) { \
86 object=HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(IWineD3D##type##Impl)); \
87 D3DMEMCHECK(object, pp##type); \
88 object->lpVtbl = &IWineD3D##type##_Vtbl; \
89 object->wineD3DDevice = This; \
90 object->parent = parent; \
92 *pp##type = (IWineD3D##type *) object; \
95 #define D3DCREATESHADEROBJECTINSTANCE(object, type) { \
96 object=HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(IWineD3D##type##Impl)); \
97 D3DMEMCHECK(object, pp##type); \
98 object->lpVtbl = &IWineD3D##type##_Vtbl; \
99 object->parent = parent; \
101 object->baseShader.device = (IWineD3DDevice*) This; \
102 *pp##type = (IWineD3D##type *) object; \
105 #define D3DCREATERESOURCEOBJECTINSTANCE(object, type, d3dtype, _size){ \
106 object=HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(IWineD3D##type##Impl)); \
107 D3DMEMCHECK(object, pp##type); \
108 object->lpVtbl = &IWineD3D##type##_Vtbl; \
109 object->resource.wineD3DDevice = This; \
110 object->resource.parent = parent; \
111 object->resource.resourceType = d3dtype; \
112 object->resource.ref = 1; \
113 object->resource.pool = Pool; \
114 object->resource.format = Format; \
115 object->resource.usage = Usage; \
116 object->resource.size = _size; \
117 /* Check that we have enough video ram left */ \
118 if (Pool == WINED3DPOOL_DEFAULT) { \
119 if (IWineD3DDevice_GetAvailableTextureMem(iface) <= _size) { \
120 WARN("Out of 'bogus' video memory\n"); \
121 HeapFree(GetProcessHeap(), 0, object); \
123 return WINED3DERR_OUTOFVIDEOMEMORY; \
125 globalChangeGlRam(_size); \
127 object->resource.allocatedMemory = (0 == _size ? NULL : Pool == WINED3DPOOL_DEFAULT ? NULL : HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, _size)); \
128 if (object->resource.allocatedMemory == NULL && _size != 0 && Pool != WINED3DPOOL_DEFAULT) { \
129 FIXME("Out of memory!\n"); \
130 HeapFree(GetProcessHeap(), 0, object); \
132 return WINED3DERR_OUTOFVIDEOMEMORY; \
134 *pp##type = (IWineD3D##type *) object; \
135 IWineD3DDeviceImpl_AddResource(iface, (IWineD3DResource *)object) ;\
136 TRACE("(%p) : Created resource %p\n", This, object); \
139 #define D3DINITIALIZEBASETEXTURE(_basetexture) { \
140 _basetexture.levels = Levels; \
141 _basetexture.filterType = (Usage & WINED3DUSAGE_AUTOGENMIPMAP) ? WINED3DTEXF_LINEAR : WINED3DTEXF_NONE; \
142 _basetexture.LOD = 0; \
143 _basetexture.dirty = TRUE; \
146 /**********************************************************
147 * Global variable / Constants follow
148 **********************************************************/
149 const float identity[16] = {1,0,0,0, 0,1,0,0, 0,0,1,0, 0,0,0,1}; /* When needed for comparisons */
151 /**********************************************************
152 * Utility functions follow
153 **********************************************************/
154 /* Convert the WINED3DLIGHT properties into equivalent gl lights */
155 static void setup_light(IWineD3DDevice *iface, LONG Index, PLIGHTINFOEL *lightInfo) {
158 float colRGBA[] = {0.0, 0.0, 0.0, 0.0};
159 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
161 /* Light settings are affected by the model view in OpenGL, the View transform in direct3d*/
162 glMatrixMode(GL_MODELVIEW);
164 glLoadMatrixf((float *)&This->stateBlock->transforms[WINED3DTS_VIEW].u.m[0][0]);
167 colRGBA[0] = lightInfo->OriginalParms.Diffuse.r;
168 colRGBA[1] = lightInfo->OriginalParms.Diffuse.g;
169 colRGBA[2] = lightInfo->OriginalParms.Diffuse.b;
170 colRGBA[3] = lightInfo->OriginalParms.Diffuse.a;
171 glLightfv(GL_LIGHT0+Index, GL_DIFFUSE, colRGBA);
172 checkGLcall("glLightfv");
175 colRGBA[0] = lightInfo->OriginalParms.Specular.r;
176 colRGBA[1] = lightInfo->OriginalParms.Specular.g;
177 colRGBA[2] = lightInfo->OriginalParms.Specular.b;
178 colRGBA[3] = lightInfo->OriginalParms.Specular.a;
179 glLightfv(GL_LIGHT0+Index, GL_SPECULAR, colRGBA);
180 checkGLcall("glLightfv");
183 colRGBA[0] = lightInfo->OriginalParms.Ambient.r;
184 colRGBA[1] = lightInfo->OriginalParms.Ambient.g;
185 colRGBA[2] = lightInfo->OriginalParms.Ambient.b;
186 colRGBA[3] = lightInfo->OriginalParms.Ambient.a;
187 glLightfv(GL_LIGHT0+Index, GL_AMBIENT, colRGBA);
188 checkGLcall("glLightfv");
190 /* Attenuation - Are these right? guessing... */
191 glLightf(GL_LIGHT0+Index, GL_CONSTANT_ATTENUATION, lightInfo->OriginalParms.Attenuation0);
192 checkGLcall("glLightf");
193 glLightf(GL_LIGHT0+Index, GL_LINEAR_ATTENUATION, lightInfo->OriginalParms.Attenuation1);
194 checkGLcall("glLightf");
196 if ((lightInfo->OriginalParms.Range *lightInfo->OriginalParms.Range) >= FLT_MIN) {
197 quad_att = 1.4/(lightInfo->OriginalParms.Range *lightInfo->OriginalParms.Range);
199 quad_att = 0; /* 0 or MAX? (0 seems to be ok) */
202 if (quad_att < lightInfo->OriginalParms.Attenuation2) quad_att = lightInfo->OriginalParms.Attenuation2;
203 glLightf(GL_LIGHT0+Index, GL_QUADRATIC_ATTENUATION, quad_att);
204 checkGLcall("glLightf");
206 switch (lightInfo->OriginalParms.Type) {
207 case WINED3DLIGHT_POINT:
209 glLightfv(GL_LIGHT0+Index, GL_POSITION, &lightInfo->lightPosn[0]);
210 checkGLcall("glLightfv");
211 glLightf(GL_LIGHT0 + Index, GL_SPOT_CUTOFF, lightInfo->cutoff);
212 checkGLcall("glLightf");
216 case WINED3DLIGHT_SPOT:
218 glLightfv(GL_LIGHT0+Index, GL_POSITION, &lightInfo->lightPosn[0]);
219 checkGLcall("glLightfv");
221 glLightfv(GL_LIGHT0+Index, GL_SPOT_DIRECTION, &lightInfo->lightDirn[0]);
222 checkGLcall("glLightfv");
223 glLightf(GL_LIGHT0 + Index, GL_SPOT_EXPONENT, lightInfo->exponent);
224 checkGLcall("glLightf");
225 glLightf(GL_LIGHT0 + Index, GL_SPOT_CUTOFF, lightInfo->cutoff);
226 checkGLcall("glLightf");
230 case WINED3DLIGHT_DIRECTIONAL:
232 glLightfv(GL_LIGHT0+Index, GL_POSITION, &lightInfo->lightPosn[0]); /* Note gl uses w position of 0 for direction! */
233 checkGLcall("glLightfv");
234 glLightf(GL_LIGHT0+Index, GL_SPOT_CUTOFF, lightInfo->cutoff);
235 checkGLcall("glLightf");
236 glLightf(GL_LIGHT0+Index, GL_SPOT_EXPONENT, 0.0f);
237 checkGLcall("glLightf");
241 FIXME("Unrecognized light type %d\n", lightInfo->OriginalParms.Type);
244 /* Restore the modelview matrix */
248 /**********************************************************
249 * GLSL helper functions follow
250 **********************************************************/
252 /** Attach a GLSL pixel or vertex shader object to the shader program */
253 static void attach_glsl_shader(IWineD3DDevice *iface, IWineD3DBaseShader* shader) {
255 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
256 GLhandleARB shaderObj = ((IWineD3DBaseShaderImpl*)shader)->baseShader.prgId;
257 if (This->stateBlock->glsl_program && shaderObj != 0) {
258 TRACE_(d3d_shader)("Attaching GLSL shader object %u to program %u\n", shaderObj, This->stateBlock->glsl_program->programId);
259 GL_EXTCALL(glAttachObjectARB(This->stateBlock->glsl_program->programId, shaderObj));
260 checkGLcall("glAttachObjectARB");
264 /** Sets the GLSL program ID for the given pixel and vertex shader combination.
265 * It sets the programId on the current StateBlock (because it should be called
266 * inside of the DrawPrimitive() part of the render loop).
268 * If a program for the given combination does not exist, create one, and store
269 * the program in the list. If it creates a program, it will link the given
272 * We keep the shader programs around on a list because linking
273 * shader objects together is an expensive operation. It's much
274 * faster to loop through a list of pre-compiled & linked programs
275 * each time that the application sets a new pixel or vertex shader
276 * than it is to re-link them together at that time.
278 * The list will be deleted in IWineD3DDevice::Release().
280 void set_glsl_shader_program(IWineD3DDevice *iface) {
282 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
283 IWineD3DPixelShader *pshader = This->stateBlock->pixelShader;
284 IWineD3DVertexShader *vshader = This->stateBlock->vertexShader;
285 struct glsl_shader_prog_link *curLink = NULL;
286 struct glsl_shader_prog_link *newLink = NULL;
287 struct list *ptr = NULL;
288 GLhandleARB programId = 0;
292 ptr = list_head( &This->glsl_shader_progs );
294 /* At least one program exists - see if it matches our ps/vs combination */
295 curLink = LIST_ENTRY( ptr, struct glsl_shader_prog_link, entry );
296 if (vshader == curLink->vertexShader && pshader == curLink->pixelShader) {
297 /* Existing Program found, use it */
298 TRACE_(d3d_shader)("Found existing program (%u) for this vertex/pixel shader combination\n",
300 This->stateBlock->glsl_program = curLink;
303 /* This isn't the entry we need - try the next one */
304 ptr = list_next( &This->glsl_shader_progs, ptr );
307 /* If we get to this point, then no matching program exists, so we create one */
308 programId = GL_EXTCALL(glCreateProgramObjectARB());
309 TRACE_(d3d_shader)("Created new GLSL shader program %u\n", programId);
311 /* Allocate a new link for the list of programs */
312 newLink = HeapAlloc(GetProcessHeap(), 0, sizeof(struct glsl_shader_prog_link));
313 newLink->programId = programId;
314 This->stateBlock->glsl_program = newLink;
316 /* Attach GLSL vshader */
317 if (NULL != vshader && This->vs_selected_mode == SHADER_GLSL) {
319 int max_attribs = 16; /* TODO: Will this always be the case? It is at the moment... */
322 TRACE("Attaching vertex shader to GLSL program\n");
323 attach_glsl_shader(iface, (IWineD3DBaseShader*)vshader);
325 /* Bind vertex attributes to a corresponding index number to match
326 * the same index numbers as ARB_vertex_programs (makes loading
327 * vertex attributes simpler). With this method, we can use the
328 * exact same code to load the attributes later for both ARB and
331 * We have to do this here because we need to know the Program ID
332 * in order to make the bindings work, and it has to be done prior
333 * to linking the GLSL program. */
334 for (i = 0; i < max_attribs; ++i) {
335 snprintf(tmp_name, sizeof(tmp_name), "attrib%i", i);
336 GL_EXTCALL(glBindAttribLocationARB(programId, i, tmp_name));
338 checkGLcall("glBindAttribLocationARB");
339 newLink->vertexShader = vshader;
342 /* Attach GLSL pshader */
343 if (NULL != pshader && This->ps_selected_mode == SHADER_GLSL) {
344 TRACE("Attaching pixel shader to GLSL program\n");
345 attach_glsl_shader(iface, (IWineD3DBaseShader*)pshader);
346 newLink->pixelShader = pshader;
349 /* Link the program */
350 TRACE_(d3d_shader)("Linking GLSL shader program %u\n", programId);
351 GL_EXTCALL(glLinkProgramARB(programId));
352 print_glsl_info_log(&GLINFO_LOCATION, programId);
353 list_add_head( &This->glsl_shader_progs, &newLink->entry);
355 newLink->vuniformF_locations = HeapAlloc(GetProcessHeap(), 0, sizeof(GLhandleARB) * GL_LIMITS(vshader_constantsF));
356 for (i = 0; i < GL_LIMITS(vshader_constantsF); ++i) {
357 snprintf(glsl_name, sizeof(glsl_name), "VC[%i]", i);
358 newLink->vuniformF_locations[i] = GL_EXTCALL(glGetUniformLocationARB(programId, glsl_name));
360 newLink->puniformF_locations = HeapAlloc(GetProcessHeap(), 0, sizeof(GLhandleARB) * GL_LIMITS(pshader_constantsF));
361 for (i = 0; i < GL_LIMITS(pshader_constantsF); ++i) {
362 snprintf(glsl_name, sizeof(glsl_name), "PC[%i]", i);
363 newLink->puniformF_locations[i] = GL_EXTCALL(glGetUniformLocationARB(programId, glsl_name));
369 /** Detach the GLSL pixel or vertex shader object from the shader program */
370 static void detach_glsl_shader(IWineD3DDevice *iface, GLhandleARB shaderObj, GLhandleARB programId) {
372 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
374 if (shaderObj != 0 && programId != 0) {
375 TRACE_(d3d_shader)("Detaching GLSL shader object %u from program %u\n", shaderObj, programId);
376 GL_EXTCALL(glDetachObjectARB(programId, shaderObj));
377 checkGLcall("glDetachObjectARB");
381 /** Delete a GLSL shader program */
382 static void delete_glsl_shader_program(IWineD3DDevice *iface, GLhandleARB obj) {
384 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
387 TRACE_(d3d_shader)("Deleting GLSL shader program %u\n", obj);
388 GL_EXTCALL(glDeleteObjectARB(obj));
389 checkGLcall("glDeleteObjectARB");
393 /** Delete the list of linked programs this shader is associated with.
394 * Also at this point, check to see if there are any objects left attached
395 * to each GLSL program. If not, delete the GLSL program object.
396 * This will be run when a device is released. */
397 static void delete_glsl_shader_list(IWineD3DDevice* iface) {
399 struct list *ptr = NULL;
400 struct glsl_shader_prog_link *curLink = NULL;
401 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
405 GLhandleARB objList[2]; /* There should never be more than 2 objects attached
406 (one pixel shader and one vertex shader at most) */
408 ptr = list_head( &This->glsl_shader_progs );
410 /* First, get the current item,
411 * save the link to the next pointer,
412 * detach and delete shader objects,
413 * then de-allocate the list item's memory */
414 curLink = LIST_ENTRY( ptr, struct glsl_shader_prog_link, entry );
415 ptr = list_next( &This->glsl_shader_progs, ptr );
417 /* See if this object is still attached to the program - it may have been detached already */
418 GL_EXTCALL(glGetAttachedObjectsARB(curLink->programId, 2, &numAttached, objList));
419 TRACE_(d3d_shader)("%i GLSL objects are currently attached to program %u\n", numAttached, curLink->programId);
420 for (i = 0; i < numAttached; i++) {
421 detach_glsl_shader(iface, objList[i], curLink->programId);
424 delete_glsl_shader_program(iface, curLink->programId);
426 /* Free the uniform locations */
427 HeapFree(GetProcessHeap(), 0, curLink->vuniformF_locations);
428 HeapFree(GetProcessHeap(), 0, curLink->puniformF_locations);
430 /* Free the memory for this list item */
431 HeapFree(GetProcessHeap(), 0, curLink);
436 /* Apply the current values to the specified texture stage */
437 static void WINAPI IWineD3DDeviceImpl_SetupTextureStates(IWineD3DDevice *iface, DWORD Sampler, DWORD texture_idx, DWORD Flags) {
438 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
446 /* In addition, IDirect3DDevice9::SetSamplerState will now be used for filtering, tiling,
447 clamping, MIPLOD, etc. This will work for up to 16 samplers.
450 if (Sampler >= GL_LIMITS(sampler_stages)) {
451 FIXME("Trying to set the state of more samplers %d than are supported %d by this openGL implementation\n", Sampler, GL_LIMITS(sampler_stages));
454 VTRACE(("Activating appropriate texture state %d\n", Sampler));
455 if (GL_SUPPORT(ARB_MULTITEXTURE)) {
457 GL_EXTCALL(glActiveTextureARB(GL_TEXTURE0_ARB + texture_idx));
458 checkGLcall("glActiveTextureARB");
460 /* Could we use bindTexture and then apply the states instead of GLACTIVETEXTURE */
461 } else if (Sampler > 0) {
462 FIXME("Program using multiple concurrent textures which this opengl implementation doesn't support\n");
466 /* TODO: change this to a lookup table
467 LOOKUP_TEXTURE_STATES lists all texture states that should be applied.
468 LOOKUP_CONTEXT_SATES list all context applicable states that can be applied
469 etc.... it's a lot cleaner, quicker and possibly easier to maintain than running a switch and setting a skip flag...
470 especially when there are a number of groups of states. */
472 TRACE("-----------------------> Updating the texture at Sampler %d to have new texture state information\n", Sampler);
474 /* The list of states not to apply is a big as the list of states to apply, so it makes sense to produce an inclusive list */
475 #define APPLY_STATE(_state) IWineD3DDeviceImpl_ApplyTextureUnitState(iface, Sampler, _state)
476 /* these are the only two supported states that need to be applied */
477 APPLY_STATE(WINED3DTSS_TEXCOORDINDEX);
478 APPLY_STATE(WINED3DTSS_TEXTURETRANSFORMFLAGS);
479 #if 0 /* not supported at the moment */
480 APPLY_STATE(WINED3DTSS_BUMPENVMAT00);
481 APPLY_STATE(WINED3DTSS_BUMPENVMAT01);
482 APPLY_STATE(WINED3DTSS_BUMPENVMAT10);
483 APPLY_STATE(WINED3DTSS_BUMPENVMAT11);
484 APPLY_STATE(WINED3DTSS_BUMPENVLSCALE);
485 APPLY_STATE(WINED3DTSS_BUMPENVLOFFSET);
486 APPLY_STATE(WINED3DTSS_RESULTARG);
487 APPLY_STATE(WINED3DTSS_CONSTANT);
489 /* a quick sanity check in case someone forgot to update this function */
490 if (WINED3D_HIGHEST_TEXTURE_STATE > WINED3DTSS_CONSTANT) {
491 FIXME("(%p) : There are more texture states than expected, update device.c to match\n", This);
495 /* apply any sampler states that always need applying */
496 if (GL_SUPPORT(EXT_TEXTURE_LOD_BIAS)) {
497 tmpvalue.d = This->stateBlock->samplerState[Sampler][WINED3DSAMP_MIPMAPLODBIAS];
498 glTexEnvf(GL_TEXTURE_FILTER_CONTROL_EXT,
499 GL_TEXTURE_LOD_BIAS_EXT,
501 checkGLcall("glTexEnvi GL_TEXTURE_LOD_BIAS_EXT ...");
504 D3DCOLORTOGLFLOAT4(This->stateBlock->renderState[WINED3DRS_TEXTUREFACTOR], col);
505 glTexEnvfv(GL_TEXTURE_ENV, GL_TEXTURE_ENV_COLOR, &col[0]);
506 checkGLcall("glTexEnvfv(GL_TEXTURE_ENV, GL_TEXTURE_ENV_COLOR, color);");
508 /* TODO: NV_POINT_SPRITE */
509 if (GL_SUPPORT(ARB_POINT_SPRITE)) {
510 if (This->stateBlock->renderState[WINED3DRS_POINTSPRITEENABLE]) {
511 /* Doesn't work with GL_POINT_SMOOTH on on my ATI 9600, but then ATI drivers are buggered! */
512 glDisable(GL_POINT_SMOOTH);
514 /* Centre the texture on the vertex */
515 VTRACE(("glTexEnvf( GL_POINT_SPRITE_ARB, GL_COORD_REPLACE_ARB, GL_TRUE)\n"));
516 glTexEnvf( GL_POINT_SPRITE_ARB, GL_COORD_REPLACE_ARB, GL_TRUE);
518 VTRACE(("glTexEnvf( GL_POINT_SPRITE_ARB, GL_COORD_REPLACE_ARB, GL_TRUE)\n"));
519 glTexEnvf( GL_POINT_SPRITE_ARB, GL_COORD_REPLACE_ARB, GL_TRUE);
520 checkGLcall("glTexEnvf(...)");
521 VTRACE(("glEnable( GL_POINT_SPRITE_ARB )\n"));
522 glEnable( GL_POINT_SPRITE_ARB );
523 checkGLcall("glEnable(...)");
525 VTRACE(("glDisable( GL_POINT_SPRITE_ARB )\n"));
526 glDisable( GL_POINT_SPRITE_ARB );
527 checkGLcall("glEnable(...)");
531 TRACE("-----------------------> Updated the texture at Sampler %d to have new texture state information\n", Sampler);
534 /**********************************************************
535 * IUnknown parts follows
536 **********************************************************/
538 static HRESULT WINAPI IWineD3DDeviceImpl_QueryInterface(IWineD3DDevice *iface,REFIID riid,LPVOID *ppobj)
540 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
542 TRACE("(%p)->(%s,%p)\n",This,debugstr_guid(riid),ppobj);
543 if (IsEqualGUID(riid, &IID_IUnknown)
544 || IsEqualGUID(riid, &IID_IWineD3DBase)
545 || IsEqualGUID(riid, &IID_IWineD3DDevice)) {
546 IUnknown_AddRef(iface);
551 return E_NOINTERFACE;
554 static ULONG WINAPI IWineD3DDeviceImpl_AddRef(IWineD3DDevice *iface) {
555 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
556 ULONG refCount = InterlockedIncrement(&This->ref);
558 TRACE("(%p) : AddRef increasing from %d\n", This, refCount - 1);
562 static ULONG WINAPI IWineD3DDeviceImpl_Release(IWineD3DDevice *iface) {
563 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
564 ULONG refCount = InterlockedDecrement(&This->ref);
566 TRACE("(%p) : Releasing from %d\n", This, refCount + 1);
569 /* TODO: Clean up all the surfaces and textures! */
570 /* NOTE: You must release the parent if the object was created via a callback
571 ** ***************************/
573 /* Delete any GLSL shader programs that may exist */
574 if (This->vs_selected_mode == SHADER_GLSL ||
575 This->ps_selected_mode == SHADER_GLSL)
576 delete_glsl_shader_list(iface);
578 /* Release the update stateblock */
579 if(IWineD3DStateBlock_Release((IWineD3DStateBlock *)This->updateStateBlock) > 0){
580 if(This->updateStateBlock != This->stateBlock)
581 FIXME("(%p) Something's still holding the Update stateblock\n",This);
583 This->updateStateBlock = NULL;
584 { /* because were not doing proper internal refcounts releasing the primary state block
585 causes recursion with the extra checks in ResourceReleased, to avoid this we have
586 to set this->stateBlock = NULL; first */
587 IWineD3DStateBlock *stateBlock = (IWineD3DStateBlock *)This->stateBlock;
588 This->stateBlock = NULL;
590 /* Release the stateblock */
591 if(IWineD3DStateBlock_Release(stateBlock) > 0){
592 FIXME("(%p) Something's still holding the Update stateblock\n",This);
596 if (This->resources != NULL ) {
597 FIXME("(%p) Device released with resources still bound, acceptable but unexpected\n", This);
598 dumpResources(This->resources);
602 IWineD3D_Release(This->wineD3D);
603 This->wineD3D = NULL;
604 HeapFree(GetProcessHeap(), 0, This);
605 TRACE("Freed device %p\n", This);
611 /**********************************************************
612 * IWineD3DDevice implementation follows
613 **********************************************************/
614 static HRESULT WINAPI IWineD3DDeviceImpl_GetParent(IWineD3DDevice *iface, IUnknown **pParent) {
615 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
616 *pParent = This->parent;
617 IUnknown_AddRef(This->parent);
621 static void CreateVBO(IWineD3DVertexBufferImpl *object) {
622 IWineD3DDeviceImpl *This = object->resource.wineD3DDevice; /* Needed for GL_EXTCALL */
623 GLenum error, glUsage;
624 DWORD vboUsage = object->resource.usage;
625 if(object->Flags & VBFLAG_VBOCREATEFAIL) {
626 WARN("Creating a vbo failed once, not trying again\n");
630 TRACE("Creating an OpenGL vertex buffer object for IWineD3DVertexBuffer %p Usage(%s)\n", object, debug_d3dusage(vboUsage));
633 /* Make sure that the gl error is cleared. Do not use checkGLcall
634 * here because checkGLcall just prints a fixme and continues. However,
635 * if an error during VBO creation occurs we can fall back to non-vbo operation
636 * with full functionality(but performance loss)
638 while(glGetError() != GL_NO_ERROR);
640 /* Basically the FVF parameter passed to CreateVertexBuffer is no good
641 * It is the FVF set with IWineD3DDevice::SetFVF or the Vertex Declaration set with
642 * IWineD3DDevice::SetVertexDeclaration that decides how the vertices in the buffer
643 * look like. This means that on each DrawPrimitive call the vertex buffer has to be verified
644 * to check if the rhw and color values are in the correct format.
647 GL_EXTCALL(glGenBuffersARB(1, &object->vbo));
648 error = glGetError();
649 if(object->vbo == 0 || error != GL_NO_ERROR) {
650 WARN("Failed to create a VBO with error %d\n", error);
654 GL_EXTCALL(glBindBufferARB(GL_ARRAY_BUFFER_ARB, object->vbo));
655 error = glGetError();
656 if(error != GL_NO_ERROR) {
657 WARN("Failed to bind the VBO, error %d\n", error);
661 /* Transformed vertices are horribly inflexible. If the app specifies an
662 * vertex buffer with transformed vertices in default pool without DYNAMIC
663 * usage assume DYNAMIC usage and print a warning. The app will have to update
664 * the vertices regularily for them to be useful
666 if(((object->fvf & WINED3DFVF_POSITION_MASK) == WINED3DFVF_XYZRHW) &&
667 !(vboUsage & WINED3DUSAGE_DYNAMIC)) {
668 WARN("Application creates a vertex buffer holding transformed vertices which doesn't specify dynamic usage\n");
669 vboUsage |= WINED3DUSAGE_DYNAMIC;
672 /* Don't use static, because dx apps tend to update the buffer
673 * quite often even if they specify 0 usage
675 switch(vboUsage & (D3DUSAGE_WRITEONLY | D3DUSAGE_DYNAMIC) ) {
676 case D3DUSAGE_WRITEONLY | D3DUSAGE_DYNAMIC:
677 TRACE("Gl usage = GL_STREAM_DRAW\n");
678 glUsage = GL_STREAM_DRAW_ARB;
680 case D3DUSAGE_WRITEONLY:
681 TRACE("Gl usage = GL_DYNAMIC_DRAW\n");
682 glUsage = GL_DYNAMIC_DRAW_ARB;
684 case D3DUSAGE_DYNAMIC:
685 TRACE("Gl usage = GL_STREAM_COPY\n");
686 glUsage = GL_STREAM_COPY_ARB;
689 TRACE("Gl usage = GL_DYNAMIC_COPY\n");
690 glUsage = GL_DYNAMIC_COPY_ARB;
694 /* Reserve memory for the buffer. The amount of data won't change
695 * so we are safe with calling glBufferData once with a NULL ptr and
696 * calling glBufferSubData on updates
698 GL_EXTCALL(glBufferDataARB(GL_ARRAY_BUFFER_ARB, object->resource.size, NULL, glUsage));
699 error = glGetError();
700 if(error != GL_NO_ERROR) {
701 WARN("glBufferDataARB failed with error %d\n", error);
709 /* Clean up all vbo init, but continue because we can work without a vbo :-) */
710 FIXME("Failed to create a vertex buffer object. Continuing, but performance issues can occur\n");
711 if(object->vbo) GL_EXTCALL(glDeleteBuffersARB(1, &object->vbo));
713 object->Flags |= VBFLAG_VBOCREATEFAIL;
718 static HRESULT WINAPI IWineD3DDeviceImpl_CreateVertexBuffer(IWineD3DDevice *iface, UINT Size, DWORD Usage,
719 DWORD FVF, WINED3DPOOL Pool, IWineD3DVertexBuffer** ppVertexBuffer, HANDLE *sharedHandle,
721 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
722 IWineD3DVertexBufferImpl *object;
723 WINED3DFORMAT Format = WINED3DFMT_VERTEXDATA; /* Dummy format for now */
724 int dxVersion = ( (IWineD3DImpl *) This->wineD3D)->dxVersion;
726 D3DCREATERESOURCEOBJECTINSTANCE(object, VertexBuffer, WINED3DRTYPE_VERTEXBUFFER, Size)
728 TRACE("(%p) : Size=%d, Usage=%d, FVF=%x, Pool=%d - Memory@%p, Iface@%p\n", This, Size, Usage, FVF, Pool, object->resource.allocatedMemory, object);
729 *ppVertexBuffer = (IWineD3DVertexBuffer *)object;
731 if(Size == 0) return WINED3DERR_INVALIDCALL;
733 if (Pool == WINED3DPOOL_DEFAULT ) { /* Allocate some system memory for now */
734 object->resource.allocatedMemory = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, object->resource.size);
738 /* Observations show that drawStridedSlow is faster on dynamic VBs than converting +
739 * drawStridedFast (half-life 2).
741 * Basically converting the vertices in the buffer is quite expensive, and observations
742 * show that drawStridedSlow is faster than converting + uploading + drawStridedFast.
743 * Therefore do not create a VBO for WINED3DUSAGE_DYNAMIC buffers.
745 * Direct3D7 has another problem: Its vertexbuffer api doesn't offer a way to specify
746 * the range of vertices being locked, so each lock will require the whole buffer to be transformed.
747 * Moreover geometry data in dx7 is quite simple, so drawStridedSlow isn't a big hit. A plus
748 * is that the vertex buffers fvf can be trusted in dx7. So only create non-converted vbos for
750 * There is a IDirect3DVertexBuffer7::Optimize call after which the buffer can't be locked any
751 * more. In this call we can convert dx7 buffers too.
753 conv = ((FVF & WINED3DFVF_POSITION_MASK) == WINED3DFVF_XYZRHW ) || (FVF & (WINED3DFVF_DIFFUSE | WINED3DFVF_SPECULAR));
754 if( GL_SUPPORT(ARB_VERTEX_BUFFER_OBJECT) && Pool != WINED3DPOOL_SYSTEMMEM && !(Usage & WINED3DUSAGE_DYNAMIC) &&
755 (dxVersion > 7 || !conv) ) {
758 /* DX7 buffers can be locked directly into the VBO (no conversion, see above */
759 if(dxVersion == 7 && object->vbo) {
760 HeapFree(GetProcessHeap(), 0, object->resource.allocatedMemory);
761 object->resource.allocatedMemory = NULL;
768 static HRESULT WINAPI IWineD3DDeviceImpl_CreateIndexBuffer(IWineD3DDevice *iface, UINT Length, DWORD Usage,
769 WINED3DFORMAT Format, WINED3DPOOL Pool, IWineD3DIndexBuffer** ppIndexBuffer,
770 HANDLE *sharedHandle, IUnknown *parent) {
771 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
772 IWineD3DIndexBufferImpl *object;
773 TRACE("(%p) Creating index buffer\n", This);
775 /* Allocate the storage for the device */
776 D3DCREATERESOURCEOBJECTINSTANCE(object,IndexBuffer,WINED3DRTYPE_INDEXBUFFER, Length)
779 if (Pool == WINED3DPOOL_DEFAULT ) { /* Allocate some system memory for now */
780 object->resource.allocatedMemory = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,object->resource.size);
783 TRACE("(%p) : Len=%d, Use=%x, Format=(%u,%s), Pool=%d - Memory@%p, Iface@%p\n", This, Length, Usage, Format,
784 debug_d3dformat(Format), Pool, object, object->resource.allocatedMemory);
785 *ppIndexBuffer = (IWineD3DIndexBuffer *) object;
790 static HRESULT WINAPI IWineD3DDeviceImpl_CreateStateBlock(IWineD3DDevice* iface, WINED3DSTATEBLOCKTYPE Type, IWineD3DStateBlock** ppStateBlock, IUnknown *parent) {
792 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
793 IWineD3DStateBlockImpl *object;
797 D3DCREATEOBJECTINSTANCE(object, StateBlock)
798 object->blockType = Type;
800 /* Special case - Used during initialization to produce a placeholder stateblock
801 so other functions called can update a state block */
802 if (Type == WINED3DSBT_INIT) {
803 /* Don't bother increasing the reference count otherwise a device will never
804 be freed due to circular dependencies */
808 temp_result = allocate_shader_constants(object);
809 if (WINED3D_OK != temp_result)
812 /* Otherwise, might as well set the whole state block to the appropriate values */
813 if (This->stateBlock != NULL)
814 stateblock_copy((IWineD3DStateBlock*) object, (IWineD3DStateBlock*) This->stateBlock);
816 memset(object->streamFreq, 1, sizeof(object->streamFreq));
818 /* Reset the ref and type after kludging it */
819 object->wineD3DDevice = This;
821 object->blockType = Type;
823 TRACE("Updating changed flags appropriate for type %d\n", Type);
825 if (Type == WINED3DSBT_ALL) {
827 TRACE("ALL => Pretend everything has changed\n");
828 stateblock_savedstates_set((IWineD3DStateBlock*) object, &object->changed, TRUE);
830 } else if (Type == WINED3DSBT_PIXELSTATE) {
832 TRACE("PIXELSTATE => Pretend all pixel shates have changed\n");
833 stateblock_savedstates_set((IWineD3DStateBlock*) object, &object->changed, FALSE);
835 object->changed.pixelShader = TRUE;
837 /* Pixel Shader Constants */
838 for (i = 0; i < GL_LIMITS(pshader_constantsF); ++i)
839 object->changed.pixelShaderConstantsF[i] = TRUE;
840 for (i = 0; i < MAX_CONST_B; ++i)
841 object->changed.pixelShaderConstantsB[i] = TRUE;
842 for (i = 0; i < MAX_CONST_I; ++i)
843 object->changed.pixelShaderConstantsI[i] = TRUE;
845 for (i = 0; i < NUM_SAVEDPIXELSTATES_R; i++) {
846 object->changed.renderState[SavedPixelStates_R[i]] = TRUE;
848 for (j = 0; j < GL_LIMITS(texture_stages); j++) {
849 for (i = 0; i < NUM_SAVEDPIXELSTATES_T; i++) {
850 object->changed.textureState[j][SavedPixelStates_T[i]] = TRUE;
853 for (j = 0 ; j < 16; j++) {
854 for (i =0; i < NUM_SAVEDPIXELSTATES_S;i++) {
856 object->changed.samplerState[j][SavedPixelStates_S[i]] = TRUE;
860 } else if (Type == WINED3DSBT_VERTEXSTATE) {
862 TRACE("VERTEXSTATE => Pretend all vertex shates have changed\n");
863 stateblock_savedstates_set((IWineD3DStateBlock*) object, &object->changed, FALSE);
865 object->changed.vertexShader = TRUE;
867 /* Vertex Shader Constants */
868 for (i = 0; i < GL_LIMITS(vshader_constantsF); ++i)
869 object->changed.vertexShaderConstantsF[i] = TRUE;
870 for (i = 0; i < MAX_CONST_B; ++i)
871 object->changed.vertexShaderConstantsB[i] = TRUE;
872 for (i = 0; i < MAX_CONST_I; ++i)
873 object->changed.vertexShaderConstantsI[i] = TRUE;
875 for (i = 0; i < NUM_SAVEDVERTEXSTATES_R; i++) {
876 object->changed.renderState[SavedVertexStates_R[i]] = TRUE;
878 for (j = 0; j < GL_LIMITS(texture_stages); j++) {
879 for (i = 0; i < NUM_SAVEDVERTEXSTATES_T; i++) {
880 object->changed.textureState[j][SavedVertexStates_T[i]] = TRUE;
883 for (j = 0 ; j < 16; j++){
884 for (i =0; i < NUM_SAVEDVERTEXSTATES_S;i++) {
885 object->changed.samplerState[j][SavedVertexStates_S[i]] = TRUE;
889 /* Duplicate light chain */
891 PLIGHTINFOEL *src = NULL;
892 PLIGHTINFOEL *dst = NULL;
893 PLIGHTINFOEL *newEl = NULL;
894 src = This->stateBlock->lights;
895 object->lights = NULL;
899 newEl = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(PLIGHTINFOEL));
900 if (newEl == NULL) return WINED3DERR_OUTOFVIDEOMEMORY;
901 memcpy(newEl, src, sizeof(PLIGHTINFOEL));
903 newEl->changed = TRUE;
904 newEl->enabledChanged = TRUE;
906 object->lights = newEl;
917 FIXME("Unrecognized state block type %d\n", Type);
920 TRACE("(%p) returning token (ptr to stateblock) of %p\n", This, object);
925 /* ************************************
927 [in] Render targets are not lockable unless the application specifies TRUE for Lockable. Note that lockable render targets reduce performance on some graphics hardware.
930 [in] Set this flag to TRUE to enable z-buffer discarding, and FALSE otherwise.
932 If this flag is set, the contents of the depth stencil buffer will be invalid after calling either IDirect3DDevice9::Present or IDirect3DDevice9::SetDepthStencilSurface with a different depth surface.
934 ******************************** */
936 static HRESULT WINAPI IWineD3DDeviceImpl_CreateSurface(IWineD3DDevice *iface, UINT Width, UINT Height, WINED3DFORMAT Format, BOOL Lockable, BOOL Discard, UINT Level, IWineD3DSurface **ppSurface,WINED3DRESOURCETYPE Type, DWORD Usage, WINED3DPOOL Pool, WINED3DMULTISAMPLE_TYPE MultiSample ,DWORD MultisampleQuality, HANDLE* pSharedHandle, WINED3DSURFTYPE Impl, IUnknown *parent) {
937 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
938 IWineD3DSurfaceImpl *object; /*NOTE: impl ref allowed since this is a create function */
939 unsigned int pow2Width, pow2Height;
940 unsigned int Size = 1;
941 const PixelFormatDesc *tableEntry = getFormatDescEntry(Format);
942 TRACE("(%p) Create surface\n",This);
944 /** FIXME: Check ranges on the inputs are valid
947 * [in] Quality level. The valid range is between zero and one less than the level
948 * returned by pQualityLevels used by IDirect3D9::CheckDeviceMultiSampleType.
949 * Passing a larger value returns the error WINED3DERR_INVALIDCALL. The MultisampleQuality
950 * values of paired render targets, depth stencil surfaces, and the MultiSample type
952 *******************************/
957 * [in] Set this flag to TRUE to enable z-buffer discarding, and FALSE otherwise.
959 * If this flag is set, the contents of the depth stencil buffer will be
960 * invalid after calling either IDirect3DDevice9::Present or * IDirect3DDevice9::SetDepthStencilSurface
961 * with a different depth surface.
963 *This flag has the same behavior as the constant, D3DPRESENTFLAG_DISCARD_DEPTHSTENCIL, in D3DPRESENTFLAG.
964 ***************************/
966 if(MultisampleQuality < 0) {
967 FIXME("Invalid multisample level %d\n", MultisampleQuality);
968 return WINED3DERR_INVALIDCALL; /* TODO: Check that this is the case! */
971 if(MultisampleQuality > 0) {
972 FIXME("MultisampleQuality set to %d, substituting 0\n", MultisampleQuality);
973 MultisampleQuality=0;
976 /** FIXME: Check that the format is supported
978 *******************************/
980 /* Non-power2 support */
981 if (wined3d_settings.nonpower2_mode == NP2_NATIVE) {
985 /* Find the nearest pow2 match */
986 pow2Width = pow2Height = 1;
987 while (pow2Width < Width) pow2Width <<= 1;
988 while (pow2Height < Height) pow2Height <<= 1;
991 if (pow2Width > Width || pow2Height > Height) {
992 /** TODO: add support for non power two compressed textures (OpenGL 2 provices support for * non-power-two textures gratis) **/
993 if (Format == WINED3DFMT_DXT1 || Format == WINED3DFMT_DXT2 || Format == WINED3DFMT_DXT3
994 || Format == WINED3DFMT_DXT4 || Format == WINED3DFMT_DXT5) {
995 FIXME("(%p) Compressed non-power-two textures are not supported w(%d) h(%d)\n",
996 This, Width, Height);
997 return WINED3DERR_NOTAVAILABLE;
1001 /** DXTn mipmaps use the same number of 'levels' down to eg. 8x1, but since
1002 * it is based around 4x4 pixel blocks it requires padding, so allocate enough
1004 *********************************/
1005 if (WINED3DFMT_UNKNOWN == Format) {
1007 } else if (Format == WINED3DFMT_DXT1) {
1008 /* DXT1 is half byte per pixel */
1009 Size = ((max(pow2Width,4) * tableEntry->bpp) * max(pow2Height,4)) >> 1;
1011 } else if (Format == WINED3DFMT_DXT2 || Format == WINED3DFMT_DXT3 ||
1012 Format == WINED3DFMT_DXT4 || Format == WINED3DFMT_DXT5) {
1013 Size = ((max(pow2Width,4) * tableEntry->bpp) * max(pow2Height,4));
1015 /* The pitch is a multiple of 4 bytes */
1016 Size = ((pow2Width * tableEntry->bpp) + SURFACE_ALIGNMENT - 1) & ~(SURFACE_ALIGNMENT - 1);
1020 /** Create and initialise the surface resource **/
1021 D3DCREATERESOURCEOBJECTINSTANCE(object,Surface,WINED3DRTYPE_SURFACE, Size)
1022 /* "Standalone" surface */
1023 IWineD3DSurface_SetContainer((IWineD3DSurface *)object, NULL);
1025 object->currentDesc.Width = Width;
1026 object->currentDesc.Height = Height;
1027 object->currentDesc.MultiSampleType = MultiSample;
1028 object->currentDesc.MultiSampleQuality = MultisampleQuality;
1030 /* Setup some glformat defaults */
1031 object->glDescription.glFormat = tableEntry->glFormat;
1032 object->glDescription.glFormatInternal = tableEntry->glInternal;
1033 object->glDescription.glType = tableEntry->glType;
1035 object->glDescription.textureName = 0;
1036 object->glDescription.level = Level;
1037 object->glDescription.target = GL_TEXTURE_2D;
1040 object->pow2Width = pow2Width;
1041 object->pow2Height = pow2Height;
1044 object->Flags = 0; /* We start without flags set */
1045 object->Flags |= (pow2Width != Width || pow2Height != Height) ? SFLAG_NONPOW2 : 0;
1046 object->Flags |= Discard ? SFLAG_DISCARD : 0;
1047 object->Flags |= (WINED3DFMT_D16_LOCKABLE == Format) ? SFLAG_LOCKABLE : 0;
1048 object->Flags |= Lockable ? SFLAG_LOCKABLE : 0;
1051 if (WINED3DFMT_UNKNOWN != Format) {
1052 object->bytesPerPixel = tableEntry->bpp;
1053 object->pow2Size = ((pow2Width * object->bytesPerPixel) + SURFACE_ALIGNMENT - 1) & ~(SURFACE_ALIGNMENT - 1);
1054 object->pow2Size *= pow2Height;
1056 object->bytesPerPixel = 0;
1057 object->pow2Size = 0;
1060 /** TODO: change this into a texture transform matrix so that it's processed in hardware **/
1062 TRACE("Pool %d %d %d %d\n",Pool, WINED3DPOOL_DEFAULT, WINED3DPOOL_MANAGED, WINED3DPOOL_SYSTEMMEM);
1064 /** Quick lockable sanity check TODO: remove this after surfaces, usage and lockability have been debugged properly
1065 * this function is too deep to need to care about things like this.
1066 * Levels need to be checked too, and possibly Type since they all affect what can be done.
1067 * ****************************************/
1069 case WINED3DPOOL_SCRATCH:
1071 FIXME("Create surface called with a pool of SCRATCH and a Lockable of FALSE \
1072 which are mutually exclusive, setting lockable to true\n");
1075 case WINED3DPOOL_SYSTEMMEM:
1076 if(!Lockable) FIXME("Create surface called with a pool of SYSTEMMEM and a Lockable of FALSE, \
1077 this is acceptable but unexpected (I can't know how the surface can be usable!)\n");
1078 case WINED3DPOOL_MANAGED:
1079 if(Usage == WINED3DUSAGE_DYNAMIC) FIXME("Create surface called with a pool of MANAGED and a \
1080 Usage of DYNAMIC which are mutually exclusive, not doing \
1081 anything just telling you.\n");
1083 case WINED3DPOOL_DEFAULT: /*TODO: Create offscreen plain can cause this check to fail..., find out if it should */
1084 if(!(Usage & WINED3DUSAGE_DYNAMIC) && !(Usage & WINED3DUSAGE_RENDERTARGET)
1085 && !(Usage && WINED3DUSAGE_DEPTHSTENCIL ) && Lockable)
1086 WARN("Creating a surface with a POOL of DEFAULT with Lockable true, that doesn't specify DYNAMIC usage.\n");
1089 FIXME("(%p) Unknown pool %d\n", This, Pool);
1093 if (Usage & WINED3DUSAGE_RENDERTARGET && Pool != WINED3DPOOL_DEFAULT) {
1094 FIXME("Trying to create a render target that isn't in the default pool\n");
1097 /* mark the texture as dirty so that it gets loaded first time around*/
1098 IWineD3DSurface_AddDirtyRect(*ppSurface, NULL);
1099 TRACE("(%p) : w(%d) h(%d) fmt(%d,%s) lockable(%d) surf@%p, surfmem@%p, %d bytes\n",
1100 This, Width, Height, Format, debug_d3dformat(Format),
1101 (WINED3DFMT_D16_LOCKABLE == Format), *ppSurface, object->resource.allocatedMemory, object->resource.size);
1103 /* Store the DirectDraw primary surface. This is the first rendertarget surface created */
1104 if( (Usage & WINED3DUSAGE_RENDERTARGET) && (!This->ddraw_primary) )
1105 This->ddraw_primary = (IWineD3DSurface *) object;
1107 /* Look at the implementation and set the correct Vtable */
1109 case SURFACE_OPENGL:
1110 /* Nothing to do, it's set already */
1114 object->lpVtbl = &IWineGDISurface_Vtbl;
1118 /* To be sure to catch this */
1119 ERR("Unknown requested surface implementation %d!\n", Impl);
1120 IWineD3DSurface_Release((IWineD3DSurface *) object);
1121 return WINED3DERR_INVALIDCALL;
1124 /* Call the private setup routine */
1125 return IWineD3DSurface_PrivateSetup( (IWineD3DSurface *) object );
1129 static HRESULT WINAPI IWineD3DDeviceImpl_CreateTexture(IWineD3DDevice *iface, UINT Width, UINT Height, UINT Levels,
1130 DWORD Usage, WINED3DFORMAT Format, WINED3DPOOL Pool,
1131 IWineD3DTexture** ppTexture, HANDLE* pSharedHandle, IUnknown *parent,
1132 D3DCB_CREATESURFACEFN D3DCB_CreateSurface) {
1134 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
1135 IWineD3DTextureImpl *object;
1140 unsigned int pow2Width;
1141 unsigned int pow2Height;
1144 TRACE("(%p) : Width %d, Height %d, Levels %d, Usage %#x\n", This, Width, Height, Levels, Usage);
1145 TRACE("Format %#x (%s), Pool %#x, ppTexture %p, pSharedHandle %p, parent %p\n",
1146 Format, debug_d3dformat(Format), Pool, ppTexture, pSharedHandle, parent);
1148 /* TODO: It should only be possible to create textures for formats
1149 that are reported as supported */
1150 if (WINED3DFMT_UNKNOWN >= Format) {
1151 WARN("(%p) : Texture cannot be created with a format of WINED3DFMT_UNKNOWN\n", This);
1152 return WINED3DERR_INVALIDCALL;
1155 D3DCREATERESOURCEOBJECTINSTANCE(object, Texture, WINED3DRTYPE_TEXTURE, 0);
1156 D3DINITIALIZEBASETEXTURE(object->baseTexture);
1157 object->width = Width;
1158 object->height = Height;
1160 /** Non-power2 support **/
1161 if (wined3d_settings.nonpower2_mode == NP2_NATIVE) {
1163 pow2Height = Height;
1165 /* Find the nearest pow2 match */
1166 pow2Width = pow2Height = 1;
1167 while (pow2Width < Width) pow2Width <<= 1;
1168 while (pow2Height < Height) pow2Height <<= 1;
1171 /** FIXME: add support for real non-power-two if it's provided by the video card **/
1172 /* Precalculated scaling for 'faked' non power of two texture coords */
1173 object->pow2scalingFactorX = (((float)Width) / ((float)pow2Width));
1174 object->pow2scalingFactorY = (((float)Height) / ((float)pow2Height));
1175 TRACE(" xf(%f) yf(%f)\n", object->pow2scalingFactorX, object->pow2scalingFactorY);
1177 /* Calculate levels for mip mapping */
1179 TRACE("calculating levels %d\n", object->baseTexture.levels);
1180 object->baseTexture.levels++;
1183 while (tmpW > 1 || tmpH > 1) {
1184 tmpW = max(1, tmpW >> 1);
1185 tmpH = max(1, tmpH >> 1);
1186 object->baseTexture.levels++;
1188 TRACE("Calculated levels = %d\n", object->baseTexture.levels);
1191 /* Generate all the surfaces */
1194 for (i = 0; i < object->baseTexture.levels; i++)
1196 /* use the callback to create the texture surface */
1197 hr = D3DCB_CreateSurface(This->parent, tmpW, tmpH, Format, Usage, Pool, i, &object->surfaces[i],NULL);
1198 if (hr!= WINED3D_OK || ( (IWineD3DSurfaceImpl *) object->surfaces[i])->Flags & SFLAG_OVERSIZE) {
1199 FIXME("Failed to create surface %p\n", object);
1201 object->surfaces[i] = NULL;
1202 IWineD3DTexture_Release((IWineD3DTexture *)object);
1208 IWineD3DSurface_SetContainer(object->surfaces[i], (IWineD3DBase *)object);
1209 TRACE("Created surface level %d @ %p\n", i, object->surfaces[i]);
1210 /* calculate the next mipmap level */
1211 tmpW = max(1, tmpW >> 1);
1212 tmpH = max(1, tmpH >> 1);
1215 TRACE("(%p) : Created texture %p\n", This, object);
1219 static HRESULT WINAPI IWineD3DDeviceImpl_CreateVolumeTexture(IWineD3DDevice *iface,
1220 UINT Width, UINT Height, UINT Depth,
1221 UINT Levels, DWORD Usage,
1222 WINED3DFORMAT Format, WINED3DPOOL Pool,
1223 IWineD3DVolumeTexture **ppVolumeTexture,
1224 HANDLE *pSharedHandle, IUnknown *parent,
1225 D3DCB_CREATEVOLUMEFN D3DCB_CreateVolume) {
1227 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
1228 IWineD3DVolumeTextureImpl *object;
1234 /* TODO: It should only be possible to create textures for formats
1235 that are reported as supported */
1236 if (WINED3DFMT_UNKNOWN >= Format) {
1237 WARN("(%p) : Texture cannot be created with a format of WINED3DFMT_UNKNOWN\n", This);
1238 return WINED3DERR_INVALIDCALL;
1241 D3DCREATERESOURCEOBJECTINSTANCE(object, VolumeTexture, WINED3DRTYPE_VOLUMETEXTURE, 0);
1242 D3DINITIALIZEBASETEXTURE(object->baseTexture);
1244 TRACE("(%p) : W(%d) H(%d) D(%d), Lvl(%d) Usage(%d), Fmt(%u,%s), Pool(%s)\n", This, Width, Height,
1245 Depth, Levels, Usage, Format, debug_d3dformat(Format), debug_d3dpool(Pool));
1247 object->width = Width;
1248 object->height = Height;
1249 object->depth = Depth;
1251 /* Calculate levels for mip mapping */
1253 object->baseTexture.levels++;
1257 while (tmpW > 1 || tmpH > 1 || tmpD > 1) {
1258 tmpW = max(1, tmpW >> 1);
1259 tmpH = max(1, tmpH >> 1);
1260 tmpD = max(1, tmpD >> 1);
1261 object->baseTexture.levels++;
1263 TRACE("Calculated levels = %d\n", object->baseTexture.levels);
1266 /* Generate all the surfaces */
1271 for (i = 0; i < object->baseTexture.levels; i++)
1273 /* Create the volume */
1274 D3DCB_CreateVolume(This->parent, Width, Height, Depth, Format, Pool, Usage,
1275 (IWineD3DVolume **)&object->volumes[i], pSharedHandle);
1277 /* Set its container to this object */
1278 IWineD3DVolume_SetContainer(object->volumes[i], (IWineD3DBase *)object);
1280 /* calcualte the next mipmap level */
1281 tmpW = max(1, tmpW >> 1);
1282 tmpH = max(1, tmpH >> 1);
1283 tmpD = max(1, tmpD >> 1);
1286 *ppVolumeTexture = (IWineD3DVolumeTexture *) object;
1287 TRACE("(%p) : Created volume texture %p\n", This, object);
1291 static HRESULT WINAPI IWineD3DDeviceImpl_CreateVolume(IWineD3DDevice *iface,
1292 UINT Width, UINT Height, UINT Depth,
1294 WINED3DFORMAT Format, WINED3DPOOL Pool,
1295 IWineD3DVolume** ppVolume,
1296 HANDLE* pSharedHandle, IUnknown *parent) {
1298 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
1299 IWineD3DVolumeImpl *object; /** NOTE: impl ref allowed since this is a create function **/
1300 const PixelFormatDesc *formatDesc = getFormatDescEntry(Format);
1302 D3DCREATERESOURCEOBJECTINSTANCE(object, Volume, WINED3DRTYPE_VOLUME, ((Width * formatDesc->bpp) * Height * Depth))
1304 TRACE("(%p) : W(%d) H(%d) D(%d), Usage(%d), Fmt(%u,%s), Pool(%s)\n", This, Width, Height,
1305 Depth, Usage, Format, debug_d3dformat(Format), debug_d3dpool(Pool));
1307 object->currentDesc.Width = Width;
1308 object->currentDesc.Height = Height;
1309 object->currentDesc.Depth = Depth;
1310 object->bytesPerPixel = formatDesc->bpp;
1312 /** Note: Volume textures cannot be dxtn, hence no need to check here **/
1313 object->lockable = TRUE;
1314 object->locked = FALSE;
1315 memset(&object->lockedBox, 0, sizeof(WINED3DBOX));
1316 object->dirty = TRUE;
1318 return IWineD3DVolume_AddDirtyBox((IWineD3DVolume *) object, NULL);
1321 static HRESULT WINAPI IWineD3DDeviceImpl_CreateCubeTexture(IWineD3DDevice *iface, UINT EdgeLength,
1322 UINT Levels, DWORD Usage,
1323 WINED3DFORMAT Format, WINED3DPOOL Pool,
1324 IWineD3DCubeTexture **ppCubeTexture,
1325 HANDLE *pSharedHandle, IUnknown *parent,
1326 D3DCB_CREATESURFACEFN D3DCB_CreateSurface) {
1328 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
1329 IWineD3DCubeTextureImpl *object; /** NOTE: impl ref allowed since this is a create function **/
1333 unsigned int pow2EdgeLength = EdgeLength;
1335 /* TODO: It should only be possible to create textures for formats
1336 that are reported as supported */
1337 if (WINED3DFMT_UNKNOWN >= Format) {
1338 WARN("(%p) : Texture cannot be created with a format of WINED3DFMT_UNKNOWN\n", This);
1339 return WINED3DERR_INVALIDCALL;
1342 D3DCREATERESOURCEOBJECTINSTANCE(object, CubeTexture, WINED3DRTYPE_CUBETEXTURE, 0);
1343 D3DINITIALIZEBASETEXTURE(object->baseTexture);
1345 TRACE("(%p) Create Cube Texture\n", This);
1347 /** Non-power2 support **/
1349 /* Find the nearest pow2 match */
1351 while (pow2EdgeLength < EdgeLength) pow2EdgeLength <<= 1;
1353 object->edgeLength = EdgeLength;
1354 /* TODO: support for native non-power 2 */
1355 /* Precalculated scaling for 'faked' non power of two texture coords */
1356 object->pow2scalingFactor = ((float)EdgeLength) / ((float)pow2EdgeLength);
1358 /* Calculate levels for mip mapping */
1360 object->baseTexture.levels++;
1363 tmpW = max(1, tmpW >> 1);
1364 object->baseTexture.levels++;
1366 TRACE("Calculated levels = %d\n", object->baseTexture.levels);
1369 /* Generate all the surfaces */
1371 for (i = 0; i < object->baseTexture.levels; i++) {
1373 /* Create the 6 faces */
1374 for (j = 0; j < 6; j++) {
1376 hr=D3DCB_CreateSurface(This->parent, tmpW, tmpW, Format, Usage, Pool,
1377 i /* Level */, &object->surfaces[j][i],pSharedHandle);
1379 if(hr!= WINED3D_OK) {
1383 for (l = 0; l < j; l++) {
1384 IWineD3DSurface_Release(object->surfaces[j][i]);
1386 for (k = 0; k < i; k++) {
1387 for (l = 0; l < 6; l++) {
1388 IWineD3DSurface_Release(object->surfaces[l][j]);
1392 FIXME("(%p) Failed to create surface\n",object);
1393 HeapFree(GetProcessHeap(),0,object);
1394 *ppCubeTexture = NULL;
1397 IWineD3DSurface_SetContainer(object->surfaces[j][i], (IWineD3DBase *)object);
1398 TRACE("Created surface level %d @ %p,\n", i, object->surfaces[j][i]);
1400 tmpW = max(1, tmpW >> 1);
1403 TRACE("(%p) : Created Cube Texture %p\n", This, object);
1404 *ppCubeTexture = (IWineD3DCubeTexture *) object;
1408 static HRESULT WINAPI IWineD3DDeviceImpl_CreateQuery(IWineD3DDevice *iface, WINED3DQUERYTYPE Type, IWineD3DQuery **ppQuery, IUnknown* parent) {
1409 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
1410 IWineD3DQueryImpl *object; /*NOTE: impl ref allowed since this is a create function */
1412 if (NULL == ppQuery) {
1413 /* Just a check to see if we support this type of query */
1414 HRESULT hr = WINED3DERR_NOTAVAILABLE;
1416 case WINED3DQUERYTYPE_OCCLUSION:
1417 TRACE("(%p) occlusion query\n", This);
1418 if (GL_SUPPORT(ARB_OCCLUSION_QUERY))
1421 WARN("Unsupported in local OpenGL implementation: ARB_OCCLUSION_QUERY/NV_OCCLUSION_QUERY\n");
1423 case WINED3DQUERYTYPE_VCACHE:
1424 case WINED3DQUERYTYPE_RESOURCEMANAGER:
1425 case WINED3DQUERYTYPE_VERTEXSTATS:
1426 case WINED3DQUERYTYPE_EVENT:
1427 case WINED3DQUERYTYPE_TIMESTAMP:
1428 case WINED3DQUERYTYPE_TIMESTAMPDISJOINT:
1429 case WINED3DQUERYTYPE_TIMESTAMPFREQ:
1430 case WINED3DQUERYTYPE_PIPELINETIMINGS:
1431 case WINED3DQUERYTYPE_INTERFACETIMINGS:
1432 case WINED3DQUERYTYPE_VERTEXTIMINGS:
1433 case WINED3DQUERYTYPE_PIXELTIMINGS:
1434 case WINED3DQUERYTYPE_BANDWIDTHTIMINGS:
1435 case WINED3DQUERYTYPE_CACHEUTILIZATION:
1437 FIXME("(%p) Unhandled query type %d\n", This, Type);
1442 D3DCREATEOBJECTINSTANCE(object, Query)
1443 object->type = Type;
1444 /* allocated the 'extended' data based on the type of query requested */
1446 case WINED3DQUERYTYPE_OCCLUSION:
1447 if(GL_SUPPORT(ARB_OCCLUSION_QUERY)) {
1448 TRACE("(%p) Allocating data for an occlusion query\n", This);
1449 object->extendedData = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(WineQueryOcclusionData));
1450 GL_EXTCALL(glGenQueriesARB(1, &((WineQueryOcclusionData *)(object->extendedData))->queryId));
1453 case WINED3DQUERYTYPE_VCACHE:
1454 case WINED3DQUERYTYPE_RESOURCEMANAGER:
1455 case WINED3DQUERYTYPE_VERTEXSTATS:
1456 case WINED3DQUERYTYPE_EVENT:
1457 case WINED3DQUERYTYPE_TIMESTAMP:
1458 case WINED3DQUERYTYPE_TIMESTAMPDISJOINT:
1459 case WINED3DQUERYTYPE_TIMESTAMPFREQ:
1460 case WINED3DQUERYTYPE_PIPELINETIMINGS:
1461 case WINED3DQUERYTYPE_INTERFACETIMINGS:
1462 case WINED3DQUERYTYPE_VERTEXTIMINGS:
1463 case WINED3DQUERYTYPE_PIXELTIMINGS:
1464 case WINED3DQUERYTYPE_BANDWIDTHTIMINGS:
1465 case WINED3DQUERYTYPE_CACHEUTILIZATION:
1467 object->extendedData = 0;
1468 FIXME("(%p) Unhandled query type %d\n",This , Type);
1470 TRACE("(%p) : Created Query %p\n", This, object);
1474 /* example at http://www.fairyengine.com/articles/dxmultiviews.htm */
1475 static HRESULT WINAPI IWineD3DDeviceImpl_CreateAdditionalSwapChain(IWineD3DDevice* iface, WINED3DPRESENT_PARAMETERS* pPresentationParameters, IWineD3DSwapChain** ppSwapChain,
1477 D3DCB_CREATERENDERTARGETFN D3DCB_CreateRenderTarget,
1478 D3DCB_CREATEDEPTHSTENCILSURFACEFN D3DCB_CreateDepthStencil) {
1479 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
1482 IWineD3DSwapChainImpl *object; /** NOTE: impl ref allowed since this is a create function **/
1484 XVisualInfo template;
1485 GLXContext oldContext;
1486 Drawable oldDrawable;
1487 HRESULT hr = WINED3D_OK;
1489 TRACE("(%p) : Created Aditional Swap Chain\n", This);
1491 /** FIXME: Test under windows to find out what the life cycle of a swap chain is,
1492 * does a device hold a reference to a swap chain giving them a lifetime of the device
1493 * or does the swap chain notify the device of its destruction.
1494 *******************************/
1496 /* Check the params */
1497 if(*pPresentationParameters->BackBufferCount > D3DPRESENT_BACK_BUFFER_MAX) {
1498 ERR("App requested %d back buffers, this is not supported for now\n", *pPresentationParameters->BackBufferCount);
1499 return WINED3DERR_INVALIDCALL;
1500 } else if (*pPresentationParameters->BackBufferCount > 1) {
1501 FIXME("The app requests more than one back buffer, this can't be supported properly. Please configure the application to use double buffering(=1 back buffer) if possible\n");
1504 D3DCREATEOBJECTINSTANCE(object, SwapChain)
1506 /*********************
1507 * Lookup the window Handle and the relating X window handle
1508 ********************/
1510 /* Setup hwnd we are using, plus which display this equates to */
1511 object->win_handle = *(pPresentationParameters->hDeviceWindow);
1512 if (!object->win_handle) {
1513 object->win_handle = This->createParms.hFocusWindow;
1516 object->win_handle = GetAncestor(object->win_handle, GA_ROOT);
1517 if ( !( object->win = (Window)GetPropA(object->win_handle, "__wine_x11_whole_window") ) ) {
1518 ERR("Can't get drawable (window), HWND:%p doesn't have the property __wine_x11_whole_window\n", object->win_handle);
1519 return WINED3DERR_NOTAVAILABLE;
1521 hDc = GetDC(object->win_handle);
1522 object->display = get_display(hDc);
1523 ReleaseDC(object->win_handle, hDc);
1524 TRACE("Using a display of %p %p\n", object->display, hDc);
1526 if (NULL == object->display || NULL == hDc) {
1527 WARN("Failed to get a display and HDc for Window %p\n", object->win_handle);
1528 return WINED3DERR_NOTAVAILABLE;
1531 if (object->win == 0) {
1532 WARN("Failed to get a valid XVisuial ID for the window %p\n", object->win_handle);
1533 return WINED3DERR_NOTAVAILABLE;
1536 * Create an opengl context for the display visual
1537 * NOTE: the visual is chosen as the window is created and the glcontext cannot
1538 * use different properties after that point in time. FIXME: How to handle when requested format
1539 * doesn't match actual visual? Cannot choose one here - code removed as it ONLY works if the one
1540 * it chooses is identical to the one already being used!
1541 **********************************/
1543 /** FIXME: Handle stencil appropriately via EnableAutoDepthStencil / AutoDepthStencilFormat **/
1546 /* Create a new context for this swapchain */
1547 template.visualid = (VisualID)GetPropA(GetDesktopWindow(), "__wine_x11_visual_id");
1548 /* TODO: change this to find a similar visual, but one with a stencil/zbuffer buffer that matches the request
1549 (or the best possible if none is requested) */
1550 TRACE("Found x visual ID : %ld\n", template.visualid);
1552 object->visInfo = XGetVisualInfo(object->display, VisualIDMask, &template, &num);
1553 if (NULL == object->visInfo) {
1554 ERR("cannot really get XVisual\n");
1556 return WINED3DERR_NOTAVAILABLE;
1559 /* Write out some debug info about the visual/s */
1560 TRACE("Using x visual ID : %ld\n", template.visualid);
1561 TRACE(" visual info: %p\n", object->visInfo);
1562 TRACE(" num items : %d\n", num);
1563 for (n = 0;n < num; n++) {
1564 TRACE("=====item=====: %d\n", n + 1);
1565 TRACE(" visualid : %ld\n", object->visInfo[n].visualid);
1566 TRACE(" screen : %d\n", object->visInfo[n].screen);
1567 TRACE(" depth : %u\n", object->visInfo[n].depth);
1568 TRACE(" class : %d\n", object->visInfo[n].class);
1569 TRACE(" red_mask : %ld\n", object->visInfo[n].red_mask);
1570 TRACE(" green_mask : %ld\n", object->visInfo[n].green_mask);
1571 TRACE(" blue_mask : %ld\n", object->visInfo[n].blue_mask);
1572 TRACE(" colormap_size : %d\n", object->visInfo[n].colormap_size);
1573 TRACE(" bits_per_rgb : %d\n", object->visInfo[n].bits_per_rgb);
1574 /* log some extra glx info */
1575 glXGetConfig(object->display, object->visInfo, GLX_AUX_BUFFERS, &value);
1576 TRACE(" gl_aux_buffers : %d\n", value);
1577 glXGetConfig(object->display, object->visInfo, GLX_BUFFER_SIZE ,&value);
1578 TRACE(" gl_buffer_size : %d\n", value);
1579 glXGetConfig(object->display, object->visInfo, GLX_RED_SIZE, &value);
1580 TRACE(" gl_red_size : %d\n", value);
1581 glXGetConfig(object->display, object->visInfo, GLX_GREEN_SIZE, &value);
1582 TRACE(" gl_green_size : %d\n", value);
1583 glXGetConfig(object->display, object->visInfo, GLX_BLUE_SIZE, &value);
1584 TRACE(" gl_blue_size : %d\n", value);
1585 glXGetConfig(object->display, object->visInfo, GLX_ALPHA_SIZE, &value);
1586 TRACE(" gl_alpha_size : %d\n", value);
1587 glXGetConfig(object->display, object->visInfo, GLX_DEPTH_SIZE ,&value);
1588 TRACE(" gl_depth_size : %d\n", value);
1589 glXGetConfig(object->display, object->visInfo, GLX_STENCIL_SIZE, &value);
1590 TRACE(" gl_stencil_size : %d\n", value);
1592 /* Now choose a similar visual ID*/
1594 #ifdef USE_CONTEXT_MANAGER
1596 /** TODO: use a context mamager **/
1600 IWineD3DSwapChain *implSwapChain;
1601 if (WINED3D_OK != IWineD3DDevice_GetSwapChain(iface, 0, &implSwapChain)) {
1602 /* The first time around we create the context that is shared with all other swapchains and render targets */
1603 object->glCtx = glXCreateContext(object->display, object->visInfo, NULL, GL_TRUE);
1604 TRACE("Creating implicit context for vis %p, hwnd %p\n", object->display, object->visInfo);
1607 TRACE("Creating context for vis %p, hwnd %p\n", object->display, object->visInfo);
1608 /* TODO: don't use Impl structures outside of create functions! (a context manager will replace the ->glCtx) */
1609 /* and create a new context with the implicit swapchains context as the shared context */
1610 object->glCtx = glXCreateContext(object->display, object->visInfo, ((IWineD3DSwapChainImpl *)implSwapChain)->glCtx, GL_TRUE);
1611 IWineD3DSwapChain_Release(implSwapChain);
1616 XFree(object->visInfo);
1617 object->visInfo = NULL;
1621 if (!object->glCtx) {
1622 ERR("Failed to create GLX context\n");
1623 return WINED3DERR_NOTAVAILABLE;
1625 TRACE("Context created (HWND=%p, glContext=%p, Window=%ld, VisInfo=%p)\n",
1626 object->win_handle, object->glCtx, object->win, object->visInfo);
1629 /*********************
1630 * Windowed / Fullscreen
1631 *******************/
1634 * TODO: MSDN says that we are only allowed one fullscreen swapchain per device,
1635 * so we should really check to see if there is a fullscreen swapchain already
1636 * I think Windows and X have different ideas about fullscreen, does a single head count as full screen?
1637 **************************************/
1639 if (!*(pPresentationParameters->Windowed)) {
1645 /* Get info on the current display setup */
1646 hdc = CreateDCA("DISPLAY", NULL, NULL, NULL);
1647 bpp = GetDeviceCaps(hdc, BITSPIXEL);
1650 /* Change the display settings */
1651 memset(&devmode, 0, sizeof(DEVMODEW));
1652 devmode.dmFields = DM_BITSPERPEL | DM_PELSWIDTH | DM_PELSHEIGHT;
1653 devmode.dmBitsPerPel = (bpp >= 24) ? 32 : bpp; /* Stupid XVidMode cannot change bpp */
1654 devmode.dmPelsWidth = *(pPresentationParameters->BackBufferWidth);
1655 devmode.dmPelsHeight = *(pPresentationParameters->BackBufferHeight);
1656 MultiByteToWideChar(CP_ACP, 0, "Gamers CG", -1, devmode.dmDeviceName, CCHDEVICENAME);
1657 ChangeDisplaySettingsExW(devmode.dmDeviceName, &devmode, object->win_handle, CDS_FULLSCREEN, NULL);
1659 /* Make popup window */
1660 SetWindowLongA(object->win_handle, GWL_STYLE, WS_POPUP);
1661 SetWindowPos(object->win_handle, HWND_TOP, 0, 0,
1662 *(pPresentationParameters->BackBufferWidth),
1663 *(pPresentationParameters->BackBufferHeight), SWP_SHOWWINDOW | SWP_FRAMECHANGED);
1665 /* For GetDisplayMode */
1666 This->ddraw_width = devmode.dmPelsWidth;
1667 This->ddraw_height = devmode.dmPelsHeight;
1668 This->ddraw_format = *(pPresentationParameters->BackBufferFormat);
1672 /** MSDN: If Windowed is TRUE and either of the BackBufferWidth/Height values is zero,
1673 * then the corresponding dimension of the client area of the hDeviceWindow
1674 * (or the focus window, if hDeviceWindow is NULL) is taken.
1675 **********************/
1677 if (*(pPresentationParameters->Windowed) &&
1678 ((*(pPresentationParameters->BackBufferWidth) == 0) ||
1679 (*(pPresentationParameters->BackBufferHeight) == 0))) {
1682 GetClientRect(object->win_handle, &Rect);
1684 if (*(pPresentationParameters->BackBufferWidth) == 0) {
1685 *(pPresentationParameters->BackBufferWidth) = Rect.right;
1686 TRACE("Updating width to %d\n", *(pPresentationParameters->BackBufferWidth));
1688 if (*(pPresentationParameters->BackBufferHeight) == 0) {
1689 *(pPresentationParameters->BackBufferHeight) = Rect.bottom;
1690 TRACE("Updating height to %d\n", *(pPresentationParameters->BackBufferHeight));
1694 /*********************
1695 * finish off parameter initialization
1696 *******************/
1698 /* Put the correct figures in the presentation parameters */
1699 TRACE("Copying across presentation parameters\n");
1700 object->presentParms.BackBufferWidth = *(pPresentationParameters->BackBufferWidth);
1701 object->presentParms.BackBufferHeight = *(pPresentationParameters->BackBufferHeight);
1702 object->presentParms.BackBufferFormat = *(pPresentationParameters->BackBufferFormat);
1703 object->presentParms.BackBufferCount = *(pPresentationParameters->BackBufferCount);
1704 object->presentParms.MultiSampleType = *(pPresentationParameters->MultiSampleType);
1705 object->presentParms.MultiSampleQuality = NULL == pPresentationParameters->MultiSampleQuality ? 0 : *(pPresentationParameters->MultiSampleQuality);
1706 object->presentParms.SwapEffect = *(pPresentationParameters->SwapEffect);
1707 object->presentParms.hDeviceWindow = *(pPresentationParameters->hDeviceWindow);
1708 object->presentParms.Windowed = *(pPresentationParameters->Windowed);
1709 object->presentParms.EnableAutoDepthStencil = *(pPresentationParameters->EnableAutoDepthStencil);
1710 object->presentParms.AutoDepthStencilFormat = *(pPresentationParameters->AutoDepthStencilFormat);
1711 object->presentParms.Flags = *(pPresentationParameters->Flags);
1712 object->presentParms.FullScreen_RefreshRateInHz = *(pPresentationParameters->FullScreen_RefreshRateInHz);
1713 object->presentParms.PresentationInterval = *(pPresentationParameters->PresentationInterval);
1716 /*********************
1717 * Create the back, front and stencil buffers
1718 *******************/
1720 TRACE("calling rendertarget CB\n");
1721 hr = D3DCB_CreateRenderTarget((IUnknown *) This->parent,
1722 object->presentParms.BackBufferWidth,
1723 object->presentParms.BackBufferHeight,
1724 object->presentParms.BackBufferFormat,
1725 object->presentParms.MultiSampleType,
1726 object->presentParms.MultiSampleQuality,
1727 TRUE /* Lockable */,
1728 &object->frontBuffer,
1729 NULL /* pShared (always null)*/);
1730 if (object->frontBuffer != NULL)
1731 IWineD3DSurface_SetContainer(object->frontBuffer, (IWineD3DBase *)object);
1733 if(object->presentParms.BackBufferCount > 0) {
1736 object->backBuffer = HeapAlloc(GetProcessHeap(), 0, sizeof(IWineD3DSurface *) * object->presentParms.BackBufferCount);
1737 if(!object->backBuffer) {
1738 ERR("Out of memory\n");
1740 if (object->frontBuffer) {
1741 IUnknown *bufferParent;
1742 IWineD3DSurface_GetParent(object->frontBuffer, &bufferParent);
1743 IUnknown_Release(bufferParent); /* once for the get parent */
1744 if (IUnknown_Release(bufferParent) > 0) {
1745 FIXME("(%p) Something's still holding the front buffer\n",This);
1748 HeapFree(GetProcessHeap(), 0, object);
1749 return E_OUTOFMEMORY;
1752 for(i = 0; i < object->presentParms.BackBufferCount; i++) {
1753 TRACE("calling rendertarget CB\n");
1754 hr = D3DCB_CreateRenderTarget((IUnknown *) This->parent,
1755 object->presentParms.BackBufferWidth,
1756 object->presentParms.BackBufferHeight,
1757 object->presentParms.BackBufferFormat,
1758 object->presentParms.MultiSampleType,
1759 object->presentParms.MultiSampleQuality,
1760 TRUE /* Lockable */,
1761 &object->backBuffer[i],
1762 NULL /* pShared (always null)*/);
1763 if(hr == WINED3D_OK && object->backBuffer[i]) {
1764 IWineD3DSurface_SetContainer(object->backBuffer[i], (IWineD3DBase *)object);
1770 object->backBuffer = NULL;
1773 if (object->backBuffer != NULL) {
1775 glDrawBuffer(GL_BACK);
1776 checkGLcall("glDrawBuffer(GL_BACK)");
1779 /* Single buffering - draw to front buffer */
1781 glDrawBuffer(GL_FRONT);
1782 checkGLcall("glDrawBuffer(GL_FRONT)");
1786 /* Under directX swapchains share the depth stencil, so only create one depth-stencil */
1787 if (*(pPresentationParameters->EnableAutoDepthStencil) && hr == WINED3D_OK) {
1788 TRACE("Creating depth stencil buffer\n");
1789 if (This->depthStencilBuffer == NULL ) {
1790 hr = D3DCB_CreateDepthStencil((IUnknown *) This->parent,
1791 object->presentParms.BackBufferWidth,
1792 object->presentParms.BackBufferHeight,
1793 object->presentParms.AutoDepthStencilFormat,
1794 object->presentParms.MultiSampleType,
1795 object->presentParms.MultiSampleQuality,
1796 FALSE /* FIXME: Discard */,
1797 &This->depthStencilBuffer,
1798 NULL /* pShared (always null)*/ );
1799 if (This->depthStencilBuffer != NULL)
1800 IWineD3DSurface_SetContainer(This->depthStencilBuffer, 0);
1803 /** TODO: A check on width, height and multisample types
1804 *(since the zbuffer must be at least as large as the render target and have the same multisample parameters)
1805 ****************************/
1806 object->wantsDepthStencilBuffer = TRUE;
1808 object->wantsDepthStencilBuffer = FALSE;
1811 TRACE("FrontBuf @ %p, BackBuf @ %p, DepthStencil %d\n",object->frontBuffer, object->backBuffer ? object->backBuffer[0] : NULL, object->wantsDepthStencilBuffer);
1814 /*********************
1815 * init the default renderTarget management
1816 *******************/
1817 object->drawable = object->win;
1818 object->render_ctx = object->glCtx;
1820 if (hr == WINED3D_OK) {
1821 /*********************
1822 * Setup some defaults and clear down the buffers
1823 *******************/
1825 /** save current context and drawable **/
1826 oldContext = glXGetCurrentContext();
1827 oldDrawable = glXGetCurrentDrawable();
1829 TRACE("Activating context (display %p context %p drawable %ld)!\n", object->display, object->glCtx, object->win);
1830 if (glXMakeCurrent(object->display, object->win, object->glCtx) == False) {
1831 ERR("Error in setting current context (display %p context %p drawable %ld)!\n", object->display, object->glCtx, object->win);
1833 checkGLcall("glXMakeCurrent");
1835 TRACE("Setting up the screen\n");
1836 /* Clear the screen */
1837 glClearColor(1.0, 0.0, 0.0, 0.0);
1838 checkGLcall("glClearColor");
1841 glClearStencil(0xffff);
1843 checkGLcall("glClear");
1845 glColor3f(1.0, 1.0, 1.0);
1846 checkGLcall("glColor3f");
1848 glEnable(GL_LIGHTING);
1849 checkGLcall("glEnable");
1851 glLightModeli(GL_LIGHT_MODEL_LOCAL_VIEWER, GL_TRUE);
1852 checkGLcall("glLightModeli(GL_LIGHT_MODEL_LOCAL_VIEWER, GL_TRUE);");
1854 glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE_EXT);
1855 checkGLcall("glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE_EXT);");
1857 glLightModeli(GL_LIGHT_MODEL_COLOR_CONTROL, GL_SEPARATE_SPECULAR_COLOR);
1858 checkGLcall("glLightModeli(GL_LIGHT_MODEL_COLOR_CONTROL, GL_SEPARATE_SPECULAR_COLOR);");
1860 /* switch back to the original context (if there was one)*/
1861 if (This->swapchains) {
1862 /** TODO: restore the context and drawable **/
1863 glXMakeCurrent(object->display, oldDrawable, oldContext);
1866 /* Set the surface alignment. This never changes, so we are safe to set it once per context*/
1867 glPixelStorei(GL_PACK_ALIGNMENT, SURFACE_ALIGNMENT);
1868 checkGLcall("glPixelStorei(GL_PACK_ALIGNMENT, SURFACE_ALIGNMENT);");
1869 glPixelStorei(GL_UNPACK_ALIGNMENT, SURFACE_ALIGNMENT);
1870 checkGLcall("glPixelStorei(GL_UNPACK_ALIGNMENT, SURFACE_ALIGNMENT);");
1874 TRACE("Set swapchain to %p\n", object);
1875 } else { /* something went wrong so clean up */
1876 IUnknown* bufferParent;
1877 if (object->frontBuffer) {
1879 IWineD3DSurface_GetParent(object->frontBuffer, &bufferParent);
1880 IUnknown_Release(bufferParent); /* once for the get parent */
1881 if (IUnknown_Release(bufferParent) > 0) {
1882 FIXME("(%p) Something's still holding the front buffer\n",This);
1885 if (object->backBuffer) {
1887 for(i = 0; i < object->presentParms.BackBufferCount; i++) {
1888 if(object->backBuffer[i]) {
1889 IWineD3DSurface_GetParent(object->backBuffer[i], &bufferParent);
1890 IUnknown_Release(bufferParent); /* once for the get parent */
1891 if (IUnknown_Release(bufferParent) > 0) {
1892 FIXME("(%p) Something's still holding the back buffer\n",This);
1896 HeapFree(GetProcessHeap(), 0, object->backBuffer);
1897 object->backBuffer = NULL;
1899 /* NOTE: don't clean up the depthstencil buffer because it belongs to the device */
1900 /* Clean up the context */
1901 /* check that we are the current context first (we shouldn't be though!) */
1902 if (object->glCtx != 0) {
1903 if(glXGetCurrentContext() == object->glCtx) {
1904 glXMakeCurrent(object->display, None, NULL);
1906 glXDestroyContext(object->display, object->glCtx);
1908 HeapFree(GetProcessHeap(), 0, object);
1915 /** NOTE: These are ahead of the other getters and setters to save using a forward declaration **/
1916 static UINT WINAPI IWineD3DDeviceImpl_GetNumberOfSwapChains(IWineD3DDevice *iface) {
1917 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
1918 TRACE("(%p)\n", This);
1920 return This->NumberOfSwapChains;
1923 static HRESULT WINAPI IWineD3DDeviceImpl_GetSwapChain(IWineD3DDevice *iface, UINT iSwapChain, IWineD3DSwapChain **pSwapChain) {
1924 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
1925 TRACE("(%p) : swapchain %d\n", This, iSwapChain);
1927 if(iSwapChain < This->NumberOfSwapChains) {
1928 *pSwapChain = This->swapchains[iSwapChain];
1929 IWineD3DSwapChain_AddRef(*pSwapChain);
1930 TRACE("(%p) returning %p\n", This, *pSwapChain);
1933 TRACE("Swapchain out of range\n");
1935 return WINED3DERR_INVALIDCALL;
1940 * Vertex Declaration
1942 static HRESULT WINAPI IWineD3DDeviceImpl_CreateVertexDeclaration(IWineD3DDevice* iface, CONST VOID* pDeclaration, IWineD3DVertexDeclaration** ppVertexDeclaration, IUnknown *parent) {
1943 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
1944 IWineD3DVertexDeclarationImpl *object = NULL;
1945 HRESULT hr = WINED3D_OK;
1946 TRACE("(%p) : directXVersion=%u, pFunction=%p, ppDecl=%p\n", This, ((IWineD3DImpl *)This->wineD3D)->dxVersion, pDeclaration, ppVertexDeclaration);
1947 D3DCREATEOBJECTINSTANCE(object, VertexDeclaration)
1950 hr = IWineD3DVertexDeclaration_SetDeclaration((IWineD3DVertexDeclaration *)object, (void *)pDeclaration);
1955 /* http://msdn.microsoft.com/archive/default.asp?url=/archive/en-us/directx9_c/directx/graphics/programmingguide/programmable/vertexshaders/vscreate.asp */
1956 static HRESULT WINAPI IWineD3DDeviceImpl_CreateVertexShader(IWineD3DDevice *iface, CONST DWORD *pDeclaration, CONST DWORD *pFunction, IWineD3DVertexShader **ppVertexShader, IUnknown *parent) {
1957 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
1958 IWineD3DVertexShaderImpl *object; /* NOTE: impl usage is ok, this is a create */
1959 HRESULT hr = WINED3D_OK;
1960 D3DCREATESHADEROBJECTINSTANCE(object, VertexShader)
1961 object->baseShader.shader_ins = IWineD3DVertexShaderImpl_shader_ins;
1963 TRACE("(%p) : Created Vertex shader %p\n", This, *ppVertexShader);
1965 /* If a vertex declaration has been passed, save it to the vertex shader, this affects d3d8 only. */
1966 /* Further it needs to be set before calling SetFunction as SetFunction needs the declaration. */
1967 if (pDeclaration != NULL) {
1968 IWineD3DVertexDeclaration *vertexDeclaration;
1969 hr = IWineD3DDevice_CreateVertexDeclaration(iface, pDeclaration, &vertexDeclaration ,NULL);
1970 if (WINED3D_OK == hr) {
1971 TRACE("(%p) : Setting vertex declaration to %p\n", This, vertexDeclaration);
1972 object->vertexDeclaration = vertexDeclaration;
1974 FIXME("(%p) : Failed to set the declaration, returning WINED3DERR_INVALIDCALL\n", iface);
1975 IWineD3DVertexShader_Release(*ppVertexShader);
1976 return WINED3DERR_INVALIDCALL;
1980 hr = IWineD3DVertexShader_SetFunction(*ppVertexShader, pFunction);
1982 if (WINED3D_OK != hr) {
1983 FIXME("(%p) : Failed to set the function, returning WINED3DERR_INVALIDCALL\n", iface);
1984 IWineD3DVertexShader_Release(*ppVertexShader);
1985 return WINED3DERR_INVALIDCALL;
1988 #if 0 /* TODO: In D3D* SVP is atatched to the shader, in D3D9 it's attached to the device and isn't stored in the stateblock. */
1989 if(Usage == WINED3DUSAGE_SOFTWAREVERTEXPROCESSING) {
2000 static HRESULT WINAPI IWineD3DDeviceImpl_CreatePixelShader(IWineD3DDevice *iface, CONST DWORD *pFunction, IWineD3DPixelShader **ppPixelShader, IUnknown *parent) {
2001 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2002 IWineD3DPixelShaderImpl *object; /* NOTE: impl allowed, this is a create */
2003 HRESULT hr = WINED3D_OK;
2005 D3DCREATESHADEROBJECTINSTANCE(object, PixelShader)
2006 object->baseShader.shader_ins = IWineD3DPixelShaderImpl_shader_ins;
2007 hr = IWineD3DPixelShader_SetFunction(*ppPixelShader, pFunction);
2008 if (WINED3D_OK == hr) {
2009 TRACE("(%p) : Created Pixel shader %p\n", This, *ppPixelShader);
2011 WARN("(%p) : Failed to create pixel shader\n", This);
2017 static HRESULT WINAPI IWineD3DDeviceImpl_CreatePalette(IWineD3DDevice *iface, DWORD Flags, PALETTEENTRY *PalEnt, IWineD3DPalette **Palette, IUnknown *Parent) {
2018 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *) iface;
2019 IWineD3DPaletteImpl *object;
2021 TRACE("(%p)->(%x, %p, %p, %p)\n", This, Flags, PalEnt, Palette, Parent);
2023 /* Create the new object */
2024 object = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(IWineD3DPaletteImpl));
2026 ERR("Out of memory when allocating memory for a IWineD3DPalette implementation\n");
2027 return E_OUTOFMEMORY;
2030 object->lpVtbl = &IWineD3DPalette_Vtbl;
2032 object->Flags = Flags;
2033 object->parent = Parent;
2034 object->wineD3DDevice = This;
2035 object->palNumEntries = IWineD3DPaletteImpl_Size(Flags);
2037 object->hpal = CreatePalette((const LOGPALETTE*)&(object->palVersion));
2040 HeapFree( GetProcessHeap(), 0, object);
2041 return E_OUTOFMEMORY;
2044 hr = IWineD3DPalette_SetEntries((IWineD3DPalette *) object, 0, 0, IWineD3DPaletteImpl_Size(Flags), PalEnt);
2046 IWineD3DPalette_Release((IWineD3DPalette *) object);
2050 *Palette = (IWineD3DPalette *) object;
2055 static HRESULT WINAPI IWineD3DDeviceImpl_Init3D(IWineD3DDevice *iface, WINED3DPRESENT_PARAMETERS* pPresentationParameters, D3DCB_CREATEADDITIONALSWAPCHAIN D3DCB_CreateAdditionalSwapChain) {
2056 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *) iface;
2057 IWineD3DSwapChainImpl *swapchain;
2059 TRACE("(%p)->(%p,%p)\n", This, pPresentationParameters, D3DCB_CreateAdditionalSwapChain);
2060 if(This->d3d_initialized) return WINED3DERR_INVALIDCALL;
2062 /* TODO: Test if OpenGL is compiled in and loaded */
2064 /* Setup the implicit swapchain */
2065 TRACE("Creating implicit swapchain\n");
2066 if (D3D_OK != D3DCB_CreateAdditionalSwapChain((IUnknown *) This->parent, pPresentationParameters, (IWineD3DSwapChain **)&swapchain) || swapchain == NULL) {
2067 WARN("Failed to create implicit swapchain\n");
2068 return WINED3DERR_INVALIDCALL;
2071 This->NumberOfSwapChains = 1;
2072 This->swapchains = HeapAlloc(GetProcessHeap(), 0, This->NumberOfSwapChains * sizeof(IWineD3DSwapChain *));
2073 if(!This->swapchains) {
2074 ERR("Out of memory!\n");
2075 IWineD3DSwapChain_Release( (IWineD3DSwapChain *) swapchain);
2076 return E_OUTOFMEMORY;
2078 This->swapchains[0] = (IWineD3DSwapChain *) swapchain;
2080 if(swapchain->backBuffer && swapchain->backBuffer[0]) {
2081 TRACE("Setting rendertarget to %p\n", swapchain->backBuffer);
2082 This->renderTarget = swapchain->backBuffer[0];
2085 TRACE("Setting rendertarget to %p\n", swapchain->frontBuffer);
2086 This->renderTarget = swapchain->frontBuffer;
2088 IWineD3DSurface_AddRef(This->renderTarget);
2089 /* Depth Stencil support */
2090 This->stencilBufferTarget = This->depthStencilBuffer;
2091 if (NULL != This->stencilBufferTarget) {
2092 IWineD3DSurface_AddRef(This->stencilBufferTarget);
2095 /* Set up some starting GL setup */
2098 * Initialize openGL extension related variables
2099 * with Default values
2102 ((IWineD3DImpl *) This->wineD3D)->isGLInfoValid = IWineD3DImpl_FillGLCaps( This->wineD3D, swapchain->display);
2103 /* Setup all the devices defaults */
2104 IWineD3DStateBlock_InitStartupStateBlock((IWineD3DStateBlock *)This->stateBlock);
2106 IWineD3DImpl_CheckGraphicsMemory();
2110 /* Initialize our list of GLSL programs */
2111 list_init(&This->glsl_shader_progs);
2113 { /* Set a default viewport */
2117 vp.Width = *(pPresentationParameters->BackBufferWidth);
2118 vp.Height = *(pPresentationParameters->BackBufferHeight);
2121 IWineD3DDevice_SetViewport((IWineD3DDevice *)This, &vp);
2124 /* Initialize the current view state */
2125 This->modelview_valid = 1;
2126 This->proj_valid = 0;
2127 This->view_ident = 1;
2128 This->last_was_rhw = 0;
2129 glGetIntegerv(GL_MAX_LIGHTS, &This->maxConcurrentLights);
2130 TRACE("(%p) All defaults now set up, leaving Init3D with %p\n", This, This);
2132 /* Clear the screen */
2133 IWineD3DDevice_Clear((IWineD3DDevice *) This, 0, NULL, WINED3DCLEAR_STENCIL|WINED3DCLEAR_ZBUFFER|WINED3DCLEAR_TARGET, 0x00, 1.0, 0);
2135 This->d3d_initialized = TRUE;
2139 static HRESULT WINAPI IWineD3DDeviceImpl_Uninit3D(IWineD3DDevice *iface) {
2140 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *) iface;
2142 IUnknown* stencilBufferParent;
2143 IUnknown* swapChainParent;
2145 TRACE("(%p)\n", This);
2147 if(!This->d3d_initialized) return WINED3DERR_INVALIDCALL;
2149 /* Delete the mouse cursor texture */
2150 if(This->cursorTexture) {
2152 glDeleteTextures(1, &This->cursorTexture);
2154 This->cursorTexture = 0;
2157 for(sampler = 0; sampler < GL_LIMITS(sampler_stages); ++sampler) {
2158 IWineD3DDevice_SetTexture(iface, sampler, NULL);
2161 /* Release the buffers (with sanity checks)*/
2162 TRACE("Releasing the depth stencil buffer at %p\n", This->stencilBufferTarget);
2163 if(This->stencilBufferTarget != NULL && (IWineD3DSurface_Release(This->stencilBufferTarget) >0)){
2164 if(This->depthStencilBuffer != This->stencilBufferTarget)
2165 FIXME("(%p) Something's still holding the depthStencilBuffer\n",This);
2167 This->stencilBufferTarget = NULL;
2169 TRACE("Releasing the render target at %p\n", This->renderTarget);
2170 if(IWineD3DSurface_Release(This->renderTarget) >0){
2171 /* This check is a bit silly, itshould be in swapchain_release FIXME("(%p) Something's still holding the renderTarget\n",This); */
2173 TRACE("Setting rendertarget to NULL\n");
2174 This->renderTarget = NULL;
2176 if (This->depthStencilBuffer) {
2177 IWineD3DSurface_GetParent(This->depthStencilBuffer, &stencilBufferParent);
2178 IUnknown_Release(stencilBufferParent); /* once for the get parent */
2179 if(IUnknown_Release(stencilBufferParent) >0){ /* the second time for when it was created */
2180 FIXME("(%p) Something's still holding the depthStencilBuffer\n",This);
2182 This->depthStencilBuffer = NULL;
2185 for(i=0; i < This->NumberOfSwapChains; i++) {
2186 TRACE("Releasing the implicit swapchain %d\n", i);
2187 /* Swapchain 0 is special because it's created in startup with a hanging parent, so we have to release its parent now */
2188 IWineD3DSwapChain_GetParent(This->swapchains[i], &swapChainParent);
2189 IUnknown_Release(swapChainParent); /* once for the get parent */
2190 if (IUnknown_Release(swapChainParent) > 0) { /* the second time for when it was created */
2191 FIXME("(%p) Something's still holding the implicit swapchain\n", This);
2195 HeapFree(GetProcessHeap(), 0, This->swapchains);
2196 This->swapchains = NULL;
2197 This->NumberOfSwapChains = 0;
2199 This->d3d_initialized = FALSE;
2203 static void WINAPI IWineD3DDeviceImpl_SetFullscreen(IWineD3DDevice *iface, BOOL fullscreen) {
2204 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *) iface;
2205 TRACE("(%p) Setting DDraw fullscreen mode to %s\n", This, fullscreen ? "true" : "false");
2207 /* DirectDraw apps can change between fullscreen and windowed mode after device creation with
2208 * IDirectDraw7::SetCooperativeLevel. The GDI surface implementation needs to know this.
2209 * DDraw doesn't necessarily have a swapchain, so we have to store the fullscreen flag
2212 This->ddraw_fullscreen = fullscreen;
2215 static HRESULT WINAPI IWineD3DDeviceImpl_EnumDisplayModes(IWineD3DDevice *iface, DWORD Flags, UINT Width, UINT Height, WINED3DFORMAT pixelformat, LPVOID context, D3DCB_ENUMDISPLAYMODESCALLBACK callback) {
2216 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2220 const PixelFormatDesc *formatDesc = getFormatDescEntry(pixelformat);
2222 TRACE("(%p)->(%x,%d,%d,%d,%p,%p)\n", This, Flags, Width, Height, pixelformat, context, callback);
2224 for (i = 0; EnumDisplaySettingsExW(NULL, i, &DevModeW, 0); i++) {
2225 /* Ignore some modes if a description was passed */
2226 if ( (Width > 0) && (Width != DevModeW.dmPelsWidth)) continue;
2227 if ( (Height > 0) && (Height != DevModeW.dmPelsHeight)) continue;
2228 if ( (pixelformat != WINED3DFMT_UNKNOWN) && ( formatDesc->bpp != DevModeW.dmBitsPerPel) ) continue;
2230 TRACE("Enumerating %dx%d@%s\n", DevModeW.dmPelsWidth, DevModeW.dmPelsHeight, debug_d3dformat(pixelformat_for_depth(DevModeW.dmBitsPerPel)));
2232 if (callback((IUnknown *) This, (UINT) DevModeW.dmPelsWidth, (UINT) DevModeW.dmPelsHeight, pixelformat_for_depth(DevModeW.dmBitsPerPel), 60.0, context) == DDENUMRET_CANCEL)
2239 static HRESULT WINAPI IWineD3DDeviceImpl_SetDisplayMode(IWineD3DDevice *iface, UINT iSwapChain, WINED3DDISPLAYMODE* pMode) {
2241 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2243 const PixelFormatDesc *formatDesc = getFormatDescEntry(pMode->Format);
2245 TRACE("(%p)->(%d,%p) Mode=%dx%dx@%d, %s\n", This, iSwapChain, pMode, pMode->Width, pMode->Height, pMode->RefreshRate, debug_d3dformat(pMode->Format));
2247 /* Resize the screen even without a window:
2248 * The app could have unset it with SetCooperativeLevel, but not called
2249 * RestoreDisplayMode first. Then the release will call RestoreDisplayMode,
2250 * but we don't have any hwnd
2253 devmode.dmFields = DM_BITSPERPEL | DM_PELSWIDTH | DM_PELSHEIGHT;
2254 devmode.dmBitsPerPel = formatDesc->bpp * 8;
2255 if(devmode.dmBitsPerPel == 24) devmode.dmBitsPerPel = 32;
2256 devmode.dmPelsWidth = pMode->Width;
2257 devmode.dmPelsHeight = pMode->Height;
2259 devmode.dmDisplayFrequency = pMode->RefreshRate;
2260 if (pMode->RefreshRate != 0) {
2261 devmode.dmFields |= DM_DISPLAYFREQUENCY;
2264 /* Only change the mode if necessary */
2265 if( (This->ddraw_width == pMode->Width) &&
2266 (This->ddraw_height == pMode->Height) &&
2267 (This->ddraw_format == pMode->Format) &&
2268 (pMode->RefreshRate == 0) ) {
2272 ret = ChangeDisplaySettingsExW(NULL, &devmode, NULL, CDS_FULLSCREEN, NULL);
2273 if (ret != DISP_CHANGE_SUCCESSFUL) {
2274 if(devmode.dmDisplayFrequency != 0) {
2275 WARN("ChangeDisplaySettingsExW failed, trying without the refresh rate\n");
2276 devmode.dmFields &= ~DM_DISPLAYFREQUENCY;
2277 devmode.dmDisplayFrequency = 0;
2278 ret = ChangeDisplaySettingsExW(NULL, &devmode, NULL, CDS_FULLSCREEN, NULL) != DISP_CHANGE_SUCCESSFUL;
2280 if(ret != DISP_CHANGE_SUCCESSFUL) {
2281 return DDERR_INVALIDMODE;
2285 /* Store the new values */
2286 This->ddraw_width = pMode->Width;
2287 This->ddraw_height = pMode->Height;
2288 This->ddraw_format = pMode->Format;
2290 /* Only do this with a window of course */
2291 if(This->ddraw_window)
2292 MoveWindow(This->ddraw_window, 0, 0, pMode->Width, pMode->Height, TRUE);
2297 static HRESULT WINAPI IWineD3DDeviceImpl_GetDirect3D(IWineD3DDevice *iface, IWineD3D **ppD3D) {
2298 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2299 *ppD3D= This->wineD3D;
2300 TRACE("(%p) : wineD3D returning %p\n", This, *ppD3D);
2301 IWineD3D_AddRef(*ppD3D);
2305 static UINT WINAPI IWineD3DDeviceImpl_GetAvailableTextureMem(IWineD3DDevice *iface) {
2306 /** NOTE: There's a probably a hack-around for this one by putting as many pbuffers, VBOs (or whatever)
2307 * into the video ram as possible and seeing how many fit
2308 * you can also get the correct initial value from nvidia and ATI's driver via X
2309 * texture memory is video memory + AGP memory
2310 *******************/
2311 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2312 static BOOL showfixmes = TRUE;
2314 FIXME("(%p) : stub, simulating %dMB for now, returning %dMB left\n", This,
2315 (wined3d_settings.emulated_textureram/(1024*1024)),
2316 ((wined3d_settings.emulated_textureram - wineD3DGlobalStatistics->glsurfaceram) / (1024*1024)));
2319 TRACE("(%p) : simulating %dMB, returning %dMB left\n", This,
2320 (wined3d_settings.emulated_textureram/(1024*1024)),
2321 ((wined3d_settings.emulated_textureram - wineD3DGlobalStatistics->glsurfaceram) / (1024*1024)));
2322 /* return simulated texture memory left */
2323 return (wined3d_settings.emulated_textureram - wineD3DGlobalStatistics->glsurfaceram);
2331 static HRESULT WINAPI IWineD3DDeviceImpl_SetFVF(IWineD3DDevice *iface, DWORD fvf) {
2332 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2333 HRESULT hr = WINED3D_OK;
2335 /* Update the current state block */
2336 This->updateStateBlock->fvf = fvf;
2337 This->updateStateBlock->changed.fvf = TRUE;
2338 This->updateStateBlock->set.fvf = TRUE;
2340 TRACE("(%p) : FVF Shader FVF set to %x\n", This, fvf);
2345 static HRESULT WINAPI IWineD3DDeviceImpl_GetFVF(IWineD3DDevice *iface, DWORD *pfvf) {
2346 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2347 TRACE("(%p) : GetFVF returning %x\n", This, This->stateBlock->fvf);
2348 *pfvf = This->stateBlock->fvf;
2353 * Get / Set Stream Source
2355 static HRESULT WINAPI IWineD3DDeviceImpl_SetStreamSource(IWineD3DDevice *iface, UINT StreamNumber,IWineD3DVertexBuffer* pStreamData, UINT OffsetInBytes, UINT Stride) {
2356 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2357 IWineD3DVertexBuffer *oldSrc;
2359 /**TODO: instance and index data, see
2360 http://msdn.microsoft.com/library/default.asp?url=/library/en-us/directx9_c/directx/graphics/programmingguide/advancedtopics/DrawingMultipleInstances.asp
2362 http://msdn.microsoft.com/library/default.asp?url=/library/en-us/directx9_c/directx/graphics/reference/d3d/interfaces/idirect3ddevice9/SetStreamSourceFreq.asp
2365 /* D3d9 only, but shouldn't hurt d3d8 */
2368 streamFlags = StreamNumber &(WINED3DSTREAMSOURCE_INDEXEDDATA | WINED3DSTREAMSOURCE_INSTANCEDATA);
2370 if (streamFlags & WINED3DSTREAMSOURCE_INDEXEDDATA) {
2371 FIXME("stream index data not supported\n");
2373 if (streamFlags & WINED3DSTREAMSOURCE_INDEXEDDATA) {
2374 FIXME("stream instance data not supported\n");
2378 StreamNumber&= ~(WINED3DSTREAMSOURCE_INDEXEDDATA | WINED3DSTREAMSOURCE_INSTANCEDATA);
2380 if (StreamNumber >= MAX_STREAMS) {
2381 WARN("Stream out of range %d\n", StreamNumber);
2382 return WINED3DERR_INVALIDCALL;
2385 oldSrc = This->stateBlock->streamSource[StreamNumber];
2386 TRACE("(%p) : StreamNo: %d, OldStream (%p), NewStream (%p), NewStride %d\n", This, StreamNumber, oldSrc, pStreamData, Stride);
2388 This->updateStateBlock->changed.streamSource[StreamNumber] = TRUE;
2389 This->updateStateBlock->set.streamSource[StreamNumber] = TRUE;
2390 This->updateStateBlock->streamStride[StreamNumber] = Stride;
2391 This->updateStateBlock->streamSource[StreamNumber] = pStreamData;
2392 This->updateStateBlock->streamOffset[StreamNumber] = OffsetInBytes;
2393 This->updateStateBlock->streamFlags[StreamNumber] = streamFlags;
2395 /* Handle recording of state blocks */
2396 if (This->isRecordingState) {
2397 TRACE("Recording... not performing anything\n");
2401 /* Same stream object: no action */
2402 if (oldSrc == pStreamData)
2405 /* Need to do a getParent and pass the reffs up */
2406 /* MSDN says ..... When an application no longer holds a references to this interface, the interface will automatically be freed.
2407 which suggests that we shouldn't be ref counting? and do need a _release on the stream source to reset the stream source
2408 so for now, just count internally */
2409 if (pStreamData != NULL) {
2410 IWineD3DVertexBufferImpl *vbImpl = (IWineD3DVertexBufferImpl *) pStreamData;
2411 if( (vbImpl->Flags & VBFLAG_STREAM) && vbImpl->stream != StreamNumber) {
2412 WARN("Assigning a Vertex Buffer to stream %d which is already assigned to stream %d\n", StreamNumber, vbImpl->stream);
2414 vbImpl->stream = StreamNumber;
2415 vbImpl->Flags |= VBFLAG_STREAM;
2416 IWineD3DVertexBuffer_AddRef(pStreamData);
2418 if (oldSrc != NULL) {
2419 ((IWineD3DVertexBufferImpl *) oldSrc)->Flags &= ~VBFLAG_STREAM;
2420 IWineD3DVertexBuffer_Release(oldSrc);
2426 static HRESULT WINAPI IWineD3DDeviceImpl_GetStreamSource(IWineD3DDevice *iface, UINT StreamNumber,IWineD3DVertexBuffer** pStream, UINT *pOffset, UINT* pStride) {
2427 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2430 TRACE("(%p) : StreamNo: %d, Stream (%p), Stride %d\n", This, StreamNumber,
2431 This->stateBlock->streamSource[StreamNumber], This->stateBlock->streamStride[StreamNumber]);
2434 streamFlags = StreamNumber &(WINED3DSTREAMSOURCE_INDEXEDDATA | WINED3DSTREAMSOURCE_INSTANCEDATA);
2436 if (streamFlags & WINED3DSTREAMSOURCE_INDEXEDDATA) {
2437 FIXME("stream index data not supported\n");
2439 if (streamFlags & WINED3DSTREAMSOURCE_INDEXEDDATA) {
2440 FIXME("stream instance data not supported\n");
2444 StreamNumber&= ~(WINED3DSTREAMSOURCE_INDEXEDDATA | WINED3DSTREAMSOURCE_INSTANCEDATA);
2446 if (StreamNumber >= MAX_STREAMS) {
2447 WARN("Stream out of range %d\n", StreamNumber);
2448 return WINED3DERR_INVALIDCALL;
2450 *pStream = This->stateBlock->streamSource[StreamNumber];
2451 *pStride = This->stateBlock->streamStride[StreamNumber];
2453 *pOffset = This->stateBlock->streamOffset[StreamNumber];
2456 if (*pStream == NULL) {
2457 FIXME("Attempting to get an empty stream %d, returning WINED3DERR_INVALIDCALL\n", StreamNumber);
2458 return WINED3DERR_INVALIDCALL;
2464 /*Should be quite easy, just an extension of vertexdata
2466 http://msdn.microsoft.com/archive/default.asp?url=/archive/en-us/directx9_c_Summer_04/directx/graphics/programmingguide/advancedtopics/DrawingMultipleInstances.asp
2468 The divider is a bit odd though
2470 VertexOffset = StartVertex / Divider * StreamStride +
2471 VertexIndex / Divider * StreamStride + StreamOffset
2474 static HRESULT WINAPI IWineD3DDeviceImpl_SetStreamSourceFreq(IWineD3DDevice *iface, UINT StreamNumber, UINT Divider) {
2475 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2477 TRACE("(%p) StreamNumber(%d), Divider(%d)\n", This, StreamNumber, Divider);
2478 This->updateStateBlock->streamFlags[StreamNumber] = Divider & (WINED3DSTREAMSOURCE_INSTANCEDATA | WINED3DSTREAMSOURCE_INDEXEDDATA );
2480 This->updateStateBlock->changed.streamFreq[StreamNumber] = TRUE;
2481 This->updateStateBlock->set.streamFreq[StreamNumber] = TRUE;
2482 This->updateStateBlock->streamFreq[StreamNumber] = Divider & 0x7FFFFF;
2484 if (This->updateStateBlock->streamFlags[StreamNumber] || This->updateStateBlock->streamFreq[StreamNumber] != 1) {
2485 FIXME("Stream indexing not fully supported\n");
2491 static HRESULT WINAPI IWineD3DDeviceImpl_GetStreamSourceFreq(IWineD3DDevice *iface, UINT StreamNumber, UINT* Divider) {
2492 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2494 TRACE("(%p) StreamNumber(%d), Divider(%p)\n", This, StreamNumber, Divider);
2495 *Divider = This->updateStateBlock->streamFreq[StreamNumber] | This->updateStateBlock->streamFlags[StreamNumber];
2497 TRACE("(%p) : returning %d\n", This, *Divider);
2503 * Get / Set & Multiply Transform
2505 static HRESULT WINAPI IWineD3DDeviceImpl_SetTransform(IWineD3DDevice *iface, WINED3DTRANSFORMSTATETYPE d3dts, CONST WINED3DMATRIX* lpmatrix) {
2506 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2508 /* Most of this routine, comments included copied from ddraw tree initially: */
2509 TRACE("(%p) : Transform State=%s\n", This, debug_d3dtstype(d3dts));
2511 /* Handle recording of state blocks */
2512 if (This->isRecordingState) {
2513 TRACE("Recording... not performing anything\n");
2514 This->updateStateBlock->changed.transform[d3dts] = TRUE;
2515 This->updateStateBlock->set.transform[d3dts] = TRUE;
2516 memcpy(&This->updateStateBlock->transforms[d3dts], lpmatrix, sizeof(WINED3DMATRIX));
2521 * If the new matrix is the same as the current one,
2522 * we cut off any further processing. this seems to be a reasonable
2523 * optimization because as was noticed, some apps (warcraft3 for example)
2524 * tend towards setting the same matrix repeatedly for some reason.
2526 * From here on we assume that the new matrix is different, wherever it matters.
2528 if (!memcmp(&This->stateBlock->transforms[d3dts].u.m[0][0], lpmatrix, sizeof(WINED3DMATRIX))) {
2529 TRACE("The app is setting the same matrix over again\n");
2532 conv_mat(lpmatrix, &This->stateBlock->transforms[d3dts].u.m[0][0]);
2536 ScreenCoord = ProjectionMat * ViewMat * WorldMat * ObjectCoord
2537 where ViewMat = Camera space, WorldMat = world space.
2539 In OpenGL, camera and world space is combined into GL_MODELVIEW
2540 matrix. The Projection matrix stay projection matrix.
2543 /* Capture the times we can just ignore the change for now */
2544 if (d3dts == WINED3DTS_WORLDMATRIX(0)) {
2545 This->modelview_valid = FALSE;
2548 } else if (d3dts == WINED3DTS_PROJECTION) {
2549 This->proj_valid = FALSE;
2552 } else if (d3dts >= WINED3DTS_WORLDMATRIX(1) && d3dts <= WINED3DTS_WORLDMATRIX(255)) {
2553 /* Indexed Vertex Blending Matrices 256 -> 511 */
2554 /* Use arb_vertex_blend or NV_VERTEX_WEIGHTING? */
2555 FIXME("WINED3DTS_WORLDMATRIX(1..255) not handled\n");
2559 /* Now we really are going to have to change a matrix */
2562 if (d3dts >= WINED3DTS_TEXTURE0 && d3dts <= WINED3DTS_TEXTURE7) { /* handle texture matrices */
2563 /* This is now set with the texture unit states, it may be a good idea to flag the change though! */
2564 } else if (d3dts == WINED3DTS_VIEW) { /* handle the VIEW matrice */
2567 /* If we are changing the View matrix, reset the light and clipping planes to the new view
2568 * NOTE: We have to reset the positions even if the light/plane is not currently
2569 * enabled, since the call to enable it will not reset the position.
2570 * NOTE2: Apparently texture transforms do NOT need reapplying
2573 PLIGHTINFOEL *lightChain = NULL;
2574 This->modelview_valid = FALSE;
2575 This->view_ident = !memcmp(lpmatrix, identity, 16 * sizeof(float));
2577 glMatrixMode(GL_MODELVIEW);
2578 checkGLcall("glMatrixMode(GL_MODELVIEW)");
2580 glLoadMatrixf((float *)lpmatrix);
2581 checkGLcall("glLoadMatrixf(...)");
2584 lightChain = This->stateBlock->lights;
2585 while (lightChain && lightChain->glIndex != -1) {
2586 glLightfv(GL_LIGHT0 + lightChain->glIndex, GL_POSITION, lightChain->lightPosn);
2587 checkGLcall("glLightfv posn");
2588 glLightfv(GL_LIGHT0 + lightChain->glIndex, GL_SPOT_DIRECTION, lightChain->lightDirn);
2589 checkGLcall("glLightfv dirn");
2590 lightChain = lightChain->next;
2593 /* Reset Clipping Planes if clipping is enabled */
2594 for (k = 0; k < GL_LIMITS(clipplanes); k++) {
2595 glClipPlane(GL_CLIP_PLANE0 + k, This->stateBlock->clipplane[k]);
2596 checkGLcall("glClipPlane");
2600 } else { /* What was requested!?? */
2601 WARN("invalid matrix specified: %i\n", d3dts);
2604 /* Release lock, all done */
2609 static HRESULT WINAPI IWineD3DDeviceImpl_GetTransform(IWineD3DDevice *iface, WINED3DTRANSFORMSTATETYPE State, WINED3DMATRIX* pMatrix) {
2610 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2611 TRACE("(%p) : for Transform State %s\n", This, debug_d3dtstype(State));
2612 memcpy(pMatrix, &This->stateBlock->transforms[State], sizeof(WINED3DMATRIX));
2616 static HRESULT WINAPI IWineD3DDeviceImpl_MultiplyTransform(IWineD3DDevice *iface, WINED3DTRANSFORMSTATETYPE State, CONST WINED3DMATRIX* pMatrix) {
2617 WINED3DMATRIX *mat = NULL;
2620 /* Note: Using 'updateStateBlock' rather than 'stateblock' in the code
2621 * below means it will be recorded in a state block change, but it
2622 * works regardless where it is recorded.
2623 * If this is found to be wrong, change to StateBlock.
2625 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2626 TRACE("(%p) : For state %s\n", This, debug_d3dtstype(State));
2628 if (State < HIGHEST_TRANSFORMSTATE)
2630 mat = &This->updateStateBlock->transforms[State];
2632 FIXME("Unhandled transform state!!\n");
2635 multiply_matrix(&temp, mat, (WINED3DMATRIX *) pMatrix);
2637 /* Apply change via set transform - will reapply to eg. lights this way */
2638 return IWineD3DDeviceImpl_SetTransform(iface, State, &temp);
2644 /* Note lights are real special cases. Although the device caps state only eg. 8 are supported,
2645 you can reference any indexes you want as long as that number max are enabled at any
2646 one point in time! Therefore since the indexes can be anything, we need a linked list of them.
2647 However, this causes stateblock problems. When capturing the state block, I duplicate the list,
2648 but when recording, just build a chain pretty much of commands to be replayed. */
2650 static HRESULT WINAPI IWineD3DDeviceImpl_SetLight(IWineD3DDevice *iface, DWORD Index, CONST WINED3DLIGHT* pLight) {
2652 PLIGHTINFOEL *object, *temp;
2654 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2655 TRACE("(%p) : Idx(%d), pLight(%p)\n", This, Index, pLight);
2657 /* If recording state block, just add to end of lights chain */
2658 if (This->isRecordingState) {
2659 object = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(PLIGHTINFOEL));
2660 if (NULL == object) {
2661 return WINED3DERR_OUTOFVIDEOMEMORY;
2663 memcpy(&object->OriginalParms, pLight, sizeof(WINED3DLIGHT));
2664 object->OriginalIndex = Index;
2665 object->glIndex = -1;
2666 object->changed = TRUE;
2668 /* Add to the END of the chain of lights changes to be replayed */
2669 if (This->updateStateBlock->lights == NULL) {
2670 This->updateStateBlock->lights = object;
2672 temp = This->updateStateBlock->lights;
2673 while (temp->next != NULL) temp=temp->next;
2674 temp->next = object;
2676 TRACE("Recording... not performing anything more\n");
2680 /* Ok, not recording any longer so do real work */
2681 object = This->stateBlock->lights;
2682 while (object != NULL && object->OriginalIndex != Index) object = object->next;
2684 /* If we didn't find it in the list of lights, time to add it */
2685 if (object == NULL) {
2686 PLIGHTINFOEL *insertAt,*prevPos;
2688 object = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(PLIGHTINFOEL));
2689 if (NULL == object) {
2690 return WINED3DERR_OUTOFVIDEOMEMORY;
2692 object->OriginalIndex = Index;
2693 object->glIndex = -1;
2695 /* Add it to the front of list with the idea that lights will be changed as needed
2696 BUT after any lights currently assigned GL indexes */
2697 insertAt = This->stateBlock->lights;
2699 while (insertAt != NULL && insertAt->glIndex != -1) {
2701 insertAt = insertAt->next;
2704 if (insertAt == NULL && prevPos == NULL) { /* Start of list */
2705 This->stateBlock->lights = object;
2706 } else if (insertAt == NULL) { /* End of list */
2707 prevPos->next = object;
2708 object->prev = prevPos;
2709 } else { /* Middle of chain */
2710 if (prevPos == NULL) {
2711 This->stateBlock->lights = object;
2713 prevPos->next = object;
2715 object->prev = prevPos;
2716 object->next = insertAt;
2717 insertAt->prev = object;
2721 /* Initialize the object */
2722 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,
2723 pLight->Diffuse.r, pLight->Diffuse.g, pLight->Diffuse.b, pLight->Diffuse.a,
2724 pLight->Specular.r, pLight->Specular.g, pLight->Specular.b, pLight->Specular.a,
2725 pLight->Ambient.r, pLight->Ambient.g, pLight->Ambient.b, pLight->Ambient.a);
2726 TRACE("... Pos(%f,%f,%f), Dirn(%f,%f,%f)\n", pLight->Position.x, pLight->Position.y, pLight->Position.z,
2727 pLight->Direction.x, pLight->Direction.y, pLight->Direction.z);
2728 TRACE("... Range(%f), Falloff(%f), Theta(%f), Phi(%f)\n", pLight->Range, pLight->Falloff, pLight->Theta, pLight->Phi);
2730 /* Save away the information */
2731 memcpy(&object->OriginalParms, pLight, sizeof(WINED3DLIGHT));
2733 switch (pLight->Type) {
2734 case WINED3DLIGHT_POINT:
2736 object->lightPosn[0] = pLight->Position.x;
2737 object->lightPosn[1] = pLight->Position.y;
2738 object->lightPosn[2] = pLight->Position.z;
2739 object->lightPosn[3] = 1.0f;
2740 object->cutoff = 180.0f;
2744 case WINED3DLIGHT_DIRECTIONAL:
2746 object->lightPosn[0] = -pLight->Direction.x;
2747 object->lightPosn[1] = -pLight->Direction.y;
2748 object->lightPosn[2] = -pLight->Direction.z;
2749 object->lightPosn[3] = 0.0;
2750 object->exponent = 0.0f;
2751 object->cutoff = 180.0f;
2754 case WINED3DLIGHT_SPOT:
2756 object->lightPosn[0] = pLight->Position.x;
2757 object->lightPosn[1] = pLight->Position.y;
2758 object->lightPosn[2] = pLight->Position.z;
2759 object->lightPosn[3] = 1.0;
2762 object->lightDirn[0] = pLight->Direction.x;
2763 object->lightDirn[1] = pLight->Direction.y;
2764 object->lightDirn[2] = pLight->Direction.z;
2765 object->lightDirn[3] = 1.0;
2768 * opengl-ish and d3d-ish spot lights use too different models for the
2769 * light "intensity" as a function of the angle towards the main light direction,
2770 * so we only can approximate very roughly.
2771 * however spot lights are rather rarely used in games (if ever used at all).
2772 * furthermore if still used, probably nobody pays attention to such details.
2774 if (pLight->Falloff == 0) {
2777 rho = pLight->Theta + (pLight->Phi - pLight->Theta)/(2*pLight->Falloff);
2779 if (rho < 0.0001) rho = 0.0001f;
2780 object->exponent = -0.3/log(cos(rho/2));
2781 if (object->exponent > 128.0) {
2782 object->exponent = 128.0;
2784 object->cutoff = pLight->Phi*90/M_PI;
2790 FIXME("Unrecognized light type %d\n", pLight->Type);
2793 /* Update the live definitions if the light is currently assigned a glIndex */
2794 if (object->glIndex != -1) {
2795 setup_light(iface, object->glIndex, object);
2800 static HRESULT WINAPI IWineD3DDeviceImpl_GetLight(IWineD3DDevice *iface, DWORD Index, WINED3DLIGHT* pLight) {
2801 PLIGHTINFOEL *lightInfo = NULL;
2802 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2803 TRACE("(%p) : Idx(%d), pLight(%p)\n", This, Index, pLight);
2805 /* Locate the light in the live lights */
2806 lightInfo = This->stateBlock->lights;
2807 while (lightInfo != NULL && lightInfo->OriginalIndex != Index) lightInfo = lightInfo->next;
2809 if (lightInfo == NULL) {
2810 TRACE("Light information requested but light not defined\n");
2811 return WINED3DERR_INVALIDCALL;
2814 memcpy(pLight, &lightInfo->OriginalParms, sizeof(WINED3DLIGHT));
2819 * Get / Set Light Enable
2820 * (Note for consistency, renamed d3dx function by adding the 'set' prefix)
2822 static HRESULT WINAPI IWineD3DDeviceImpl_SetLightEnable(IWineD3DDevice *iface, DWORD Index, BOOL Enable) {
2823 PLIGHTINFOEL *lightInfo = NULL;
2824 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2825 TRACE("(%p) : Idx(%d), enable? %d\n", This, Index, Enable);
2827 /* Tests show true = 128...not clear why */
2829 Enable = Enable? 128: 0;
2831 /* If recording state block, just add to end of lights chain with changedEnable set to true */
2832 if (This->isRecordingState) {
2833 lightInfo = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(PLIGHTINFOEL));
2834 if (NULL == lightInfo) {
2835 return WINED3DERR_OUTOFVIDEOMEMORY;
2837 lightInfo->OriginalIndex = Index;
2838 lightInfo->glIndex = -1;
2839 lightInfo->enabledChanged = TRUE;
2840 lightInfo->lightEnabled = Enable;
2842 /* Add to the END of the chain of lights changes to be replayed */
2843 if (This->updateStateBlock->lights == NULL) {
2844 This->updateStateBlock->lights = lightInfo;
2846 PLIGHTINFOEL *temp = This->updateStateBlock->lights;
2847 while (temp->next != NULL) temp=temp->next;
2848 temp->next = lightInfo;
2850 TRACE("Recording... not performing anything more\n");
2854 /* Not recording... So, locate the light in the live lights */
2855 lightInfo = This->stateBlock->lights;
2856 while (lightInfo != NULL && lightInfo->OriginalIndex != Index) lightInfo = lightInfo->next;
2858 /* Special case - enabling an undefined light creates one with a strict set of parms! */
2859 if (lightInfo == NULL) {
2861 TRACE("Light enabled requested but light not defined, so defining one!\n");
2862 IWineD3DDeviceImpl_SetLight(iface, Index, &WINED3D_default_light);
2864 /* Search for it again! Should be fairly quick as near head of list */
2865 lightInfo = This->stateBlock->lights;
2866 while (lightInfo != NULL && lightInfo->OriginalIndex != Index) lightInfo = lightInfo->next;
2867 if (lightInfo == NULL) {
2868 FIXME("Adding default lights has failed dismally\n");
2869 return WINED3DERR_INVALIDCALL;
2873 /* OK, we now have a light... */
2876 /* If we are disabling it, check it was enabled, and
2877 still only do something if it has assigned a glIndex (which it should have!) */
2878 if ((lightInfo->lightEnabled) && (lightInfo->glIndex != -1)) {
2879 TRACE("Disabling light set up at gl idx %d\n", lightInfo->glIndex);
2881 glDisable(GL_LIGHT0 + lightInfo->glIndex);
2882 checkGLcall("glDisable GL_LIGHT0+Index");
2885 TRACE("Nothing to do as light was not enabled\n");
2887 lightInfo->lightEnabled = Enable;
2890 /* We are enabling it. If it is enabled, it's really simple */
2891 if (lightInfo->lightEnabled) {
2893 TRACE("Nothing to do as light was enabled\n");
2895 /* If it already has a glIndex, it's still simple */
2896 } else if (lightInfo->glIndex != -1) {
2897 TRACE("Reusing light as already set up at gl idx %d\n", lightInfo->glIndex);
2898 lightInfo->lightEnabled = Enable;
2900 glEnable(GL_LIGHT0 + lightInfo->glIndex);
2901 checkGLcall("glEnable GL_LIGHT0+Index already setup");
2904 /* Otherwise got to find space - lights are ordered gl indexes first */
2906 PLIGHTINFOEL *bsf = NULL;
2907 PLIGHTINFOEL *pos = This->stateBlock->lights;
2908 PLIGHTINFOEL *prev = NULL;
2912 /* Try to minimize changes as much as possible */
2913 while (pos != NULL && pos->glIndex != -1 && Index < This->maxConcurrentLights) {
2915 /* Try to remember which index can be replaced if necessary */
2916 if (bsf==NULL && !pos->lightEnabled) {
2917 /* Found a light we can replace, save as best replacement */
2921 /* Step to next space */
2927 /* If we have too many active lights, fail the call */
2928 if ((Index == This->maxConcurrentLights) && (bsf == NULL)) {
2929 FIXME("Program requests too many concurrent lights\n");
2930 return WINED3DERR_INVALIDCALL;
2932 /* If we have allocated all lights, but not all are enabled,
2933 reuse one which is not enabled */
2934 } else if (Index == This->maxConcurrentLights) {
2935 /* use bsf - Simply swap the new light and the BSF one */
2936 PLIGHTINFOEL *bsfNext = bsf->next;
2937 PLIGHTINFOEL *bsfPrev = bsf->prev;
2940 if (lightInfo->next != NULL) lightInfo->next->prev = bsf;
2941 if (bsf->prev != NULL) {
2942 bsf->prev->next = lightInfo;
2944 This->stateBlock->lights = lightInfo;
2947 /* If not side by side, lots of chains to update */
2948 if (bsf->next != lightInfo) {
2949 lightInfo->prev->next = bsf;
2950 bsf->next->prev = lightInfo;
2951 bsf->next = lightInfo->next;
2952 bsf->prev = lightInfo->prev;
2953 lightInfo->next = bsfNext;
2954 lightInfo->prev = bsfPrev;
2958 bsf->prev = lightInfo;
2959 bsf->next = lightInfo->next;
2960 lightInfo->next = bsf;
2961 lightInfo->prev = bsfPrev;
2966 glIndex = bsf->glIndex;
2968 lightInfo->glIndex = glIndex;
2969 lightInfo->lightEnabled = Enable;
2971 /* Finally set up the light in gl itself */
2972 TRACE("Replacing light which was set up at gl idx %d\n", lightInfo->glIndex);
2974 setup_light(iface, glIndex, lightInfo);
2975 glEnable(GL_LIGHT0 + glIndex);
2976 checkGLcall("glEnable GL_LIGHT0 new setup");
2979 /* If we reached the end of the allocated lights, with space in the
2980 gl lights, setup a new light */
2981 } else if (pos->glIndex == -1) {
2983 /* We reached the end of the allocated gl lights, so already
2984 know the index of the next one! */
2986 lightInfo->glIndex = glIndex;
2987 lightInfo->lightEnabled = Enable;
2989 /* In an ideal world, it's already in the right place */
2990 if (lightInfo->prev == NULL || lightInfo->prev->glIndex!=-1) {
2991 /* No need to move it */
2993 /* Remove this light from the list */
2994 lightInfo->prev->next = lightInfo->next;
2995 if (lightInfo->next != NULL) {
2996 lightInfo->next->prev = lightInfo->prev;
2999 /* Add in at appropriate place (inbetween prev and pos) */
3000 lightInfo->prev = prev;
3001 lightInfo->next = pos;
3003 This->stateBlock->lights = lightInfo;
3005 prev->next = lightInfo;
3008 pos->prev = lightInfo;
3012 /* Finally set up the light in gl itself */
3013 TRACE("Defining new light at gl idx %d\n", lightInfo->glIndex);
3015 setup_light(iface, glIndex, lightInfo);
3016 glEnable(GL_LIGHT0 + glIndex);
3017 checkGLcall("glEnable GL_LIGHT0 new setup");
3026 static HRESULT WINAPI IWineD3DDeviceImpl_GetLightEnable(IWineD3DDevice *iface, DWORD Index,BOOL* pEnable) {
3028 PLIGHTINFOEL *lightInfo = NULL;
3029 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3030 TRACE("(%p) : for idx(%d)\n", This, Index);
3032 /* Locate the light in the live lights */
3033 lightInfo = This->stateBlock->lights;
3034 while (lightInfo != NULL && lightInfo->OriginalIndex != Index) lightInfo = lightInfo->next;
3036 if (lightInfo == NULL) {
3037 TRACE("Light enabled state requested but light not defined\n");
3038 return WINED3DERR_INVALIDCALL;
3040 *pEnable = lightInfo->lightEnabled;
3045 * Get / Set Clip Planes
3047 static HRESULT WINAPI IWineD3DDeviceImpl_SetClipPlane(IWineD3DDevice *iface, DWORD Index, CONST float *pPlane) {
3048 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3049 TRACE("(%p) : for idx %d, %p\n", This, Index, pPlane);
3051 /* Validate Index */
3052 if (Index >= GL_LIMITS(clipplanes)) {
3053 TRACE("Application has requested clipplane this device doesn't support\n");
3054 return WINED3DERR_INVALIDCALL;
3057 This->updateStateBlock->changed.clipplane[Index] = TRUE;
3058 This->updateStateBlock->set.clipplane[Index] = TRUE;
3059 This->updateStateBlock->clipplane[Index][0] = pPlane[0];
3060 This->updateStateBlock->clipplane[Index][1] = pPlane[1];
3061 This->updateStateBlock->clipplane[Index][2] = pPlane[2];
3062 This->updateStateBlock->clipplane[Index][3] = pPlane[3];
3064 /* Handle recording of state blocks */
3065 if (This->isRecordingState) {
3066 TRACE("Recording... not performing anything\n");
3074 /* Clip Plane settings are affected by the model view in OpenGL, the View transform in direct3d */
3075 glMatrixMode(GL_MODELVIEW);
3077 glLoadMatrixf((float *) &This->stateBlock->transforms[WINED3DTS_VIEW].u.m[0][0]);
3079 TRACE("Clipplane [%f,%f,%f,%f]\n",
3080 This->updateStateBlock->clipplane[Index][0],
3081 This->updateStateBlock->clipplane[Index][1],
3082 This->updateStateBlock->clipplane[Index][2],
3083 This->updateStateBlock->clipplane[Index][3]);
3084 glClipPlane(GL_CLIP_PLANE0 + Index, This->updateStateBlock->clipplane[Index]);
3085 checkGLcall("glClipPlane");
3093 static HRESULT WINAPI IWineD3DDeviceImpl_GetClipPlane(IWineD3DDevice *iface, DWORD Index, float *pPlane) {
3094 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3095 TRACE("(%p) : for idx %d\n", This, Index);
3097 /* Validate Index */
3098 if (Index >= GL_LIMITS(clipplanes)) {
3099 TRACE("Application has requested clipplane this device doesn't support\n");
3100 return WINED3DERR_INVALIDCALL;
3103 pPlane[0] = This->stateBlock->clipplane[Index][0];
3104 pPlane[1] = This->stateBlock->clipplane[Index][1];
3105 pPlane[2] = This->stateBlock->clipplane[Index][2];
3106 pPlane[3] = This->stateBlock->clipplane[Index][3];
3111 * Get / Set Clip Plane Status
3112 * WARNING: This code relies on the fact that D3DCLIPSTATUS8 == D3DCLIPSTATUS9
3114 static HRESULT WINAPI IWineD3DDeviceImpl_SetClipStatus(IWineD3DDevice *iface, CONST WINED3DCLIPSTATUS* pClipStatus) {
3115 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3116 FIXME("(%p) : stub\n", This);
3117 if (NULL == pClipStatus) {
3118 return WINED3DERR_INVALIDCALL;
3120 This->updateStateBlock->clip_status.ClipUnion = pClipStatus->ClipUnion;
3121 This->updateStateBlock->clip_status.ClipIntersection = pClipStatus->ClipIntersection;
3125 static HRESULT WINAPI IWineD3DDeviceImpl_GetClipStatus(IWineD3DDevice *iface, WINED3DCLIPSTATUS* pClipStatus) {
3126 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3127 FIXME("(%p) : stub\n", This);
3128 if (NULL == pClipStatus) {
3129 return WINED3DERR_INVALIDCALL;
3131 pClipStatus->ClipUnion = This->updateStateBlock->clip_status.ClipUnion;
3132 pClipStatus->ClipIntersection = This->updateStateBlock->clip_status.ClipIntersection;
3137 * Get / Set Material
3139 static HRESULT WINAPI IWineD3DDeviceImpl_SetMaterial(IWineD3DDevice *iface, CONST WINED3DMATERIAL* pMaterial) {
3140 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3142 This->updateStateBlock->changed.material = TRUE;
3143 This->updateStateBlock->set.material = TRUE;
3144 memcpy(&This->updateStateBlock->material, pMaterial, sizeof(WINED3DMATERIAL));
3146 /* Handle recording of state blocks */
3147 if (This->isRecordingState) {
3148 TRACE("Recording... not performing anything\n");
3153 TRACE("(%p) : Diffuse (%f,%f,%f,%f)\n", This, pMaterial->Diffuse.r, pMaterial->Diffuse.g,
3154 pMaterial->Diffuse.b, pMaterial->Diffuse.a);
3155 TRACE("(%p) : Ambient (%f,%f,%f,%f)\n", This, pMaterial->Ambient.r, pMaterial->Ambient.g,
3156 pMaterial->Ambient.b, pMaterial->Ambient.a);
3157 TRACE("(%p) : Specular (%f,%f,%f,%f)\n", This, pMaterial->Specular.r, pMaterial->Specular.g,
3158 pMaterial->Specular.b, pMaterial->Specular.a);
3159 TRACE("(%p) : Emissive (%f,%f,%f,%f)\n", This, pMaterial->Emissive.r, pMaterial->Emissive.g,
3160 pMaterial->Emissive.b, pMaterial->Emissive.a);
3161 TRACE("(%p) : Power (%f)\n", This, pMaterial->Power);
3163 glMaterialfv(GL_FRONT_AND_BACK, GL_AMBIENT, (float*) &This->updateStateBlock->material.Ambient);
3164 checkGLcall("glMaterialfv(GL_AMBIENT)");
3165 glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, (float*) &This->updateStateBlock->material.Diffuse);
3166 checkGLcall("glMaterialfv(GL_DIFFUSE)");
3168 /* Only change material color if specular is enabled, otherwise it is set to black */
3169 if (This->stateBlock->renderState[WINED3DRS_SPECULARENABLE]) {
3170 glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, (float*) &This->updateStateBlock->material.Specular);
3171 checkGLcall("glMaterialfv(GL_SPECULAR");
3173 float black[4] = {0.0f, 0.0f, 0.0f, 0.0f};
3174 glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, &black[0]);
3175 checkGLcall("glMaterialfv(GL_SPECULAR");
3177 glMaterialfv(GL_FRONT_AND_BACK, GL_EMISSION, (float*) &This->updateStateBlock->material.Emissive);
3178 checkGLcall("glMaterialfv(GL_EMISSION)");
3179 glMaterialf(GL_FRONT_AND_BACK, GL_SHININESS, This->updateStateBlock->material.Power);
3180 checkGLcall("glMaterialf(GL_SHININESS");
3186 static HRESULT WINAPI IWineD3DDeviceImpl_GetMaterial(IWineD3DDevice *iface, WINED3DMATERIAL* pMaterial) {
3187 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3188 memcpy(pMaterial, &This->updateStateBlock->material, sizeof (WINED3DMATERIAL));
3189 TRACE("(%p) : Diffuse (%f,%f,%f,%f)\n", This, pMaterial->Diffuse.r, pMaterial->Diffuse.g,
3190 pMaterial->Diffuse.b, pMaterial->Diffuse.a);
3191 TRACE("(%p) : Ambient (%f,%f,%f,%f)\n", This, pMaterial->Ambient.r, pMaterial->Ambient.g,
3192 pMaterial->Ambient.b, pMaterial->Ambient.a);
3193 TRACE("(%p) : Specular (%f,%f,%f,%f)\n", This, pMaterial->Specular.r, pMaterial->Specular.g,
3194 pMaterial->Specular.b, pMaterial->Specular.a);
3195 TRACE("(%p) : Emissive (%f,%f,%f,%f)\n", This, pMaterial->Emissive.r, pMaterial->Emissive.g,
3196 pMaterial->Emissive.b, pMaterial->Emissive.a);
3197 TRACE("(%p) : Power (%f)\n", This, pMaterial->Power);
3205 static HRESULT WINAPI IWineD3DDeviceImpl_SetIndices(IWineD3DDevice *iface, IWineD3DIndexBuffer* pIndexData,
3206 UINT BaseVertexIndex) {
3207 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3208 IWineD3DIndexBuffer *oldIdxs;
3210 TRACE("(%p) : Setting to %p, base %d\n", This, pIndexData, BaseVertexIndex);
3211 oldIdxs = This->updateStateBlock->pIndexData;
3213 This->updateStateBlock->changed.indices = TRUE;
3214 This->updateStateBlock->set.indices = TRUE;
3215 This->updateStateBlock->pIndexData = pIndexData;
3216 This->updateStateBlock->baseVertexIndex = BaseVertexIndex;
3218 /* Handle recording of state blocks */
3219 if (This->isRecordingState) {
3220 TRACE("Recording... not performing anything\n");
3224 if (NULL != pIndexData) {
3225 IWineD3DIndexBuffer_AddRef(pIndexData);
3227 if (NULL != oldIdxs) {
3228 IWineD3DIndexBuffer_Release(oldIdxs);
3233 static HRESULT WINAPI IWineD3DDeviceImpl_GetIndices(IWineD3DDevice *iface, IWineD3DIndexBuffer** ppIndexData, UINT* pBaseVertexIndex) {
3234 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3236 *ppIndexData = This->stateBlock->pIndexData;
3238 /* up ref count on ppindexdata */
3240 IWineD3DIndexBuffer_AddRef(*ppIndexData);
3241 *pBaseVertexIndex = This->stateBlock->baseVertexIndex;
3242 TRACE("(%p) index data set to %p + %u\n", This, ppIndexData, This->stateBlock->baseVertexIndex);
3244 TRACE("(%p) No index data set\n", This);
3246 TRACE("Returning %p %d\n", *ppIndexData, *pBaseVertexIndex);
3252 * Get / Set Viewports
3254 static HRESULT WINAPI IWineD3DDeviceImpl_SetViewport(IWineD3DDevice *iface, CONST WINED3DVIEWPORT* pViewport) {
3255 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3257 TRACE("(%p)\n", This);
3258 This->updateStateBlock->changed.viewport = TRUE;
3259 This->updateStateBlock->set.viewport = TRUE;
3260 memcpy(&This->updateStateBlock->viewport, pViewport, sizeof(WINED3DVIEWPORT));
3262 /* Handle recording of state blocks */
3263 if (This->isRecordingState) {
3264 TRACE("Recording... not performing anything\n");
3267 This->viewport_changed = TRUE;
3271 TRACE("(%p) : x=%d, y=%d, wid=%d, hei=%d, minz=%f, maxz=%f\n", This,
3272 pViewport->X, pViewport->Y, pViewport->Width, pViewport->Height, pViewport->MinZ, pViewport->MaxZ);
3274 glDepthRange(pViewport->MinZ, pViewport->MaxZ);
3275 checkGLcall("glDepthRange");
3276 /* Note: GL requires lower left, DirectX supplies upper left */
3277 /* TODO: replace usage of renderTarget with context management */
3278 glViewport(pViewport->X,
3279 (((IWineD3DSurfaceImpl *)This->renderTarget)->currentDesc.Height - (pViewport->Y + pViewport->Height)),
3280 pViewport->Width, pViewport->Height);
3282 checkGLcall("glViewport");
3290 static HRESULT WINAPI IWineD3DDeviceImpl_GetViewport(IWineD3DDevice *iface, WINED3DVIEWPORT* pViewport) {
3291 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3292 TRACE("(%p)\n", This);
3293 memcpy(pViewport, &This->stateBlock->viewport, sizeof(WINED3DVIEWPORT));
3297 static void renderstate_stencil_twosided(
3298 IWineD3DDeviceImpl *This,
3305 GLint stencilPass ) {
3306 #if 0 /* Don't use OpenGL 2.0 calls for now */
3307 if(GL_EXTCALL(glStencilFuncSeparate) && GL_EXTCALL(glStencilOpSeparate)) {
3308 GL_EXTCALL(glStencilFuncSeparate(face, func, ref, mask));
3309 checkGLcall("glStencilFuncSeparate(...)");
3310 GL_EXTCALL(glStencilOpSeparate(face, stencilFail, depthFail, stencilPass));
3311 checkGLcall("glStencilOpSeparate(...)");
3315 if(GL_SUPPORT(EXT_STENCIL_TWO_SIDE)) {
3316 glEnable(GL_STENCIL_TEST_TWO_SIDE_EXT);
3317 checkGLcall("glEnable(GL_STENCIL_TEST_TWO_SIDE_EXT)");
3318 GL_EXTCALL(glActiveStencilFaceEXT(face));
3319 checkGLcall("glActiveStencilFaceEXT(...)");
3320 glStencilFunc(func, ref, mask);
3321 checkGLcall("glStencilFunc(...)");
3322 glStencilOp(stencilFail, depthFail, stencilPass);
3323 checkGLcall("glStencilOp(...)");
3324 } else if(GL_SUPPORT(ATI_SEPARATE_STENCIL)) {
3325 GL_EXTCALL(glStencilFuncSeparateATI(face, func, ref, mask));
3326 checkGLcall("glStencilFuncSeparateATI(...)");
3327 GL_EXTCALL(glStencilOpSeparateATI(face, stencilFail, depthFail, stencilPass));
3328 checkGLcall("glStencilOpSeparateATI(...)");
3330 ERR("Separate (two sided) stencil not supported on this version of opengl. Caps weren't honored?\n");
3334 static void renderstate_stencil(IWineD3DDeviceImpl *This, WINED3DRENDERSTATETYPE State, DWORD Value) {
3335 DWORD onesided_enable = FALSE;
3336 DWORD twosided_enable = FALSE;
3337 GLint func = GL_ALWAYS;
3338 GLint func_ccw = GL_ALWAYS;
3341 GLint stencilFail = GL_KEEP;
3342 GLint depthFail = GL_KEEP;
3343 GLint stencilPass = GL_KEEP;
3344 GLint stencilFail_ccw = GL_KEEP;
3345 GLint depthFail_ccw = GL_KEEP;
3346 GLint stencilPass_ccw = GL_KEEP;
3348 if( This->stateBlock->set.renderState[WINED3DRS_STENCILENABLE] )
3349 onesided_enable = This->stateBlock->renderState[WINED3DRS_STENCILENABLE];
3350 if( This->stateBlock->set.renderState[WINED3DRS_TWOSIDEDSTENCILMODE] )
3351 twosided_enable = This->stateBlock->renderState[WINED3DRS_TWOSIDEDSTENCILMODE];
3352 if( This->stateBlock->set.renderState[WINED3DRS_STENCILFUNC] )
3353 if( !( func = CompareFunc(This->stateBlock->renderState[WINED3DRS_STENCILFUNC]) ) )
3355 if( This->stateBlock->set.renderState[WINED3DRS_CCW_STENCILFUNC] )
3356 if( !( func_ccw = CompareFunc(This->stateBlock->renderState[WINED3DRS_CCW_STENCILFUNC]) ) )
3358 if( This->stateBlock->set.renderState[WINED3DRS_STENCILREF] )
3359 ref = This->stateBlock->renderState[WINED3DRS_STENCILREF];
3360 if( This->stateBlock->set.renderState[WINED3DRS_STENCILMASK] )
3361 mask = This->stateBlock->renderState[WINED3DRS_STENCILMASK];
3362 if( This->stateBlock->set.renderState[WINED3DRS_STENCILFAIL] )
3363 stencilFail = StencilOp(This->stateBlock->renderState[WINED3DRS_STENCILFAIL]);
3364 if( This->stateBlock->set.renderState[WINED3DRS_STENCILZFAIL] )
3365 depthFail = StencilOp(This->stateBlock->renderState[WINED3DRS_STENCILZFAIL]);
3366 if( This->stateBlock->set.renderState[WINED3DRS_STENCILPASS] )
3367 stencilPass = StencilOp(This->stateBlock->renderState[WINED3DRS_STENCILPASS]);
3368 if( This->stateBlock->set.renderState[WINED3DRS_CCW_STENCILFAIL] )
3369 stencilFail_ccw = StencilOp(This->stateBlock->renderState[WINED3DRS_CCW_STENCILFAIL]);
3370 if( This->stateBlock->set.renderState[WINED3DRS_CCW_STENCILZFAIL] )
3371 depthFail_ccw = StencilOp(This->stateBlock->renderState[WINED3DRS_CCW_STENCILZFAIL]);
3372 if( This->stateBlock->set.renderState[WINED3DRS_CCW_STENCILPASS] )
3373 stencilPass_ccw = StencilOp(This->stateBlock->renderState[WINED3DRS_CCW_STENCILPASS]);
3375 TRACE("(onesided %d, twosided %d, ref %x, mask %x, \
3376 GL_FRONT: func: %x, fail %x, zfail %x, zpass %x \
3377 GL_BACK: func: %x, fail %x, zfail %x, zpass %x )\n",
3378 onesided_enable, twosided_enable, ref, mask,
3379 func, stencilFail, depthFail, stencilPass,
3380 func_ccw, stencilFail_ccw, depthFail_ccw, stencilPass_ccw);
3382 if (twosided_enable) {
3383 renderstate_stencil_twosided(This, GL_FRONT, func, ref, mask, stencilFail, depthFail, stencilPass);
3384 renderstate_stencil_twosided(This, GL_BACK, func_ccw, ref, mask, stencilFail_ccw, depthFail_ccw, stencilPass_ccw);
3386 if (onesided_enable) {
3387 glEnable(GL_STENCIL_TEST);
3388 checkGLcall("glEnable GL_STENCIL_TEST");
3389 glStencilFunc(func, ref, mask);
3390 checkGLcall("glStencilFunc(...)");
3391 glStencilOp(stencilFail, depthFail, stencilPass);
3392 checkGLcall("glStencilOp(...)");
3394 glDisable(GL_STENCIL_TEST);
3395 checkGLcall("glDisable GL_STENCIL_TEST");
3401 * Get / Set Render States
3402 * TODO: Verify against dx9 definitions
3404 static HRESULT WINAPI IWineD3DDeviceImpl_SetRenderState(IWineD3DDevice *iface, WINED3DRENDERSTATETYPE State, DWORD Value) {
3406 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3407 DWORD OldValue = This->stateBlock->renderState[State];
3409 /* Simple way of referring to either a DWORD or a 4 byte float */
3415 TRACE("(%p)->state = %s(%d), value = %d\n", This, debug_d3drenderstate(State), State, Value);
3416 This->updateStateBlock->changed.renderState[State] = TRUE;
3417 This->updateStateBlock->set.renderState[State] = TRUE;
3418 This->updateStateBlock->renderState[State] = Value;
3420 /* Handle recording of state blocks */
3421 if (This->isRecordingState) {
3422 TRACE("Recording... not performing anything\n");
3429 case WINED3DRS_FILLMODE :
3430 switch ((WINED3DFILLMODE) Value) {
3431 case WINED3DFILL_POINT : glPolygonMode(GL_FRONT_AND_BACK, GL_POINT); break;
3432 case WINED3DFILL_WIREFRAME : glPolygonMode(GL_FRONT_AND_BACK, GL_LINE); break;
3433 case WINED3DFILL_SOLID : glPolygonMode(GL_FRONT_AND_BACK, GL_FILL); break;
3435 FIXME("Unrecognized WINED3DRS_FILLMODE value %d\n", Value);
3437 checkGLcall("glPolygonMode (fillmode)");
3440 case WINED3DRS_LIGHTING :
3442 glEnable(GL_LIGHTING);
3443 checkGLcall("glEnable GL_LIGHTING");
3445 glDisable(GL_LIGHTING);
3446 checkGLcall("glDisable GL_LIGHTING");
3450 case WINED3DRS_ZENABLE :
3451 switch ((WINED3DZBUFFERTYPE) Value) {
3452 case WINED3DZB_FALSE:
3453 glDisable(GL_DEPTH_TEST);
3454 checkGLcall("glDisable GL_DEPTH_TEST");
3456 case WINED3DZB_TRUE:
3457 glEnable(GL_DEPTH_TEST);
3458 checkGLcall("glEnable GL_DEPTH_TEST");
3460 case WINED3DZB_USEW:
3461 glEnable(GL_DEPTH_TEST);
3462 checkGLcall("glEnable GL_DEPTH_TEST");
3463 FIXME("W buffer is not well handled\n");
3466 FIXME("Unrecognized WINED3DZBUFFERTYPE value %d\n", Value);
3470 case WINED3DRS_CULLMODE :
3472 /* If we are culling "back faces with clockwise vertices" then
3473 set front faces to be counter clockwise and enable culling
3475 switch ((WINED3DCULL) Value) {
3476 case WINED3DCULL_NONE:
3477 glDisable(GL_CULL_FACE);
3478 checkGLcall("glDisable GL_CULL_FACE");
3480 case WINED3DCULL_CW:
3481 glEnable(GL_CULL_FACE);
3482 checkGLcall("glEnable GL_CULL_FACE");
3483 if (This->render_offscreen) {
3485 checkGLcall("glFrontFace GL_CW");
3487 glFrontFace(GL_CCW);
3488 checkGLcall("glFrontFace GL_CCW");
3490 glCullFace(GL_BACK);
3492 case WINED3DCULL_CCW:
3493 glEnable(GL_CULL_FACE);
3494 checkGLcall("glEnable GL_CULL_FACE");
3495 if (This->render_offscreen) {
3496 glFrontFace(GL_CCW);
3497 checkGLcall("glFrontFace GL_CCW");
3500 checkGLcall("glFrontFace GL_CW");
3502 glCullFace(GL_BACK);
3505 FIXME("Unrecognized/Unhandled WINED3DCULL value %d\n", Value);
3509 case WINED3DRS_SHADEMODE :
3510 switch ((WINED3DSHADEMODE) Value) {
3511 case WINED3DSHADE_FLAT:
3512 glShadeModel(GL_FLAT);
3513 checkGLcall("glShadeModel");
3515 case WINED3DSHADE_GOURAUD:
3516 glShadeModel(GL_SMOOTH);
3517 checkGLcall("glShadeModel");
3519 case WINED3DSHADE_PHONG:
3520 FIXME("WINED3DSHADE_PHONG isn't supported\n");
3523 FIXME("Unrecognized/Unhandled WINED3DSHADEMODE value %d\n", Value);
3527 case WINED3DRS_DITHERENABLE :
3529 glEnable(GL_DITHER);
3530 checkGLcall("glEnable GL_DITHER");
3532 glDisable(GL_DITHER);
3533 checkGLcall("glDisable GL_DITHER");
3537 case WINED3DRS_ZWRITEENABLE :
3540 checkGLcall("glDepthMask");
3543 checkGLcall("glDepthMask");
3547 case WINED3DRS_ZFUNC :
3549 int glParm = CompareFunc(Value);
3552 glDepthFunc(glParm);
3553 checkGLcall("glDepthFunc");
3558 case WINED3DRS_AMBIENT :
3561 D3DCOLORTOGLFLOAT4(Value, col);
3562 TRACE("Setting ambient to (%f,%f,%f,%f)\n", col[0], col[1], col[2], col[3]);
3563 glLightModelfv(GL_LIGHT_MODEL_AMBIENT, col);
3564 checkGLcall("glLightModel for MODEL_AMBIENT");
3569 case WINED3DRS_ALPHABLENDENABLE :
3572 checkGLcall("glEnable GL_BLEND");
3574 glDisable(GL_BLEND);
3575 checkGLcall("glDisable GL_BLEND");
3579 case WINED3DRS_SRCBLEND :
3580 case WINED3DRS_DESTBLEND :
3582 int newVal = GL_ZERO;
3584 case WINED3DBLEND_ZERO : newVal = GL_ZERO; break;
3585 case WINED3DBLEND_ONE : newVal = GL_ONE; break;
3586 case WINED3DBLEND_SRCCOLOR : newVal = GL_SRC_COLOR; break;
3587 case WINED3DBLEND_INVSRCCOLOR : newVal = GL_ONE_MINUS_SRC_COLOR; break;
3588 case WINED3DBLEND_SRCALPHA : newVal = GL_SRC_ALPHA; break;
3589 case WINED3DBLEND_INVSRCALPHA : newVal = GL_ONE_MINUS_SRC_ALPHA; break;
3590 case WINED3DBLEND_DESTALPHA : newVal = GL_DST_ALPHA; break;
3591 case WINED3DBLEND_INVDESTALPHA : newVal = GL_ONE_MINUS_DST_ALPHA; break;
3592 case WINED3DBLEND_DESTCOLOR : newVal = GL_DST_COLOR; break;
3593 case WINED3DBLEND_INVDESTCOLOR : newVal = GL_ONE_MINUS_DST_COLOR; break;
3594 case WINED3DBLEND_SRCALPHASAT : newVal = GL_SRC_ALPHA_SATURATE; break;
3596 case WINED3DBLEND_BOTHSRCALPHA : newVal = GL_SRC_ALPHA;
3597 This->srcBlend = newVal;
3598 This->dstBlend = newVal;
3601 case WINED3DBLEND_BOTHINVSRCALPHA : newVal = GL_ONE_MINUS_SRC_ALPHA;
3602 This->srcBlend = newVal;
3603 This->dstBlend = newVal;
3605 case WINED3DBLEND_BLENDFACTOR : newVal = GL_CONSTANT_COLOR; break;
3606 case WINED3DBLEND_INVBLENDFACTOR : newVal = GL_ONE_MINUS_CONSTANT_COLOR; break;
3608 FIXME("Unrecognized src/dest blend value %d (%d)\n", Value, State);
3611 if (State == WINED3DRS_SRCBLEND) This->srcBlend = newVal;
3612 if (State == WINED3DRS_DESTBLEND) This->dstBlend = newVal;
3613 TRACE("glBlendFunc src=%x, dst=%x\n", This->srcBlend, This->dstBlend);
3614 glBlendFunc(This->srcBlend, This->dstBlend);
3616 checkGLcall("glBlendFunc");
3620 case WINED3DRS_ALPHATESTENABLE :
3621 case WINED3DRS_ALPHAFUNC :
3622 case WINED3DRS_ALPHAREF :
3623 case WINED3DRS_COLORKEYENABLE :
3627 BOOL enable_ckey = FALSE;
3629 IWineD3DSurfaceImpl *surf;
3631 /* Find out if the texture on the first stage has a ckey set */
3632 if(This->stateBlock->textures[0]) {
3633 surf = (IWineD3DSurfaceImpl *) ((IWineD3DTextureImpl *)This->stateBlock->textures[0])->surfaces[0];
3634 if(surf->CKeyFlags & DDSD_CKSRCBLT) enable_ckey = TRUE;
3637 if (This->stateBlock->renderState[WINED3DRS_ALPHATESTENABLE] ||
3638 (This->stateBlock->renderState[WINED3DRS_COLORKEYENABLE] && enable_ckey)) {
3639 glEnable(GL_ALPHA_TEST);
3640 checkGLcall("glEnable GL_ALPHA_TEST");
3642 glDisable(GL_ALPHA_TEST);
3643 checkGLcall("glDisable GL_ALPHA_TEST");
3644 /* Alpha test is disabled, don't bother setting the params - it will happen on the next
3650 if(This->stateBlock->renderState[WINED3DRS_COLORKEYENABLE] && enable_ckey) {
3651 glParm = GL_NOTEQUAL;
3654 ref = ((float) This->stateBlock->renderState[WINED3DRS_ALPHAREF]) / 255.0f;
3655 glParm = CompareFunc(This->stateBlock->renderState[WINED3DRS_ALPHAFUNC]);
3658 This->alphafunc = glParm;
3659 glAlphaFunc(glParm, ref);
3660 checkGLcall("glAlphaFunc");
3665 case WINED3DRS_CLIPPLANEENABLE :
3666 case WINED3DRS_CLIPPING :
3668 /* Ensure we only do the changed clip planes */
3669 DWORD enable = 0xFFFFFFFF;
3670 DWORD disable = 0x00000000;
3672 /* If enabling / disabling all */
3673 if (State == WINED3DRS_CLIPPING) {
3675 enable = This->stateBlock->renderState[WINED3DRS_CLIPPLANEENABLE];
3678 disable = This->stateBlock->renderState[WINED3DRS_CLIPPLANEENABLE];
3682 enable = Value & ~OldValue;
3683 disable = ~Value & OldValue;
3686 if (enable & WINED3DCLIPPLANE0) { glEnable(GL_CLIP_PLANE0); checkGLcall("glEnable(clip plane 0)"); }
3687 if (enable & WINED3DCLIPPLANE1) { glEnable(GL_CLIP_PLANE1); checkGLcall("glEnable(clip plane 1)"); }
3688 if (enable & WINED3DCLIPPLANE2) { glEnable(GL_CLIP_PLANE2); checkGLcall("glEnable(clip plane 2)"); }
3689 if (enable & WINED3DCLIPPLANE3) { glEnable(GL_CLIP_PLANE3); checkGLcall("glEnable(clip plane 3)"); }
3690 if (enable & WINED3DCLIPPLANE4) { glEnable(GL_CLIP_PLANE4); checkGLcall("glEnable(clip plane 4)"); }
3691 if (enable & WINED3DCLIPPLANE5) { glEnable(GL_CLIP_PLANE5); checkGLcall("glEnable(clip plane 5)"); }
3693 if (disable & WINED3DCLIPPLANE0) { glDisable(GL_CLIP_PLANE0); checkGLcall("glDisable(clip plane 0)"); }
3694 if (disable & WINED3DCLIPPLANE1) { glDisable(GL_CLIP_PLANE1); checkGLcall("glDisable(clip plane 1)"); }
3695 if (disable & WINED3DCLIPPLANE2) { glDisable(GL_CLIP_PLANE2); checkGLcall("glDisable(clip plane 2)"); }
3696 if (disable & WINED3DCLIPPLANE3) { glDisable(GL_CLIP_PLANE3); checkGLcall("glDisable(clip plane 3)"); }
3697 if (disable & WINED3DCLIPPLANE4) { glDisable(GL_CLIP_PLANE4); checkGLcall("glDisable(clip plane 4)"); }
3698 if (disable & WINED3DCLIPPLANE5) { glDisable(GL_CLIP_PLANE5); checkGLcall("glDisable(clip plane 5)"); }
3700 /** update clipping status */
3702 This->stateBlock->clip_status.ClipUnion = 0;
3703 This->stateBlock->clip_status.ClipIntersection = 0xFFFFFFFF;
3705 This->stateBlock->clip_status.ClipUnion = 0;
3706 This->stateBlock->clip_status.ClipIntersection = 0;
3711 case WINED3DRS_BLENDOP :
3713 int glParm = GL_FUNC_ADD;
3715 switch ((WINED3DBLENDOP) Value) {
3716 case WINED3DBLENDOP_ADD : glParm = GL_FUNC_ADD; break;
3717 case WINED3DBLENDOP_SUBTRACT : glParm = GL_FUNC_SUBTRACT; break;
3718 case WINED3DBLENDOP_REVSUBTRACT : glParm = GL_FUNC_REVERSE_SUBTRACT; break;
3719 case WINED3DBLENDOP_MIN : glParm = GL_MIN; break;
3720 case WINED3DBLENDOP_MAX : glParm = GL_MAX; break;
3722 FIXME("Unrecognized/Unhandled WINED3DBLENDOP value %d\n", Value);
3725 if(GL_SUPPORT(EXT_BLEND_MINMAX)) {
3726 TRACE("glBlendEquation(%x)\n", glParm);
3727 GL_EXTCALL(glBlendEquation(glParm));
3728 checkGLcall("glBlendEquation");
3730 WARN("Unsupported in local OpenGL implementation: glBlendEquation\n");
3735 case WINED3DRS_TEXTUREFACTOR :
3739 /* Note the texture color applies to all textures whereas
3740 GL_TEXTURE_ENV_COLOR applies to active only */
3742 D3DCOLORTOGLFLOAT4(Value, col);
3744 if (!GL_SUPPORT(NV_REGISTER_COMBINERS)) {
3745 /* And now the default texture color as well */
3746 for (i = 0; i < GL_LIMITS(texture_stages); i++) {
3747 /* Note the WINED3DRS value applies to all textures, but GL has one
3748 per texture, so apply it now ready to be used! */
3749 if (GL_SUPPORT(ARB_MULTITEXTURE)) {
3750 GL_EXTCALL(glActiveTextureARB(GL_TEXTURE0_ARB + i));
3751 checkGLcall("glActiveTextureARB");
3753 FIXME("Program using multiple concurrent textures which this opengl implementation doesn't support\n");
3756 glTexEnvfv(GL_TEXTURE_ENV, GL_TEXTURE_ENV_COLOR, &col[0]);
3757 checkGLcall("glTexEnvfv(GL_TEXTURE_ENV, GL_TEXTURE_ENV_COLOR, color);");
3763 case WINED3DRS_SPECULARENABLE :
3765 /* Originally this used glLightModeli(GL_LIGHT_MODEL_COLOR_CONTROL,GL_SEPARATE_SPECULAR_COLOR)
3766 and (GL_LIGHT_MODEL_COLOR_CONTROL,GL_SINGLE_COLOR) to swap between enabled/disabled
3767 specular color. This is wrong:
3768 Separate specular color means the specular colour is maintained separately, whereas
3769 single color means it is merged in. However in both cases they are being used to
3771 To disable specular color, set it explicitly to black and turn off GL_COLOR_SUM_EXT
3772 NOTE: If not supported don't give FIXMEs the impact is really minimal and very few people are
3776 * If register combiners are enabled, enabling / disabling GL_COLOR_SUM has no effect.
3777 * Instead, we need to setup the FinalCombiner properly.
3779 * The default setup for the FinalCombiner is:
3781 * <variable> <input> <mapping> <usage>
3782 * GL_VARIABLE_A_NV GL_FOG, GL_UNSIGNED_IDENTITY_NV GL_ALPHA
3783 * GL_VARIABLE_B_NV GL_SPARE0_PLUS_SECONDARY_COLOR_NV GL_UNSIGNED_IDENTITY_NV GL_RGB
3784 * GL_VARIABLE_C_NV GL_FOG GL_UNSIGNED_IDENTITY_NV GL_RGB
3785 * GL_VARIABLE_D_NV GL_ZERO GL_UNSIGNED_IDENTITY_NV GL_RGB
3786 * GL_VARIABLE_E_NV GL_ZERO GL_UNSIGNED_IDENTITY_NV GL_RGB
3787 * GL_VARIABLE_F_NV GL_ZERO GL_UNSIGNED_IDENTITY_NV GL_RGB
3788 * GL_VARIABLE_G_NV GL_SPARE0_NV GL_UNSIGNED_IDENTITY_NV GL_ALPHA
3790 * That's pretty much fine as it is, except for variable B, which needs to take
3791 * either GL_SPARE0_PLUS_SECONDARY_COLOR_NV or GL_SPARE0_NV, depending on
3792 * whether WINED3DRS_SPECULARENABLE is enabled or not.
3796 glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, (float*) &This->updateStateBlock->material.Specular);
3797 checkGLcall("glMaterialfv");
3798 if (GL_SUPPORT(EXT_SECONDARY_COLOR)) {
3799 glEnable(GL_COLOR_SUM_EXT);
3801 TRACE("Specular colors cannot be enabled in this version of opengl\n");
3803 checkGLcall("glEnable(GL_COLOR_SUM)");
3805 if (GL_SUPPORT(NV_REGISTER_COMBINERS)) {
3806 GL_EXTCALL(glFinalCombinerInputNV(GL_VARIABLE_B_NV, GL_SPARE0_PLUS_SECONDARY_COLOR_NV, GL_UNSIGNED_IDENTITY_NV, GL_RGB));
3807 checkGLcall("glFinalCombinerInputNV()");
3810 float black[4] = {0.0f, 0.0f, 0.0f, 0.0f};
3812 /* for the case of enabled lighting: */
3813 glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, &black[0]);
3814 checkGLcall("glMaterialfv");
3816 /* for the case of disabled lighting: */
3817 if (GL_SUPPORT(EXT_SECONDARY_COLOR)) {
3818 glDisable(GL_COLOR_SUM_EXT);
3820 TRACE("Specular colors cannot be disabled in this version of opengl\n");
3822 checkGLcall("glDisable(GL_COLOR_SUM)");
3824 if (GL_SUPPORT(NV_REGISTER_COMBINERS)) {
3825 GL_EXTCALL(glFinalCombinerInputNV(GL_VARIABLE_B_NV, GL_SPARE0_NV, GL_UNSIGNED_IDENTITY_NV, GL_RGB));
3826 checkGLcall("glFinalCombinerInputNV()");
3832 case WINED3DRS_STENCILENABLE :
3833 case WINED3DRS_TWOSIDEDSTENCILMODE :
3834 case WINED3DRS_STENCILFUNC :
3835 case WINED3DRS_CCW_STENCILFUNC :
3836 case WINED3DRS_STENCILREF :
3837 case WINED3DRS_STENCILMASK :
3838 case WINED3DRS_STENCILFAIL :
3839 case WINED3DRS_STENCILZFAIL :
3840 case WINED3DRS_STENCILPASS :
3841 case WINED3DRS_CCW_STENCILFAIL :
3842 case WINED3DRS_CCW_STENCILZFAIL :
3843 case WINED3DRS_CCW_STENCILPASS :
3844 renderstate_stencil(This, State, Value);
3846 case WINED3DRS_STENCILWRITEMASK :
3848 glStencilMask(Value);
3849 TRACE("glStencilMask(%u)\n", Value);
3850 checkGLcall("glStencilMask");
3854 case WINED3DRS_FOGENABLE :
3858 checkGLcall("glEnable GL_FOG");
3861 checkGLcall("glDisable GL_FOG");
3866 case WINED3DRS_RANGEFOGENABLE :
3869 TRACE("Enabled RANGEFOG\n");
3871 TRACE("Disabled RANGEFOG\n");
3876 case WINED3DRS_FOGCOLOR :
3879 D3DCOLORTOGLFLOAT4(Value, col);
3880 /* Set the default alpha blend color */
3881 glFogfv(GL_FOG_COLOR, &col[0]);
3882 checkGLcall("glFog GL_FOG_COLOR");
3886 case WINED3DRS_FOGTABLEMODE :
3887 case WINED3DRS_FOGVERTEXMODE :
3889 /* 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." */
3890 if(This->stateBlock->renderState[WINED3DRS_FOGTABLEMODE] == WINED3DFOG_NONE) {
3891 glHint(GL_FOG_HINT, GL_FASTEST);
3892 checkGLcall("glHint(GL_FOG_HINT, GL_FASTEST)");
3893 switch (This->stateBlock->renderState[WINED3DRS_FOGVERTEXMODE]) {
3894 /* Processed vertices have their fog factor stored in the specular value. Fall too the none case.
3895 * If we are drawing untransformed vertices atm, d3ddevice_set_ortho will update the fog
3897 case WINED3DFOG_EXP: {
3898 if(!This->last_was_rhw) {
3899 glFogi(GL_FOG_MODE, GL_EXP);
3900 checkGLcall("glFogi(GL_FOG_MODE, GL_EXP");
3901 if(GL_SUPPORT(EXT_FOG_COORD)) {
3902 glFogi(GL_FOG_COORDINATE_SOURCE_EXT, GL_FRAGMENT_DEPTH_EXT);
3903 checkGLcall("glFogi(GL_FOG_COORDINATE_SOURCE_EXT, GL_FRAGMENT_DEPTH_EXT");
3904 IWineD3DDevice_SetRenderState(iface, WINED3DRS_FOGSTART, This->stateBlock->renderState[WINED3DRS_FOGSTART]);
3905 IWineD3DDevice_SetRenderState(iface, WINED3DRS_FOGEND, This->stateBlock->renderState[WINED3DRS_FOGEND]);
3910 case WINED3DFOG_EXP2: {
3911 if(!This->last_was_rhw) {
3912 glFogi(GL_FOG_MODE, GL_EXP2);
3913 checkGLcall("glFogi(GL_FOG_MODE, GL_EXP2");
3914 if(GL_SUPPORT(EXT_FOG_COORD)) {
3915 glFogi(GL_FOG_COORDINATE_SOURCE_EXT, GL_FRAGMENT_DEPTH_EXT);
3916 checkGLcall("glFogi(GL_FOG_COORDINATE_SOURCE_EXT, GL_FRAGMENT_DEPTH_EXT");
3917 IWineD3DDevice_SetRenderState(iface, WINED3DRS_FOGSTART, This->stateBlock->renderState[WINED3DRS_FOGSTART]);
3918 IWineD3DDevice_SetRenderState(iface, WINED3DRS_FOGEND, This->stateBlock->renderState[WINED3DRS_FOGEND]);
3923 case WINED3DFOG_LINEAR: {
3924 if(!This->last_was_rhw) {
3925 glFogi(GL_FOG_MODE, GL_LINEAR);
3926 checkGLcall("glFogi(GL_FOG_MODE, GL_LINEAR");
3927 if(GL_SUPPORT(EXT_FOG_COORD)) {
3928 glFogi(GL_FOG_COORDINATE_SOURCE_EXT, GL_FRAGMENT_DEPTH_EXT);
3929 checkGLcall("glFogi(GL_FOG_COORDINATE_SOURCE_EXT, GL_FRAGMENT_DEPTH_EXT");
3930 IWineD3DDevice_SetRenderState(iface, WINED3DRS_FOGSTART, This->stateBlock->renderState[WINED3DRS_FOGSTART]);
3931 IWineD3DDevice_SetRenderState(iface, WINED3DRS_FOGEND, This->stateBlock->renderState[WINED3DRS_FOGEND]);
3936 case WINED3DFOG_NONE: {
3937 /* Both are none? According to msdn the alpha channel of the specular
3938 * color contains a fog factor. Set it in drawStridedSlow.
3939 * Same happens with Vertexfog on transformed vertices
3941 if(GL_SUPPORT(EXT_FOG_COORD)) {
3942 glFogi(GL_FOG_COORDINATE_SOURCE_EXT, GL_FOG_COORDINATE_EXT);
3943 checkGLcall("glFogi(GL_FOG_COORDINATE_SOURCE_EXT, GL_FOG_COORDINATE_EXT)\n");
3944 glFogi(GL_FOG_MODE, GL_LINEAR);
3945 checkGLcall("glFogi(GL_FOG_MODE, GL_LINEAR)");
3946 glFogf(GL_FOG_START, (float) 0xff);
3947 checkGLcall("glFogfv GL_FOG_START");
3948 glFogf(GL_FOG_END, 0.0);
3949 checkGLcall("glFogfv GL_FOG_END");
3951 /* Disable GL fog, handle this in software in drawStridedSlow */
3953 checkGLcall("glDisable(GL_FOG)");
3957 default: FIXME("Unexpected WINED3DRS_FOGVERTEXMODE %d\n", This->stateBlock->renderState[WINED3DRS_FOGVERTEXMODE]);
3960 glHint(GL_FOG_HINT, GL_NICEST);
3961 checkGLcall("glHint(GL_FOG_HINT, GL_NICEST)");
3962 switch (This->stateBlock->renderState[WINED3DRS_FOGTABLEMODE]) {
3963 case WINED3DFOG_EXP:
3964 glFogi(GL_FOG_MODE, GL_EXP);
3965 checkGLcall("glFogi(GL_FOG_MODE, GL_EXP");
3966 if(GL_SUPPORT(EXT_FOG_COORD)) {
3967 glFogi(GL_FOG_COORDINATE_SOURCE_EXT, GL_FRAGMENT_DEPTH_EXT);
3968 checkGLcall("glFogi(GL_FOG_COORDINATE_SOURCE_EXT, GL_FRAGMENT_DEPTH_EXT");
3969 IWineD3DDevice_SetRenderState(iface, WINED3DRS_FOGSTART, This->stateBlock->renderState[WINED3DRS_FOGSTART]);
3970 IWineD3DDevice_SetRenderState(iface, WINED3DRS_FOGEND, This->stateBlock->renderState[WINED3DRS_FOGEND]);
3973 case WINED3DFOG_EXP2:
3974 glFogi(GL_FOG_MODE, GL_EXP2);
3975 checkGLcall("glFogi(GL_FOG_MODE, GL_EXP2");
3976 if(GL_SUPPORT(EXT_FOG_COORD)) {
3977 glFogi(GL_FOG_COORDINATE_SOURCE_EXT, GL_FRAGMENT_DEPTH_EXT);
3978 checkGLcall("glFogi(GL_FOG_COORDINATE_SOURCE_EXT, GL_FRAGMENT_DEPTH_EXT");
3979 IWineD3DDevice_SetRenderState(iface, WINED3DRS_FOGSTART, This->stateBlock->renderState[WINED3DRS_FOGSTART]);
3980 IWineD3DDevice_SetRenderState(iface, WINED3DRS_FOGEND, This->stateBlock->renderState[WINED3DRS_FOGEND]);
3983 case WINED3DFOG_LINEAR:
3984 glFogi(GL_FOG_MODE, GL_LINEAR);
3985 checkGLcall("glFogi(GL_FOG_MODE, GL_LINEAR");
3986 if(GL_SUPPORT(EXT_FOG_COORD)) {
3987 glFogi(GL_FOG_COORDINATE_SOURCE_EXT, GL_FRAGMENT_DEPTH_EXT);
3988 checkGLcall("glFogi(GL_FOG_COORDINATE_SOURCE_EXT, GL_FRAGMENT_DEPTH_EXT");
3989 IWineD3DDevice_SetRenderState(iface, WINED3DRS_FOGSTART, This->stateBlock->renderState[WINED3DRS_FOGSTART]);
3990 IWineD3DDevice_SetRenderState(iface, WINED3DRS_FOGEND, This->stateBlock->renderState[WINED3DRS_FOGEND]);
3993 case WINED3DFOG_NONE:
3994 default: /* Won't happen */
3995 FIXME("Unexpected WINED3DRS_FOGTABLEMODE %d\n", This->stateBlock->renderState[WINED3DRS_FOGTABLEMODE]);
3998 if (GL_SUPPORT(NV_FOG_DISTANCE)) {
3999 glFogi(GL_FOG_DISTANCE_MODE_NV, GL_EYE_PLANE_ABSOLUTE_NV);
4004 case WINED3DRS_FOGSTART :
4007 glFogfv(GL_FOG_START, &tmpvalue.f);
4008 checkGLcall("glFogf(GL_FOG_START, (float) Value)");
4009 TRACE("Fog Start == %f\n", tmpvalue.f);
4013 case WINED3DRS_FOGEND :
4016 glFogfv(GL_FOG_END, &tmpvalue.f);
4017 checkGLcall("glFogf(GL_FOG_END, (float) Value)");
4018 TRACE("Fog End == %f\n", tmpvalue.f);
4022 case WINED3DRS_FOGDENSITY :
4025 glFogfv(GL_FOG_DENSITY, &tmpvalue.f);
4026 checkGLcall("glFogf(GL_FOG_DENSITY, (float) Value)");
4030 case WINED3DRS_VERTEXBLEND :
4032 This->updateStateBlock->vertex_blend = (WINED3DVERTEXBLENDFLAGS) Value;
4033 TRACE("Vertex Blending state to %d\n", Value);
4037 case WINED3DRS_TWEENFACTOR :
4040 This->updateStateBlock->tween_factor = tmpvalue.f;
4041 TRACE("Vertex Blending Tween Factor to %f\n", This->updateStateBlock->tween_factor);
4045 case WINED3DRS_INDEXEDVERTEXBLENDENABLE :
4047 TRACE("Indexed Vertex Blend Enable to %u\n", (BOOL) Value);
4051 case WINED3DRS_COLORVERTEX :
4052 case WINED3DRS_DIFFUSEMATERIALSOURCE :
4053 case WINED3DRS_SPECULARMATERIALSOURCE :
4054 case WINED3DRS_AMBIENTMATERIALSOURCE :
4055 case WINED3DRS_EMISSIVEMATERIALSOURCE :
4057 GLenum Parm = GL_AMBIENT_AND_DIFFUSE;
4059 if (This->stateBlock->renderState[WINED3DRS_COLORVERTEX]) {
4060 TRACE("diff %d, amb %d, emis %d, spec %d\n",
4061 This->stateBlock->renderState[WINED3DRS_DIFFUSEMATERIALSOURCE],
4062 This->stateBlock->renderState[WINED3DRS_AMBIENTMATERIALSOURCE],
4063 This->stateBlock->renderState[WINED3DRS_EMISSIVEMATERIALSOURCE],
4064 This->stateBlock->renderState[WINED3DRS_SPECULARMATERIALSOURCE]);
4066 if (This->stateBlock->renderState[WINED3DRS_DIFFUSEMATERIALSOURCE] == WINED3DMCS_COLOR1) {
4067 if (This->stateBlock->renderState[WINED3DRS_AMBIENTMATERIALSOURCE] == WINED3DMCS_COLOR1) {
4068 Parm = GL_AMBIENT_AND_DIFFUSE;
4072 } else if (This->stateBlock->renderState[WINED3DRS_AMBIENTMATERIALSOURCE] == WINED3DMCS_COLOR1) {
4074 } else if (This->stateBlock->renderState[WINED3DRS_EMISSIVEMATERIALSOURCE] == WINED3DMCS_COLOR1) {
4076 } else if (This->stateBlock->renderState[WINED3DRS_SPECULARMATERIALSOURCE] == WINED3DMCS_COLOR1) {
4083 if (This->tracking_color != DISABLED_TRACKING) This->tracking_color = NEEDS_DISABLE;
4085 This->tracking_color = NEEDS_TRACKING;
4086 This->tracking_parm = Parm;
4090 if (This->tracking_color != DISABLED_TRACKING) This->tracking_color = NEEDS_DISABLE;
4095 case WINED3DRS_LINEPATTERN :
4099 WINED3DLINEPATTERN lp;
4101 tmppattern.d = Value;
4103 TRACE("Line pattern: repeat %d bits %x\n", tmppattern.lp.wRepeatFactor, tmppattern.lp.wLinePattern);
4105 if (tmppattern.lp.wRepeatFactor) {
4106 glLineStipple(tmppattern.lp.wRepeatFactor, tmppattern.lp.wLinePattern);
4107 checkGLcall("glLineStipple(repeat, linepattern)");
4108 glEnable(GL_LINE_STIPPLE);
4109 checkGLcall("glEnable(GL_LINE_STIPPLE);");
4111 glDisable(GL_LINE_STIPPLE);
4112 checkGLcall("glDisable(GL_LINE_STIPPLE);");
4117 case WINED3DRS_ZBIAS : /* D3D8 only */
4121 TRACE("ZBias value %f\n", tmpvalue.f);
4122 glPolygonOffset(0, -tmpvalue.f);
4123 checkGLcall("glPolygonOffset(0, -Value)");
4124 glEnable(GL_POLYGON_OFFSET_FILL);
4125 checkGLcall("glEnable(GL_POLYGON_OFFSET_FILL);");
4126 glEnable(GL_POLYGON_OFFSET_LINE);
4127 checkGLcall("glEnable(GL_POLYGON_OFFSET_LINE);");
4128 glEnable(GL_POLYGON_OFFSET_POINT);
4129 checkGLcall("glEnable(GL_POLYGON_OFFSET_POINT);");
4131 glDisable(GL_POLYGON_OFFSET_FILL);
4132 checkGLcall("glDisable(GL_POLYGON_OFFSET_FILL);");
4133 glDisable(GL_POLYGON_OFFSET_LINE);
4134 checkGLcall("glDisable(GL_POLYGON_OFFSET_LINE);");
4135 glDisable(GL_POLYGON_OFFSET_POINT);
4136 checkGLcall("glDisable(GL_POLYGON_OFFSET_POINT);");
4141 case WINED3DRS_NORMALIZENORMALS :
4143 glEnable(GL_NORMALIZE);
4144 checkGLcall("glEnable(GL_NORMALIZE);");
4146 glDisable(GL_NORMALIZE);
4147 checkGLcall("glDisable(GL_NORMALIZE);");
4151 case WINED3DRS_POINTSIZE :
4152 /* FIXME: check that pointSize isn't outside glGetFloatv( GL_POINT_SIZE_MAX_ARB, &maxSize ); or -ve */
4154 TRACE("Set point size to %f\n", tmpvalue.f);
4155 glPointSize(tmpvalue.f);
4156 checkGLcall("glPointSize(...);");
4159 case WINED3DRS_POINTSIZE_MIN :
4160 if (GL_SUPPORT(EXT_POINT_PARAMETERS)) {
4162 GL_EXTCALL(glPointParameterfEXT)(GL_POINT_SIZE_MIN_EXT, tmpvalue.f);
4163 checkGLcall("glPointParameterfEXT(...);");
4165 FIXME("WINED3DRS_POINTSIZE_MIN not supported on this opengl\n");
4169 case WINED3DRS_POINTSIZE_MAX :
4170 if (GL_SUPPORT(EXT_POINT_PARAMETERS)) {
4172 GL_EXTCALL(glPointParameterfEXT)(GL_POINT_SIZE_MAX_EXT, tmpvalue.f);
4173 checkGLcall("glPointParameterfEXT(...);");
4175 FIXME("WINED3DRS_POINTSIZE_MAX not supported on this opengl\n");
4179 case WINED3DRS_POINTSCALE_A :
4180 case WINED3DRS_POINTSCALE_B :
4181 case WINED3DRS_POINTSCALE_C :
4182 case WINED3DRS_POINTSCALEENABLE :
4185 * POINTSCALEENABLE controls how point size value is treated. If set to
4186 * true, the point size is scaled with respect to height of viewport.
4187 * When set to false point size is in pixels.
4189 * http://msdn.microsoft.com/library/en-us/directx9_c/point_sprites.asp
4192 /* Default values */
4193 GLfloat att[3] = {1.0f, 0.0f, 0.0f};
4196 * Minimum valid point size for OpenGL is 1.0f. For Direct3D it is 0.0f.
4197 * This means that OpenGL will clamp really small point sizes to 1.0f.
4198 * To correct for this we need to multiply by the scale factor when sizes
4199 * are less than 1.0f. scale_factor = 1.0f / point_size.
4201 GLfloat pointSize = *((float*)&This->stateBlock->renderState[WINED3DRS_POINTSIZE]);
4202 if(pointSize > 0.0f) {
4203 GLfloat scaleFactor;
4205 if(pointSize < 1.0f) {
4206 scaleFactor = pointSize * pointSize;
4211 if(This->stateBlock->renderState[WINED3DRS_POINTSCALEENABLE]) {
4212 att[0] = *((float*)&This->stateBlock->renderState[WINED3DRS_POINTSCALE_A]) /
4213 (This->stateBlock->viewport.Height * This->stateBlock->viewport.Height * scaleFactor);
4214 att[1] = *((float*)&This->stateBlock->renderState[WINED3DRS_POINTSCALE_B]) /
4215 (This->stateBlock->viewport.Height * This->stateBlock->viewport.Height * scaleFactor);
4216 att[2] = *((float*)&This->stateBlock->renderState[WINED3DRS_POINTSCALE_C]) /
4217 (This->stateBlock->viewport.Height * This->stateBlock->viewport.Height * scaleFactor);
4221 if(GL_SUPPORT(ARB_POINT_PARAMETERS)) {
4222 GL_EXTCALL(glPointParameterfvARB)(GL_POINT_DISTANCE_ATTENUATION_ARB, att);
4223 checkGLcall("glPointParameterfvARB(GL_DISTANCE_ATTENUATION_ARB, ...");
4225 else if(GL_SUPPORT(EXT_POINT_PARAMETERS)) {
4226 GL_EXTCALL(glPointParameterfvEXT)(GL_DISTANCE_ATTENUATION_EXT, att);
4227 checkGLcall("glPointParameterfvEXT(GL_DISTANCE_ATTENUATION_EXT, ...");
4229 TRACE("POINT_PARAMETERS not supported in this version of opengl\n");
4233 case WINED3DRS_COLORWRITEENABLE :
4235 TRACE("Color mask: r(%d) g(%d) b(%d) a(%d)\n",
4236 Value & WINED3DCOLORWRITEENABLE_RED ? 1 : 0,
4237 Value & WINED3DCOLORWRITEENABLE_GREEN ? 1 : 0,
4238 Value & WINED3DCOLORWRITEENABLE_BLUE ? 1 : 0,
4239 Value & WINED3DCOLORWRITEENABLE_ALPHA ? 1 : 0);
4240 glColorMask(Value & WINED3DCOLORWRITEENABLE_RED ? GL_TRUE : GL_FALSE,
4241 Value & WINED3DCOLORWRITEENABLE_GREEN ? GL_TRUE : GL_FALSE,
4242 Value & WINED3DCOLORWRITEENABLE_BLUE ? GL_TRUE : GL_FALSE,
4243 Value & WINED3DCOLORWRITEENABLE_ALPHA ? GL_TRUE : GL_FALSE);
4244 checkGLcall("glColorMask(...)");
4248 case WINED3DRS_LOCALVIEWER :
4250 GLint state = (Value) ? 1 : 0;
4251 TRACE("Local Viewer Enable to %ul\n", (BOOL) Value);
4252 glLightModeli(GL_LIGHT_MODEL_LOCAL_VIEWER, state);
4256 case WINED3DRS_LASTPIXEL :
4259 TRACE("Last Pixel Drawing Enabled\n");
4261 FIXME("Last Pixel Drawing Disabled, not handled yet\n");
4266 case WINED3DRS_SOFTWAREVERTEXPROCESSING :
4269 TRACE("Software Processing Enabled\n");
4271 TRACE("Software Processing Disabled\n");
4276 /** not supported */
4277 case WINED3DRS_ZVISIBLE :
4280 return WINED3DERR_INVALIDCALL;
4282 case WINED3DRS_POINTSPRITEENABLE :
4284 /* TODO: NV_POINT_SPRITE */
4285 if (!GL_SUPPORT(ARB_POINT_SPRITE)) {
4286 TRACE("Point sprites not supported\n");
4291 * Point sprites are always enabled. Value controls texture coordinate
4292 * replacement mode. Must be set true for point sprites to use
4295 glEnable(GL_POINT_SPRITE_ARB);
4296 checkGLcall("glEnable(GL_POINT_SPRITE_ARB)");
4299 glTexEnvf(GL_POINT_SPRITE_ARB, GL_COORD_REPLACE_ARB, TRUE);
4300 checkGLcall("glTexEnvf(GL_POINT_SPRITE, GL_COORD_REPLACE, TRUE)");
4302 glTexEnvf(GL_POINT_SPRITE_ARB, GL_COORD_REPLACE_ARB, FALSE);
4303 checkGLcall("glTexEnvf(GL_POINT_SPRITE, GL_COORD_REPLACE, FALSE)");
4307 case WINED3DRS_EDGEANTIALIAS :
4310 glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
4312 checkGLcall("glEnable(GL_BLEND)");
4313 glEnable(GL_LINE_SMOOTH);
4314 checkGLcall("glEnable(GL_LINE_SMOOTH)");
4316 if(!This->stateBlock->renderState[WINED3DRS_ALPHABLENDENABLE]) {
4317 glDisable(GL_BLEND);
4318 checkGLcall("glDisable(GL_BLEND)");
4320 glDisable(GL_LINE_SMOOTH);
4321 checkGLcall("glDisable(GL_LINE_SMOOTH)");
4325 case WINED3DRS_WRAP0 :
4326 case WINED3DRS_WRAP1 :
4327 case WINED3DRS_WRAP2 :
4328 case WINED3DRS_WRAP3 :
4329 case WINED3DRS_WRAP4 :
4330 case WINED3DRS_WRAP5 :
4331 case WINED3DRS_WRAP6 :
4332 case WINED3DRS_WRAP7 :
4333 case WINED3DRS_WRAP8 :
4334 case WINED3DRS_WRAP9 :
4335 case WINED3DRS_WRAP10 :
4336 case WINED3DRS_WRAP11 :
4337 case WINED3DRS_WRAP12 :
4338 case WINED3DRS_WRAP13 :
4339 case WINED3DRS_WRAP14 :
4340 case WINED3DRS_WRAP15 :
4342 http://www.cosc.brocku.ca/Offerings/3P98/course/lectures/texture/
4343 http://msdn.microsoft.com/archive/default.asp?url=/archive/en-us/directx9_c/directx/graphics/programmingguide/FixedFunction/Textures/texturewrapping.asp
4344 http://www.gamedev.net/reference/programming/features/rendererdll3/page2.asp
4345 Descussion that ways to turn on WRAPing to solve an opengl conversion problem.
4346 http://www.flipcode.org/cgi-bin/fcmsg.cgi?thread_show=10248
4348 so far as I can tell, wrapping and texture-coordinate generate go hand in hand,
4352 ERR("(%p)->(%s,%d) Texture wraping not yet supported\n",This, debug_d3drenderstate(State), Value);
4357 case WINED3DRS_MULTISAMPLEANTIALIAS :
4359 if( GL_SUPPORT(ARB_MULTISAMPLE) ) {
4361 glEnable(GL_MULTISAMPLE_ARB);
4362 checkGLcall("glEnable(GL_MULTISAMPLE_ARB)");
4364 glDisable(GL_MULTISAMPLE_ARB);
4365 checkGLcall("glDisable(GL_MULTISAMPLE_ARB)");
4369 ERR("Multisample antialiasing not supported by gl\n");
4375 case WINED3DRS_SCISSORTESTENABLE :
4378 glEnable(GL_SCISSOR_TEST);
4379 checkGLcall("glEnable(GL_SCISSOR_TEST)");
4381 glDisable(GL_SCISSOR_TEST);
4382 checkGLcall("glDisable(GL_SCISSOR_TEST)");
4386 case WINED3DRS_SLOPESCALEDEPTHBIAS :
4390 glEnable(GL_POLYGON_OFFSET_FILL);
4391 checkGLcall("glEnable(GL_POLYGON_OFFSET_FILL)");
4392 glPolygonOffset(tmpvalue.f, *((float*)&This->stateBlock->renderState[WINED3DRS_DEPTHBIAS]));
4393 checkGLcall("glPolygonOffset(...)");
4395 glDisable(GL_POLYGON_OFFSET_FILL);
4396 checkGLcall("glDisable(GL_POLYGON_OFFSET_FILL)");
4400 case WINED3DRS_ANTIALIASEDLINEENABLE :
4403 glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
4405 checkGLcall("glEnable(GL_BLEND)");
4406 glEnable(GL_LINE_SMOOTH);
4407 checkGLcall("glEnable(GL_LINE_SMOOTH)");
4409 glDisable(GL_BLEND);
4410 checkGLcall("glDisable(GL_BLEND)");
4411 glDisable(GL_LINE_SMOOTH);
4412 checkGLcall("glDisable(GL_LINE_SMOOTH)");
4416 case WINED3DRS_DEPTHBIAS :
4420 glEnable(GL_POLYGON_OFFSET_FILL);
4421 checkGLcall("glEnable(GL_POLYGON_OFFSET_FILL)");
4422 glPolygonOffset(*((float*)&This->stateBlock->renderState[WINED3DRS_SLOPESCALEDEPTHBIAS]), tmpvalue.f);
4423 checkGLcall("glPolygonOffset(...)");
4425 glDisable(GL_POLYGON_OFFSET_FILL);
4426 checkGLcall("glDisable(GL_POLYGON_OFFSET_FILL)");
4431 case WINED3DRS_TEXTUREPERSPECTIVE :
4434 glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST);
4436 glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_FASTEST);
4440 case WINED3DRS_STIPPLEDALPHA :
4443 ERR(" Stippled Alpha not supported yet.\n");
4446 case WINED3DRS_ANTIALIAS :
4449 ERR(" Antialias not supported yet.\n");
4453 case WINED3DRS_MULTISAMPLEMASK :
4455 if(0xFFFFFFFF != Value)
4456 ERR("(%p)->(%s,%d) not yet implemented\n", This, debug_d3drenderstate(State), Value);
4460 case WINED3DRS_PATCHEDGESTYLE :
4462 if(WINED3DPATCHEDGE_DISCRETE != Value)
4463 ERR("(%p)->(%s,%d) not yet implemented\n", This, debug_d3drenderstate(State), Value);
4467 case WINED3DRS_PATCHSEGMENTS :
4469 /* available in d3d8 but in d3d9 it was replaced by IDirect3DDevice9::SetNPatchMode */
4471 if(tmpvalue.d != Value)
4472 ERR("(%p)->(%s,%d) not yet implemented\n", This, debug_d3drenderstate(State), Value);
4476 case WINED3DRS_DEBUGMONITORTOKEN :
4478 /* Only useful for "debug builds". */
4479 if(0xbaadcafe != Value) {
4480 /* MSDN says the default is D3DDMT_ENABLE but our tests confirm 0xbaadcafe is the default. */
4481 /* MSDN says anything other than D3DDMT_ENABLE or DISABLE does not change the state,
4482 * but our tests disagree.
4483 * We do not claim to implement a debugging lib, so do not write an ERR
4485 WARN("(%p)->(%s,%d) not yet implemented\n", This, debug_d3drenderstate(State), Value);
4490 case WINED3DRS_POSITIONDEGREE :
4492 if(WINED3DDEGREE_CUBIC != Value)
4493 ERR("(%p)->(%s,%d) not yet implemented\n", This, debug_d3drenderstate(State), Value);
4497 case WINED3DRS_NORMALDEGREE :
4499 if(WINED3DDEGREE_LINEAR != Value)
4500 ERR("(%p)->(%s,%d) not yet implemented\n", This, debug_d3drenderstate(State), Value);
4504 case WINED3DRS_MINTESSELLATIONLEVEL :
4505 case WINED3DRS_MAXTESSELLATIONLEVEL :
4506 case WINED3DRS_ADAPTIVETESS_X :
4507 case WINED3DRS_ADAPTIVETESS_Y :
4508 case WINED3DRS_ADAPTIVETESS_Z :
4509 case WINED3DRS_ADAPTIVETESS_W :
4511 if(This->stateBlock->renderState[WINED3DRS_ENABLEADAPTIVETESSELLATION])
4512 FIXME("(%p)->(%s,%d) not yet implemented\n", This, debug_d3drenderstate(State), Value);
4514 TRACE("(%p)->(%s,%d): recording state but WINED3DRS_ENABLEADAPTIVETESSELLATION is not enabled\n", This, debug_d3drenderstate(State), Value);
4518 case WINED3DRS_ENABLEADAPTIVETESSELLATION:
4521 ERR("(%p)->(%s,%d) not yet implemented\n", This, debug_d3drenderstate(State), Value);
4525 case WINED3DRS_COLORWRITEENABLE1 :
4526 case WINED3DRS_COLORWRITEENABLE2 :
4527 case WINED3DRS_COLORWRITEENABLE3 :
4529 /* depends on WINED3DRS_COLORWRITEENABLE. */
4530 if(0x0000000F != Value)
4531 ERR("(%p)->(%s,%d) not yet implemented. Missing of cap D3DPMISCCAPS_INDEPENDENTWRITEMASKS wasn't honored?\n", This, debug_d3drenderstate(State), Value);
4535 case WINED3DRS_BLENDFACTOR :
4539 TRACE("Setting BlendFactor to %d\n", Value);
4541 D3DCOLORTOGLFLOAT4(Value, col);
4542 if (0xFFFFFFFF != Value) {
4544 checkGLcall("glEnable(GL_BLEND)");
4547 glDisable(GL_BLEND);
4548 checkGLcall("glDisable(GL_BLEND)");
4550 glBlendColor (col[0],col[1],col[2],col[3]);
4554 case WINED3DRS_SRGBWRITEENABLE :
4557 ERR("(%p)->(%s,%d) not yet implemented\n", This, debug_d3drenderstate(State), Value);
4561 case WINED3DRS_SEPARATEALPHABLENDENABLE :
4564 ERR("(%p)->(%s,%d) not yet implemented. Missing of cap D3DPMISCCAPS_SEPARATEALPHABLEND wasn't honored?\n", This, debug_d3drenderstate(State), Value);
4568 case WINED3DRS_SRCBLENDALPHA :
4569 case WINED3DRS_DESTBLENDALPHA :
4570 case WINED3DRS_BLENDOPALPHA :
4572 if(This->stateBlock->renderState[WINED3DRS_SEPARATEALPHABLENDENABLE])
4573 FIXME("(%p)->(%s,%d) not yet implemented\n", This, debug_d3drenderstate(State), Value);
4575 TRACE("(%p)->(%s,%d): recording state but WINED3DRS_SEPARATEALPHABLENDENABLE is not enabled\n", This, debug_d3drenderstate(State), Value);
4580 FIXME("(%p)->(%s,%d) unknown state\n", This, debug_d3drenderstate(State), Value);
4588 static HRESULT WINAPI IWineD3DDeviceImpl_GetRenderState(IWineD3DDevice *iface, WINED3DRENDERSTATETYPE State, DWORD *pValue) {
4589 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4590 TRACE("(%p) for State %d = %d\n", This, State, This->stateBlock->renderState[State]);
4591 *pValue = This->stateBlock->renderState[State];
4596 * Get / Set Sampler States
4597 * TODO: Verify against dx9 definitions
4600 static HRESULT WINAPI IWineD3DDeviceImpl_SetSamplerState(IWineD3DDevice *iface, DWORD Sampler, WINED3DSAMPLERSTATETYPE Type, DWORD Value) {
4601 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4603 * SetSampler is designed to allow for more than the standard up to 8 textures
4604 * and Geforce has stopped supporting more than 6 standard textures in openGL.
4605 * So I have to use ARB for Gforce. (maybe if the sampler > 4 then use ARB?)
4607 * http://developer.nvidia.com/object/General_FAQ.html#t6
4609 * There are two new settings for GForce
4611 * GL_MAX_TEXTURE_IMAGE_UNITS_ARB
4612 * and the texture one:
4613 * GL_MAX_TEXTURE_COORDS_ARB.
4614 * Ok GForce say it's ok to use glTexParameter/glGetTexParameter(...).
4616 /** NOTE: States are appled in IWineD3DBaseTextre ApplyStateChanges and IWineD3DDevice SetupTextureStates**/
4617 if(Sampler > GL_LIMITS(sampler_stages) || Sampler < 0 || Type > WINED3D_HIGHEST_SAMPLER_STATE || Type < 0) {
4618 FIXME("sampler %d type %s(%u) is out of range [max_samplers=%d, highest_state=%d]\n",
4619 Sampler, debug_d3dsamplerstate(Type), Type, GL_LIMITS(sampler_stages), WINED3D_HIGHEST_SAMPLER_STATE);
4620 return WINED3DERR_INVALIDCALL;
4623 TRACE("(%p) : Sampler=%d, Type=%s(%d), Value=%d\n", This, Sampler,
4624 debug_d3dsamplerstate(Type), Type, Value);
4625 This->updateStateBlock->samplerState[Sampler][Type] = Value;
4626 This->updateStateBlock->set.samplerState[Sampler][Type] = Value;
4627 This->updateStateBlock->changed.samplerState[Sampler][Type] = Value;
4629 /* Handle recording of state blocks */
4630 if (This->isRecordingState) {
4631 TRACE("Recording... not performing anything\n");
4638 static HRESULT WINAPI IWineD3DDeviceImpl_GetSamplerState(IWineD3DDevice *iface, DWORD Sampler, WINED3DSAMPLERSTATETYPE Type, DWORD* Value) {
4639 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4640 /** TODO: check that sampler is in range **/
4641 *Value = This->stateBlock->samplerState[Sampler][Type];
4642 TRACE("(%p) : Sampler %d Type %u Returning %d\n", This, Sampler, Type, *Value);
4647 static HRESULT WINAPI IWineD3DDeviceImpl_SetScissorRect(IWineD3DDevice *iface, CONST RECT* pRect) {
4648 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4652 GetClientRect(((IWineD3DSwapChainImpl *)This->swapchains[0])->win_handle, &windowRect);
4653 /* Warning: glScissor uses window coordinates, not viewport coordinates, so our viewport correction does not apply
4654 * Warning2: Even in windowed mode the coords are relative to the window, not the screen
4656 winHeight = windowRect.bottom - windowRect.top;
4657 TRACE("(%p)Setting new Scissor Rect to %d:%d-%d:%d\n", This, pRect->left, pRect->bottom - winHeight,
4658 pRect->right - pRect->left, pRect->bottom - pRect->top);
4660 glScissor(pRect->left, winHeight - pRect->bottom, pRect->right - pRect->left, pRect->bottom - pRect->top);
4661 checkGLcall("glScissor");
4667 static HRESULT WINAPI IWineD3DDeviceImpl_GetScissorRect(IWineD3DDevice *iface, RECT* pRect) {
4668 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4669 GLint scissorBox[4];
4672 /** FIXME: Windows uses a top,left origin openGL uses a bottom Right? **/
4673 glGetIntegerv(GL_SCISSOR_BOX, scissorBox);
4674 pRect->left = scissorBox[0];
4675 pRect->top = scissorBox[1];
4676 pRect->right = scissorBox[0] + scissorBox[2];
4677 pRect->bottom = scissorBox[1] + scissorBox[3];
4678 TRACE("(%p)Returning a Scissor Rect of %d:%d-%d:%d\n", This, pRect->left, pRect->top, pRect->right, pRect->bottom);
4683 static HRESULT WINAPI IWineD3DDeviceImpl_SetVertexDeclaration(IWineD3DDevice* iface, IWineD3DVertexDeclaration* pDecl) {
4684 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *) iface;
4685 IWineD3DVertexDeclaration *oldDecl = This->updateStateBlock->vertexDecl;
4687 TRACE("(%p) : pDecl=%p\n", This, pDecl);
4689 This->updateStateBlock->vertexDecl = pDecl;
4690 This->updateStateBlock->changed.vertexDecl = TRUE;
4691 This->updateStateBlock->set.vertexDecl = TRUE;
4693 if (This->isRecordingState) {
4694 TRACE("Recording... not performing anything\n");
4697 if (NULL != pDecl) {
4698 IWineD3DVertexDeclaration_AddRef(pDecl);
4700 if (NULL != oldDecl) {
4701 IWineD3DVertexDeclaration_Release(oldDecl);
4706 static HRESULT WINAPI IWineD3DDeviceImpl_GetVertexDeclaration(IWineD3DDevice* iface, IWineD3DVertexDeclaration** ppDecl) {
4707 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4709 TRACE("(%p) : ppDecl=%p\n", This, ppDecl);
4711 *ppDecl = This->stateBlock->vertexDecl;
4712 if (NULL != *ppDecl) IWineD3DVertexDeclaration_AddRef(*ppDecl);
4716 static HRESULT WINAPI IWineD3DDeviceImpl_SetVertexShader(IWineD3DDevice *iface, IWineD3DVertexShader* pShader) {
4717 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4718 IWineD3DVertexShader* oldShader = This->updateStateBlock->vertexShader;
4720 This->updateStateBlock->vertexShader = pShader;
4721 This->updateStateBlock->changed.vertexShader = TRUE;
4722 This->updateStateBlock->set.vertexShader = TRUE;
4724 if (This->isRecordingState) {
4725 TRACE("Recording... not performing anything\n");
4728 if (NULL != pShader) {
4729 IWineD3DVertexShader_AddRef(pShader);
4731 if (NULL != oldShader) {
4732 IWineD3DVertexShader_Release(oldShader);
4735 TRACE("(%p) : setting pShader(%p)\n", This, pShader);
4737 * TODO: merge HAL shaders context switching from prototype
4742 static HRESULT WINAPI IWineD3DDeviceImpl_GetVertexShader(IWineD3DDevice *iface, IWineD3DVertexShader** ppShader) {
4743 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4745 if (NULL == ppShader) {
4746 return WINED3DERR_INVALIDCALL;
4748 *ppShader = This->stateBlock->vertexShader;
4749 if( NULL != *ppShader)
4750 IWineD3DVertexShader_AddRef(*ppShader);
4752 TRACE("(%p) : returning %p\n", This, *ppShader);
4756 static HRESULT WINAPI IWineD3DDeviceImpl_SetVertexShaderConstantB(
4757 IWineD3DDevice *iface,
4759 CONST BOOL *srcData,
4762 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4763 int i, cnt = min(count, MAX_CONST_B - start);
4765 TRACE("(iface %p, srcData %p, start %d, count %d)\n",
4766 iface, srcData, start, count);
4768 if (srcData == NULL || cnt < 0)
4769 return WINED3DERR_INVALIDCALL;
4771 memcpy(&This->updateStateBlock->vertexShaderConstantB[start], srcData, cnt * sizeof(BOOL));
4772 for (i = 0; i < cnt; i++)
4773 TRACE("Set BOOL constant %u to %s\n", start + i, srcData[i]? "true":"false");
4775 for (i = start; i < cnt + start; ++i) {
4776 This->updateStateBlock->changed.vertexShaderConstantsB[i] = TRUE;
4777 This->updateStateBlock->set.vertexShaderConstantsB[i] = TRUE;
4783 static HRESULT WINAPI IWineD3DDeviceImpl_GetVertexShaderConstantB(
4784 IWineD3DDevice *iface,
4789 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4790 int cnt = min(count, MAX_CONST_B - start);
4792 TRACE("(iface %p, dstData %p, start %d, count %d)\n",
4793 iface, dstData, start, count);
4795 if (dstData == NULL || cnt < 0)
4796 return WINED3DERR_INVALIDCALL;
4798 memcpy(dstData, &This->stateBlock->vertexShaderConstantB[start], cnt * sizeof(BOOL));
4802 static HRESULT WINAPI IWineD3DDeviceImpl_SetVertexShaderConstantI(
4803 IWineD3DDevice *iface,
4808 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4809 int i, cnt = min(count, MAX_CONST_I - start);
4811 TRACE("(iface %p, srcData %p, start %d, count %d)\n",
4812 iface, srcData, start, count);
4814 if (srcData == NULL || cnt < 0)
4815 return WINED3DERR_INVALIDCALL;
4817 memcpy(&This->updateStateBlock->vertexShaderConstantI[start * 4], srcData, cnt * sizeof(int) * 4);
4818 for (i = 0; i < cnt; i++)
4819 TRACE("Set INT constant %u to { %d, %d, %d, %d }\n", start + i,
4820 srcData[i*4], srcData[i*4+1], srcData[i*4+2], srcData[i*4+3]);
4822 for (i = start; i < cnt + start; ++i) {
4823 This->updateStateBlock->changed.vertexShaderConstantsI[i] = TRUE;
4824 This->updateStateBlock->set.vertexShaderConstantsI[i] = TRUE;
4830 static HRESULT WINAPI IWineD3DDeviceImpl_GetVertexShaderConstantI(
4831 IWineD3DDevice *iface,
4836 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4837 int cnt = min(count, MAX_CONST_I - start);
4839 TRACE("(iface %p, dstData %p, start %d, count %d)\n",
4840 iface, dstData, start, count);
4842 if (dstData == NULL || ((signed int) MAX_CONST_I - (signed int) start) <= (signed int) 0)
4843 return WINED3DERR_INVALIDCALL;
4845 memcpy(dstData, &This->stateBlock->vertexShaderConstantI[start * 4], cnt * sizeof(int) * 4);
4849 static HRESULT WINAPI IWineD3DDeviceImpl_SetVertexShaderConstantF(
4850 IWineD3DDevice *iface,
4852 CONST float *srcData,
4855 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4856 int i, cnt = min(count, GL_LIMITS(vshader_constantsF) - start);
4858 TRACE("(iface %p, srcData %p, start %d, count %d)\n",
4859 iface, srcData, start, count);
4861 if (srcData == NULL || ((signed int) GL_LIMITS(vshader_constantsF) - (signed int) start) <= (signed int) 0)
4862 return WINED3DERR_INVALIDCALL;
4864 memcpy(&This->updateStateBlock->vertexShaderConstantF[start * 4], srcData, cnt * sizeof(float) * 4);
4865 for (i = 0; i < cnt; i++)
4866 TRACE("Set FLOAT constant %u to { %f, %f, %f, %f }\n", start + i,
4867 srcData[i*4], srcData[i*4+1], srcData[i*4+2], srcData[i*4+3]);
4869 for (i = start; i < cnt + start; ++i) {
4870 if (!This->updateStateBlock->set.vertexShaderConstantsF[i]) {
4871 constant_entry *ptr = HeapAlloc(GetProcessHeap(), 0, sizeof(constant_entry));
4873 list_add_head(&This->updateStateBlock->set_vconstantsF, &ptr->entry);
4874 This->updateStateBlock->set.vertexShaderConstantsF[i] = TRUE;
4876 This->updateStateBlock->changed.vertexShaderConstantsF[i] = TRUE;
4882 static HRESULT WINAPI IWineD3DDeviceImpl_GetVertexShaderConstantF(
4883 IWineD3DDevice *iface,
4888 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4889 int cnt = min(count, GL_LIMITS(vshader_constantsF) - start);
4891 TRACE("(iface %p, dstData %p, start %d, count %d)\n",
4892 iface, dstData, start, count);
4894 if (dstData == NULL || cnt < 0)
4895 return WINED3DERR_INVALIDCALL;
4897 memcpy(dstData, &This->stateBlock->vertexShaderConstantF[start * 4], cnt * sizeof(float) * 4);
4901 static HRESULT WINAPI IWineD3DDeviceImpl_SetPixelShader(IWineD3DDevice *iface, IWineD3DPixelShader *pShader) {
4902 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4903 IWineD3DPixelShader *oldShader = This->updateStateBlock->pixelShader;
4904 This->updateStateBlock->pixelShader = pShader;
4905 This->updateStateBlock->changed.pixelShader = TRUE;
4906 This->updateStateBlock->set.pixelShader = TRUE;
4908 /* Handle recording of state blocks */
4909 if (This->isRecordingState) {
4910 TRACE("Recording... not performing anything\n");
4913 if (NULL != pShader) {
4914 IWineD3DPixelShader_AddRef(pShader);
4916 if (NULL != oldShader) {
4917 IWineD3DPixelShader_Release(oldShader);
4920 TRACE("(%p) : setting pShader(%p)\n", This, pShader);
4922 * TODO: merge HAL shaders context switching from prototype
4927 static HRESULT WINAPI IWineD3DDeviceImpl_GetPixelShader(IWineD3DDevice *iface, IWineD3DPixelShader **ppShader) {
4928 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4930 if (NULL == ppShader) {
4931 WARN("(%p) : PShader is NULL, returning INVALIDCALL\n", This);
4932 return WINED3DERR_INVALIDCALL;
4935 *ppShader = This->stateBlock->pixelShader;
4936 if (NULL != *ppShader) {
4937 IWineD3DPixelShader_AddRef(*ppShader);
4939 TRACE("(%p) : returning %p\n", This, *ppShader);
4943 static HRESULT WINAPI IWineD3DDeviceImpl_SetPixelShaderConstantB(
4944 IWineD3DDevice *iface,
4946 CONST BOOL *srcData,
4949 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4950 int i, cnt = min(count, MAX_CONST_B - start);
4952 TRACE("(iface %p, srcData %p, start %d, count %d)\n",
4953 iface, srcData, start, count);
4955 if (srcData == NULL || cnt < 0)
4956 return WINED3DERR_INVALIDCALL;
4958 memcpy(&This->updateStateBlock->pixelShaderConstantB[start], srcData, cnt * sizeof(BOOL));
4959 for (i = 0; i < cnt; i++)
4960 TRACE("Set BOOL constant %u to %s\n", start + i, srcData[i]? "true":"false");
4962 for (i = start; i < cnt + start; ++i) {
4963 This->updateStateBlock->changed.pixelShaderConstantsB[i] = TRUE;
4964 This->updateStateBlock->set.pixelShaderConstantsB[i] = TRUE;
4970 static HRESULT WINAPI IWineD3DDeviceImpl_GetPixelShaderConstantB(
4971 IWineD3DDevice *iface,
4976 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4977 int cnt = min(count, MAX_CONST_B - start);
4979 TRACE("(iface %p, dstData %p, start %d, count %d)\n",
4980 iface, dstData, start, count);
4982 if (dstData == NULL || cnt < 0)
4983 return WINED3DERR_INVALIDCALL;
4985 memcpy(dstData, &This->stateBlock->pixelShaderConstantB[start], cnt * sizeof(BOOL));
4989 static HRESULT WINAPI IWineD3DDeviceImpl_SetPixelShaderConstantI(
4990 IWineD3DDevice *iface,
4995 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4996 int i, cnt = min(count, MAX_CONST_I - start);
4998 TRACE("(iface %p, srcData %p, start %d, count %d)\n",
4999 iface, srcData, start, count);
5001 if (srcData == NULL || cnt < 0)
5002 return WINED3DERR_INVALIDCALL;
5004 memcpy(&This->updateStateBlock->pixelShaderConstantI[start * 4], srcData, cnt * sizeof(int) * 4);
5005 for (i = 0; i < cnt; i++)
5006 TRACE("Set INT constant %u to { %d, %d, %d, %d }\n", start + i,
5007 srcData[i*4], srcData[i*4+1], srcData[i*4+2], srcData[i*4+3]);
5009 for (i = start; i < cnt + start; ++i) {
5010 This->updateStateBlock->changed.pixelShaderConstantsI[i] = TRUE;
5011 This->updateStateBlock->set.pixelShaderConstantsI[i] = TRUE;
5017 static HRESULT WINAPI IWineD3DDeviceImpl_GetPixelShaderConstantI(
5018 IWineD3DDevice *iface,
5023 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5024 int cnt = min(count, MAX_CONST_I - start);
5026 TRACE("(iface %p, dstData %p, start %d, count %d)\n",
5027 iface, dstData, start, count);
5029 if (dstData == NULL || cnt < 0)
5030 return WINED3DERR_INVALIDCALL;
5032 memcpy(dstData, &This->stateBlock->pixelShaderConstantI[start * 4], cnt * sizeof(int) * 4);
5036 static HRESULT WINAPI IWineD3DDeviceImpl_SetPixelShaderConstantF(
5037 IWineD3DDevice *iface,
5039 CONST float *srcData,
5042 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5043 int i, cnt = min(count, GL_LIMITS(pshader_constantsF) - start);
5045 TRACE("(iface %p, srcData %p, start %d, count %d)\n",
5046 iface, srcData, start, count);
5048 if (srcData == NULL || cnt < 0)
5049 return WINED3DERR_INVALIDCALL;
5051 memcpy(&This->updateStateBlock->pixelShaderConstantF[start * 4], srcData, cnt * sizeof(float) * 4);
5052 for (i = 0; i < cnt; i++)
5053 TRACE("Set FLOAT constant %u to { %f, %f, %f, %f }\n", start + i,
5054 srcData[i*4], srcData[i*4+1], srcData[i*4+2], srcData[i*4+3]);
5056 for (i = start; i < cnt + start; ++i) {
5057 if (!This->updateStateBlock->set.pixelShaderConstantsF[i]) {
5058 constant_entry *ptr = HeapAlloc(GetProcessHeap(), 0, sizeof(constant_entry));
5060 list_add_head(&This->updateStateBlock->set_pconstantsF, &ptr->entry);
5061 This->updateStateBlock->set.pixelShaderConstantsF[i] = TRUE;
5063 This->updateStateBlock->changed.pixelShaderConstantsF[i] = TRUE;
5069 static HRESULT WINAPI IWineD3DDeviceImpl_GetPixelShaderConstantF(
5070 IWineD3DDevice *iface,
5075 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5076 int cnt = min(count, GL_LIMITS(pshader_constantsF) - start);
5078 TRACE("(iface %p, dstData %p, start %d, count %d)\n",
5079 iface, dstData, start, count);
5081 if (dstData == NULL || cnt < 0)
5082 return WINED3DERR_INVALIDCALL;
5084 memcpy(dstData, &This->stateBlock->pixelShaderConstantF[start * 4], cnt * sizeof(float) * 4);
5088 #define copy_and_next(dest, src, size) memcpy(dest, src, size); dest += (size)
5090 process_vertices_strided(IWineD3DDeviceImpl *This, DWORD dwDestIndex, DWORD dwCount, WineDirect3DVertexStridedData *lpStrideData, DWORD SrcFVF, IWineD3DVertexBufferImpl *dest, DWORD dwFlags) {
5091 char *dest_ptr, *dest_conv = NULL;
5093 DWORD DestFVF = dest->fvf;
5095 WINED3DMATRIX mat, proj_mat, view_mat, world_mat;
5099 if (SrcFVF & WINED3DFVF_NORMAL) {
5100 WARN(" lighting state not saved yet... Some strange stuff may happen !\n");
5103 if ( (SrcFVF & WINED3DFVF_POSITION_MASK) != WINED3DFVF_XYZ) {
5104 ERR("Source has no position mask\n");
5105 return WINED3DERR_INVALIDCALL;
5108 /* We might access VBOs from this code, so hold the lock */
5111 if (dest->resource.allocatedMemory == NULL) {
5112 /* This may happen if we do direct locking into a vbo. Unlikely,
5113 * but theoretically possible(ddraw processvertices test)
5115 dest->resource.allocatedMemory = HeapAlloc(GetProcessHeap(), 0, dest->resource.size);
5116 if(!dest->resource.allocatedMemory) {
5118 ERR("Out of memory\n");
5119 return E_OUTOFMEMORY;
5123 GL_EXTCALL(glBindBufferARB(GL_ARRAY_BUFFER_ARB, dest->vbo));
5124 checkGLcall("glBindBufferARB");
5125 src = GL_EXTCALL(glMapBufferARB(GL_ARRAY_BUFFER_ARB, GL_READ_ONLY_ARB));
5127 memcpy(dest->resource.allocatedMemory, src, dest->resource.size);
5129 GL_EXTCALL(glUnmapBufferARB(GL_ARRAY_BUFFER_ARB));
5130 checkGLcall("glUnmapBufferARB");
5134 /* Get a pointer into the destination vbo(create one if none exists) and
5135 * write correct opengl data into it. It's cheap and allows us to run drawStridedFast
5137 if(!dest->vbo && GL_SUPPORT(ARB_VERTEX_BUFFER_OBJECT)) {
5142 GL_EXTCALL(glBindBufferARB(GL_ARRAY_BUFFER_ARB, dest->vbo));
5143 dest_conv = GL_EXTCALL(glMapBufferARB(GL_ARRAY_BUFFER_ARB, GL_WRITE_ONLY_ARB));
5145 ERR("glMapBuffer failed\n");
5146 /* Continue without storing converted vertices */
5151 * a) WINED3DRS_CLIPPING is enabled
5152 * b) WINED3DVOP_CLIP is passed
5154 if(This->stateBlock->renderState[WINED3DRS_CLIPPING]) {
5155 static BOOL warned = FALSE;
5157 * The clipping code is not quite correct. Some things need
5158 * to be checked against IDirect3DDevice3 (!), d3d8 and d3d9,
5159 * so disable clipping for now.
5160 * (The graphics in Half-Life are broken, and my processvertices
5161 * test crashes with IDirect3DDevice3)
5167 FIXME("Clipping is broken and disabled for now\n");
5169 } else doClip = FALSE;
5170 dest_ptr = ((char *) dest->resource.allocatedMemory) + dwDestIndex * get_flexible_vertex_size(DestFVF);
5172 dest_conv = ((char *) dest_conv) + dwDestIndex * get_flexible_vertex_size(DestFVF);
5175 IWineD3DDevice_GetTransform( (IWineD3DDevice *) This,
5178 IWineD3DDevice_GetTransform( (IWineD3DDevice *) This,
5179 WINED3DTS_PROJECTION,
5181 IWineD3DDevice_GetTransform( (IWineD3DDevice *) This,
5182 WINED3DTS_WORLDMATRIX(0),
5185 TRACE("View mat:\n");
5186 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); \
5187 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); \
5188 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); \
5189 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); \
5191 TRACE("Proj mat:\n");
5192 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); \
5193 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); \
5194 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); \
5195 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); \
5197 TRACE("World mat:\n");
5198 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); \
5199 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); \
5200 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); \
5201 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); \
5203 /* Get the viewport */
5204 IWineD3DDevice_GetViewport( (IWineD3DDevice *) This, &vp);
5205 TRACE("Viewport: X=%d, Y=%d, Width=%d, Height=%d, MinZ=%f, MaxZ=%f\n",
5206 vp.X, vp.Y, vp.Width, vp.Height, vp.MinZ, vp.MaxZ);
5208 multiply_matrix(&mat,&view_mat,&world_mat);
5209 multiply_matrix(&mat,&proj_mat,&mat);
5211 numTextures = (DestFVF & WINED3DFVF_TEXCOUNT_MASK) >> WINED3DFVF_TEXCOUNT_SHIFT;
5213 for (i = 0; i < dwCount; i+= 1) {
5214 unsigned int tex_index;
5216 if ( ((DestFVF & WINED3DFVF_POSITION_MASK) == WINED3DFVF_XYZ ) ||
5217 ((DestFVF & WINED3DFVF_POSITION_MASK) == WINED3DFVF_XYZRHW ) ) {
5218 /* The position first */
5220 (float *) (((char *) lpStrideData->u.s.position.lpData) + i * lpStrideData->u.s.position.dwStride);
5222 TRACE("In: ( %06.2f %06.2f %06.2f )\n", p[0], p[1], p[2]);
5224 /* Multiplication with world, view and projection matrix */
5225 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);
5226 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);
5227 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);
5228 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);
5230 TRACE("x=%f y=%f z=%f rhw=%f\n", x, y, z, rhw);
5232 /* WARNING: The following things are taken from d3d7 and were not yet checked
5233 * against d3d8 or d3d9!
5236 /* Clipping conditions: From
5237 * http://msdn.microsoft.com/archive/default.asp?url=/archive/en-us/directx9_c/directx/graphics/programmingguide/fixedfunction/viewportsclipping/clippingvolumes.asp
5239 * A vertex is clipped if it does not match the following requirements
5243 * 0 < rhw ( Not in d3d7, but tested in d3d7)
5245 * If clipping is on is determined by the D3DVOP_CLIP flag in D3D7, and
5246 * by the D3DRS_CLIPPING in D3D9(according to the msdn, not checked)
5251 ( (-rhw -eps < x) && (-rhw -eps < y) && ( -eps < z) &&
5252 (x <= rhw + eps) && (y <= rhw + eps ) && (z <= rhw + eps) &&
5255 /* "Normal" viewport transformation (not clipped)
5256 * 1) The values are divided by rhw
5257 * 2) The y axis is negative, so multiply it with -1
5258 * 3) Screen coordinates go from -(Width/2) to +(Width/2) and
5259 * -(Height/2) to +(Height/2). The z range is MinZ to MaxZ
5260 * 4) Multiply x with Width/2 and add Width/2
5261 * 5) The same for the height
5262 * 6) Add the viewpoint X and Y to the 2D coordinates and
5263 * The minimum Z value to z
5264 * 7) rhw = 1 / rhw Reciprocal of Homogeneous W....
5266 * Well, basically it's simply a linear transformation into viewport
5278 z *= vp.MaxZ - vp.MinZ;
5280 x += vp.Width / 2 + vp.X;
5281 y += vp.Height / 2 + vp.Y;
5286 /* That vertex got clipped
5287 * Contrary to OpenGL it is not dropped completely, it just
5288 * undergoes a different calculation.
5290 TRACE("Vertex got clipped\n");
5297 /* Msdn mentions that Direct3D9 keeps a list of clipped vertices
5298 * outside of the main vertex buffer memory. That needs some more
5303 TRACE("Writing (%f %f %f) %f\n", x, y, z, rhw);
5306 ( (float *) dest_ptr)[0] = x;
5307 ( (float *) dest_ptr)[1] = y;
5308 ( (float *) dest_ptr)[2] = z;
5309 ( (float *) dest_ptr)[3] = rhw; /* SIC, see ddraw test! */
5311 dest_ptr += 3 * sizeof(float);
5313 if((DestFVF & WINED3DFVF_POSITION_MASK) == WINED3DFVF_XYZRHW) {
5314 dest_ptr += sizeof(float);
5319 ( (float *) dest_conv)[0] = x * w;
5320 ( (float *) dest_conv)[1] = y * w;
5321 ( (float *) dest_conv)[2] = z * w;
5322 ( (float *) dest_conv)[3] = w;
5324 dest_conv += 3 * sizeof(float);
5326 if((DestFVF & WINED3DFVF_POSITION_MASK) == WINED3DFVF_XYZRHW) {
5327 dest_conv += sizeof(float);
5331 if (DestFVF & WINED3DFVF_PSIZE) {
5332 dest_ptr += sizeof(DWORD);
5333 if(dest_conv) dest_conv += sizeof(DWORD);
5335 if (DestFVF & WINED3DFVF_NORMAL) {
5337 (float *) (((float *) lpStrideData->u.s.normal.lpData) + i * lpStrideData->u.s.normal.dwStride);
5338 /* AFAIK this should go into the lighting information */
5339 FIXME("Didn't expect the destination to have a normal\n");
5340 copy_and_next(dest_ptr, normal, 3 * sizeof(float));
5342 copy_and_next(dest_conv, normal, 3 * sizeof(float));
5346 if (DestFVF & WINED3DFVF_DIFFUSE) {
5348 (DWORD *) (((char *) lpStrideData->u.s.diffuse.lpData) + i * lpStrideData->u.s.diffuse.dwStride);
5350 static BOOL warned = FALSE;
5353 ERR("No diffuse color in source, but destination has one\n");
5357 *( (DWORD *) dest_ptr) = 0xffffffff;
5358 dest_ptr += sizeof(DWORD);
5361 *( (DWORD *) dest_conv) = 0xffffffff;
5362 dest_conv += sizeof(DWORD);
5366 copy_and_next(dest_ptr, color_d, sizeof(DWORD));
5368 *( (DWORD *) dest_conv) = (*color_d & 0xff00ff00) ; /* Alpha + green */
5369 *( (DWORD *) dest_conv) |= (*color_d & 0x00ff0000) >> 16; /* Red */
5370 *( (DWORD *) dest_conv) |= (*color_d & 0xff0000ff) << 16; /* Blue */
5371 dest_conv += sizeof(DWORD);
5376 if (DestFVF & WINED3DFVF_SPECULAR) {
5377 /* What's the color value in the feedback buffer? */
5379 (DWORD *) (((char *) lpStrideData->u.s.specular.lpData) + i * lpStrideData->u.s.specular.dwStride);
5381 static BOOL warned = FALSE;
5384 ERR("No specular color in source, but destination has one\n");
5388 *( (DWORD *) dest_ptr) = 0xFF000000;
5389 dest_ptr += sizeof(DWORD);
5392 *( (DWORD *) dest_conv) = 0xFF000000;
5393 dest_conv += sizeof(DWORD);
5397 copy_and_next(dest_ptr, color_s, sizeof(DWORD));
5399 *( (DWORD *) dest_conv) = (*color_s & 0xff00ff00) ; /* Alpha + green */
5400 *( (DWORD *) dest_conv) |= (*color_s & 0x00ff0000) >> 16; /* Red */
5401 *( (DWORD *) dest_conv) |= (*color_s & 0xff0000ff) << 16; /* Blue */
5402 dest_conv += sizeof(DWORD);
5407 for (tex_index = 0; tex_index < numTextures; tex_index++) {
5409 (float *) (((char *) lpStrideData->u.s.texCoords[tex_index].lpData) +
5410 i * lpStrideData->u.s.texCoords[tex_index].dwStride);
5412 ERR("No source texture, but destination requests one\n");
5413 dest_ptr+=GET_TEXCOORD_SIZE_FROM_FVF(DestFVF, tex_index) * sizeof(float);
5414 if(dest_conv) dest_conv += GET_TEXCOORD_SIZE_FROM_FVF(DestFVF, tex_index) * sizeof(float);
5417 copy_and_next(dest_ptr, tex_coord, GET_TEXCOORD_SIZE_FROM_FVF(DestFVF, tex_index) * sizeof(float));
5419 copy_and_next(dest_conv, tex_coord, GET_TEXCOORD_SIZE_FROM_FVF(DestFVF, tex_index) * sizeof(float));
5426 GL_EXTCALL(glUnmapBufferARB(GL_ARRAY_BUFFER_ARB));
5427 checkGLcall("glUnmapBufferARB(GL_ARRAY_BUFFER_ARB)");
5434 #undef copy_and_next
5436 static HRESULT WINAPI IWineD3DDeviceImpl_ProcessVertices(IWineD3DDevice *iface, UINT SrcStartIndex, UINT DestIndex, UINT VertexCount, IWineD3DVertexBuffer* pDestBuffer, IWineD3DVertexBuffer* pVertexDecl, DWORD Flags) {
5437 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5438 IWineD3DVertexBufferImpl *SrcImpl = (IWineD3DVertexBufferImpl *) pVertexDecl;
5439 WineDirect3DVertexStridedData strided;
5440 TRACE("(%p)->(%d,%d,%d,%p,%p,%d\n", This, SrcStartIndex, DestIndex, VertexCount, pDestBuffer, pVertexDecl, Flags);
5443 WARN("NULL source vertex buffer\n");
5444 return WINED3DERR_INVALIDCALL;
5446 /* We don't need the source vbo because this buffer is only used as
5447 * a source for ProcessVertices. Avoid wasting resources by converting the
5448 * buffer and loading the VBO
5451 TRACE("Releasing the source vbo, it won't be needed\n");
5453 if(!SrcImpl->resource.allocatedMemory) {
5454 /* Rescue the data from the buffer */
5456 SrcImpl->resource.allocatedMemory = HeapAlloc(GetProcessHeap(), 0, SrcImpl->resource.size);
5457 if(!SrcImpl->resource.allocatedMemory) {
5458 ERR("Out of memory\n");
5459 return E_OUTOFMEMORY;
5463 GL_EXTCALL(glBindBufferARB(GL_ARRAY_BUFFER_ARB, SrcImpl->vbo));
5464 checkGLcall("glBindBufferARB");
5466 src = GL_EXTCALL(glMapBufferARB(GL_ARRAY_BUFFER_ARB, GL_READ_ONLY_ARB));
5468 memcpy(SrcImpl->resource.allocatedMemory, src, SrcImpl->resource.size);
5471 GL_EXTCALL(glUnmapBufferARB(GL_ARRAY_BUFFER_ARB));
5472 checkGLcall("glUnmapBufferARB");
5477 GL_EXTCALL(glBindBufferARB(GL_ARRAY_BUFFER_ARB, 0));
5478 checkGLcall("glBindBufferARB");
5479 GL_EXTCALL(glDeleteBuffersARB(1, &SrcImpl->vbo));
5480 checkGLcall("glDeleteBuffersARB");
5486 memset(&strided, 0, sizeof(strided));
5487 primitiveConvertFVFtoOffset(SrcImpl->fvf, get_flexible_vertex_size(SrcImpl->fvf), SrcImpl->resource.allocatedMemory + get_flexible_vertex_size(SrcImpl->fvf) * SrcStartIndex, &strided, 0);
5489 return process_vertices_strided(This, DestIndex, VertexCount, &strided, SrcImpl->fvf, (IWineD3DVertexBufferImpl *) pDestBuffer, Flags);
5493 * Apply / Get / Set Texture Stage States
5494 * TODO: Verify against dx9 definitions
5497 /* 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 */
5498 static void WINAPI IWineD3DDeviceImpl_ApplyTextureUnitState(IWineD3DDevice *iface, DWORD Stage, WINED3DTEXTURESTAGESTATETYPE Type) {
5499 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5500 DWORD Value = This->updateStateBlock->textureState[Stage][Type];
5501 /* FIXME: Handle 3d textures? What if TSS value set before set texture? Need to reapply all values? */
5503 TRACE("(%p) : Stage=%d, Type=%s(%d), Value=%d\n", This, Stage, debug_d3dtexturestate(Type), Type, Value);
5505 /* Check that the stage is within limits */
5506 if (Stage >= GL_LIMITS(texture_stages) || Stage < 0) {
5507 TRACE("Attempt to access invalid texture rejected\n");
5514 case WINED3DTSS_ALPHAOP :
5515 case WINED3DTSS_COLOROP :
5516 /* nothing to do as moved to drawprim for now */
5518 case WINED3DTSS_ADDRESSW :
5519 #if 0 /* I'm not sure what D3D does about ADDRESSW appearing twice */
5520 if (Value < minLookup[WINELOOKUP_WARPPARAM] || Value > maxLookup[WINELOOKUP_WARPPARAM]) {
5521 FIXME("Unrecognized or unsupported WINED3DTADDRESS_* value %d, state %d\n", Value, Type);
5524 GLint wrapParm = stateLookup[WINELOOKUP_WARPPARAM][Value - minLookup[WINELOOKUP_WARPPARAM]];
5525 TRACE("Setting WRAP_R to %d for %x\n", wrapParm, This->stateBlock->textureDimensions[Stage]);
5526 glTexParameteri(This->stateBlock->textureDimensions[Stage], GL_TEXTURE_WRAP_R, wrapParm);
5527 checkGLcall("glTexParameteri(..., GL_TEXTURE_WRAP_R, wrapParm)");
5530 case WINED3DTSS_TEXCOORDINDEX :
5532 /* Values 0-7 are indexes into the FVF tex coords - See comments in DrawPrimitive */
5534 /* FIXME: From MSDN: The WINED3DTSS_TCI_* flags are mutually exclusive. If you include
5535 one flag, you can still specify an index value, which the system uses to
5536 determine the texture wrapping mode.
5537 eg. SetTextureStageState( 0, WINED3DTSS_TEXCOORDINDEX, WINED3DTSS_TCI_CAMERASPACEPOSITION | 1 );
5538 means use the vertex position (camera-space) as the input texture coordinates
5539 for this texture stage, and the wrap mode set in the WINED3DRS_WRAP1 render
5540 state. We do not (yet) support the WINED3DRENDERSTATE_WRAPx values, nor tie them up
5541 to the TEXCOORDINDEX value */
5544 * Be careful the value of the mask 0xF0000 come from d3d8types.h infos
5546 switch (Value & 0xFFFF0000) {
5547 case WINED3DTSS_TCI_PASSTHRU:
5548 /*Use the specified texture coordinates contained within the vertex format. This value resolves to zero.*/
5549 glDisable(GL_TEXTURE_GEN_S);
5550 glDisable(GL_TEXTURE_GEN_T);
5551 glDisable(GL_TEXTURE_GEN_R);
5552 glDisable(GL_TEXTURE_GEN_Q);
5553 checkGLcall("glDisable(GL_TEXTURE_GEN_S,T,R,Q)");
5556 case WINED3DTSS_TCI_CAMERASPACEPOSITION:
5557 /* CameraSpacePosition means use the vertex position, transformed to camera space,
5558 as the input texture coordinates for this stage's texture transformation. This
5559 equates roughly to EYE_LINEAR */
5561 float s_plane[] = { 1.0, 0.0, 0.0, 0.0 };
5562 float t_plane[] = { 0.0, 1.0, 0.0, 0.0 };
5563 float r_plane[] = { 0.0, 0.0, 1.0, 0.0 };
5564 float q_plane[] = { 0.0, 0.0, 0.0, 1.0 };
5565 TRACE("WINED3DTSS_TCI_CAMERASPACEPOSITION - Set eye plane\n");
5567 glMatrixMode(GL_MODELVIEW);
5570 glTexGenfv(GL_S, GL_EYE_PLANE, s_plane);
5571 glTexGenfv(GL_T, GL_EYE_PLANE, t_plane);
5572 glTexGenfv(GL_R, GL_EYE_PLANE, r_plane);
5573 glTexGenfv(GL_Q, GL_EYE_PLANE, q_plane);
5576 TRACE("WINED3DTSS_TCI_CAMERASPACEPOSITION - Set GL_TEXTURE_GEN_x and GL_x, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR\n");
5577 glEnable(GL_TEXTURE_GEN_S);
5578 checkGLcall("glEnable(GL_TEXTURE_GEN_S);");
5579 glTexGeni(GL_S, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR);
5580 checkGLcall("glTexGeni(GL_S, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR)");
5581 glEnable(GL_TEXTURE_GEN_T);
5582 checkGLcall("glEnable(GL_TEXTURE_GEN_T);");
5583 glTexGeni(GL_T, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR);
5584 checkGLcall("glTexGeni(GL_T, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR)");
5585 glEnable(GL_TEXTURE_GEN_R);
5586 checkGLcall("glEnable(GL_TEXTURE_GEN_R);");
5587 glTexGeni(GL_R, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR);
5588 checkGLcall("glTexGeni(GL_R, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR)");
5592 case WINED3DTSS_TCI_CAMERASPACENORMAL:
5594 if (GL_SUPPORT(NV_TEXGEN_REFLECTION)) {
5595 float s_plane[] = { 1.0, 0.0, 0.0, 0.0 };
5596 float t_plane[] = { 0.0, 1.0, 0.0, 0.0 };
5597 float r_plane[] = { 0.0, 0.0, 1.0, 0.0 };
5598 float q_plane[] = { 0.0, 0.0, 0.0, 1.0 };
5599 TRACE("WINED3DTSS_TCI_CAMERASPACENORMAL - Set eye plane\n");
5601 glMatrixMode(GL_MODELVIEW);
5604 glTexGenfv(GL_S, GL_EYE_PLANE, s_plane);
5605 glTexGenfv(GL_T, GL_EYE_PLANE, t_plane);
5606 glTexGenfv(GL_R, GL_EYE_PLANE, r_plane);
5607 glTexGenfv(GL_Q, GL_EYE_PLANE, q_plane);
5610 glEnable(GL_TEXTURE_GEN_S);
5611 checkGLcall("glEnable(GL_TEXTURE_GEN_S);");
5612 glTexGeni(GL_S, GL_TEXTURE_GEN_MODE, GL_NORMAL_MAP_NV);
5613 checkGLcall("glTexGeni(GL_S, GL_TEXTURE_GEN_MODE, GL_NORMAL_MAP_NV)");
5614 glEnable(GL_TEXTURE_GEN_T);
5615 checkGLcall("glEnable(GL_TEXTURE_GEN_T);");
5616 glTexGeni(GL_T, GL_TEXTURE_GEN_MODE, GL_NORMAL_MAP_NV);
5617 checkGLcall("glTexGeni(GL_T, GL_TEXTURE_GEN_MODE, GL_NORMAL_MAP_NV)");
5618 glEnable(GL_TEXTURE_GEN_R);
5619 checkGLcall("glEnable(GL_TEXTURE_GEN_R);");
5620 glTexGeni(GL_R, GL_TEXTURE_GEN_MODE, GL_NORMAL_MAP_NV);
5621 checkGLcall("glTexGeni(GL_R, GL_TEXTURE_GEN_MODE, GL_NORMAL_MAP_NV)");
5626 case WINED3DTSS_TCI_CAMERASPACEREFLECTIONVECTOR:
5628 if (GL_SUPPORT(NV_TEXGEN_REFLECTION)) {
5629 float s_plane[] = { 1.0, 0.0, 0.0, 0.0 };
5630 float t_plane[] = { 0.0, 1.0, 0.0, 0.0 };
5631 float r_plane[] = { 0.0, 0.0, 1.0, 0.0 };
5632 float q_plane[] = { 0.0, 0.0, 0.0, 1.0 };
5633 TRACE("WINED3DTSS_TCI_CAMERASPACEREFLECTIONVECTOR - Set eye plane\n");
5635 glMatrixMode(GL_MODELVIEW);
5638 glTexGenfv(GL_S, GL_EYE_PLANE, s_plane);
5639 glTexGenfv(GL_T, GL_EYE_PLANE, t_plane);
5640 glTexGenfv(GL_R, GL_EYE_PLANE, r_plane);
5641 glTexGenfv(GL_Q, GL_EYE_PLANE, q_plane);
5644 glEnable(GL_TEXTURE_GEN_S);
5645 checkGLcall("glEnable(GL_TEXTURE_GEN_S);");
5646 glTexGeni(GL_S, GL_TEXTURE_GEN_MODE, GL_REFLECTION_MAP_NV);
5647 checkGLcall("glTexGeni(GL_S, GL_TEXTURE_GEN_MODE, GL_REFLECTION_MAP_NV)");
5648 glEnable(GL_TEXTURE_GEN_T);
5649 checkGLcall("glEnable(GL_TEXTURE_GEN_T);");
5650 glTexGeni(GL_T, GL_TEXTURE_GEN_MODE, GL_REFLECTION_MAP_NV);
5651 checkGLcall("glTexGeni(GL_T, GL_TEXTURE_GEN_MODE, GL_REFLECTION_MAP_NV)");
5652 glEnable(GL_TEXTURE_GEN_R);
5653 checkGLcall("glEnable(GL_TEXTURE_GEN_R);");
5654 glTexGeni(GL_R, GL_TEXTURE_GEN_MODE, GL_REFLECTION_MAP_NV);
5655 checkGLcall("glTexGeni(GL_R, GL_TEXTURE_GEN_MODE, GL_REFLECTION_MAP_NV)");
5660 /* Unhandled types: */
5663 /* ? disable GL_TEXTURE_GEN_n ? */
5664 glDisable(GL_TEXTURE_GEN_S);
5665 glDisable(GL_TEXTURE_GEN_T);
5666 glDisable(GL_TEXTURE_GEN_R);
5667 glDisable(GL_TEXTURE_GEN_Q);
5668 FIXME("Unhandled WINED3DTSS_TEXCOORDINDEX %x\n", Value);
5675 case WINED3DTSS_TEXTURETRANSFORMFLAGS :
5676 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);
5679 case WINED3DTSS_BUMPENVMAT00 :
5680 case WINED3DTSS_BUMPENVMAT01 :
5681 TRACE("BUMPENVMAT0%u Stage=%d, Type=%d, Value =%d\n", Type - WINED3DTSS_BUMPENVMAT00, Stage, Type, Value);
5683 case WINED3DTSS_BUMPENVMAT10 :
5684 case WINED3DTSS_BUMPENVMAT11 :
5685 TRACE("BUMPENVMAT1%u Stage=%d, Type=%d, Value =%d\n", Type - WINED3DTSS_BUMPENVMAT10, Stage, Type, Value);
5688 case WINED3DTSS_BUMPENVLSCALE :
5689 TRACE("BUMPENVLSCALE Stage=%d, Type=%d, Value =%d\n", Stage, Type, Value);
5692 case WINED3DTSS_BUMPENVLOFFSET :
5693 TRACE("BUMPENVLOFFSET Stage=%d, Type=%d, Value =%d\n", Stage, Type, Value);
5696 case WINED3DTSS_RESULTARG :
5697 TRACE("RESULTARG Still a stub, Stage=%d, Type=%d, Value =%d\n", Stage, Type, Value);
5701 /* Put back later: FIXME("(%p) : stub, Stage=%d, Type=%d, Value =%d\n", This, Stage, Type, Value); */
5702 TRACE("Still a stub, Stage=%d, Type=%d, Value =%d\n", Stage, Type, Value);
5711 * Get / Set Texture Stage States
5712 * TODO: Verify against dx9 definitions
5714 static HRESULT WINAPI IWineD3DDeviceImpl_SetTextureStageState(IWineD3DDevice *iface, DWORD Stage, WINED3DTEXTURESTAGESTATETYPE Type, DWORD Value) {
5715 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5717 /* FIXME: Handle 3d textures? What if TSS value set before set texture? Need to reapply all values? */
5719 TRACE("(%p) : Stage=%d, Type=%s(%d), Value=%d\n", This, Stage, debug_d3dtexturestate(Type), Type, Value);
5721 /* Reject invalid texture units */
5722 if (Stage >= GL_LIMITS(texture_stages)) {
5723 TRACE("Attempt to access invalid texture rejected\n");
5724 return WINED3DERR_INVALIDCALL;
5727 This->updateStateBlock->changed.textureState[Stage][Type] = TRUE;
5728 This->updateStateBlock->set.textureState[Stage][Type] = TRUE;
5729 This->updateStateBlock->textureState[Stage][Type] = Value;
5734 static HRESULT WINAPI IWineD3DDeviceImpl_GetTextureStageState(IWineD3DDevice *iface, DWORD Stage, WINED3DTEXTURESTAGESTATETYPE Type, DWORD* pValue) {
5735 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5736 TRACE("(%p) : requesting Stage %d, Type %d getting %d\n", This, Stage, Type, This->updateStateBlock->textureState[Stage][Type]);
5737 *pValue = This->updateStateBlock->textureState[Stage][Type];
5744 static HRESULT WINAPI IWineD3DDeviceImpl_SetTexture(IWineD3DDevice *iface, DWORD Stage, IWineD3DBaseTexture* pTexture) {
5746 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5747 IWineD3DBaseTexture *oldTexture;
5749 oldTexture = This->updateStateBlock->textures[Stage];
5750 TRACE("(%p) : Stage(%d), Texture (%p)\n", This, Stage, pTexture);
5752 #if 0 /* TODO: check so vertex textures */
5753 if (Stage >= D3DVERTEXTEXTURESAMPLER && Stage <= D3DVERTEXTEXTURESAMPLER3){
5754 This->updateStateBlock->vertexTextures[Stage - D3DVERTEXTEXTURESAMPLER] = pTexture;
5759 /* Reject invalid texture units */
5760 if (Stage >= GL_LIMITS(sampler_stages) || Stage < 0) {
5761 WARN("Attempt to access invalid texture rejected\n");
5762 return WINED3DERR_INVALIDCALL;
5765 if(pTexture != NULL) {
5766 /* SetTexture isn't allowed on textures in WINED3DPOOL_SCRATCH;
5768 if(((IWineD3DTextureImpl*)pTexture)->resource.pool == WINED3DPOOL_SCRATCH) {
5769 WARN("(%p) Attempt to set scratch texture rejected\n", pTexture);
5770 return WINED3DERR_INVALIDCALL;
5774 oldTexture = This->updateStateBlock->textures[Stage];
5775 TRACE("GL_LIMITS %d\n",GL_LIMITS(sampler_stages));
5776 TRACE("(%p) : oldtexture(%p)\n", This,oldTexture);
5778 This->updateStateBlock->set.textures[Stage] = TRUE;
5779 This->updateStateBlock->changed.textures[Stage] = TRUE;
5780 TRACE("(%p) : setting new texture to %p\n", This, pTexture);
5781 This->updateStateBlock->textures[Stage] = pTexture;
5783 /* Handle recording of state blocks */
5784 if (This->isRecordingState) {
5785 TRACE("Recording... not performing anything\n");
5789 /** NOTE: MSDN says that setTexture increases the reference count,
5790 * and the the application nust set the texture back to null (or have a leaky application),
5791 * This means we should pass the refcount up to the parent
5792 *******************************/
5793 if (NULL != This->updateStateBlock->textures[Stage]) {
5794 IWineD3DBaseTexture_AddRef(This->updateStateBlock->textures[Stage]);
5797 if (NULL != oldTexture) {
5798 IWineD3DBaseTexture_Release(oldTexture);
5801 /* Reset color keying */
5802 if(Stage == 0 && This->stateBlock->renderState[WINED3DRS_COLORKEYENABLE]) {
5803 BOOL enable_ckey = FALSE;
5806 IWineD3DSurfaceImpl *surf = (IWineD3DSurfaceImpl *) ((IWineD3DTextureImpl *)pTexture)->surfaces[0];
5807 if(surf->CKeyFlags & DDSD_CKSRCBLT) enable_ckey = TRUE;
5811 glAlphaFunc(GL_NOTEQUAL, 0.0);
5812 checkGLcall("glAlphaFunc");
5819 static HRESULT WINAPI IWineD3DDeviceImpl_GetTexture(IWineD3DDevice *iface, DWORD Stage, IWineD3DBaseTexture** ppTexture) {
5820 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5821 TRACE("(%p) : (%d /* Stage */,%p /* ppTexture */)\n", This, Stage, ppTexture);
5823 /* Reject invalid texture units */
5824 if (Stage >= GL_LIMITS(sampler_stages)) {
5825 TRACE("Attempt to access invalid texture rejected\n");
5826 return WINED3DERR_INVALIDCALL;
5828 *ppTexture=This->stateBlock->textures[Stage];
5836 static HRESULT WINAPI IWineD3DDeviceImpl_GetBackBuffer(IWineD3DDevice *iface, UINT iSwapChain, UINT BackBuffer, WINED3DBACKBUFFER_TYPE Type,
5837 IWineD3DSurface **ppBackBuffer) {
5838 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5839 IWineD3DSwapChain *swapChain;
5842 TRACE("(%p) : BackBuf %d Type %d SwapChain %d returning %p\n", This, BackBuffer, Type, iSwapChain, *ppBackBuffer);
5844 hr = IWineD3DDeviceImpl_GetSwapChain(iface, iSwapChain, &swapChain);
5845 if (hr == WINED3D_OK) {
5846 hr = IWineD3DSwapChain_GetBackBuffer(swapChain, BackBuffer, Type, ppBackBuffer);
5847 IWineD3DSwapChain_Release(swapChain);
5849 *ppBackBuffer = NULL;
5854 static HRESULT WINAPI IWineD3DDeviceImpl_GetDeviceCaps(IWineD3DDevice *iface, WINED3DCAPS* pCaps) {
5855 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5856 WARN("(%p) : stub, calling idirect3d for now\n", This);
5857 return IWineD3D_GetDeviceCaps(This->wineD3D, This->adapterNo, This->devType, pCaps);
5860 static HRESULT WINAPI IWineD3DDeviceImpl_GetDisplayMode(IWineD3DDevice *iface, UINT iSwapChain, WINED3DDISPLAYMODE* pMode) {
5861 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5862 IWineD3DSwapChain *swapChain;
5865 if(iSwapChain > 0) {
5866 hr = IWineD3DDeviceImpl_GetSwapChain(iface, iSwapChain, (IWineD3DSwapChain **)&swapChain);
5867 if (hr == WINED3D_OK) {
5868 hr = IWineD3DSwapChain_GetDisplayMode(swapChain, pMode);
5869 IWineD3DSwapChain_Release(swapChain);
5871 FIXME("(%p) Error getting display mode\n", This);
5874 /* Don't read the real display mode,
5875 but return the stored mode instead. X11 can't change the color
5876 depth, and some apps are pretty angry if they SetDisplayMode from
5877 24 to 16 bpp and find out that GetDisplayMode still returns 24 bpp
5879 Also don't relay to the swapchain because with ddraw it's possible
5880 that there isn't a swapchain at all */
5881 pMode->Width = This->ddraw_width;
5882 pMode->Height = This->ddraw_height;
5883 pMode->Format = This->ddraw_format;
5884 pMode->RefreshRate = 0;
5891 static HRESULT WINAPI IWineD3DDeviceImpl_SetHWND(IWineD3DDevice *iface, HWND hWnd) {
5892 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5893 TRACE("(%p)->(%p)\n", This, hWnd);
5895 This->ddraw_window = hWnd;
5899 static HRESULT WINAPI IWineD3DDeviceImpl_GetHWND(IWineD3DDevice *iface, HWND *hWnd) {
5900 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5901 TRACE("(%p)->(%p)\n", This, hWnd);
5903 *hWnd = This->ddraw_window;
5908 * Stateblock related functions
5911 static HRESULT WINAPI IWineD3DDeviceImpl_BeginStateBlock(IWineD3DDevice *iface) {
5912 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5913 IWineD3DStateBlockImpl *object;
5914 HRESULT temp_result;
5916 TRACE("(%p)\n", This);
5918 if (This->isRecordingState) {
5919 return WINED3DERR_INVALIDCALL;
5922 object = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(IWineD3DStateBlockImpl));
5923 if (NULL == object ) {
5924 FIXME("(%p)Error allocating memory for stateblock\n", This);
5925 return E_OUTOFMEMORY;
5927 TRACE("(%p) created object %p\n", This, object);
5928 object->wineD3DDevice= This;
5929 /** FIXME: object->parent = parent; **/
5930 object->parent = NULL;
5931 object->blockType = WINED3DSBT_ALL;
5933 object->lpVtbl = &IWineD3DStateBlock_Vtbl;
5935 temp_result = allocate_shader_constants(object);
5936 if (WINED3D_OK != temp_result)
5939 IWineD3DStateBlock_Release((IWineD3DStateBlock*)This->updateStateBlock);
5940 This->updateStateBlock = object;
5941 This->isRecordingState = TRUE;
5943 TRACE("(%p) recording stateblock %p\n",This , object);
5947 static HRESULT WINAPI IWineD3DDeviceImpl_EndStateBlock(IWineD3DDevice *iface, IWineD3DStateBlock** ppStateBlock) {
5948 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5950 if (!This->isRecordingState) {
5951 FIXME("(%p) not recording! returning error\n", This);
5952 *ppStateBlock = NULL;
5953 return WINED3DERR_INVALIDCALL;
5956 *ppStateBlock = (IWineD3DStateBlock*)This->updateStateBlock;
5957 This->isRecordingState = FALSE;
5958 This->updateStateBlock = This->stateBlock;
5959 IWineD3DStateBlock_AddRef((IWineD3DStateBlock*)This->updateStateBlock);
5960 /* IWineD3DStateBlock_AddRef(*ppStateBlock); don't need to do this, since we should really just release UpdateStateBlock first */
5961 TRACE("(%p) returning token (ptr to stateblock) of %p\n", This, *ppStateBlock);
5966 * Scene related functions
5968 static HRESULT WINAPI IWineD3DDeviceImpl_BeginScene(IWineD3DDevice *iface) {
5969 /* At the moment we have no need for any functionality at the beginning
5971 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5972 TRACE("(%p) : stub\n", This);
5976 static HRESULT WINAPI IWineD3DDeviceImpl_EndScene(IWineD3DDevice *iface) {
5977 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5978 TRACE("(%p)\n", This);
5980 /* We only have to do this if we need to read the, swapbuffers performs a flush for us */
5982 checkGLcall("glFlush");
5984 TRACE("End Scene\n");
5985 /* If we're using FBOs this isn't needed */
5986 if (wined3d_settings.offscreen_rendering_mode != ORM_FBO && This->renderTarget != NULL) {
5988 /* If the container of the rendertarget is a texture then we need to save the data from the pbuffer */
5989 IUnknown *targetContainer = NULL;
5990 if (WINED3D_OK == IWineD3DSurface_GetContainer(This->renderTarget, &IID_IWineD3DBaseTexture, (void **)&targetContainer)
5991 || WINED3D_OK == IWineD3DSurface_GetContainer(This->renderTarget, &IID_IWineD3DDevice, (void **)&targetContainer)) {
5992 TRACE("(%p) : Texture rendertarget %p\n", This ,This->renderTarget);
5993 /** always dirtify for now. we must find a better way to see that surface have been modified
5994 (Modifications should will only occur via draw-primitive, but we do need better locking
5995 switching to render-to-texture should remove the overhead though.
5997 IWineD3DSurface_SetPBufferState(This->renderTarget, TRUE /* inPBuffer */, FALSE /* inTexture */);
5998 IWineD3DSurface_AddDirtyRect(This->renderTarget, NULL);
5999 IWineD3DSurface_PreLoad(This->renderTarget);
6000 IWineD3DSurface_SetPBufferState(This->renderTarget, FALSE /* inPBuffer */, FALSE /* inTexture */);
6001 IUnknown_Release(targetContainer);
6004 This->sceneEnded = TRUE;
6009 static HRESULT WINAPI IWineD3DDeviceImpl_Present(IWineD3DDevice *iface,
6010 CONST RECT* pSourceRect, CONST RECT* pDestRect,
6011 HWND hDestWindowOverride, CONST RGNDATA* pDirtyRegion) {
6012 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
6013 IWineD3DSwapChain *swapChain = NULL;
6015 int swapchains = IWineD3DDeviceImpl_GetNumberOfSwapChains(iface);
6017 TRACE("(%p) Presenting the frame\n", This);
6019 for(i = 0 ; i < swapchains ; i ++) {
6021 IWineD3DDeviceImpl_GetSwapChain(iface, i , (IWineD3DSwapChain **)&swapChain);
6022 TRACE("presentinng chain %d, %p\n", i, swapChain);
6023 IWineD3DSwapChain_Present(swapChain, pSourceRect, pDestRect, hDestWindowOverride, pDirtyRegion, 0);
6024 IWineD3DSwapChain_Release(swapChain);
6030 static HRESULT WINAPI IWineD3DDeviceImpl_Clear(IWineD3DDevice *iface, DWORD Count, CONST WINED3DRECT* pRects,
6031 DWORD Flags, WINED3DCOLOR Color, float Z, DWORD Stencil) {
6032 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
6034 /* TODO: From MSDN This method fails if you specify the WINED3DCLEAR_ZBUFFER or WINED3DCLEAR_STENCIL flags when the
6035 render target does not have an attached depth buffer. Similarly, if you specify the WINED3DCLEAR_STENCIL flag
6036 when the depth-buffer format does not contain stencil buffer information, this method fails. */
6037 GLbitfield glMask = 0;
6038 GLboolean old_ztest;
6039 GLfloat old_z_clear_value;
6040 GLint old_stencil_clear_value;
6041 GLfloat old_color_clear_value[4];
6043 CONST WINED3DRECT* curRect;
6045 TRACE("(%p) Count (%d), pRects (%p), Flags (%x), Z (%f), Stencil (%d)\n", This,
6046 Count, pRects, Flags, Z, Stencil);
6050 glEnable(GL_SCISSOR_TEST);
6051 checkGLcall("glEnable GL_SCISSOR_TEST");
6053 if (Count > 0 && pRects) {
6059 /* Only set the values up once, as they are not changing */
6060 if (Flags & WINED3DCLEAR_STENCIL) {
6061 glGetIntegerv(GL_STENCIL_CLEAR_VALUE, &old_stencil_clear_value);
6062 glClearStencil(Stencil);
6063 checkGLcall("glClearStencil");
6064 glMask = glMask | GL_STENCIL_BUFFER_BIT;
6065 glStencilMask(0xFFFFFFFF);
6068 if (Flags & WINED3DCLEAR_ZBUFFER) {
6069 glGetBooleanv(GL_DEPTH_WRITEMASK, &old_ztest);
6070 glDepthMask(GL_TRUE);
6071 glGetFloatv(GL_DEPTH_CLEAR_VALUE, &old_z_clear_value);
6073 checkGLcall("glClearDepth");
6074 glMask = glMask | GL_DEPTH_BUFFER_BIT;
6077 if (Flags & WINED3DCLEAR_TARGET) {
6078 TRACE("Clearing screen with glClear to color %x\n", Color);
6079 glGetFloatv(GL_COLOR_CLEAR_VALUE, old_color_clear_value);
6080 glClearColor(D3DCOLOR_R(Color),
6084 checkGLcall("glClearColor");
6086 /* Clear ALL colors! */
6087 glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
6088 glMask = glMask | GL_COLOR_BUFFER_BIT;
6091 /* Now process each rect in turn */
6092 for (i = 0; i < Count || i == 0; i++) {
6095 /* Note gl uses lower left, width/height */
6096 TRACE("(%p) %p Rect=(%d,%d)->(%d,%d) glRect=(%d,%d), len=%d, hei=%d\n", This, curRect,
6097 curRect->x1, curRect->y1, curRect->x2, curRect->y2,
6098 curRect->x1, (((IWineD3DSurfaceImpl *)This->renderTarget)->currentDesc.Height - curRect->y2),
6099 curRect->x2 - curRect->x1, curRect->y2 - curRect->y1);
6100 glScissor(curRect->x1, (((IWineD3DSurfaceImpl *)This->renderTarget)->currentDesc.Height - curRect->y2),
6101 curRect->x2 - curRect->x1, curRect->y2 - curRect->y1);
6102 checkGLcall("glScissor");
6104 glScissor(This->stateBlock->viewport.X,
6105 (((IWineD3DSurfaceImpl *)This->renderTarget)->currentDesc.Height -
6106 (This->stateBlock->viewport.Y + This->stateBlock->viewport.Height)),
6107 This->stateBlock->viewport.Width,
6108 This->stateBlock->viewport.Height);
6109 checkGLcall("glScissor");
6112 /* Clear the selected rectangle (or full screen) */
6114 checkGLcall("glClear");
6116 /* Step to the next rectangle */
6117 if (curRect) curRect = curRect + sizeof(WINED3DRECT);
6120 /* Restore the old values (why..?) */
6121 if (Flags & WINED3DCLEAR_STENCIL) {
6122 glClearStencil(old_stencil_clear_value);
6123 glStencilMask(This->stateBlock->renderState[WINED3DRS_STENCILWRITEMASK]);
6125 if (Flags & WINED3DCLEAR_ZBUFFER) {
6126 glDepthMask(old_ztest);
6127 glClearDepth(old_z_clear_value);
6129 if (Flags & WINED3DCLEAR_TARGET) {
6130 glClearColor(old_color_clear_value[0],
6131 old_color_clear_value[1],
6132 old_color_clear_value[2],
6133 old_color_clear_value[3]);
6134 glColorMask(This->stateBlock->renderState[WINED3DRS_COLORWRITEENABLE] & WINED3DCOLORWRITEENABLE_RED ? GL_TRUE : GL_FALSE,
6135 This->stateBlock->renderState[WINED3DRS_COLORWRITEENABLE] & WINED3DCOLORWRITEENABLE_GREEN ? GL_TRUE : GL_FALSE,
6136 This->stateBlock->renderState[WINED3DRS_COLORWRITEENABLE] & WINED3DCOLORWRITEENABLE_BLUE ? GL_TRUE : GL_FALSE,
6137 This->stateBlock->renderState[WINED3DRS_COLORWRITEENABLE] & WINED3DCOLORWRITEENABLE_ALPHA ? GL_TRUE : GL_FALSE);
6140 glDisable(GL_SCISSOR_TEST);
6141 checkGLcall("glDisable");
6150 static HRESULT WINAPI IWineD3DDeviceImpl_DrawPrimitive(IWineD3DDevice *iface, WINED3DPRIMITIVETYPE PrimitiveType, UINT StartVertex,
6151 UINT PrimitiveCount) {
6153 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
6154 This->stateBlock->streamIsUP = FALSE;
6156 TRACE("(%p) : Type=(%d,%s), Start=%d, Count=%d\n", This, PrimitiveType,
6157 debug_d3dprimitivetype(PrimitiveType),
6158 StartVertex, PrimitiveCount);
6159 drawPrimitive(iface, PrimitiveType, PrimitiveCount, StartVertex, 0/* NumVertices */, -1 /* indxStart */,
6160 0 /* indxSize */, NULL /* indxData */, 0 /* minIndex */, NULL);
6166 /* TODO: baseVIndex needs to be provided from This->stateBlock->baseVertexIndex when called from d3d8 */
6167 static HRESULT WINAPI IWineD3DDeviceImpl_DrawIndexedPrimitive(IWineD3DDevice *iface,
6168 WINED3DPRIMITIVETYPE PrimitiveType,
6169 INT baseVIndex, UINT minIndex,
6170 UINT NumVertices, UINT startIndex, UINT primCount) {
6172 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
6174 IWineD3DIndexBuffer *pIB;
6175 WINED3DINDEXBUFFER_DESC IdxBufDsc;
6177 pIB = This->stateBlock->pIndexData;
6178 This->stateBlock->streamIsUP = FALSE;
6180 TRACE("(%p) : Type=(%d,%s), min=%d, CountV=%d, startIdx=%d, baseVidx=%d, countP=%d\n", This,
6181 PrimitiveType, debug_d3dprimitivetype(PrimitiveType),
6182 minIndex, NumVertices, startIndex, baseVIndex, primCount);
6184 IWineD3DIndexBuffer_GetDesc(pIB, &IdxBufDsc);
6185 if (IdxBufDsc.Format == WINED3DFMT_INDEX16) {
6191 drawPrimitive(iface, PrimitiveType, primCount, baseVIndex, NumVertices, startIndex,
6192 idxStride, ((IWineD3DIndexBufferImpl *) pIB)->resource.allocatedMemory, minIndex, NULL);
6197 static HRESULT WINAPI IWineD3DDeviceImpl_DrawPrimitiveUP(IWineD3DDevice *iface, WINED3DPRIMITIVETYPE PrimitiveType,
6198 UINT PrimitiveCount, CONST void* pVertexStreamZeroData,
6199 UINT VertexStreamZeroStride) {
6200 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
6202 TRACE("(%p) : Type=(%d,%s), pCount=%d, pVtxData=%p, Stride=%d\n", This, PrimitiveType,
6203 debug_d3dprimitivetype(PrimitiveType),
6204 PrimitiveCount, pVertexStreamZeroData, VertexStreamZeroStride);
6206 /* release the stream source */
6207 if (This->stateBlock->streamSource[0] != NULL) {
6208 IWineD3DVertexBuffer_Release(This->stateBlock->streamSource[0]);
6211 /* Note in the following, it's not this type, but that's the purpose of streamIsUP */
6212 This->stateBlock->streamSource[0] = (IWineD3DVertexBuffer *)pVertexStreamZeroData;
6213 This->stateBlock->streamStride[0] = VertexStreamZeroStride;
6214 This->stateBlock->streamIsUP = TRUE;
6216 drawPrimitive(iface, PrimitiveType, PrimitiveCount, 0 /* start vertex */, 0 /* NumVertices */,
6217 0 /* indxStart*/, 0 /* indxSize*/, NULL /* indxData */, 0 /* indxMin */, NULL);
6219 /* MSDN specifies stream zero settings must be set to NULL */
6220 This->stateBlock->streamStride[0] = 0;
6221 This->stateBlock->streamSource[0] = NULL;
6223 /*stream zero settings set to null at end, as per the msdn */
6227 static HRESULT WINAPI IWineD3DDeviceImpl_DrawIndexedPrimitiveUP(IWineD3DDevice *iface, WINED3DPRIMITIVETYPE PrimitiveType,
6228 UINT MinVertexIndex, UINT NumVertices,
6229 UINT PrimitiveCount, CONST void* pIndexData,
6230 WINED3DFORMAT IndexDataFormat,CONST void* pVertexStreamZeroData,
6231 UINT VertexStreamZeroStride) {
6233 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
6235 TRACE("(%p) : Type=(%d,%s), MinVtxIdx=%d, NumVIdx=%d, PCount=%d, pidxdata=%p, IdxFmt=%d, pVtxdata=%p, stride=%d\n",
6236 This, PrimitiveType, debug_d3dprimitivetype(PrimitiveType),
6237 MinVertexIndex, NumVertices, PrimitiveCount, pIndexData,
6238 IndexDataFormat, pVertexStreamZeroData, VertexStreamZeroStride);
6240 if (IndexDataFormat == WINED3DFMT_INDEX16) {
6246 /* release the stream and index data */
6247 if (This->stateBlock->streamSource[0] != NULL) {
6248 IWineD3DVertexBuffer_Release(This->stateBlock->streamSource[0]);
6250 if (This->stateBlock->pIndexData) {
6251 IWineD3DIndexBuffer_Release(This->stateBlock->pIndexData);
6254 /* Note in the following, it's not this type, but that's the purpose of streamIsUP */
6255 This->stateBlock->streamSource[0] = (IWineD3DVertexBuffer *)pVertexStreamZeroData;
6256 This->stateBlock->streamIsUP = TRUE;
6257 This->stateBlock->streamStride[0] = VertexStreamZeroStride;
6259 drawPrimitive(iface, PrimitiveType, PrimitiveCount, 0 /* vertexStart */, NumVertices, 0 /* indxStart */, idxStride, pIndexData, MinVertexIndex, NULL);
6261 /* MSDN specifies stream zero settings and index buffer must be set to NULL */
6262 This->stateBlock->streamSource[0] = NULL;
6263 This->stateBlock->streamStride[0] = 0;
6264 This->stateBlock->pIndexData = NULL;
6269 static HRESULT WINAPI IWineD3DDeviceImpl_DrawPrimitiveStrided (IWineD3DDevice *iface, WINED3DPRIMITIVETYPE PrimitiveType, UINT PrimitiveCount, WineDirect3DVertexStridedData *DrawPrimStrideData) {
6271 drawPrimitive(iface, PrimitiveType, PrimitiveCount, 0, 0, 0, 0, NULL, 0, DrawPrimStrideData);
6274 /* Yet another way to update a texture, some apps use this to load default textures instead of using surface/texture lock/unlock */
6275 static HRESULT WINAPI IWineD3DDeviceImpl_UpdateTexture (IWineD3DDevice *iface, IWineD3DBaseTexture *pSourceTexture, IWineD3DBaseTexture *pDestinationTexture){
6276 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
6277 HRESULT hr = WINED3D_OK;
6278 WINED3DRESOURCETYPE sourceType;
6279 WINED3DRESOURCETYPE destinationType;
6282 /* TODO: think about moving the code into IWineD3DBaseTexture */
6284 TRACE("(%p) Source %p Destination %p\n", This, pSourceTexture, pDestinationTexture);
6286 /* verify that the source and destination textures aren't NULL */
6287 if (NULL == pSourceTexture || NULL == pDestinationTexture) {
6288 WARN("(%p) : source (%p) and destination (%p) textures must not be NULL, returning WINED3DERR_INVALIDCALL\n",
6289 This, pSourceTexture, pDestinationTexture);
6290 hr = WINED3DERR_INVALIDCALL;
6293 if (pSourceTexture == pDestinationTexture) {
6294 WARN("(%p) : source (%p) and destination (%p) textures must be different, returning WINED3DERR_INVALIDCALL\n",
6295 This, pSourceTexture, pDestinationTexture);
6296 hr = WINED3DERR_INVALIDCALL;
6298 /* Verify that the source and destination textures are the same type */
6299 sourceType = IWineD3DBaseTexture_GetType(pSourceTexture);
6300 destinationType = IWineD3DBaseTexture_GetType(pDestinationTexture);
6302 if (sourceType != destinationType) {
6303 WARN("(%p) Sorce and destination types must match, returning WINED3DERR_INVALIDCALL\n",
6305 hr = WINED3DERR_INVALIDCALL;
6308 /* check that both textures have the identical numbers of levels */
6309 if (IWineD3DBaseTexture_GetLevelCount(pDestinationTexture) != IWineD3DBaseTexture_GetLevelCount(pSourceTexture)) {
6310 WARN("(%p) : source (%p) and destination (%p) textures must have identicle numbers of levels, returning WINED3DERR_INVALIDCALL\n", This, pSourceTexture, pDestinationTexture);
6311 hr = WINED3DERR_INVALIDCALL;
6314 if (WINED3D_OK == hr) {
6316 /* Make sure that the destination texture is loaded */
6317 IWineD3DBaseTexture_PreLoad(pDestinationTexture);
6319 /* Update every surface level of the texture */
6320 levels = IWineD3DBaseTexture_GetLevelCount(pDestinationTexture);
6322 switch (sourceType) {
6323 case WINED3DRTYPE_TEXTURE:
6325 IWineD3DSurface *srcSurface;
6326 IWineD3DSurface *destSurface;
6328 for (i = 0 ; i < levels ; ++i) {
6329 IWineD3DTexture_GetSurfaceLevel((IWineD3DTexture *)pSourceTexture, i, &srcSurface);
6330 IWineD3DTexture_GetSurfaceLevel((IWineD3DTexture *)pDestinationTexture, i, &destSurface);
6331 hr = IWineD3DDevice_UpdateSurface(iface, srcSurface, NULL, destSurface, NULL);
6332 IWineD3DSurface_Release(srcSurface);
6333 IWineD3DSurface_Release(destSurface);
6334 if (WINED3D_OK != hr) {
6335 WARN("(%p) : Call to update surface failed\n", This);
6341 case WINED3DRTYPE_CUBETEXTURE:
6343 IWineD3DSurface *srcSurface;
6344 IWineD3DSurface *destSurface;
6345 WINED3DCUBEMAP_FACES faceType;
6347 for (i = 0 ; i < levels ; ++i) {
6348 /* Update each cube face */
6349 for (faceType = WINED3DCUBEMAP_FACE_POSITIVE_X; faceType <= WINED3DCUBEMAP_FACE_NEGATIVE_Z; ++faceType){
6350 hr = IWineD3DCubeTexture_GetCubeMapSurface((IWineD3DCubeTexture *)pSourceTexture, faceType, i, &srcSurface);
6351 if (WINED3D_OK != hr) {
6352 FIXME("(%p) : Failed to get src cube surface facetype %d, level %d\n", This, faceType, i);
6354 TRACE("Got srcSurface %p\n", srcSurface);
6356 hr = IWineD3DCubeTexture_GetCubeMapSurface((IWineD3DCubeTexture *)pDestinationTexture, faceType, i, &destSurface);
6357 if (WINED3D_OK != hr) {
6358 FIXME("(%p) : Failed to get src cube surface facetype %d, level %d\n", This, faceType, i);
6360 TRACE("Got desrSurface %p\n", destSurface);
6362 hr = IWineD3DDevice_UpdateSurface(iface, srcSurface, NULL, destSurface, NULL);
6363 IWineD3DSurface_Release(srcSurface);
6364 IWineD3DSurface_Release(destSurface);
6365 if (WINED3D_OK != hr) {
6366 WARN("(%p) : Call to update surface failed\n", This);
6373 #if 0 /* TODO: Add support for volume textures */
6374 case WINED3DRTYPE_VOLUMETEXTURE:
6376 IWineD3DVolume srcVolume = NULL;
6377 IWineD3DSurface destVolume = NULL;
6379 for (i = 0 ; i < levels ; ++i) {
6380 IWineD3DVolumeTexture_GetVolume((IWineD3DVolumeTexture *)pSourceTexture, i, &srcVolume);
6381 IWineD3DVolumeTexture_GetVolume((IWineD3DVolumeTexture *)pDestinationTexture, i, &destVolume);
6382 hr = IWineD3DFoo_UpdateVolume(iface, srcVolume, NULL, destVolume, NULL);
6383 IWineD3DVolume_Release(srcSurface);
6384 IWineD3DVolume_Release(destSurface);
6385 if (WINED3D_OK != hr) {
6386 WARN("(%p) : Call to update volume failed\n", This);
6394 FIXME("(%p) : Unsupported source and destination type\n", This);
6395 hr = WINED3DERR_INVALIDCALL;
6402 static HRESULT WINAPI IWineD3DDeviceImpl_StretchRect(IWineD3DDevice *iface, IWineD3DSurface *pSourceSurface,
6403 CONST RECT* pSourceRect, IWineD3DSurface *pDestinationSurface,
6404 CONST RECT* pDestRect, WINED3DTEXTUREFILTERTYPE Filter) {
6405 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
6407 TRACE("(%p) : stub\n", This);
6410 static HRESULT WINAPI IWineD3DDeviceImpl_GetRenderTargetData(IWineD3DDevice *iface, IWineD3DSurface *pRenderTarget, IWineD3DSurface *pSurface) {
6411 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
6412 /** TODO: remove remove casts to IWineD3DSurfaceImpl *
6413 * NOTE It may be best to move the code into surface to occomplish this
6414 ****************************************/
6416 WINED3DSURFACE_DESC surfaceDesc;
6417 unsigned int surfaceWidth, surfaceHeight;
6418 glDescriptor *targetGlDescription = NULL;
6419 glDescriptor *surfaceGlDescription = NULL;
6420 IWineD3DSwapChainImpl *container = NULL;
6422 IWineD3DSurface_GetGlDesc(pRenderTarget, &targetGlDescription);
6423 IWineD3DSurface_GetGlDesc(pSurface, &surfaceGlDescription);
6424 memset(&surfaceDesc, 0, sizeof(surfaceDesc));
6426 surfaceDesc.Width = &surfaceWidth;
6427 surfaceDesc.Height = &surfaceHeight;
6428 IWineD3DSurface_GetDesc(pSurface, &surfaceDesc);
6429 /* check to see if it's the backbuffer or the frontbuffer being requested (to make sure the data is up to date)*/
6431 /* Ok, I may need to setup some kind of active swapchain reference on the device */
6432 IWineD3DSurface_GetContainer(pRenderTarget, &IID_IWineD3DSwapChain, (void **)&container);
6434 /* TODO: opengl Context switching for swapchains etc... */
6435 if (NULL != container || pRenderTarget == This->renderTarget || pRenderTarget == This->depthStencilBuffer) {
6436 if (NULL != container && (pRenderTarget == container->backBuffer[0])) {
6437 glReadBuffer(GL_BACK);
6438 vcheckGLcall("glReadBuffer(GL_BACK)");
6439 } else if ((NULL != container && (pRenderTarget == container->frontBuffer)) || (pRenderTarget == This->renderTarget)) {
6440 glReadBuffer(GL_FRONT);
6441 vcheckGLcall("glReadBuffer(GL_FRONT)");
6442 } else if (pRenderTarget == This->depthStencilBuffer) {
6443 FIXME("Reading of depthstencil not yet supported\n");
6450 surfaceGlDescription->glFormat,
6451 surfaceGlDescription->glType,
6452 (void *)IWineD3DSurface_GetData(pSurface));
6453 vcheckGLcall("glReadPixels(...)");
6454 if(NULL != container ){
6455 IWineD3DSwapChain_Release((IWineD3DSwapChain*) container);
6458 IWineD3DBaseTexture *container;
6459 GLenum textureDimensions = GL_TEXTURE_2D;
6461 if (WINED3D_OK == IWineD3DSurface_GetContainer(pSurface, &IID_IWineD3DBaseTexture, (void **)&container)) {
6462 textureDimensions = IWineD3DBaseTexture_GetTextureDimensions(container);
6463 IWineD3DBaseTexture_Release(container);
6465 /* TODO: 2D -> Cube surface coppies etc.. */
6466 if (surfaceGlDescription->target != textureDimensions) {
6467 FIXME("(%p) : Texture dimension mismatch\n", This);
6469 glEnable(textureDimensions);
6470 vcheckGLcall("glEnable(GL_TEXTURE_...)");
6471 /* FIXME: this isn't correct, it need to add a dirty rect if nothing else... */
6472 glBindTexture(targetGlDescription->target, targetGlDescription->textureName);
6473 vcheckGLcall("glBindTexture");
6474 glGetTexImage(surfaceGlDescription->target,
6475 surfaceGlDescription->level,
6476 surfaceGlDescription->glFormat,
6477 surfaceGlDescription->glType,
6478 (void *)IWineD3DSurface_GetData(pSurface));
6479 glDisable(textureDimensions);
6480 vcheckGLcall("glDisable(GL_TEXTURE_...)");
6487 static HRESULT WINAPI IWineD3DDeviceImpl_GetFrontBufferData(IWineD3DDevice *iface,UINT iSwapChain, IWineD3DSurface *pDestSurface) {
6488 IWineD3DSwapChain *swapChain;
6490 hr = IWineD3DDeviceImpl_GetSwapChain(iface, iSwapChain, (IWineD3DSwapChain **)&swapChain);
6491 if(hr == WINED3D_OK) {
6492 hr = IWineD3DSwapChain_GetFrontBufferData(swapChain, pDestSurface);
6493 IWineD3DSwapChain_Release(swapChain);
6498 static HRESULT WINAPI IWineD3DDeviceImpl_ValidateDevice(IWineD3DDevice *iface, DWORD* pNumPasses) {
6499 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
6500 /* return a sensible default */
6502 /* TODO: If the window is minimized then validate device should return something other than WINED3D_OK */
6503 FIXME("(%p) : stub\n", This);
6507 static HRESULT WINAPI IWineD3DDeviceImpl_SetPaletteEntries(IWineD3DDevice *iface, UINT PaletteNumber, CONST PALETTEENTRY* pEntries) {
6508 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
6510 TRACE("(%p) : PaletteNumber %u\n", This, PaletteNumber);
6511 if ( PaletteNumber < 0 || PaletteNumber >= MAX_PALETTES) {
6512 WARN("(%p) : (%u) Out of range 0-%u, returning Invalid Call\n", This, PaletteNumber, MAX_PALETTES);
6513 return WINED3DERR_INVALIDCALL;
6515 for (j = 0; j < 256; ++j) {
6516 This->palettes[PaletteNumber][j].peRed = pEntries[j].peRed;
6517 This->palettes[PaletteNumber][j].peGreen = pEntries[j].peGreen;
6518 This->palettes[PaletteNumber][j].peBlue = pEntries[j].peBlue;
6519 This->palettes[PaletteNumber][j].peFlags = pEntries[j].peFlags;
6521 TRACE("(%p) : returning\n", This);
6525 static HRESULT WINAPI IWineD3DDeviceImpl_GetPaletteEntries(IWineD3DDevice *iface, UINT PaletteNumber, PALETTEENTRY* pEntries) {
6526 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
6528 TRACE("(%p) : PaletteNumber %u\n", This, PaletteNumber);
6529 if ( PaletteNumber < 0 || PaletteNumber >= MAX_PALETTES) {
6530 WARN("(%p) : (%u) Out of range 0-%u, returning Invalid Call\n", This, PaletteNumber, MAX_PALETTES);
6531 return WINED3DERR_INVALIDCALL;
6533 for (j = 0; j < 256; ++j) {
6534 pEntries[j].peRed = This->palettes[PaletteNumber][j].peRed;
6535 pEntries[j].peGreen = This->palettes[PaletteNumber][j].peGreen;
6536 pEntries[j].peBlue = This->palettes[PaletteNumber][j].peBlue;
6537 pEntries[j].peFlags = This->palettes[PaletteNumber][j].peFlags;
6539 TRACE("(%p) : returning\n", This);
6543 static HRESULT WINAPI IWineD3DDeviceImpl_SetCurrentTexturePalette(IWineD3DDevice *iface, UINT PaletteNumber) {
6544 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
6545 TRACE("(%p) : PaletteNumber %u\n", This, PaletteNumber);
6546 if ( PaletteNumber < 0 || PaletteNumber >= MAX_PALETTES) {
6547 WARN("(%p) : (%u) Out of range 0-%u, returning Invalid Call\n", This, PaletteNumber, MAX_PALETTES);
6548 return WINED3DERR_INVALIDCALL;
6550 /*TODO: stateblocks */
6551 This->currentPalette = PaletteNumber;
6552 TRACE("(%p) : returning\n", This);
6556 static HRESULT WINAPI IWineD3DDeviceImpl_GetCurrentTexturePalette(IWineD3DDevice *iface, UINT* PaletteNumber) {
6557 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
6558 if (PaletteNumber == NULL) {
6559 WARN("(%p) : returning Invalid Call\n", This);
6560 return WINED3DERR_INVALIDCALL;
6562 /*TODO: stateblocks */
6563 *PaletteNumber = This->currentPalette;
6564 TRACE("(%p) : returning %u\n", This, *PaletteNumber);
6568 static HRESULT WINAPI IWineD3DDeviceImpl_SetSoftwareVertexProcessing(IWineD3DDevice *iface, BOOL bSoftware) {
6569 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
6570 static BOOL showFixmes = TRUE;
6572 FIXME("(%p) : stub\n", This);
6576 This->softwareVertexProcessing = bSoftware;
6581 static BOOL WINAPI IWineD3DDeviceImpl_GetSoftwareVertexProcessing(IWineD3DDevice *iface) {
6582 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
6583 static BOOL showFixmes = TRUE;
6585 FIXME("(%p) : stub\n", This);
6588 return This->softwareVertexProcessing;
6592 static HRESULT WINAPI IWineD3DDeviceImpl_GetRasterStatus(IWineD3DDevice *iface, UINT iSwapChain, WINED3DRASTER_STATUS* pRasterStatus) {
6593 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
6594 IWineD3DSwapChain *swapChain;
6597 TRACE("(%p) : SwapChain %d returning %p\n", This, iSwapChain, pRasterStatus);
6599 hr = IWineD3DDeviceImpl_GetSwapChain(iface, iSwapChain, (IWineD3DSwapChain **)&swapChain);
6600 if(hr == WINED3D_OK){
6601 hr = IWineD3DSwapChain_GetRasterStatus(swapChain, pRasterStatus);
6602 IWineD3DSwapChain_Release(swapChain);
6604 FIXME("(%p) IWineD3DSwapChain_GetRasterStatus returned in error\n", This);
6610 static HRESULT WINAPI IWineD3DDeviceImpl_SetNPatchMode(IWineD3DDevice *iface, float nSegments) {
6611 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
6612 static BOOL showfixmes = TRUE;
6613 if(nSegments != 0.0f) {
6615 FIXME("(%p) : stub nSegments(%f)\n", This, nSegments);
6622 static float WINAPI IWineD3DDeviceImpl_GetNPatchMode(IWineD3DDevice *iface) {
6623 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
6624 static BOOL showfixmes = TRUE;
6626 FIXME("(%p) : stub returning(%f)\n", This, 0.0f);
6632 static HRESULT WINAPI IWineD3DDeviceImpl_UpdateSurface(IWineD3DDevice *iface, IWineD3DSurface *pSourceSurface, CONST RECT* pSourceRect, IWineD3DSurface *pDestinationSurface, CONST POINT* pDestPoint) {
6633 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *) iface;
6634 /** TODO: remove casts to IWineD3DSurfaceImpl
6635 * NOTE: move code to surface to accomplish this
6636 ****************************************/
6637 IWineD3DSurfaceImpl *pSrcSurface = (IWineD3DSurfaceImpl *)pSourceSurface;
6638 int srcWidth, srcHeight;
6639 unsigned int srcSurfaceWidth, srcSurfaceHeight, destSurfaceWidth, destSurfaceHeight;
6640 WINED3DFORMAT destFormat, srcFormat;
6642 int destLeft, destTop;
6643 WINED3DPOOL srcPool, destPool;
6645 int rowoffset = 0; /* how many bytes to add onto the end of a row to wraparound to the beginning of the next */
6646 glDescriptor *glDescription = NULL;
6647 GLenum textureDimensions = GL_TEXTURE_2D;
6648 IWineD3DBaseTexture *baseTexture;
6650 WINED3DSURFACE_DESC winedesc;
6652 TRACE("(%p) : Source (%p) Rect (%p) Destination (%p) Point(%p)\n", This, pSourceSurface, pSourceRect, pDestinationSurface, pDestPoint);
6653 memset(&winedesc, 0, sizeof(winedesc));
6654 winedesc.Width = &srcSurfaceWidth;
6655 winedesc.Height = &srcSurfaceHeight;
6656 winedesc.Pool = &srcPool;
6657 winedesc.Format = &srcFormat;
6659 IWineD3DSurface_GetDesc(pSourceSurface, &winedesc);
6661 winedesc.Width = &destSurfaceWidth;
6662 winedesc.Height = &destSurfaceHeight;
6663 winedesc.Pool = &destPool;
6664 winedesc.Format = &destFormat;
6665 winedesc.Size = &destSize;
6667 IWineD3DSurface_GetDesc(pDestinationSurface, &winedesc);
6669 if(srcPool != WINED3DPOOL_SYSTEMMEM || destPool != WINED3DPOOL_DEFAULT){
6670 WARN("source %p must be SYSTEMMEM and dest %p must be DEFAULT, returning WINED3DERR_INVALIDCALL\n", pSourceSurface, pDestinationSurface);
6671 return WINED3DERR_INVALIDCALL;
6674 if (destFormat == WINED3DFMT_UNKNOWN) {
6675 TRACE("(%p) : Converting destination surface from WINED3DFMT_UNKNOWN to the source format\n", This);
6676 IWineD3DSurface_SetFormat(pDestinationSurface, srcFormat);
6678 /* Get the update surface description */
6679 IWineD3DSurface_GetDesc(pDestinationSurface, &winedesc);
6682 /* Make sure the surface is loaded and up to date */
6683 IWineD3DSurface_PreLoad(pDestinationSurface);
6685 IWineD3DSurface_GetGlDesc(pDestinationSurface, &glDescription);
6689 /* this needs to be done in lines if the sourceRect != the sourceWidth */
6690 srcWidth = pSourceRect ? pSourceRect->right - pSourceRect->left : srcSurfaceWidth;
6691 srcHeight = pSourceRect ? pSourceRect->top - pSourceRect->bottom : srcSurfaceHeight;
6692 destLeft = pDestPoint ? pDestPoint->x : 0;
6693 destTop = pDestPoint ? pDestPoint->y : 0;
6696 /* This function doesn't support compressed textures
6697 the pitch is just bytesPerPixel * width */
6698 if(srcWidth != srcSurfaceWidth || (pSourceRect != NULL && pSourceRect->left != 0) ){
6699 rowoffset = (srcSurfaceWidth - srcWidth) * pSrcSurface->bytesPerPixel;
6700 offset += pSourceRect->left * pSrcSurface->bytesPerPixel;
6701 /* TODO: do we ever get 3bpp?, would a shift and an add be quicker than a mul (well maybe a cycle or two) */
6703 /* TODO DXT formats */
6705 if(pSourceRect != NULL && pSourceRect->top != 0){
6706 offset += pSourceRect->top * srcWidth * pSrcSurface->bytesPerPixel;
6708 TRACE("(%p) glTexSubImage2D, Level %d, left %d, top %d, width %d, height %d , ftm %d, type %d, memory %p\n"
6710 ,glDescription->level
6715 ,glDescription->glFormat
6716 ,glDescription->glType
6717 ,IWineD3DSurface_GetData(pSourceSurface)
6721 if (IWineD3DSurface_GetData(pSourceSurface) == NULL) {
6723 /* need to lock the surface to get the data */
6724 FIXME("Surfaces has no allocated memory, but should be an in memory only surface\n");
6727 /* TODO: Cube and volume support */
6729 /* not a whole row so we have to do it a line at a time */
6732 /* hopefully using pointer addtion will be quicker than using a point + j * rowoffset */
6733 unsigned char* data =((unsigned char *)IWineD3DSurface_GetData(pSourceSurface)) + offset;
6735 for(j = destTop ; j < (srcHeight + destTop) ; j++){
6737 glTexSubImage2D(glDescription->target
6738 ,glDescription->level
6743 ,glDescription->glFormat
6744 ,glDescription->glType
6745 ,data /* could be quicker using */
6750 } else { /* Full width, so just write out the whole texture */
6752 if (WINED3DFMT_DXT1 == destFormat ||
6753 WINED3DFMT_DXT2 == destFormat ||
6754 WINED3DFMT_DXT3 == destFormat ||
6755 WINED3DFMT_DXT4 == destFormat ||
6756 WINED3DFMT_DXT5 == destFormat) {
6757 if (GL_SUPPORT(EXT_TEXTURE_COMPRESSION_S3TC)) {
6758 if (destSurfaceHeight != srcHeight || destSurfaceWidth != srcWidth) {
6759 /* FIXME: The easy way to do this is to lock the destination, and copy the bits across */
6760 FIXME("Updating part of a compressed texture is not supported at the moment\n");
6761 } if (destFormat != srcFormat) {
6762 FIXME("Updating mixed format compressed texture is not curretly support\n");
6764 GL_EXTCALL(glCompressedTexImage2DARB)(glDescription->target,
6765 glDescription->level,
6766 glDescription->glFormatInternal,
6771 IWineD3DSurface_GetData(pSourceSurface));
6774 FIXME("Attempting to update a DXT compressed texture without hardware support\n");
6779 if (NP2_REPACK == wined3d_settings.nonpower2_mode) {
6781 /* some applications cannot handle odd pitches returned by soft non-power2, so we have
6782 to repack the data from pow2Width/Height to expected Width,Height, this makes the
6783 data returned by GetData non-power2 width/height with hardware non-power2
6784 pow2Width/height are set to surface width height, repacking isn't needed so it
6785 doesn't matter which function gets called. */
6786 glTexSubImage2D(glDescription->target
6787 ,glDescription->level
6792 ,glDescription->glFormat
6793 ,glDescription->glType
6794 ,IWineD3DSurface_GetData(pSourceSurface)
6798 /* not repacked, the data returned by IWineD3DSurface_GetData is pow2Width x pow2Height */
6799 glTexSubImage2D(glDescription->target
6800 ,glDescription->level
6803 ,((IWineD3DSurfaceImpl *)pSourceSurface)->pow2Width
6804 ,((IWineD3DSurfaceImpl *)pSourceSurface)->pow2Height
6805 ,glDescription->glFormat
6806 ,glDescription->glType
6807 ,IWineD3DSurface_GetData(pSourceSurface)
6813 checkGLcall("glTexSubImage2D");
6814 ((IWineD3DSurfaceImpl *)pDestinationSurface)->Flags |= SFLAG_GLDIRTY;
6816 /* I only need to look up baseTexture here, so it may be a good idea to hava a GL_TARGET ->
6817 * GL_DIMENSIONS lookup, or maybe store the dimensions on the surface (but that's making the
6818 * surface bigger than it needs to be hmm.. */
6819 if (WINED3D_OK == IWineD3DSurface_GetContainer(pDestinationSurface, &IID_IWineD3DBaseTexture, (void **)&baseTexture)) {
6820 textureDimensions = IWineD3DBaseTexture_GetTextureDimensions(baseTexture);
6821 IWineD3DBaseTexture_Release(baseTexture);
6824 glDisable(textureDimensions); /* This needs to be managed better.... */
6830 /* Implementation details at http://developer.nvidia.com/attach/6494
6832 http://oss.sgi.com/projects/ogl-sample/registry/NV/evaluators.txt
6833 hmm.. no longer supported use
6834 OpenGL evaluators or tessellate surfaces within your application.
6837 /* http://msdn.microsoft.com/library/default.asp?url=/library/en-us/directx9_c/directx/graphics/reference/d3d/interfaces/idirect3ddevice9/DrawRectPatch.asp */
6838 static HRESULT WINAPI IWineD3DDeviceImpl_DrawRectPatch(IWineD3DDevice *iface, UINT Handle, CONST float* pNumSegs, CONST WINED3DRECTPATCH_INFO* pRectPatchInfo) {
6839 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
6840 TRACE("(%p) Handle(%d) noSegs(%p) rectpatch(%p)\n", This, Handle, pNumSegs, pRectPatchInfo);
6841 FIXME("(%p) : Stub\n", This);
6846 /* http://msdn.microsoft.com/library/default.asp?url=/library/en-us/directx9_c/directx/graphics/reference/d3d/interfaces/idirect3ddevice9/DrawTriPatch.asp */
6847 static HRESULT WINAPI IWineD3DDeviceImpl_DrawTriPatch(IWineD3DDevice *iface, UINT Handle, CONST float* pNumSegs, CONST WINED3DTRIPATCH_INFO* pTriPatchInfo) {
6848 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
6849 TRACE("(%p) Handle(%d) noSegs(%p) tripatch(%p)\n", This, Handle, pNumSegs, pTriPatchInfo);
6850 FIXME("(%p) : Stub\n", This);
6854 static HRESULT WINAPI IWineD3DDeviceImpl_DeletePatch(IWineD3DDevice *iface, UINT Handle) {
6855 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
6856 TRACE("(%p) Handle(%d)\n", This, Handle);
6857 FIXME("(%p) : Stub\n", This);
6861 static HRESULT WINAPI IWineD3DDeviceImpl_ColorFill(IWineD3DDevice *iface, IWineD3DSurface *pSurface, CONST WINED3DRECT* pRect, WINED3DCOLOR color) {
6862 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *) iface;
6863 IWineD3DSurfaceImpl *surface = (IWineD3DSurfaceImpl *) pSurface;
6865 TRACE("(%p) Colour fill Surface: %p rect: %p color: %d\n", This, pSurface, pRect, color);
6867 if (surface->resource.pool != WINED3DPOOL_DEFAULT && surface->resource.pool != WINED3DPOOL_SYSTEMMEM) {
6868 FIXME("call to colorfill with non WINED3DPOOL_DEFAULT or WINED3DPOOL_SYSTEMMEM surface\n");
6869 return WINED3DERR_INVALIDCALL;
6872 /* Just forward this to the DirectDraw blitting engine */
6873 memset(&BltFx, 0, sizeof(BltFx));
6874 BltFx.dwSize = sizeof(BltFx);
6875 BltFx.u5.dwFillColor = color;
6876 return IWineD3DSurface_Blt(pSurface, (RECT *) pRect, NULL, NULL, DDBLT_COLORFILL, &BltFx);
6879 /* rendertarget and deptth stencil functions */
6880 static HRESULT WINAPI IWineD3DDeviceImpl_GetRenderTarget(IWineD3DDevice* iface,DWORD RenderTargetIndex, IWineD3DSurface **ppRenderTarget) {
6881 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
6883 /* FIXME: Implelent RenderTargetIndex >0 */
6884 if(RenderTargetIndex > 0)
6885 FIXME("(%p) : RenderTargetIndex %d >0 not currently supported\n", This, RenderTargetIndex);
6887 *ppRenderTarget = This->renderTarget;
6888 TRACE("(%p) : RenderTarget %d Index returning %p\n", This, RenderTargetIndex, *ppRenderTarget);
6893 static HRESULT WINAPI IWineD3DDeviceImpl_SetFrontBackBuffers(IWineD3DDevice *iface, IWineD3DSurface *Front, IWineD3DSurface *Back) {
6894 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
6895 IWineD3DSurfaceImpl *FrontImpl = (IWineD3DSurfaceImpl *) Front;
6896 IWineD3DSurfaceImpl *BackImpl = (IWineD3DSurfaceImpl *) Back;
6897 IWineD3DSwapChainImpl *Swapchain;
6900 TRACE("(%p)->(%p,%p)\n", This, FrontImpl, BackImpl);
6902 hr = IWineD3DDevice_GetSwapChain(iface, 0, (IWineD3DSwapChain **) &Swapchain);
6903 if(hr != WINED3D_OK) {
6904 ERR("Can't get the swapchain\n");
6908 /* Make sure to release the swapchain */
6909 IWineD3DSwapChain_Release((IWineD3DSwapChain *) Swapchain);
6911 if(FrontImpl && !(FrontImpl->resource.usage & WINED3DUSAGE_RENDERTARGET) ) {
6912 ERR("Trying to set a front buffer which doesn't have WINED3DUSAGE_RENDERTARGET usage\n");
6913 return WINED3DERR_INVALIDCALL;
6915 else if(BackImpl && !(BackImpl->resource.usage & WINED3DUSAGE_RENDERTARGET)) {
6916 ERR("Trying to set a back buffer which doesn't have WINED3DUSAGE_RENDERTARGET usage\n");
6917 return WINED3DERR_INVALIDCALL;
6920 if(Swapchain->frontBuffer != Front) {
6921 TRACE("Changing the front buffer from %p to %p\n", Swapchain->frontBuffer, Front);
6923 if(Swapchain->frontBuffer)
6924 IWineD3DSurface_SetContainer(Swapchain->frontBuffer, NULL);
6925 Swapchain->frontBuffer = Front;
6927 if(Swapchain->frontBuffer) {
6928 IWineD3DSurface_SetContainer(Swapchain->frontBuffer, (IWineD3DBase *) Swapchain);
6932 if(Back && !Swapchain->backBuffer) {
6933 /* We need memory for the back buffer array - only one back buffer this way */
6934 Swapchain->backBuffer = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(IWineD3DSurface *));
6935 if(!Swapchain->backBuffer) {
6936 ERR("Out of memory\n");
6937 return E_OUTOFMEMORY;
6941 if(Swapchain->backBuffer[0] != Back) {
6942 TRACE("Changing the back buffer from %p to %p\n", Swapchain->backBuffer, Back);
6944 if(!Swapchain->backBuffer[0]) {
6945 /* GL was told to draw to the front buffer at creation,
6948 glDrawBuffer(GL_BACK);
6949 checkGLcall("glDrawBuffer(GL_BACK)");
6950 /* Set the backbuffer count to 1 because other code uses it to fing the back buffers */
6951 Swapchain->presentParms.BackBufferCount = 1;
6953 /* That makes problems - disable for now */
6954 /* glDrawBuffer(GL_FRONT); */
6955 checkGLcall("glDrawBuffer(GL_FRONT)");
6956 /* We have lost our back buffer, set this to 0 to avoid confusing other code */
6957 Swapchain->presentParms.BackBufferCount = 0;
6961 if(Swapchain->backBuffer[0])
6962 IWineD3DSurface_SetContainer(Swapchain->backBuffer[0], NULL);
6963 Swapchain->backBuffer[0] = Back;
6965 if(Swapchain->backBuffer[0]) {
6966 IWineD3DSurface_SetContainer(Swapchain->backBuffer[0], (IWineD3DBase *) Swapchain);
6968 HeapFree(GetProcessHeap(), 0, Swapchain->backBuffer);
6976 static HRESULT WINAPI IWineD3DDeviceImpl_GetDepthStencilSurface(IWineD3DDevice* iface, IWineD3DSurface **ppZStencilSurface) {
6977 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
6978 *ppZStencilSurface = This->depthStencilBuffer;
6979 TRACE("(%p) : zStencilSurface returning %p\n", This, *ppZStencilSurface);
6984 static void bind_fbo(IWineD3DDevice *iface) {
6985 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
6988 GL_EXTCALL(glGenFramebuffersEXT(1, &This->fbo));
6989 checkGLcall("glGenFramebuffersEXT()");
6991 GL_EXTCALL(glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, This->fbo));
6992 checkGLcall("glBindFramebuffer()");
6995 /* TODO: Handle stencil attachments */
6996 static void set_depth_stencil_fbo(IWineD3DDevice *iface, IWineD3DSurface *depth_stencil) {
6997 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
6998 IWineD3DSurfaceImpl *depth_stencil_impl = (IWineD3DSurfaceImpl *)depth_stencil;
7000 This->depth_copy_state = WINED3D_DCS_NO_COPY;
7004 if (depth_stencil_impl) {
7005 GLenum texttarget, target;
7007 IWineD3DSurface_PreLoad(depth_stencil);
7008 texttarget = depth_stencil_impl->glDescription.target;
7009 target = texttarget == GL_TEXTURE_2D ? GL_TEXTURE_2D : GL_TEXTURE_CUBE_MAP_ARB;
7011 glBindTexture(target, depth_stencil_impl->glDescription.textureName);
7012 glTexParameteri(target, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
7013 glTexParameteri(target, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
7014 glTexParameteri(target, GL_DEPTH_TEXTURE_MODE_ARB, GL_LUMINANCE);
7015 glBindTexture(target, 0);
7017 GL_EXTCALL(glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_DEPTH_ATTACHMENT_EXT, texttarget, depth_stencil_impl->glDescription.textureName, 0));
7018 checkGLcall("glFramebufferTexture2DEXT()");
7020 GL_EXTCALL(glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_DEPTH_ATTACHMENT_EXT, GL_TEXTURE_2D, 0, 0));
7021 checkGLcall("glFramebufferTexture2DEXT()");
7024 if (!This->render_offscreen) {
7025 GL_EXTCALL(glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0));
7026 checkGLcall("glBindFramebuffer()");
7030 static void set_render_target_fbo(IWineD3DDevice *iface, IWineD3DSurface *render_target) {
7031 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
7032 IWineD3DSurfaceImpl *rtimpl = (IWineD3DSurfaceImpl *)render_target;
7034 if (This->render_offscreen) {
7035 GLenum texttarget, target;
7039 IWineD3DSurface_PreLoad(render_target);
7040 texttarget = rtimpl->glDescription.target;
7041 target = texttarget == GL_TEXTURE_2D ? GL_TEXTURE_2D : GL_TEXTURE_CUBE_MAP_ARB;
7043 glBindTexture(target, rtimpl->glDescription.textureName);
7044 glTexParameteri(target, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
7045 glTexParameteri(target, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
7046 glBindTexture(target, 0);
7048 GL_EXTCALL(glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT, texttarget, rtimpl->glDescription.textureName, 0));
7049 checkGLcall("glFramebufferTexture2DEXT()");
7051 GL_EXTCALL(glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0));
7052 checkGLcall("glBindFramebuffer()");
7056 /* internal static helper functions */
7057 static HRESULT WINAPI IWineD3DDeviceImpl_ActiveRender(IWineD3DDevice* iface,
7058 IWineD3DSurface *RenderSurface);
7060 static HRESULT WINAPI IWineD3DDeviceImpl_SetRenderTarget(IWineD3DDevice *iface, DWORD RenderTargetIndex, IWineD3DSurface *pRenderTarget) {
7061 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
7062 HRESULT hr = WINED3D_OK;
7063 WINED3DVIEWPORT viewport;
7065 TRACE("(%p) Swapping rendertarget\n",This);
7066 if (RenderTargetIndex > 0) {
7067 FIXME("(%p) Render targets other than the first are not supported\n",This);
7068 RenderTargetIndex = 0;
7071 /* MSDN says that null disables the render target
7072 but a device must always be associated with a render target
7073 nope MSDN says that we return invalid call to a null rendertarget with an index of 0
7075 see http://msdn.microsoft.com/library/default.asp?url=/library/en-us/directx9_c/directx/graphics/programmingguide/AdvancedTopics/PixelPipe/MultipleRenderTarget.asp
7078 if (RenderTargetIndex == 0 && pRenderTarget == NULL) {
7079 FIXME("Trying to set render target 0 to NULL\n");
7080 return WINED3DERR_INVALIDCALL;
7082 /* TODO: replace Impl* usage with interface usage */
7083 if (!((IWineD3DSurfaceImpl *)pRenderTarget)->resource.usage & WINED3DUSAGE_RENDERTARGET) {
7084 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);
7085 return WINED3DERR_INVALIDCALL;
7087 /** TODO: check that the depth stencil format matches the render target, this is only done in debug
7088 * builds, but I think wine counts as a 'debug' build for now.
7089 ******************************/
7090 /* If we are trying to set what we already have, don't bother */
7091 if (pRenderTarget == This->renderTarget) {
7092 TRACE("Trying to do a NOP SetRenderTarget operation\n");
7094 /* Otherwise, set the render target up */
7096 if (!This->sceneEnded) {
7097 IWineD3DDevice_EndScene(iface);
7099 TRACE("clearing renderer\n");
7100 /* IWineD3DDeviceImpl_CleanRender(iface); */
7101 /* OpenGL doesn't support 'sharing' of the stencilBuffer so we may incure an extra memory overhead
7102 depending on the renter target implementation being used.
7103 A shared context implementation will share all buffers between all rendertargets (including swapchains),
7104 implementations that use separate pbuffers for different swapchains or rendertargets will have to duplicate the
7105 stencil buffer and incure an extra memory overhead */
7106 hr = IWineD3DDeviceImpl_ActiveRender(iface, pRenderTarget);
7107 if (wined3d_settings.offscreen_rendering_mode == ORM_FBO) {
7108 set_render_target_fbo(iface, pRenderTarget);
7112 if (SUCCEEDED(hr)) {
7113 /* Finally, reset the viewport as the MSDN states. */
7114 /* TODO: Replace impl usage */
7115 viewport.Height = ((IWineD3DSurfaceImpl *)This->renderTarget)->currentDesc.Height;
7116 viewport.Width = ((IWineD3DSurfaceImpl *)This->renderTarget)->currentDesc.Width;
7119 viewport.MaxZ = 1.0f;
7120 viewport.MinZ = 0.0f;
7121 IWineD3DDeviceImpl_SetViewport(iface, &viewport);
7123 FIXME("Unknown error setting the render target\n");
7125 This->sceneEnded = FALSE;
7129 static HRESULT WINAPI IWineD3DDeviceImpl_SetDepthStencilSurface(IWineD3DDevice *iface, IWineD3DSurface *pNewZStencil) {
7130 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
7131 HRESULT hr = WINED3D_OK;
7132 IWineD3DSurface *tmp;
7134 TRACE("(%p) Swapping z-buffer\n",This);
7136 if (pNewZStencil == This->stencilBufferTarget) {
7137 TRACE("Trying to do a NOP SetRenderTarget operation\n");
7139 /** OpenGL doesn't support 'sharing' of the stencilBuffer so we may incure an extra memory overhead
7140 * depending on the renter target implementation being used.
7141 * A shared context implementation will share all buffers between all rendertargets (including swapchains),
7142 * implementations that use separate pbuffers for different swapchains or rendertargets will have to duplicate the
7143 * stencil buffer and incure an extra memory overhead
7144 ******************************************************/
7147 tmp = This->stencilBufferTarget;
7148 This->stencilBufferTarget = pNewZStencil;
7149 /* should we be calling the parent or the wined3d surface? */
7150 if (NULL != This->stencilBufferTarget) IWineD3DSurface_AddRef(This->stencilBufferTarget);
7151 if (NULL != tmp) IWineD3DSurface_Release(tmp);
7153 /** TODO: glEnable/glDisable on depth/stencil depending on
7154 * pNewZStencil is NULL and the depth/stencil is enabled in d3d
7155 **********************************************************/
7156 if (wined3d_settings.offscreen_rendering_mode == ORM_FBO) {
7157 set_depth_stencil_fbo(iface, pNewZStencil);
7165 #ifdef GL_VERSION_1_3
7166 /* Internal functions not in DirectX */
7167 /** TODO: move this off to the opengl context manager
7168 *(the swapchain doesn't need to know anything about offscreen rendering!)
7169 ****************************************************/
7171 static HRESULT WINAPI IWineD3DDeviceImpl_CleanRender(IWineD3DDevice* iface, IWineD3DSwapChainImpl *swapchain)
7173 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
7175 TRACE("(%p), %p\n", This, swapchain);
7177 if (swapchain->win != swapchain->drawable) {
7178 /* Set everything back the way it ws */
7179 swapchain->render_ctx = swapchain->glCtx;
7180 swapchain->drawable = swapchain->win;
7185 /* TODO: move this off into a context manager so that GLX_ATI_render_texture and other types of surface can be used. */
7186 static HRESULT WINAPI IWineD3DDeviceImpl_FindGLContext(IWineD3DDevice *iface, IWineD3DSurface *pSurface, glContext **context) {
7187 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
7190 unsigned int height;
7191 WINED3DFORMAT format;
7192 WINED3DSURFACE_DESC surfaceDesc;
7193 memset(&surfaceDesc, 0, sizeof(surfaceDesc));
7194 surfaceDesc.Width = &width;
7195 surfaceDesc.Height = &height;
7196 surfaceDesc.Format = &format;
7197 IWineD3DSurface_GetDesc(pSurface, &surfaceDesc);
7199 /* I need a get width/height function (and should do something with the format) */
7200 for (i = 0; i < CONTEXT_CACHE; ++i) {
7201 /** NOTE: the contextCache[i].pSurface == pSurface check ceates onepbuffer per surface
7202 ATI cards don't destroy pbuffers, but as soon as resource releasing callbacks are inplace
7203 the pSurface can be set to 0 allowing it to be reused from cache **/
7204 if (This->contextCache[i].Width == width && This->contextCache[i].Height == height
7205 && (!pbuffer_per_surface || This->contextCache[i].pSurface == pSurface || This->contextCache[i].pSurface == NULL)) {
7206 *context = &This->contextCache[i];
7209 if (This->contextCache[i].Width == 0) {
7210 This->contextCache[i].pSurface = pSurface;
7211 This->contextCache[i].Width = width;
7212 This->contextCache[i].Height = height;
7213 *context = &This->contextCache[i];
7217 if (i == CONTEXT_CACHE) {
7218 int minUsage = 0x7FFFFFFF; /* MAX_INT */
7219 glContext *dropContext = 0;
7220 for (i = 0; i < CONTEXT_CACHE; i++) {
7221 if (This->contextCache[i].usedcount < minUsage) {
7222 dropContext = &This->contextCache[i];
7223 minUsage = This->contextCache[i].usedcount;
7226 /* clean up the context (this doesn't work for ATI at the moment */
7228 glXDestroyContext(swapchain->display, dropContext->context);
7229 glXDestroyPbuffer(swapchain->display, dropContext->drawable);
7232 dropContext->Width = 0;
7233 dropContext->pSurface = pSurface;
7234 *context = dropContext;
7236 if (++This->contextCache[i].usedcount == 0x7FFFFFFF /* MAX_INT */ - 1 ) {
7237 for (i = 0; i < CONTEXT_CACHE; i++) {
7238 This->contextCache[i].usedcount = max(0, This->contextCache[i].usedcount - (0x7FFFFFFF /* MAX_INT */ >> 1));
7242 if (*context != NULL)
7245 return E_OUTOFMEMORY;
7249 /* Reapply the device stateblock */
7250 static void device_reapply_stateblock(IWineD3DDeviceImpl* This) {
7253 IWineD3DStateBlockImpl *oldUpdateStateBlock;
7255 /* Disable recording */
7256 oldUpdateStateBlock = This->updateStateBlock;
7257 oldRecording= This->isRecordingState;
7258 This->isRecordingState = FALSE;
7259 This->updateStateBlock = This->stateBlock;
7261 /* Reapply the state block */
7262 IWineD3DStateBlock_Apply((IWineD3DStateBlock *)This->stateBlock);
7264 /* Restore recording */
7265 This->isRecordingState = oldRecording;
7266 This->updateStateBlock = oldUpdateStateBlock;
7269 /* Set offscreen rendering. When rendering offscreen the surface will be
7270 * rendered upside down to compensate for the fact that D3D texture coordinates
7271 * are flipped compared to GL texture coordinates. The cullmode is affected by
7272 * this, so it must be updated. To update the cullmode stateblock recording has
7273 * to be temporarily disabled. The new state management code will hopefully
7274 * make this unnecessary */
7275 static void device_render_to_texture(IWineD3DDeviceImpl* This, BOOL isTexture) {
7279 IWineD3DStateBlockImpl *oldUpdateStateBlock;
7281 /* Nothing to update, return. */
7282 if (This->render_offscreen == isTexture) return;
7284 /* Disable recording */
7285 oldUpdateStateBlock = This->updateStateBlock;
7286 oldRecording= This->isRecordingState;
7287 This->isRecordingState = FALSE;
7288 This->updateStateBlock = This->stateBlock;
7290 This->render_offscreen = isTexture;
7291 if (This->depth_copy_state != WINED3D_DCS_NO_COPY) {
7292 This->depth_copy_state = WINED3D_DCS_COPY;
7294 This->last_was_rhw = FALSE;
7295 This->proj_valid = FALSE;
7296 IWineD3DDevice_GetRenderState((IWineD3DDevice*) This, WINED3DRS_CULLMODE, &cullMode);
7297 IWineD3DDevice_SetRenderState((IWineD3DDevice*) This, WINED3DRS_CULLMODE, cullMode);
7299 /* Restore recording */
7300 This->isRecordingState = oldRecording;
7301 This->updateStateBlock = oldUpdateStateBlock;
7304 /* Returns an array of compatible FBconfig(s).
7305 * The array must be freed with XFree. Requires ENTER_GL() */
7307 static GLXFBConfig* device_find_fbconfigs(
7308 IWineD3DDeviceImpl* This,
7309 IWineD3DSwapChainImpl* implicitSwapchainImpl,
7310 IWineD3DSurface* RenderSurface) {
7312 GLXFBConfig* cfgs = NULL;
7317 IWineD3DSurface *StencilSurface = This->stencilBufferTarget;
7318 WINED3DFORMAT BackBufferFormat = ((IWineD3DSurfaceImpl *) RenderSurface)->resource.format;
7319 WINED3DFORMAT StencilBufferFormat = (NULL != StencilSurface) ? ((IWineD3DSurfaceImpl *) StencilSurface)->resource.format : 0;
7322 if StencilSurface == NULL && zBufferTarget != NULL then switch the zbuffer off,
7323 it StencilSurface != NULL && zBufferTarget == NULL switch it on
7326 #define PUSH1(att) attribs[nAttribs++] = (att);
7327 #define PUSH2(att,value) attribs[nAttribs++] = (att); attribs[nAttribs++] = (value);
7329 /* PUSH2(GLX_BIND_TO_TEXTURE_RGBA_ATI, True); examples of this are few and far between (but I've got a nice working one!)*/
7331 PUSH2(GLX_DRAWABLE_TYPE, GLX_PBUFFER_BIT);
7332 PUSH2(GLX_X_RENDERABLE, TRUE);
7333 PUSH2(GLX_DOUBLEBUFFER, TRUE);
7334 TRACE("calling makeglcfg\n");
7335 D3DFmtMakeGlCfg(BackBufferFormat, StencilBufferFormat, attribs, &nAttribs, FALSE /* alternate */);
7337 TRACE("calling chooseFGConfig\n");
7338 cfgs = glXChooseFBConfig(implicitSwapchainImpl->display,
7339 DefaultScreen(implicitSwapchainImpl->display),
7342 /* OK we didn't find the exact config, so use any reasonable match */
7343 /* TODO: fill in the 'requested' and 'current' depths, and make sure that's
7345 static BOOL show_message = TRUE;
7347 ERR("Failed to find exact match, finding alternative but you may "
7348 "suffer performance issues, try changing xfree's depth to match the requested depth\n");
7349 show_message = FALSE;
7352 PUSH2(GLX_DRAWABLE_TYPE, GLX_PBUFFER_BIT | GLX_WINDOW_BIT);
7353 /* PUSH2(GLX_X_RENDERABLE, TRUE); */
7354 PUSH2(GLX_RENDER_TYPE, GLX_RGBA_BIT);
7355 PUSH2(GLX_DOUBLEBUFFER, FALSE);
7356 TRACE("calling makeglcfg\n");
7357 D3DFmtMakeGlCfg(BackBufferFormat, StencilBufferFormat, attribs, &nAttribs, TRUE /* alternate */);
7359 cfgs = glXChooseFBConfig(implicitSwapchainImpl->display,
7360 DefaultScreen(implicitSwapchainImpl->display),
7365 ERR("Could not get a valid FBConfig for (%u,%s)/(%u,%s)\n",
7366 BackBufferFormat, debug_d3dformat(BackBufferFormat),
7367 StencilBufferFormat, debug_d3dformat(StencilBufferFormat));
7371 for (i = 0; i < nCfgs; ++i) {
7372 TRACE("for (%u,%s)/(%u,%s) found config[%d]@%p\n", BackBufferFormat,
7373 debug_d3dformat(BackBufferFormat), StencilBufferFormat,
7374 debug_d3dformat(StencilBufferFormat), i, cfgs[i]);
7376 if (NULL != This->renderTarget) {
7378 vcheckGLcall("glFlush");
7379 /** This is only useful if the old render target was a swapchain,
7380 * we need to supercede this with a function that displays
7381 * the current buffer on the screen. This is easy to do in glx1.3 but
7382 * we need to do copy-write pixels in glx 1.2.
7383 ************************************************/
7384 glXSwapBuffers(implicitSwapChainImpl->display,
7385 implicitSwapChainImpl->drawable);
7386 printf("Hit Enter to get next frame ...\n");
7397 /** FIXME: This is currently used called whenever SetRenderTarget or SetStencilBuffer are called
7398 * the functionality needs splitting up so that we don't do more than we should do.
7399 * this only seems to impact performance a little.
7400 ******************************/
7401 static HRESULT WINAPI IWineD3DDeviceImpl_ActiveRender(IWineD3DDevice* iface,
7402 IWineD3DSurface *RenderSurface) {
7405 * Currently only active for GLX >= 1.3
7406 * for others versions we'll have to use GLXPixmaps
7408 * normally we must test GLX_VERSION_1_3 but nvidia headers are not correct
7409 * as they implement GLX 1.3 but only define GLX_VERSION_1_2
7410 * so only check OpenGL version
7411 * ..........................
7412 * I don't believe that it is a problem with NVidia headers,
7413 * XFree only supports GLX1.2, nVidia (and ATI to some extent) provide 1.3 functions
7414 * in GLX 1.2, there is no mention of the correct way to tell if the extensions are provided.
7416 * Your application will report GLX version 1.2 on glXQueryVersion.
7417 * However, it is safe to call the GLX 1.3 functions as described below.
7419 #if defined(GL_VERSION_1_3)
7421 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
7422 GLXFBConfig* cfgs = NULL;
7423 IWineD3DSwapChain *currentSwapchain;
7424 IWineD3DSwapChainImpl *currentSwapchainImpl;
7425 IWineD3DSwapChain *implicitSwapchain;
7426 IWineD3DSwapChainImpl *implicitSwapchainImpl;
7427 IWineD3DSwapChain *renderSurfaceSwapchain;
7428 IWineD3DSwapChainImpl *renderSurfaceSwapchainImpl;
7430 /* Obtain a reference to the device implicit swapchain,
7431 * the swapchain of the current render target,
7432 * and the swapchain of the new render target.
7433 * Fallback to device implicit swapchain if the current render target doesn't have one */
7434 IWineD3DDevice_GetSwapChain(iface, 0, &implicitSwapchain);
7435 IWineD3DSurface_GetContainer(RenderSurface, &IID_IWineD3DSwapChain, (void**) &renderSurfaceSwapchain);
7436 IWineD3DSurface_GetContainer(This->renderTarget, &IID_IWineD3DSwapChain, (void **)¤tSwapchain);
7437 if (currentSwapchain == NULL)
7438 IWineD3DDevice_GetSwapChain(iface, 0, ¤tSwapchain);
7440 currentSwapchainImpl = (IWineD3DSwapChainImpl*) currentSwapchain;
7441 implicitSwapchainImpl = (IWineD3DSwapChainImpl*) implicitSwapchain;
7442 renderSurfaceSwapchainImpl = (IWineD3DSwapChainImpl*) renderSurfaceSwapchain;
7447 * TODO: remove the use of IWineD3DSwapChainImpl, a context manager will help since it will replace the
7448 * renderTarget = swapchain->backBuffer[i] bit and anything to do with *glContexts
7449 **********************************************************************/
7450 if (renderSurfaceSwapchain != NULL) {
7452 /* We also need to make sure that the lights &co are also in the context of the swapchains */
7453 /* FIXME: If the render target gets sent to the frontBuffer, should we be presenting it raw? */
7454 TRACE("making swapchain active\n");
7455 if (RenderSurface != This->renderTarget) {
7456 BOOL backbuf = FALSE;
7459 for(i = 0; i < renderSurfaceSwapchainImpl->presentParms.BackBufferCount; i++) {
7460 if(RenderSurface == renderSurfaceSwapchainImpl->backBuffer[i]) {
7468 /* This could be flagged so that some operations work directly with the front buffer */
7469 FIXME("Attempting to set the renderTarget to the frontBuffer\n");
7471 if (glXMakeCurrent(renderSurfaceSwapchainImpl->display,
7472 renderSurfaceSwapchainImpl->win,
7473 renderSurfaceSwapchainImpl->glCtx) == False) {
7475 TRACE("Error in setting current context: context %p drawable %ld !\n",
7476 implicitSwapchainImpl->glCtx, implicitSwapchainImpl->win);
7478 checkGLcall("glXMakeContextCurrent");
7480 /* Clean up the old context */
7481 IWineD3DDeviceImpl_CleanRender(iface, currentSwapchainImpl);
7483 /* Reapply the stateblock, and set the device not to render to texture */
7484 device_reapply_stateblock(This);
7485 device_render_to_texture(This, FALSE);
7488 /* Offscreen rendering: PBuffers (currently disabled).
7489 * Also note that this path is never reached if FBOs are supported */
7490 } else if (wined3d_settings.offscreen_rendering_mode == ORM_PBUFFER &&
7491 (cfgs = device_find_fbconfigs(This, implicitSwapchainImpl, RenderSurface)) != NULL) {
7493 /** ********************************************************************
7494 * This is a quickly hacked out implementation of offscreen textures.
7495 * It will work in most cases but there may be problems if the client
7496 * modifies the texture directly, or expects the contents of the rendertarget
7499 * There are some real speed vs compatibility issues here:
7500 * we should really use a new context for every texture, but that eats ram.
7501 * we should also be restoring the texture to the pbuffer but that eats CPU
7502 * we can also 'reuse' the current pbuffer if the size is larger than the requested buffer,
7503 * but if this means reusing the display backbuffer then we need to make sure that
7504 * states are correctly preserved.
7505 * In many cases I would expect that we can 'skip' some functions, such as preserving states,
7506 * and gain a good performance increase at the cost of compatibility.
7507 * I would suggest that, when this is the case, a user configurable flag be made
7508 * available, allowing the user to choose the best emulated experience for them.
7509 *********************************************************************/
7511 XVisualInfo *visinfo;
7512 glContext *newContext;
7514 /* Here were using a shared context model */
7515 if (WINED3D_OK != IWineD3DDeviceImpl_FindGLContext(iface, RenderSurface, &newContext)) {
7516 FIXME("(%p) : Failed to find a context for surface %p\n", iface, RenderSurface);
7519 /* If the context doesn't exist then create a new one */
7520 /* TODO: This should really be part of findGlContext */
7521 if (NULL == newContext->context) {
7526 TRACE("making new buffer\n");
7527 attribs[nAttribs++] = GLX_PBUFFER_WIDTH;
7528 attribs[nAttribs++] = newContext->Width;
7529 attribs[nAttribs++] = GLX_PBUFFER_HEIGHT;
7530 attribs[nAttribs++] = newContext->Height;
7531 attribs[nAttribs++] = None;
7533 newContext->drawable = glXCreatePbuffer(implicitSwapchainImpl->display, cfgs[0], attribs);
7535 /** ****************************************
7536 *GLX1.3 isn't supported by XFree 'yet' until that point ATI emulates pBuffers
7538 * In future releases, we may provide the calls glXCreateNewContext,
7539 * glXQueryDrawable and glXMakeContextCurrent.
7540 * so until then we have to use glXGetVisualFromFBConfig &co..
7541 ********************************************/
7543 visinfo = glXGetVisualFromFBConfig(implicitSwapchainImpl->display, cfgs[0]);
7545 ERR("Error: couldn't get an RGBA, double-buffered visual\n");
7547 newContext->context = glXCreateContext(
7548 implicitSwapchainImpl->display, visinfo,
7549 implicitSwapchainImpl->glCtx, GL_TRUE);
7554 if (NULL == newContext || NULL == newContext->context) {
7555 ERR("(%p) : Failed to find a context for surface %p\n", iface, RenderSurface);
7557 /* Debug logging, (this function leaks), change to a TRACE when the leak is plugged */
7558 if (glXMakeCurrent(implicitSwapchainImpl->display,
7559 newContext->drawable, newContext->context) == False) {
7561 TRACE("Error in setting current context: context %p drawable %ld\n",
7562 newContext->context, newContext->drawable);
7564 checkGLcall("glXMakeContextCurrent");
7566 /* Clean up the old context */
7567 IWineD3DDeviceImpl_CleanRender(iface, currentSwapchainImpl);
7569 /* Reapply stateblock, and set device to render to a texture */
7570 device_reapply_stateblock(This);
7571 device_render_to_texture(This, TRUE);
7573 /* Set the current context of the swapchain to the new context */
7574 implicitSwapchainImpl->drawable = newContext->drawable;
7575 implicitSwapchainImpl->render_ctx = newContext->context;
7578 /* Same context, but update render_offscreen and cull mode */
7579 device_render_to_texture(This, TRUE);
7582 /* Replace the render target */
7583 if (This->renderTarget != RenderSurface) {
7584 IWineD3DSurface_Release(This->renderTarget);
7585 This->renderTarget = RenderSurface;
7586 IWineD3DSurface_AddRef(RenderSurface);
7589 if (cfgs != NULL) XFree(cfgs);
7590 if (implicitSwapchain != NULL) IWineD3DSwapChain_Release(implicitSwapchain);
7591 if (currentSwapchain != NULL) IWineD3DSwapChain_Release(currentSwapchain);
7592 if (renderSurfaceSwapchain != NULL) IWineD3DSwapChain_Release(renderSurfaceSwapchain);
7598 static HRESULT WINAPI IWineD3DDeviceImpl_SetCursorProperties(IWineD3DDevice* iface, UINT XHotSpot,
7599 UINT YHotSpot, IWineD3DSurface *pCursorBitmap) {
7600 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *) iface;
7601 /* TODO: the use of Impl is deprecated. */
7602 IWineD3DSurfaceImpl * pSur = (IWineD3DSurfaceImpl *) pCursorBitmap;
7604 TRACE("(%p) : Spot Pos(%u,%u)\n", This, XHotSpot, YHotSpot);
7606 /* some basic validation checks */
7607 if(This->cursorTexture) {
7609 glDeleteTextures(1, &This->cursorTexture);
7611 This->cursorTexture = 0;
7615 /* MSDN: Cursor must be A8R8G8B8 */
7616 if (WINED3DFMT_A8R8G8B8 != pSur->resource.format) {
7617 ERR("(%p) : surface(%p) has an invalid format\n", This, pCursorBitmap);
7618 return WINED3DERR_INVALIDCALL;
7621 /* MSDN: Cursor must be smaller than the display mode */
7622 if(pSur->currentDesc.Width > This->ddraw_width ||
7623 pSur->currentDesc.Height > This->ddraw_height) {
7624 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);
7625 return WINED3DERR_INVALIDCALL;
7628 /* TODO: MSDN: Cursor sizes must be a power of 2 */
7629 /* This is to tell our texture code to load a SCRATCH surface. This allows us to use out
7630 * Texture and Blitting code to draw the cursor
7632 pSur->Flags |= SFLAG_FORCELOAD;
7633 IWineD3DSurface_PreLoad(pCursorBitmap);
7634 pSur->Flags &= ~SFLAG_FORCELOAD;
7635 /* Do not store the surface's pointer because the application may release
7636 * it after setting the cursor image. Windows doesn't addref the set surface, so we can't
7637 * do this either without creating circular refcount dependencies. Copy out the gl texture instead.
7639 This->cursorTexture = pSur->glDescription.textureName;
7640 This->cursorWidth = pSur->currentDesc.Width;
7641 This->cursorHeight = pSur->currentDesc.Height;
7642 pSur->glDescription.textureName = 0; /* Prevent the texture from being changed or deleted */
7645 This->xHotSpot = XHotSpot;
7646 This->yHotSpot = YHotSpot;
7650 static void WINAPI IWineD3DDeviceImpl_SetCursorPosition(IWineD3DDevice* iface, int XScreenSpace, int YScreenSpace, DWORD Flags) {
7651 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *) iface;
7652 TRACE("(%p) : SetPos to (%u,%u)\n", This, XScreenSpace, YScreenSpace);
7654 This->xScreenSpace = XScreenSpace;
7655 This->yScreenSpace = YScreenSpace;
7661 static BOOL WINAPI IWineD3DDeviceImpl_ShowCursor(IWineD3DDevice* iface, BOOL bShow) {
7662 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *) iface;
7663 BOOL oldVisible = This->bCursorVisible;
7664 TRACE("(%p) : visible(%d)\n", This, bShow);
7666 if(This->cursorTexture)
7667 This->bCursorVisible = bShow;
7672 static HRESULT WINAPI IWineD3DDeviceImpl_TestCooperativeLevel(IWineD3DDevice* iface) {
7673 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *) iface;
7674 TRACE("(%p) : state (%u)\n", This, This->state);
7675 /* TODO: Implement wrapping of the WndProc so that mimimize and maxamise can be monitored and the states adjusted. */
7676 switch (This->state) {
7679 case WINED3DERR_DEVICELOST:
7681 ResourceList *resourceList = This->resources;
7682 while (NULL != resourceList) {
7683 if (((IWineD3DResourceImpl *)resourceList->resource)->resource.pool == WINED3DPOOL_DEFAULT /* TODO: IWineD3DResource_GetPool(resourceList->resource)*/)
7684 return WINED3DERR_DEVICENOTRESET;
7685 resourceList = resourceList->next;
7687 return WINED3DERR_DEVICELOST;
7689 case WINED3DERR_DRIVERINTERNALERROR:
7690 return WINED3DERR_DRIVERINTERNALERROR;
7694 return WINED3DERR_DRIVERINTERNALERROR;
7698 static HRESULT WINAPI IWineD3DDeviceImpl_EvictManagedResources(IWineD3DDevice* iface) {
7699 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *) iface;
7700 /** FIXME: Resource tracking needs to be done,
7701 * The closes we can do to this is set the priorities of all managed textures low
7702 * and then reset them.
7703 ***********************************************************/
7704 FIXME("(%p) : stub\n", This);
7708 static HRESULT WINAPI IWineD3DDeviceImpl_Reset(IWineD3DDevice* iface, WINED3DPRESENT_PARAMETERS* pPresentationParameters) {
7709 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *) iface;
7710 /** FIXME: Resource trascking needs to be done.
7711 * in effect this pulls all non only default
7712 * textures out of video memory and deletes all glTextures (glDeleteTextures)
7713 * and should clear down the context and set it up according to pPresentationParameters
7714 ***********************************************************/
7715 FIXME("(%p) : stub\n", This);
7719 static HRESULT WINAPI IWineD3DDeviceImpl_SetDialogBoxMode(IWineD3DDevice *iface, BOOL bEnableDialogs) {
7720 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
7721 /** FIXME: always true at the moment **/
7722 if(!bEnableDialogs) {
7723 FIXME("(%p) Dialogs cannot be disabled yet\n", This);
7729 static HRESULT WINAPI IWineD3DDeviceImpl_GetCreationParameters(IWineD3DDevice *iface, WINED3DDEVICE_CREATION_PARAMETERS *pParameters) {
7730 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *) iface;
7731 TRACE("(%p) : pParameters %p\n", This, pParameters);
7733 *pParameters = This->createParms;
7737 static void WINAPI IWineD3DDeviceImpl_SetGammaRamp(IWineD3DDevice * iface, UINT iSwapChain, DWORD Flags, CONST WINED3DGAMMARAMP* pRamp) {
7738 IWineD3DSwapChain *swapchain;
7739 HRESULT hrc = WINED3D_OK;
7741 TRACE("Relaying to swapchain\n");
7743 if ((hrc = IWineD3DDeviceImpl_GetSwapChain(iface, iSwapChain, &swapchain)) == WINED3D_OK) {
7744 IWineD3DSwapChain_SetGammaRamp(swapchain, Flags, (WINED3DGAMMARAMP *)pRamp);
7745 IWineD3DSwapChain_Release(swapchain);
7750 static void WINAPI IWineD3DDeviceImpl_GetGammaRamp(IWineD3DDevice *iface, UINT iSwapChain, WINED3DGAMMARAMP* pRamp) {
7751 IWineD3DSwapChain *swapchain;
7752 HRESULT hrc = WINED3D_OK;
7754 TRACE("Relaying to swapchain\n");
7756 if ((hrc = IWineD3DDeviceImpl_GetSwapChain(iface, iSwapChain, &swapchain)) == WINED3D_OK) {
7757 hrc =IWineD3DSwapChain_GetGammaRamp(swapchain, pRamp);
7758 IWineD3DSwapChain_Release(swapchain);
7764 /** ********************************************************
7765 * Notification functions
7766 ** ********************************************************/
7767 /** This function must be called in the release of a resource when ref == 0,
7768 * the contents of resource must still be correct,
7769 * any handels to other resource held by the caller must be closed
7770 * (e.g. a texture should release all held surfaces because telling the device that it's been released.)
7771 *****************************************************/
7772 static void WINAPI IWineD3DDeviceImpl_AddResource(IWineD3DDevice *iface, IWineD3DResource *resource){
7773 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
7774 ResourceList* resourceList;
7776 TRACE("(%p) : resource %p\n", This, resource);
7778 EnterCriticalSection(&resourceStoreCriticalSection);
7780 /* add a new texture to the frot of the linked list */
7781 resourceList = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(ResourceList));
7782 resourceList->resource = resource;
7784 /* Get the old head */
7785 resourceList->next = This->resources;
7787 This->resources = resourceList;
7788 TRACE("Added resource %p with element %p pointing to %p\n", resource, resourceList, resourceList->next);
7791 LeaveCriticalSection(&resourceStoreCriticalSection);
7796 static void WINAPI IWineD3DDeviceImpl_RemoveResource(IWineD3DDevice *iface, IWineD3DResource *resource){
7797 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
7798 ResourceList* resourceList = NULL;
7799 ResourceList* previousResourceList = NULL;
7801 TRACE("(%p) : resource %p\n", This, resource);
7804 EnterCriticalSection(&resourceStoreCriticalSection);
7806 resourceList = This->resources;
7808 while (resourceList != NULL) {
7809 if(resourceList->resource == resource) break;
7810 previousResourceList = resourceList;
7811 resourceList = resourceList->next;
7814 if (resourceList == NULL) {
7815 FIXME("Attempted to remove resource %p that hasn't been stored\n", resource);
7817 LeaveCriticalSection(&resourceStoreCriticalSection);
7821 TRACE("Found resource %p with element %p pointing to %p (previous %p)\n", resourceList->resource, resourceList, resourceList->next, previousResourceList);
7823 /* make sure we don't leave a hole in the list */
7824 if (previousResourceList != NULL) {
7825 previousResourceList->next = resourceList->next;
7827 This->resources = resourceList->next;
7831 LeaveCriticalSection(&resourceStoreCriticalSection);
7837 static void WINAPI IWineD3DDeviceImpl_ResourceReleased(IWineD3DDevice *iface, IWineD3DResource *resource){
7838 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *) iface;
7841 TRACE("(%p) : resource %p\n", This, resource);
7842 switch(IWineD3DResource_GetType(resource)){
7843 case WINED3DRTYPE_SURFACE:
7844 /* TODO: check front and back buffers, rendertargets etc.. possibly swapchains? */
7846 case WINED3DRTYPE_TEXTURE:
7847 case WINED3DRTYPE_CUBETEXTURE:
7848 case WINED3DRTYPE_VOLUMETEXTURE:
7849 for (counter = 0; counter < GL_LIMITS(sampler_stages); counter++) {
7850 if (This->stateBlock != NULL && This->stateBlock->textures[counter] == (IWineD3DBaseTexture *)resource) {
7851 WARN("Texture being released is still by a stateblock, Stage = %u Texture = %p\n", counter, resource);
7852 This->stateBlock->textures[counter] = NULL;
7854 if (This->updateStateBlock != This->stateBlock ){
7855 if (This->updateStateBlock->textures[counter] == (IWineD3DBaseTexture *)resource) {
7856 WARN("Texture being released is still by a stateblock, Stage = %u Texture = %p\n", counter, resource);
7857 This->updateStateBlock->textures[counter] = NULL;
7862 case WINED3DRTYPE_VOLUME:
7863 /* TODO: nothing really? */
7865 case WINED3DRTYPE_VERTEXBUFFER:
7866 /* MSDN: When an application no longer holds a references to this interface, the interface will automatically be freed. */
7869 TRACE("Cleaning up stream pointers\n");
7871 for(streamNumber = 0; streamNumber < MAX_STREAMS; streamNumber ++){
7872 /* FINDOUT: should a warn be generated if were recording and updateStateBlock->streamSource is lost?
7873 FINDOUT: should changes.streamSource[StreamNumber] be set ?
7875 if (This->updateStateBlock != NULL ) { /* ==NULL when device is being destroyed */
7876 if ((IWineD3DResource *)This->updateStateBlock->streamSource[streamNumber] == resource) {
7877 FIXME("Vertex buffer released while bound to a state block, stream %d\n", streamNumber);
7878 This->updateStateBlock->streamSource[streamNumber] = 0;
7879 /* Set changed flag? */
7882 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) */
7883 if ((IWineD3DResource *)This->stateBlock->streamSource[streamNumber] == resource) {
7884 TRACE("Vertex buffer released while bound to a state block, stream %d\n", streamNumber);
7885 This->stateBlock->streamSource[streamNumber] = 0;
7888 #if 0 /* TODO: Manage internal tracking properly so that 'this shouldn't happen' */
7889 else { /* This shouldn't happen */
7890 FIXME("Calling application has released the device before relasing all the resources bound to the device\n");
7897 case WINED3DRTYPE_INDEXBUFFER:
7898 /* MSDN: When an application no longer holds a references to this interface, the interface will automatically be freed.*/
7899 if (This->updateStateBlock != NULL ) { /* ==NULL when device is being destroyed */
7900 if (This->updateStateBlock->pIndexData == (IWineD3DIndexBuffer *)resource) {
7901 This->updateStateBlock->pIndexData = NULL;
7904 if (This->stateBlock != NULL ) { /* ==NULL when device is being destroyed */
7905 if (This->stateBlock->pIndexData == (IWineD3DIndexBuffer *)resource) {
7906 This->stateBlock->pIndexData = NULL;
7912 FIXME("(%p) unknown resource type %p %u\n", This, resource, IWineD3DResource_GetType(resource));
7917 /* Remove the resoruce from the resourceStore */
7918 IWineD3DDeviceImpl_RemoveResource(iface, resource);
7920 TRACE("Resource released\n");
7924 /**********************************************************
7925 * IWineD3DDevice VTbl follows
7926 **********************************************************/
7928 const IWineD3DDeviceVtbl IWineD3DDevice_Vtbl =
7930 /*** IUnknown methods ***/
7931 IWineD3DDeviceImpl_QueryInterface,
7932 IWineD3DDeviceImpl_AddRef,
7933 IWineD3DDeviceImpl_Release,
7934 /*** IWineD3DDevice methods ***/
7935 IWineD3DDeviceImpl_GetParent,
7936 /*** Creation methods**/
7937 IWineD3DDeviceImpl_CreateVertexBuffer,
7938 IWineD3DDeviceImpl_CreateIndexBuffer,
7939 IWineD3DDeviceImpl_CreateStateBlock,
7940 IWineD3DDeviceImpl_CreateSurface,
7941 IWineD3DDeviceImpl_CreateTexture,
7942 IWineD3DDeviceImpl_CreateVolumeTexture,
7943 IWineD3DDeviceImpl_CreateVolume,
7944 IWineD3DDeviceImpl_CreateCubeTexture,
7945 IWineD3DDeviceImpl_CreateQuery,
7946 IWineD3DDeviceImpl_CreateAdditionalSwapChain,
7947 IWineD3DDeviceImpl_CreateVertexDeclaration,
7948 IWineD3DDeviceImpl_CreateVertexShader,
7949 IWineD3DDeviceImpl_CreatePixelShader,
7950 IWineD3DDeviceImpl_CreatePalette,
7951 /*** Odd functions **/
7952 IWineD3DDeviceImpl_Init3D,
7953 IWineD3DDeviceImpl_Uninit3D,
7954 IWineD3DDeviceImpl_SetFullscreen,
7955 IWineD3DDeviceImpl_EnumDisplayModes,
7956 IWineD3DDeviceImpl_EvictManagedResources,
7957 IWineD3DDeviceImpl_GetAvailableTextureMem,
7958 IWineD3DDeviceImpl_GetBackBuffer,
7959 IWineD3DDeviceImpl_GetCreationParameters,
7960 IWineD3DDeviceImpl_GetDeviceCaps,
7961 IWineD3DDeviceImpl_GetDirect3D,
7962 IWineD3DDeviceImpl_GetDisplayMode,
7963 IWineD3DDeviceImpl_SetDisplayMode,
7964 IWineD3DDeviceImpl_GetHWND,
7965 IWineD3DDeviceImpl_SetHWND,
7966 IWineD3DDeviceImpl_GetNumberOfSwapChains,
7967 IWineD3DDeviceImpl_GetRasterStatus,
7968 IWineD3DDeviceImpl_GetSwapChain,
7969 IWineD3DDeviceImpl_Reset,
7970 IWineD3DDeviceImpl_SetDialogBoxMode,
7971 IWineD3DDeviceImpl_SetCursorProperties,
7972 IWineD3DDeviceImpl_SetCursorPosition,
7973 IWineD3DDeviceImpl_ShowCursor,
7974 IWineD3DDeviceImpl_TestCooperativeLevel,
7975 /*** Getters and setters **/
7976 IWineD3DDeviceImpl_SetClipPlane,
7977 IWineD3DDeviceImpl_GetClipPlane,
7978 IWineD3DDeviceImpl_SetClipStatus,
7979 IWineD3DDeviceImpl_GetClipStatus,
7980 IWineD3DDeviceImpl_SetCurrentTexturePalette,
7981 IWineD3DDeviceImpl_GetCurrentTexturePalette,
7982 IWineD3DDeviceImpl_SetDepthStencilSurface,
7983 IWineD3DDeviceImpl_GetDepthStencilSurface,
7984 IWineD3DDeviceImpl_SetFVF,
7985 IWineD3DDeviceImpl_GetFVF,
7986 IWineD3DDeviceImpl_SetGammaRamp,
7987 IWineD3DDeviceImpl_GetGammaRamp,
7988 IWineD3DDeviceImpl_SetIndices,
7989 IWineD3DDeviceImpl_GetIndices,
7990 IWineD3DDeviceImpl_SetLight,
7991 IWineD3DDeviceImpl_GetLight,
7992 IWineD3DDeviceImpl_SetLightEnable,
7993 IWineD3DDeviceImpl_GetLightEnable,
7994 IWineD3DDeviceImpl_SetMaterial,
7995 IWineD3DDeviceImpl_GetMaterial,
7996 IWineD3DDeviceImpl_SetNPatchMode,
7997 IWineD3DDeviceImpl_GetNPatchMode,
7998 IWineD3DDeviceImpl_SetPaletteEntries,
7999 IWineD3DDeviceImpl_GetPaletteEntries,
8000 IWineD3DDeviceImpl_SetPixelShader,
8001 IWineD3DDeviceImpl_GetPixelShader,
8002 IWineD3DDeviceImpl_SetPixelShaderConstantB,
8003 IWineD3DDeviceImpl_GetPixelShaderConstantB,
8004 IWineD3DDeviceImpl_SetPixelShaderConstantI,
8005 IWineD3DDeviceImpl_GetPixelShaderConstantI,
8006 IWineD3DDeviceImpl_SetPixelShaderConstantF,
8007 IWineD3DDeviceImpl_GetPixelShaderConstantF,
8008 IWineD3DDeviceImpl_SetRenderState,
8009 IWineD3DDeviceImpl_GetRenderState,
8010 IWineD3DDeviceImpl_SetRenderTarget,
8011 IWineD3DDeviceImpl_GetRenderTarget,
8012 IWineD3DDeviceImpl_SetFrontBackBuffers,
8013 IWineD3DDeviceImpl_SetSamplerState,
8014 IWineD3DDeviceImpl_GetSamplerState,
8015 IWineD3DDeviceImpl_SetScissorRect,
8016 IWineD3DDeviceImpl_GetScissorRect,
8017 IWineD3DDeviceImpl_SetSoftwareVertexProcessing,
8018 IWineD3DDeviceImpl_GetSoftwareVertexProcessing,
8019 IWineD3DDeviceImpl_SetStreamSource,
8020 IWineD3DDeviceImpl_GetStreamSource,
8021 IWineD3DDeviceImpl_SetStreamSourceFreq,
8022 IWineD3DDeviceImpl_GetStreamSourceFreq,
8023 IWineD3DDeviceImpl_SetTexture,
8024 IWineD3DDeviceImpl_GetTexture,
8025 IWineD3DDeviceImpl_SetTextureStageState,
8026 IWineD3DDeviceImpl_GetTextureStageState,
8027 IWineD3DDeviceImpl_SetTransform,
8028 IWineD3DDeviceImpl_GetTransform,
8029 IWineD3DDeviceImpl_SetVertexDeclaration,
8030 IWineD3DDeviceImpl_GetVertexDeclaration,
8031 IWineD3DDeviceImpl_SetVertexShader,
8032 IWineD3DDeviceImpl_GetVertexShader,
8033 IWineD3DDeviceImpl_SetVertexShaderConstantB,
8034 IWineD3DDeviceImpl_GetVertexShaderConstantB,
8035 IWineD3DDeviceImpl_SetVertexShaderConstantI,
8036 IWineD3DDeviceImpl_GetVertexShaderConstantI,
8037 IWineD3DDeviceImpl_SetVertexShaderConstantF,
8038 IWineD3DDeviceImpl_GetVertexShaderConstantF,
8039 IWineD3DDeviceImpl_SetViewport,
8040 IWineD3DDeviceImpl_GetViewport,
8041 IWineD3DDeviceImpl_MultiplyTransform,
8042 IWineD3DDeviceImpl_ValidateDevice,
8043 IWineD3DDeviceImpl_ProcessVertices,
8044 /*** State block ***/
8045 IWineD3DDeviceImpl_BeginStateBlock,
8046 IWineD3DDeviceImpl_EndStateBlock,
8047 /*** Scene management ***/
8048 IWineD3DDeviceImpl_BeginScene,
8049 IWineD3DDeviceImpl_EndScene,
8050 IWineD3DDeviceImpl_Present,
8051 IWineD3DDeviceImpl_Clear,
8053 IWineD3DDeviceImpl_DrawPrimitive,
8054 IWineD3DDeviceImpl_DrawIndexedPrimitive,
8055 IWineD3DDeviceImpl_DrawPrimitiveUP,
8056 IWineD3DDeviceImpl_DrawIndexedPrimitiveUP,
8057 IWineD3DDeviceImpl_DrawPrimitiveStrided,
8058 IWineD3DDeviceImpl_DrawRectPatch,
8059 IWineD3DDeviceImpl_DrawTriPatch,
8060 IWineD3DDeviceImpl_DeletePatch,
8061 IWineD3DDeviceImpl_ColorFill,
8062 IWineD3DDeviceImpl_UpdateTexture,
8063 IWineD3DDeviceImpl_UpdateSurface,
8064 IWineD3DDeviceImpl_StretchRect,
8065 IWineD3DDeviceImpl_GetRenderTargetData,
8066 IWineD3DDeviceImpl_GetFrontBufferData,
8067 /*** Internal use IWineD3DDevice methods ***/
8068 IWineD3DDeviceImpl_SetupTextureStates,
8069 /*** object tracking ***/
8070 IWineD3DDeviceImpl_ResourceReleased
8074 const DWORD SavedPixelStates_R[NUM_SAVEDPIXELSTATES_R] = {
8075 WINED3DRS_ALPHABLENDENABLE ,
8076 WINED3DRS_ALPHAFUNC ,
8077 WINED3DRS_ALPHAREF ,
8078 WINED3DRS_ALPHATESTENABLE ,
8080 WINED3DRS_COLORWRITEENABLE ,
8081 WINED3DRS_DESTBLEND ,
8082 WINED3DRS_DITHERENABLE ,
8083 WINED3DRS_FILLMODE ,
8084 WINED3DRS_FOGDENSITY ,
8086 WINED3DRS_FOGSTART ,
8087 WINED3DRS_LASTPIXEL ,
8088 WINED3DRS_SHADEMODE ,
8089 WINED3DRS_SRCBLEND ,
8090 WINED3DRS_STENCILENABLE ,
8091 WINED3DRS_STENCILFAIL ,
8092 WINED3DRS_STENCILFUNC ,
8093 WINED3DRS_STENCILMASK ,
8094 WINED3DRS_STENCILPASS ,
8095 WINED3DRS_STENCILREF ,
8096 WINED3DRS_STENCILWRITEMASK ,
8097 WINED3DRS_STENCILZFAIL ,
8098 WINED3DRS_TEXTUREFACTOR ,
8109 WINED3DRS_ZWRITEENABLE
8112 const DWORD SavedPixelStates_T[NUM_SAVEDPIXELSTATES_T] = {
8113 WINED3DTSS_ADDRESSW ,
8114 WINED3DTSS_ALPHAARG0 ,
8115 WINED3DTSS_ALPHAARG1 ,
8116 WINED3DTSS_ALPHAARG2 ,
8117 WINED3DTSS_ALPHAOP ,
8118 WINED3DTSS_BUMPENVLOFFSET ,
8119 WINED3DTSS_BUMPENVLSCALE ,
8120 WINED3DTSS_BUMPENVMAT00 ,
8121 WINED3DTSS_BUMPENVMAT01 ,
8122 WINED3DTSS_BUMPENVMAT10 ,
8123 WINED3DTSS_BUMPENVMAT11 ,
8124 WINED3DTSS_COLORARG0 ,
8125 WINED3DTSS_COLORARG1 ,
8126 WINED3DTSS_COLORARG2 ,
8127 WINED3DTSS_COLOROP ,
8128 WINED3DTSS_RESULTARG ,
8129 WINED3DTSS_TEXCOORDINDEX ,
8130 WINED3DTSS_TEXTURETRANSFORMFLAGS
8133 const DWORD SavedPixelStates_S[NUM_SAVEDPIXELSTATES_S] = {
8134 WINED3DSAMP_ADDRESSU ,
8135 WINED3DSAMP_ADDRESSV ,
8136 WINED3DSAMP_ADDRESSW ,
8137 WINED3DSAMP_BORDERCOLOR ,
8138 WINED3DSAMP_MAGFILTER ,
8139 WINED3DSAMP_MINFILTER ,
8140 WINED3DSAMP_MIPFILTER ,
8141 WINED3DSAMP_MIPMAPLODBIAS ,
8142 WINED3DSAMP_MAXMIPLEVEL ,
8143 WINED3DSAMP_MAXANISOTROPY ,
8144 WINED3DSAMP_SRGBTEXTURE ,
8145 WINED3DSAMP_ELEMENTINDEX
8148 const DWORD SavedVertexStates_R[NUM_SAVEDVERTEXSTATES_R] = {
8150 WINED3DRS_AMBIENTMATERIALSOURCE ,
8151 WINED3DRS_CLIPPING ,
8152 WINED3DRS_CLIPPLANEENABLE ,
8153 WINED3DRS_COLORVERTEX ,
8154 WINED3DRS_DIFFUSEMATERIALSOURCE ,
8155 WINED3DRS_EMISSIVEMATERIALSOURCE ,
8156 WINED3DRS_FOGDENSITY ,
8158 WINED3DRS_FOGSTART ,
8159 WINED3DRS_FOGTABLEMODE ,
8160 WINED3DRS_FOGVERTEXMODE ,
8161 WINED3DRS_INDEXEDVERTEXBLENDENABLE ,
8162 WINED3DRS_LIGHTING ,
8163 WINED3DRS_LOCALVIEWER ,
8164 WINED3DRS_MULTISAMPLEANTIALIAS ,
8165 WINED3DRS_MULTISAMPLEMASK ,
8166 WINED3DRS_NORMALIZENORMALS ,
8167 WINED3DRS_PATCHEDGESTYLE ,
8168 WINED3DRS_POINTSCALE_A ,
8169 WINED3DRS_POINTSCALE_B ,
8170 WINED3DRS_POINTSCALE_C ,
8171 WINED3DRS_POINTSCALEENABLE ,
8172 WINED3DRS_POINTSIZE ,
8173 WINED3DRS_POINTSIZE_MAX ,
8174 WINED3DRS_POINTSIZE_MIN ,
8175 WINED3DRS_POINTSPRITEENABLE ,
8176 WINED3DRS_RANGEFOGENABLE ,
8177 WINED3DRS_SPECULARMATERIALSOURCE ,
8178 WINED3DRS_TWEENFACTOR ,
8179 WINED3DRS_VERTEXBLEND
8182 const DWORD SavedVertexStates_T[NUM_SAVEDVERTEXSTATES_T] = {
8183 WINED3DTSS_TEXCOORDINDEX ,
8184 WINED3DTSS_TEXTURETRANSFORMFLAGS
8187 const DWORD SavedVertexStates_S[NUM_SAVEDVERTEXSTATES_S] = {
8188 WINED3DSAMP_DMAPOFFSET