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 D3DLIGHT_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 /* TODO: setup some flags in the regestry to enable, disable pbuffer support */
75 /* enable pbuffer support for offscreen textures */
76 BOOL pbuffer_support = FALSE;
77 /* allocate one pbuffer per surface */
78 BOOL pbuffer_per_surface = FALSE;
80 /* static function declarations */
81 static void WINAPI IWineD3DDeviceImpl_AddResource(IWineD3DDevice *iface, IWineD3DResource *resource);
83 static void WINAPI IWineD3DDeviceImpl_ApplyTextureUnitState(IWineD3DDevice *iface, DWORD Stage, WINED3DTEXTURESTAGESTATETYPE Type);
86 #define D3DMEMCHECK(object, ppResult) if(NULL == object) { *ppResult = NULL; WARN("Out of memory\n"); return WINED3DERR_OUTOFVIDEOMEMORY;}
88 #define D3DCREATEOBJECTINSTANCE(object, type) { \
89 object=HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(IWineD3D##type##Impl)); \
90 D3DMEMCHECK(object, pp##type); \
91 object->lpVtbl = &IWineD3D##type##_Vtbl; \
92 object->wineD3DDevice = This; \
93 object->parent = parent; \
95 *pp##type = (IWineD3D##type *) object; \
98 #define D3DCREATERESOURCEOBJECTINSTANCE(object, type, d3dtype, _size){ \
99 object=HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(IWineD3D##type##Impl)); \
100 D3DMEMCHECK(object, pp##type); \
101 object->lpVtbl = &IWineD3D##type##_Vtbl; \
102 object->resource.wineD3DDevice = This; \
103 object->resource.parent = parent; \
104 object->resource.resourceType = d3dtype; \
105 object->resource.ref = 1; \
106 object->resource.pool = Pool; \
107 object->resource.format = Format; \
108 object->resource.usage = Usage; \
109 object->resource.size = _size; \
110 /* Check that we have enough video ram left */ \
111 if (Pool == WINED3DPOOL_DEFAULT) { \
112 if (IWineD3DDevice_GetAvailableTextureMem(iface) <= _size) { \
113 WARN("Out of 'bogus' video memory\n"); \
114 HeapFree(GetProcessHeap(), 0, object); \
116 return WINED3DERR_OUTOFVIDEOMEMORY; \
118 globalChangeGlRam(_size); \
120 object->resource.allocatedMemory = (0 == _size ? NULL : Pool == WINED3DPOOL_DEFAULT ? NULL : HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, _size)); \
121 if (object->resource.allocatedMemory == NULL && _size != 0 && Pool != WINED3DPOOL_DEFAULT) { \
122 FIXME("Out of memory!\n"); \
123 HeapFree(GetProcessHeap(), 0, object); \
125 return WINED3DERR_OUTOFVIDEOMEMORY; \
127 *pp##type = (IWineD3D##type *) object; \
128 IWineD3DDeviceImpl_AddResource(iface, (IWineD3DResource *)object) ;\
129 TRACE("(%p) : Created resource %p\n", This, object); \
132 #define D3DINITIALIZEBASETEXTURE(_basetexture) { \
133 _basetexture.levels = Levels; \
134 _basetexture.filterType = (Usage & WINED3DUSAGE_AUTOGENMIPMAP) ? WINED3DTEXF_LINEAR : WINED3DTEXF_NONE; \
135 _basetexture.LOD = 0; \
136 _basetexture.dirty = TRUE; \
139 /**********************************************************
140 * Global variable / Constants follow
141 **********************************************************/
142 const float identity[16] = {1,0,0,0, 0,1,0,0, 0,0,1,0, 0,0,0,1}; /* When needed for comparisons */
144 /**********************************************************
145 * Utility functions follow
146 **********************************************************/
147 /* Convert the D3DLIGHT properties into equivalent gl lights */
148 static void setup_light(IWineD3DDevice *iface, LONG Index, PLIGHTINFOEL *lightInfo) {
151 float colRGBA[] = {0.0, 0.0, 0.0, 0.0};
152 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
154 /* Light settings are affected by the model view in OpenGL, the View transform in direct3d*/
155 glMatrixMode(GL_MODELVIEW);
157 glLoadMatrixf((float *)&This->stateBlock->transforms[WINED3DTS_VIEW].u.m[0][0]);
160 colRGBA[0] = lightInfo->OriginalParms.Diffuse.r;
161 colRGBA[1] = lightInfo->OriginalParms.Diffuse.g;
162 colRGBA[2] = lightInfo->OriginalParms.Diffuse.b;
163 colRGBA[3] = lightInfo->OriginalParms.Diffuse.a;
164 glLightfv(GL_LIGHT0+Index, GL_DIFFUSE, colRGBA);
165 checkGLcall("glLightfv");
168 colRGBA[0] = lightInfo->OriginalParms.Specular.r;
169 colRGBA[1] = lightInfo->OriginalParms.Specular.g;
170 colRGBA[2] = lightInfo->OriginalParms.Specular.b;
171 colRGBA[3] = lightInfo->OriginalParms.Specular.a;
172 glLightfv(GL_LIGHT0+Index, GL_SPECULAR, colRGBA);
173 checkGLcall("glLightfv");
176 colRGBA[0] = lightInfo->OriginalParms.Ambient.r;
177 colRGBA[1] = lightInfo->OriginalParms.Ambient.g;
178 colRGBA[2] = lightInfo->OriginalParms.Ambient.b;
179 colRGBA[3] = lightInfo->OriginalParms.Ambient.a;
180 glLightfv(GL_LIGHT0+Index, GL_AMBIENT, colRGBA);
181 checkGLcall("glLightfv");
183 /* Attenuation - Are these right? guessing... */
184 glLightf(GL_LIGHT0+Index, GL_CONSTANT_ATTENUATION, lightInfo->OriginalParms.Attenuation0);
185 checkGLcall("glLightf");
186 glLightf(GL_LIGHT0+Index, GL_LINEAR_ATTENUATION, lightInfo->OriginalParms.Attenuation1);
187 checkGLcall("glLightf");
189 if ((lightInfo->OriginalParms.Range *lightInfo->OriginalParms.Range) >= FLT_MIN) {
190 quad_att = 1.4/(lightInfo->OriginalParms.Range *lightInfo->OriginalParms.Range);
192 quad_att = 0; /* 0 or MAX? (0 seems to be ok) */
195 if (quad_att < lightInfo->OriginalParms.Attenuation2) quad_att = lightInfo->OriginalParms.Attenuation2;
196 glLightf(GL_LIGHT0+Index, GL_QUADRATIC_ATTENUATION, quad_att);
197 checkGLcall("glLightf");
199 switch (lightInfo->OriginalParms.Type) {
202 glLightfv(GL_LIGHT0+Index, GL_POSITION, &lightInfo->lightPosn[0]);
203 checkGLcall("glLightfv");
204 glLightf(GL_LIGHT0 + Index, GL_SPOT_CUTOFF, lightInfo->cutoff);
205 checkGLcall("glLightf");
211 glLightfv(GL_LIGHT0+Index, GL_POSITION, &lightInfo->lightPosn[0]);
212 checkGLcall("glLightfv");
214 glLightfv(GL_LIGHT0+Index, GL_SPOT_DIRECTION, &lightInfo->lightDirn[0]);
215 checkGLcall("glLightfv");
216 glLightf(GL_LIGHT0 + Index, GL_SPOT_EXPONENT, lightInfo->exponent);
217 checkGLcall("glLightf");
218 glLightf(GL_LIGHT0 + Index, GL_SPOT_CUTOFF, lightInfo->cutoff);
219 checkGLcall("glLightf");
223 case D3DLIGHT_DIRECTIONAL:
225 glLightfv(GL_LIGHT0+Index, GL_POSITION, &lightInfo->lightPosn[0]); /* Note gl uses w position of 0 for direction! */
226 checkGLcall("glLightfv");
227 glLightf(GL_LIGHT0+Index, GL_SPOT_CUTOFF, lightInfo->cutoff);
228 checkGLcall("glLightf");
229 glLightf(GL_LIGHT0+Index, GL_SPOT_EXPONENT, 0.0f);
230 checkGLcall("glLightf");
234 FIXME("Unrecognized light type %d\n", lightInfo->OriginalParms.Type);
237 /* Restore the modelview matrix */
241 /**********************************************************
242 * GLSL helper functions follow
243 **********************************************************/
245 /** Attach a GLSL pixel or vertex shader object to the shader program */
246 static void attach_glsl_shader(IWineD3DDevice *iface, IWineD3DBaseShader* shader) {
248 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
249 GLhandleARB shaderObj = ((IWineD3DBaseShaderImpl*)shader)->baseShader.prgId;
250 if (This->stateBlock->glsl_program && shaderObj != 0) {
251 TRACE_(d3d_shader)("Attaching GLSL shader object %u to program %u\n", shaderObj, This->stateBlock->glsl_program->programId);
252 GL_EXTCALL(glAttachObjectARB(This->stateBlock->glsl_program->programId, shaderObj));
253 checkGLcall("glAttachObjectARB");
257 /** Sets the GLSL program ID for the given pixel and vertex shader combination.
258 * It sets the programId on the current StateBlock (because it should be called
259 * inside of the DrawPrimitive() part of the render loop).
261 * If a program for the given combination does not exist, create one, and store
262 * the program in the list. If it creates a program, it will link the given
265 * We keep the shader programs around on a list because linking
266 * shader objects together is an expensive operation. It's much
267 * faster to loop through a list of pre-compiled & linked programs
268 * each time that the application sets a new pixel or vertex shader
269 * than it is to re-link them together at that time.
271 * The list will be deleted in IWineD3DDevice::Release().
273 void set_glsl_shader_program(IWineD3DDevice *iface) {
275 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
276 IWineD3DPixelShader *pshader = This->stateBlock->pixelShader;
277 IWineD3DVertexShader *vshader = This->stateBlock->vertexShader;
278 struct glsl_shader_prog_link *curLink = NULL;
279 struct glsl_shader_prog_link *newLink = NULL;
280 struct list *ptr = NULL;
281 GLhandleARB programId = 0;
285 ptr = list_head( &This->glsl_shader_progs );
287 /* At least one program exists - see if it matches our ps/vs combination */
288 curLink = LIST_ENTRY( ptr, struct glsl_shader_prog_link, entry );
289 if (vshader == curLink->vertexShader && pshader == curLink->pixelShader) {
290 /* Existing Program found, use it */
291 TRACE_(d3d_shader)("Found existing program (%u) for this vertex/pixel shader combination\n",
293 This->stateBlock->glsl_program = curLink;
296 /* This isn't the entry we need - try the next one */
297 ptr = list_next( &This->glsl_shader_progs, ptr );
300 /* If we get to this point, then no matching program exists, so we create one */
301 programId = GL_EXTCALL(glCreateProgramObjectARB());
302 TRACE_(d3d_shader)("Created new GLSL shader program %u\n", programId);
304 /* Allocate a new link for the list of programs */
305 newLink = HeapAlloc(GetProcessHeap(), 0, sizeof(struct glsl_shader_prog_link));
306 newLink->programId = programId;
307 This->stateBlock->glsl_program = newLink;
309 /* Attach GLSL vshader */
310 if (NULL != vshader && wined3d_settings.vs_selected_mode == SHADER_GLSL) {
312 int max_attribs = 16; /* TODO: Will this always be the case? It is at the moment... */
315 TRACE("Attaching vertex shader to GLSL program\n");
316 attach_glsl_shader(iface, (IWineD3DBaseShader*)vshader);
318 /* Bind vertex attributes to a corresponding index number to match
319 * the same index numbers as ARB_vertex_programs (makes loading
320 * vertex attributes simpler). With this method, we can use the
321 * exact same code to load the attributes later for both ARB and
324 * We have to do this here because we need to know the Program ID
325 * in order to make the bindings work, and it has to be done prior
326 * to linking the GLSL program. */
327 for (i = 0; i < max_attribs; ++i) {
328 snprintf(tmp_name, sizeof(tmp_name), "attrib%i", i);
329 GL_EXTCALL(glBindAttribLocationARB(programId, i, tmp_name));
331 checkGLcall("glBindAttribLocationARB");
332 newLink->vertexShader = vshader;
335 /* Attach GLSL pshader */
336 if (NULL != pshader && wined3d_settings.ps_selected_mode == SHADER_GLSL) {
337 TRACE("Attaching pixel shader to GLSL program\n");
338 attach_glsl_shader(iface, (IWineD3DBaseShader*)pshader);
339 newLink->pixelShader = pshader;
342 /* Link the program */
343 TRACE_(d3d_shader)("Linking GLSL shader program %u\n", programId);
344 GL_EXTCALL(glLinkProgramARB(programId));
345 print_glsl_info_log(&GLINFO_LOCATION, programId);
346 list_add_head( &This->glsl_shader_progs, &newLink->entry);
348 newLink->vuniformF_locations = HeapAlloc(GetProcessHeap(), 0, sizeof(GLhandleARB) * GL_LIMITS(vshader_constantsF));
349 for (i = 0; i < GL_LIMITS(vshader_constantsF); ++i) {
350 snprintf(glsl_name, sizeof(glsl_name), "VC[%i]", i);
351 newLink->vuniformF_locations[i] = GL_EXTCALL(glGetUniformLocationARB(programId, glsl_name));
353 newLink->puniformF_locations = HeapAlloc(GetProcessHeap(), 0, sizeof(GLhandleARB) * GL_LIMITS(pshader_constantsF));
354 for (i = 0; i < GL_LIMITS(pshader_constantsF); ++i) {
355 snprintf(glsl_name, sizeof(glsl_name), "PC[%i]", i);
356 newLink->puniformF_locations[i] = GL_EXTCALL(glGetUniformLocationARB(programId, glsl_name));
362 /** Detach the GLSL pixel or vertex shader object from the shader program */
363 static void detach_glsl_shader(IWineD3DDevice *iface, GLhandleARB shaderObj, GLhandleARB programId) {
365 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
367 if (shaderObj != 0 && programId != 0) {
368 TRACE_(d3d_shader)("Detaching GLSL shader object %u from program %u\n", shaderObj, programId);
369 GL_EXTCALL(glDetachObjectARB(programId, shaderObj));
370 checkGLcall("glDetachObjectARB");
374 /** Delete a GLSL shader program */
375 static void delete_glsl_shader_program(IWineD3DDevice *iface, GLhandleARB obj) {
377 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
380 TRACE_(d3d_shader)("Deleting GLSL shader program %u\n", obj);
381 GL_EXTCALL(glDeleteObjectARB(obj));
382 checkGLcall("glDeleteObjectARB");
386 /** Delete the list of linked programs this shader is associated with.
387 * Also at this point, check to see if there are any objects left attached
388 * to each GLSL program. If not, delete the GLSL program object.
389 * This will be run when a device is released. */
390 static void delete_glsl_shader_list(IWineD3DDevice* iface) {
392 struct list *ptr = NULL;
393 struct glsl_shader_prog_link *curLink = NULL;
394 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
398 GLhandleARB objList[2]; /* There should never be more than 2 objects attached
399 (one pixel shader and one vertex shader at most) */
401 ptr = list_head( &This->glsl_shader_progs );
403 /* First, get the current item,
404 * save the link to the next pointer,
405 * detach and delete shader objects,
406 * then de-allocate the list item's memory */
407 curLink = LIST_ENTRY( ptr, struct glsl_shader_prog_link, entry );
408 ptr = list_next( &This->glsl_shader_progs, ptr );
410 /* See if this object is still attached to the program - it may have been detached already */
411 GL_EXTCALL(glGetAttachedObjectsARB(curLink->programId, 2, &numAttached, objList));
412 TRACE_(d3d_shader)("%i GLSL objects are currently attached to program %u\n", numAttached, curLink->programId);
413 for (i = 0; i < numAttached; i++) {
414 detach_glsl_shader(iface, objList[i], curLink->programId);
417 delete_glsl_shader_program(iface, curLink->programId);
419 /* Free the uniform locations */
420 HeapFree(GetProcessHeap(), 0, curLink->vuniformF_locations);
421 HeapFree(GetProcessHeap(), 0, curLink->puniformF_locations);
423 /* Free the memory for this list item */
424 HeapFree(GetProcessHeap(), 0, curLink);
429 /* Apply the current values to the specified texture stage */
430 static void WINAPI IWineD3DDeviceImpl_SetupTextureStates(IWineD3DDevice *iface, DWORD Sampler, DWORD texture_idx, DWORD Flags) {
431 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
439 /* In addition, IDirect3DDevice9::SetSamplerState will now be used for filtering, tiling,
440 clamping, MIPLOD, etc. This will work for up to 16 samplers.
443 if (Sampler >= GL_LIMITS(sampler_stages)) {
444 FIXME("Trying to set the state of more samplers %ld than are supported %d by this openGL implementation\n", Sampler, GL_LIMITS(sampler_stages));
447 VTRACE(("Activating appropriate texture state %ld\n", Sampler));
448 if (GL_SUPPORT(ARB_MULTITEXTURE)) {
450 GL_EXTCALL(glActiveTextureARB(GL_TEXTURE0_ARB + texture_idx));
451 checkGLcall("glActiveTextureARB");
453 /* Could we use bindTexture and then apply the states instead of GLACTIVETEXTURE */
454 } else if (Sampler > 0) {
455 FIXME("Program using multiple concurrent textures which this opengl implementation doesn't support\n");
459 /* TODO: change this to a lookup table
460 LOOKUP_TEXTURE_STATES lists all texture states that should be applied.
461 LOOKUP_CONTEXT_SATES list all context applicable states that can be applied
462 etc.... it's a lot cleaner, quicker and possibly easier to maintain than running a switch and setting a skip flag...
463 especially when there are a number of groups of states. */
465 TRACE("-----------------------> Updating the texture at Sampler %ld to have new texture state information\n", Sampler);
467 /* 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 */
468 #define APPLY_STATE(_state) IWineD3DDeviceImpl_ApplyTextureUnitState(iface, Sampler, _state)
469 /* these are the only two supported states that need to be applied */
470 APPLY_STATE(WINED3DTSS_TEXCOORDINDEX);
471 APPLY_STATE(WINED3DTSS_TEXTURETRANSFORMFLAGS);
472 #if 0 /* not supported at the moment */
473 APPLY_STATE(WINED3DTSS_BUMPENVMAT00);
474 APPLY_STATE(WINED3DTSS_BUMPENVMAT01);
475 APPLY_STATE(WINED3DTSS_BUMPENVMAT10);
476 APPLY_STATE(WINED3DTSS_BUMPENVMAT11);
477 APPLY_STATE(WINED3DTSS_BUMPENVLSCALE);
478 APPLY_STATE(WINED3DTSS_BUMPENVLOFFSET);
479 APPLY_STATE(WINED3DTSS_RESULTARG);
480 APPLY_STATE(WINED3DTSS_CONSTANT);
482 /* a quick sanity check in case someone forgot to update this function */
483 if (WINED3D_HIGHEST_TEXTURE_STATE > WINED3DTSS_CONSTANT) {
484 FIXME("(%p) : There are more texture states than expected, update device.c to match\n", This);
488 /* apply any sampler states that always need applying */
489 if (GL_SUPPORT(EXT_TEXTURE_LOD_BIAS)) {
490 tmpvalue.d = This->stateBlock->samplerState[Sampler][WINED3DSAMP_MIPMAPLODBIAS];
491 glTexEnvf(GL_TEXTURE_FILTER_CONTROL_EXT,
492 GL_TEXTURE_LOD_BIAS_EXT,
494 checkGLcall("glTexEnvi GL_TEXTURE_LOD_BIAS_EXT ...");
497 D3DCOLORTOGLFLOAT4(This->stateBlock->renderState[WINED3DRS_TEXTUREFACTOR], col);
498 glTexEnvfv(GL_TEXTURE_ENV, GL_TEXTURE_ENV_COLOR, &col[0]);
499 checkGLcall("glTexEnvfv(GL_TEXTURE_ENV, GL_TEXTURE_ENV_COLOR, color);");
501 /* TODO: NV_POINT_SPRITE */
502 if (GL_SUPPORT(ARB_POINT_SPRITE)) {
503 if (This->stateBlock->renderState[WINED3DRS_POINTSPRITEENABLE] != FALSE) {
504 /* Doesn't work with GL_POINT_SMOOTH on on my ATI 9600, but then ATI drivers are buggered! */
505 glDisable(GL_POINT_SMOOTH);
507 /* Centre the texture on the vertex */
508 VTRACE(("glTexEnvf( GL_POINT_SPRITE_ARB, GL_COORD_REPLACE_ARB, GL_TRUE)\n"));
509 glTexEnvf( GL_POINT_SPRITE_ARB, GL_COORD_REPLACE_ARB, GL_TRUE);
511 VTRACE(("glTexEnvf( GL_POINT_SPRITE_ARB, GL_COORD_REPLACE_ARB, GL_TRUE)\n"));
512 glTexEnvf( GL_POINT_SPRITE_ARB, GL_COORD_REPLACE_ARB, GL_TRUE);
513 checkGLcall("glTexEnvf(...)");
514 VTRACE(("glEnable( GL_POINT_SPRITE_ARB )\n"));
515 glEnable( GL_POINT_SPRITE_ARB );
516 checkGLcall("glEnable(...)");
518 VTRACE(("glDisable( GL_POINT_SPRITE_ARB )\n"));
519 glDisable( GL_POINT_SPRITE_ARB );
520 checkGLcall("glEnable(...)");
524 TRACE("-----------------------> Updated the texture at Sampler %ld to have new texture state information\n", Sampler);
527 /**********************************************************
528 * IUnknown parts follows
529 **********************************************************/
531 static HRESULT WINAPI IWineD3DDeviceImpl_QueryInterface(IWineD3DDevice *iface,REFIID riid,LPVOID *ppobj)
533 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
535 TRACE("(%p)->(%s,%p)\n",This,debugstr_guid(riid),ppobj);
536 if (IsEqualGUID(riid, &IID_IUnknown)
537 || IsEqualGUID(riid, &IID_IWineD3DBase)
538 || IsEqualGUID(riid, &IID_IWineD3DDevice)) {
539 IUnknown_AddRef(iface);
544 return E_NOINTERFACE;
547 static ULONG WINAPI IWineD3DDeviceImpl_AddRef(IWineD3DDevice *iface) {
548 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
549 ULONG refCount = InterlockedIncrement(&This->ref);
551 TRACE("(%p) : AddRef increasing from %ld\n", This, refCount - 1);
555 static ULONG WINAPI IWineD3DDeviceImpl_Release(IWineD3DDevice *iface) {
556 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
557 ULONG refCount = InterlockedDecrement(&This->ref);
559 TRACE("(%p) : Releasing from %ld\n", This, refCount + 1);
562 /* TODO: Clean up all the surfaces and textures! */
563 /* NOTE: You must release the parent if the object was created via a callback
564 ** ***************************/
566 /* Delete any GLSL shader programs that may exist */
567 if (wined3d_settings.vs_selected_mode == SHADER_GLSL ||
568 wined3d_settings.ps_selected_mode == SHADER_GLSL)
569 delete_glsl_shader_list(iface);
571 /* Release the update stateblock */
572 if(IWineD3DStateBlock_Release((IWineD3DStateBlock *)This->updateStateBlock) > 0){
573 if(This->updateStateBlock != This->stateBlock)
574 FIXME("(%p) Something's still holding the Update stateblock\n",This);
576 This->updateStateBlock = NULL;
577 { /* because were not doing proper internal refcounts releasing the primary state block
578 causes recursion with the extra checks in ResourceReleased, to avoid this we have
579 to set this->stateBlock = NULL; first */
580 IWineD3DStateBlock *stateBlock = (IWineD3DStateBlock *)This->stateBlock;
581 This->stateBlock = NULL;
583 /* Release the stateblock */
584 if(IWineD3DStateBlock_Release(stateBlock) > 0){
585 FIXME("(%p) Something's still holding the Update stateblock\n",This);
589 if (This->resources != NULL ) {
590 FIXME("(%p) Device released with resources still bound, acceptable but unexpected\n", This);
591 dumpResources(This->resources);
595 IWineD3D_Release(This->wineD3D);
596 This->wineD3D = NULL;
597 HeapFree(GetProcessHeap(), 0, This);
598 TRACE("Freed device %p\n", This);
604 /**********************************************************
605 * IWineD3DDevice implementation follows
606 **********************************************************/
607 static HRESULT WINAPI IWineD3DDeviceImpl_GetParent(IWineD3DDevice *iface, IUnknown **pParent) {
608 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
609 *pParent = This->parent;
610 IUnknown_AddRef(This->parent);
614 static void CreateVBO(IWineD3DVertexBufferImpl *object) {
615 IWineD3DDeviceImpl *This = object->resource.wineD3DDevice; /* Needed for GL_EXTCALL */
616 GLenum error, glUsage;
617 DWORD vboUsage = object->resource.usage;
618 if(object->Flags & VBFLAG_VBOCREATEFAIL) {
619 WARN("Creating a vbo failed once, not trying again\n");
623 TRACE("Creating an OpenGL vertex buffer object for IWineD3DVertexBuffer %p Usage(%s)\n", object, debug_d3dusage(vboUsage));
626 /* Make sure that the gl error is cleared. Do not use checkGLcall
627 * here because checkGLcall just prints a fixme and continues. However,
628 * if an error during VBO creation occurs we can fall back to non-vbo operation
629 * with full functionality(but performance loss)
631 while(glGetError() != GL_NO_ERROR);
633 /* Basically the FVF parameter passed to CreateVertexBuffer is no good
634 * It is the FVF set with IWineD3DDevice::SetFVF or the Vertex Declaration set with
635 * IWineD3DDevice::SetVertexDeclaration that decides how the vertices in the buffer
636 * look like. This means that on each DrawPrimitive call the vertex buffer has to be verified
637 * to check if the rhw and color values are in the correct format.
640 GL_EXTCALL(glGenBuffersARB(1, &object->vbo));
641 error = glGetError();
642 if(object->vbo == 0 || error != GL_NO_ERROR) {
643 WARN("Failed to create a VBO with error %d\n", error);
647 GL_EXTCALL(glBindBufferARB(GL_ARRAY_BUFFER_ARB, object->vbo));
648 error = glGetError();
649 if(error != GL_NO_ERROR) {
650 WARN("Failed to bind the VBO, error %d\n", error);
654 /* Transformed vertices are horribly inflexible. If the app specifies an
655 * vertex buffer with transformed vertices in default pool without DYNAMIC
656 * usage assume DYNAMIC usage and print a warning. The app will have to update
657 * the vertices regularily for them to be useful
659 if(((object->fvf & D3DFVF_POSITION_MASK) == D3DFVF_XYZRHW) &&
660 !(vboUsage & WINED3DUSAGE_DYNAMIC)) {
661 WARN("Application creates a vertex buffer holding transformed vertices which doesn't specify dynamic usage\n");
662 vboUsage |= WINED3DUSAGE_DYNAMIC;
665 /* Don't use static, because dx apps tend to update the buffer
666 * quite often even if they specify 0 usage
668 switch(vboUsage & (D3DUSAGE_WRITEONLY | D3DUSAGE_DYNAMIC) ) {
669 case D3DUSAGE_WRITEONLY | D3DUSAGE_DYNAMIC:
670 TRACE("Gl usage = GL_STREAM_DRAW\n");
671 glUsage = GL_STREAM_DRAW_ARB;
673 case D3DUSAGE_WRITEONLY:
674 TRACE("Gl usage = GL_DYNAMIC_DRAW\n");
675 glUsage = GL_DYNAMIC_DRAW_ARB;
677 case D3DUSAGE_DYNAMIC:
678 TRACE("Gl usage = GL_STREAM_COPY\n");
679 glUsage = GL_STREAM_COPY_ARB;
682 TRACE("Gl usage = GL_DYNAMIC_COPY\n");
683 glUsage = GL_DYNAMIC_COPY_ARB;
687 /* Reserve memory for the buffer. The amount of data won't change
688 * so we are safe with calling glBufferData once with a NULL ptr and
689 * calling glBufferSubData on updates
691 GL_EXTCALL(glBufferDataARB(GL_ARRAY_BUFFER_ARB, object->resource.size, NULL, glUsage));
692 error = glGetError();
693 if(error != GL_NO_ERROR) {
694 WARN("glBufferDataARB failed with error %d\n", error);
702 /* Clean up all vbo init, but continue because we can work without a vbo :-) */
703 FIXME("Failed to create a vertex buffer object. Continuing, but performance issues can occur\n");
704 if(object->vbo) GL_EXTCALL(glDeleteBuffersARB(1, &object->vbo));
706 object->Flags |= VBFLAG_VBOCREATEFAIL;
711 static HRESULT WINAPI IWineD3DDeviceImpl_CreateVertexBuffer(IWineD3DDevice *iface, UINT Size, DWORD Usage,
712 DWORD FVF, WINED3DPOOL Pool, IWineD3DVertexBuffer** ppVertexBuffer, HANDLE *sharedHandle,
714 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
715 IWineD3DVertexBufferImpl *object;
716 WINED3DFORMAT Format = WINED3DFMT_VERTEXDATA; /* Dummy format for now */
717 int dxVersion = ( (IWineD3DImpl *) This->wineD3D)->dxVersion;
719 D3DCREATERESOURCEOBJECTINSTANCE(object, VertexBuffer, WINED3DRTYPE_VERTEXBUFFER, Size)
721 TRACE("(%p) : Size=%d, Usage=%ld, FVF=%lx, Pool=%d - Memory@%p, Iface@%p\n", This, Size, Usage, FVF, Pool, object->resource.allocatedMemory, object);
722 *ppVertexBuffer = (IWineD3DVertexBuffer *)object;
724 if(Size == 0) return WINED3DERR_INVALIDCALL;
726 if (Pool == WINED3DPOOL_DEFAULT ) { /* Allocate some system memory for now */
727 object->resource.allocatedMemory = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, object->resource.size);
731 /* Observations show that drawStridedSlow is faster on dynamic VBs than converting +
732 * drawStridedFast (half-life 2).
734 * Basically converting the vertices in the buffer is quite expensive, and observations
735 * show that drawStridedSlow is faster than converting + uploading + drawStridedFast.
736 * Therefore do not create a VBO for WINED3DUSAGE_DYNAMIC buffers.
738 * Direct3D7 has another problem: Its vertexbuffer api doesn't offer a way to specify
739 * the range of vertices being locked, so each lock will require the whole buffer to be transformed.
740 * Moreover geometry data in dx7 is quite simple, so drawStridedSlow isn't a big hit. A plus
741 * is that the vertex buffers fvf can be trusted in dx7. So only create non-converted vbos for
743 * There is a IDirect3DVertexBuffer7::Optimize call after which the buffer can't be locked any
744 * more. In this call we can convert dx7 buffers too.
746 conv = ((FVF & D3DFVF_POSITION_MASK) == D3DFVF_XYZRHW ) || (FVF & (D3DFVF_DIFFUSE | D3DFVF_SPECULAR));
747 if( GL_SUPPORT(ARB_VERTEX_BUFFER_OBJECT) && Pool != WINED3DPOOL_SYSTEMMEM && !(Usage & WINED3DUSAGE_DYNAMIC) &&
748 (dxVersion > 7 || !conv) ) {
751 /* DX7 buffers can be locked directly into the VBO (no conversion, see above */
752 if(dxVersion == 7 && object->vbo) {
753 HeapFree(GetProcessHeap(), 0, object->resource.allocatedMemory);
754 object->resource.allocatedMemory = NULL;
761 static HRESULT WINAPI IWineD3DDeviceImpl_CreateIndexBuffer(IWineD3DDevice *iface, UINT Length, DWORD Usage,
762 WINED3DFORMAT Format, WINED3DPOOL Pool, IWineD3DIndexBuffer** ppIndexBuffer,
763 HANDLE *sharedHandle, IUnknown *parent) {
764 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
765 IWineD3DIndexBufferImpl *object;
766 TRACE("(%p) Creating index buffer\n", This);
768 /* Allocate the storage for the device */
769 D3DCREATERESOURCEOBJECTINSTANCE(object,IndexBuffer,WINED3DRTYPE_INDEXBUFFER, Length)
772 if (Pool == WINED3DPOOL_DEFAULT ) { /* Allocate some system memory for now */
773 object->resource.allocatedMemory = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,object->resource.size);
776 TRACE("(%p) : Len=%d, Use=%lx, Format=(%u,%s), Pool=%d - Memory@%p, Iface@%p\n", This, Length, Usage, Format,
777 debug_d3dformat(Format), Pool, object, object->resource.allocatedMemory);
778 *ppIndexBuffer = (IWineD3DIndexBuffer *) object;
783 static HRESULT WINAPI IWineD3DDeviceImpl_CreateStateBlock(IWineD3DDevice* iface, WINED3DSTATEBLOCKTYPE Type, IWineD3DStateBlock** ppStateBlock, IUnknown *parent) {
785 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
786 IWineD3DStateBlockImpl *object;
790 D3DCREATEOBJECTINSTANCE(object, StateBlock)
791 object->blockType = Type;
793 /* Special case - Used during initialization to produce a placeholder stateblock
794 so other functions called can update a state block */
795 if (Type == WINED3DSBT_INIT) {
796 /* Don't bother increasing the reference count otherwise a device will never
797 be freed due to circular dependencies */
801 temp_result = allocate_shader_constants(object);
802 if (WINED3D_OK != temp_result)
805 /* Otherwise, might as well set the whole state block to the appropriate values */
806 if (This->stateBlock != NULL)
807 stateblock_copy((IWineD3DStateBlock*) object, (IWineD3DStateBlock*) This->stateBlock);
809 memset(object->streamFreq, 1, sizeof(object->streamFreq));
811 /* Reset the ref and type after kludging it */
812 object->wineD3DDevice = This;
814 object->blockType = Type;
816 TRACE("Updating changed flags appropriate for type %d\n", Type);
818 if (Type == WINED3DSBT_ALL) {
820 TRACE("ALL => Pretend everything has changed\n");
821 stateblock_savedstates_set((IWineD3DStateBlock*) object, &object->changed, TRUE);
823 } else if (Type == WINED3DSBT_PIXELSTATE) {
825 TRACE("PIXELSTATE => Pretend all pixel shates have changed\n");
826 stateblock_savedstates_set((IWineD3DStateBlock*) object, &object->changed, FALSE);
828 object->changed.pixelShader = TRUE;
830 /* Pixel Shader Constants */
831 for (i = 0; i < GL_LIMITS(pshader_constantsF); ++i)
832 object->changed.pixelShaderConstantsF[i] = TRUE;
833 for (i = 0; i < MAX_CONST_B; ++i)
834 object->changed.pixelShaderConstantsB[i] = TRUE;
835 for (i = 0; i < MAX_CONST_I; ++i)
836 object->changed.pixelShaderConstantsI[i] = TRUE;
838 for (i = 0; i < NUM_SAVEDPIXELSTATES_R; i++) {
839 object->changed.renderState[SavedPixelStates_R[i]] = TRUE;
841 for (j = 0; j < GL_LIMITS(texture_stages); j++) {
842 for (i = 0; i < NUM_SAVEDPIXELSTATES_T; i++) {
843 object->changed.textureState[j][SavedPixelStates_T[i]] = TRUE;
846 for (j = 0 ; j < 16; j++) {
847 for (i =0; i < NUM_SAVEDPIXELSTATES_S;i++) {
849 object->changed.samplerState[j][SavedPixelStates_S[i]] = TRUE;
853 } else if (Type == WINED3DSBT_VERTEXSTATE) {
855 TRACE("VERTEXSTATE => Pretend all vertex shates have changed\n");
856 stateblock_savedstates_set((IWineD3DStateBlock*) object, &object->changed, FALSE);
858 object->changed.vertexShader = TRUE;
860 /* Vertex Shader Constants */
861 for (i = 0; i < GL_LIMITS(vshader_constantsF); ++i)
862 object->changed.vertexShaderConstantsF[i] = TRUE;
863 for (i = 0; i < MAX_CONST_B; ++i)
864 object->changed.vertexShaderConstantsB[i] = TRUE;
865 for (i = 0; i < MAX_CONST_I; ++i)
866 object->changed.vertexShaderConstantsI[i] = TRUE;
868 for (i = 0; i < NUM_SAVEDVERTEXSTATES_R; i++) {
869 object->changed.renderState[SavedVertexStates_R[i]] = TRUE;
871 for (j = 0; j < GL_LIMITS(texture_stages); j++) {
872 for (i = 0; i < NUM_SAVEDVERTEXSTATES_T; i++) {
873 object->changed.textureState[j][SavedVertexStates_T[i]] = TRUE;
876 for (j = 0 ; j < 16; j++){
877 for (i =0; i < NUM_SAVEDVERTEXSTATES_S;i++) {
878 object->changed.samplerState[j][SavedVertexStates_S[i]] = TRUE;
882 /* Duplicate light chain */
884 PLIGHTINFOEL *src = NULL;
885 PLIGHTINFOEL *dst = NULL;
886 PLIGHTINFOEL *newEl = NULL;
887 src = This->stateBlock->lights;
888 object->lights = NULL;
892 newEl = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(PLIGHTINFOEL));
893 if (newEl == NULL) return WINED3DERR_OUTOFVIDEOMEMORY;
894 memcpy(newEl, src, sizeof(PLIGHTINFOEL));
896 newEl->changed = TRUE;
897 newEl->enabledChanged = TRUE;
899 object->lights = newEl;
910 FIXME("Unrecognized state block type %d\n", Type);
913 TRACE("(%p) returning token (ptr to stateblock) of %p\n", This, object);
918 /* ************************************
920 [in] Render targets are not lockable unless the application specifies TRUE for Lockable. Note that lockable render targets reduce performance on some graphics hardware.
923 [in] Set this flag to TRUE to enable z-buffer discarding, and FALSE otherwise.
925 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.
927 ******************************** */
929 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) {
930 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
931 IWineD3DSurfaceImpl *object; /*NOTE: impl ref allowed since this is a create function */
932 unsigned int pow2Width, pow2Height;
933 unsigned int Size = 1;
934 const PixelFormatDesc *tableEntry = getFormatDescEntry(Format);
935 TRACE("(%p) Create surface\n",This);
937 /** FIXME: Check ranges on the inputs are valid
940 * [in] Quality level. The valid range is between zero and one less than the level
941 * returned by pQualityLevels used by IDirect3D9::CheckDeviceMultiSampleType.
942 * Passing a larger value returns the error WINED3DERR_INVALIDCALL. The MultisampleQuality
943 * values of paired render targets, depth stencil surfaces, and the MultiSample type
945 *******************************/
950 * [in] Set this flag to TRUE to enable z-buffer discarding, and FALSE otherwise.
952 * If this flag is set, the contents of the depth stencil buffer will be
953 * invalid after calling either IDirect3DDevice9::Present or * IDirect3DDevice9::SetDepthStencilSurface
954 * with a different depth surface.
956 *This flag has the same behavior as the constant, D3DPRESENTFLAG_DISCARD_DEPTHSTENCIL, in D3DPRESENTFLAG.
957 ***************************/
959 if(MultisampleQuality < 0) {
960 FIXME("Invalid multisample level %ld\n", MultisampleQuality);
961 return WINED3DERR_INVALIDCALL; /* TODO: Check that this is the case! */
964 if(MultisampleQuality > 0) {
965 FIXME("MultisampleQuality set to %ld, substituting 0\n", MultisampleQuality);
966 MultisampleQuality=0;
969 /** FIXME: Check that the format is supported
971 *******************************/
973 /* Non-power2 support */
975 /* Find the nearest pow2 match */
976 pow2Width = pow2Height = 1;
977 while (pow2Width < Width) pow2Width <<= 1;
978 while (pow2Height < Height) pow2Height <<= 1;
980 if (pow2Width > Width || pow2Height > Height) {
981 /** TODO: add support for non power two compressed textures (OpenGL 2 provices support for * non-power-two textures gratis) **/
982 if (Format == WINED3DFMT_DXT1 || Format == WINED3DFMT_DXT2 || Format == WINED3DFMT_DXT3
983 || Format == WINED3DFMT_DXT4 || Format == WINED3DFMT_DXT5) {
984 FIXME("(%p) Compressed non-power-two textures are not supported w(%d) h(%d)\n",
985 This, Width, Height);
986 return WINED3DERR_NOTAVAILABLE;
990 /** DXTn mipmaps use the same number of 'levels' down to eg. 8x1, but since
991 * it is based around 4x4 pixel blocks it requires padding, so allocate enough
993 *********************************/
994 if (WINED3DFMT_UNKNOWN == Format) {
996 } else if (Format == WINED3DFMT_DXT1) {
997 /* DXT1 is half byte per pixel */
998 Size = ((max(pow2Width,4) * tableEntry->bpp) * max(pow2Height,4)) >> 1;
1000 } else if (Format == WINED3DFMT_DXT2 || Format == WINED3DFMT_DXT3 ||
1001 Format == WINED3DFMT_DXT4 || Format == WINED3DFMT_DXT5) {
1002 Size = ((max(pow2Width,4) * tableEntry->bpp) * max(pow2Height,4));
1004 Size = (pow2Width * tableEntry->bpp) * pow2Height;
1007 /** Create and initialise the surface resource **/
1008 D3DCREATERESOURCEOBJECTINSTANCE(object,Surface,WINED3DRTYPE_SURFACE, Size)
1009 /* "Standalone" surface */
1010 IWineD3DSurface_SetContainer((IWineD3DSurface *)object, NULL);
1012 object->currentDesc.Width = Width;
1013 object->currentDesc.Height = Height;
1014 object->currentDesc.MultiSampleType = MultiSample;
1015 object->currentDesc.MultiSampleQuality = MultisampleQuality;
1017 /* Setup some glformat defaults */
1018 object->glDescription.glFormat = tableEntry->glFormat;
1019 object->glDescription.glFormatInternal = tableEntry->glInternal;
1020 object->glDescription.glType = tableEntry->glType;
1022 object->glDescription.textureName = 0;
1023 object->glDescription.level = Level;
1024 object->glDescription.target = GL_TEXTURE_2D;
1027 object->pow2Width = pow2Width;
1028 object->pow2Height = pow2Height;
1031 object->Flags = 0; /* We start without flags set */
1032 object->Flags |= (pow2Width != Width || pow2Height != Height) ? SFLAG_NONPOW2 : 0;
1033 object->Flags |= Discard ? SFLAG_DISCARD : 0;
1034 object->Flags |= (WINED3DFMT_D16_LOCKABLE == Format) ? SFLAG_LOCKABLE : 0;
1035 object->Flags |= Lockable ? SFLAG_LOCKABLE : 0;
1038 if (WINED3DFMT_UNKNOWN != Format) {
1039 object->bytesPerPixel = tableEntry->bpp;
1040 object->pow2Size = (pow2Width * object->bytesPerPixel) * pow2Height;
1042 object->bytesPerPixel = 0;
1043 object->pow2Size = 0;
1046 /** TODO: change this into a texture transform matrix so that it's processed in hardware **/
1048 TRACE("Pool %d %d %d %d",Pool, WINED3DPOOL_DEFAULT, WINED3DPOOL_MANAGED, WINED3DPOOL_SYSTEMMEM);
1050 /** Quick lockable sanity check TODO: remove this after surfaces, usage and locablility have been debugged properly
1051 * this function is too deap to need to care about things like this.
1052 * Levels need to be checked too, and possibly Type wince they all affect what can be done.
1053 * ****************************************/
1055 case WINED3DPOOL_SCRATCH:
1056 if(Lockable == FALSE)
1057 FIXME("Create suface called with a pool of SCRATCH and a Lockable of FALSE \
1058 which are mutually exclusive, setting lockable to true\n");
1061 case WINED3DPOOL_SYSTEMMEM:
1062 if(Lockable == FALSE) FIXME("Create surface called with a pool of SYSTEMMEM and a Lockable of FALSE, \
1063 this is acceptable but unexpected (I can't know how the surface can be usable!)\n");
1064 case WINED3DPOOL_MANAGED:
1065 if(Usage == WINED3DUSAGE_DYNAMIC) FIXME("Create surface called with a pool of MANAGED and a \
1066 Usage of DYNAMIC which are mutually exclusive, not doing \
1067 anything just telling you.\n");
1069 case WINED3DPOOL_DEFAULT: /*TODO: Create offscreen plain can cause this check to fail..., find out if it should */
1070 if(!(Usage & WINED3DUSAGE_DYNAMIC) && !(Usage & WINED3DUSAGE_RENDERTARGET)
1071 && !(Usage && WINED3DUSAGE_DEPTHSTENCIL ) && Lockable)
1072 WARN("Creating a surface with a POOL of DEFAULT with Lockable true, that doesn't specify DYNAMIC usage.\n");
1075 FIXME("(%p) Unknown pool %d\n", This, Pool);
1079 if (Usage & WINED3DUSAGE_RENDERTARGET && Pool != WINED3DPOOL_DEFAULT) {
1080 FIXME("Trying to create a render target that isn't in the default pool\n");
1083 /* mark the texture as dirty so that it get's loaded first time around*/
1084 IWineD3DSurface_AddDirtyRect(*ppSurface, NULL);
1085 TRACE("(%p) : w(%d) h(%d) fmt(%d,%s) lockable(%d) surf@%p, surfmem@%p, %d bytes\n",
1086 This, Width, Height, Format, debug_d3dformat(Format),
1087 (WINED3DFMT_D16_LOCKABLE == Format), *ppSurface, object->resource.allocatedMemory, object->resource.size);
1089 /* Store the DirectDraw primary surface. This is the first rendertarget surface created */
1090 if( (Usage & WINED3DUSAGE_RENDERTARGET) && (!This->ddraw_primary) )
1091 This->ddraw_primary = (IWineD3DSurface *) object;
1093 /* Look at the implementation and set the correct Vtable */
1095 case SURFACE_OPENGL:
1096 /* Nothing to do, it's set already */
1100 object->lpVtbl = &IWineGDISurface_Vtbl;
1104 /* To be sure to catch this */
1105 ERR("Unknown requested surface implementation %d!\n", Impl);
1106 IWineD3DSurface_Release((IWineD3DSurface *) object);
1107 return WINED3DERR_INVALIDCALL;
1110 /* Call the private setup routine */
1111 return IWineD3DSurface_PrivateSetup( (IWineD3DSurface *) object );
1115 static HRESULT WINAPI IWineD3DDeviceImpl_CreateTexture(IWineD3DDevice *iface, UINT Width, UINT Height, UINT Levels,
1116 DWORD Usage, WINED3DFORMAT Format, WINED3DPOOL Pool,
1117 IWineD3DTexture** ppTexture, HANDLE* pSharedHandle, IUnknown *parent,
1118 D3DCB_CREATESURFACEFN D3DCB_CreateSurface) {
1120 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
1121 IWineD3DTextureImpl *object;
1126 unsigned int pow2Width = Width;
1127 unsigned int pow2Height = Height;
1130 TRACE("(%p) : Width %d, Height %d, Levels %d, Usage %#lx\n", This, Width, Height, Levels, Usage);
1131 TRACE("Format %#x (%s), Pool %#x, ppTexture %p, pSharedHandle %p, parent %p\n",
1132 Format, debug_d3dformat(Format), Pool, ppTexture, pSharedHandle, parent);
1134 /* TODO: It should only be possible to create textures for formats
1135 that are reported as supported */
1136 if (WINED3DFMT_UNKNOWN >= Format) {
1137 WARN("(%p) : Texture cannot be created with a format of D3DFMT_UNKNOWN\n", This);
1138 return WINED3DERR_INVALIDCALL;
1141 D3DCREATERESOURCEOBJECTINSTANCE(object, Texture, WINED3DRTYPE_TEXTURE, 0);
1142 D3DINITIALIZEBASETEXTURE(object->baseTexture);
1143 object->width = Width;
1144 object->height = Height;
1146 /** Non-power2 support **/
1147 /* Find the nearest pow2 match */
1148 pow2Width = pow2Height = 1;
1149 while (pow2Width < Width) pow2Width <<= 1;
1150 while (pow2Height < Height) pow2Height <<= 1;
1152 /** FIXME: add support for real non-power-two if it's provided by the video card **/
1153 /* Precalculated scaling for 'faked' non power of two texture coords */
1154 object->pow2scalingFactorX = (((float)Width) / ((float)pow2Width));
1155 object->pow2scalingFactorY = (((float)Height) / ((float)pow2Height));
1156 TRACE(" xf(%f) yf(%f)\n", object->pow2scalingFactorX, object->pow2scalingFactorY);
1158 /* Calculate levels for mip mapping */
1160 TRACE("calculating levels %d\n", object->baseTexture.levels);
1161 object->baseTexture.levels++;
1164 while (tmpW > 1 || tmpH > 1) {
1165 tmpW = max(1, tmpW >> 1);
1166 tmpH = max(1, tmpH >> 1);
1167 object->baseTexture.levels++;
1169 TRACE("Calculated levels = %d\n", object->baseTexture.levels);
1172 /* Generate all the surfaces */
1175 for (i = 0; i < object->baseTexture.levels; i++)
1177 /* use the callback to create the texture surface */
1178 hr = D3DCB_CreateSurface(This->parent, tmpW, tmpH, Format, Usage, Pool, i, &object->surfaces[i],NULL);
1179 if (hr!= WINED3D_OK || ( (IWineD3DSurfaceImpl *) object->surfaces[i])->Flags & SFLAG_OVERSIZE) {
1180 FIXME("Failed to create surface %p\n", object);
1182 object->surfaces[i] = NULL;
1183 IWineD3DTexture_Release((IWineD3DTexture *)object);
1189 IWineD3DSurface_SetContainer(object->surfaces[i], (IWineD3DBase *)object);
1190 TRACE("Created surface level %d @ %p\n", i, object->surfaces[i]);
1191 /* calculate the next mipmap level */
1192 tmpW = max(1, tmpW >> 1);
1193 tmpH = max(1, tmpH >> 1);
1196 TRACE("(%p) : Created texture %p\n", This, object);
1200 static HRESULT WINAPI IWineD3DDeviceImpl_CreateVolumeTexture(IWineD3DDevice *iface,
1201 UINT Width, UINT Height, UINT Depth,
1202 UINT Levels, DWORD Usage,
1203 WINED3DFORMAT Format, WINED3DPOOL Pool,
1204 IWineD3DVolumeTexture **ppVolumeTexture,
1205 HANDLE *pSharedHandle, IUnknown *parent,
1206 D3DCB_CREATEVOLUMEFN D3DCB_CreateVolume) {
1208 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
1209 IWineD3DVolumeTextureImpl *object;
1215 /* TODO: It should only be possible to create textures for formats
1216 that are reported as supported */
1217 if (WINED3DFMT_UNKNOWN >= Format) {
1218 WARN("(%p) : Texture cannot be created with a format of D3DFMT_UNKNOWN\n", This);
1219 return WINED3DERR_INVALIDCALL;
1222 D3DCREATERESOURCEOBJECTINSTANCE(object, VolumeTexture, WINED3DRTYPE_VOLUMETEXTURE, 0);
1223 D3DINITIALIZEBASETEXTURE(object->baseTexture);
1225 TRACE("(%p) : W(%d) H(%d) D(%d), Lvl(%d) Usage(%ld), Fmt(%u,%s), Pool(%s)\n", This, Width, Height,
1226 Depth, Levels, Usage, Format, debug_d3dformat(Format), debug_d3dpool(Pool));
1228 object->width = Width;
1229 object->height = Height;
1230 object->depth = Depth;
1232 /* Calculate levels for mip mapping */
1234 object->baseTexture.levels++;
1238 while (tmpW > 1 || tmpH > 1 || tmpD > 1) {
1239 tmpW = max(1, tmpW >> 1);
1240 tmpH = max(1, tmpH >> 1);
1241 tmpD = max(1, tmpD >> 1);
1242 object->baseTexture.levels++;
1244 TRACE("Calculated levels = %d\n", object->baseTexture.levels);
1247 /* Generate all the surfaces */
1252 for (i = 0; i < object->baseTexture.levels; i++)
1254 /* Create the volume */
1255 D3DCB_CreateVolume(This->parent, Width, Height, Depth, Format, Pool, Usage,
1256 (IWineD3DVolume **)&object->volumes[i], pSharedHandle);
1258 /* Set it's container to this object */
1259 IWineD3DVolume_SetContainer(object->volumes[i], (IWineD3DBase *)object);
1261 /* calcualte the next mipmap level */
1262 tmpW = max(1, tmpW >> 1);
1263 tmpH = max(1, tmpH >> 1);
1264 tmpD = max(1, tmpD >> 1);
1267 *ppVolumeTexture = (IWineD3DVolumeTexture *) object;
1268 TRACE("(%p) : Created volume texture %p\n", This, object);
1272 static HRESULT WINAPI IWineD3DDeviceImpl_CreateVolume(IWineD3DDevice *iface,
1273 UINT Width, UINT Height, UINT Depth,
1275 WINED3DFORMAT Format, WINED3DPOOL Pool,
1276 IWineD3DVolume** ppVolume,
1277 HANDLE* pSharedHandle, IUnknown *parent) {
1279 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
1280 IWineD3DVolumeImpl *object; /** NOTE: impl ref allowed since this is a create function **/
1281 const PixelFormatDesc *formatDesc = getFormatDescEntry(Format);
1283 D3DCREATERESOURCEOBJECTINSTANCE(object, Volume, WINED3DRTYPE_VOLUME, ((Width * formatDesc->bpp) * Height * Depth))
1285 TRACE("(%p) : W(%d) H(%d) D(%d), Usage(%ld), Fmt(%u,%s), Pool(%s)\n", This, Width, Height,
1286 Depth, Usage, Format, debug_d3dformat(Format), debug_d3dpool(Pool));
1288 object->currentDesc.Width = Width;
1289 object->currentDesc.Height = Height;
1290 object->currentDesc.Depth = Depth;
1291 object->bytesPerPixel = formatDesc->bpp;
1293 /** Note: Volume textures cannot be dxtn, hence no need to check here **/
1294 object->lockable = TRUE;
1295 object->locked = FALSE;
1296 memset(&object->lockedBox, 0, sizeof(WINED3DBOX));
1297 object->dirty = TRUE;
1299 return IWineD3DVolume_AddDirtyBox((IWineD3DVolume *) object, NULL);
1302 static HRESULT WINAPI IWineD3DDeviceImpl_CreateCubeTexture(IWineD3DDevice *iface, UINT EdgeLength,
1303 UINT Levels, DWORD Usage,
1304 WINED3DFORMAT Format, WINED3DPOOL Pool,
1305 IWineD3DCubeTexture **ppCubeTexture,
1306 HANDLE *pSharedHandle, IUnknown *parent,
1307 D3DCB_CREATESURFACEFN D3DCB_CreateSurface) {
1309 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
1310 IWineD3DCubeTextureImpl *object; /** NOTE: impl ref allowed since this is a create function **/
1314 unsigned int pow2EdgeLength = EdgeLength;
1316 /* TODO: It should only be possible to create textures for formats
1317 that are reported as supported */
1318 if (WINED3DFMT_UNKNOWN >= Format) {
1319 WARN("(%p) : Texture cannot be created with a format of D3DFMT_UNKNOWN\n", This);
1320 return WINED3DERR_INVALIDCALL;
1323 D3DCREATERESOURCEOBJECTINSTANCE(object, CubeTexture, WINED3DRTYPE_CUBETEXTURE, 0);
1324 D3DINITIALIZEBASETEXTURE(object->baseTexture);
1326 TRACE("(%p) Create Cube Texture\n", This);
1328 /** Non-power2 support **/
1330 /* Find the nearest pow2 match */
1332 while (pow2EdgeLength < EdgeLength) pow2EdgeLength <<= 1;
1334 object->edgeLength = EdgeLength;
1335 /* TODO: support for native non-power 2 */
1336 /* Precalculated scaling for 'faked' non power of two texture coords */
1337 object->pow2scalingFactor = ((float)EdgeLength) / ((float)pow2EdgeLength);
1339 /* Calculate levels for mip mapping */
1341 object->baseTexture.levels++;
1344 tmpW = max(1, tmpW >> 1);
1345 object->baseTexture.levels++;
1347 TRACE("Calculated levels = %d\n", object->baseTexture.levels);
1350 /* Generate all the surfaces */
1352 for (i = 0; i < object->baseTexture.levels; i++) {
1354 /* Create the 6 faces */
1355 for (j = 0; j < 6; j++) {
1357 hr=D3DCB_CreateSurface(This->parent, tmpW, tmpW, Format, Usage, Pool,
1358 i /* Level */, &object->surfaces[j][i],pSharedHandle);
1360 if(hr!= WINED3D_OK) {
1364 for (l = 0; l < j; l++) {
1365 IWineD3DSurface_Release(object->surfaces[j][i]);
1367 for (k = 0; k < i; k++) {
1368 for (l = 0; l < 6; l++) {
1369 IWineD3DSurface_Release(object->surfaces[l][j]);
1373 FIXME("(%p) Failed to create surface\n",object);
1374 HeapFree(GetProcessHeap(),0,object);
1375 *ppCubeTexture = NULL;
1378 IWineD3DSurface_SetContainer(object->surfaces[j][i], (IWineD3DBase *)object);
1379 TRACE("Created surface level %d @ %p,\n", i, object->surfaces[j][i]);
1381 tmpW = max(1, tmpW >> 1);
1384 TRACE("(%p) : Created Cube Texture %p\n", This, object);
1385 *ppCubeTexture = (IWineD3DCubeTexture *) object;
1389 static HRESULT WINAPI IWineD3DDeviceImpl_CreateQuery(IWineD3DDevice *iface, WINED3DQUERYTYPE Type, IWineD3DQuery **ppQuery, IUnknown* parent) {
1390 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
1391 IWineD3DQueryImpl *object; /*NOTE: impl ref allowed since this is a create function */
1393 if (NULL == ppQuery) {
1394 /* Just a check to see if we support this type of query */
1395 HRESULT hr = WINED3DERR_NOTAVAILABLE;
1397 case WINED3DQUERYTYPE_OCCLUSION:
1398 TRACE("(%p) occlusion query\n", This);
1399 if (GL_SUPPORT(ARB_OCCLUSION_QUERY))
1402 WARN("Unsupported in local OpenGL implementation: ARB_OCCLUSION_QUERY/NV_OCCLUSION_QUERY\n");
1404 case WINED3DQUERYTYPE_VCACHE:
1405 case WINED3DQUERYTYPE_RESOURCEMANAGER:
1406 case WINED3DQUERYTYPE_VERTEXSTATS:
1407 case WINED3DQUERYTYPE_EVENT:
1408 case WINED3DQUERYTYPE_TIMESTAMP:
1409 case WINED3DQUERYTYPE_TIMESTAMPDISJOINT:
1410 case WINED3DQUERYTYPE_TIMESTAMPFREQ:
1411 case WINED3DQUERYTYPE_PIPELINETIMINGS:
1412 case WINED3DQUERYTYPE_INTERFACETIMINGS:
1413 case WINED3DQUERYTYPE_VERTEXTIMINGS:
1414 case WINED3DQUERYTYPE_PIXELTIMINGS:
1415 case WINED3DQUERYTYPE_BANDWIDTHTIMINGS:
1416 case WINED3DQUERYTYPE_CACHEUTILIZATION:
1418 FIXME("(%p) Unhandled query type %d\n", This, Type);
1423 D3DCREATEOBJECTINSTANCE(object, Query)
1424 object->type = Type;
1425 /* allocated the 'extended' data based on the type of query requested */
1427 case D3DQUERYTYPE_OCCLUSION:
1428 if(GL_SUPPORT(ARB_OCCLUSION_QUERY)) {
1429 TRACE("(%p) Allocating data for an occlusion query\n", This);
1430 object->extendedData = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(WineQueryOcclusionData));
1431 GL_EXTCALL(glGenQueriesARB(1, &((WineQueryOcclusionData *)(object->extendedData))->queryId));
1434 case D3DQUERYTYPE_VCACHE:
1435 case D3DQUERYTYPE_RESOURCEMANAGER:
1436 case D3DQUERYTYPE_VERTEXSTATS:
1437 case D3DQUERYTYPE_EVENT:
1438 case D3DQUERYTYPE_TIMESTAMP:
1439 case D3DQUERYTYPE_TIMESTAMPDISJOINT:
1440 case D3DQUERYTYPE_TIMESTAMPFREQ:
1441 case D3DQUERYTYPE_PIPELINETIMINGS:
1442 case D3DQUERYTYPE_INTERFACETIMINGS:
1443 case D3DQUERYTYPE_VERTEXTIMINGS:
1444 case D3DQUERYTYPE_PIXELTIMINGS:
1445 case D3DQUERYTYPE_BANDWIDTHTIMINGS:
1446 case D3DQUERYTYPE_CACHEUTILIZATION:
1448 object->extendedData = 0;
1449 FIXME("(%p) Unhandled query type %d\n",This , Type);
1451 TRACE("(%p) : Created Query %p\n", This, object);
1455 /* example at http://www.fairyengine.com/articles/dxmultiviews.htm */
1456 static HRESULT WINAPI IWineD3DDeviceImpl_CreateAdditionalSwapChain(IWineD3DDevice* iface, WINED3DPRESENT_PARAMETERS* pPresentationParameters, IWineD3DSwapChain** ppSwapChain,
1458 D3DCB_CREATERENDERTARGETFN D3DCB_CreateRenderTarget,
1459 D3DCB_CREATEDEPTHSTENCILSURFACEFN D3DCB_CreateDepthStencil) {
1460 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
1463 IWineD3DSwapChainImpl *object; /** NOTE: impl ref allowed since this is a create function **/
1465 XVisualInfo template;
1466 GLXContext oldContext;
1467 Drawable oldDrawable;
1468 HRESULT hr = WINED3D_OK;
1470 TRACE("(%p) : Created Aditional Swap Chain\n", This);
1472 /** FIXME: Test under windows to find out what the life cycle of a swap chain is,
1473 * does a device hold a reference to a swap chain giving them a lifetime of the device
1474 * or does the swap chain notify the device of its destruction.
1475 *******************************/
1477 /* Check the params */
1478 if(*pPresentationParameters->BackBufferCount > D3DPRESENT_BACK_BUFFER_MAX) {
1479 ERR("App requested %d back buffers, this is not supported for now\n", *pPresentationParameters->BackBufferCount);
1480 return WINED3DERR_INVALIDCALL;
1481 } else if (*pPresentationParameters->BackBufferCount > 1) {
1482 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");
1485 D3DCREATEOBJECTINSTANCE(object, SwapChain)
1487 /*********************
1488 * Lookup the window Handle and the relating X window handle
1489 ********************/
1491 /* Setup hwnd we are using, plus which display this equates to */
1492 object->win_handle = *(pPresentationParameters->hDeviceWindow);
1493 if (!object->win_handle) {
1494 object->win_handle = This->createParms.hFocusWindow;
1497 object->win_handle = GetAncestor(object->win_handle, GA_ROOT);
1498 if ( !( object->win = (Window)GetPropA(object->win_handle, "__wine_x11_whole_window") ) ) {
1499 ERR("Can't get drawable (window), HWND:%p doesn't have the property __wine_x11_whole_window\n", object->win_handle);
1500 return WINED3DERR_NOTAVAILABLE;
1502 hDc = GetDC(object->win_handle);
1503 object->display = get_display(hDc);
1504 ReleaseDC(object->win_handle, hDc);
1505 TRACE("Using a display of %p %p\n", object->display, hDc);
1507 if (NULL == object->display || NULL == hDc) {
1508 WARN("Failed to get a display and HDc for Window %p\n", object->win_handle);
1509 return WINED3DERR_NOTAVAILABLE;
1512 if (object->win == 0) {
1513 WARN("Failed to get a valid XVisuial ID for the window %p\n", object->win_handle);
1514 return WINED3DERR_NOTAVAILABLE;
1517 * Create an opengl context for the display visual
1518 * NOTE: the visual is chosen as the window is created and the glcontext cannot
1519 * use different properties after that point in time. FIXME: How to handle when requested format
1520 * doesn't match actual visual? Cannot choose one here - code removed as it ONLY works if the one
1521 * it chooses is identical to the one already being used!
1522 **********************************/
1524 /** FIXME: Handle stencil appropriately via EnableAutoDepthStencil / AutoDepthStencilFormat **/
1527 /* Create a new context for this swapchain */
1528 template.visualid = (VisualID)GetPropA(GetDesktopWindow(), "__wine_x11_visual_id");
1529 /* TODO: change this to find a similar visual, but one with a stencil/zbuffer buffer that matches the request
1530 (or the best possible if none is requested) */
1531 TRACE("Found x visual ID : %ld\n", template.visualid);
1533 object->visInfo = XGetVisualInfo(object->display, VisualIDMask, &template, &num);
1534 if (NULL == object->visInfo) {
1535 ERR("cannot really get XVisual\n");
1537 return WINED3DERR_NOTAVAILABLE;
1540 /* Write out some debug info about the visual/s */
1541 TRACE("Using x visual ID : %ld\n", template.visualid);
1542 TRACE(" visual info: %p\n", object->visInfo);
1543 TRACE(" num items : %d\n", num);
1544 for (n = 0;n < num; n++) {
1545 TRACE("=====item=====: %d\n", n + 1);
1546 TRACE(" visualid : %ld\n", object->visInfo[n].visualid);
1547 TRACE(" screen : %d\n", object->visInfo[n].screen);
1548 TRACE(" depth : %u\n", object->visInfo[n].depth);
1549 TRACE(" class : %d\n", object->visInfo[n].class);
1550 TRACE(" red_mask : %ld\n", object->visInfo[n].red_mask);
1551 TRACE(" green_mask : %ld\n", object->visInfo[n].green_mask);
1552 TRACE(" blue_mask : %ld\n", object->visInfo[n].blue_mask);
1553 TRACE(" colormap_size : %d\n", object->visInfo[n].colormap_size);
1554 TRACE(" bits_per_rgb : %d\n", object->visInfo[n].bits_per_rgb);
1555 /* log some extra glx info */
1556 glXGetConfig(object->display, object->visInfo, GLX_AUX_BUFFERS, &value);
1557 TRACE(" gl_aux_buffers : %d\n", value);
1558 glXGetConfig(object->display, object->visInfo, GLX_BUFFER_SIZE ,&value);
1559 TRACE(" gl_buffer_size : %d\n", value);
1560 glXGetConfig(object->display, object->visInfo, GLX_RED_SIZE, &value);
1561 TRACE(" gl_red_size : %d\n", value);
1562 glXGetConfig(object->display, object->visInfo, GLX_GREEN_SIZE, &value);
1563 TRACE(" gl_green_size : %d\n", value);
1564 glXGetConfig(object->display, object->visInfo, GLX_BLUE_SIZE, &value);
1565 TRACE(" gl_blue_size : %d\n", value);
1566 glXGetConfig(object->display, object->visInfo, GLX_ALPHA_SIZE, &value);
1567 TRACE(" gl_alpha_size : %d\n", value);
1568 glXGetConfig(object->display, object->visInfo, GLX_DEPTH_SIZE ,&value);
1569 TRACE(" gl_depth_size : %d\n", value);
1570 glXGetConfig(object->display, object->visInfo, GLX_STENCIL_SIZE, &value);
1571 TRACE(" gl_stencil_size : %d\n", value);
1573 /* Now choose a simila visual ID*/
1575 #ifdef USE_CONTEXT_MANAGER
1577 /** TODO: use a context mamager **/
1581 IWineD3DSwapChain *implSwapChain;
1582 if (WINED3D_OK != IWineD3DDevice_GetSwapChain(iface, 0, &implSwapChain)) {
1583 /* The first time around we create the context that is shared with all other swapchains and render targets */
1584 object->glCtx = glXCreateContext(object->display, object->visInfo, NULL, GL_TRUE);
1585 TRACE("Creating implicit context for vis %p, hwnd %p\n", object->display, object->visInfo);
1588 TRACE("Creating context for vis %p, hwnd %p\n", object->display, object->visInfo);
1589 /* TODO: don't use Impl structures outside of create functions! (a context manager will replace the ->glCtx) */
1590 /* and create a new context with the implicit swapchains context as the shared context */
1591 object->glCtx = glXCreateContext(object->display, object->visInfo, ((IWineD3DSwapChainImpl *)implSwapChain)->glCtx, GL_TRUE);
1592 IWineD3DSwapChain_Release(implSwapChain);
1597 XFree(object->visInfo);
1598 object->visInfo = NULL;
1602 if (!object->glCtx) {
1603 ERR("Failed to create GLX context\n");
1604 return WINED3DERR_NOTAVAILABLE;
1606 TRACE("Context created (HWND=%p, glContext=%p, Window=%ld, VisInfo=%p)\n",
1607 object->win_handle, object->glCtx, object->win, object->visInfo);
1610 /*********************
1611 * Windowed / Fullscreen
1612 *******************/
1615 * TODO: MSDN says that we are only allowed one fullscreen swapchain per device,
1616 * so we should really check to see if there is a fullscreen swapchain already
1617 * I think Windows and X have different ideas about fullscreen, does a single head count as full screen?
1618 **************************************/
1620 if (!*(pPresentationParameters->Windowed)) {
1626 /* Get info on the current display setup */
1627 hdc = CreateDCA("DISPLAY", NULL, NULL, NULL);
1628 bpp = GetDeviceCaps(hdc, BITSPIXEL);
1631 /* Change the display settings */
1632 memset(&devmode, 0, sizeof(DEVMODEW));
1633 devmode.dmFields = DM_BITSPERPEL | DM_PELSWIDTH | DM_PELSHEIGHT;
1634 devmode.dmBitsPerPel = (bpp >= 24) ? 32 : bpp; /* Stupid XVidMode cannot change bpp */
1635 devmode.dmPelsWidth = *(pPresentationParameters->BackBufferWidth);
1636 devmode.dmPelsHeight = *(pPresentationParameters->BackBufferHeight);
1637 MultiByteToWideChar(CP_ACP, 0, "Gamers CG", -1, devmode.dmDeviceName, CCHDEVICENAME);
1638 ChangeDisplaySettingsExW(devmode.dmDeviceName, &devmode, object->win_handle, CDS_FULLSCREEN, NULL);
1640 /* Make popup window */
1641 SetWindowLongA(object->win_handle, GWL_STYLE, WS_POPUP);
1642 SetWindowPos(object->win_handle, HWND_TOP, 0, 0,
1643 *(pPresentationParameters->BackBufferWidth),
1644 *(pPresentationParameters->BackBufferHeight), SWP_SHOWWINDOW | SWP_FRAMECHANGED);
1646 /* For GetDisplayMode */
1647 This->ddraw_width = devmode.dmPelsWidth;
1648 This->ddraw_height = devmode.dmPelsHeight;
1649 This->ddraw_format = *(pPresentationParameters->BackBufferFormat);
1653 /** MSDN: If Windowed is TRUE and either of the BackBufferWidth/Height values is zero,
1654 * then the corresponding dimension of the client area of the hDeviceWindow
1655 * (or the focus window, if hDeviceWindow is NULL) is taken.
1656 **********************/
1658 if (*(pPresentationParameters->Windowed) &&
1659 ((*(pPresentationParameters->BackBufferWidth) == 0) ||
1660 (*(pPresentationParameters->BackBufferHeight) == 0))) {
1663 GetClientRect(object->win_handle, &Rect);
1665 if (*(pPresentationParameters->BackBufferWidth) == 0) {
1666 *(pPresentationParameters->BackBufferWidth) = Rect.right;
1667 TRACE("Updating width to %d\n", *(pPresentationParameters->BackBufferWidth));
1669 if (*(pPresentationParameters->BackBufferHeight) == 0) {
1670 *(pPresentationParameters->BackBufferHeight) = Rect.bottom;
1671 TRACE("Updating height to %d\n", *(pPresentationParameters->BackBufferHeight));
1675 /*********************
1676 * finish off parameter initialization
1677 *******************/
1679 /* Put the correct figures in the presentation parameters */
1680 TRACE("Coppying accross presentaion paraneters\n");
1681 object->presentParms.BackBufferWidth = *(pPresentationParameters->BackBufferWidth);
1682 object->presentParms.BackBufferHeight = *(pPresentationParameters->BackBufferHeight);
1683 object->presentParms.BackBufferFormat = *(pPresentationParameters->BackBufferFormat);
1684 object->presentParms.BackBufferCount = *(pPresentationParameters->BackBufferCount);
1685 object->presentParms.MultiSampleType = *(pPresentationParameters->MultiSampleType);
1686 object->presentParms.MultiSampleQuality = NULL == pPresentationParameters->MultiSampleQuality ? 0 : *(pPresentationParameters->MultiSampleQuality);
1687 object->presentParms.SwapEffect = *(pPresentationParameters->SwapEffect);
1688 object->presentParms.hDeviceWindow = *(pPresentationParameters->hDeviceWindow);
1689 object->presentParms.Windowed = *(pPresentationParameters->Windowed);
1690 object->presentParms.EnableAutoDepthStencil = *(pPresentationParameters->EnableAutoDepthStencil);
1691 object->presentParms.AutoDepthStencilFormat = *(pPresentationParameters->AutoDepthStencilFormat);
1692 object->presentParms.Flags = *(pPresentationParameters->Flags);
1693 object->presentParms.FullScreen_RefreshRateInHz = *(pPresentationParameters->FullScreen_RefreshRateInHz);
1694 object->presentParms.PresentationInterval = *(pPresentationParameters->PresentationInterval);
1697 /*********************
1698 * Create the back, front and stencil buffers
1699 *******************/
1701 TRACE("calling rendertarget CB\n");
1702 hr = D3DCB_CreateRenderTarget((IUnknown *) This->parent,
1703 object->presentParms.BackBufferWidth,
1704 object->presentParms.BackBufferHeight,
1705 object->presentParms.BackBufferFormat,
1706 object->presentParms.MultiSampleType,
1707 object->presentParms.MultiSampleQuality,
1708 TRUE /* Lockable */,
1709 &object->frontBuffer,
1710 NULL /* pShared (always null)*/);
1711 if (object->frontBuffer != NULL)
1712 IWineD3DSurface_SetContainer(object->frontBuffer, (IWineD3DBase *)object);
1714 if(object->presentParms.BackBufferCount > 0) {
1717 object->backBuffer = HeapAlloc(GetProcessHeap(), 0, sizeof(IWineD3DSurface *) * object->presentParms.BackBufferCount);
1718 if(!object->backBuffer) {
1719 ERR("Out of memory\n");
1721 if (object->frontBuffer) {
1722 IUnknown *bufferParent;
1723 IWineD3DSurface_GetParent(object->frontBuffer, &bufferParent);
1724 IUnknown_Release(bufferParent); /* once for the get parent */
1725 if (IUnknown_Release(bufferParent) > 0) {
1726 FIXME("(%p) Something's still holding the front buffer\n",This);
1729 HeapFree(GetProcessHeap(), 0, object);
1730 return E_OUTOFMEMORY;
1733 for(i = 0; i < object->presentParms.BackBufferCount; i++) {
1734 TRACE("calling rendertarget CB\n");
1735 hr = D3DCB_CreateRenderTarget((IUnknown *) This->parent,
1736 object->presentParms.BackBufferWidth,
1737 object->presentParms.BackBufferHeight,
1738 object->presentParms.BackBufferFormat,
1739 object->presentParms.MultiSampleType,
1740 object->presentParms.MultiSampleQuality,
1741 TRUE /* Lockable */,
1742 &object->backBuffer[i],
1743 NULL /* pShared (always null)*/);
1744 if(hr == WINED3D_OK && object->backBuffer[i]) {
1745 IWineD3DSurface_SetContainer(object->backBuffer[i], (IWineD3DBase *)object);
1751 object->backBuffer = NULL;
1754 if (object->backBuffer != NULL) {
1756 glDrawBuffer(GL_BACK);
1757 checkGLcall("glDrawBuffer(GL_BACK)");
1760 /* Single buffering - draw to front buffer */
1762 glDrawBuffer(GL_FRONT);
1763 checkGLcall("glDrawBuffer(GL_FRONT)");
1767 /* Under directX swapchains share the depth stencil, so only create one depth-stencil */
1768 if (*(pPresentationParameters->EnableAutoDepthStencil) && hr == WINED3D_OK) {
1769 TRACE("Creating depth stencil buffer\n");
1770 if (This->depthStencilBuffer == NULL ) {
1771 hr = D3DCB_CreateDepthStencil((IUnknown *) This->parent,
1772 object->presentParms.BackBufferWidth,
1773 object->presentParms.BackBufferHeight,
1774 object->presentParms.AutoDepthStencilFormat,
1775 object->presentParms.MultiSampleType,
1776 object->presentParms.MultiSampleQuality,
1777 FALSE /* FIXME: Discard */,
1778 &This->depthStencilBuffer,
1779 NULL /* pShared (always null)*/ );
1780 if (This->depthStencilBuffer != NULL)
1781 IWineD3DSurface_SetContainer(This->depthStencilBuffer, 0);
1784 /** TODO: A check on width, height and multisample types
1785 *(since the zbuffer must be at least as large as the render target and have the same multisample parameters)
1786 ****************************/
1787 object->wantsDepthStencilBuffer = TRUE;
1789 object->wantsDepthStencilBuffer = FALSE;
1792 TRACE("FrontBuf @ %p, BackBuf @ %p, DepthStencil %d\n",object->frontBuffer, object->backBuffer ? object->backBuffer[0] : NULL, object->wantsDepthStencilBuffer);
1795 /*********************
1796 * init the default renderTarget management
1797 *******************/
1798 object->drawable = object->win;
1799 object->render_ctx = object->glCtx;
1801 if (hr == WINED3D_OK) {
1802 /*********************
1803 * Setup some defaults and clear down the buffers
1804 *******************/
1806 /** save current context and drawable **/
1807 oldContext = glXGetCurrentContext();
1808 oldDrawable = glXGetCurrentDrawable();
1810 TRACE("Activating context (display %p context %p drawable %ld)!\n", object->display, object->glCtx, object->win);
1811 if (glXMakeCurrent(object->display, object->win, object->glCtx) == False) {
1812 ERR("Error in setting current context (display %p context %p drawable %ld)!\n", object->display, object->glCtx, object->win);
1814 checkGLcall("glXMakeCurrent");
1816 TRACE("Setting up the screen\n");
1817 /* Clear the screen */
1818 glClearColor(1.0, 0.0, 0.0, 0.0);
1819 checkGLcall("glClearColor");
1822 glClearStencil(0xffff);
1824 checkGLcall("glClear");
1826 glColor3f(1.0, 1.0, 1.0);
1827 checkGLcall("glColor3f");
1829 glEnable(GL_LIGHTING);
1830 checkGLcall("glEnable");
1832 glLightModeli(GL_LIGHT_MODEL_LOCAL_VIEWER, GL_TRUE);
1833 checkGLcall("glLightModeli(GL_LIGHT_MODEL_LOCAL_VIEWER, GL_TRUE);");
1835 glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE_EXT);
1836 checkGLcall("glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE_EXT);");
1838 glLightModeli(GL_LIGHT_MODEL_COLOR_CONTROL, GL_SEPARATE_SPECULAR_COLOR);
1839 checkGLcall("glLightModeli(GL_LIGHT_MODEL_COLOR_CONTROL, GL_SEPARATE_SPECULAR_COLOR);");
1841 /* switch back to the original context (if there was one)*/
1842 if (This->swapchains) {
1843 /** TODO: restore the context and drawable **/
1844 glXMakeCurrent(object->display, oldDrawable, oldContext);
1849 TRACE("Set swapchain to %p\n", object);
1850 } else { /* something went wrong so clean up */
1851 IUnknown* bufferParent;
1852 if (object->frontBuffer) {
1854 IWineD3DSurface_GetParent(object->frontBuffer, &bufferParent);
1855 IUnknown_Release(bufferParent); /* once for the get parent */
1856 if (IUnknown_Release(bufferParent) > 0) {
1857 FIXME("(%p) Something's still holding the front buffer\n",This);
1860 if (object->backBuffer) {
1862 for(i = 0; i < object->presentParms.BackBufferCount; i++) {
1863 if(object->backBuffer[i]) {
1864 IWineD3DSurface_GetParent(object->backBuffer[i], &bufferParent);
1865 IUnknown_Release(bufferParent); /* once for the get parent */
1866 if (IUnknown_Release(bufferParent) > 0) {
1867 FIXME("(%p) Something's still holding the back buffer\n",This);
1871 HeapFree(GetProcessHeap(), 0, object->backBuffer);
1872 object->backBuffer = NULL;
1874 /* NOTE: don't clean up the depthstencil buffer because it belongs to the device */
1875 /* Clean up the context */
1876 /* check that we are the current context first (we shouldn't be though!) */
1877 if (object->glCtx != 0) {
1878 if(glXGetCurrentContext() == object->glCtx) {
1879 glXMakeCurrent(object->display, None, NULL);
1881 glXDestroyContext(object->display, object->glCtx);
1883 HeapFree(GetProcessHeap(), 0, object);
1890 /** NOTE: These are ahead of the other getters and setters to save using a forward declaration **/
1891 static UINT WINAPI IWineD3DDeviceImpl_GetNumberOfSwapChains(IWineD3DDevice *iface) {
1892 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
1893 TRACE("(%p)\n", This);
1895 return This->NumberOfSwapChains;
1898 static HRESULT WINAPI IWineD3DDeviceImpl_GetSwapChain(IWineD3DDevice *iface, UINT iSwapChain, IWineD3DSwapChain **pSwapChain) {
1899 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
1900 TRACE("(%p) : swapchain %d\n", This, iSwapChain);
1902 if(iSwapChain < This->NumberOfSwapChains) {
1903 *pSwapChain = This->swapchains[iSwapChain];
1904 IWineD3DSwapChain_AddRef(*pSwapChain);
1905 TRACE("(%p) returning %p\n", This, *pSwapChain);
1908 TRACE("Swapchain out of range\n");
1910 return WINED3DERR_INVALIDCALL;
1915 * Vertex Declaration
1917 static HRESULT WINAPI IWineD3DDeviceImpl_CreateVertexDeclaration(IWineD3DDevice* iface, CONST VOID* pDeclaration, IWineD3DVertexDeclaration** ppVertexDeclaration, IUnknown *parent) {
1918 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
1919 IWineD3DVertexDeclarationImpl *object = NULL;
1920 HRESULT hr = WINED3D_OK;
1921 TRACE("(%p) : directXVersion=%u, pFunction=%p, ppDecl=%p\n", This, ((IWineD3DImpl *)This->wineD3D)->dxVersion, pDeclaration, ppVertexDeclaration);
1922 D3DCREATEOBJECTINSTANCE(object, VertexDeclaration)
1925 hr = IWineD3DVertexDeclaration_SetDeclaration((IWineD3DVertexDeclaration *)object, (void *)pDeclaration);
1930 /* http://msdn.microsoft.com/archive/default.asp?url=/archive/en-us/directx9_c/directx/graphics/programmingguide/programmable/vertexshaders/vscreate.asp */
1931 static HRESULT WINAPI IWineD3DDeviceImpl_CreateVertexShader(IWineD3DDevice *iface, CONST DWORD *pDeclaration, CONST DWORD *pFunction, IWineD3DVertexShader **ppVertexShader, IUnknown *parent) {
1932 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
1933 IWineD3DVertexShaderImpl *object; /* NOTE: impl usage is ok, this is a create */
1934 HRESULT hr = WINED3D_OK;
1935 D3DCREATEOBJECTINSTANCE(object, VertexShader)
1936 object->baseShader.shader_ins = IWineD3DVertexShaderImpl_shader_ins;
1938 TRACE("(%p) : Created Vertex shader %p\n", This, *ppVertexShader);
1940 /* If a vertex declaration has been passed, save it to the vertex shader, this affects d3d8 only. */
1941 /* Further it needs to be set before calling SetFunction as SetFunction needs the declaration. */
1942 if (pDeclaration != NULL) {
1943 IWineD3DVertexDeclaration *vertexDeclaration;
1944 hr = IWineD3DDevice_CreateVertexDeclaration(iface, pDeclaration, &vertexDeclaration ,NULL);
1945 if (WINED3D_OK == hr) {
1946 TRACE("(%p) : Setting vertex declaration to %p\n", This, vertexDeclaration);
1947 object->vertexDeclaration = vertexDeclaration;
1949 FIXME("(%p) : Failed to set the declaration, returning WINED3DERR_INVALIDCALL\n", iface);
1950 IWineD3DVertexShader_Release(*ppVertexShader);
1951 return WINED3DERR_INVALIDCALL;
1955 hr = IWineD3DVertexShader_SetFunction(*ppVertexShader, pFunction);
1957 if (WINED3D_OK != hr) {
1958 FIXME("(%p) : Failed to set the function, returning WINED3DERR_INVALIDCALL\n", iface);
1959 IWineD3DVertexShader_Release(*ppVertexShader);
1960 return WINED3DERR_INVALIDCALL;
1963 #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. */
1964 if(Usage == WINED3DUSAGE_SOFTWAREVERTEXPROCESSING) {
1975 static HRESULT WINAPI IWineD3DDeviceImpl_CreatePixelShader(IWineD3DDevice *iface, CONST DWORD *pFunction, IWineD3DPixelShader **ppPixelShader, IUnknown *parent) {
1976 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
1977 IWineD3DPixelShaderImpl *object; /* NOTE: impl allowed, this is a create */
1978 HRESULT hr = WINED3D_OK;
1980 D3DCREATEOBJECTINSTANCE(object, PixelShader)
1981 object->baseShader.shader_ins = IWineD3DPixelShaderImpl_shader_ins;
1982 hr = IWineD3DPixelShader_SetFunction(*ppPixelShader, pFunction);
1983 if (WINED3D_OK == hr) {
1984 TRACE("(%p) : Created Pixel shader %p\n", This, *ppPixelShader);
1986 WARN("(%p) : Failed to create pixel shader\n", This);
1992 static HRESULT WINAPI IWineD3DDeviceImpl_CreatePalette(IWineD3DDevice *iface, DWORD Flags, PALETTEENTRY *PalEnt, IWineD3DPalette **Palette, IUnknown *Parent) {
1993 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *) iface;
1994 IWineD3DPaletteImpl *object;
1996 TRACE("(%p)->(%lx, %p, %p, %p)\n", This, Flags, PalEnt, Palette, Parent);
1998 /* Create the new object */
1999 object = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(IWineD3DPaletteImpl));
2001 ERR("Out of memory when allocating memory for a IWineD3DPalette implementation\n");
2002 return E_OUTOFMEMORY;
2005 object->lpVtbl = &IWineD3DPalette_Vtbl;
2007 object->Flags = Flags;
2008 object->parent = Parent;
2009 object->wineD3DDevice = This;
2010 object->palNumEntries = IWineD3DPaletteImpl_Size(Flags);
2012 object->hpal = CreatePalette((const LOGPALETTE*)&(object->palVersion));
2015 HeapFree( GetProcessHeap(), 0, object);
2016 return E_OUTOFMEMORY;
2019 hr = IWineD3DPalette_SetEntries((IWineD3DPalette *) object, 0, 0, IWineD3DPaletteImpl_Size(Flags), PalEnt);
2021 IWineD3DPalette_Release((IWineD3DPalette *) object);
2025 *Palette = (IWineD3DPalette *) object;
2030 static HRESULT WINAPI IWineD3DDeviceImpl_Init3D(IWineD3DDevice *iface, WINED3DPRESENT_PARAMETERS* pPresentationParameters, D3DCB_CREATEADDITIONALSWAPCHAIN D3DCB_CreateAdditionalSwapChain) {
2031 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *) iface;
2032 IWineD3DSwapChainImpl *swapchain;
2034 TRACE("(%p)->(%p,%p)\n", This, pPresentationParameters, D3DCB_CreateAdditionalSwapChain);
2035 if(This->d3d_initialized) return WINED3DERR_INVALIDCALL;
2037 /* TODO: Test if OpenGL is compiled in and loaded */
2039 /* Setup the implicit swapchain */
2040 TRACE("Creating implicit swapchain\n");
2041 if (D3D_OK != D3DCB_CreateAdditionalSwapChain((IUnknown *) This->parent, pPresentationParameters, (IWineD3DSwapChain **)&swapchain) || swapchain == NULL) {
2042 WARN("Failed to create implicit swapchain\n");
2043 return WINED3DERR_INVALIDCALL;
2046 This->NumberOfSwapChains = 1;
2047 This->swapchains = HeapAlloc(GetProcessHeap(), 0, This->NumberOfSwapChains * sizeof(IWineD3DSwapChain *));
2048 if(!This->swapchains) {
2049 ERR("Out of memory!\n");
2050 IWineD3DSwapChain_Release( (IWineD3DSwapChain *) swapchain);
2051 return E_OUTOFMEMORY;
2053 This->swapchains[0] = (IWineD3DSwapChain *) swapchain;
2055 if(swapchain->backBuffer && swapchain->backBuffer[0]) {
2056 TRACE("Setting rendertarget to %p\n", swapchain->backBuffer);
2057 This->renderTarget = swapchain->backBuffer[0];
2060 TRACE("Setting rendertarget to %p\n", swapchain->frontBuffer);
2061 This->renderTarget = swapchain->frontBuffer;
2063 IWineD3DSurface_AddRef(This->renderTarget);
2064 /* Depth Stencil support */
2065 This->stencilBufferTarget = This->depthStencilBuffer;
2066 if (NULL != This->stencilBufferTarget) {
2067 IWineD3DSurface_AddRef(This->stencilBufferTarget);
2070 /* Set up some starting GL setup */
2073 * Initialize openGL extension related variables
2074 * with Default values
2077 ((IWineD3DImpl *) This->wineD3D)->isGLInfoValid = IWineD3DImpl_FillGLCaps( This->wineD3D, swapchain->display);
2078 /* Setup all the devices defaults */
2079 IWineD3DStateBlock_InitStartupStateBlock((IWineD3DStateBlock *)This->stateBlock);
2081 IWineD3DImpl_CheckGraphicsMemory();
2085 /* Initialize our list of GLSL programs */
2086 list_init(&This->glsl_shader_progs);
2088 { /* Set a default viewport */
2092 vp.Width = *(pPresentationParameters->BackBufferWidth);
2093 vp.Height = *(pPresentationParameters->BackBufferHeight);
2096 IWineD3DDevice_SetViewport((IWineD3DDevice *)This, &vp);
2099 /* Initialize the current view state */
2100 This->modelview_valid = 1;
2101 This->proj_valid = 0;
2102 This->view_ident = 1;
2103 This->last_was_rhw = 0;
2104 glGetIntegerv(GL_MAX_LIGHTS, &This->maxConcurrentLights);
2105 TRACE("(%p) All defaults now set up, leaving Init3D with %p\n", This, This);
2107 /* Clear the screen */
2108 IWineD3DDevice_Clear((IWineD3DDevice *) This, 0, NULL, D3DCLEAR_STENCIL|D3DCLEAR_ZBUFFER|D3DCLEAR_TARGET, 0x00, 1.0, 0);
2110 This->d3d_initialized = TRUE;
2114 static HRESULT WINAPI IWineD3DDeviceImpl_Uninit3D(IWineD3DDevice *iface) {
2115 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *) iface;
2117 IUnknown* stencilBufferParent;
2118 IUnknown* swapChainParent;
2120 TRACE("(%p)\n", This);
2122 if(!This->d3d_initialized) return WINED3DERR_INVALIDCALL;
2124 /* Delete the mouse cursor texture */
2125 if(This->cursorTexture) {
2127 glDeleteTextures(1, &This->cursorTexture);
2129 This->cursorTexture = 0;
2132 for(sampler = 0; sampler < GL_LIMITS(sampler_stages); ++sampler) {
2133 IWineD3DDevice_SetTexture(iface, sampler, NULL);
2136 /* Release the buffers (with sanity checks)*/
2137 TRACE("Releasing the depth stencil buffer at %p\n", This->stencilBufferTarget);
2138 if(This->stencilBufferTarget != NULL && (IWineD3DSurface_Release(This->stencilBufferTarget) >0)){
2139 if(This->depthStencilBuffer != This->stencilBufferTarget)
2140 FIXME("(%p) Something's still holding the depthStencilBuffer\n",This);
2142 This->stencilBufferTarget = NULL;
2144 TRACE("Releasing the render target at %p\n", This->renderTarget);
2145 if(IWineD3DSurface_Release(This->renderTarget) >0){
2146 /* This check is a bit silly, itshould be in swapchain_release FIXME("(%p) Something's still holding the renderTarget\n",This); */
2148 TRACE("Setting rendertarget to NULL\n");
2149 This->renderTarget = NULL;
2151 if (This->depthStencilBuffer) {
2152 IWineD3DSurface_GetParent(This->depthStencilBuffer, &stencilBufferParent);
2153 IUnknown_Release(stencilBufferParent); /* once for the get parent */
2154 if(IUnknown_Release(stencilBufferParent) >0){ /* the second time for when it was created */
2155 FIXME("(%p) Something's still holding the depthStencilBuffer\n",This);
2157 This->depthStencilBuffer = NULL;
2160 for(i=0; i < This->NumberOfSwapChains; i++) {
2161 TRACE("Releasing the implicit swapchain %d\n", i);
2162 /* Swapchain 0 is special because it's created in startup with a hanging parent, so we have to release its parent now */
2163 IWineD3DSwapChain_GetParent(This->swapchains[i], &swapChainParent);
2164 IUnknown_Release(swapChainParent); /* once for the get parent */
2165 if (IUnknown_Release(swapChainParent) > 0) { /* the second time for when it was created */
2166 FIXME("(%p) Something's still holding the implicit swapchain\n", This);
2170 HeapFree(GetProcessHeap(), 0, This->swapchains);
2171 This->swapchains = NULL;
2172 This->NumberOfSwapChains = 0;
2174 This->d3d_initialized = FALSE;
2178 static HRESULT WINAPI IWineD3DDeviceImpl_EnumDisplayModes(IWineD3DDevice *iface, DWORD Flags, UINT Width, UINT Height, WINED3DFORMAT pixelformat, LPVOID context, D3DCB_ENUMDISPLAYMODESCALLBACK callback) {
2179 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2183 const PixelFormatDesc *formatDesc = getFormatDescEntry(pixelformat);
2185 TRACE("(%p)->(%lx,%d,%d,%d,%p,%p)\n", This, Flags, Width, Height, pixelformat, context, callback);
2187 for (i = 0; EnumDisplaySettingsExW(NULL, i, &DevModeW, 0); i++) {
2188 /* Ignore some modes if a description was passed */
2189 if ( (Width > 0) && (Width != DevModeW.dmPelsWidth)) continue;
2190 if ( (Height > 0) && (Height != DevModeW.dmPelsHeight)) continue;
2191 if ( (pixelformat != WINED3DFMT_UNKNOWN) && ( formatDesc->bpp != DevModeW.dmBitsPerPel) ) continue;
2193 TRACE("Enumerating %ldx%ld@%s\n", DevModeW.dmPelsWidth, DevModeW.dmPelsHeight, debug_d3dformat(pixelformat_for_depth(DevModeW.dmBitsPerPel)));
2195 if (callback((IUnknown *) This, (UINT) DevModeW.dmPelsWidth, (UINT) DevModeW.dmPelsHeight, pixelformat_for_depth(DevModeW.dmBitsPerPel), 60.0, context) == DDENUMRET_CANCEL)
2202 static HRESULT WINAPI IWineD3DDeviceImpl_SetDisplayMode(IWineD3DDevice *iface, UINT iSwapChain, WINED3DDISPLAYMODE* pMode) {
2204 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2206 const PixelFormatDesc *formatDesc = getFormatDescEntry(pMode->Format);
2208 TRACE("(%p)->(%d,%p) Mode=%dx%dx@%d, %s\n", This, iSwapChain, pMode, pMode->Width, pMode->Height, pMode->RefreshRate, debug_d3dformat(pMode->Format));
2210 /* Resize the screen even without a window:
2211 * The app could have unset it with SetCooperativeLevel, but not called
2212 * RestoreDisplayMode first. Then the release will call RestoreDisplayMode,
2213 * but we don't have any hwnd
2216 devmode.dmFields = DM_BITSPERPEL | DM_PELSWIDTH | DM_PELSHEIGHT;
2217 devmode.dmBitsPerPel = formatDesc->bpp * 8;
2218 if(devmode.dmBitsPerPel == 24) devmode.dmBitsPerPel = 32;
2219 devmode.dmPelsWidth = pMode->Width;
2220 devmode.dmPelsHeight = pMode->Height;
2222 devmode.dmDisplayFrequency = pMode->RefreshRate;
2223 if (pMode->RefreshRate != 0) {
2224 devmode.dmFields |= DM_DISPLAYFREQUENCY;
2227 /* Only change the mode if necessary */
2228 if( (This->ddraw_width == pMode->Width) &&
2229 (This->ddraw_height == pMode->Height) &&
2230 (This->ddraw_format == pMode->Format) &&
2231 (pMode->RefreshRate == 0) ) {
2235 ret = ChangeDisplaySettingsExW(NULL, &devmode, NULL, CDS_FULLSCREEN, NULL);
2236 if (ret != DISP_CHANGE_SUCCESSFUL) {
2237 if(devmode.dmDisplayFrequency != 0) {
2238 WARN("ChangeDisplaySettingsExW failed, trying without the refresh rate\n");
2239 devmode.dmFields &= ~DM_DISPLAYFREQUENCY;
2240 devmode.dmDisplayFrequency = 0;
2241 ret = ChangeDisplaySettingsExW(NULL, &devmode, NULL, CDS_FULLSCREEN, NULL) != DISP_CHANGE_SUCCESSFUL;
2243 if(ret != DISP_CHANGE_SUCCESSFUL) {
2244 return DDERR_INVALIDMODE;
2248 /* Store the new values */
2249 This->ddraw_width = pMode->Width;
2250 This->ddraw_height = pMode->Height;
2251 This->ddraw_format = pMode->Format;
2253 /* Only do this with a window of course */
2254 if(This->ddraw_window)
2255 MoveWindow(This->ddraw_window, 0, 0, pMode->Width, pMode->Height, TRUE);
2260 static HRESULT WINAPI IWineD3DDeviceImpl_GetDirect3D(IWineD3DDevice *iface, IWineD3D **ppD3D) {
2261 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2262 *ppD3D= This->wineD3D;
2263 TRACE("(%p) : wineD3D returning %p\n", This, *ppD3D);
2264 IWineD3D_AddRef(*ppD3D);
2268 static UINT WINAPI IWineD3DDeviceImpl_GetAvailableTextureMem(IWineD3DDevice *iface) {
2269 /** NOTE: There's a probably a hack-around for this one by putting as many pbuffers, VBO's (or whatever)
2270 * Into the video ram as possible and seeing how many fit
2271 * you can also get the correct initial value from nvidia and ATI's driver via X
2272 * texture memory is video memory + AGP memory
2273 *******************/
2274 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2275 static BOOL showfixmes = TRUE;
2277 FIXME("(%p) : stub, simulating %dMB for now, returning %dMB left\n", This,
2278 (wined3d_settings.emulated_textureram/(1024*1024)),
2279 ((wined3d_settings.emulated_textureram - wineD3DGlobalStatistics->glsurfaceram) / (1024*1024)));
2282 TRACE("(%p) : simulating %dMB, returning %dMB left\n", This,
2283 (wined3d_settings.emulated_textureram/(1024*1024)),
2284 ((wined3d_settings.emulated_textureram - wineD3DGlobalStatistics->glsurfaceram) / (1024*1024)));
2285 /* return simulated texture memory left */
2286 return (wined3d_settings.emulated_textureram - wineD3DGlobalStatistics->glsurfaceram);
2294 static HRESULT WINAPI IWineD3DDeviceImpl_SetFVF(IWineD3DDevice *iface, DWORD fvf) {
2295 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2296 HRESULT hr = WINED3D_OK;
2298 /* Update the current state block */
2299 This->updateStateBlock->fvf = fvf;
2300 This->updateStateBlock->changed.fvf = TRUE;
2301 This->updateStateBlock->set.fvf = TRUE;
2303 TRACE("(%p) : FVF Shader FVF set to %lx\n", This, fvf);
2308 static HRESULT WINAPI IWineD3DDeviceImpl_GetFVF(IWineD3DDevice *iface, DWORD *pfvf) {
2309 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2310 TRACE("(%p) : GetFVF returning %lx\n", This, This->stateBlock->fvf);
2311 *pfvf = This->stateBlock->fvf;
2316 * Get / Set Stream Source
2318 static HRESULT WINAPI IWineD3DDeviceImpl_SetStreamSource(IWineD3DDevice *iface, UINT StreamNumber,IWineD3DVertexBuffer* pStreamData, UINT OffsetInBytes, UINT Stride) {
2319 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2320 IWineD3DVertexBuffer *oldSrc;
2322 /**TODO: instance and index data, see
2323 http://msdn.microsoft.com/library/default.asp?url=/library/en-us/directx9_c/directx/graphics/programmingguide/advancedtopics/DrawingMultipleInstances.asp
2325 http://msdn.microsoft.com/library/default.asp?url=/library/en-us/directx9_c/directx/graphics/reference/d3d/interfaces/idirect3ddevice9/SetStreamSourceFreq.asp
2328 /* D3d9 only, but shouldn't hurt d3d8 */
2331 streamFlags = StreamNumber &(D3DSTREAMSOURCE_INDEXEDDATA | D3DSTREAMSOURCE_INSTANCEDATA);
2333 if (streamFlags & D3DSTREAMSOURCE_INDEXEDDATA) {
2334 FIXME("stream index data not supported\n");
2336 if (streamFlags & D3DSTREAMSOURCE_INDEXEDDATA) {
2337 FIXME("stream instance data not supported\n");
2341 StreamNumber&= ~(D3DSTREAMSOURCE_INDEXEDDATA | D3DSTREAMSOURCE_INSTANCEDATA);
2343 if (StreamNumber >= MAX_STREAMS) {
2344 WARN("Stream out of range %d\n", StreamNumber);
2345 return WINED3DERR_INVALIDCALL;
2348 oldSrc = This->stateBlock->streamSource[StreamNumber];
2349 TRACE("(%p) : StreamNo: %d, OldStream (%p), NewStream (%p), NewStride %d\n", This, StreamNumber, oldSrc, pStreamData, Stride);
2351 This->updateStateBlock->changed.streamSource[StreamNumber] = TRUE;
2352 This->updateStateBlock->set.streamSource[StreamNumber] = TRUE;
2353 This->updateStateBlock->streamStride[StreamNumber] = Stride;
2354 This->updateStateBlock->streamSource[StreamNumber] = pStreamData;
2355 This->updateStateBlock->streamOffset[StreamNumber] = OffsetInBytes;
2356 This->updateStateBlock->streamFlags[StreamNumber] = streamFlags;
2358 /* Handle recording of state blocks */
2359 if (This->isRecordingState) {
2360 TRACE("Recording... not performing anything\n");
2364 /* Same stream object: no action */
2365 if (oldSrc == pStreamData)
2368 /* Need to do a getParent and pass the reffs up */
2369 /* MSDN says ..... When an application no longer holds a references to this interface, the interface will automatically be freed.
2370 which suggests that we shouldn't be ref counting? and do need a _release on the stream source to reset the stream source
2371 so for now, just count internally */
2372 if (pStreamData != NULL) {
2373 IWineD3DVertexBufferImpl *vbImpl = (IWineD3DVertexBufferImpl *) pStreamData;
2374 if( (vbImpl->Flags & VBFLAG_STREAM) && vbImpl->stream != StreamNumber) {
2375 WARN("Assigning a Vertex Buffer to stream %d which is already assigned to stream %d\n", StreamNumber, vbImpl->stream);
2377 vbImpl->stream = StreamNumber;
2378 vbImpl->Flags |= VBFLAG_STREAM;
2379 IWineD3DVertexBuffer_AddRef(pStreamData);
2381 if (oldSrc != NULL) {
2382 ((IWineD3DVertexBufferImpl *) oldSrc)->Flags &= ~VBFLAG_STREAM;
2383 IWineD3DVertexBuffer_Release(oldSrc);
2389 static HRESULT WINAPI IWineD3DDeviceImpl_GetStreamSource(IWineD3DDevice *iface, UINT StreamNumber,IWineD3DVertexBuffer** pStream, UINT *pOffset, UINT* pStride) {
2390 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2393 TRACE("(%p) : StreamNo: %d, Stream (%p), Stride %d\n", This, StreamNumber,
2394 This->stateBlock->streamSource[StreamNumber], This->stateBlock->streamStride[StreamNumber]);
2397 streamFlags = StreamNumber &(D3DSTREAMSOURCE_INDEXEDDATA | D3DSTREAMSOURCE_INSTANCEDATA);
2399 if (streamFlags & D3DSTREAMSOURCE_INDEXEDDATA) {
2400 FIXME("stream index data not supported\n");
2402 if (streamFlags & D3DSTREAMSOURCE_INDEXEDDATA) {
2403 FIXME("stream instance data not supported\n");
2407 StreamNumber&= ~(D3DSTREAMSOURCE_INDEXEDDATA | D3DSTREAMSOURCE_INSTANCEDATA);
2409 if (StreamNumber >= MAX_STREAMS) {
2410 WARN("Stream out of range %d\n", StreamNumber);
2411 return WINED3DERR_INVALIDCALL;
2413 *pStream = This->stateBlock->streamSource[StreamNumber];
2414 *pStride = This->stateBlock->streamStride[StreamNumber];
2416 *pOffset = This->stateBlock->streamOffset[StreamNumber];
2419 if (*pStream == NULL) {
2420 FIXME("Attempting to get an empty stream %d, returning WINED3DERR_INVALIDCALL\n", StreamNumber);
2421 return WINED3DERR_INVALIDCALL;
2424 IWineD3DVertexBuffer_AddRef(*pStream); /* We have created a new reference to the VB */
2428 /*Should be quite easy, just an extension of vertexdata
2430 http://msdn.microsoft.com/archive/default.asp?url=/archive/en-us/directx9_c_Summer_04/directx/graphics/programmingguide/advancedtopics/DrawingMultipleInstances.asp
2432 The divider is a bit odd though
2434 VertexOffset = StartVertex / Divider * StreamStride +
2435 VertexIndex / Divider * StreamStride + StreamOffset
2438 static HRESULT WINAPI IWineD3DDeviceImpl_SetStreamSourceFreq(IWineD3DDevice *iface, UINT StreamNumber, UINT Divider) {
2439 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2441 TRACE("(%p) StreamNumber(%d), Divider(%d)\n", This, StreamNumber, Divider);
2442 This->updateStateBlock->streamFlags[StreamNumber] = Divider & (D3DSTREAMSOURCE_INSTANCEDATA | D3DSTREAMSOURCE_INDEXEDDATA );
2444 This->updateStateBlock->changed.streamFreq[StreamNumber] = TRUE;
2445 This->updateStateBlock->set.streamFreq[StreamNumber] = TRUE;
2446 This->updateStateBlock->streamFreq[StreamNumber] = Divider & 0x7FFFFF;
2448 if (This->updateStateBlock->streamFlags[StreamNumber] || This->updateStateBlock->streamFreq[StreamNumber] != 1) {
2449 FIXME("Stream indexing not fully supported\n");
2455 static HRESULT WINAPI IWineD3DDeviceImpl_GetStreamSourceFreq(IWineD3DDevice *iface, UINT StreamNumber, UINT* Divider) {
2456 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2458 TRACE("(%p) StreamNumber(%d), Divider(%p)\n", This, StreamNumber, Divider);
2459 *Divider = This->updateStateBlock->streamFreq[StreamNumber] | This->updateStateBlock->streamFlags[StreamNumber];
2461 TRACE("(%p) : returning %d\n", This, *Divider);
2467 * Get / Set & Multiply Transform
2469 static HRESULT WINAPI IWineD3DDeviceImpl_SetTransform(IWineD3DDevice *iface, D3DTRANSFORMSTATETYPE d3dts, CONST D3DMATRIX* lpmatrix) {
2470 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2472 /* Most of this routine, comments included copied from ddraw tree initially: */
2473 TRACE("(%p) : Transform State=%s\n", This, debug_d3dtstype(d3dts));
2475 /* Handle recording of state blocks */
2476 if (This->isRecordingState) {
2477 TRACE("Recording... not performing anything\n");
2478 This->updateStateBlock->changed.transform[d3dts] = TRUE;
2479 This->updateStateBlock->set.transform[d3dts] = TRUE;
2480 memcpy(&This->updateStateBlock->transforms[d3dts], lpmatrix, sizeof(D3DMATRIX));
2485 * If the new matrix is the same as the current one,
2486 * we cut off any further processing. this seems to be a reasonable
2487 * optimization because as was noticed, some apps (warcraft3 for example)
2488 * tend towards setting the same matrix repeatedly for some reason.
2490 * From here on we assume that the new matrix is different, wherever it matters.
2492 if (!memcmp(&This->stateBlock->transforms[d3dts].u.m[0][0], lpmatrix, sizeof(D3DMATRIX))) {
2493 TRACE("The app is setting the same matrix over again\n");
2496 conv_mat(lpmatrix, &This->stateBlock->transforms[d3dts].u.m[0][0]);
2500 ScreenCoord = ProjectionMat * ViewMat * WorldMat * ObjectCoord
2501 where ViewMat = Camera space, WorldMat = world space.
2503 In OpenGL, camera and world space is combined into GL_MODELVIEW
2504 matrix. The Projection matrix stay projection matrix.
2507 /* Capture the times we can just ignore the change for now */
2508 if (d3dts == WINED3DTS_WORLDMATRIX(0)) {
2509 This->modelview_valid = FALSE;
2512 } else if (d3dts == WINED3DTS_PROJECTION) {
2513 This->proj_valid = FALSE;
2516 } else if (d3dts >= WINED3DTS_WORLDMATRIX(1) && d3dts <= WINED3DTS_WORLDMATRIX(255)) {
2517 /* Indexed Vertex Blending Matrices 256 -> 511 */
2518 /* Use arb_vertex_blend or NV_VERTEX_WEIGHTING? */
2519 FIXME("WINED3DTS_WORLDMATRIX(1..255) not handled\n");
2523 /* Now we really are going to have to change a matrix */
2526 if (d3dts >= WINED3DTS_TEXTURE0 && d3dts <= WINED3DTS_TEXTURE7) { /* handle texture matrices */
2527 /* This is now set with the texture unit states, it may be a good idea to flag the change though! */
2528 } else if (d3dts == WINED3DTS_VIEW) { /* handle the VIEW matrice */
2531 /* If we are changing the View matrix, reset the light and clipping planes to the new view
2532 * NOTE: We have to reset the positions even if the light/plane is not currently
2533 * enabled, since the call to enable it will not reset the position.
2534 * NOTE2: Apparently texture transforms do NOT need reapplying
2537 PLIGHTINFOEL *lightChain = NULL;
2538 This->modelview_valid = FALSE;
2539 This->view_ident = !memcmp(lpmatrix, identity, 16 * sizeof(float));
2541 glMatrixMode(GL_MODELVIEW);
2542 checkGLcall("glMatrixMode(GL_MODELVIEW)");
2544 glLoadMatrixf((float *)lpmatrix);
2545 checkGLcall("glLoadMatrixf(...)");
2548 lightChain = This->stateBlock->lights;
2549 while (lightChain && lightChain->glIndex != -1) {
2550 glLightfv(GL_LIGHT0 + lightChain->glIndex, GL_POSITION, lightChain->lightPosn);
2551 checkGLcall("glLightfv posn");
2552 glLightfv(GL_LIGHT0 + lightChain->glIndex, GL_SPOT_DIRECTION, lightChain->lightDirn);
2553 checkGLcall("glLightfv dirn");
2554 lightChain = lightChain->next;
2557 /* Reset Clipping Planes if clipping is enabled */
2558 for (k = 0; k < GL_LIMITS(clipplanes); k++) {
2559 glClipPlane(GL_CLIP_PLANE0 + k, This->stateBlock->clipplane[k]);
2560 checkGLcall("glClipPlane");
2564 } else { /* What was requested!?? */
2565 WARN("invalid matrix specified: %i\n", d3dts);
2568 /* Release lock, all done */
2573 static HRESULT WINAPI IWineD3DDeviceImpl_GetTransform(IWineD3DDevice *iface, D3DTRANSFORMSTATETYPE State, D3DMATRIX* pMatrix) {
2574 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2575 TRACE("(%p) : for Transform State %s\n", This, debug_d3dtstype(State));
2576 memcpy(pMatrix, &This->stateBlock->transforms[State], sizeof(D3DMATRIX));
2580 static HRESULT WINAPI IWineD3DDeviceImpl_MultiplyTransform(IWineD3DDevice *iface, D3DTRANSFORMSTATETYPE State, CONST D3DMATRIX* pMatrix) {
2581 D3DMATRIX *mat = NULL;
2584 /* Note: Using 'updateStateBlock' rather than 'stateblock' in the code
2585 * below means it will be recorded in a state block change, but it
2586 * works regardless where it is recorded.
2587 * If this is found to be wrong, change to StateBlock.
2589 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2590 TRACE("(%p) : For state %s\n", This, debug_d3dtstype(State));
2592 if (State < HIGHEST_TRANSFORMSTATE)
2594 mat = &This->updateStateBlock->transforms[State];
2596 FIXME("Unhandled transform state!!\n");
2599 multiply_matrix(&temp, mat, (D3DMATRIX *) pMatrix);
2601 /* Apply change via set transform - will reapply to eg. lights this way */
2602 return IWineD3DDeviceImpl_SetTransform(iface, State, &temp);
2607 * WARNING: This code relies on the fact that D3DLIGHT8 == D3DLIGHT9
2609 /* Note lights are real special cases. Although the device caps state only eg. 8 are supported,
2610 you can reference any indexes you want as long as that number max are enabled at any
2611 one point in time! Therefore since the indexes can be anything, we need a linked list of them.
2612 However, this causes stateblock problems. When capturing the state block, I duplicate the list,
2613 but when recording, just build a chain pretty much of commands to be replayed. */
2615 static HRESULT WINAPI IWineD3DDeviceImpl_SetLight(IWineD3DDevice *iface, DWORD Index, CONST WINED3DLIGHT* pLight) {
2617 PLIGHTINFOEL *object, *temp;
2619 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2620 TRACE("(%p) : Idx(%ld), pLight(%p)\n", This, Index, pLight);
2622 /* If recording state block, just add to end of lights chain */
2623 if (This->isRecordingState) {
2624 object = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(PLIGHTINFOEL));
2625 if (NULL == object) {
2626 return WINED3DERR_OUTOFVIDEOMEMORY;
2628 memcpy(&object->OriginalParms, pLight, sizeof(D3DLIGHT9));
2629 object->OriginalIndex = Index;
2630 object->glIndex = -1;
2631 object->changed = TRUE;
2633 /* Add to the END of the chain of lights changes to be replayed */
2634 if (This->updateStateBlock->lights == NULL) {
2635 This->updateStateBlock->lights = object;
2637 temp = This->updateStateBlock->lights;
2638 while (temp->next != NULL) temp=temp->next;
2639 temp->next = object;
2641 TRACE("Recording... not performing anything more\n");
2645 /* Ok, not recording any longer so do real work */
2646 object = This->stateBlock->lights;
2647 while (object != NULL && object->OriginalIndex != Index) object = object->next;
2649 /* If we didn't find it in the list of lights, time to add it */
2650 if (object == NULL) {
2651 PLIGHTINFOEL *insertAt,*prevPos;
2653 object = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(PLIGHTINFOEL));
2654 if (NULL == object) {
2655 return WINED3DERR_OUTOFVIDEOMEMORY;
2657 object->OriginalIndex = Index;
2658 object->glIndex = -1;
2660 /* Add it to the front of list with the idea that lights will be changed as needed
2661 BUT after any lights currently assigned GL indexes */
2662 insertAt = This->stateBlock->lights;
2664 while (insertAt != NULL && insertAt->glIndex != -1) {
2666 insertAt = insertAt->next;
2669 if (insertAt == NULL && prevPos == NULL) { /* Start of list */
2670 This->stateBlock->lights = object;
2671 } else if (insertAt == NULL) { /* End of list */
2672 prevPos->next = object;
2673 object->prev = prevPos;
2674 } else { /* Middle of chain */
2675 if (prevPos == NULL) {
2676 This->stateBlock->lights = object;
2678 prevPos->next = object;
2680 object->prev = prevPos;
2681 object->next = insertAt;
2682 insertAt->prev = object;
2686 /* Initialize the object */
2687 TRACE("Light %ld setting to type %d, Diffuse(%f,%f,%f,%f), Specular(%f,%f,%f,%f), Ambient(%f,%f,%f,%f)\n", Index, pLight->Type,
2688 pLight->Diffuse.r, pLight->Diffuse.g, pLight->Diffuse.b, pLight->Diffuse.a,
2689 pLight->Specular.r, pLight->Specular.g, pLight->Specular.b, pLight->Specular.a,
2690 pLight->Ambient.r, pLight->Ambient.g, pLight->Ambient.b, pLight->Ambient.a);
2691 TRACE("... Pos(%f,%f,%f), Dirn(%f,%f,%f)\n", pLight->Position.x, pLight->Position.y, pLight->Position.z,
2692 pLight->Direction.x, pLight->Direction.y, pLight->Direction.z);
2693 TRACE("... Range(%f), Falloff(%f), Theta(%f), Phi(%f)\n", pLight->Range, pLight->Falloff, pLight->Theta, pLight->Phi);
2695 /* Save away the information */
2696 memcpy(&object->OriginalParms, pLight, sizeof(D3DLIGHT9));
2698 switch (pLight->Type) {
2699 case D3DLIGHT_POINT:
2701 object->lightPosn[0] = pLight->Position.x;
2702 object->lightPosn[1] = pLight->Position.y;
2703 object->lightPosn[2] = pLight->Position.z;
2704 object->lightPosn[3] = 1.0f;
2705 object->cutoff = 180.0f;
2709 case D3DLIGHT_DIRECTIONAL:
2711 object->lightPosn[0] = -pLight->Direction.x;
2712 object->lightPosn[1] = -pLight->Direction.y;
2713 object->lightPosn[2] = -pLight->Direction.z;
2714 object->lightPosn[3] = 0.0;
2715 object->exponent = 0.0f;
2716 object->cutoff = 180.0f;
2721 object->lightPosn[0] = pLight->Position.x;
2722 object->lightPosn[1] = pLight->Position.y;
2723 object->lightPosn[2] = pLight->Position.z;
2724 object->lightPosn[3] = 1.0;
2727 object->lightDirn[0] = pLight->Direction.x;
2728 object->lightDirn[1] = pLight->Direction.y;
2729 object->lightDirn[2] = pLight->Direction.z;
2730 object->lightDirn[3] = 1.0;
2733 * opengl-ish and d3d-ish spot lights use too different models for the
2734 * light "intensity" as a function of the angle towards the main light direction,
2735 * so we only can approximate very roughly.
2736 * however spot lights are rather rarely used in games (if ever used at all).
2737 * furthermore if still used, probably nobody pays attention to such details.
2739 if (pLight->Falloff == 0) {
2742 rho = pLight->Theta + (pLight->Phi - pLight->Theta)/(2*pLight->Falloff);
2744 if (rho < 0.0001) rho = 0.0001f;
2745 object->exponent = -0.3/log(cos(rho/2));
2746 object->cutoff = pLight->Phi*90/M_PI;
2752 FIXME("Unrecognized light type %d\n", pLight->Type);
2755 /* Update the live definitions if the light is currently assigned a glIndex */
2756 if (object->glIndex != -1) {
2757 setup_light(iface, object->glIndex, object);
2762 static HRESULT WINAPI IWineD3DDeviceImpl_GetLight(IWineD3DDevice *iface, DWORD Index, WINED3DLIGHT* pLight) {
2763 PLIGHTINFOEL *lightInfo = NULL;
2764 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2765 TRACE("(%p) : Idx(%ld), pLight(%p)\n", This, Index, pLight);
2767 /* Locate the light in the live lights */
2768 lightInfo = This->stateBlock->lights;
2769 while (lightInfo != NULL && lightInfo->OriginalIndex != Index) lightInfo = lightInfo->next;
2771 if (lightInfo == NULL) {
2772 TRACE("Light information requested but light not defined\n");
2773 return WINED3DERR_INVALIDCALL;
2776 memcpy(pLight, &lightInfo->OriginalParms, sizeof(D3DLIGHT9));
2781 * Get / Set Light Enable
2782 * (Note for consistency, renamed d3dx function by adding the 'set' prefix)
2784 static HRESULT WINAPI IWineD3DDeviceImpl_SetLightEnable(IWineD3DDevice *iface, DWORD Index, BOOL Enable) {
2785 PLIGHTINFOEL *lightInfo = NULL;
2786 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2787 TRACE("(%p) : Idx(%ld), enable? %d\n", This, Index, Enable);
2789 /* Tests show true = 128...not clear why */
2791 Enable = Enable? 128: 0;
2793 /* If recording state block, just add to end of lights chain with changedEnable set to true */
2794 if (This->isRecordingState) {
2795 lightInfo = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(PLIGHTINFOEL));
2796 if (NULL == lightInfo) {
2797 return WINED3DERR_OUTOFVIDEOMEMORY;
2799 lightInfo->OriginalIndex = Index;
2800 lightInfo->glIndex = -1;
2801 lightInfo->enabledChanged = TRUE;
2802 lightInfo->lightEnabled = Enable;
2804 /* Add to the END of the chain of lights changes to be replayed */
2805 if (This->updateStateBlock->lights == NULL) {
2806 This->updateStateBlock->lights = lightInfo;
2808 PLIGHTINFOEL *temp = This->updateStateBlock->lights;
2809 while (temp->next != NULL) temp=temp->next;
2810 temp->next = lightInfo;
2812 TRACE("Recording... not performing anything more\n");
2816 /* Not recording... So, locate the light in the live lights */
2817 lightInfo = This->stateBlock->lights;
2818 while (lightInfo != NULL && lightInfo->OriginalIndex != Index) lightInfo = lightInfo->next;
2820 /* Special case - enabling an undefined light creates one with a strict set of parms! */
2821 if (lightInfo == NULL) {
2823 TRACE("Light enabled requested but light not defined, so defining one!\n");
2824 IWineD3DDeviceImpl_SetLight(iface, Index, &WINED3D_default_light);
2826 /* Search for it again! Should be fairly quick as near head of list */
2827 lightInfo = This->stateBlock->lights;
2828 while (lightInfo != NULL && lightInfo->OriginalIndex != Index) lightInfo = lightInfo->next;
2829 if (lightInfo == NULL) {
2830 FIXME("Adding default lights has failed dismally\n");
2831 return WINED3DERR_INVALIDCALL;
2835 /* OK, we now have a light... */
2836 if (Enable == FALSE) {
2838 /* If we are disabling it, check it was enabled, and
2839 still only do something if it has assigned a glIndex (which it should have!) */
2840 if ((lightInfo->lightEnabled) && (lightInfo->glIndex != -1)) {
2841 TRACE("Disabling light set up at gl idx %ld\n", lightInfo->glIndex);
2843 glDisable(GL_LIGHT0 + lightInfo->glIndex);
2844 checkGLcall("glDisable GL_LIGHT0+Index");
2847 TRACE("Nothing to do as light was not enabled\n");
2849 lightInfo->lightEnabled = Enable;
2852 /* We are enabling it. If it is enabled, it's really simple */
2853 if (lightInfo->lightEnabled) {
2855 TRACE("Nothing to do as light was enabled\n");
2857 /* If it already has a glIndex, it's still simple */
2858 } else if (lightInfo->glIndex != -1) {
2859 TRACE("Reusing light as already set up at gl idx %ld\n", lightInfo->glIndex);
2860 lightInfo->lightEnabled = Enable;
2862 glEnable(GL_LIGHT0 + lightInfo->glIndex);
2863 checkGLcall("glEnable GL_LIGHT0+Index already setup");
2866 /* Otherwise got to find space - lights are ordered gl indexes first */
2868 PLIGHTINFOEL *bsf = NULL;
2869 PLIGHTINFOEL *pos = This->stateBlock->lights;
2870 PLIGHTINFOEL *prev = NULL;
2874 /* Try to minimize changes as much as possible */
2875 while (pos != NULL && pos->glIndex != -1 && Index < This->maxConcurrentLights) {
2877 /* Try to remember which index can be replaced if necessary */
2878 if (bsf==NULL && pos->lightEnabled == FALSE) {
2879 /* Found a light we can replace, save as best replacement */
2883 /* Step to next space */
2889 /* If we have too many active lights, fail the call */
2890 if ((Index == This->maxConcurrentLights) && (bsf == NULL)) {
2891 FIXME("Program requests too many concurrent lights\n");
2892 return WINED3DERR_INVALIDCALL;
2894 /* If we have allocated all lights, but not all are enabled,
2895 reuse one which is not enabled */
2896 } else if (Index == This->maxConcurrentLights) {
2897 /* use bsf - Simply swap the new light and the BSF one */
2898 PLIGHTINFOEL *bsfNext = bsf->next;
2899 PLIGHTINFOEL *bsfPrev = bsf->prev;
2902 if (lightInfo->next != NULL) lightInfo->next->prev = bsf;
2903 if (bsf->prev != NULL) {
2904 bsf->prev->next = lightInfo;
2906 This->stateBlock->lights = lightInfo;
2909 /* If not side by side, lots of chains to update */
2910 if (bsf->next != lightInfo) {
2911 lightInfo->prev->next = bsf;
2912 bsf->next->prev = lightInfo;
2913 bsf->next = lightInfo->next;
2914 bsf->prev = lightInfo->prev;
2915 lightInfo->next = bsfNext;
2916 lightInfo->prev = bsfPrev;
2920 bsf->prev = lightInfo;
2921 bsf->next = lightInfo->next;
2922 lightInfo->next = bsf;
2923 lightInfo->prev = bsfPrev;
2928 glIndex = bsf->glIndex;
2930 lightInfo->glIndex = glIndex;
2931 lightInfo->lightEnabled = Enable;
2933 /* Finally set up the light in gl itself */
2934 TRACE("Replacing light which was set up at gl idx %ld\n", lightInfo->glIndex);
2936 setup_light(iface, glIndex, lightInfo);
2937 glEnable(GL_LIGHT0 + glIndex);
2938 checkGLcall("glEnable GL_LIGHT0 new setup");
2941 /* If we reached the end of the allocated lights, with space in the
2942 gl lights, setup a new light */
2943 } else if (pos->glIndex == -1) {
2945 /* We reached the end of the allocated gl lights, so already
2946 know the index of the next one! */
2948 lightInfo->glIndex = glIndex;
2949 lightInfo->lightEnabled = Enable;
2951 /* In an ideal world, it's already in the right place */
2952 if (lightInfo->prev == NULL || lightInfo->prev->glIndex!=-1) {
2953 /* No need to move it */
2955 /* Remove this light from the list */
2956 lightInfo->prev->next = lightInfo->next;
2957 if (lightInfo->next != NULL) {
2958 lightInfo->next->prev = lightInfo->prev;
2961 /* Add in at appropriate place (inbetween prev and pos) */
2962 lightInfo->prev = prev;
2963 lightInfo->next = pos;
2965 This->stateBlock->lights = lightInfo;
2967 prev->next = lightInfo;
2970 pos->prev = lightInfo;
2974 /* Finally set up the light in gl itself */
2975 TRACE("Defining new light at gl idx %ld\n", lightInfo->glIndex);
2977 setup_light(iface, glIndex, lightInfo);
2978 glEnable(GL_LIGHT0 + glIndex);
2979 checkGLcall("glEnable GL_LIGHT0 new setup");
2988 static HRESULT WINAPI IWineD3DDeviceImpl_GetLightEnable(IWineD3DDevice *iface, DWORD Index,BOOL* pEnable) {
2990 PLIGHTINFOEL *lightInfo = NULL;
2991 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2992 TRACE("(%p) : for idx(%ld)\n", This, Index);
2994 /* Locate the light in the live lights */
2995 lightInfo = This->stateBlock->lights;
2996 while (lightInfo != NULL && lightInfo->OriginalIndex != Index) lightInfo = lightInfo->next;
2998 if (lightInfo == NULL) {
2999 TRACE("Light enabled state requested but light not defined\n");
3000 return WINED3DERR_INVALIDCALL;
3002 *pEnable = lightInfo->lightEnabled;
3007 * Get / Set Clip Planes
3009 static HRESULT WINAPI IWineD3DDeviceImpl_SetClipPlane(IWineD3DDevice *iface, DWORD Index, CONST float *pPlane) {
3010 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3011 TRACE("(%p) : for idx %ld, %p\n", This, Index, pPlane);
3013 /* Validate Index */
3014 if (Index >= GL_LIMITS(clipplanes)) {
3015 TRACE("Application has requested clipplane this device doesn't support\n");
3016 return WINED3DERR_INVALIDCALL;
3019 This->updateStateBlock->changed.clipplane[Index] = TRUE;
3020 This->updateStateBlock->set.clipplane[Index] = TRUE;
3021 This->updateStateBlock->clipplane[Index][0] = pPlane[0];
3022 This->updateStateBlock->clipplane[Index][1] = pPlane[1];
3023 This->updateStateBlock->clipplane[Index][2] = pPlane[2];
3024 This->updateStateBlock->clipplane[Index][3] = pPlane[3];
3026 /* Handle recording of state blocks */
3027 if (This->isRecordingState) {
3028 TRACE("Recording... not performing anything\n");
3036 /* Clip Plane settings are affected by the model view in OpenGL, the View transform in direct3d */
3037 glMatrixMode(GL_MODELVIEW);
3039 glLoadMatrixf((float *) &This->stateBlock->transforms[WINED3DTS_VIEW].u.m[0][0]);
3041 TRACE("Clipplane [%f,%f,%f,%f]\n",
3042 This->updateStateBlock->clipplane[Index][0],
3043 This->updateStateBlock->clipplane[Index][1],
3044 This->updateStateBlock->clipplane[Index][2],
3045 This->updateStateBlock->clipplane[Index][3]);
3046 glClipPlane(GL_CLIP_PLANE0 + Index, This->updateStateBlock->clipplane[Index]);
3047 checkGLcall("glClipPlane");
3055 static HRESULT WINAPI IWineD3DDeviceImpl_GetClipPlane(IWineD3DDevice *iface, DWORD Index, float *pPlane) {
3056 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3057 TRACE("(%p) : for idx %ld\n", This, Index);
3059 /* Validate Index */
3060 if (Index >= GL_LIMITS(clipplanes)) {
3061 TRACE("Application has requested clipplane this device doesn't support\n");
3062 return WINED3DERR_INVALIDCALL;
3065 pPlane[0] = This->stateBlock->clipplane[Index][0];
3066 pPlane[1] = This->stateBlock->clipplane[Index][1];
3067 pPlane[2] = This->stateBlock->clipplane[Index][2];
3068 pPlane[3] = This->stateBlock->clipplane[Index][3];
3073 * Get / Set Clip Plane Status
3074 * WARNING: This code relies on the fact that D3DCLIPSTATUS8 == D3DCLIPSTATUS9
3076 static HRESULT WINAPI IWineD3DDeviceImpl_SetClipStatus(IWineD3DDevice *iface, CONST WINED3DCLIPSTATUS* pClipStatus) {
3077 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3078 FIXME("(%p) : stub\n", This);
3079 if (NULL == pClipStatus) {
3080 return WINED3DERR_INVALIDCALL;
3082 This->updateStateBlock->clip_status.ClipUnion = pClipStatus->ClipUnion;
3083 This->updateStateBlock->clip_status.ClipIntersection = pClipStatus->ClipIntersection;
3087 static HRESULT WINAPI IWineD3DDeviceImpl_GetClipStatus(IWineD3DDevice *iface, WINED3DCLIPSTATUS* pClipStatus) {
3088 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3089 FIXME("(%p) : stub\n", This);
3090 if (NULL == pClipStatus) {
3091 return WINED3DERR_INVALIDCALL;
3093 pClipStatus->ClipUnion = This->updateStateBlock->clip_status.ClipUnion;
3094 pClipStatus->ClipIntersection = This->updateStateBlock->clip_status.ClipIntersection;
3099 * Get / Set Material
3100 * WARNING: This code relies on the fact that D3DMATERIAL8 == D3DMATERIAL9
3102 static HRESULT WINAPI IWineD3DDeviceImpl_SetMaterial(IWineD3DDevice *iface, CONST WINED3DMATERIAL* pMaterial) {
3103 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3105 This->updateStateBlock->changed.material = TRUE;
3106 This->updateStateBlock->set.material = TRUE;
3107 memcpy(&This->updateStateBlock->material, pMaterial, sizeof(WINED3DMATERIAL));
3109 /* Handle recording of state blocks */
3110 if (This->isRecordingState) {
3111 TRACE("Recording... not performing anything\n");
3116 TRACE("(%p) : Diffuse (%f,%f,%f,%f)\n", This, pMaterial->Diffuse.r, pMaterial->Diffuse.g,
3117 pMaterial->Diffuse.b, pMaterial->Diffuse.a);
3118 TRACE("(%p) : Ambient (%f,%f,%f,%f)\n", This, pMaterial->Ambient.r, pMaterial->Ambient.g,
3119 pMaterial->Ambient.b, pMaterial->Ambient.a);
3120 TRACE("(%p) : Specular (%f,%f,%f,%f)\n", This, pMaterial->Specular.r, pMaterial->Specular.g,
3121 pMaterial->Specular.b, pMaterial->Specular.a);
3122 TRACE("(%p) : Emissive (%f,%f,%f,%f)\n", This, pMaterial->Emissive.r, pMaterial->Emissive.g,
3123 pMaterial->Emissive.b, pMaterial->Emissive.a);
3124 TRACE("(%p) : Power (%f)\n", This, pMaterial->Power);
3126 glMaterialfv(GL_FRONT_AND_BACK, GL_AMBIENT, (float*) &This->updateStateBlock->material.Ambient);
3127 checkGLcall("glMaterialfv(GL_AMBIENT)");
3128 glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, (float*) &This->updateStateBlock->material.Diffuse);
3129 checkGLcall("glMaterialfv(GL_DIFFUSE)");
3131 /* Only change material color if specular is enabled, otherwise it is set to black */
3132 if (This->stateBlock->renderState[WINED3DRS_SPECULARENABLE]) {
3133 glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, (float*) &This->updateStateBlock->material.Specular);
3134 checkGLcall("glMaterialfv(GL_SPECULAR");
3136 float black[4] = {0.0f, 0.0f, 0.0f, 0.0f};
3137 glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, &black[0]);
3138 checkGLcall("glMaterialfv(GL_SPECULAR");
3140 glMaterialfv(GL_FRONT_AND_BACK, GL_EMISSION, (float*) &This->updateStateBlock->material.Emissive);
3141 checkGLcall("glMaterialfv(GL_EMISSION)");
3142 glMaterialf(GL_FRONT_AND_BACK, GL_SHININESS, This->updateStateBlock->material.Power);
3143 checkGLcall("glMaterialf(GL_SHININESS");
3149 static HRESULT WINAPI IWineD3DDeviceImpl_GetMaterial(IWineD3DDevice *iface, WINED3DMATERIAL* pMaterial) {
3150 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3151 memcpy(pMaterial, &This->updateStateBlock->material, sizeof (WINED3DMATERIAL));
3152 TRACE("(%p) : Diffuse (%f,%f,%f,%f)\n", This, pMaterial->Diffuse.r, pMaterial->Diffuse.g,
3153 pMaterial->Diffuse.b, pMaterial->Diffuse.a);
3154 TRACE("(%p) : Ambient (%f,%f,%f,%f)\n", This, pMaterial->Ambient.r, pMaterial->Ambient.g,
3155 pMaterial->Ambient.b, pMaterial->Ambient.a);
3156 TRACE("(%p) : Specular (%f,%f,%f,%f)\n", This, pMaterial->Specular.r, pMaterial->Specular.g,
3157 pMaterial->Specular.b, pMaterial->Specular.a);
3158 TRACE("(%p) : Emissive (%f,%f,%f,%f)\n", This, pMaterial->Emissive.r, pMaterial->Emissive.g,
3159 pMaterial->Emissive.b, pMaterial->Emissive.a);
3160 TRACE("(%p) : Power (%f)\n", This, pMaterial->Power);
3168 static HRESULT WINAPI IWineD3DDeviceImpl_SetIndices(IWineD3DDevice *iface, IWineD3DIndexBuffer* pIndexData,
3169 UINT BaseVertexIndex) {
3170 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3171 IWineD3DIndexBuffer *oldIdxs;
3173 TRACE("(%p) : Setting to %p, base %d\n", This, pIndexData, BaseVertexIndex);
3174 oldIdxs = This->updateStateBlock->pIndexData;
3176 This->updateStateBlock->changed.indices = TRUE;
3177 This->updateStateBlock->set.indices = TRUE;
3178 This->updateStateBlock->pIndexData = pIndexData;
3179 This->updateStateBlock->baseVertexIndex = BaseVertexIndex;
3181 /* Handle recording of state blocks */
3182 if (This->isRecordingState) {
3183 TRACE("Recording... not performing anything\n");
3187 if (NULL != pIndexData) {
3188 IWineD3DIndexBuffer_AddRef(pIndexData);
3190 if (NULL != oldIdxs) {
3191 IWineD3DIndexBuffer_Release(oldIdxs);
3196 static HRESULT WINAPI IWineD3DDeviceImpl_GetIndices(IWineD3DDevice *iface, IWineD3DIndexBuffer** ppIndexData, UINT* pBaseVertexIndex) {
3197 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3199 *ppIndexData = This->stateBlock->pIndexData;
3201 /* up ref count on ppindexdata */
3203 IWineD3DIndexBuffer_AddRef(*ppIndexData);
3204 *pBaseVertexIndex = This->stateBlock->baseVertexIndex;
3205 TRACE("(%p) index data set to %p + %u\n", This, ppIndexData, This->stateBlock->baseVertexIndex);
3207 TRACE("(%p) No index data set\n", This);
3209 TRACE("Returning %p %d\n", *ppIndexData, *pBaseVertexIndex);
3215 * Get / Set Viewports
3217 static HRESULT WINAPI IWineD3DDeviceImpl_SetViewport(IWineD3DDevice *iface, CONST WINED3DVIEWPORT* pViewport) {
3218 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3220 TRACE("(%p)\n", This);
3221 This->updateStateBlock->changed.viewport = TRUE;
3222 This->updateStateBlock->set.viewport = TRUE;
3223 memcpy(&This->updateStateBlock->viewport, pViewport, sizeof(WINED3DVIEWPORT));
3225 /* Handle recording of state blocks */
3226 if (This->isRecordingState) {
3227 TRACE("Recording... not performing anything\n");
3230 This->viewport_changed = TRUE;
3234 TRACE("(%p) : x=%ld, y=%ld, wid=%ld, hei=%ld, minz=%f, maxz=%f\n", This,
3235 pViewport->X, pViewport->Y, pViewport->Width, pViewport->Height, pViewport->MinZ, pViewport->MaxZ);
3237 glDepthRange(pViewport->MinZ, pViewport->MaxZ);
3238 checkGLcall("glDepthRange");
3239 /* Note: GL requires lower left, DirectX supplies upper left */
3240 /* TODO: replace usage of renderTarget with context management */
3241 glViewport(pViewport->X,
3242 (((IWineD3DSurfaceImpl *)This->renderTarget)->currentDesc.Height - (pViewport->Y + pViewport->Height)),
3243 pViewport->Width, pViewport->Height);
3245 checkGLcall("glViewport");
3253 static HRESULT WINAPI IWineD3DDeviceImpl_GetViewport(IWineD3DDevice *iface, WINED3DVIEWPORT* pViewport) {
3254 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3255 TRACE("(%p)\n", This);
3256 memcpy(pViewport, &This->stateBlock->viewport, sizeof(WINED3DVIEWPORT));
3260 static void renderstate_stencil_twosided(
3261 IWineD3DDeviceImpl *This,
3268 GLint stencilPass ) {
3269 #if 0 /* Don't use OpenGL 2.0 calls for now */
3270 if(GL_EXTCALL(glStencilFuncSeparate) && GL_EXTCALL(glStencilOpSeparate)) {
3271 GL_EXTCALL(glStencilFuncSeparate(face, func, ref, mask));
3272 checkGLcall("glStencilFuncSeparate(...)");
3273 GL_EXTCALL(glStencilOpSeparate(face, stencilFail, depthFail, stencilPass));
3274 checkGLcall("glStencilOpSeparate(...)");
3278 if(GL_SUPPORT(EXT_STENCIL_TWO_SIDE)) {
3279 glEnable(GL_STENCIL_TEST_TWO_SIDE_EXT);
3280 checkGLcall("glEnable(GL_STENCIL_TEST_TWO_SIDE_EXT)");
3281 GL_EXTCALL(glActiveStencilFaceEXT(face));
3282 checkGLcall("glActiveStencilFaceEXT(...)");
3283 glStencilFunc(func, ref, mask);
3284 checkGLcall("glStencilFunc(...)");
3285 glStencilOp(stencilFail, depthFail, stencilPass);
3286 checkGLcall("glStencilOp(...)");
3287 } else if(GL_SUPPORT(ATI_SEPARATE_STENCIL)) {
3288 GL_EXTCALL(glStencilFuncSeparateATI(face, func, ref, mask));
3289 checkGLcall("glStencilFuncSeparateATI(...)");
3290 GL_EXTCALL(glStencilOpSeparateATI(face, stencilFail, depthFail, stencilPass));
3291 checkGLcall("glStencilOpSeparateATI(...)");
3293 ERR("Separate (two sided) stencil not supported on this version of opengl. Caps weren't honored?\n");
3297 static void renderstate_stencil(IWineD3DDeviceImpl *This, D3DRENDERSTATETYPE State, DWORD Value) {
3298 DWORD onesided_enable = FALSE;
3299 DWORD twosided_enable = FALSE;
3300 GLint func = GL_ALWAYS;
3301 GLint func_ccw = GL_ALWAYS;
3304 GLint stencilFail = GL_KEEP;
3305 GLint depthFail = GL_KEEP;
3306 GLint stencilPass = GL_KEEP;
3307 GLint stencilFail_ccw = GL_KEEP;
3308 GLint depthFail_ccw = GL_KEEP;
3309 GLint stencilPass_ccw = GL_KEEP;
3311 if( This->stateBlock->set.renderState[WINED3DRS_STENCILENABLE] )
3312 onesided_enable = This->stateBlock->renderState[WINED3DRS_STENCILENABLE];
3313 if( This->stateBlock->set.renderState[WINED3DRS_TWOSIDEDSTENCILMODE] )
3314 twosided_enable = This->stateBlock->renderState[WINED3DRS_TWOSIDEDSTENCILMODE];
3315 if( This->stateBlock->set.renderState[WINED3DRS_STENCILFUNC] )
3316 if( !( func = CompareFunc(This->stateBlock->renderState[WINED3DRS_STENCILFUNC]) ) )
3318 if( This->stateBlock->set.renderState[WINED3DRS_CCW_STENCILFUNC] )
3319 if( !( func_ccw = CompareFunc(This->stateBlock->renderState[WINED3DRS_CCW_STENCILFUNC]) ) )
3321 if( This->stateBlock->set.renderState[WINED3DRS_STENCILREF] )
3322 ref = This->stateBlock->renderState[WINED3DRS_STENCILREF];
3323 if( This->stateBlock->set.renderState[WINED3DRS_STENCILMASK] )
3324 mask = This->stateBlock->renderState[WINED3DRS_STENCILMASK];
3325 if( This->stateBlock->set.renderState[WINED3DRS_STENCILFAIL] )
3326 stencilFail = StencilOp(This->stateBlock->renderState[WINED3DRS_STENCILFAIL]);
3327 if( This->stateBlock->set.renderState[WINED3DRS_STENCILZFAIL] )
3328 depthFail = StencilOp(This->stateBlock->renderState[WINED3DRS_STENCILZFAIL]);
3329 if( This->stateBlock->set.renderState[WINED3DRS_STENCILPASS] )
3330 stencilPass = StencilOp(This->stateBlock->renderState[WINED3DRS_STENCILPASS]);
3331 if( This->stateBlock->set.renderState[WINED3DRS_CCW_STENCILFAIL] )
3332 stencilFail_ccw = StencilOp(This->stateBlock->renderState[WINED3DRS_CCW_STENCILFAIL]);
3333 if( This->stateBlock->set.renderState[WINED3DRS_CCW_STENCILZFAIL] )
3334 depthFail_ccw = StencilOp(This->stateBlock->renderState[WINED3DRS_CCW_STENCILZFAIL]);
3335 if( This->stateBlock->set.renderState[WINED3DRS_CCW_STENCILPASS] )
3336 stencilPass_ccw = StencilOp(This->stateBlock->renderState[WINED3DRS_CCW_STENCILPASS]);
3339 case WINED3DRS_STENCILENABLE :
3340 onesided_enable = Value;
3342 case WINED3DRS_TWOSIDEDSTENCILMODE :
3343 twosided_enable = Value;
3345 case WINED3DRS_STENCILFUNC :
3346 if( !( func = CompareFunc(Value) ) )
3349 case WINED3DRS_CCW_STENCILFUNC :
3350 if( !( func_ccw = CompareFunc(Value) ) )
3351 func_ccw = GL_ALWAYS;
3353 case WINED3DRS_STENCILREF :
3356 case WINED3DRS_STENCILMASK :
3359 case WINED3DRS_STENCILFAIL :
3360 stencilFail = StencilOp(Value);
3362 case WINED3DRS_STENCILZFAIL :
3363 depthFail = StencilOp(Value);
3365 case WINED3DRS_STENCILPASS :
3366 stencilPass = StencilOp(Value);
3368 case WINED3DRS_CCW_STENCILFAIL :
3369 stencilFail_ccw = StencilOp(Value);
3371 case WINED3DRS_CCW_STENCILZFAIL :
3372 depthFail_ccw = StencilOp(Value);
3374 case WINED3DRS_CCW_STENCILPASS :
3375 stencilPass_ccw = StencilOp(Value);
3378 ERR("This should not happen!");
3381 TRACE("(onesided %ld, twosided %ld, ref %x, mask %x, \
3382 GL_FRONT: func: %x, fail %x, zfail %x, zpass %x \
3383 GL_BACK: func: %x, fail %x, zfail %x, zpass %x )\n",
3384 onesided_enable, twosided_enable, ref, mask,
3385 func, stencilFail, depthFail, stencilPass,
3386 func_ccw, stencilFail_ccw, depthFail_ccw, stencilPass_ccw);
3388 if (twosided_enable) {
3389 renderstate_stencil_twosided(This, GL_FRONT, func, ref, mask, stencilFail, depthFail, stencilPass);
3390 renderstate_stencil_twosided(This, GL_BACK, func_ccw, ref, mask, stencilFail_ccw, depthFail_ccw, stencilPass_ccw);
3392 if (onesided_enable) {
3393 glEnable(GL_STENCIL_TEST);
3394 checkGLcall("glEnable GL_STENCIL_TEST");
3395 glStencilFunc(func, ref, mask);
3396 checkGLcall("glStencilFunc(...)");
3397 glStencilOp(stencilFail, depthFail, stencilPass);
3398 checkGLcall("glStencilOp(...)");
3400 glDisable(GL_STENCIL_TEST);
3401 checkGLcall("glDisable GL_STENCIL_TEST");
3407 * Get / Set Render States
3408 * TODO: Verify against dx9 definitions
3410 static HRESULT WINAPI IWineD3DDeviceImpl_SetRenderState(IWineD3DDevice *iface, D3DRENDERSTATETYPE State, DWORD Value) {
3412 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3413 DWORD OldValue = This->stateBlock->renderState[State];
3415 /* Simple way of referring to either a DWORD or a 4 byte float */
3421 TRACE("(%p)->state = %s(%d), value = %ld\n", This, debug_d3drenderstate(State), State, Value);
3422 This->updateStateBlock->changed.renderState[State] = TRUE;
3423 This->updateStateBlock->set.renderState[State] = TRUE;
3424 This->updateStateBlock->renderState[State] = Value;
3426 /* Handle recording of state blocks */
3427 if (This->isRecordingState) {
3428 TRACE("Recording... not performing anything\n");
3435 case WINED3DRS_FILLMODE :
3436 switch ((D3DFILLMODE) Value) {
3437 case D3DFILL_POINT : glPolygonMode(GL_FRONT_AND_BACK, GL_POINT); break;
3438 case D3DFILL_WIREFRAME : glPolygonMode(GL_FRONT_AND_BACK, GL_LINE); break;
3439 case D3DFILL_SOLID : glPolygonMode(GL_FRONT_AND_BACK, GL_FILL); break;
3441 FIXME("Unrecognized WINED3DRS_FILLMODE value %ld\n", Value);
3443 checkGLcall("glPolygonMode (fillmode)");
3446 case WINED3DRS_LIGHTING :
3448 glEnable(GL_LIGHTING);
3449 checkGLcall("glEnable GL_LIGHTING");
3451 glDisable(GL_LIGHTING);
3452 checkGLcall("glDisable GL_LIGHTING");
3456 case WINED3DRS_ZENABLE :
3457 switch ((D3DZBUFFERTYPE) Value) {
3459 glDisable(GL_DEPTH_TEST);
3460 checkGLcall("glDisable GL_DEPTH_TEST");
3463 glEnable(GL_DEPTH_TEST);
3464 checkGLcall("glEnable GL_DEPTH_TEST");
3467 glEnable(GL_DEPTH_TEST);
3468 checkGLcall("glEnable GL_DEPTH_TEST");
3469 FIXME("W buffer is not well handled\n");
3472 FIXME("Unrecognized D3DZBUFFERTYPE value %ld\n", Value);
3476 case WINED3DRS_CULLMODE :
3478 /* If we are culling "back faces with clockwise vertices" then
3479 set front faces to be counter clockwise and enable culling
3481 switch ((D3DCULL) Value) {
3483 glDisable(GL_CULL_FACE);
3484 checkGLcall("glDisable GL_CULL_FACE");
3487 glEnable(GL_CULL_FACE);
3488 checkGLcall("glEnable GL_CULL_FACE");
3489 if (This->renderUpsideDown) {
3491 checkGLcall("glFrontFace GL_CW");
3493 glFrontFace(GL_CCW);
3494 checkGLcall("glFrontFace GL_CCW");
3496 glCullFace(GL_BACK);
3499 glEnable(GL_CULL_FACE);
3500 checkGLcall("glEnable GL_CULL_FACE");
3501 if (This->renderUpsideDown) {
3502 glFrontFace(GL_CCW);
3503 checkGLcall("glFrontFace GL_CCW");
3506 checkGLcall("glFrontFace GL_CW");
3508 glCullFace(GL_BACK);
3511 FIXME("Unrecognized/Unhandled D3DCULL value %ld\n", Value);
3515 case WINED3DRS_SHADEMODE :
3516 switch ((D3DSHADEMODE) Value) {
3518 glShadeModel(GL_FLAT);
3519 checkGLcall("glShadeModel");
3521 case D3DSHADE_GOURAUD:
3522 glShadeModel(GL_SMOOTH);
3523 checkGLcall("glShadeModel");
3525 case D3DSHADE_PHONG:
3526 FIXME("D3DSHADE_PHONG isn't supported\n");
3529 FIXME("Unrecognized/Unhandled D3DSHADEMODE value %ld\n", Value);
3533 case WINED3DRS_DITHERENABLE :
3535 glEnable(GL_DITHER);
3536 checkGLcall("glEnable GL_DITHER");
3538 glDisable(GL_DITHER);
3539 checkGLcall("glDisable GL_DITHER");
3543 case WINED3DRS_ZWRITEENABLE :
3546 checkGLcall("glDepthMask");
3549 checkGLcall("glDepthMask");
3553 case WINED3DRS_ZFUNC :
3555 int glParm = CompareFunc(Value);
3558 glDepthFunc(glParm);
3559 checkGLcall("glDepthFunc");
3564 case WINED3DRS_AMBIENT :
3567 D3DCOLORTOGLFLOAT4(Value, col);
3568 TRACE("Setting ambient to (%f,%f,%f,%f)\n", col[0], col[1], col[2], col[3]);
3569 glLightModelfv(GL_LIGHT_MODEL_AMBIENT, col);
3570 checkGLcall("glLightModel for MODEL_AMBIENT");
3575 case WINED3DRS_ALPHABLENDENABLE :
3578 checkGLcall("glEnable GL_BLEND");
3580 glDisable(GL_BLEND);
3581 checkGLcall("glDisable GL_BLEND");
3585 case WINED3DRS_SRCBLEND :
3586 case WINED3DRS_DESTBLEND :
3588 int newVal = GL_ZERO;
3590 case D3DBLEND_ZERO : newVal = GL_ZERO; break;
3591 case D3DBLEND_ONE : newVal = GL_ONE; break;
3592 case D3DBLEND_SRCCOLOR : newVal = GL_SRC_COLOR; break;
3593 case D3DBLEND_INVSRCCOLOR : newVal = GL_ONE_MINUS_SRC_COLOR; break;
3594 case D3DBLEND_SRCALPHA : newVal = GL_SRC_ALPHA; break;
3595 case D3DBLEND_INVSRCALPHA : newVal = GL_ONE_MINUS_SRC_ALPHA; break;
3596 case D3DBLEND_DESTALPHA : newVal = GL_DST_ALPHA; break;
3597 case D3DBLEND_INVDESTALPHA : newVal = GL_ONE_MINUS_DST_ALPHA; break;
3598 case D3DBLEND_DESTCOLOR : newVal = GL_DST_COLOR; break;
3599 case D3DBLEND_INVDESTCOLOR : newVal = GL_ONE_MINUS_DST_COLOR; break;
3600 case D3DBLEND_SRCALPHASAT : newVal = GL_SRC_ALPHA_SATURATE; break;
3602 case D3DBLEND_BOTHSRCALPHA : newVal = GL_SRC_ALPHA;
3603 This->srcBlend = newVal;
3604 This->dstBlend = newVal;
3607 case D3DBLEND_BOTHINVSRCALPHA : newVal = GL_ONE_MINUS_SRC_ALPHA;
3608 This->srcBlend = newVal;
3609 This->dstBlend = newVal;
3611 case D3DBLEND_BLENDFACTOR : newVal = GL_CONSTANT_COLOR; break;
3612 case D3DBLEND_INVBLENDFACTOR : newVal = GL_ONE_MINUS_CONSTANT_COLOR; break;
3614 FIXME("Unrecognized src/dest blend value %ld (%d)\n", Value, State);
3617 if (State == WINED3DRS_SRCBLEND) This->srcBlend = newVal;
3618 if (State == WINED3DRS_DESTBLEND) This->dstBlend = newVal;
3619 TRACE("glBlendFunc src=%x, dst=%x\n", This->srcBlend, This->dstBlend);
3620 glBlendFunc(This->srcBlend, This->dstBlend);
3622 checkGLcall("glBlendFunc");
3626 case WINED3DRS_ALPHATESTENABLE :
3627 case WINED3DRS_ALPHAFUNC :
3628 case WINED3DRS_ALPHAREF :
3629 case WINED3DRS_COLORKEYENABLE :
3633 BOOL enable_ckey = FALSE;
3635 IWineD3DSurfaceImpl *surf;
3637 /* Find out if the texture on the first stage has a ckey set */
3638 if(This->stateBlock->textures[0]) {
3639 surf = (IWineD3DSurfaceImpl *) ((IWineD3DTextureImpl *)This->stateBlock->textures[0])->surfaces[0];
3640 if(surf->CKeyFlags & DDSD_CKSRCBLT) enable_ckey = TRUE;
3643 if (This->stateBlock->renderState[WINED3DRS_ALPHATESTENABLE] ||
3644 (This->stateBlock->renderState[WINED3DRS_COLORKEYENABLE] && enable_ckey)) {
3645 glEnable(GL_ALPHA_TEST);
3646 checkGLcall("glEnable GL_ALPHA_TEST");
3648 glDisable(GL_ALPHA_TEST);
3649 checkGLcall("glDisable GL_ALPHA_TEST");
3650 /* Alpha test is disabled, don't bother setting the params - it will happen on the next
3656 if(This->stateBlock->renderState[WINED3DRS_COLORKEYENABLE] && enable_ckey) {
3657 glParm = GL_NOTEQUAL;
3660 ref = ((float) This->stateBlock->renderState[WINED3DRS_ALPHAREF]) / 255.0f;
3661 glParm = CompareFunc(This->stateBlock->renderState[WINED3DRS_ALPHAFUNC]);
3664 This->alphafunc = glParm;
3665 glAlphaFunc(glParm, ref);
3666 checkGLcall("glAlphaFunc");
3671 case WINED3DRS_CLIPPLANEENABLE :
3672 case WINED3DRS_CLIPPING :
3674 /* Ensure we only do the changed clip planes */
3675 DWORD enable = 0xFFFFFFFF;
3676 DWORD disable = 0x00000000;
3678 /* If enabling / disabling all */
3679 if (State == WINED3DRS_CLIPPING) {
3681 enable = This->stateBlock->renderState[WINED3DRS_CLIPPLANEENABLE];
3684 disable = This->stateBlock->renderState[WINED3DRS_CLIPPLANEENABLE];
3688 enable = Value & ~OldValue;
3689 disable = ~Value & OldValue;
3692 if (enable & D3DCLIPPLANE0) { glEnable(GL_CLIP_PLANE0); checkGLcall("glEnable(clip plane 0)"); }
3693 if (enable & D3DCLIPPLANE1) { glEnable(GL_CLIP_PLANE1); checkGLcall("glEnable(clip plane 1)"); }
3694 if (enable & D3DCLIPPLANE2) { glEnable(GL_CLIP_PLANE2); checkGLcall("glEnable(clip plane 2)"); }
3695 if (enable & D3DCLIPPLANE3) { glEnable(GL_CLIP_PLANE3); checkGLcall("glEnable(clip plane 3)"); }
3696 if (enable & D3DCLIPPLANE4) { glEnable(GL_CLIP_PLANE4); checkGLcall("glEnable(clip plane 4)"); }
3697 if (enable & D3DCLIPPLANE5) { glEnable(GL_CLIP_PLANE5); checkGLcall("glEnable(clip plane 5)"); }
3699 if (disable & D3DCLIPPLANE0) { glDisable(GL_CLIP_PLANE0); checkGLcall("glDisable(clip plane 0)"); }
3700 if (disable & D3DCLIPPLANE1) { glDisable(GL_CLIP_PLANE1); checkGLcall("glDisable(clip plane 1)"); }
3701 if (disable & D3DCLIPPLANE2) { glDisable(GL_CLIP_PLANE2); checkGLcall("glDisable(clip plane 2)"); }
3702 if (disable & D3DCLIPPLANE3) { glDisable(GL_CLIP_PLANE3); checkGLcall("glDisable(clip plane 3)"); }
3703 if (disable & D3DCLIPPLANE4) { glDisable(GL_CLIP_PLANE4); checkGLcall("glDisable(clip plane 4)"); }
3704 if (disable & D3DCLIPPLANE5) { glDisable(GL_CLIP_PLANE5); checkGLcall("glDisable(clip plane 5)"); }
3706 /** update clipping status */
3708 This->stateBlock->clip_status.ClipUnion = 0;
3709 This->stateBlock->clip_status.ClipIntersection = 0xFFFFFFFF;
3711 This->stateBlock->clip_status.ClipUnion = 0;
3712 This->stateBlock->clip_status.ClipIntersection = 0;
3717 case WINED3DRS_BLENDOP :
3719 int glParm = GL_FUNC_ADD;
3721 switch ((D3DBLENDOP) Value) {
3722 case D3DBLENDOP_ADD : glParm = GL_FUNC_ADD; break;
3723 case D3DBLENDOP_SUBTRACT : glParm = GL_FUNC_SUBTRACT; break;
3724 case D3DBLENDOP_REVSUBTRACT : glParm = GL_FUNC_REVERSE_SUBTRACT; break;
3725 case D3DBLENDOP_MIN : glParm = GL_MIN; break;
3726 case D3DBLENDOP_MAX : glParm = GL_MAX; break;
3728 FIXME("Unrecognized/Unhandled D3DBLENDOP value %ld\n", Value);
3731 if(GL_SUPPORT(ARB_IMAGING)) {
3732 TRACE("glBlendEquation(%x)\n", glParm);
3733 GL_EXTCALL(glBlendEquation(glParm));
3734 checkGLcall("glBlendEquation");
3736 WARN("Unsupported in local OpenGL implementation: glBlendEquation\n");
3741 case WINED3DRS_TEXTUREFACTOR :
3745 /* Note the texture color applies to all textures whereas
3746 GL_TEXTURE_ENV_COLOR applies to active only */
3748 D3DCOLORTOGLFLOAT4(Value, col);
3750 if (!GL_SUPPORT(NV_REGISTER_COMBINERS)) {
3751 /* And now the default texture color as well */
3752 for (i = 0; i < GL_LIMITS(texture_stages); i++) {
3753 /* Note the D3DRS value applies to all textures, but GL has one
3754 per texture, so apply it now ready to be used! */
3755 if (GL_SUPPORT(ARB_MULTITEXTURE)) {
3756 GL_EXTCALL(glActiveTextureARB(GL_TEXTURE0_ARB + i));
3757 checkGLcall("glActiveTextureARB");
3759 FIXME("Program using multiple concurrent textures which this opengl implementation doesn't support\n");
3762 glTexEnvfv(GL_TEXTURE_ENV, GL_TEXTURE_ENV_COLOR, &col[0]);
3763 checkGLcall("glTexEnvfv(GL_TEXTURE_ENV, GL_TEXTURE_ENV_COLOR, color);");
3769 case WINED3DRS_SPECULARENABLE :
3771 /* Originally this used glLightModeli(GL_LIGHT_MODEL_COLOR_CONTROL,GL_SEPARATE_SPECULAR_COLOR)
3772 and (GL_LIGHT_MODEL_COLOR_CONTROL,GL_SINGLE_COLOR) to swap between enabled/disabled
3773 specular color. This is wrong:
3774 Separate specular color means the specular colour is maintained separately, whereas
3775 single color means it is merged in. However in both cases they are being used to
3777 To disable specular color, set it explicitly to black and turn off GL_COLOR_SUM_EXT
3778 NOTE: If not supported don't give FIXMEs the impact is really minimal and very few people are
3782 * If register combiners are enabled, enabling / disabling GL_COLOR_SUM has no effect.
3783 * Instead, we need to setup the FinalCombiner properly.
3785 * The default setup for the FinalCombiner is:
3787 * <variable> <input> <mapping> <usage>
3788 * GL_VARIABLE_A_NV GL_FOG, GL_UNSIGNED_IDENTITY_NV GL_ALPHA
3789 * GL_VARIABLE_B_NV GL_SPARE0_PLUS_SECONDARY_COLOR_NV GL_UNSIGNED_IDENTITY_NV GL_RGB
3790 * GL_VARIABLE_C_NV GL_FOG GL_UNSIGNED_IDENTITY_NV GL_RGB
3791 * GL_VARIABLE_D_NV GL_ZERO GL_UNSIGNED_IDENTITY_NV GL_RGB
3792 * GL_VARIABLE_E_NV GL_ZERO GL_UNSIGNED_IDENTITY_NV GL_RGB
3793 * GL_VARIABLE_F_NV GL_ZERO GL_UNSIGNED_IDENTITY_NV GL_RGB
3794 * GL_VARIABLE_G_NV GL_SPARE0_NV GL_UNSIGNED_IDENTITY_NV GL_ALPHA
3796 * That's pretty much fine as it is, except for variable B, which needs to take
3797 * either GL_SPARE0_PLUS_SECONDARY_COLOR_NV or GL_SPARE0_NV, depending on
3798 * whether WINED3DRS_SPECULARENABLE is enabled or not.
3802 glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, (float*) &This->updateStateBlock->material.Specular);
3803 checkGLcall("glMaterialfv");
3804 if (GL_SUPPORT(EXT_SECONDARY_COLOR)) {
3805 glEnable(GL_COLOR_SUM_EXT);
3807 TRACE("Specular colors cannot be enabled in this version of opengl\n");
3809 checkGLcall("glEnable(GL_COLOR_SUM)");
3811 if (GL_SUPPORT(NV_REGISTER_COMBINERS)) {
3812 GL_EXTCALL(glFinalCombinerInputNV(GL_VARIABLE_B_NV, GL_SPARE0_PLUS_SECONDARY_COLOR_NV, GL_UNSIGNED_IDENTITY_NV, GL_RGB));
3813 checkGLcall("glFinalCombinerInputNV()");
3816 float black[4] = {0.0f, 0.0f, 0.0f, 0.0f};
3818 /* for the case of enabled lighting: */
3819 glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, &black[0]);
3820 checkGLcall("glMaterialfv");
3822 /* for the case of disabled lighting: */
3823 if (GL_SUPPORT(EXT_SECONDARY_COLOR)) {
3824 glDisable(GL_COLOR_SUM_EXT);
3826 TRACE("Specular colors cannot be disabled in this version of opengl\n");
3828 checkGLcall("glDisable(GL_COLOR_SUM)");
3830 if (GL_SUPPORT(NV_REGISTER_COMBINERS)) {
3831 GL_EXTCALL(glFinalCombinerInputNV(GL_VARIABLE_B_NV, GL_SPARE0_NV, GL_UNSIGNED_IDENTITY_NV, GL_RGB));
3832 checkGLcall("glFinalCombinerInputNV()");
3838 case WINED3DRS_STENCILENABLE :
3839 case WINED3DRS_TWOSIDEDSTENCILMODE :
3840 case WINED3DRS_STENCILFUNC :
3841 case WINED3DRS_CCW_STENCILFUNC :
3842 case WINED3DRS_STENCILREF :
3843 case WINED3DRS_STENCILMASK :
3844 case WINED3DRS_STENCILFAIL :
3845 case WINED3DRS_STENCILZFAIL :
3846 case WINED3DRS_STENCILPASS :
3847 case WINED3DRS_CCW_STENCILFAIL :
3848 case WINED3DRS_CCW_STENCILZFAIL :
3849 case WINED3DRS_CCW_STENCILPASS :
3850 renderstate_stencil(This, State, Value);
3852 case WINED3DRS_STENCILWRITEMASK :
3854 glStencilMask(Value);
3855 TRACE("glStencilMask(%lu)\n", Value);
3856 checkGLcall("glStencilMask");
3860 case WINED3DRS_FOGENABLE :
3864 checkGLcall("glEnable GL_FOG");
3867 checkGLcall("glDisable GL_FOG");
3872 case WINED3DRS_RANGEFOGENABLE :
3875 TRACE("Enabled RANGEFOG\n");
3877 TRACE("Disabled RANGEFOG\n");
3882 case WINED3DRS_FOGCOLOR :
3885 D3DCOLORTOGLFLOAT4(Value, col);
3886 /* Set the default alpha blend color */
3887 glFogfv(GL_FOG_COLOR, &col[0]);
3888 checkGLcall("glFog GL_FOG_COLOR");
3892 case WINED3DRS_FOGTABLEMODE :
3893 case WINED3DRS_FOGVERTEXMODE :
3895 /* 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." */
3896 if(This->stateBlock->renderState[WINED3DRS_FOGTABLEMODE] == D3DFOG_NONE) {
3897 glHint(GL_FOG_HINT, GL_FASTEST);
3898 checkGLcall("glHint(GL_FOG_HINT, GL_FASTEST)");
3899 switch (This->stateBlock->renderState[WINED3DRS_FOGVERTEXMODE]) {
3900 /* Processed vertices have their fog factor stored in the specular value. Fall too the none case.
3901 * If we are drawing untransformed vertices atm, d3ddevice_set_ortho will update the fog
3904 if(!This->last_was_rhw) {
3905 glFogi(GL_FOG_MODE, GL_EXP);
3906 checkGLcall("glFogi(GL_FOG_MODE, GL_EXP");
3907 if(GL_SUPPORT(EXT_FOG_COORD)) {
3908 glFogi(GL_FOG_COORDINATE_SOURCE_EXT, GL_FRAGMENT_DEPTH_EXT);
3909 checkGLcall("glFogi(GL_FOG_COORDINATE_SOURCE_EXT, GL_FRAGMENT_DEPTH_EXT");
3910 IWineD3DDevice_SetRenderState(iface, WINED3DRS_FOGSTART, This->stateBlock->renderState[WINED3DRS_FOGSTART]);
3911 IWineD3DDevice_SetRenderState(iface, WINED3DRS_FOGEND, This->stateBlock->renderState[WINED3DRS_FOGEND]);
3917 if(!This->last_was_rhw) {
3918 glFogi(GL_FOG_MODE, GL_EXP2);
3919 checkGLcall("glFogi(GL_FOG_MODE, GL_EXP2");
3920 if(GL_SUPPORT(EXT_FOG_COORD)) {
3921 glFogi(GL_FOG_COORDINATE_SOURCE_EXT, GL_FRAGMENT_DEPTH_EXT);
3922 checkGLcall("glFogi(GL_FOG_COORDINATE_SOURCE_EXT, GL_FRAGMENT_DEPTH_EXT");
3923 IWineD3DDevice_SetRenderState(iface, WINED3DRS_FOGSTART, This->stateBlock->renderState[WINED3DRS_FOGSTART]);
3924 IWineD3DDevice_SetRenderState(iface, WINED3DRS_FOGEND, This->stateBlock->renderState[WINED3DRS_FOGEND]);
3929 case D3DFOG_LINEAR: {
3930 if(!This->last_was_rhw) {
3931 glFogi(GL_FOG_MODE, GL_LINEAR);
3932 checkGLcall("glFogi(GL_FOG_MODE, GL_LINEAR");
3933 if(GL_SUPPORT(EXT_FOG_COORD)) {
3934 glFogi(GL_FOG_COORDINATE_SOURCE_EXT, GL_FRAGMENT_DEPTH_EXT);
3935 checkGLcall("glFogi(GL_FOG_COORDINATE_SOURCE_EXT, GL_FRAGMENT_DEPTH_EXT");
3936 IWineD3DDevice_SetRenderState(iface, WINED3DRS_FOGSTART, This->stateBlock->renderState[WINED3DRS_FOGSTART]);
3937 IWineD3DDevice_SetRenderState(iface, WINED3DRS_FOGEND, This->stateBlock->renderState[WINED3DRS_FOGEND]);
3943 /* Both are none? According to msdn the alpha channel of the specular
3944 * color contains a fog factor. Set it in drawStridedSlow.
3945 * Same happens with Vertexfog on transformed vertices
3947 if(GL_SUPPORT(EXT_FOG_COORD)) {
3948 glFogi(GL_FOG_COORDINATE_SOURCE_EXT, GL_FOG_COORDINATE_EXT);
3949 checkGLcall("glFogi(GL_FOG_COORDINATE_SOURCE_EXT, GL_FOG_COORDINATE_EXT)\n");
3950 glFogi(GL_FOG_MODE, GL_LINEAR);
3951 checkGLcall("glFogi(GL_FOG_MODE, GL_LINEAR)");
3952 glFogf(GL_FOG_START, (float) 0xff);
3953 checkGLcall("glFogfv GL_FOG_START");
3954 glFogf(GL_FOG_END, 0.0);
3955 checkGLcall("glFogfv GL_FOG_END");
3957 /* Disable GL fog, handle this in software in drawStridedSlow */
3959 checkGLcall("glDisable(GL_FOG)");
3963 default: FIXME("Unexpected WINED3DRS_FOGVERTEXMODE %ld\n", This->stateBlock->renderState[WINED3DRS_FOGVERTEXMODE]);
3966 glHint(GL_FOG_HINT, GL_NICEST);
3967 checkGLcall("glHint(GL_FOG_HINT, GL_NICEST)");
3968 switch (This->stateBlock->renderState[WINED3DRS_FOGTABLEMODE]) {
3969 case D3DFOG_EXP: glFogi(GL_FOG_MODE, GL_EXP);
3970 checkGLcall("glFogi(GL_FOG_MODE, GL_EXP");
3971 if(GL_SUPPORT(EXT_FOG_COORD)) {
3972 glFogi(GL_FOG_COORDINATE_SOURCE_EXT, GL_FRAGMENT_DEPTH_EXT);
3973 checkGLcall("glFogi(GL_FOG_COORDINATE_SOURCE_EXT, GL_FRAGMENT_DEPTH_EXT");
3974 IWineD3DDevice_SetRenderState(iface, WINED3DRS_FOGSTART, This->stateBlock->renderState[WINED3DRS_FOGSTART]);
3975 IWineD3DDevice_SetRenderState(iface, WINED3DRS_FOGEND, This->stateBlock->renderState[WINED3DRS_FOGEND]);
3978 case D3DFOG_EXP2: glFogi(GL_FOG_MODE, GL_EXP2);
3979 checkGLcall("glFogi(GL_FOG_MODE, GL_EXP2");
3980 if(GL_SUPPORT(EXT_FOG_COORD)) {
3981 glFogi(GL_FOG_COORDINATE_SOURCE_EXT, GL_FRAGMENT_DEPTH_EXT);
3982 checkGLcall("glFogi(GL_FOG_COORDINATE_SOURCE_EXT, GL_FRAGMENT_DEPTH_EXT");
3983 IWineD3DDevice_SetRenderState(iface, WINED3DRS_FOGSTART, This->stateBlock->renderState[WINED3DRS_FOGSTART]);
3984 IWineD3DDevice_SetRenderState(iface, WINED3DRS_FOGEND, This->stateBlock->renderState[WINED3DRS_FOGEND]);
3987 case D3DFOG_LINEAR: glFogi(GL_FOG_MODE, GL_LINEAR);
3988 checkGLcall("glFogi(GL_FOG_MODE, GL_LINEAR");
3989 if(GL_SUPPORT(EXT_FOG_COORD)) {
3990 glFogi(GL_FOG_COORDINATE_SOURCE_EXT, GL_FRAGMENT_DEPTH_EXT);
3991 checkGLcall("glFogi(GL_FOG_COORDINATE_SOURCE_EXT, GL_FRAGMENT_DEPTH_EXT");
3992 IWineD3DDevice_SetRenderState(iface, WINED3DRS_FOGSTART, This->stateBlock->renderState[WINED3DRS_FOGSTART]);
3993 IWineD3DDevice_SetRenderState(iface, WINED3DRS_FOGEND, This->stateBlock->renderState[WINED3DRS_FOGEND]);
3996 case D3DFOG_NONE: /* Won't happen */
3997 default: FIXME("Unexpected WINED3DRS_FOGTABLEMODE %ld\n", This->stateBlock->renderState[WINED3DRS_FOGTABLEMODE]);
4000 if (GL_SUPPORT(NV_FOG_DISTANCE)) {
4001 glFogi(GL_FOG_DISTANCE_MODE_NV, GL_EYE_PLANE_ABSOLUTE_NV);
4006 case WINED3DRS_FOGSTART :
4009 glFogfv(GL_FOG_START, &tmpvalue.f);
4010 checkGLcall("glFogf(GL_FOG_START, (float) Value)");
4011 TRACE("Fog Start == %f\n", tmpvalue.f);
4015 case WINED3DRS_FOGEND :
4018 glFogfv(GL_FOG_END, &tmpvalue.f);
4019 checkGLcall("glFogf(GL_FOG_END, (float) Value)");
4020 TRACE("Fog End == %f\n", tmpvalue.f);
4024 case WINED3DRS_FOGDENSITY :
4027 glFogfv(GL_FOG_DENSITY, &tmpvalue.f);
4028 checkGLcall("glFogf(GL_FOG_DENSITY, (float) Value)");
4032 case WINED3DRS_VERTEXBLEND :
4034 This->updateStateBlock->vertex_blend = (D3DVERTEXBLENDFLAGS) Value;
4035 TRACE("Vertex Blending state to %ld\n", Value);
4039 case WINED3DRS_TWEENFACTOR :
4042 This->updateStateBlock->tween_factor = tmpvalue.f;
4043 TRACE("Vertex Blending Tween Factor to %f\n", This->updateStateBlock->tween_factor);
4047 case WINED3DRS_INDEXEDVERTEXBLENDENABLE :
4049 TRACE("Indexed Vertex Blend Enable to %ul\n", (BOOL) Value);
4053 case WINED3DRS_COLORVERTEX :
4054 case WINED3DRS_DIFFUSEMATERIALSOURCE :
4055 case WINED3DRS_SPECULARMATERIALSOURCE :
4056 case WINED3DRS_AMBIENTMATERIALSOURCE :
4057 case WINED3DRS_EMISSIVEMATERIALSOURCE :
4059 GLenum Parm = GL_AMBIENT_AND_DIFFUSE;
4061 if (This->stateBlock->renderState[WINED3DRS_COLORVERTEX]) {
4062 TRACE("diff %ld, amb %ld, emis %ld, spec %ld\n",
4063 This->stateBlock->renderState[WINED3DRS_DIFFUSEMATERIALSOURCE],
4064 This->stateBlock->renderState[WINED3DRS_AMBIENTMATERIALSOURCE],
4065 This->stateBlock->renderState[WINED3DRS_EMISSIVEMATERIALSOURCE],
4066 This->stateBlock->renderState[WINED3DRS_SPECULARMATERIALSOURCE]);
4068 if (This->stateBlock->renderState[WINED3DRS_DIFFUSEMATERIALSOURCE] == D3DMCS_COLOR1) {
4069 if (This->stateBlock->renderState[WINED3DRS_AMBIENTMATERIALSOURCE] == D3DMCS_COLOR1) {
4070 Parm = GL_AMBIENT_AND_DIFFUSE;
4074 } else if (This->stateBlock->renderState[WINED3DRS_AMBIENTMATERIALSOURCE] == D3DMCS_COLOR1) {
4076 } else if (This->stateBlock->renderState[WINED3DRS_EMISSIVEMATERIALSOURCE] == D3DMCS_COLOR1) {
4078 } else if (This->stateBlock->renderState[WINED3DRS_SPECULARMATERIALSOURCE] == D3DMCS_COLOR1) {
4085 if (This->tracking_color != DISABLED_TRACKING) This->tracking_color = NEEDS_DISABLE;
4087 This->tracking_color = NEEDS_TRACKING;
4088 This->tracking_parm = Parm;
4092 if (This->tracking_color != DISABLED_TRACKING) This->tracking_color = NEEDS_DISABLE;
4097 case WINED3DRS_LINEPATTERN :
4103 tmppattern.d = Value;
4105 TRACE("Line pattern: repeat %d bits %x\n", tmppattern.lp.wRepeatFactor, tmppattern.lp.wLinePattern);
4107 if (tmppattern.lp.wRepeatFactor) {
4108 glLineStipple(tmppattern.lp.wRepeatFactor, tmppattern.lp.wLinePattern);
4109 checkGLcall("glLineStipple(repeat, linepattern)");
4110 glEnable(GL_LINE_STIPPLE);
4111 checkGLcall("glEnable(GL_LINE_STIPPLE);");
4113 glDisable(GL_LINE_STIPPLE);
4114 checkGLcall("glDisable(GL_LINE_STIPPLE);");
4119 case WINED3DRS_ZBIAS : /* D3D8 only */
4123 TRACE("ZBias value %f\n", tmpvalue.f);
4124 glPolygonOffset(0, -tmpvalue.f);
4125 checkGLcall("glPolygonOffset(0, -Value)");
4126 glEnable(GL_POLYGON_OFFSET_FILL);
4127 checkGLcall("glEnable(GL_POLYGON_OFFSET_FILL);");
4128 glEnable(GL_POLYGON_OFFSET_LINE);
4129 checkGLcall("glEnable(GL_POLYGON_OFFSET_LINE);");
4130 glEnable(GL_POLYGON_OFFSET_POINT);
4131 checkGLcall("glEnable(GL_POLYGON_OFFSET_POINT);");
4133 glDisable(GL_POLYGON_OFFSET_FILL);
4134 checkGLcall("glDisable(GL_POLYGON_OFFSET_FILL);");
4135 glDisable(GL_POLYGON_OFFSET_LINE);
4136 checkGLcall("glDisable(GL_POLYGON_OFFSET_LINE);");
4137 glDisable(GL_POLYGON_OFFSET_POINT);
4138 checkGLcall("glDisable(GL_POLYGON_OFFSET_POINT);");
4143 case WINED3DRS_NORMALIZENORMALS :
4145 glEnable(GL_NORMALIZE);
4146 checkGLcall("glEnable(GL_NORMALIZE);");
4148 glDisable(GL_NORMALIZE);
4149 checkGLcall("glDisable(GL_NORMALIZE);");
4153 case WINED3DRS_POINTSIZE :
4154 /* FIXME: check that pointSize isn't outside glGetFloatv( GL_POINT_SIZE_MAX_ARB, &maxSize ); or -ve */
4156 TRACE("Set point size to %f\n", tmpvalue.f);
4157 glPointSize(tmpvalue.f);
4158 checkGLcall("glPointSize(...);");
4161 case WINED3DRS_POINTSIZE_MIN :
4162 if (GL_SUPPORT(EXT_POINT_PARAMETERS)) {
4164 GL_EXTCALL(glPointParameterfEXT)(GL_POINT_SIZE_MIN_EXT, tmpvalue.f);
4165 checkGLcall("glPointParameterfEXT(...);");
4167 FIXME("WINED3DRS_POINTSIZE_MIN not supported on this opengl\n");
4171 case WINED3DRS_POINTSIZE_MAX :
4172 if (GL_SUPPORT(EXT_POINT_PARAMETERS)) {
4174 GL_EXTCALL(glPointParameterfEXT)(GL_POINT_SIZE_MAX_EXT, tmpvalue.f);
4175 checkGLcall("glPointParameterfEXT(...);");
4177 FIXME("WINED3DRS_POINTSIZE_MAX not supported on this opengl\n");
4181 case WINED3DRS_POINTSCALE_A :
4182 case WINED3DRS_POINTSCALE_B :
4183 case WINED3DRS_POINTSCALE_C :
4184 case WINED3DRS_POINTSCALEENABLE :
4187 * POINTSCALEENABLE controls how point size value is treated. If set to
4188 * true, the point size is scaled with respect to height of viewport.
4189 * When set to false point size is in pixels.
4191 * http://msdn.microsoft.com/library/en-us/directx9_c/point_sprites.asp
4194 /* Default values */
4195 GLfloat att[3] = {1.0f, 0.0f, 0.0f};
4198 * Minimum valid point size for OpenGL is 1.0f. For Direct3D it is 0.0f.
4199 * This means that OpenGL will clamp really small point sizes to 1.0f.
4200 * To correct for this we need to multiply by the scale factor when sizes
4201 * are less than 1.0f. scale_factor = 1.0f / point_size.
4203 GLfloat pointSize = *((float*)&This->stateBlock->renderState[WINED3DRS_POINTSIZE]);
4204 if(pointSize > 0.0f) {
4205 GLfloat scaleFactor;
4207 if(pointSize < 1.0f) {
4208 scaleFactor = pointSize * pointSize;
4213 if(This->stateBlock->renderState[WINED3DRS_POINTSCALEENABLE]) {
4214 att[0] = *((float*)&This->stateBlock->renderState[WINED3DRS_POINTSCALE_A]) /
4215 (This->stateBlock->viewport.Height * This->stateBlock->viewport.Height * scaleFactor);
4216 att[1] = *((float*)&This->stateBlock->renderState[WINED3DRS_POINTSCALE_B]) /
4217 (This->stateBlock->viewport.Height * This->stateBlock->viewport.Height * scaleFactor);
4218 att[2] = *((float*)&This->stateBlock->renderState[WINED3DRS_POINTSCALE_C]) /
4219 (This->stateBlock->viewport.Height * This->stateBlock->viewport.Height * scaleFactor);
4223 if(GL_SUPPORT(ARB_POINT_PARAMETERS)) {
4224 GL_EXTCALL(glPointParameterfvARB)(GL_POINT_DISTANCE_ATTENUATION_ARB, att);
4225 checkGLcall("glPointParameterfvARB(GL_DISTANCE_ATTENUATION_ARB, ...");
4227 else if(GL_SUPPORT(EXT_POINT_PARAMETERS)) {
4228 GL_EXTCALL(glPointParameterfvEXT)(GL_DISTANCE_ATTENUATION_EXT, att);
4229 checkGLcall("glPointParameterfvEXT(GL_DISTANCE_ATTENUATION_EXT, ...");
4231 TRACE("POINT_PARAMETERS not supported in this version of opengl\n");
4235 case WINED3DRS_COLORWRITEENABLE :
4237 TRACE("Color mask: r(%d) g(%d) b(%d) a(%d)\n",
4238 Value & D3DCOLORWRITEENABLE_RED ? 1 : 0,
4239 Value & D3DCOLORWRITEENABLE_GREEN ? 1 : 0,
4240 Value & D3DCOLORWRITEENABLE_BLUE ? 1 : 0,
4241 Value & D3DCOLORWRITEENABLE_ALPHA ? 1 : 0);
4242 glColorMask(Value & D3DCOLORWRITEENABLE_RED ? GL_TRUE : GL_FALSE,
4243 Value & D3DCOLORWRITEENABLE_GREEN ? GL_TRUE : GL_FALSE,
4244 Value & D3DCOLORWRITEENABLE_BLUE ? GL_TRUE : GL_FALSE,
4245 Value & D3DCOLORWRITEENABLE_ALPHA ? GL_TRUE : GL_FALSE);
4246 checkGLcall("glColorMask(...)");
4250 case WINED3DRS_LOCALVIEWER :
4252 GLint state = (Value) ? 1 : 0;
4253 TRACE("Local Viewer Enable to %ul\n", (BOOL) Value);
4254 glLightModeli(GL_LIGHT_MODEL_LOCAL_VIEWER, state);
4258 case WINED3DRS_LASTPIXEL :
4261 TRACE("Last Pixel Drawing Enabled\n");
4263 FIXME("Last Pixel Drawing Disabled, not handled yet\n");
4268 case WINED3DRS_SOFTWAREVERTEXPROCESSING :
4271 TRACE("Software Processing Enabled\n");
4273 TRACE("Software Processing Disabled\n");
4278 /** not supported */
4279 case WINED3DRS_ZVISIBLE :
4282 return WINED3DERR_INVALIDCALL;
4284 case WINED3DRS_POINTSPRITEENABLE :
4286 /* TODO: NV_POINT_SPRITE */
4287 if (!GL_SUPPORT(ARB_POINT_SPRITE)) {
4288 TRACE("Point sprites not supported\n");
4293 * Point sprites are always enabled. Value controls texture coordinate
4294 * replacement mode. Must be set true for point sprites to use
4297 glEnable(GL_POINT_SPRITE_ARB);
4298 checkGLcall("glEnable(GL_POINT_SPRITE_ARB)");
4301 glTexEnvf(GL_POINT_SPRITE_ARB, GL_COORD_REPLACE_ARB, TRUE);
4302 checkGLcall("glTexEnvf(GL_POINT_SPRITE, GL_COORD_REPLACE, TRUE)");
4304 glTexEnvf(GL_POINT_SPRITE_ARB, GL_COORD_REPLACE_ARB, FALSE);
4305 checkGLcall("glTexEnvf(GL_POINT_SPRITE, GL_COORD_REPLACE, FALSE)");
4309 case WINED3DRS_EDGEANTIALIAS :
4312 glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
4314 checkGLcall("glEnable(GL_BLEND)");
4315 glEnable(GL_LINE_SMOOTH);
4316 checkGLcall("glEnable(GL_LINE_SMOOTH)");
4318 if(!This->stateBlock->renderState[WINED3DRS_ALPHABLENDENABLE]) {
4319 glDisable(GL_BLEND);
4320 checkGLcall("glDisable(GL_BLEND)");
4322 glDisable(GL_LINE_SMOOTH);
4323 checkGLcall("glDisable(GL_LINE_SMOOTH)");
4327 case WINED3DRS_WRAP0 :
4328 case WINED3DRS_WRAP1 :
4329 case WINED3DRS_WRAP2 :
4330 case WINED3DRS_WRAP3 :
4331 case WINED3DRS_WRAP4 :
4332 case WINED3DRS_WRAP5 :
4333 case WINED3DRS_WRAP6 :
4334 case WINED3DRS_WRAP7 :
4335 case WINED3DRS_WRAP8 :
4336 case WINED3DRS_WRAP9 :
4337 case WINED3DRS_WRAP10 :
4338 case WINED3DRS_WRAP11 :
4339 case WINED3DRS_WRAP12 :
4340 case WINED3DRS_WRAP13 :
4341 case WINED3DRS_WRAP14 :
4342 case WINED3DRS_WRAP15 :
4344 http://www.cosc.brocku.ca/Offerings/3P98/course/lectures/texture/
4345 http://msdn.microsoft.com/archive/default.asp?url=/archive/en-us/directx9_c/directx/graphics/programmingguide/FixedFunction/Textures/texturewrapping.asp
4346 http://www.gamedev.net/reference/programming/features/rendererdll3/page2.asp
4347 Descussion that ways to turn on WRAPing to solve an opengl conversion problem.
4348 http://www.flipcode.org/cgi-bin/fcmsg.cgi?thread_show=10248
4350 so far as I can tell, wrapping and texture-coordinate generate go hand in hand,
4354 ERR("(%p)->(%s,%ld) Texture wraping not yet supported\n",This, debug_d3drenderstate(State), Value);
4359 case WINED3DRS_MULTISAMPLEANTIALIAS :
4361 if( GL_SUPPORT(ARB_MULTISAMPLE) ) {
4363 glEnable(GL_MULTISAMPLE_ARB);
4364 checkGLcall("glEnable(GL_MULTISAMPLE_ARB)");
4366 glDisable(GL_MULTISAMPLE_ARB);
4367 checkGLcall("glDisable(GL_MULTISAMPLE_ARB)");
4371 ERR("Multisample antialiasing not supported by gl\n");
4377 case WINED3DRS_SCISSORTESTENABLE :
4380 glEnable(GL_SCISSOR_TEST);
4381 checkGLcall("glEnable(GL_SCISSOR_TEST)");
4383 glDisable(GL_SCISSOR_TEST);
4384 checkGLcall("glDisable(GL_SCISSOR_TEST)");
4388 case WINED3DRS_SLOPESCALEDEPTHBIAS :
4392 glEnable(GL_POLYGON_OFFSET_FILL);
4393 checkGLcall("glEnable(GL_POLYGON_OFFSET_FILL)");
4394 glPolygonOffset(tmpvalue.f, *((float*)&This->stateBlock->renderState[WINED3DRS_DEPTHBIAS]));
4395 checkGLcall("glPolygonOffset(...)");
4397 glDisable(GL_POLYGON_OFFSET_FILL);
4398 checkGLcall("glDisable(GL_POLYGON_OFFSET_FILL)");
4402 case WINED3DRS_ANTIALIASEDLINEENABLE :
4405 glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
4407 checkGLcall("glEnable(GL_BLEND)");
4408 glEnable(GL_LINE_SMOOTH);
4409 checkGLcall("glEnable(GL_LINE_SMOOTH)");
4411 glDisable(GL_BLEND);
4412 checkGLcall("glDisable(GL_BLEND)");
4413 glDisable(GL_LINE_SMOOTH);
4414 checkGLcall("glDisable(GL_LINE_SMOOTH)");
4418 case WINED3DRS_DEPTHBIAS :
4422 glEnable(GL_POLYGON_OFFSET_FILL);
4423 checkGLcall("glEnable(GL_POLYGON_OFFSET_FILL)");
4424 glPolygonOffset(*((float*)&This->stateBlock->renderState[WINED3DRS_SLOPESCALEDEPTHBIAS]), tmpvalue.f);
4425 checkGLcall("glPolygonOffset(...)");
4427 glDisable(GL_POLYGON_OFFSET_FILL);
4428 checkGLcall("glDisable(GL_POLYGON_OFFSET_FILL)");
4433 case WINED3DRS_TEXTUREPERSPECTIVE :
4436 glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST);
4438 glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_FASTEST);
4442 case WINED3DRS_STIPPLEDALPHA :
4445 ERR(" Stippled Alpha not supported yet.\n");
4448 case WINED3DRS_ANTIALIAS :
4451 ERR(" Antialias not supported yet.\n");
4455 case WINED3DRS_MULTISAMPLEMASK :
4457 if(0xFFFFFFFF != Value)
4458 ERR("(%p)->(%s,%ld) not yet implemented\n", This, debug_d3drenderstate(State), Value);
4462 case WINED3DRS_PATCHEDGESTYLE :
4464 if(D3DPATCHEDGE_DISCRETE != Value)
4465 ERR("(%p)->(%s,%ld) not yet implemented\n", This, debug_d3drenderstate(State), Value);
4469 case WINED3DRS_PATCHSEGMENTS :
4471 /* available in d3d8 but in d3d9 it was replaced by IDirect3DDevice9::SetNPatchMode */
4473 if(tmpvalue.d != Value)
4474 ERR("(%p)->(%s,%ld) not yet implemented\n", This, debug_d3drenderstate(State), Value);
4478 case WINED3DRS_DEBUGMONITORTOKEN :
4480 /* Only useful for "debug builds". */
4481 if(0xbaadcafe != Value) {
4482 /* MSDN says the default is D3DDMT_ENABLE but our tests confirm 0xbaadcafe is the default. */
4483 /* MSDN says anything other than D3DDMT_ENABLE or DISABLE does not change the state,
4484 * but our tests disagree.
4485 * We do not claim to implement a debugging lib, so do not write an ERR
4487 WARN("(%p)->(%s,%ld) not yet implemented\n", This, debug_d3drenderstate(State), Value);
4492 case WINED3DRS_POSITIONDEGREE :
4494 if(D3DDEGREE_CUBIC != Value)
4495 ERR("(%p)->(%s,%ld) not yet implemented\n", This, debug_d3drenderstate(State), Value);
4499 case WINED3DRS_NORMALDEGREE :
4501 if(D3DDEGREE_LINEAR != Value)
4502 ERR("(%p)->(%s,%ld) not yet implemented\n", This, debug_d3drenderstate(State), Value);
4506 case WINED3DRS_MINTESSELLATIONLEVEL :
4507 case WINED3DRS_MAXTESSELLATIONLEVEL :
4508 case WINED3DRS_ADAPTIVETESS_X :
4509 case WINED3DRS_ADAPTIVETESS_Y :
4510 case WINED3DRS_ADAPTIVETESS_Z :
4511 case WINED3DRS_ADAPTIVETESS_W :
4513 if(This->stateBlock->renderState[WINED3DRS_ENABLEADAPTIVETESSELLATION])
4514 FIXME("(%p)->(%s,%ld) not yet implemented\n", This, debug_d3drenderstate(State), Value);
4516 TRACE("(%p)->(%s,%ld): recording state but WINED3DRS_ENABLEADAPTIVETESSELLATION is not enabled\n", This, debug_d3drenderstate(State), Value);
4520 case WINED3DRS_ENABLEADAPTIVETESSELLATION:
4523 ERR("(%p)->(%s,%ld) not yet implemented\n", This, debug_d3drenderstate(State), Value);
4527 case WINED3DRS_COLORWRITEENABLE1 :
4528 case WINED3DRS_COLORWRITEENABLE2 :
4529 case WINED3DRS_COLORWRITEENABLE3 :
4531 /* depends on WINED3DRS_COLORWRITEENABLE. */
4532 if(0x0000000F != Value)
4533 ERR("(%p)->(%s,%ld) not yet implemented. Missing of cap D3DPMISCCAPS_INDEPENDENTWRITEMASKS wasn't honored?\n", This, debug_d3drenderstate(State), Value);
4537 case WINED3DRS_BLENDFACTOR :
4540 if (GL_SUPPORT(ARB_IMAGING)) {
4542 TRACE("Setting BlendFactor to %ld", Value);
4544 D3DCOLORTOGLFLOAT4(Value, col);
4545 if (0xFFFFFFFF != Value) {
4547 checkGLcall("glEnable(GL_BLEND)");
4550 glDisable(GL_BLEND);
4551 checkGLcall("glDisable(GL_BLEND)");
4553 glBlendColor (col[0],col[1],col[2],col[3]);
4555 WARN("Unsupported in local OpenGL implementation: glBlendColor\n");
4560 case WINED3DRS_SRGBWRITEENABLE :
4563 ERR("(%p)->(%s,%ld) not yet implemented\n", This, debug_d3drenderstate(State), Value);
4567 case WINED3DRS_SEPARATEALPHABLENDENABLE :
4570 ERR("(%p)->(%s,%ld) not yet implemented. Missing of cap D3DPMISCCAPS_SEPARATEALPHABLEND wasn't honored?\n", This, debug_d3drenderstate(State), Value);
4574 case WINED3DRS_SRCBLENDALPHA :
4575 case WINED3DRS_DESTBLENDALPHA :
4576 case WINED3DRS_BLENDOPALPHA :
4578 if(This->stateBlock->renderState[WINED3DRS_SEPARATEALPHABLENDENABLE])
4579 FIXME("(%p)->(%s,%ld) not yet implemented\n", This, debug_d3drenderstate(State), Value);
4581 TRACE("(%p)->(%s,%ld): recording state but WINED3DRS_SEPARATEALPHABLENDENABLE is not enabled\n", This, debug_d3drenderstate(State), Value);
4586 FIXME("(%p)->(%s,%ld) unknown state\n", This, debug_d3drenderstate(State), Value);
4594 static HRESULT WINAPI IWineD3DDeviceImpl_GetRenderState(IWineD3DDevice *iface, D3DRENDERSTATETYPE State, DWORD *pValue) {
4595 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4596 TRACE("(%p) for State %d = %ld\n", This, State, This->stateBlock->renderState[State]);
4597 *pValue = This->stateBlock->renderState[State];
4602 * Get / Set Sampler States
4603 * TODO: Verify against dx9 definitions
4606 static HRESULT WINAPI IWineD3DDeviceImpl_SetSamplerState(IWineD3DDevice *iface, DWORD Sampler, WINED3DSAMPLERSTATETYPE Type, DWORD Value) {
4607 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4609 * SetSampler is designed to allow for more than the standard up to 8 textures
4610 * and Geforce has stopped supporting more than 6 standard textures in openGL.
4611 * So I have to use ARB for Gforce. (maybe if the sampler > 4 then use ARB?)
4613 * http://developer.nvidia.com/object/General_FAQ.html#t6
4615 * There are two new settings for GForce
4617 * GL_MAX_TEXTURE_IMAGE_UNITS_ARB
4618 * and the texture one:
4619 * GL_MAX_TEXTURE_COORDS_ARB.
4620 * Ok GForce say it's ok to use glTexParameter/glGetTexParameter(...).
4622 /** NOTE: States are appled in IWineD3DBaseTextre ApplyStateChanges and IWineD3DDevice SetupTextureStates**/
4623 if(Sampler > GL_LIMITS(sampler_stages) || Sampler < 0 || Type > WINED3D_HIGHEST_SAMPLER_STATE || Type < 0) {
4624 FIXME("sampler %ld type %s(%u) is out of range [max_samplers=%d, highest_state=%d]\n",
4625 Sampler, debug_d3dsamplerstate(Type), Type, GL_LIMITS(sampler_stages), WINED3D_HIGHEST_SAMPLER_STATE);
4626 return WINED3DERR_INVALIDCALL;
4629 TRACE("(%p) : Sampler=%ld, Type=%s(%d), Value=%ld\n", This, Sampler,
4630 debug_d3dsamplerstate(Type), Type, Value);
4631 This->updateStateBlock->samplerState[Sampler][Type] = Value;
4632 This->updateStateBlock->set.samplerState[Sampler][Type] = Value;
4633 This->updateStateBlock->changed.samplerState[Sampler][Type] = Value;
4635 /* Handle recording of state blocks */
4636 if (This->isRecordingState) {
4637 TRACE("Recording... not performing anything\n");
4644 static HRESULT WINAPI IWineD3DDeviceImpl_GetSamplerState(IWineD3DDevice *iface, DWORD Sampler, WINED3DSAMPLERSTATETYPE Type, DWORD* Value) {
4645 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4646 /** TODO: check that sampler is in range **/
4647 *Value = This->updateStateBlock->samplerState[Sampler][Type];
4648 TRACE("(%p) : Sampler %ld Type %u Returning %ld\n", This, Sampler, Type, *Value);
4653 static HRESULT WINAPI IWineD3DDeviceImpl_SetScissorRect(IWineD3DDevice *iface, CONST RECT* pRect) {
4654 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4657 /** FIXME: Windows uses a top,left origin openGL uses a bottom Right? **/
4658 TRACE("(%p)Setting new Scissor Rect to %ld:%ld-%ld:%ld\n", This, pRect->left, pRect->top, pRect->right, pRect->bottom);
4659 glScissor(pRect->left, pRect->top, pRect->right - pRect->left, pRect->bottom - pRect->top);
4665 static HRESULT WINAPI IWineD3DDeviceImpl_GetScissorRect(IWineD3DDevice *iface, RECT* pRect) {
4666 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4667 GLint scissorBox[4];
4670 /** FIXME: Windows uses a top,left origin openGL uses a bottom Right? **/
4671 glGetIntegerv(GL_SCISSOR_BOX, scissorBox);
4672 pRect->left = scissorBox[0];
4673 pRect->top = scissorBox[1];
4674 pRect->right = scissorBox[0] + scissorBox[2];
4675 pRect->bottom = scissorBox[1] + scissorBox[3];
4676 TRACE("(%p)Returning a Scissor Rect of %ld:%ld-%ld:%ld\n", This, pRect->left, pRect->top, pRect->right, pRect->bottom);
4681 static HRESULT WINAPI IWineD3DDeviceImpl_SetVertexDeclaration(IWineD3DDevice* iface, IWineD3DVertexDeclaration* pDecl) {
4682 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *) iface;
4683 IWineD3DVertexDeclaration *oldDecl = This->updateStateBlock->vertexDecl;
4685 TRACE("(%p) : pDecl=%p\n", This, pDecl);
4687 This->updateStateBlock->vertexDecl = pDecl;
4688 This->updateStateBlock->changed.vertexDecl = TRUE;
4689 This->updateStateBlock->set.vertexDecl = TRUE;
4691 if (This->isRecordingState) {
4692 TRACE("Recording... not performing anything\n");
4695 if (NULL != pDecl) {
4696 IWineD3DVertexDeclaration_AddRef(pDecl);
4698 if (NULL != oldDecl) {
4699 IWineD3DVertexDeclaration_Release(oldDecl);
4704 static HRESULT WINAPI IWineD3DDeviceImpl_GetVertexDeclaration(IWineD3DDevice* iface, IWineD3DVertexDeclaration** ppDecl) {
4705 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4707 TRACE("(%p) : ppDecl=%p\n", This, ppDecl);
4709 *ppDecl = This->stateBlock->vertexDecl;
4710 if (NULL != *ppDecl) IWineD3DVertexDeclaration_AddRef(*ppDecl);
4714 static HRESULT WINAPI IWineD3DDeviceImpl_SetVertexShader(IWineD3DDevice *iface, IWineD3DVertexShader* pShader) {
4715 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4716 IWineD3DVertexShader* oldShader = This->updateStateBlock->vertexShader;
4718 This->updateStateBlock->vertexShader = pShader;
4719 This->updateStateBlock->changed.vertexShader = TRUE;
4720 This->updateStateBlock->set.vertexShader = TRUE;
4722 if (This->isRecordingState) {
4723 TRACE("Recording... not performing anything\n");
4726 if (NULL != pShader) {
4727 IWineD3DVertexShader_AddRef(pShader);
4729 if (NULL != oldShader) {
4730 IWineD3DVertexShader_Release(oldShader);
4733 TRACE("(%p) : setting pShader(%p)\n", This, pShader);
4735 * TODO: merge HAL shaders context switching from prototype
4740 static HRESULT WINAPI IWineD3DDeviceImpl_GetVertexShader(IWineD3DDevice *iface, IWineD3DVertexShader** ppShader) {
4741 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4743 if (NULL == ppShader) {
4744 return WINED3DERR_INVALIDCALL;
4746 *ppShader = This->stateBlock->vertexShader;
4747 if( NULL != *ppShader)
4748 IWineD3DVertexShader_AddRef(*ppShader);
4750 TRACE("(%p) : returning %p\n", This, *ppShader);
4754 static HRESULT WINAPI IWineD3DDeviceImpl_SetVertexShaderConstantB(
4755 IWineD3DDevice *iface,
4757 CONST BOOL *srcData,
4760 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4761 int i, cnt = min(count, MAX_CONST_B - start);
4763 TRACE("(iface %p, srcData %p, start %d, count %d)\n",
4764 iface, srcData, start, count);
4766 if (srcData == NULL || cnt < 0)
4767 return WINED3DERR_INVALIDCALL;
4769 memcpy(&This->updateStateBlock->vertexShaderConstantB[start], srcData, cnt * sizeof(BOOL));
4770 for (i = 0; i < cnt; i++)
4771 TRACE("Set BOOL constant %u to %s\n", start + i, srcData[i]? "true":"false");
4773 for (i = start; i < cnt + start; ++i) {
4774 This->updateStateBlock->changed.vertexShaderConstantsB[i] = TRUE;
4775 This->updateStateBlock->set.vertexShaderConstantsB[i] = TRUE;
4781 static HRESULT WINAPI IWineD3DDeviceImpl_GetVertexShaderConstantB(
4782 IWineD3DDevice *iface,
4787 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4788 int cnt = min(count, MAX_CONST_B - start);
4790 TRACE("(iface %p, dstData %p, start %d, count %d)\n",
4791 iface, dstData, start, count);
4793 if (dstData == NULL || cnt < 0)
4794 return WINED3DERR_INVALIDCALL;
4796 memcpy(dstData, &This->stateBlock->vertexShaderConstantB[start], cnt * sizeof(BOOL));
4800 static HRESULT WINAPI IWineD3DDeviceImpl_SetVertexShaderConstantI(
4801 IWineD3DDevice *iface,
4806 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4807 int i, cnt = min(count, MAX_CONST_I - start);
4809 TRACE("(iface %p, srcData %p, start %d, count %d)\n",
4810 iface, srcData, start, count);
4812 if (srcData == NULL || cnt < 0)
4813 return WINED3DERR_INVALIDCALL;
4815 memcpy(&This->updateStateBlock->vertexShaderConstantI[start * 4], srcData, cnt * sizeof(int) * 4);
4816 for (i = 0; i < cnt; i++)
4817 TRACE("Set INT constant %u to { %d, %d, %d, %d }\n", start + i,
4818 srcData[i*4], srcData[i*4+1], srcData[i*4+2], srcData[i*4+3]);
4820 for (i = start; i < cnt + start; ++i) {
4821 This->updateStateBlock->changed.vertexShaderConstantsI[i] = TRUE;
4822 This->updateStateBlock->set.vertexShaderConstantsI[i] = TRUE;
4828 static HRESULT WINAPI IWineD3DDeviceImpl_GetVertexShaderConstantI(
4829 IWineD3DDevice *iface,
4834 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4835 int cnt = min(count, MAX_CONST_I - start);
4837 TRACE("(iface %p, dstData %p, start %d, count %d)\n",
4838 iface, dstData, start, count);
4840 if (dstData == NULL || ((signed int) MAX_CONST_I - (signed int) start) <= (signed int) 0)
4841 return WINED3DERR_INVALIDCALL;
4843 memcpy(dstData, &This->stateBlock->vertexShaderConstantI[start * 4], cnt * sizeof(int) * 4);
4847 static HRESULT WINAPI IWineD3DDeviceImpl_SetVertexShaderConstantF(
4848 IWineD3DDevice *iface,
4850 CONST float *srcData,
4853 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4854 int i, cnt = min(count, GL_LIMITS(vshader_constantsF) - start);
4856 TRACE("(iface %p, srcData %p, start %d, count %d)\n",
4857 iface, srcData, start, count);
4859 if (srcData == NULL || ((signed int) GL_LIMITS(vshader_constantsF) - (signed int) start) <= (signed int) 0)
4860 return WINED3DERR_INVALIDCALL;
4862 memcpy(&This->updateStateBlock->vertexShaderConstantF[start * 4], srcData, cnt * sizeof(float) * 4);
4863 for (i = 0; i < cnt; i++)
4864 TRACE("Set FLOAT constant %u to { %f, %f, %f, %f }\n", start + i,
4865 srcData[i*4], srcData[i*4+1], srcData[i*4+2], srcData[i*4+3]);
4867 for (i = start; i < cnt + start; ++i) {
4868 if (!This->updateStateBlock->set.vertexShaderConstantsF[i]) {
4869 constant_entry *ptr = HeapAlloc(GetProcessHeap(), 0, sizeof(constant_entry));
4871 list_add_head(&This->updateStateBlock->set_vconstantsF, &ptr->entry);
4872 This->updateStateBlock->set.vertexShaderConstantsF[i] = TRUE;
4874 This->updateStateBlock->changed.vertexShaderConstantsF[i] = TRUE;
4880 static HRESULT WINAPI IWineD3DDeviceImpl_GetVertexShaderConstantF(
4881 IWineD3DDevice *iface,
4886 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4887 int cnt = min(count, GL_LIMITS(vshader_constantsF) - start);
4889 TRACE("(iface %p, dstData %p, start %d, count %d)\n",
4890 iface, dstData, start, count);
4892 if (dstData == NULL || cnt < 0)
4893 return WINED3DERR_INVALIDCALL;
4895 memcpy(dstData, &This->stateBlock->vertexShaderConstantF[start * 4], cnt * sizeof(float) * 4);
4899 static HRESULT WINAPI IWineD3DDeviceImpl_SetPixelShader(IWineD3DDevice *iface, IWineD3DPixelShader *pShader) {
4900 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4901 IWineD3DPixelShader *oldShader = This->updateStateBlock->pixelShader;
4902 This->updateStateBlock->pixelShader = pShader;
4903 This->updateStateBlock->changed.pixelShader = TRUE;
4904 This->updateStateBlock->set.pixelShader = TRUE;
4906 /* Handle recording of state blocks */
4907 if (This->isRecordingState) {
4908 TRACE("Recording... not performing anything\n");
4911 if (NULL != pShader) {
4912 IWineD3DPixelShader_AddRef(pShader);
4914 if (NULL != oldShader) {
4915 IWineD3DPixelShader_Release(oldShader);
4918 TRACE("(%p) : setting pShader(%p)\n", This, pShader);
4920 * TODO: merge HAL shaders context switching from prototype
4925 static HRESULT WINAPI IWineD3DDeviceImpl_GetPixelShader(IWineD3DDevice *iface, IWineD3DPixelShader **ppShader) {
4926 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4928 if (NULL == ppShader) {
4929 WARN("(%p) : PShader is NULL, returning INVALIDCALL\n", This);
4930 return WINED3DERR_INVALIDCALL;
4933 *ppShader = This->stateBlock->pixelShader;
4934 if (NULL != *ppShader) {
4935 IWineD3DPixelShader_AddRef(*ppShader);
4937 TRACE("(%p) : returning %p\n", This, *ppShader);
4941 static HRESULT WINAPI IWineD3DDeviceImpl_SetPixelShaderConstantB(
4942 IWineD3DDevice *iface,
4944 CONST BOOL *srcData,
4947 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4948 int i, cnt = min(count, MAX_CONST_B - start);
4950 TRACE("(iface %p, srcData %p, start %d, count %d)\n",
4951 iface, srcData, start, count);
4953 if (srcData == NULL || cnt < 0)
4954 return WINED3DERR_INVALIDCALL;
4956 memcpy(&This->updateStateBlock->pixelShaderConstantB[start], srcData, cnt * sizeof(BOOL));
4957 for (i = 0; i < cnt; i++)
4958 TRACE("Set BOOL constant %u to %s\n", start + i, srcData[i]? "true":"false");
4960 for (i = start; i < cnt + start; ++i) {
4961 This->updateStateBlock->changed.pixelShaderConstantsB[i] = TRUE;
4962 This->updateStateBlock->set.pixelShaderConstantsB[i] = TRUE;
4968 static HRESULT WINAPI IWineD3DDeviceImpl_GetPixelShaderConstantB(
4969 IWineD3DDevice *iface,
4974 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4975 int cnt = min(count, MAX_CONST_B - start);
4977 TRACE("(iface %p, dstData %p, start %d, count %d)\n",
4978 iface, dstData, start, count);
4980 if (dstData == NULL || cnt < 0)
4981 return WINED3DERR_INVALIDCALL;
4983 memcpy(dstData, &This->stateBlock->pixelShaderConstantB[start], cnt * sizeof(BOOL));
4987 static HRESULT WINAPI IWineD3DDeviceImpl_SetPixelShaderConstantI(
4988 IWineD3DDevice *iface,
4993 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4994 int i, cnt = min(count, MAX_CONST_I - start);
4996 TRACE("(iface %p, srcData %p, start %d, count %d)\n",
4997 iface, srcData, start, count);
4999 if (srcData == NULL || cnt < 0)
5000 return WINED3DERR_INVALIDCALL;
5002 memcpy(&This->updateStateBlock->pixelShaderConstantI[start * 4], srcData, cnt * sizeof(int) * 4);
5003 for (i = 0; i < cnt; i++)
5004 TRACE("Set INT constant %u to { %d, %d, %d, %d }\n", start + i,
5005 srcData[i*4], srcData[i*4+1], srcData[i*4+2], srcData[i*4+3]);
5007 for (i = start; i < cnt + start; ++i) {
5008 This->updateStateBlock->changed.pixelShaderConstantsI[i] = TRUE;
5009 This->updateStateBlock->set.pixelShaderConstantsI[i] = TRUE;
5015 static HRESULT WINAPI IWineD3DDeviceImpl_GetPixelShaderConstantI(
5016 IWineD3DDevice *iface,
5021 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5022 int cnt = min(count, MAX_CONST_I - start);
5024 TRACE("(iface %p, dstData %p, start %d, count %d)\n",
5025 iface, dstData, start, count);
5027 if (dstData == NULL || cnt < 0)
5028 return WINED3DERR_INVALIDCALL;
5030 memcpy(dstData, &This->stateBlock->pixelShaderConstantI[start * 4], cnt * sizeof(int) * 4);
5034 static HRESULT WINAPI IWineD3DDeviceImpl_SetPixelShaderConstantF(
5035 IWineD3DDevice *iface,
5037 CONST float *srcData,
5040 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5041 int i, cnt = min(count, GL_LIMITS(pshader_constantsF) - start);
5043 TRACE("(iface %p, srcData %p, start %d, count %d)\n",
5044 iface, srcData, start, count);
5046 if (srcData == NULL || cnt < 0)
5047 return WINED3DERR_INVALIDCALL;
5049 memcpy(&This->updateStateBlock->pixelShaderConstantF[start * 4], srcData, cnt * sizeof(float) * 4);
5050 for (i = 0; i < cnt; i++)
5051 TRACE("Set FLOAT constant %u to { %f, %f, %f, %f }\n", start + i,
5052 srcData[i*4], srcData[i*4+1], srcData[i*4+2], srcData[i*4+3]);
5054 for (i = start; i < cnt + start; ++i) {
5055 if (!This->updateStateBlock->set.pixelShaderConstantsF[i]) {
5056 constant_entry *ptr = HeapAlloc(GetProcessHeap(), 0, sizeof(constant_entry));
5058 list_add_head(&This->updateStateBlock->set_pconstantsF, &ptr->entry);
5059 This->updateStateBlock->set.pixelShaderConstantsF[i] = TRUE;
5061 This->updateStateBlock->changed.pixelShaderConstantsF[i] = TRUE;
5067 static HRESULT WINAPI IWineD3DDeviceImpl_GetPixelShaderConstantF(
5068 IWineD3DDevice *iface,
5073 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5074 int cnt = min(count, GL_LIMITS(pshader_constantsF) - start);
5076 TRACE("(iface %p, dstData %p, start %d, count %d)\n",
5077 iface, dstData, start, count);
5079 if (dstData == NULL || cnt < 0)
5080 return WINED3DERR_INVALIDCALL;
5082 memcpy(dstData, &This->stateBlock->pixelShaderConstantF[start * 4], cnt * sizeof(float) * 4);
5086 #define copy_and_next(dest, src, size) memcpy(dest, src, size); dest += (size)
5088 process_vertices_strided(IWineD3DDeviceImpl *This, DWORD dwDestIndex, DWORD dwCount, WineDirect3DVertexStridedData *lpStrideData, DWORD SrcFVF, IWineD3DVertexBufferImpl *dest, DWORD dwFlags) {
5089 char *dest_ptr, *dest_conv = NULL;
5091 DWORD DestFVF = dest->fvf;
5093 D3DMATRIX mat, proj_mat, view_mat, world_mat;
5097 if (SrcFVF & D3DFVF_NORMAL) {
5098 WARN(" lighting state not saved yet... Some strange stuff may happen !\n");
5101 if ( (SrcFVF & D3DFVF_POSITION_MASK) != D3DFVF_XYZ) {
5102 ERR("Source has no position mask\n");
5103 return WINED3DERR_INVALIDCALL;
5106 /* We might access VBOs from this code, so hold the lock */
5109 if (dest->resource.allocatedMemory == NULL) {
5110 /* This may happen if we do direct locking into a vbo. Unlikely,
5111 * but theoretically possible(ddraw processvertices test)
5113 dest->resource.allocatedMemory = HeapAlloc(GetProcessHeap(), 0, dest->resource.size);
5114 if(!dest->resource.allocatedMemory) {
5116 ERR("Out of memory\n");
5117 return E_OUTOFMEMORY;
5121 GL_EXTCALL(glBindBufferARB(GL_ARRAY_BUFFER_ARB, dest->vbo));
5122 checkGLcall("glBindBufferARB");
5123 src = GL_EXTCALL(glMapBufferARB(GL_ARRAY_BUFFER_ARB, GL_READ_ONLY_ARB));
5125 memcpy(dest->resource.allocatedMemory, src, dest->resource.size);
5127 GL_EXTCALL(glUnmapBufferARB(GL_ARRAY_BUFFER_ARB));
5128 checkGLcall("glUnmapBufferARB");
5132 /* Get a pointer into the destination vbo(create one if none exists) and
5133 * write correct opengl data into it. It's cheap and allows us to run drawStridedFast
5135 if(!dest->vbo && GL_SUPPORT(ARB_VERTEX_BUFFER_OBJECT)) {
5140 GL_EXTCALL(glBindBufferARB(GL_ARRAY_BUFFER_ARB, dest->vbo));
5141 dest_conv = GL_EXTCALL(glMapBufferARB(GL_ARRAY_BUFFER_ARB, GL_WRITE_ONLY_ARB));
5143 ERR("glMapBuffer failed\n");
5144 /* Continue without storing converted vertices */
5149 * a) D3DRS_CLIPPING is enabled
5150 * b) WINED3DVOP_CLIP is passed
5152 if(This->stateBlock->renderState[WINED3DRS_CLIPPING]) {
5153 static BOOL warned = FALSE;
5155 * The clipping code is not quite correct. Some things need
5156 * to be checked against IDirect3DDevice3 (!), d3d8 and d3d9,
5157 * so disable clipping for now.
5158 * (The graphics in Half-Life are broken, and my processvertices
5159 * test crashes with IDirect3DDevice3)
5165 FIXME("Clipping is broken and disabled for now\n");
5167 } else doClip = FALSE;
5168 dest_ptr = ((char *) dest->resource.allocatedMemory) + dwDestIndex * get_flexible_vertex_size(DestFVF);
5170 dest_conv = ((char *) dest_conv) + dwDestIndex * get_flexible_vertex_size(DestFVF);
5173 IWineD3DDevice_GetTransform( (IWineD3DDevice *) This,
5176 IWineD3DDevice_GetTransform( (IWineD3DDevice *) This,
5177 WINED3DTS_PROJECTION,
5179 IWineD3DDevice_GetTransform( (IWineD3DDevice *) This,
5180 WINED3DTS_WORLDMATRIX(0),
5183 TRACE("View mat:\n");
5184 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); \
5185 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); \
5186 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); \
5187 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); \
5189 TRACE("Proj mat:\n");
5190 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); \
5191 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); \
5192 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); \
5193 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); \
5195 TRACE("World mat:\n");
5196 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); \
5197 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); \
5198 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); \
5199 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); \
5201 /* Get the viewport */
5202 IWineD3DDevice_GetViewport( (IWineD3DDevice *) This, &vp);
5203 TRACE("Viewport: X=%ld, Y=%ld, Width=%ld, Height=%ld, MinZ=%f, MaxZ=%f\n",
5204 vp.X, vp.Y, vp.Width, vp.Height, vp.MinZ, vp.MaxZ);
5206 multiply_matrix(&mat,&view_mat,&world_mat);
5207 multiply_matrix(&mat,&proj_mat,&mat);
5209 numTextures = (DestFVF & D3DFVF_TEXCOUNT_MASK) >> D3DFVF_TEXCOUNT_SHIFT;
5211 for (i = 0; i < dwCount; i+= 1) {
5212 unsigned int tex_index;
5214 if ( ((DestFVF & D3DFVF_POSITION_MASK) == D3DFVF_XYZ ) ||
5215 ((DestFVF & D3DFVF_POSITION_MASK) == D3DFVF_XYZRHW ) ) {
5216 /* The position first */
5218 (float *) (((char *) lpStrideData->u.s.position.lpData) + i * lpStrideData->u.s.position.dwStride);
5220 TRACE("In: ( %06.2f %06.2f %06.2f )\n", p[0], p[1], p[2]);
5222 /* Multiplication with world, view and projection matrix */
5223 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);
5224 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);
5225 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);
5226 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);
5228 TRACE("x=%f y=%f z=%f rhw=%f\n", x, y, z, rhw);
5230 /* WARNING: The following things are taken from d3d7 and were not yet checked
5231 * against d3d8 or d3d9!
5234 /* Clipping conditions: From
5235 * http://msdn.microsoft.com/archive/default.asp?url=/archive/en-us/directx9_c/directx/graphics/programmingguide/fixedfunction/viewportsclipping/clippingvolumes.asp
5237 * A vertex is clipped if it does not match the following requirements
5241 * 0 < rhw ( Not in d3d7, but tested in d3d7)
5243 * If clipping is on is determined by the D3DVOP_CLIP flag in D3D7, and
5244 * by the D3DRS_CLIPPING in D3D9(according to the msdn, not checked)
5248 if( doClip == FALSE ||
5249 ( (-rhw -eps < x) && (-rhw -eps < y) && ( -eps < z) &&
5250 (x <= rhw + eps) && (y <= rhw + eps ) && (z <= rhw + eps) &&
5253 /* "Normal" viewport transformation (not clipped)
5254 * 1) The values are divided by rhw
5255 * 2) The y axis is negative, so multiply it with -1
5256 * 3) Screen coordinates go from -(Width/2) to +(Width/2) and
5257 * -(Height/2) to +(Height/2). The z range is MinZ to MaxZ
5258 * 4) Multiply x with Width/2 and add Width/2
5259 * 5) The same for the height
5260 * 6) Add the viewpoint X and Y to the 2D coordinates and
5261 * The minimum Z value to z
5262 * 7) rhw = 1 / rhw Reciprocal of Homogeneous W....
5264 * Well, basically it's simply a linear transformation into viewport
5276 z *= vp.MaxZ - vp.MinZ;
5278 x += vp.Width / 2 + vp.X;
5279 y += vp.Height / 2 + vp.Y;
5284 /* That vertex got clipped
5285 * Contrary to OpenGL it is not dropped completely, it just
5286 * undergoes a different calculation.
5288 TRACE("Vertex got clipped\n");
5295 /* Msdn mentions that Direct3D9 keeps a list of clipped vertices
5296 * outside of the main vertex buffer memory. That needs some more
5301 TRACE("Writing (%f %f %f) %f\n", x, y, z, rhw);
5304 ( (float *) dest_ptr)[0] = x;
5305 ( (float *) dest_ptr)[1] = y;
5306 ( (float *) dest_ptr)[2] = z;
5307 ( (float *) dest_ptr)[3] = rhw; /* SIC, see ddraw test! */
5309 dest_ptr += 3 * sizeof(float);
5311 if((DestFVF & D3DFVF_POSITION_MASK) == D3DFVF_XYZRHW) {
5312 dest_ptr += sizeof(float);
5317 ( (float *) dest_conv)[0] = x * w;
5318 ( (float *) dest_conv)[1] = y * w;
5319 ( (float *) dest_conv)[2] = z * w;
5320 ( (float *) dest_conv)[3] = w;
5322 dest_conv += 3 * sizeof(float);
5324 if((DestFVF & D3DFVF_POSITION_MASK) == D3DFVF_XYZRHW) {
5325 dest_conv += sizeof(float);
5329 if (DestFVF & D3DFVF_PSIZE) {
5330 dest_ptr += sizeof(DWORD);
5331 if(dest_conv) dest_conv += sizeof(DWORD);
5333 if (DestFVF & D3DFVF_NORMAL) {
5335 (float *) (((float *) lpStrideData->u.s.normal.lpData) + i * lpStrideData->u.s.normal.dwStride);
5336 /* AFAIK this should go into the lighting information */
5337 FIXME("Didn't expect the destination to have a normal\n");
5338 copy_and_next(dest_ptr, normal, 3 * sizeof(float));
5340 copy_and_next(dest_conv, normal, 3 * sizeof(float));
5344 if (DestFVF & D3DFVF_DIFFUSE) {
5346 (DWORD *) (((char *) lpStrideData->u.s.diffuse.lpData) + i * lpStrideData->u.s.diffuse.dwStride);
5348 static BOOL warned = FALSE;
5350 if(warned == FALSE) {
5351 ERR("No diffuse color in source, but destination has one\n");
5355 *( (DWORD *) dest_ptr) = 0xffffffff;
5356 dest_ptr += sizeof(DWORD);
5359 *( (DWORD *) dest_conv) = 0xffffffff;
5360 dest_conv += sizeof(DWORD);
5364 copy_and_next(dest_ptr, color_d, sizeof(DWORD));
5366 *( (DWORD *) dest_conv) = (*color_d & 0xff00ff00) ; /* Alpha + green */
5367 *( (DWORD *) dest_conv) |= (*color_d & 0x00ff0000) >> 16; /* Red */
5368 *( (DWORD *) dest_conv) |= (*color_d & 0xff0000ff) << 16; /* Blue */
5369 dest_conv += sizeof(DWORD);
5374 if (DestFVF & D3DFVF_SPECULAR) {
5375 /* What's the color value in the feedback buffer? */
5377 (DWORD *) (((char *) lpStrideData->u.s.specular.lpData) + i * lpStrideData->u.s.specular.dwStride);
5379 static BOOL warned = FALSE;
5381 if(warned == FALSE) {
5382 ERR("No specular color in source, but destination has one\n");
5386 *( (DWORD *) dest_ptr) = 0xFF000000;
5387 dest_ptr += sizeof(DWORD);
5390 *( (DWORD *) dest_conv) = 0xFF000000;
5391 dest_conv += sizeof(DWORD);
5395 copy_and_next(dest_ptr, color_s, sizeof(DWORD));
5397 *( (DWORD *) dest_conv) = (*color_s & 0xff00ff00) ; /* Alpha + green */
5398 *( (DWORD *) dest_conv) |= (*color_s & 0x00ff0000) >> 16; /* Red */
5399 *( (DWORD *) dest_conv) |= (*color_s & 0xff0000ff) << 16; /* Blue */
5400 dest_conv += sizeof(DWORD);
5405 for (tex_index = 0; tex_index < numTextures; tex_index++) {
5407 (float *) (((char *) lpStrideData->u.s.texCoords[tex_index].lpData) +
5408 i * lpStrideData->u.s.texCoords[tex_index].dwStride);
5410 ERR("No source texture, but destination requests one\n");
5411 dest_ptr+=GET_TEXCOORD_SIZE_FROM_FVF(DestFVF, tex_index) * sizeof(float);
5412 if(dest_conv) dest_conv += GET_TEXCOORD_SIZE_FROM_FVF(DestFVF, tex_index) * sizeof(float);
5415 copy_and_next(dest_ptr, tex_coord, GET_TEXCOORD_SIZE_FROM_FVF(DestFVF, tex_index) * sizeof(float));
5417 copy_and_next(dest_conv, tex_coord, GET_TEXCOORD_SIZE_FROM_FVF(DestFVF, tex_index) * sizeof(float));
5424 GL_EXTCALL(glUnmapBufferARB(GL_ARRAY_BUFFER_ARB));
5425 checkGLcall("glUnmapBufferARB(GL_ARRAY_BUFFER_ARB)");
5432 #undef copy_and_next
5434 static HRESULT WINAPI IWineD3DDeviceImpl_ProcessVertices(IWineD3DDevice *iface, UINT SrcStartIndex, UINT DestIndex, UINT VertexCount, IWineD3DVertexBuffer* pDestBuffer, IWineD3DVertexBuffer* pVertexDecl, DWORD Flags) {
5435 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5436 IWineD3DVertexBufferImpl *SrcImpl = (IWineD3DVertexBufferImpl *) pVertexDecl;
5437 WineDirect3DVertexStridedData strided;
5438 TRACE("(%p)->(%d,%d,%d,%p,%p,%ld\n", This, SrcStartIndex, DestIndex, VertexCount, pDestBuffer, pVertexDecl, Flags);
5441 WARN("NULL source vertex buffer\n");
5442 return WINED3DERR_INVALIDCALL;
5444 /* We don't need the source vbo because this buffer is only used as
5445 * a source for ProcessVertices. Avoid wasting resources by converting the
5446 * buffer and loading the VBO
5449 TRACE("Releaseing the source vbo, it won't be needed\n");
5451 if(!SrcImpl->resource.allocatedMemory) {
5452 /* Rescue the data from the buffer */
5454 SrcImpl->resource.allocatedMemory = HeapAlloc(GetProcessHeap(), 0, SrcImpl->resource.size);
5455 if(!SrcImpl->resource.allocatedMemory) {
5456 ERR("Out of memory\n");
5457 return E_OUTOFMEMORY;
5461 GL_EXTCALL(glBindBufferARB(GL_ARRAY_BUFFER_ARB, SrcImpl->vbo));
5462 checkGLcall("glBindBufferARB");
5464 src = GL_EXTCALL(glMapBufferARB(GL_ARRAY_BUFFER_ARB, GL_READ_ONLY_ARB));
5466 memcpy(SrcImpl->resource.allocatedMemory, src, SrcImpl->resource.size);
5469 GL_EXTCALL(glUnmapBufferARB(GL_ARRAY_BUFFER_ARB));
5470 checkGLcall("glUnmapBufferARB");
5475 GL_EXTCALL(glBindBufferARB(GL_ARRAY_BUFFER_ARB, 0));
5476 checkGLcall("glBindBufferARB");
5477 GL_EXTCALL(glDeleteBuffersARB(1, &SrcImpl->vbo));
5478 checkGLcall("glDeleteBuffersARB");
5484 memset(&strided, 0, sizeof(strided));
5485 primitiveConvertFVFtoOffset(SrcImpl->fvf, get_flexible_vertex_size(SrcImpl->fvf), SrcImpl->resource.allocatedMemory + get_flexible_vertex_size(SrcImpl->fvf) * SrcStartIndex, &strided, 0);
5487 return process_vertices_strided(This, DestIndex, VertexCount, &strided, SrcImpl->fvf, (IWineD3DVertexBufferImpl *) pDestBuffer, Flags);
5491 * Apply / Get / Set Texture Stage States
5492 * TODO: Verify against dx9 definitions
5495 /* 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 */
5496 static void WINAPI IWineD3DDeviceImpl_ApplyTextureUnitState(IWineD3DDevice *iface, DWORD Stage, WINED3DTEXTURESTAGESTATETYPE Type) {
5497 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5498 DWORD Value = This->updateStateBlock->textureState[Stage][Type];
5499 /* FIXME: Handle 3d textures? What if TSS value set before set texture? Need to reapply all values? */
5501 TRACE("(%p) : Stage=%ld, Type=%s(%d), Value=%ld\n", This, Stage, debug_d3dtexturestate(Type), Type, Value);
5503 /* Check that the stage is within limits */
5504 if (Stage >= GL_LIMITS(texture_stages) || Stage < 0) {
5505 TRACE("Attempt to access invalid texture rejected\n");
5512 case WINED3DTSS_ALPHAOP :
5513 case WINED3DTSS_COLOROP :
5514 /* nothing to do as moved to drawprim for now */
5516 case WINED3DTSS_ADDRESSW :
5517 #if 0 /* I'm not sure what D3D does about ADDRESSW appearing twice */
5518 if (Value < minLookup[WINELOOKUP_WARPPARAM] || Value > maxLookup[WINELOOKUP_WARPPARAM]) {
5519 FIXME("Unrecognized or unsupported D3DTADDRESS_* value %ld, state %d\n", Value, Type);
5522 GLint wrapParm = stateLookup[WINELOOKUP_WARPPARAM][Value - minLookup[WINELOOKUP_WARPPARAM]];
5523 TRACE("Setting WRAP_R to %d for %x\n", wrapParm, This->stateBlock->textureDimensions[Stage]);
5524 glTexParameteri(This->stateBlock->textureDimensions[Stage], GL_TEXTURE_WRAP_R, wrapParm);
5525 checkGLcall("glTexParameteri(..., GL_TEXTURE_WRAP_R, wrapParm)");
5528 case WINED3DTSS_TEXCOORDINDEX :
5530 /* Values 0-7 are indexes into the FVF tex coords - See comments in DrawPrimitive */
5532 /* FIXME: From MSDN: The WINED3DTSS_TCI_* flags are mutually exclusive. If you include
5533 one flag, you can still specify an index value, which the system uses to
5534 determine the texture wrapping mode.
5535 eg. SetTextureStageState( 0, D3DTSS_TEXCOORDINDEX, D3DTSS_TCI_CAMERASPACEPOSITION | 1 );
5536 means use the vertex position (camera-space) as the input texture coordinates
5537 for this texture stage, and the wrap mode set in the WINED3DRS_WRAP1 render
5538 state. We do not (yet) support the D3DRENDERSTATE_WRAPx values, nor tie them up
5539 to the TEXCOORDINDEX value */
5542 * Be careful the value of the mask 0xF0000 come from d3d8types.h infos
5544 switch (Value & 0xFFFF0000) {
5545 case D3DTSS_TCI_PASSTHRU:
5546 /*Use the specified texture coordinates contained within the vertex format. This value resolves to zero.*/
5547 glDisable(GL_TEXTURE_GEN_S);
5548 glDisable(GL_TEXTURE_GEN_T);
5549 glDisable(GL_TEXTURE_GEN_R);
5550 glDisable(GL_TEXTURE_GEN_Q);
5551 checkGLcall("glDisable(GL_TEXTURE_GEN_S,T,R,Q)");
5554 case D3DTSS_TCI_CAMERASPACEPOSITION:
5555 /* CameraSpacePosition means use the vertex position, transformed to camera space,
5556 as the input texture coordinates for this stage's texture transformation. This
5557 equates roughly to EYE_LINEAR */
5559 float s_plane[] = { 1.0, 0.0, 0.0, 0.0 };
5560 float t_plane[] = { 0.0, 1.0, 0.0, 0.0 };
5561 float r_plane[] = { 0.0, 0.0, 1.0, 0.0 };
5562 float q_plane[] = { 0.0, 0.0, 0.0, 1.0 };
5563 TRACE("WINED3DTSS_TCI_CAMERASPACEPOSITION - Set eye plane\n");
5565 glMatrixMode(GL_MODELVIEW);
5568 glTexGenfv(GL_S, GL_EYE_PLANE, s_plane);
5569 glTexGenfv(GL_T, GL_EYE_PLANE, t_plane);
5570 glTexGenfv(GL_R, GL_EYE_PLANE, r_plane);
5571 glTexGenfv(GL_Q, GL_EYE_PLANE, q_plane);
5574 TRACE("WINED3DTSS_TCI_CAMERASPACEPOSITION - Set GL_TEXTURE_GEN_x and GL_x, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR\n");
5575 glEnable(GL_TEXTURE_GEN_S);
5576 checkGLcall("glEnable(GL_TEXTURE_GEN_S);");
5577 glTexGeni(GL_S, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR);
5578 checkGLcall("glTexGeni(GL_S, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR)");
5579 glEnable(GL_TEXTURE_GEN_T);
5580 checkGLcall("glEnable(GL_TEXTURE_GEN_T);");
5581 glTexGeni(GL_T, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR);
5582 checkGLcall("glTexGeni(GL_T, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR)");
5583 glEnable(GL_TEXTURE_GEN_R);
5584 checkGLcall("glEnable(GL_TEXTURE_GEN_R);");
5585 glTexGeni(GL_R, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR);
5586 checkGLcall("glTexGeni(GL_R, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR)");
5590 case D3DTSS_TCI_CAMERASPACENORMAL:
5592 if (GL_SUPPORT(NV_TEXGEN_REFLECTION)) {
5593 float s_plane[] = { 1.0, 0.0, 0.0, 0.0 };
5594 float t_plane[] = { 0.0, 1.0, 0.0, 0.0 };
5595 float r_plane[] = { 0.0, 0.0, 1.0, 0.0 };
5596 float q_plane[] = { 0.0, 0.0, 0.0, 1.0 };
5597 TRACE("WINED3DTSS_TCI_CAMERASPACENORMAL - Set eye plane\n");
5599 glMatrixMode(GL_MODELVIEW);
5602 glTexGenfv(GL_S, GL_EYE_PLANE, s_plane);
5603 glTexGenfv(GL_T, GL_EYE_PLANE, t_plane);
5604 glTexGenfv(GL_R, GL_EYE_PLANE, r_plane);
5605 glTexGenfv(GL_Q, GL_EYE_PLANE, q_plane);
5608 glEnable(GL_TEXTURE_GEN_S);
5609 checkGLcall("glEnable(GL_TEXTURE_GEN_S);");
5610 glTexGeni(GL_S, GL_TEXTURE_GEN_MODE, GL_NORMAL_MAP_NV);
5611 checkGLcall("glTexGeni(GL_S, GL_TEXTURE_GEN_MODE, GL_NORMAL_MAP_NV)");
5612 glEnable(GL_TEXTURE_GEN_T);
5613 checkGLcall("glEnable(GL_TEXTURE_GEN_T);");
5614 glTexGeni(GL_T, GL_TEXTURE_GEN_MODE, GL_NORMAL_MAP_NV);
5615 checkGLcall("glTexGeni(GL_T, GL_TEXTURE_GEN_MODE, GL_NORMAL_MAP_NV)");
5616 glEnable(GL_TEXTURE_GEN_R);
5617 checkGLcall("glEnable(GL_TEXTURE_GEN_R);");
5618 glTexGeni(GL_R, GL_TEXTURE_GEN_MODE, GL_NORMAL_MAP_NV);
5619 checkGLcall("glTexGeni(GL_R, GL_TEXTURE_GEN_MODE, GL_NORMAL_MAP_NV)");
5624 case D3DTSS_TCI_CAMERASPACEREFLECTIONVECTOR:
5626 if (GL_SUPPORT(NV_TEXGEN_REFLECTION)) {
5627 float s_plane[] = { 1.0, 0.0, 0.0, 0.0 };
5628 float t_plane[] = { 0.0, 1.0, 0.0, 0.0 };
5629 float r_plane[] = { 0.0, 0.0, 1.0, 0.0 };
5630 float q_plane[] = { 0.0, 0.0, 0.0, 1.0 };
5631 TRACE("WINED3DTSS_TCI_CAMERASPACEREFLECTIONVECTOR - Set eye plane\n");
5633 glMatrixMode(GL_MODELVIEW);
5636 glTexGenfv(GL_S, GL_EYE_PLANE, s_plane);
5637 glTexGenfv(GL_T, GL_EYE_PLANE, t_plane);
5638 glTexGenfv(GL_R, GL_EYE_PLANE, r_plane);
5639 glTexGenfv(GL_Q, GL_EYE_PLANE, q_plane);
5642 glEnable(GL_TEXTURE_GEN_S);
5643 checkGLcall("glEnable(GL_TEXTURE_GEN_S);");
5644 glTexGeni(GL_S, GL_TEXTURE_GEN_MODE, GL_REFLECTION_MAP_NV);
5645 checkGLcall("glTexGeni(GL_S, GL_TEXTURE_GEN_MODE, GL_REFLECTION_MAP_NV)");
5646 glEnable(GL_TEXTURE_GEN_T);
5647 checkGLcall("glEnable(GL_TEXTURE_GEN_T);");
5648 glTexGeni(GL_T, GL_TEXTURE_GEN_MODE, GL_REFLECTION_MAP_NV);
5649 checkGLcall("glTexGeni(GL_T, GL_TEXTURE_GEN_MODE, GL_REFLECTION_MAP_NV)");
5650 glEnable(GL_TEXTURE_GEN_R);
5651 checkGLcall("glEnable(GL_TEXTURE_GEN_R);");
5652 glTexGeni(GL_R, GL_TEXTURE_GEN_MODE, GL_REFLECTION_MAP_NV);
5653 checkGLcall("glTexGeni(GL_R, GL_TEXTURE_GEN_MODE, GL_REFLECTION_MAP_NV)");
5658 /* Unhandled types: */
5661 /* ? disable GL_TEXTURE_GEN_n ? */
5662 glDisable(GL_TEXTURE_GEN_S);
5663 glDisable(GL_TEXTURE_GEN_T);
5664 glDisable(GL_TEXTURE_GEN_R);
5665 glDisable(GL_TEXTURE_GEN_Q);
5666 FIXME("Unhandled WINED3DTSS_TEXCOORDINDEX %lx\n", Value);
5673 case WINED3DTSS_TEXTURETRANSFORMFLAGS :
5674 set_texture_matrix((float *)&This->stateBlock->transforms[WINED3DTS_TEXTURE0 + Stage].u.m[0][0], Value, (This->stateBlock->textureState[Stage][WINED3DTSS_TEXCOORDINDEX] & 0xFFFF0000) != D3DTSS_TCI_PASSTHRU);
5677 case WINED3DTSS_BUMPENVMAT00 :
5678 case WINED3DTSS_BUMPENVMAT01 :
5679 TRACE("BUMPENVMAT0%u Stage=%ld, Type=%d, Value =%ld\n", Type - WINED3DTSS_BUMPENVMAT00, Stage, Type, Value);
5681 case WINED3DTSS_BUMPENVMAT10 :
5682 case WINED3DTSS_BUMPENVMAT11 :
5683 TRACE("BUMPENVMAT1%u Stage=%ld, Type=%d, Value =%ld\n", Type - WINED3DTSS_BUMPENVMAT10, Stage, Type, Value);
5686 case WINED3DTSS_BUMPENVLSCALE :
5687 TRACE("BUMPENVLSCALE Stage=%ld, Type=%d, Value =%ld\n", Stage, Type, Value);
5690 case WINED3DTSS_BUMPENVLOFFSET :
5691 TRACE("BUMPENVLOFFSET Stage=%ld, Type=%d, Value =%ld\n", Stage, Type, Value);
5694 case WINED3DTSS_RESULTARG :
5695 TRACE("RESULTARG Still a stub, Stage=%ld, Type=%d, Value =%ld\n", Stage, Type, Value);
5699 /* Put back later: FIXME("(%p) : stub, Stage=%ld, Type=%d, Value =%ld\n", This, Stage, Type, Value); */
5700 TRACE("Still a stub, Stage=%ld, Type=%d, Value =%ld\n", Stage, Type, Value);
5709 * Get / Set Texture Stage States
5710 * TODO: Verify against dx9 definitions
5712 static HRESULT WINAPI IWineD3DDeviceImpl_SetTextureStageState(IWineD3DDevice *iface, DWORD Stage, WINED3DTEXTURESTAGESTATETYPE Type, DWORD Value) {
5713 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5715 /* FIXME: Handle 3d textures? What if TSS value set before set texture? Need to reapply all values? */
5717 TRACE("(%p) : Stage=%ld, Type=%s(%d), Value=%ld\n", This, Stage, debug_d3dtexturestate(Type), Type, Value);
5719 /* Reject invalid texture units */
5720 if (Stage >= GL_LIMITS(texture_stages)) {
5721 TRACE("Attempt to access invalid texture rejected\n");
5722 return WINED3DERR_INVALIDCALL;
5725 This->updateStateBlock->changed.textureState[Stage][Type] = TRUE;
5726 This->updateStateBlock->set.textureState[Stage][Type] = TRUE;
5727 This->updateStateBlock->textureState[Stage][Type] = Value;
5732 static HRESULT WINAPI IWineD3DDeviceImpl_GetTextureStageState(IWineD3DDevice *iface, DWORD Stage, WINED3DTEXTURESTAGESTATETYPE Type, DWORD* pValue) {
5733 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5734 TRACE("(%p) : requesting Stage %ld, Type %d getting %ld\n", This, Stage, Type, This->updateStateBlock->textureState[Stage][Type]);
5735 *pValue = This->updateStateBlock->textureState[Stage][Type];
5742 static HRESULT WINAPI IWineD3DDeviceImpl_SetTexture(IWineD3DDevice *iface, DWORD Stage, IWineD3DBaseTexture* pTexture) {
5744 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5745 IWineD3DBaseTexture *oldTexture;
5747 oldTexture = This->updateStateBlock->textures[Stage];
5748 TRACE("(%p) : Stage(%ld), Texture (%p)\n", This, Stage, pTexture);
5750 #if 0 /* TODO: check so vertex textures */
5751 if (Stage >= D3DVERTEXTEXTURESAMPLER && Stage <= D3DVERTEXTEXTURESAMPLER3){
5752 This->updateStateBlock->vertexTextures[Stage - D3DVERTEXTEXTURESAMPLER] = pTexture;
5757 /* Reject invalid texture units */
5758 if (Stage >= GL_LIMITS(sampler_stages) || Stage < 0) {
5759 WARN("Attempt to access invalid texture rejected\n");
5760 return WINED3DERR_INVALIDCALL;
5763 if(pTexture != NULL) {
5764 /* SetTexture isn't allowed on textures in WINED3DPOOL_SCRATCH;
5766 if(((IWineD3DTextureImpl*)pTexture)->resource.pool == WINED3DPOOL_SCRATCH) {
5767 WARN("(%p) Attempt to set scratch texture rejected\n", pTexture);
5768 return WINED3DERR_INVALIDCALL;
5772 oldTexture = This->updateStateBlock->textures[Stage];
5773 TRACE("GL_LIMITS %d\n",GL_LIMITS(sampler_stages));
5774 TRACE("(%p) : oldtexture(%p)\n", This,oldTexture);
5776 This->updateStateBlock->set.textures[Stage] = TRUE;
5777 This->updateStateBlock->changed.textures[Stage] = TRUE;
5778 TRACE("(%p) : setting new texture to %p\n", This, pTexture);
5779 This->updateStateBlock->textures[Stage] = pTexture;
5781 /* Handle recording of state blocks */
5782 if (This->isRecordingState) {
5783 TRACE("Recording... not performing anything\n");
5787 /** NOTE: MSDN says that setTexture increases the reference count,
5788 * and the the application nust set the texture back to null (or have a leaky application),
5789 * This means we should pass the refcount up to the parent
5790 *******************************/
5791 if (NULL != This->updateStateBlock->textures[Stage]) {
5792 IWineD3DBaseTexture_AddRef(This->updateStateBlock->textures[Stage]);
5795 if (NULL != oldTexture) {
5796 IWineD3DBaseTexture_Release(oldTexture);
5799 /* Reset color keying */
5800 if(Stage == 0 && This->stateBlock->renderState[WINED3DRS_COLORKEYENABLE]) {
5801 BOOL enable_ckey = FALSE;
5804 IWineD3DSurfaceImpl *surf = (IWineD3DSurfaceImpl *) ((IWineD3DTextureImpl *)pTexture)->surfaces[0];
5805 if(surf->CKeyFlags & DDSD_CKSRCBLT) enable_ckey = TRUE;
5809 glAlphaFunc(GL_NOTEQUAL, 0.0);
5810 checkGLcall("glAlphaFunc");
5817 static HRESULT WINAPI IWineD3DDeviceImpl_GetTexture(IWineD3DDevice *iface, DWORD Stage, IWineD3DBaseTexture** ppTexture) {
5818 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5819 TRACE("(%p) : (%ld /* Stage */,%p /* ppTexture */)\n", This, Stage, ppTexture);
5821 /* Reject invalid texture units */
5822 if (Stage >= GL_LIMITS(sampler_stages)) {
5823 TRACE("Attempt to access invalid texture rejected\n");
5824 return WINED3DERR_INVALIDCALL;
5826 *ppTexture=This->updateStateBlock->textures[Stage];
5828 IWineD3DBaseTexture_AddRef(*ppTexture);
5830 return WINED3DERR_INVALIDCALL;
5837 static HRESULT WINAPI IWineD3DDeviceImpl_GetBackBuffer(IWineD3DDevice *iface, UINT iSwapChain, UINT BackBuffer, WINED3DBACKBUFFER_TYPE Type,
5838 IWineD3DSurface **ppBackBuffer) {
5839 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5840 IWineD3DSwapChain *swapChain;
5843 TRACE("(%p) : BackBuf %d Type %d SwapChain %d returning %p\n", This, BackBuffer, Type, iSwapChain, *ppBackBuffer);
5845 hr = IWineD3DDeviceImpl_GetSwapChain(iface, iSwapChain, &swapChain);
5846 if (hr == WINED3D_OK) {
5847 hr = IWineD3DSwapChain_GetBackBuffer(swapChain, BackBuffer, Type, ppBackBuffer);
5848 IWineD3DSwapChain_Release(swapChain);
5850 *ppBackBuffer = NULL;
5855 static HRESULT WINAPI IWineD3DDeviceImpl_GetDeviceCaps(IWineD3DDevice *iface, WINED3DCAPS* pCaps) {
5856 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5857 WARN("(%p) : stub, calling idirect3d for now\n", This);
5858 return IWineD3D_GetDeviceCaps(This->wineD3D, This->adapterNo, This->devType, pCaps);
5861 static HRESULT WINAPI IWineD3DDeviceImpl_GetDisplayMode(IWineD3DDevice *iface, UINT iSwapChain, WINED3DDISPLAYMODE* pMode) {
5862 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5863 IWineD3DSwapChain *swapChain;
5866 if(iSwapChain > 0) {
5867 hr = IWineD3DDeviceImpl_GetSwapChain(iface, iSwapChain, (IWineD3DSwapChain **)&swapChain);
5868 if (hr == WINED3D_OK) {
5869 hr = IWineD3DSwapChain_GetDisplayMode(swapChain, pMode);
5870 IWineD3DSwapChain_Release(swapChain);
5872 FIXME("(%p) Error getting display mode\n", This);
5875 /* Don't read the real display mode,
5876 but return the stored mode instead. X11 can't change the color
5877 depth, and some apps are pretty angry if they SetDisplayMode from
5878 24 to 16 bpp and find out that GetDisplayMode still returns 24 bpp
5880 Also don't relay to the swapchain because with ddraw it's possible
5881 that there isn't a swapchain at all */
5882 pMode->Width = This->ddraw_width;
5883 pMode->Height = This->ddraw_height;
5884 pMode->Format = This->ddraw_format;
5885 pMode->RefreshRate = 0;
5892 static HRESULT WINAPI IWineD3DDeviceImpl_SetHWND(IWineD3DDevice *iface, HWND hWnd) {
5893 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5894 TRACE("(%p)->(%p)\n", This, hWnd);
5896 This->ddraw_window = hWnd;
5900 static HRESULT WINAPI IWineD3DDeviceImpl_GetHWND(IWineD3DDevice *iface, HWND *hWnd) {
5901 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5902 TRACE("(%p)->(%p)\n", This, hWnd);
5904 *hWnd = This->ddraw_window;
5909 * Stateblock related functions
5912 static HRESULT WINAPI IWineD3DDeviceImpl_BeginStateBlock(IWineD3DDevice *iface) {
5913 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5914 IWineD3DStateBlockImpl *object;
5915 HRESULT temp_result;
5917 TRACE("(%p)", This);
5919 if (This->isRecordingState) {
5920 return WINED3DERR_INVALIDCALL;
5923 object = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(IWineD3DStateBlockImpl));
5924 if (NULL == object ) {
5925 FIXME("(%p)Error allocating memory for stateblock\n", This);
5926 return E_OUTOFMEMORY;
5928 TRACE("(%p) created object %p\n", This, object);
5929 object->wineD3DDevice= This;
5930 /** FIXME: object->parent = parent; **/
5931 object->parent = NULL;
5932 object->blockType = WINED3DSBT_ALL;
5934 object->lpVtbl = &IWineD3DStateBlock_Vtbl;
5936 temp_result = allocate_shader_constants(object);
5937 if (WINED3D_OK != temp_result)
5940 IWineD3DStateBlock_Release((IWineD3DStateBlock*)This->updateStateBlock);
5941 This->updateStateBlock = object;
5942 This->isRecordingState = TRUE;
5944 TRACE("(%p) recording stateblock %p\n",This , object);
5948 static HRESULT WINAPI IWineD3DDeviceImpl_EndStateBlock(IWineD3DDevice *iface, IWineD3DStateBlock** ppStateBlock) {
5949 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5951 if (!This->isRecordingState) {
5952 FIXME("(%p) not recording! returning error\n", This);
5953 *ppStateBlock = NULL;
5954 return WINED3DERR_INVALIDCALL;
5957 *ppStateBlock = (IWineD3DStateBlock*)This->updateStateBlock;
5958 This->isRecordingState = FALSE;
5959 This->updateStateBlock = This->stateBlock;
5960 IWineD3DStateBlock_AddRef((IWineD3DStateBlock*)This->updateStateBlock);
5961 /* IWineD3DStateBlock_AddRef(*ppStateBlock); don't need to do this, since we should really just release UpdateStateBlock first */
5962 TRACE("(%p) returning token (ptr to stateblock) of %p\n", This, *ppStateBlock);
5967 * Scene related functions
5969 static HRESULT WINAPI IWineD3DDeviceImpl_BeginScene(IWineD3DDevice *iface) {
5970 /* At the moment we have no need for any functionality at the beginning
5972 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5973 TRACE("(%p) : stub\n", This);
5977 static HRESULT WINAPI IWineD3DDeviceImpl_EndScene(IWineD3DDevice *iface) {
5978 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5979 TRACE("(%p)\n", This);
5981 /* We only have to do this if we need to read the, swapbuffers performs a flush for us */
5983 checkGLcall("glFlush");
5985 TRACE("End Scene\n");
5986 if(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 D3DRECT* pRects,
6031 DWORD Flags, D3DCOLOR Color, float Z, DWORD Stencil) {
6032 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
6034 /* TODO: From MSDN This method fails if you specify the D3DCLEAR_ZBUFFER or D3DCLEAR_STENCIL flags when the
6035 render target does not have an attached depth buffer. Similarly, if you specify the D3DCLEAR_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 D3DRECT* curRect;
6045 TRACE("(%p) Count (%ld), pRects (%p), Flags (%lx), Z (%f), Stencil (%ld)\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 & D3DCLEAR_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 & D3DCLEAR_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 & D3DCLEAR_TARGET) {
6078 TRACE("Clearing screen with glClear to color %lx\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=(%ld,%ld)->(%ld,%ld) glRect=(%ld,%ld), len=%ld, hei=%ld\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(D3DRECT);
6120 /* Restore the old values (why..?) */
6121 if (Flags & D3DCLEAR_STENCIL) {
6122 glClearStencil(old_stencil_clear_value);
6123 glStencilMask(This->stateBlock->renderState[WINED3DRS_STENCILWRITEMASK]);
6125 if (Flags & D3DCLEAR_ZBUFFER) {
6126 glDepthMask(old_ztest);
6127 glClearDepth(old_z_clear_value);
6129 if (Flags & D3DCLEAR_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] & D3DCOLORWRITEENABLE_RED ? GL_TRUE : GL_FALSE,
6135 This->stateBlock->renderState[WINED3DRS_COLORWRITEENABLE] & D3DCOLORWRITEENABLE_GREEN ? GL_TRUE : GL_FALSE,
6136 This->stateBlock->renderState[WINED3DRS_COLORWRITEENABLE] & D3DCOLORWRITEENABLE_BLUE ? GL_TRUE : GL_FALSE,
6137 This->stateBlock->renderState[WINED3DRS_COLORWRITEENABLE] & D3DCOLORWRITEENABLE_ALPHA ? GL_TRUE : GL_FALSE);
6140 glDisable(GL_SCISSOR_TEST);
6141 checkGLcall("glDisable");
6150 static HRESULT WINAPI IWineD3DDeviceImpl_DrawPrimitive(IWineD3DDevice *iface, D3DPRIMITIVETYPE 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 D3DPRIMITIVETYPE 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, D3DPRIMITIVETYPE 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, D3DPRIMITIVETYPE 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, D3DPRIMITIVETYPE 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 = D3DCUBEMAP_FACE_POSITIVE_X; faceType <= D3DCUBEMAP_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");
6446 glReadPixels(surfaceGlDescription->target,
6447 surfaceGlDescription->level,
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 lock the destination, and copy the bits accross */
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 /* Used by DirectX 8 */
6831 static HRESULT WINAPI IWineD3DDeviceImpl_CopyRects(IWineD3DDevice *iface,
6832 IWineD3DSurface* pSourceSurface, CONST RECT* pSourceRectsArray, UINT cRects,
6833 IWineD3DSurface* pDestinationSurface, CONST POINT* pDestPointsArray) {
6835 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
6836 HRESULT hr = WINED3D_OK;
6837 WINED3DFORMAT srcFormat, destFormat;
6838 UINT srcWidth, destWidth;
6839 UINT srcHeight, destHeight;
6841 WINED3DSURFACE_DESC winedesc;
6843 TRACE("(%p) pSrcSur=%p, pSourceRects=%p, cRects=%d, pDstSur=%p, pDestPtsArr=%p\n", This,
6844 pSourceSurface, pSourceRectsArray, cRects, pDestinationSurface, pDestPointsArray);
6847 /* Check that the source texture is in WINED3DPOOL_SYSTEMMEM and the destination texture is in WINED3DPOOL_DEFAULT */
6848 memset(&winedesc, 0, sizeof(winedesc));
6850 winedesc.Format = &srcFormat;
6851 winedesc.Width = &srcWidth;
6852 winedesc.Height = &srcHeight;
6853 winedesc.Size = &srcSize;
6854 IWineD3DSurface_GetDesc(pSourceSurface, &winedesc);
6856 winedesc.Format = &destFormat;
6857 winedesc.Width = &destWidth;
6858 winedesc.Height = &destHeight;
6859 winedesc.Size = NULL;
6860 IWineD3DSurface_GetDesc(pDestinationSurface, &winedesc);
6862 /* Check that the source and destination formats match */
6863 if (srcFormat != destFormat && WINED3DFMT_UNKNOWN != destFormat) {
6864 WARN("(%p) source %p format must match the dest %p format, returning WINED3DERR_INVALIDCALL\n", This, pSourceSurface, pDestinationSurface);
6865 return WINED3DERR_INVALIDCALL;
6866 } else if (WINED3DFMT_UNKNOWN == destFormat) {
6867 TRACE("(%p) : Converting destination surface from WINED3DFMT_UNKNOWN to the source format\n", This);
6868 IWineD3DSurface_SetFormat(pDestinationSurface, srcFormat);
6869 destFormat = srcFormat;
6872 /* Quick if complete copy ... */
6873 if (cRects == 0 && pSourceRectsArray == NULL && pDestPointsArray == NULL) {
6875 if (srcWidth == destWidth && srcHeight == destHeight) {
6876 WINED3DLOCKED_RECT lrSrc;
6877 WINED3DLOCKED_RECT lrDst;
6878 IWineD3DSurface_LockRect(pSourceSurface, &lrSrc, NULL, WINED3DLOCK_READONLY);
6879 IWineD3DSurface_LockRect(pDestinationSurface, &lrDst, NULL, 0L);
6880 TRACE("Locked src and dst, Direct copy as surfaces are equal, w=%d, h=%d\n", srcWidth, srcHeight);
6882 memcpy(lrDst.pBits, lrSrc.pBits, srcSize);
6884 IWineD3DSurface_UnlockRect(pSourceSurface);
6885 IWineD3DSurface_UnlockRect(pDestinationSurface);
6886 TRACE("Unlocked src and dst\n");
6890 FIXME("Wanted to copy all surfaces but size not compatible, returning WINED3DERR_INVALIDCALL\n");
6891 hr = WINED3DERR_INVALIDCALL;
6896 if (NULL != pSourceRectsArray && NULL != pDestPointsArray) {
6898 int bytesPerPixel = ((IWineD3DSurfaceImpl *) pSourceSurface)->bytesPerPixel;
6901 /* Copy rect by rect */
6902 for (i = 0; i < cRects; ++i) {
6903 CONST RECT* r = &pSourceRectsArray[i];
6904 CONST POINT* p = &pDestPointsArray[i];
6907 WINED3DLOCKED_RECT lrSrc;
6908 WINED3DLOCKED_RECT lrDst;
6911 TRACE("Copying rect %d (%ld,%ld),(%ld,%ld) -> (%ld,%ld)\n", i, r->left, r->top, r->right, r->bottom, p->x, p->y);
6912 if (srcFormat == WINED3DFMT_DXT1) {
6913 copyperline = ((r->right - r->left) * bytesPerPixel) / 2; /* DXT1 is half byte per pixel */
6915 copyperline = ((r->right - r->left) * bytesPerPixel);
6918 IWineD3DSurface_LockRect(pSourceSurface, &lrSrc, r, WINED3DLOCK_READONLY);
6919 dest_rect.left = p->x;
6920 dest_rect.top = p->y;
6921 dest_rect.right = p->x + (r->right - r->left);
6922 dest_rect.bottom= p->y + (r->bottom - r->top);
6923 IWineD3DSurface_LockRect(pDestinationSurface, &lrDst, &dest_rect, 0L);
6924 TRACE("Locked src and dst\n");
6926 /* Find where to start */
6927 for (j = 0; j < (r->bottom - r->top - 1); ++j) {
6928 memcpy((char*) lrDst.pBits + (j * lrDst.Pitch), (char*) lrSrc.pBits + (j * lrSrc.Pitch), copyperline);
6930 IWineD3DSurface_UnlockRect(pSourceSurface);
6931 IWineD3DSurface_UnlockRect(pDestinationSurface);
6932 TRACE("Unlocked src and dst\n");
6936 int bytesPerPixel = ((IWineD3DSurfaceImpl *) pSourceSurface)->bytesPerPixel;
6939 WINED3DLOCKED_RECT lrSrc;
6940 WINED3DLOCKED_RECT lrDst;
6943 for(i=0; i < cRects; i++) {
6944 CONST RECT* r = &pSourceRectsArray[i];
6946 TRACE("Copying rect %d (%ld,%ld),(%ld,%ld) -> (0, 0)\n", i, r->left, r->top, r->right, r->bottom);
6947 if (srcFormat == WINED3DFMT_DXT1) {
6948 copyperline = ((r->right - r->left) * bytesPerPixel) / 2; /* DXT1 is half byte per pixel */
6950 copyperline = ((r->right - r->left) * bytesPerPixel);
6952 IWineD3DSurface_LockRect(pSourceSurface, &lrSrc, r, WINED3DLOCK_READONLY);
6955 dest_rect.right = r->right - r->left;
6956 dest_rect.bottom= r->bottom - r->top;
6957 IWineD3DSurface_LockRect(pDestinationSurface, &lrDst, &dest_rect, 0L);
6958 TRACE("Locked src and dst\n");
6959 /* Find where to start */
6960 for (j = 0; j < (r->bottom - r->top - 1); ++j) {
6961 memcpy((char*) lrDst.pBits + (j * lrDst.Pitch), (char*) lrSrc.pBits + (j * lrSrc.Pitch), copyperline);
6963 IWineD3DSurface_UnlockRect(pSourceSurface);
6964 IWineD3DSurface_UnlockRect(pDestinationSurface);
6965 TRACE("Unlocked src and dst\n");
6973 /* Implementation details at http://developer.nvidia.com/attach/6494
6975 http://oss.sgi.com/projects/ogl-sample/registry/NV/evaluators.txt
6976 hmm.. no longer supported use
6977 OpenGL evaluators or tessellate surfaces within your application.
6980 /* http://msdn.microsoft.com/library/default.asp?url=/library/en-us/directx9_c/directx/graphics/reference/d3d/interfaces/idirect3ddevice9/DrawRectPatch.asp */
6981 static HRESULT WINAPI IWineD3DDeviceImpl_DrawRectPatch(IWineD3DDevice *iface, UINT Handle, CONST float* pNumSegs, CONST WINED3DRECTPATCH_INFO* pRectPatchInfo) {
6982 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
6983 TRACE("(%p) Handle(%d) noSegs(%p) rectpatch(%p)\n", This, Handle, pNumSegs, pRectPatchInfo);
6984 FIXME("(%p) : Stub\n", This);
6989 /* http://msdn.microsoft.com/library/default.asp?url=/library/en-us/directx9_c/directx/graphics/reference/d3d/interfaces/idirect3ddevice9/DrawTriPatch.asp */
6990 static HRESULT WINAPI IWineD3DDeviceImpl_DrawTriPatch(IWineD3DDevice *iface, UINT Handle, CONST float* pNumSegs, CONST WINED3DTRIPATCH_INFO* pTriPatchInfo) {
6991 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
6992 TRACE("(%p) Handle(%d) noSegs(%p) tripatch(%p)\n", This, Handle, pNumSegs, pTriPatchInfo);
6993 FIXME("(%p) : Stub\n", This);
6997 static HRESULT WINAPI IWineD3DDeviceImpl_DeletePatch(IWineD3DDevice *iface, UINT Handle) {
6998 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
6999 TRACE("(%p) Handle(%d)\n", This, Handle);
7000 FIXME("(%p) : Stub\n", This);
7004 static HRESULT WINAPI IWineD3DDeviceImpl_ColorFill(IWineD3DDevice *iface, IWineD3DSurface *pSurface, CONST D3DRECT* pRect, D3DCOLOR color) {
7005 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *) iface;
7006 IWineD3DSurfaceImpl *surface = (IWineD3DSurfaceImpl *) pSurface;
7008 TRACE("(%p) Colour fill Surface: %p rect: %p color: %ld\n", This, pSurface, pRect, color);
7010 if (surface->resource.pool != WINED3DPOOL_DEFAULT && surface->resource.pool != WINED3DPOOL_SYSTEMMEM) {
7011 FIXME("call to colorfill with non WINED3DPOOL_DEFAULT or WINED3DPOOL_SYSTEMMEM surface\n");
7012 return WINED3DERR_INVALIDCALL;
7015 /* Just forward this to the DirectDraw blitting engine */
7016 memset(&BltFx, 0, sizeof(BltFx));
7017 BltFx.dwSize = sizeof(BltFx);
7018 BltFx.u5.dwFillColor = color;
7019 return IWineD3DSurface_Blt(pSurface, (RECT *) pRect, NULL, NULL, DDBLT_COLORFILL, &BltFx);
7022 /* rendertarget and deptth stencil functions */
7023 static HRESULT WINAPI IWineD3DDeviceImpl_GetRenderTarget(IWineD3DDevice* iface,DWORD RenderTargetIndex, IWineD3DSurface **ppRenderTarget) {
7024 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
7026 /* FIXME: Implelent RenderTargetIndex >0 */
7027 if(RenderTargetIndex > 0)
7028 FIXME("(%p) : RenderTargetIndex %ld >0 not currently supported\n", This, RenderTargetIndex);
7030 *ppRenderTarget = This->renderTarget;
7031 TRACE("(%p) : RenderTarget %ld Index returning %p\n", This, RenderTargetIndex, *ppRenderTarget);
7032 /* Note inc ref on returned surface */
7033 if(*ppRenderTarget != NULL)
7034 IWineD3DSurface_AddRef(*ppRenderTarget);
7038 static HRESULT WINAPI IWineD3DDeviceImpl_SetFrontBackBuffers(IWineD3DDevice *iface, IWineD3DSurface *Front, IWineD3DSurface *Back) {
7039 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
7040 IWineD3DSurfaceImpl *FrontImpl = (IWineD3DSurfaceImpl *) Front;
7041 IWineD3DSurfaceImpl *BackImpl = (IWineD3DSurfaceImpl *) Back;
7042 IWineD3DSwapChainImpl *Swapchain;
7045 TRACE("(%p)->(%p,%p)\n", This, FrontImpl, BackImpl);
7047 hr = IWineD3DDevice_GetSwapChain(iface, 0, (IWineD3DSwapChain **) &Swapchain);
7048 if(hr != WINED3D_OK) {
7049 ERR("Can't get the swapchain\n");
7053 /* Make sure to release the swapchain */
7054 IWineD3DSwapChain_Release((IWineD3DSwapChain *) Swapchain);
7056 if(FrontImpl && !(FrontImpl->resource.usage & WINED3DUSAGE_RENDERTARGET) ) {
7057 ERR("Trying to set a front buffer which doesn't have WINED3DUSAGE_RENDERTARGET usage\n");
7058 return WINED3DERR_INVALIDCALL;
7060 else if(BackImpl && !(BackImpl->resource.usage & WINED3DUSAGE_RENDERTARGET)) {
7061 ERR("Trying to set a back buffer which doesn't have WINED3DUSAGE_RENDERTARGET usage\n");
7062 return WINED3DERR_INVALIDCALL;
7065 if(Swapchain->frontBuffer != Front) {
7066 TRACE("Changing the front buffer from %p to %p\n", Swapchain->frontBuffer, Front);
7068 if(Swapchain->frontBuffer)
7069 IWineD3DSurface_SetContainer(Swapchain->frontBuffer, NULL);
7070 Swapchain->frontBuffer = Front;
7072 if(Swapchain->frontBuffer) {
7073 IWineD3DSurface_SetContainer(Swapchain->frontBuffer, (IWineD3DBase *) Swapchain);
7077 if(Back && !Swapchain->backBuffer) {
7078 /* We need memory for the back buffer array - only one back buffer this way */
7079 Swapchain->backBuffer = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(IWineD3DSurface *));
7080 if(!Swapchain->backBuffer) {
7081 ERR("Out of memory\n");
7082 return E_OUTOFMEMORY;
7086 if(Swapchain->backBuffer[0] != Back) {
7087 TRACE("Changing the back buffer from %p to %p\n", Swapchain->backBuffer, Back);
7089 if(!Swapchain->backBuffer[0]) {
7090 /* GL was told to draw to the front buffer at creation,
7093 glDrawBuffer(GL_BACK);
7094 checkGLcall("glDrawBuffer(GL_BACK)");
7095 /* Set the backbuffer count to 1 because other code uses it to fing the back buffers */
7096 Swapchain->presentParms.BackBufferCount = 1;
7098 /* That makes problems - disable for now */
7099 /* glDrawBuffer(GL_FRONT); */
7100 checkGLcall("glDrawBuffer(GL_FRONT)");
7101 /* We have lost our back buffer, set this to 0 to avoid confusing other code */
7102 Swapchain->presentParms.BackBufferCount = 0;
7106 if(Swapchain->backBuffer[0])
7107 IWineD3DSurface_SetContainer(Swapchain->backBuffer[0], NULL);
7108 Swapchain->backBuffer[0] = Back;
7110 if(Swapchain->backBuffer[0]) {
7111 IWineD3DSurface_SetContainer(Swapchain->backBuffer[0], (IWineD3DBase *) Swapchain);
7113 HeapFree(GetProcessHeap(), 0, Swapchain->backBuffer);
7121 static HRESULT WINAPI IWineD3DDeviceImpl_GetDepthStencilSurface(IWineD3DDevice* iface, IWineD3DSurface **ppZStencilSurface) {
7122 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
7123 *ppZStencilSurface = This->depthStencilBuffer;
7124 TRACE("(%p) : zStencilSurface returning %p\n", This, *ppZStencilSurface);
7126 if(*ppZStencilSurface != NULL) {
7127 /* Note inc ref on returned surface */
7128 IWineD3DSurface_AddRef(*ppZStencilSurface);
7133 /* internal static helper functions */
7134 static HRESULT WINAPI IWineD3DDeviceImpl_ActiveRender(IWineD3DDevice* iface,
7135 IWineD3DSurface *RenderSurface);
7137 static HRESULT WINAPI IWineD3DDeviceImpl_SetRenderTarget(IWineD3DDevice *iface, DWORD RenderTargetIndex, IWineD3DSurface *pRenderTarget) {
7138 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
7139 HRESULT hr = WINED3D_OK;
7140 WINED3DVIEWPORT viewport;
7142 TRACE("(%p) Swapping rendertarget\n",This);
7143 if (RenderTargetIndex > 0) {
7144 FIXME("(%p) Render targets other than the first are not supported\n",This);
7145 RenderTargetIndex = 0;
7148 /* MSDN says that null disables the render target
7149 but a device must always be associated with a render target
7150 nope MSDN says that we return invalid call to a null rendertarget with an index of 0
7152 see http://msdn.microsoft.com/library/default.asp?url=/library/en-us/directx9_c/directx/graphics/programmingguide/AdvancedTopics/PixelPipe/MultipleRenderTarget.asp
7155 if (RenderTargetIndex == 0 && pRenderTarget == NULL) {
7156 FIXME("Trying to set render target 0 to NULL\n");
7157 return WINED3DERR_INVALIDCALL;
7159 /* TODO: replace Impl* usage with interface usage */
7160 if (!((IWineD3DSurfaceImpl *)pRenderTarget)->resource.usage & WINED3DUSAGE_RENDERTARGET) {
7161 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);
7162 return WINED3DERR_INVALIDCALL;
7164 /** TODO: check that the depth stencil format matches the render target, this is only done in debug
7165 * builds, but I think wine counts as a 'debug' build for now.
7166 ******************************/
7167 /* If we are trying to set what we already have, don't bother */
7168 if (pRenderTarget == This->renderTarget) {
7169 TRACE("Trying to do a NOP SetRenderTarget operation\n");
7171 /* Otherwise, set the render target up */
7173 if (FALSE == This->sceneEnded) {
7174 IWineD3DDevice_EndScene(iface);
7176 TRACE("clearing renderer\n");
7177 /* IWineD3DDeviceImpl_CleanRender(iface); */
7178 /* OpenGL doesn't support 'sharing' of the stencilBuffer so we may incure an extra memory overhead
7179 depending on the renter target implementation being used.
7180 A shared context implementation will share all buffers between all rendertargets (including swapchains),
7181 implementations that use separate pbuffers for different swapchains or rendertargets will have to duplicate the
7182 stencil buffer and incure an extra memory overhead */
7183 hr = IWineD3DDeviceImpl_ActiveRender(iface, pRenderTarget);
7186 if (SUCCEEDED(hr)) {
7187 /* Finally, reset the viewport as the MSDN states. */
7188 /* TODO: Replace impl usage */
7189 viewport.Height = ((IWineD3DSurfaceImpl *)This->renderTarget)->currentDesc.Height;
7190 viewport.Width = ((IWineD3DSurfaceImpl *)This->renderTarget)->currentDesc.Width;
7193 viewport.MaxZ = 1.0f;
7194 viewport.MinZ = 0.0f;
7195 IWineD3DDeviceImpl_SetViewport(iface, &viewport);
7197 FIXME("Unknown error setting the render target\n");
7199 This->sceneEnded = FALSE;
7203 static HRESULT WINAPI IWineD3DDeviceImpl_SetDepthStencilSurface(IWineD3DDevice *iface, IWineD3DSurface *pNewZStencil) {
7204 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
7205 HRESULT hr = WINED3D_OK;
7206 IWineD3DSurface *tmp;
7208 TRACE("(%p) Swapping z-buffer\n",This);
7210 if (pNewZStencil == This->stencilBufferTarget) {
7211 TRACE("Trying to do a NOP SetRenderTarget operation\n");
7213 /** OpenGL doesn't support 'sharing' of the stencilBuffer so we may incure an extra memory overhead
7214 * depending on the renter target implementation being used.
7215 * A shared context implementation will share all buffers between all rendertargets (including swapchains),
7216 * implementations that use separate pbuffers for different swapchains or rendertargets will have to duplicate the
7217 * stencil buffer and incure an extra memory overhead
7218 ******************************************************/
7221 tmp = This->stencilBufferTarget;
7222 This->stencilBufferTarget = pNewZStencil;
7223 /* should we be calling the parent or the wined3d surface? */
7224 if (NULL != This->stencilBufferTarget) IWineD3DSurface_AddRef(This->stencilBufferTarget);
7225 if (NULL != tmp) IWineD3DSurface_Release(tmp);
7227 /** TODO: glEnable/glDisable on depth/stencil depending on
7228 * pNewZStencil is NULL and the depth/stencil is enabled in d3d
7229 **********************************************************/
7236 #ifdef GL_VERSION_1_3
7237 /* Internal functions not in DirectX */
7238 /** TODO: move this off to the opengl context manager
7239 *(the swapchain doesn't need to know anything about offscreen rendering!)
7240 ****************************************************/
7242 static HRESULT WINAPI IWineD3DDeviceImpl_CleanRender(IWineD3DDevice* iface, IWineD3DSwapChainImpl *swapchain)
7244 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
7246 TRACE("(%p), %p\n", This, swapchain);
7248 if (swapchain->win != swapchain->drawable) {
7249 /* Set everything back the way it ws */
7250 swapchain->render_ctx = swapchain->glCtx;
7251 swapchain->drawable = swapchain->win;
7256 /* TODO: move this off into a context manager so that GLX_ATI_render_texture and other types of surface can be used. */
7257 static HRESULT WINAPI IWineD3DDeviceImpl_FindGLContext(IWineD3DDevice *iface, IWineD3DSurface *pSurface, glContext **context) {
7258 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
7261 unsigned int height;
7262 WINED3DFORMAT format;
7263 WINED3DSURFACE_DESC surfaceDesc;
7264 memset(&surfaceDesc, 0, sizeof(surfaceDesc));
7265 surfaceDesc.Width = &width;
7266 surfaceDesc.Height = &height;
7267 surfaceDesc.Format = &format;
7268 IWineD3DSurface_GetDesc(pSurface, &surfaceDesc);
7270 /* I need a get width/height function (and should do something with the format) */
7271 for (i = 0; i < CONTEXT_CACHE; ++i) {
7272 /** NOTE: the contextCache[i].pSurface == pSurface check ceates onepbuffer per surface
7273 ATI cards don't destroy pbuffers, but as soon as resource releasing callbacks are inplace
7274 the pSurface can be set to 0 allowing it to be reused from cache **/
7275 if (This->contextCache[i].Width == width && This->contextCache[i].Height == height
7276 && (pbuffer_per_surface == FALSE || This->contextCache[i].pSurface == pSurface || This->contextCache[i].pSurface == NULL)) {
7277 *context = &This->contextCache[i];
7280 if (This->contextCache[i].Width == 0) {
7281 This->contextCache[i].pSurface = pSurface;
7282 This->contextCache[i].Width = width;
7283 This->contextCache[i].Height = height;
7284 *context = &This->contextCache[i];
7288 if (i == CONTEXT_CACHE) {
7289 int minUsage = 0x7FFFFFFF; /* MAX_INT */
7290 glContext *dropContext = 0;
7291 for (i = 0; i < CONTEXT_CACHE; i++) {
7292 if (This->contextCache[i].usedcount < minUsage) {
7293 dropContext = &This->contextCache[i];
7294 minUsage = This->contextCache[i].usedcount;
7297 /* clean up the context (this doesn't work for ATI at the moment */
7299 glXDestroyContext(swapchain->display, dropContext->context);
7300 glXDestroyPbuffer(swapchain->display, dropContext->drawable);
7303 dropContext->Width = 0;
7304 dropContext->pSurface = pSurface;
7305 *context = dropContext;
7307 if (++This->contextCache[i].usedcount == 0x7FFFFFFF /* MAX_INT */ - 1 ) {
7308 for (i = 0; i < CONTEXT_CACHE; i++) {
7309 This->contextCache[i].usedcount = max(0, This->contextCache[i].usedcount - (0x7FFFFFFF /* MAX_INT */ >> 1));
7313 if (*context != NULL)
7316 return E_OUTOFMEMORY;
7320 /** FIXME: This is currently used called whenever SetRenderTarget or SetStencilBuffer are called
7321 * the functionality needs splitting up so that we don't do more than we should do.
7322 * this only seems to impact performance a little.
7323 ******************************/
7324 static HRESULT WINAPI IWineD3DDeviceImpl_ActiveRender(IWineD3DDevice* iface,
7325 IWineD3DSurface *RenderSurface) {
7326 HRESULT ret = WINED3DERR_INVALIDCALL;
7328 IWineD3DStateBlockImpl *oldUpdateStateBlock;
7331 * Currently only active for GLX >= 1.3
7332 * for others versions we'll have to use GLXPixmaps
7334 * normally we must test GLX_VERSION_1_3 but nvidia headers are not correct
7335 * as they implement GLX 1.3 but only define GLX_VERSION_1_2
7336 * so only check OpenGL version
7337 * ..........................
7338 * I don't believe that it is a problem with NVidia headers,
7339 * XFree only supports GLX1.2, nVidia (and ATI to some extent) provide 1.3 functions
7340 * in GLX 1.2, there is no mention of the correct way to tell if the extensions are provided.
7342 * Your application will report GLX version 1.2 on glXQueryVersion.
7343 * However, it is safe to call the GLX 1.3 functions as described below.
7345 #if defined(GL_VERSION_1_3)
7347 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
7348 IWineD3DSurface *StencilSurface = This->stencilBufferTarget;
7349 IWineD3DSurface *tmp;
7350 /** TODO: we only need to look up the configuration !IF! we are setting the target to a texture **/
7351 GLXFBConfig* cfgs = NULL;
7355 IWineD3DSwapChain *currentSwapchain;
7356 IWineD3DSwapChainImpl *swapchain;
7357 /** TODO: get rid of Impl usage we should always create a zbuffer/stencil with our contexts if possible,
7358 * but switch them off if the StencilSurface is set to NULL
7359 ** *********************************************************/
7360 D3DFORMAT BackBufferFormat = ((IWineD3DSurfaceImpl *) RenderSurface)->resource.format;
7361 D3DFORMAT StencilBufferFormat = (NULL != StencilSurface) ? ((IWineD3DSurfaceImpl *) StencilSurface)->resource.format : 0;
7364 if StencilSurface == NULL && zBufferTarget != NULL then switch the zbuffer off,
7365 it StencilSurface != NULL && zBufferTarget == NULL switch it on
7368 #define PUSH1(att) attribs[nAttribs++] = (att);
7369 #define PUSH2(att,value) attribs[nAttribs++] = (att); attribs[nAttribs++] = (value);
7371 /* PUSH2(GLX_BIND_TO_TEXTURE_RGBA_ATI, True); examples of this are few and far between (but I've got a nice working one!)*/
7373 /** TODO: remove the reff to Impl (context manager should fix this!) **/
7374 IWineD3DSwapChainImpl *impSwapChain;
7375 IWineD3DDevice_GetSwapChain(iface, 0, (IWineD3DSwapChain **)&impSwapChain);
7376 if (NULL == impSwapChain) { /* NOTE: This should NEVER fail */
7377 ERR("(%p) Failed to get a the implicit swapchain\n", iface);
7382 PUSH2(GLX_DRAWABLE_TYPE, GLX_PBUFFER_BIT);
7383 PUSH2(GLX_X_RENDERABLE, TRUE);
7384 PUSH2(GLX_DOUBLEBUFFER, TRUE);
7385 TRACE("calling makeglcfg\n");
7386 D3DFmtMakeGlCfg(BackBufferFormat, StencilBufferFormat, attribs, &nAttribs, FALSE /* alternate */);
7389 TRACE("calling chooseFGConfig\n");
7390 cfgs = glXChooseFBConfig(impSwapChain->display, DefaultScreen(impSwapChain->display),
7393 if (!cfgs) { /* OK we didn't find the exact config, so use any reasonable match */
7394 /* TODO: fill in the 'requested' and 'current' depths, also make sure that's
7395 why we failed and only show this message once! */
7396 MESSAGE("Failed to find exact match, finding alternative but you may suffer performance issues, try changing xfree's depth to match the requested depth\n"); /**/
7398 PUSH2(GLX_DRAWABLE_TYPE, GLX_PBUFFER_BIT | GLX_WINDOW_BIT);
7399 /* PUSH2(GLX_X_RENDERABLE, TRUE); */
7400 PUSH2(GLX_RENDER_TYPE, GLX_RGBA_BIT);
7401 PUSH2(GLX_DOUBLEBUFFER, FALSE);
7402 TRACE("calling makeglcfg\n");
7403 D3DFmtMakeGlCfg(BackBufferFormat, StencilBufferFormat, attribs, &nAttribs, TRUE /* alternate */);
7405 cfgs = glXChooseFBConfig(impSwapChain->display, DefaultScreen(impSwapChain->display),
7412 for (i = 0; i < nCfgs; ++i) {
7413 TRACE("for (%u,%s)/(%u,%s) found config[%d]@%p\n", BackBufferFormat,
7414 debug_d3dformat(BackBufferFormat), StencilBufferFormat,
7415 debug_d3dformat(StencilBufferFormat), i, cfgs[i]);
7418 if (NULL != This->renderTarget) {
7420 vcheckGLcall("glFlush");
7421 /** This is only useful if the old render target was a swapchain,
7422 * we need to supercede this with a function that displays
7423 * the current buffer on the screen. This is easy to do in glx1.3 but
7424 * we need to do copy-write pixels in glx 1.2.
7425 ************************************************/
7426 glXSwapBuffers(impSwapChain->display, impSwapChain->drawable);
7428 printf("Hit Enter to get next frame ...\n");
7434 if (IWineD3DSurface_GetContainer(This->renderTarget, &IID_IWineD3DSwapChain, (void **)¤tSwapchain) != WINED3D_OK) {
7435 /* the selected render target doesn't belong to a swapchain, so use the devices implicit swapchain */
7436 IWineD3DDevice_GetSwapChain(iface, 0, ¤tSwapchain);
7440 * TODO: remove the use of IWineD3DSwapChainImpl, a context manager will help since it will replace the
7441 * renderTarget = swapchain->backBuffer[i] bit and anything to do with *glContexts
7442 **********************************************************************/
7443 if (IWineD3DSurface_GetContainer(RenderSurface, &IID_IWineD3DSwapChain, (void **)&swapchain) == WINED3D_OK) {
7444 /* We also need to make sure that the lights &co are also in the context of the swapchains */
7445 /* FIXME: If the render target gets sent to the frontBuffer should be be presenting it raw? */
7446 TRACE("making swapchain active\n");
7447 if (RenderSurface != This->renderTarget) {
7448 BOOL backbuf = FALSE;
7451 for(i = 0; i < swapchain->presentParms.BackBufferCount; i++) {
7452 if(RenderSurface == swapchain->backBuffer[i]) {
7460 /* This could be flagged so that some operations work directly with the front buffer */
7461 FIXME("Attempting to set the renderTarget to the frontBuffer\n");
7463 if (glXMakeCurrent(swapchain->display, swapchain->win, swapchain->glCtx)
7465 TRACE("Error in setting current context: context %p drawable %ld !\n",
7466 impSwapChain->glCtx, impSwapChain->win);
7469 IWineD3DDeviceImpl_CleanRender(iface, (IWineD3DSwapChainImpl *)currentSwapchain);
7471 checkGLcall("glXMakeContextCurrent");
7473 IWineD3DSwapChain_Release((IWineD3DSwapChain *)swapchain);
7475 else if (pbuffer_support && cfgs != NULL /* && some test to make sure that opengl supports pbuffers */) {
7477 /** ********************************************************************
7478 * This is a quickly hacked out implementation of offscreen textures.
7479 * It will work in most cases but there may be problems if the client
7480 * modifies the texture directly, or expects the contents of the rendertarget
7483 * There are some real speed vs compatibility issues here:
7484 * we should really use a new context for every texture, but that eats ram.
7485 * we should also be restoring the texture to the pbuffer but that eats CPU
7486 * we can also 'reuse' the current pbuffer if the size is larger than the requested buffer,
7487 * but if this means reusing the display backbuffer then we need to make sure that
7488 * states are correctly preserved.
7489 * In many cases I would expect that we can 'skip' some functions, such as preserving states,
7490 * and gain a good performance increase at the cost of compatibility.
7491 * I would suggest that, when this is the case, a user configurable flag be made
7492 * available, allowing the user to choose the best emulated experience for them.
7493 *********************************************************************/
7495 XVisualInfo *visinfo;
7496 glContext *newContext;
7498 /* Here were using a shared context model */
7499 if (WINED3D_OK != IWineD3DDeviceImpl_FindGLContext(iface, RenderSurface, &newContext)) {
7500 FIXME("(%p) : Failed to find a context for surface %p\n", iface, RenderSurface);
7503 /* If the context doesn't exist then create a new one */
7504 /* TODO: This should really be part of findGlContext */
7505 if (NULL == newContext->context) {
7507 TRACE("making new buffer\n");
7509 PUSH2(GLX_PBUFFER_WIDTH, newContext->Width);
7510 PUSH2(GLX_PBUFFER_HEIGHT, newContext->Height);
7513 newContext->drawable = glXCreatePbuffer(impSwapChain->display, cfgs[0], attribs);
7515 /** ****************************************
7516 *GLX1.3 isn't supported by XFree 'yet' until that point ATI emulates pBuffers
7518 * In future releases, we may provide the calls glXCreateNewContext,
7519 * glXQueryDrawable and glXMakeContextCurrent.
7520 * so until then we have to use glXGetVisualFromFBConfig &co..
7521 ********************************************/
7524 visinfo = glXGetVisualFromFBConfig(impSwapChain->display, cfgs[0]);
7526 ERR("Error: couldn't get an RGBA, double-buffered visual\n");
7528 newContext->context = glXCreateContext(impSwapChain->display, visinfo, impSwapChain->glCtx, GL_TRUE);
7532 if (NULL == newContext || NULL == newContext->context) {
7533 ERR("(%p) : Failed to find a context for surface %p\n", iface, RenderSurface);
7535 /* Debug logging, (this function leaks), change to a TRACE when the leak is plugged */
7536 if (glXMakeCurrent(impSwapChain->display, newContext->drawable, newContext->context) == False) {
7537 TRACE("Error in setting current context: context %p drawable %ld\n", newContext->context, newContext->drawable);
7540 /* Clean up the old context */
7541 IWineD3DDeviceImpl_CleanRender(iface, (IWineD3DSwapChainImpl *)currentSwapchain);
7542 /* Set the current context of the swapchain to the new context */
7543 impSwapChain->drawable = newContext->drawable;
7544 impSwapChain->render_ctx = newContext->context;
7548 /* Disable recording, and apply the stateblock to the new context
7549 * FIXME: This is a bit of a hack, each context should know it's own state,
7550 * the directX current directX state should then be applied to the context */
7551 oldUpdateStateBlock = This->updateStateBlock;
7552 oldRecording= This->isRecordingState;
7553 This->isRecordingState = FALSE;
7554 This->updateStateBlock = This->stateBlock;
7555 IWineD3DStateBlock_Apply((IWineD3DStateBlock *)This->stateBlock);
7557 /* clean up the current rendertargets swapchain (if it belonged to one) */
7558 if (currentSwapchain != NULL) {
7559 IWineD3DSwapChain_Release((IWineD3DSwapChain *)currentSwapchain);
7562 /* Were done with the opengl context management, setup the rendertargets */
7564 tmp = This->renderTarget;
7565 This->renderTarget = RenderSurface;
7566 IWineD3DSurface_AddRef(This->renderTarget);
7567 IWineD3DSurface_Release(tmp);
7572 /* The surface must be rendered upside down to cancel the flip produce by glCopyTexImage */
7573 /* Check that the container is not a swapchain member */
7575 IWineD3DSwapChain *tmpSwapChain;
7576 if (WINED3D_OK != IWineD3DSurface_GetContainer(This->renderTarget, &IID_IWineD3DSwapChain, (void **)&tmpSwapChain)) {
7577 This->renderUpsideDown = TRUE;
7579 This->renderUpsideDown = FALSE;
7580 IWineD3DSwapChain_Release(tmpSwapChain);
7582 /* Force updating the cull mode */
7583 TRACE("setting render state\n");
7584 IWineD3DDevice_GetRenderState(iface, WINED3DRS_CULLMODE, &value);
7585 IWineD3DDevice_SetRenderState(iface, WINED3DRS_CULLMODE, value);
7587 /* Force updating projection matrix */
7588 This->last_was_rhw = FALSE;
7589 This->proj_valid = FALSE;
7592 /* Restore recording state */
7593 This->isRecordingState = oldRecording;
7594 This->updateStateBlock = oldUpdateStateBlock;
7601 ERR("cannot get valides GLXFBConfig for (%u,%s)/(%u,%s)\n", BackBufferFormat,
7602 debug_d3dformat(BackBufferFormat), StencilBufferFormat, debug_d3dformat(StencilBufferFormat));
7607 if ( NULL != impSwapChain) {
7608 IWineD3DSwapChain_Release((IWineD3DSwapChain *)impSwapChain);
7616 static HRESULT WINAPI IWineD3DDeviceImpl_SetCursorProperties(IWineD3DDevice* iface, UINT XHotSpot,
7617 UINT YHotSpot, IWineD3DSurface *pCursorBitmap) {
7618 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *) iface;
7619 /* TODO: the use of Impl is deprecated. */
7620 IWineD3DSurfaceImpl * pSur = (IWineD3DSurfaceImpl *) pCursorBitmap;
7622 TRACE("(%p) : Spot Pos(%u,%u)\n", This, XHotSpot, YHotSpot);
7624 /* some basic validation checks */
7625 if(This->cursorTexture) {
7627 glDeleteTextures(1, &This->cursorTexture);
7629 This->cursorTexture = 0;
7633 /* MSDN: Cursor must be A8R8G8B8 */
7634 if (WINED3DFMT_A8R8G8B8 != pSur->resource.format) {
7635 ERR("(%p) : surface(%p) has an invalid format\n", This, pCursorBitmap);
7636 return WINED3DERR_INVALIDCALL;
7639 /* MSDN: Cursor must be smaller than the display mode */
7640 if(pSur->currentDesc.Width > This->ddraw_width ||
7641 pSur->currentDesc.Height > This->ddraw_height) {
7642 ERR("(%p) : Surface(%p) is %dx%d pixels, but screen res is %ldx%ld\n", This, pSur, pSur->currentDesc.Width, pSur->currentDesc.Height, This->ddraw_width, This->ddraw_height);
7643 return WINED3DERR_INVALIDCALL;
7646 /* TODO: MSDN: Cursor sizes must be a power of 2 */
7647 /* This is to tell our texture code to load a SCRATCH surface. This allows us to use out
7648 * Texture and Blitting code to draw the cursor
7650 pSur->Flags |= SFLAG_FORCELOAD;
7651 IWineD3DSurface_PreLoad(pCursorBitmap);
7652 pSur->Flags &= ~SFLAG_FORCELOAD;
7653 /* Do not store the surface's pointer because the application may release
7654 * it after setting the cursor image. Windows doesn't addref the set surface, so we can't
7655 * do this either without creating circular refcount dependencies. Copy out the gl texture instead.
7657 This->cursorTexture = pSur->glDescription.textureName;
7658 This->cursorWidth = pSur->currentDesc.Width;
7659 This->cursorHeight = pSur->currentDesc.Height;
7660 pSur->glDescription.textureName = 0; /* Prevent the texture from being changed or deleted */
7663 This->xHotSpot = XHotSpot;
7664 This->yHotSpot = YHotSpot;
7668 static void WINAPI IWineD3DDeviceImpl_SetCursorPosition(IWineD3DDevice* iface, int XScreenSpace, int YScreenSpace, DWORD Flags) {
7669 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *) iface;
7670 TRACE("(%p) : SetPos to (%u,%u)\n", This, XScreenSpace, YScreenSpace);
7672 This->xScreenSpace = XScreenSpace;
7673 This->yScreenSpace = YScreenSpace;
7679 static BOOL WINAPI IWineD3DDeviceImpl_ShowCursor(IWineD3DDevice* iface, BOOL bShow) {
7680 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *) iface;
7681 BOOL oldVisible = This->bCursorVisible;
7682 TRACE("(%p) : visible(%d)\n", This, bShow);
7684 if(This->cursorTexture)
7685 This->bCursorVisible = bShow;
7690 static HRESULT WINAPI IWineD3DDeviceImpl_TestCooperativeLevel(IWineD3DDevice* iface) {
7691 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *) iface;
7692 TRACE("(%p) : state (%lu)\n", This, This->state);
7693 /* TODO: Implement wrapping of the WndProc so that mimimize and maxamise can be monitored and the states adjusted. */
7694 switch (This->state) {
7697 case WINED3DERR_DEVICELOST:
7699 ResourceList *resourceList = This->resources;
7700 while (NULL != resourceList) {
7701 if (((IWineD3DResourceImpl *)resourceList->resource)->resource.pool == WINED3DPOOL_DEFAULT /* TODO: IWineD3DResource_GetPool(resourceList->resource)*/)
7702 return WINED3DERR_DEVICENOTRESET;
7703 resourceList = resourceList->next;
7705 return WINED3DERR_DEVICELOST;
7707 case WINED3DERR_DRIVERINTERNALERROR:
7708 return WINED3DERR_DRIVERINTERNALERROR;
7712 return WINED3DERR_DRIVERINTERNALERROR;
7716 static HRESULT WINAPI IWineD3DDeviceImpl_EvictManagedResources(IWineD3DDevice* iface) {
7717 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *) iface;
7718 /** FIXME: Resource tracking needs to be done,
7719 * The closes we can do to this is set the priorities of all managed textures low
7720 * and then reset them.
7721 ***********************************************************/
7722 FIXME("(%p) : stub\n", This);
7726 static HRESULT WINAPI IWineD3DDeviceImpl_Reset(IWineD3DDevice* iface, WINED3DPRESENT_PARAMETERS* pPresentationParameters) {
7727 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *) iface;
7728 /** FIXME: Resource trascking needs to be done.
7729 * in effect this pulls all non only default
7730 * textures out of video memory and deletes all glTextures (glDeleteTextures)
7731 * and should clear down the context and set it up according to pPresentationParameters
7732 ***********************************************************/
7733 FIXME("(%p) : stub\n", This);
7737 static HRESULT WINAPI IWineD3DDeviceImpl_SetDialogBoxMode(IWineD3DDevice *iface, BOOL bEnableDialogs) {
7738 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
7739 /** FIXME: always true at the moment **/
7740 if(bEnableDialogs == FALSE) {
7741 FIXME("(%p) Dialogs cannot be disabled yet\n", This);
7747 static HRESULT WINAPI IWineD3DDeviceImpl_GetCreationParameters(IWineD3DDevice *iface, WINED3DDEVICE_CREATION_PARAMETERS *pParameters) {
7748 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *) iface;
7749 TRACE("(%p) : pParameters %p\n", This, pParameters);
7751 *pParameters = This->createParms;
7755 static void WINAPI IWineD3DDeviceImpl_SetGammaRamp(IWineD3DDevice * iface, UINT iSwapChain, DWORD Flags, CONST WINED3DGAMMARAMP* pRamp) {
7756 IWineD3DSwapChain *swapchain;
7757 HRESULT hrc = WINED3D_OK;
7759 TRACE("Relaying to swapchain\n");
7761 if ((hrc = IWineD3DDeviceImpl_GetSwapChain(iface, iSwapChain, &swapchain)) == WINED3D_OK) {
7762 IWineD3DSwapChain_SetGammaRamp(swapchain, Flags, (WINED3DGAMMARAMP *)pRamp);
7763 IWineD3DSwapChain_Release(swapchain);
7768 static void WINAPI IWineD3DDeviceImpl_GetGammaRamp(IWineD3DDevice *iface, UINT iSwapChain, WINED3DGAMMARAMP* pRamp) {
7769 IWineD3DSwapChain *swapchain;
7770 HRESULT hrc = WINED3D_OK;
7772 TRACE("Relaying to swapchain\n");
7774 if ((hrc = IWineD3DDeviceImpl_GetSwapChain(iface, iSwapChain, &swapchain)) == WINED3D_OK) {
7775 hrc =IWineD3DSwapChain_GetGammaRamp(swapchain, pRamp);
7776 IWineD3DSwapChain_Release(swapchain);
7782 /** ********************************************************
7783 * Notification functions
7784 ** ********************************************************/
7785 /** This function must be called in the release of a resource when ref == 0,
7786 * the contents of resource must still be correct,
7787 * any handels to other resource held by the caller must be closed
7788 * (e.g. a texture should release all held surfaces because telling the device that it's been released.)
7789 *****************************************************/
7790 static void WINAPI IWineD3DDeviceImpl_AddResource(IWineD3DDevice *iface, IWineD3DResource *resource){
7791 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
7792 ResourceList* resourceList;
7794 TRACE("(%p) : resource %p\n", This, resource);
7796 EnterCriticalSection(&resourceStoreCriticalSection);
7798 /* add a new texture to the frot of the linked list */
7799 resourceList = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(ResourceList));
7800 resourceList->resource = resource;
7802 /* Get the old head */
7803 resourceList->next = This->resources;
7805 This->resources = resourceList;
7806 TRACE("Added resource %p with element %p pointing to %p\n", resource, resourceList, resourceList->next);
7809 LeaveCriticalSection(&resourceStoreCriticalSection);
7814 static void WINAPI IWineD3DDeviceImpl_RemoveResource(IWineD3DDevice *iface, IWineD3DResource *resource){
7815 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
7816 ResourceList* resourceList = NULL;
7817 ResourceList* previousResourceList = NULL;
7819 TRACE("(%p) : resource %p\n", This, resource);
7822 EnterCriticalSection(&resourceStoreCriticalSection);
7824 resourceList = This->resources;
7826 while (resourceList != NULL) {
7827 if(resourceList->resource == resource) break;
7828 previousResourceList = resourceList;
7829 resourceList = resourceList->next;
7832 if (resourceList == NULL) {
7833 FIXME("Attempted to remove resource %p that hasn't been stored\n", resource);
7835 LeaveCriticalSection(&resourceStoreCriticalSection);
7839 TRACE("Found resource %p with element %p pointing to %p (previous %p)\n", resourceList->resource, resourceList, resourceList->next, previousResourceList);
7841 /* make sure we don't leave a hole in the list */
7842 if (previousResourceList != NULL) {
7843 previousResourceList->next = resourceList->next;
7845 This->resources = resourceList->next;
7849 LeaveCriticalSection(&resourceStoreCriticalSection);
7855 static void WINAPI IWineD3DDeviceImpl_ResourceReleased(IWineD3DDevice *iface, IWineD3DResource *resource){
7856 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *) iface;
7859 TRACE("(%p) : resource %p\n", This, resource);
7860 switch(IWineD3DResource_GetType(resource)){
7861 case WINED3DRTYPE_SURFACE:
7862 /* TODO: check front and back buffers, rendertargets etc.. possibly swapchains? */
7864 case WINED3DRTYPE_TEXTURE:
7865 case WINED3DRTYPE_CUBETEXTURE:
7866 case WINED3DRTYPE_VOLUMETEXTURE:
7867 for (counter = 0; counter < GL_LIMITS(sampler_stages); counter++) {
7868 if (This->stateBlock != NULL && This->stateBlock->textures[counter] == (IWineD3DBaseTexture *)resource) {
7869 WARN("Texture being released is still by a stateblock, Stage = %u Texture = %p\n", counter, resource);
7870 This->stateBlock->textures[counter] = NULL;
7872 if (This->updateStateBlock != This->stateBlock ){
7873 if (This->updateStateBlock->textures[counter] == (IWineD3DBaseTexture *)resource) {
7874 WARN("Texture being released is still by a stateblock, Stage = %u Texture = %p\n", counter, resource);
7875 This->updateStateBlock->textures[counter] = NULL;
7880 case WINED3DRTYPE_VOLUME:
7881 /* TODO: nothing really? */
7883 case WINED3DRTYPE_VERTEXBUFFER:
7884 /* MSDN: When an application no longer holds a references to this interface, the interface will automatically be freed. */
7887 TRACE("Cleaning up stream pointers\n");
7889 for(streamNumber = 0; streamNumber < MAX_STREAMS; streamNumber ++){
7890 /* FINDOUT: should a warn be generated if were recording and updateStateBlock->streamSource is lost?
7891 FINDOUT: should changes.streamSource[StreamNumber] be set ?
7893 if (This->updateStateBlock != NULL ) { /* ==NULL when device is being destroyed */
7894 if ((IWineD3DResource *)This->updateStateBlock->streamSource[streamNumber] == resource) {
7895 FIXME("Vertex buffer released whlst bound to a state block stream %d\n", streamNumber);
7896 This->updateStateBlock->streamSource[streamNumber] = 0;
7897 /* Set changed flag? */
7900 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) */
7901 if ((IWineD3DResource *)This->stateBlock->streamSource[streamNumber] == resource) {
7902 TRACE("Vertex buffer released whlst bound to a state block stream %d\n", streamNumber);
7903 This->stateBlock->streamSource[streamNumber] = 0;
7906 #if 0 /* TODO: Manage internal tracking properly so that 'this shouldn't happen' */
7907 else { /* This shouldn't happen */
7908 FIXME("Calling application has released the device before relasing all the resources bound to the device\n");
7915 case WINED3DRTYPE_INDEXBUFFER:
7916 /* MSDN: When an application no longer holds a references to this interface, the interface will automatically be freed.*/
7917 if (This->updateStateBlock != NULL ) { /* ==NULL when device is being destroyed */
7918 if (This->updateStateBlock->pIndexData == (IWineD3DIndexBuffer *)resource) {
7919 This->updateStateBlock->pIndexData = NULL;
7922 if (This->stateBlock != NULL ) { /* ==NULL when device is being destroyed */
7923 if (This->stateBlock->pIndexData == (IWineD3DIndexBuffer *)resource) {
7924 This->stateBlock->pIndexData = NULL;
7930 FIXME("(%p) unknown resource type %p %u\n", This, resource, IWineD3DResource_GetType(resource));
7935 /* Remove the resoruce from the resourceStore */
7936 IWineD3DDeviceImpl_RemoveResource(iface, resource);
7938 TRACE("Resource released\n");
7942 /**********************************************************
7943 * IWineD3DDevice VTbl follows
7944 **********************************************************/
7946 const IWineD3DDeviceVtbl IWineD3DDevice_Vtbl =
7948 /*** IUnknown methods ***/
7949 IWineD3DDeviceImpl_QueryInterface,
7950 IWineD3DDeviceImpl_AddRef,
7951 IWineD3DDeviceImpl_Release,
7952 /*** IWineD3DDevice methods ***/
7953 IWineD3DDeviceImpl_GetParent,
7954 /*** Creation methods**/
7955 IWineD3DDeviceImpl_CreateVertexBuffer,
7956 IWineD3DDeviceImpl_CreateIndexBuffer,
7957 IWineD3DDeviceImpl_CreateStateBlock,
7958 IWineD3DDeviceImpl_CreateSurface,
7959 IWineD3DDeviceImpl_CreateTexture,
7960 IWineD3DDeviceImpl_CreateVolumeTexture,
7961 IWineD3DDeviceImpl_CreateVolume,
7962 IWineD3DDeviceImpl_CreateCubeTexture,
7963 IWineD3DDeviceImpl_CreateQuery,
7964 IWineD3DDeviceImpl_CreateAdditionalSwapChain,
7965 IWineD3DDeviceImpl_CreateVertexDeclaration,
7966 IWineD3DDeviceImpl_CreateVertexShader,
7967 IWineD3DDeviceImpl_CreatePixelShader,
7968 IWineD3DDeviceImpl_CreatePalette,
7969 /*** Odd functions **/
7970 IWineD3DDeviceImpl_Init3D,
7971 IWineD3DDeviceImpl_Uninit3D,
7972 IWineD3DDeviceImpl_EnumDisplayModes,
7973 IWineD3DDeviceImpl_EvictManagedResources,
7974 IWineD3DDeviceImpl_GetAvailableTextureMem,
7975 IWineD3DDeviceImpl_GetBackBuffer,
7976 IWineD3DDeviceImpl_GetCreationParameters,
7977 IWineD3DDeviceImpl_GetDeviceCaps,
7978 IWineD3DDeviceImpl_GetDirect3D,
7979 IWineD3DDeviceImpl_GetDisplayMode,
7980 IWineD3DDeviceImpl_SetDisplayMode,
7981 IWineD3DDeviceImpl_GetHWND,
7982 IWineD3DDeviceImpl_SetHWND,
7983 IWineD3DDeviceImpl_GetNumberOfSwapChains,
7984 IWineD3DDeviceImpl_GetRasterStatus,
7985 IWineD3DDeviceImpl_GetSwapChain,
7986 IWineD3DDeviceImpl_Reset,
7987 IWineD3DDeviceImpl_SetDialogBoxMode,
7988 IWineD3DDeviceImpl_SetCursorProperties,
7989 IWineD3DDeviceImpl_SetCursorPosition,
7990 IWineD3DDeviceImpl_ShowCursor,
7991 IWineD3DDeviceImpl_TestCooperativeLevel,
7992 /*** Getters and setters **/
7993 IWineD3DDeviceImpl_SetClipPlane,
7994 IWineD3DDeviceImpl_GetClipPlane,
7995 IWineD3DDeviceImpl_SetClipStatus,
7996 IWineD3DDeviceImpl_GetClipStatus,
7997 IWineD3DDeviceImpl_SetCurrentTexturePalette,
7998 IWineD3DDeviceImpl_GetCurrentTexturePalette,
7999 IWineD3DDeviceImpl_SetDepthStencilSurface,
8000 IWineD3DDeviceImpl_GetDepthStencilSurface,
8001 IWineD3DDeviceImpl_SetFVF,
8002 IWineD3DDeviceImpl_GetFVF,
8003 IWineD3DDeviceImpl_SetGammaRamp,
8004 IWineD3DDeviceImpl_GetGammaRamp,
8005 IWineD3DDeviceImpl_SetIndices,
8006 IWineD3DDeviceImpl_GetIndices,
8007 IWineD3DDeviceImpl_SetLight,
8008 IWineD3DDeviceImpl_GetLight,
8009 IWineD3DDeviceImpl_SetLightEnable,
8010 IWineD3DDeviceImpl_GetLightEnable,
8011 IWineD3DDeviceImpl_SetMaterial,
8012 IWineD3DDeviceImpl_GetMaterial,
8013 IWineD3DDeviceImpl_SetNPatchMode,
8014 IWineD3DDeviceImpl_GetNPatchMode,
8015 IWineD3DDeviceImpl_SetPaletteEntries,
8016 IWineD3DDeviceImpl_GetPaletteEntries,
8017 IWineD3DDeviceImpl_SetPixelShader,
8018 IWineD3DDeviceImpl_GetPixelShader,
8019 IWineD3DDeviceImpl_SetPixelShaderConstantB,
8020 IWineD3DDeviceImpl_GetPixelShaderConstantB,
8021 IWineD3DDeviceImpl_SetPixelShaderConstantI,
8022 IWineD3DDeviceImpl_GetPixelShaderConstantI,
8023 IWineD3DDeviceImpl_SetPixelShaderConstantF,
8024 IWineD3DDeviceImpl_GetPixelShaderConstantF,
8025 IWineD3DDeviceImpl_SetRenderState,
8026 IWineD3DDeviceImpl_GetRenderState,
8027 IWineD3DDeviceImpl_SetRenderTarget,
8028 IWineD3DDeviceImpl_GetRenderTarget,
8029 IWineD3DDeviceImpl_SetFrontBackBuffers,
8030 IWineD3DDeviceImpl_SetSamplerState,
8031 IWineD3DDeviceImpl_GetSamplerState,
8032 IWineD3DDeviceImpl_SetScissorRect,
8033 IWineD3DDeviceImpl_GetScissorRect,
8034 IWineD3DDeviceImpl_SetSoftwareVertexProcessing,
8035 IWineD3DDeviceImpl_GetSoftwareVertexProcessing,
8036 IWineD3DDeviceImpl_SetStreamSource,
8037 IWineD3DDeviceImpl_GetStreamSource,
8038 IWineD3DDeviceImpl_SetStreamSourceFreq,
8039 IWineD3DDeviceImpl_GetStreamSourceFreq,
8040 IWineD3DDeviceImpl_SetTexture,
8041 IWineD3DDeviceImpl_GetTexture,
8042 IWineD3DDeviceImpl_SetTextureStageState,
8043 IWineD3DDeviceImpl_GetTextureStageState,
8044 IWineD3DDeviceImpl_SetTransform,
8045 IWineD3DDeviceImpl_GetTransform,
8046 IWineD3DDeviceImpl_SetVertexDeclaration,
8047 IWineD3DDeviceImpl_GetVertexDeclaration,
8048 IWineD3DDeviceImpl_SetVertexShader,
8049 IWineD3DDeviceImpl_GetVertexShader,
8050 IWineD3DDeviceImpl_SetVertexShaderConstantB,
8051 IWineD3DDeviceImpl_GetVertexShaderConstantB,
8052 IWineD3DDeviceImpl_SetVertexShaderConstantI,
8053 IWineD3DDeviceImpl_GetVertexShaderConstantI,
8054 IWineD3DDeviceImpl_SetVertexShaderConstantF,
8055 IWineD3DDeviceImpl_GetVertexShaderConstantF,
8056 IWineD3DDeviceImpl_SetViewport,
8057 IWineD3DDeviceImpl_GetViewport,
8058 IWineD3DDeviceImpl_MultiplyTransform,
8059 IWineD3DDeviceImpl_ValidateDevice,
8060 IWineD3DDeviceImpl_ProcessVertices,
8061 /*** State block ***/
8062 IWineD3DDeviceImpl_BeginStateBlock,
8063 IWineD3DDeviceImpl_EndStateBlock,
8064 /*** Scene management ***/
8065 IWineD3DDeviceImpl_BeginScene,
8066 IWineD3DDeviceImpl_EndScene,
8067 IWineD3DDeviceImpl_Present,
8068 IWineD3DDeviceImpl_Clear,
8070 IWineD3DDeviceImpl_DrawPrimitive,
8071 IWineD3DDeviceImpl_DrawIndexedPrimitive,
8072 IWineD3DDeviceImpl_DrawPrimitiveUP,
8073 IWineD3DDeviceImpl_DrawIndexedPrimitiveUP,
8074 IWineD3DDeviceImpl_DrawPrimitiveStrided,
8075 IWineD3DDeviceImpl_DrawRectPatch,
8076 IWineD3DDeviceImpl_DrawTriPatch,
8077 IWineD3DDeviceImpl_DeletePatch,
8078 IWineD3DDeviceImpl_ColorFill,
8079 IWineD3DDeviceImpl_UpdateTexture,
8080 IWineD3DDeviceImpl_UpdateSurface,
8081 IWineD3DDeviceImpl_CopyRects,
8082 IWineD3DDeviceImpl_StretchRect,
8083 IWineD3DDeviceImpl_GetRenderTargetData,
8084 IWineD3DDeviceImpl_GetFrontBufferData,
8085 /*** Internal use IWineD3DDevice methods ***/
8086 IWineD3DDeviceImpl_SetupTextureStates,
8087 /*** object tracking ***/
8088 IWineD3DDeviceImpl_ResourceReleased
8092 const DWORD SavedPixelStates_R[NUM_SAVEDPIXELSTATES_R] = {
8093 WINED3DRS_ALPHABLENDENABLE ,
8094 WINED3DRS_ALPHAFUNC ,
8095 WINED3DRS_ALPHAREF ,
8096 WINED3DRS_ALPHATESTENABLE ,
8098 WINED3DRS_COLORWRITEENABLE ,
8099 WINED3DRS_DESTBLEND ,
8100 WINED3DRS_DITHERENABLE ,
8101 WINED3DRS_FILLMODE ,
8102 WINED3DRS_FOGDENSITY ,
8104 WINED3DRS_FOGSTART ,
8105 WINED3DRS_LASTPIXEL ,
8106 WINED3DRS_SHADEMODE ,
8107 WINED3DRS_SRCBLEND ,
8108 WINED3DRS_STENCILENABLE ,
8109 WINED3DRS_STENCILFAIL ,
8110 WINED3DRS_STENCILFUNC ,
8111 WINED3DRS_STENCILMASK ,
8112 WINED3DRS_STENCILPASS ,
8113 WINED3DRS_STENCILREF ,
8114 WINED3DRS_STENCILWRITEMASK ,
8115 WINED3DRS_STENCILZFAIL ,
8116 WINED3DRS_TEXTUREFACTOR ,
8127 WINED3DRS_ZWRITEENABLE
8130 const DWORD SavedPixelStates_T[NUM_SAVEDPIXELSTATES_T] = {
8131 WINED3DTSS_ADDRESSW ,
8132 WINED3DTSS_ALPHAARG0 ,
8133 WINED3DTSS_ALPHAARG1 ,
8134 WINED3DTSS_ALPHAARG2 ,
8135 WINED3DTSS_ALPHAOP ,
8136 WINED3DTSS_BUMPENVLOFFSET ,
8137 WINED3DTSS_BUMPENVLSCALE ,
8138 WINED3DTSS_BUMPENVMAT00 ,
8139 WINED3DTSS_BUMPENVMAT01 ,
8140 WINED3DTSS_BUMPENVMAT10 ,
8141 WINED3DTSS_BUMPENVMAT11 ,
8142 WINED3DTSS_COLORARG0 ,
8143 WINED3DTSS_COLORARG1 ,
8144 WINED3DTSS_COLORARG2 ,
8145 WINED3DTSS_COLOROP ,
8146 WINED3DTSS_RESULTARG ,
8147 WINED3DTSS_TEXCOORDINDEX ,
8148 WINED3DTSS_TEXTURETRANSFORMFLAGS
8151 const DWORD SavedPixelStates_S[NUM_SAVEDPIXELSTATES_S] = {
8152 WINED3DSAMP_ADDRESSU ,
8153 WINED3DSAMP_ADDRESSV ,
8154 WINED3DSAMP_ADDRESSW ,
8155 WINED3DSAMP_BORDERCOLOR ,
8156 WINED3DSAMP_MAGFILTER ,
8157 WINED3DSAMP_MINFILTER ,
8158 WINED3DSAMP_MIPFILTER ,
8159 WINED3DSAMP_MIPMAPLODBIAS ,
8160 WINED3DSAMP_MAXMIPLEVEL ,
8161 WINED3DSAMP_MAXANISOTROPY ,
8162 WINED3DSAMP_SRGBTEXTURE ,
8163 WINED3DSAMP_ELEMENTINDEX
8166 const DWORD SavedVertexStates_R[NUM_SAVEDVERTEXSTATES_R] = {
8168 WINED3DRS_AMBIENTMATERIALSOURCE ,
8169 WINED3DRS_CLIPPING ,
8170 WINED3DRS_CLIPPLANEENABLE ,
8171 WINED3DRS_COLORVERTEX ,
8172 WINED3DRS_DIFFUSEMATERIALSOURCE ,
8173 WINED3DRS_EMISSIVEMATERIALSOURCE ,
8174 WINED3DRS_FOGDENSITY ,
8176 WINED3DRS_FOGSTART ,
8177 WINED3DRS_FOGTABLEMODE ,
8178 WINED3DRS_FOGVERTEXMODE ,
8179 WINED3DRS_INDEXEDVERTEXBLENDENABLE ,
8180 WINED3DRS_LIGHTING ,
8181 WINED3DRS_LOCALVIEWER ,
8182 WINED3DRS_MULTISAMPLEANTIALIAS ,
8183 WINED3DRS_MULTISAMPLEMASK ,
8184 WINED3DRS_NORMALIZENORMALS ,
8185 WINED3DRS_PATCHEDGESTYLE ,
8186 WINED3DRS_POINTSCALE_A ,
8187 WINED3DRS_POINTSCALE_B ,
8188 WINED3DRS_POINTSCALE_C ,
8189 WINED3DRS_POINTSCALEENABLE ,
8190 WINED3DRS_POINTSIZE ,
8191 WINED3DRS_POINTSIZE_MAX ,
8192 WINED3DRS_POINTSIZE_MIN ,
8193 WINED3DRS_POINTSPRITEENABLE ,
8194 WINED3DRS_RANGEFOGENABLE ,
8195 WINED3DRS_SPECULARMATERIALSOURCE ,
8196 WINED3DRS_TWEENFACTOR ,
8197 WINED3DRS_VERTEXBLEND
8200 const DWORD SavedVertexStates_T[NUM_SAVEDVERTEXSTATES_T] = {
8201 WINED3DTSS_TEXCOORDINDEX ,
8202 WINED3DTSS_TEXTURETRANSFORMFLAGS
8205 const DWORD SavedVertexStates_S[NUM_SAVEDVERTEXSTATES_S] = {
8206 WINED3DSAMP_DMAPOFFSET