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 /* The pitch is a multiple of 4 bytes */
1005 Size = ((pow2Width * tableEntry->bpp) + 3) & ~3;
1009 /** Create and initialise the surface resource **/
1010 D3DCREATERESOURCEOBJECTINSTANCE(object,Surface,WINED3DRTYPE_SURFACE, Size)
1011 /* "Standalone" surface */
1012 IWineD3DSurface_SetContainer((IWineD3DSurface *)object, NULL);
1014 object->currentDesc.Width = Width;
1015 object->currentDesc.Height = Height;
1016 object->currentDesc.MultiSampleType = MultiSample;
1017 object->currentDesc.MultiSampleQuality = MultisampleQuality;
1019 /* Setup some glformat defaults */
1020 object->glDescription.glFormat = tableEntry->glFormat;
1021 object->glDescription.glFormatInternal = tableEntry->glInternal;
1022 object->glDescription.glType = tableEntry->glType;
1024 object->glDescription.textureName = 0;
1025 object->glDescription.level = Level;
1026 object->glDescription.target = GL_TEXTURE_2D;
1029 object->pow2Width = pow2Width;
1030 object->pow2Height = pow2Height;
1033 object->Flags = 0; /* We start without flags set */
1034 object->Flags |= (pow2Width != Width || pow2Height != Height) ? SFLAG_NONPOW2 : 0;
1035 object->Flags |= Discard ? SFLAG_DISCARD : 0;
1036 object->Flags |= (WINED3DFMT_D16_LOCKABLE == Format) ? SFLAG_LOCKABLE : 0;
1037 object->Flags |= Lockable ? SFLAG_LOCKABLE : 0;
1040 if (WINED3DFMT_UNKNOWN != Format) {
1041 object->bytesPerPixel = tableEntry->bpp;
1042 object->pow2Size = (pow2Width * object->bytesPerPixel) * pow2Height;
1044 object->bytesPerPixel = 0;
1045 object->pow2Size = 0;
1048 /** TODO: change this into a texture transform matrix so that it's processed in hardware **/
1050 TRACE("Pool %d %d %d %d",Pool, WINED3DPOOL_DEFAULT, WINED3DPOOL_MANAGED, WINED3DPOOL_SYSTEMMEM);
1052 /** Quick lockable sanity check TODO: remove this after surfaces, usage and locablility have been debugged properly
1053 * this function is too deap to need to care about things like this.
1054 * Levels need to be checked too, and possibly Type wince they all affect what can be done.
1055 * ****************************************/
1057 case WINED3DPOOL_SCRATCH:
1058 if(Lockable == FALSE)
1059 FIXME("Create suface called with a pool of SCRATCH and a Lockable of FALSE \
1060 which are mutually exclusive, setting lockable to true\n");
1063 case WINED3DPOOL_SYSTEMMEM:
1064 if(Lockable == FALSE) FIXME("Create surface called with a pool of SYSTEMMEM and a Lockable of FALSE, \
1065 this is acceptable but unexpected (I can't know how the surface can be usable!)\n");
1066 case WINED3DPOOL_MANAGED:
1067 if(Usage == WINED3DUSAGE_DYNAMIC) FIXME("Create surface called with a pool of MANAGED and a \
1068 Usage of DYNAMIC which are mutually exclusive, not doing \
1069 anything just telling you.\n");
1071 case WINED3DPOOL_DEFAULT: /*TODO: Create offscreen plain can cause this check to fail..., find out if it should */
1072 if(!(Usage & WINED3DUSAGE_DYNAMIC) && !(Usage & WINED3DUSAGE_RENDERTARGET)
1073 && !(Usage && WINED3DUSAGE_DEPTHSTENCIL ) && Lockable)
1074 WARN("Creating a surface with a POOL of DEFAULT with Lockable true, that doesn't specify DYNAMIC usage.\n");
1077 FIXME("(%p) Unknown pool %d\n", This, Pool);
1081 if (Usage & WINED3DUSAGE_RENDERTARGET && Pool != WINED3DPOOL_DEFAULT) {
1082 FIXME("Trying to create a render target that isn't in the default pool\n");
1085 /* mark the texture as dirty so that it get's loaded first time around*/
1086 IWineD3DSurface_AddDirtyRect(*ppSurface, NULL);
1087 TRACE("(%p) : w(%d) h(%d) fmt(%d,%s) lockable(%d) surf@%p, surfmem@%p, %d bytes\n",
1088 This, Width, Height, Format, debug_d3dformat(Format),
1089 (WINED3DFMT_D16_LOCKABLE == Format), *ppSurface, object->resource.allocatedMemory, object->resource.size);
1091 /* Store the DirectDraw primary surface. This is the first rendertarget surface created */
1092 if( (Usage & WINED3DUSAGE_RENDERTARGET) && (!This->ddraw_primary) )
1093 This->ddraw_primary = (IWineD3DSurface *) object;
1095 /* Look at the implementation and set the correct Vtable */
1097 case SURFACE_OPENGL:
1098 /* Nothing to do, it's set already */
1102 object->lpVtbl = &IWineGDISurface_Vtbl;
1106 /* To be sure to catch this */
1107 ERR("Unknown requested surface implementation %d!\n", Impl);
1108 IWineD3DSurface_Release((IWineD3DSurface *) object);
1109 return WINED3DERR_INVALIDCALL;
1112 /* Call the private setup routine */
1113 return IWineD3DSurface_PrivateSetup( (IWineD3DSurface *) object );
1117 static HRESULT WINAPI IWineD3DDeviceImpl_CreateTexture(IWineD3DDevice *iface, UINT Width, UINT Height, UINT Levels,
1118 DWORD Usage, WINED3DFORMAT Format, WINED3DPOOL Pool,
1119 IWineD3DTexture** ppTexture, HANDLE* pSharedHandle, IUnknown *parent,
1120 D3DCB_CREATESURFACEFN D3DCB_CreateSurface) {
1122 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
1123 IWineD3DTextureImpl *object;
1128 unsigned int pow2Width = Width;
1129 unsigned int pow2Height = Height;
1132 TRACE("(%p) : Width %d, Height %d, Levels %d, Usage %#lx\n", This, Width, Height, Levels, Usage);
1133 TRACE("Format %#x (%s), Pool %#x, ppTexture %p, pSharedHandle %p, parent %p\n",
1134 Format, debug_d3dformat(Format), Pool, ppTexture, pSharedHandle, parent);
1136 /* TODO: It should only be possible to create textures for formats
1137 that are reported as supported */
1138 if (WINED3DFMT_UNKNOWN >= Format) {
1139 WARN("(%p) : Texture cannot be created with a format of D3DFMT_UNKNOWN\n", This);
1140 return WINED3DERR_INVALIDCALL;
1143 D3DCREATERESOURCEOBJECTINSTANCE(object, Texture, WINED3DRTYPE_TEXTURE, 0);
1144 D3DINITIALIZEBASETEXTURE(object->baseTexture);
1145 object->width = Width;
1146 object->height = Height;
1148 /** Non-power2 support **/
1149 /* Find the nearest pow2 match */
1150 pow2Width = pow2Height = 1;
1151 while (pow2Width < Width) pow2Width <<= 1;
1152 while (pow2Height < Height) pow2Height <<= 1;
1154 /** FIXME: add support for real non-power-two if it's provided by the video card **/
1155 /* Precalculated scaling for 'faked' non power of two texture coords */
1156 object->pow2scalingFactorX = (((float)Width) / ((float)pow2Width));
1157 object->pow2scalingFactorY = (((float)Height) / ((float)pow2Height));
1158 TRACE(" xf(%f) yf(%f)\n", object->pow2scalingFactorX, object->pow2scalingFactorY);
1160 /* Calculate levels for mip mapping */
1162 TRACE("calculating levels %d\n", object->baseTexture.levels);
1163 object->baseTexture.levels++;
1166 while (tmpW > 1 || tmpH > 1) {
1167 tmpW = max(1, tmpW >> 1);
1168 tmpH = max(1, tmpH >> 1);
1169 object->baseTexture.levels++;
1171 TRACE("Calculated levels = %d\n", object->baseTexture.levels);
1174 /* Generate all the surfaces */
1177 for (i = 0; i < object->baseTexture.levels; i++)
1179 /* use the callback to create the texture surface */
1180 hr = D3DCB_CreateSurface(This->parent, tmpW, tmpH, Format, Usage, Pool, i, &object->surfaces[i],NULL);
1181 if (hr!= WINED3D_OK || ( (IWineD3DSurfaceImpl *) object->surfaces[i])->Flags & SFLAG_OVERSIZE) {
1182 FIXME("Failed to create surface %p\n", object);
1184 object->surfaces[i] = NULL;
1185 IWineD3DTexture_Release((IWineD3DTexture *)object);
1191 IWineD3DSurface_SetContainer(object->surfaces[i], (IWineD3DBase *)object);
1192 TRACE("Created surface level %d @ %p\n", i, object->surfaces[i]);
1193 /* calculate the next mipmap level */
1194 tmpW = max(1, tmpW >> 1);
1195 tmpH = max(1, tmpH >> 1);
1198 TRACE("(%p) : Created texture %p\n", This, object);
1202 static HRESULT WINAPI IWineD3DDeviceImpl_CreateVolumeTexture(IWineD3DDevice *iface,
1203 UINT Width, UINT Height, UINT Depth,
1204 UINT Levels, DWORD Usage,
1205 WINED3DFORMAT Format, WINED3DPOOL Pool,
1206 IWineD3DVolumeTexture **ppVolumeTexture,
1207 HANDLE *pSharedHandle, IUnknown *parent,
1208 D3DCB_CREATEVOLUMEFN D3DCB_CreateVolume) {
1210 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
1211 IWineD3DVolumeTextureImpl *object;
1217 /* TODO: It should only be possible to create textures for formats
1218 that are reported as supported */
1219 if (WINED3DFMT_UNKNOWN >= Format) {
1220 WARN("(%p) : Texture cannot be created with a format of D3DFMT_UNKNOWN\n", This);
1221 return WINED3DERR_INVALIDCALL;
1224 D3DCREATERESOURCEOBJECTINSTANCE(object, VolumeTexture, WINED3DRTYPE_VOLUMETEXTURE, 0);
1225 D3DINITIALIZEBASETEXTURE(object->baseTexture);
1227 TRACE("(%p) : W(%d) H(%d) D(%d), Lvl(%d) Usage(%ld), Fmt(%u,%s), Pool(%s)\n", This, Width, Height,
1228 Depth, Levels, Usage, Format, debug_d3dformat(Format), debug_d3dpool(Pool));
1230 object->width = Width;
1231 object->height = Height;
1232 object->depth = Depth;
1234 /* Calculate levels for mip mapping */
1236 object->baseTexture.levels++;
1240 while (tmpW > 1 || tmpH > 1 || tmpD > 1) {
1241 tmpW = max(1, tmpW >> 1);
1242 tmpH = max(1, tmpH >> 1);
1243 tmpD = max(1, tmpD >> 1);
1244 object->baseTexture.levels++;
1246 TRACE("Calculated levels = %d\n", object->baseTexture.levels);
1249 /* Generate all the surfaces */
1254 for (i = 0; i < object->baseTexture.levels; i++)
1256 /* Create the volume */
1257 D3DCB_CreateVolume(This->parent, Width, Height, Depth, Format, Pool, Usage,
1258 (IWineD3DVolume **)&object->volumes[i], pSharedHandle);
1260 /* Set it's container to this object */
1261 IWineD3DVolume_SetContainer(object->volumes[i], (IWineD3DBase *)object);
1263 /* calcualte the next mipmap level */
1264 tmpW = max(1, tmpW >> 1);
1265 tmpH = max(1, tmpH >> 1);
1266 tmpD = max(1, tmpD >> 1);
1269 *ppVolumeTexture = (IWineD3DVolumeTexture *) object;
1270 TRACE("(%p) : Created volume texture %p\n", This, object);
1274 static HRESULT WINAPI IWineD3DDeviceImpl_CreateVolume(IWineD3DDevice *iface,
1275 UINT Width, UINT Height, UINT Depth,
1277 WINED3DFORMAT Format, WINED3DPOOL Pool,
1278 IWineD3DVolume** ppVolume,
1279 HANDLE* pSharedHandle, IUnknown *parent) {
1281 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
1282 IWineD3DVolumeImpl *object; /** NOTE: impl ref allowed since this is a create function **/
1283 const PixelFormatDesc *formatDesc = getFormatDescEntry(Format);
1285 D3DCREATERESOURCEOBJECTINSTANCE(object, Volume, WINED3DRTYPE_VOLUME, ((Width * formatDesc->bpp) * Height * Depth))
1287 TRACE("(%p) : W(%d) H(%d) D(%d), Usage(%ld), Fmt(%u,%s), Pool(%s)\n", This, Width, Height,
1288 Depth, Usage, Format, debug_d3dformat(Format), debug_d3dpool(Pool));
1290 object->currentDesc.Width = Width;
1291 object->currentDesc.Height = Height;
1292 object->currentDesc.Depth = Depth;
1293 object->bytesPerPixel = formatDesc->bpp;
1295 /** Note: Volume textures cannot be dxtn, hence no need to check here **/
1296 object->lockable = TRUE;
1297 object->locked = FALSE;
1298 memset(&object->lockedBox, 0, sizeof(WINED3DBOX));
1299 object->dirty = TRUE;
1301 return IWineD3DVolume_AddDirtyBox((IWineD3DVolume *) object, NULL);
1304 static HRESULT WINAPI IWineD3DDeviceImpl_CreateCubeTexture(IWineD3DDevice *iface, UINT EdgeLength,
1305 UINT Levels, DWORD Usage,
1306 WINED3DFORMAT Format, WINED3DPOOL Pool,
1307 IWineD3DCubeTexture **ppCubeTexture,
1308 HANDLE *pSharedHandle, IUnknown *parent,
1309 D3DCB_CREATESURFACEFN D3DCB_CreateSurface) {
1311 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
1312 IWineD3DCubeTextureImpl *object; /** NOTE: impl ref allowed since this is a create function **/
1316 unsigned int pow2EdgeLength = EdgeLength;
1318 /* TODO: It should only be possible to create textures for formats
1319 that are reported as supported */
1320 if (WINED3DFMT_UNKNOWN >= Format) {
1321 WARN("(%p) : Texture cannot be created with a format of D3DFMT_UNKNOWN\n", This);
1322 return WINED3DERR_INVALIDCALL;
1325 D3DCREATERESOURCEOBJECTINSTANCE(object, CubeTexture, WINED3DRTYPE_CUBETEXTURE, 0);
1326 D3DINITIALIZEBASETEXTURE(object->baseTexture);
1328 TRACE("(%p) Create Cube Texture\n", This);
1330 /** Non-power2 support **/
1332 /* Find the nearest pow2 match */
1334 while (pow2EdgeLength < EdgeLength) pow2EdgeLength <<= 1;
1336 object->edgeLength = EdgeLength;
1337 /* TODO: support for native non-power 2 */
1338 /* Precalculated scaling for 'faked' non power of two texture coords */
1339 object->pow2scalingFactor = ((float)EdgeLength) / ((float)pow2EdgeLength);
1341 /* Calculate levels for mip mapping */
1343 object->baseTexture.levels++;
1346 tmpW = max(1, tmpW >> 1);
1347 object->baseTexture.levels++;
1349 TRACE("Calculated levels = %d\n", object->baseTexture.levels);
1352 /* Generate all the surfaces */
1354 for (i = 0; i < object->baseTexture.levels; i++) {
1356 /* Create the 6 faces */
1357 for (j = 0; j < 6; j++) {
1359 hr=D3DCB_CreateSurface(This->parent, tmpW, tmpW, Format, Usage, Pool,
1360 i /* Level */, &object->surfaces[j][i],pSharedHandle);
1362 if(hr!= WINED3D_OK) {
1366 for (l = 0; l < j; l++) {
1367 IWineD3DSurface_Release(object->surfaces[j][i]);
1369 for (k = 0; k < i; k++) {
1370 for (l = 0; l < 6; l++) {
1371 IWineD3DSurface_Release(object->surfaces[l][j]);
1375 FIXME("(%p) Failed to create surface\n",object);
1376 HeapFree(GetProcessHeap(),0,object);
1377 *ppCubeTexture = NULL;
1380 IWineD3DSurface_SetContainer(object->surfaces[j][i], (IWineD3DBase *)object);
1381 TRACE("Created surface level %d @ %p,\n", i, object->surfaces[j][i]);
1383 tmpW = max(1, tmpW >> 1);
1386 TRACE("(%p) : Created Cube Texture %p\n", This, object);
1387 *ppCubeTexture = (IWineD3DCubeTexture *) object;
1391 static HRESULT WINAPI IWineD3DDeviceImpl_CreateQuery(IWineD3DDevice *iface, WINED3DQUERYTYPE Type, IWineD3DQuery **ppQuery, IUnknown* parent) {
1392 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
1393 IWineD3DQueryImpl *object; /*NOTE: impl ref allowed since this is a create function */
1395 if (NULL == ppQuery) {
1396 /* Just a check to see if we support this type of query */
1397 HRESULT hr = WINED3DERR_NOTAVAILABLE;
1399 case WINED3DQUERYTYPE_OCCLUSION:
1400 TRACE("(%p) occlusion query\n", This);
1401 if (GL_SUPPORT(ARB_OCCLUSION_QUERY))
1404 WARN("Unsupported in local OpenGL implementation: ARB_OCCLUSION_QUERY/NV_OCCLUSION_QUERY\n");
1406 case WINED3DQUERYTYPE_VCACHE:
1407 case WINED3DQUERYTYPE_RESOURCEMANAGER:
1408 case WINED3DQUERYTYPE_VERTEXSTATS:
1409 case WINED3DQUERYTYPE_EVENT:
1410 case WINED3DQUERYTYPE_TIMESTAMP:
1411 case WINED3DQUERYTYPE_TIMESTAMPDISJOINT:
1412 case WINED3DQUERYTYPE_TIMESTAMPFREQ:
1413 case WINED3DQUERYTYPE_PIPELINETIMINGS:
1414 case WINED3DQUERYTYPE_INTERFACETIMINGS:
1415 case WINED3DQUERYTYPE_VERTEXTIMINGS:
1416 case WINED3DQUERYTYPE_PIXELTIMINGS:
1417 case WINED3DQUERYTYPE_BANDWIDTHTIMINGS:
1418 case WINED3DQUERYTYPE_CACHEUTILIZATION:
1420 FIXME("(%p) Unhandled query type %d\n", This, Type);
1425 D3DCREATEOBJECTINSTANCE(object, Query)
1426 object->type = Type;
1427 /* allocated the 'extended' data based on the type of query requested */
1429 case D3DQUERYTYPE_OCCLUSION:
1430 if(GL_SUPPORT(ARB_OCCLUSION_QUERY)) {
1431 TRACE("(%p) Allocating data for an occlusion query\n", This);
1432 object->extendedData = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(WineQueryOcclusionData));
1433 GL_EXTCALL(glGenQueriesARB(1, &((WineQueryOcclusionData *)(object->extendedData))->queryId));
1436 case D3DQUERYTYPE_VCACHE:
1437 case D3DQUERYTYPE_RESOURCEMANAGER:
1438 case D3DQUERYTYPE_VERTEXSTATS:
1439 case D3DQUERYTYPE_EVENT:
1440 case D3DQUERYTYPE_TIMESTAMP:
1441 case D3DQUERYTYPE_TIMESTAMPDISJOINT:
1442 case D3DQUERYTYPE_TIMESTAMPFREQ:
1443 case D3DQUERYTYPE_PIPELINETIMINGS:
1444 case D3DQUERYTYPE_INTERFACETIMINGS:
1445 case D3DQUERYTYPE_VERTEXTIMINGS:
1446 case D3DQUERYTYPE_PIXELTIMINGS:
1447 case D3DQUERYTYPE_BANDWIDTHTIMINGS:
1448 case D3DQUERYTYPE_CACHEUTILIZATION:
1450 object->extendedData = 0;
1451 FIXME("(%p) Unhandled query type %d\n",This , Type);
1453 TRACE("(%p) : Created Query %p\n", This, object);
1457 /* example at http://www.fairyengine.com/articles/dxmultiviews.htm */
1458 static HRESULT WINAPI IWineD3DDeviceImpl_CreateAdditionalSwapChain(IWineD3DDevice* iface, WINED3DPRESENT_PARAMETERS* pPresentationParameters, IWineD3DSwapChain** ppSwapChain,
1460 D3DCB_CREATERENDERTARGETFN D3DCB_CreateRenderTarget,
1461 D3DCB_CREATEDEPTHSTENCILSURFACEFN D3DCB_CreateDepthStencil) {
1462 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
1465 IWineD3DSwapChainImpl *object; /** NOTE: impl ref allowed since this is a create function **/
1467 XVisualInfo template;
1468 GLXContext oldContext;
1469 Drawable oldDrawable;
1470 HRESULT hr = WINED3D_OK;
1472 TRACE("(%p) : Created Aditional Swap Chain\n", This);
1474 /** FIXME: Test under windows to find out what the life cycle of a swap chain is,
1475 * does a device hold a reference to a swap chain giving them a lifetime of the device
1476 * or does the swap chain notify the device of its destruction.
1477 *******************************/
1479 /* Check the params */
1480 if(*pPresentationParameters->BackBufferCount > D3DPRESENT_BACK_BUFFER_MAX) {
1481 ERR("App requested %d back buffers, this is not supported for now\n", *pPresentationParameters->BackBufferCount);
1482 return WINED3DERR_INVALIDCALL;
1483 } else if (*pPresentationParameters->BackBufferCount > 1) {
1484 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");
1487 D3DCREATEOBJECTINSTANCE(object, SwapChain)
1489 /*********************
1490 * Lookup the window Handle and the relating X window handle
1491 ********************/
1493 /* Setup hwnd we are using, plus which display this equates to */
1494 object->win_handle = *(pPresentationParameters->hDeviceWindow);
1495 if (!object->win_handle) {
1496 object->win_handle = This->createParms.hFocusWindow;
1499 object->win_handle = GetAncestor(object->win_handle, GA_ROOT);
1500 if ( !( object->win = (Window)GetPropA(object->win_handle, "__wine_x11_whole_window") ) ) {
1501 ERR("Can't get drawable (window), HWND:%p doesn't have the property __wine_x11_whole_window\n", object->win_handle);
1502 return WINED3DERR_NOTAVAILABLE;
1504 hDc = GetDC(object->win_handle);
1505 object->display = get_display(hDc);
1506 ReleaseDC(object->win_handle, hDc);
1507 TRACE("Using a display of %p %p\n", object->display, hDc);
1509 if (NULL == object->display || NULL == hDc) {
1510 WARN("Failed to get a display and HDc for Window %p\n", object->win_handle);
1511 return WINED3DERR_NOTAVAILABLE;
1514 if (object->win == 0) {
1515 WARN("Failed to get a valid XVisuial ID for the window %p\n", object->win_handle);
1516 return WINED3DERR_NOTAVAILABLE;
1519 * Create an opengl context for the display visual
1520 * NOTE: the visual is chosen as the window is created and the glcontext cannot
1521 * use different properties after that point in time. FIXME: How to handle when requested format
1522 * doesn't match actual visual? Cannot choose one here - code removed as it ONLY works if the one
1523 * it chooses is identical to the one already being used!
1524 **********************************/
1526 /** FIXME: Handle stencil appropriately via EnableAutoDepthStencil / AutoDepthStencilFormat **/
1529 /* Create a new context for this swapchain */
1530 template.visualid = (VisualID)GetPropA(GetDesktopWindow(), "__wine_x11_visual_id");
1531 /* TODO: change this to find a similar visual, but one with a stencil/zbuffer buffer that matches the request
1532 (or the best possible if none is requested) */
1533 TRACE("Found x visual ID : %ld\n", template.visualid);
1535 object->visInfo = XGetVisualInfo(object->display, VisualIDMask, &template, &num);
1536 if (NULL == object->visInfo) {
1537 ERR("cannot really get XVisual\n");
1539 return WINED3DERR_NOTAVAILABLE;
1542 /* Write out some debug info about the visual/s */
1543 TRACE("Using x visual ID : %ld\n", template.visualid);
1544 TRACE(" visual info: %p\n", object->visInfo);
1545 TRACE(" num items : %d\n", num);
1546 for (n = 0;n < num; n++) {
1547 TRACE("=====item=====: %d\n", n + 1);
1548 TRACE(" visualid : %ld\n", object->visInfo[n].visualid);
1549 TRACE(" screen : %d\n", object->visInfo[n].screen);
1550 TRACE(" depth : %u\n", object->visInfo[n].depth);
1551 TRACE(" class : %d\n", object->visInfo[n].class);
1552 TRACE(" red_mask : %ld\n", object->visInfo[n].red_mask);
1553 TRACE(" green_mask : %ld\n", object->visInfo[n].green_mask);
1554 TRACE(" blue_mask : %ld\n", object->visInfo[n].blue_mask);
1555 TRACE(" colormap_size : %d\n", object->visInfo[n].colormap_size);
1556 TRACE(" bits_per_rgb : %d\n", object->visInfo[n].bits_per_rgb);
1557 /* log some extra glx info */
1558 glXGetConfig(object->display, object->visInfo, GLX_AUX_BUFFERS, &value);
1559 TRACE(" gl_aux_buffers : %d\n", value);
1560 glXGetConfig(object->display, object->visInfo, GLX_BUFFER_SIZE ,&value);
1561 TRACE(" gl_buffer_size : %d\n", value);
1562 glXGetConfig(object->display, object->visInfo, GLX_RED_SIZE, &value);
1563 TRACE(" gl_red_size : %d\n", value);
1564 glXGetConfig(object->display, object->visInfo, GLX_GREEN_SIZE, &value);
1565 TRACE(" gl_green_size : %d\n", value);
1566 glXGetConfig(object->display, object->visInfo, GLX_BLUE_SIZE, &value);
1567 TRACE(" gl_blue_size : %d\n", value);
1568 glXGetConfig(object->display, object->visInfo, GLX_ALPHA_SIZE, &value);
1569 TRACE(" gl_alpha_size : %d\n", value);
1570 glXGetConfig(object->display, object->visInfo, GLX_DEPTH_SIZE ,&value);
1571 TRACE(" gl_depth_size : %d\n", value);
1572 glXGetConfig(object->display, object->visInfo, GLX_STENCIL_SIZE, &value);
1573 TRACE(" gl_stencil_size : %d\n", value);
1575 /* Now choose a simila visual ID*/
1577 #ifdef USE_CONTEXT_MANAGER
1579 /** TODO: use a context mamager **/
1583 IWineD3DSwapChain *implSwapChain;
1584 if (WINED3D_OK != IWineD3DDevice_GetSwapChain(iface, 0, &implSwapChain)) {
1585 /* The first time around we create the context that is shared with all other swapchains and render targets */
1586 object->glCtx = glXCreateContext(object->display, object->visInfo, NULL, GL_TRUE);
1587 TRACE("Creating implicit context for vis %p, hwnd %p\n", object->display, object->visInfo);
1590 TRACE("Creating context for vis %p, hwnd %p\n", object->display, object->visInfo);
1591 /* TODO: don't use Impl structures outside of create functions! (a context manager will replace the ->glCtx) */
1592 /* and create a new context with the implicit swapchains context as the shared context */
1593 object->glCtx = glXCreateContext(object->display, object->visInfo, ((IWineD3DSwapChainImpl *)implSwapChain)->glCtx, GL_TRUE);
1594 IWineD3DSwapChain_Release(implSwapChain);
1599 XFree(object->visInfo);
1600 object->visInfo = NULL;
1604 if (!object->glCtx) {
1605 ERR("Failed to create GLX context\n");
1606 return WINED3DERR_NOTAVAILABLE;
1608 TRACE("Context created (HWND=%p, glContext=%p, Window=%ld, VisInfo=%p)\n",
1609 object->win_handle, object->glCtx, object->win, object->visInfo);
1612 /*********************
1613 * Windowed / Fullscreen
1614 *******************/
1617 * TODO: MSDN says that we are only allowed one fullscreen swapchain per device,
1618 * so we should really check to see if there is a fullscreen swapchain already
1619 * I think Windows and X have different ideas about fullscreen, does a single head count as full screen?
1620 **************************************/
1622 if (!*(pPresentationParameters->Windowed)) {
1628 /* Get info on the current display setup */
1629 hdc = CreateDCA("DISPLAY", NULL, NULL, NULL);
1630 bpp = GetDeviceCaps(hdc, BITSPIXEL);
1633 /* Change the display settings */
1634 memset(&devmode, 0, sizeof(DEVMODEW));
1635 devmode.dmFields = DM_BITSPERPEL | DM_PELSWIDTH | DM_PELSHEIGHT;
1636 devmode.dmBitsPerPel = (bpp >= 24) ? 32 : bpp; /* Stupid XVidMode cannot change bpp */
1637 devmode.dmPelsWidth = *(pPresentationParameters->BackBufferWidth);
1638 devmode.dmPelsHeight = *(pPresentationParameters->BackBufferHeight);
1639 MultiByteToWideChar(CP_ACP, 0, "Gamers CG", -1, devmode.dmDeviceName, CCHDEVICENAME);
1640 ChangeDisplaySettingsExW(devmode.dmDeviceName, &devmode, object->win_handle, CDS_FULLSCREEN, NULL);
1642 /* Make popup window */
1643 SetWindowLongA(object->win_handle, GWL_STYLE, WS_POPUP);
1644 SetWindowPos(object->win_handle, HWND_TOP, 0, 0,
1645 *(pPresentationParameters->BackBufferWidth),
1646 *(pPresentationParameters->BackBufferHeight), SWP_SHOWWINDOW | SWP_FRAMECHANGED);
1648 /* For GetDisplayMode */
1649 This->ddraw_width = devmode.dmPelsWidth;
1650 This->ddraw_height = devmode.dmPelsHeight;
1651 This->ddraw_format = *(pPresentationParameters->BackBufferFormat);
1655 /** MSDN: If Windowed is TRUE and either of the BackBufferWidth/Height values is zero,
1656 * then the corresponding dimension of the client area of the hDeviceWindow
1657 * (or the focus window, if hDeviceWindow is NULL) is taken.
1658 **********************/
1660 if (*(pPresentationParameters->Windowed) &&
1661 ((*(pPresentationParameters->BackBufferWidth) == 0) ||
1662 (*(pPresentationParameters->BackBufferHeight) == 0))) {
1665 GetClientRect(object->win_handle, &Rect);
1667 if (*(pPresentationParameters->BackBufferWidth) == 0) {
1668 *(pPresentationParameters->BackBufferWidth) = Rect.right;
1669 TRACE("Updating width to %d\n", *(pPresentationParameters->BackBufferWidth));
1671 if (*(pPresentationParameters->BackBufferHeight) == 0) {
1672 *(pPresentationParameters->BackBufferHeight) = Rect.bottom;
1673 TRACE("Updating height to %d\n", *(pPresentationParameters->BackBufferHeight));
1677 /*********************
1678 * finish off parameter initialization
1679 *******************/
1681 /* Put the correct figures in the presentation parameters */
1682 TRACE("Coppying accross presentaion paraneters\n");
1683 object->presentParms.BackBufferWidth = *(pPresentationParameters->BackBufferWidth);
1684 object->presentParms.BackBufferHeight = *(pPresentationParameters->BackBufferHeight);
1685 object->presentParms.BackBufferFormat = *(pPresentationParameters->BackBufferFormat);
1686 object->presentParms.BackBufferCount = *(pPresentationParameters->BackBufferCount);
1687 object->presentParms.MultiSampleType = *(pPresentationParameters->MultiSampleType);
1688 object->presentParms.MultiSampleQuality = NULL == pPresentationParameters->MultiSampleQuality ? 0 : *(pPresentationParameters->MultiSampleQuality);
1689 object->presentParms.SwapEffect = *(pPresentationParameters->SwapEffect);
1690 object->presentParms.hDeviceWindow = *(pPresentationParameters->hDeviceWindow);
1691 object->presentParms.Windowed = *(pPresentationParameters->Windowed);
1692 object->presentParms.EnableAutoDepthStencil = *(pPresentationParameters->EnableAutoDepthStencil);
1693 object->presentParms.AutoDepthStencilFormat = *(pPresentationParameters->AutoDepthStencilFormat);
1694 object->presentParms.Flags = *(pPresentationParameters->Flags);
1695 object->presentParms.FullScreen_RefreshRateInHz = *(pPresentationParameters->FullScreen_RefreshRateInHz);
1696 object->presentParms.PresentationInterval = *(pPresentationParameters->PresentationInterval);
1699 /*********************
1700 * Create the back, front and stencil buffers
1701 *******************/
1703 TRACE("calling rendertarget CB\n");
1704 hr = D3DCB_CreateRenderTarget((IUnknown *) This->parent,
1705 object->presentParms.BackBufferWidth,
1706 object->presentParms.BackBufferHeight,
1707 object->presentParms.BackBufferFormat,
1708 object->presentParms.MultiSampleType,
1709 object->presentParms.MultiSampleQuality,
1710 TRUE /* Lockable */,
1711 &object->frontBuffer,
1712 NULL /* pShared (always null)*/);
1713 if (object->frontBuffer != NULL)
1714 IWineD3DSurface_SetContainer(object->frontBuffer, (IWineD3DBase *)object);
1716 if(object->presentParms.BackBufferCount > 0) {
1719 object->backBuffer = HeapAlloc(GetProcessHeap(), 0, sizeof(IWineD3DSurface *) * object->presentParms.BackBufferCount);
1720 if(!object->backBuffer) {
1721 ERR("Out of memory\n");
1723 if (object->frontBuffer) {
1724 IUnknown *bufferParent;
1725 IWineD3DSurface_GetParent(object->frontBuffer, &bufferParent);
1726 IUnknown_Release(bufferParent); /* once for the get parent */
1727 if (IUnknown_Release(bufferParent) > 0) {
1728 FIXME("(%p) Something's still holding the front buffer\n",This);
1731 HeapFree(GetProcessHeap(), 0, object);
1732 return E_OUTOFMEMORY;
1735 for(i = 0; i < object->presentParms.BackBufferCount; i++) {
1736 TRACE("calling rendertarget CB\n");
1737 hr = D3DCB_CreateRenderTarget((IUnknown *) This->parent,
1738 object->presentParms.BackBufferWidth,
1739 object->presentParms.BackBufferHeight,
1740 object->presentParms.BackBufferFormat,
1741 object->presentParms.MultiSampleType,
1742 object->presentParms.MultiSampleQuality,
1743 TRUE /* Lockable */,
1744 &object->backBuffer[i],
1745 NULL /* pShared (always null)*/);
1746 if(hr == WINED3D_OK && object->backBuffer[i]) {
1747 IWineD3DSurface_SetContainer(object->backBuffer[i], (IWineD3DBase *)object);
1753 object->backBuffer = NULL;
1756 if (object->backBuffer != NULL) {
1758 glDrawBuffer(GL_BACK);
1759 checkGLcall("glDrawBuffer(GL_BACK)");
1762 /* Single buffering - draw to front buffer */
1764 glDrawBuffer(GL_FRONT);
1765 checkGLcall("glDrawBuffer(GL_FRONT)");
1769 /* Under directX swapchains share the depth stencil, so only create one depth-stencil */
1770 if (*(pPresentationParameters->EnableAutoDepthStencil) && hr == WINED3D_OK) {
1771 TRACE("Creating depth stencil buffer\n");
1772 if (This->depthStencilBuffer == NULL ) {
1773 hr = D3DCB_CreateDepthStencil((IUnknown *) This->parent,
1774 object->presentParms.BackBufferWidth,
1775 object->presentParms.BackBufferHeight,
1776 object->presentParms.AutoDepthStencilFormat,
1777 object->presentParms.MultiSampleType,
1778 object->presentParms.MultiSampleQuality,
1779 FALSE /* FIXME: Discard */,
1780 &This->depthStencilBuffer,
1781 NULL /* pShared (always null)*/ );
1782 if (This->depthStencilBuffer != NULL)
1783 IWineD3DSurface_SetContainer(This->depthStencilBuffer, 0);
1786 /** TODO: A check on width, height and multisample types
1787 *(since the zbuffer must be at least as large as the render target and have the same multisample parameters)
1788 ****************************/
1789 object->wantsDepthStencilBuffer = TRUE;
1791 object->wantsDepthStencilBuffer = FALSE;
1794 TRACE("FrontBuf @ %p, BackBuf @ %p, DepthStencil %d\n",object->frontBuffer, object->backBuffer ? object->backBuffer[0] : NULL, object->wantsDepthStencilBuffer);
1797 /*********************
1798 * init the default renderTarget management
1799 *******************/
1800 object->drawable = object->win;
1801 object->render_ctx = object->glCtx;
1803 if (hr == WINED3D_OK) {
1804 /*********************
1805 * Setup some defaults and clear down the buffers
1806 *******************/
1808 /** save current context and drawable **/
1809 oldContext = glXGetCurrentContext();
1810 oldDrawable = glXGetCurrentDrawable();
1812 TRACE("Activating context (display %p context %p drawable %ld)!\n", object->display, object->glCtx, object->win);
1813 if (glXMakeCurrent(object->display, object->win, object->glCtx) == False) {
1814 ERR("Error in setting current context (display %p context %p drawable %ld)!\n", object->display, object->glCtx, object->win);
1816 checkGLcall("glXMakeCurrent");
1818 TRACE("Setting up the screen\n");
1819 /* Clear the screen */
1820 glClearColor(1.0, 0.0, 0.0, 0.0);
1821 checkGLcall("glClearColor");
1824 glClearStencil(0xffff);
1826 checkGLcall("glClear");
1828 glColor3f(1.0, 1.0, 1.0);
1829 checkGLcall("glColor3f");
1831 glEnable(GL_LIGHTING);
1832 checkGLcall("glEnable");
1834 glLightModeli(GL_LIGHT_MODEL_LOCAL_VIEWER, GL_TRUE);
1835 checkGLcall("glLightModeli(GL_LIGHT_MODEL_LOCAL_VIEWER, GL_TRUE);");
1837 glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE_EXT);
1838 checkGLcall("glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE_EXT);");
1840 glLightModeli(GL_LIGHT_MODEL_COLOR_CONTROL, GL_SEPARATE_SPECULAR_COLOR);
1841 checkGLcall("glLightModeli(GL_LIGHT_MODEL_COLOR_CONTROL, GL_SEPARATE_SPECULAR_COLOR);");
1843 /* switch back to the original context (if there was one)*/
1844 if (This->swapchains) {
1845 /** TODO: restore the context and drawable **/
1846 glXMakeCurrent(object->display, oldDrawable, oldContext);
1851 TRACE("Set swapchain to %p\n", object);
1852 } else { /* something went wrong so clean up */
1853 IUnknown* bufferParent;
1854 if (object->frontBuffer) {
1856 IWineD3DSurface_GetParent(object->frontBuffer, &bufferParent);
1857 IUnknown_Release(bufferParent); /* once for the get parent */
1858 if (IUnknown_Release(bufferParent) > 0) {
1859 FIXME("(%p) Something's still holding the front buffer\n",This);
1862 if (object->backBuffer) {
1864 for(i = 0; i < object->presentParms.BackBufferCount; i++) {
1865 if(object->backBuffer[i]) {
1866 IWineD3DSurface_GetParent(object->backBuffer[i], &bufferParent);
1867 IUnknown_Release(bufferParent); /* once for the get parent */
1868 if (IUnknown_Release(bufferParent) > 0) {
1869 FIXME("(%p) Something's still holding the back buffer\n",This);
1873 HeapFree(GetProcessHeap(), 0, object->backBuffer);
1874 object->backBuffer = NULL;
1876 /* NOTE: don't clean up the depthstencil buffer because it belongs to the device */
1877 /* Clean up the context */
1878 /* check that we are the current context first (we shouldn't be though!) */
1879 if (object->glCtx != 0) {
1880 if(glXGetCurrentContext() == object->glCtx) {
1881 glXMakeCurrent(object->display, None, NULL);
1883 glXDestroyContext(object->display, object->glCtx);
1885 HeapFree(GetProcessHeap(), 0, object);
1892 /** NOTE: These are ahead of the other getters and setters to save using a forward declaration **/
1893 static UINT WINAPI IWineD3DDeviceImpl_GetNumberOfSwapChains(IWineD3DDevice *iface) {
1894 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
1895 TRACE("(%p)\n", This);
1897 return This->NumberOfSwapChains;
1900 static HRESULT WINAPI IWineD3DDeviceImpl_GetSwapChain(IWineD3DDevice *iface, UINT iSwapChain, IWineD3DSwapChain **pSwapChain) {
1901 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
1902 TRACE("(%p) : swapchain %d\n", This, iSwapChain);
1904 if(iSwapChain < This->NumberOfSwapChains) {
1905 *pSwapChain = This->swapchains[iSwapChain];
1906 IWineD3DSwapChain_AddRef(*pSwapChain);
1907 TRACE("(%p) returning %p\n", This, *pSwapChain);
1910 TRACE("Swapchain out of range\n");
1912 return WINED3DERR_INVALIDCALL;
1917 * Vertex Declaration
1919 static HRESULT WINAPI IWineD3DDeviceImpl_CreateVertexDeclaration(IWineD3DDevice* iface, CONST VOID* pDeclaration, IWineD3DVertexDeclaration** ppVertexDeclaration, IUnknown *parent) {
1920 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
1921 IWineD3DVertexDeclarationImpl *object = NULL;
1922 HRESULT hr = WINED3D_OK;
1923 TRACE("(%p) : directXVersion=%u, pFunction=%p, ppDecl=%p\n", This, ((IWineD3DImpl *)This->wineD3D)->dxVersion, pDeclaration, ppVertexDeclaration);
1924 D3DCREATEOBJECTINSTANCE(object, VertexDeclaration)
1927 hr = IWineD3DVertexDeclaration_SetDeclaration((IWineD3DVertexDeclaration *)object, (void *)pDeclaration);
1932 /* http://msdn.microsoft.com/archive/default.asp?url=/archive/en-us/directx9_c/directx/graphics/programmingguide/programmable/vertexshaders/vscreate.asp */
1933 static HRESULT WINAPI IWineD3DDeviceImpl_CreateVertexShader(IWineD3DDevice *iface, CONST DWORD *pDeclaration, CONST DWORD *pFunction, IWineD3DVertexShader **ppVertexShader, IUnknown *parent) {
1934 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
1935 IWineD3DVertexShaderImpl *object; /* NOTE: impl usage is ok, this is a create */
1936 HRESULT hr = WINED3D_OK;
1937 D3DCREATEOBJECTINSTANCE(object, VertexShader)
1938 object->baseShader.shader_ins = IWineD3DVertexShaderImpl_shader_ins;
1940 TRACE("(%p) : Created Vertex shader %p\n", This, *ppVertexShader);
1942 /* If a vertex declaration has been passed, save it to the vertex shader, this affects d3d8 only. */
1943 /* Further it needs to be set before calling SetFunction as SetFunction needs the declaration. */
1944 if (pDeclaration != NULL) {
1945 IWineD3DVertexDeclaration *vertexDeclaration;
1946 hr = IWineD3DDevice_CreateVertexDeclaration(iface, pDeclaration, &vertexDeclaration ,NULL);
1947 if (WINED3D_OK == hr) {
1948 TRACE("(%p) : Setting vertex declaration to %p\n", This, vertexDeclaration);
1949 object->vertexDeclaration = vertexDeclaration;
1951 FIXME("(%p) : Failed to set the declaration, returning WINED3DERR_INVALIDCALL\n", iface);
1952 IWineD3DVertexShader_Release(*ppVertexShader);
1953 return WINED3DERR_INVALIDCALL;
1957 hr = IWineD3DVertexShader_SetFunction(*ppVertexShader, pFunction);
1959 if (WINED3D_OK != hr) {
1960 FIXME("(%p) : Failed to set the function, returning WINED3DERR_INVALIDCALL\n", iface);
1961 IWineD3DVertexShader_Release(*ppVertexShader);
1962 return WINED3DERR_INVALIDCALL;
1965 #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. */
1966 if(Usage == WINED3DUSAGE_SOFTWAREVERTEXPROCESSING) {
1977 static HRESULT WINAPI IWineD3DDeviceImpl_CreatePixelShader(IWineD3DDevice *iface, CONST DWORD *pFunction, IWineD3DPixelShader **ppPixelShader, IUnknown *parent) {
1978 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
1979 IWineD3DPixelShaderImpl *object; /* NOTE: impl allowed, this is a create */
1980 HRESULT hr = WINED3D_OK;
1982 D3DCREATEOBJECTINSTANCE(object, PixelShader)
1983 object->baseShader.shader_ins = IWineD3DPixelShaderImpl_shader_ins;
1984 hr = IWineD3DPixelShader_SetFunction(*ppPixelShader, pFunction);
1985 if (WINED3D_OK == hr) {
1986 TRACE("(%p) : Created Pixel shader %p\n", This, *ppPixelShader);
1988 WARN("(%p) : Failed to create pixel shader\n", This);
1994 static HRESULT WINAPI IWineD3DDeviceImpl_CreatePalette(IWineD3DDevice *iface, DWORD Flags, PALETTEENTRY *PalEnt, IWineD3DPalette **Palette, IUnknown *Parent) {
1995 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *) iface;
1996 IWineD3DPaletteImpl *object;
1998 TRACE("(%p)->(%lx, %p, %p, %p)\n", This, Flags, PalEnt, Palette, Parent);
2000 /* Create the new object */
2001 object = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(IWineD3DPaletteImpl));
2003 ERR("Out of memory when allocating memory for a IWineD3DPalette implementation\n");
2004 return E_OUTOFMEMORY;
2007 object->lpVtbl = &IWineD3DPalette_Vtbl;
2009 object->Flags = Flags;
2010 object->parent = Parent;
2011 object->wineD3DDevice = This;
2012 object->palNumEntries = IWineD3DPaletteImpl_Size(Flags);
2014 object->hpal = CreatePalette((const LOGPALETTE*)&(object->palVersion));
2017 HeapFree( GetProcessHeap(), 0, object);
2018 return E_OUTOFMEMORY;
2021 hr = IWineD3DPalette_SetEntries((IWineD3DPalette *) object, 0, 0, IWineD3DPaletteImpl_Size(Flags), PalEnt);
2023 IWineD3DPalette_Release((IWineD3DPalette *) object);
2027 *Palette = (IWineD3DPalette *) object;
2032 static HRESULT WINAPI IWineD3DDeviceImpl_Init3D(IWineD3DDevice *iface, WINED3DPRESENT_PARAMETERS* pPresentationParameters, D3DCB_CREATEADDITIONALSWAPCHAIN D3DCB_CreateAdditionalSwapChain) {
2033 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *) iface;
2034 IWineD3DSwapChainImpl *swapchain;
2036 TRACE("(%p)->(%p,%p)\n", This, pPresentationParameters, D3DCB_CreateAdditionalSwapChain);
2037 if(This->d3d_initialized) return WINED3DERR_INVALIDCALL;
2039 /* TODO: Test if OpenGL is compiled in and loaded */
2041 /* Setup the implicit swapchain */
2042 TRACE("Creating implicit swapchain\n");
2043 if (D3D_OK != D3DCB_CreateAdditionalSwapChain((IUnknown *) This->parent, pPresentationParameters, (IWineD3DSwapChain **)&swapchain) || swapchain == NULL) {
2044 WARN("Failed to create implicit swapchain\n");
2045 return WINED3DERR_INVALIDCALL;
2048 This->NumberOfSwapChains = 1;
2049 This->swapchains = HeapAlloc(GetProcessHeap(), 0, This->NumberOfSwapChains * sizeof(IWineD3DSwapChain *));
2050 if(!This->swapchains) {
2051 ERR("Out of memory!\n");
2052 IWineD3DSwapChain_Release( (IWineD3DSwapChain *) swapchain);
2053 return E_OUTOFMEMORY;
2055 This->swapchains[0] = (IWineD3DSwapChain *) swapchain;
2057 if(swapchain->backBuffer && swapchain->backBuffer[0]) {
2058 TRACE("Setting rendertarget to %p\n", swapchain->backBuffer);
2059 This->renderTarget = swapchain->backBuffer[0];
2062 TRACE("Setting rendertarget to %p\n", swapchain->frontBuffer);
2063 This->renderTarget = swapchain->frontBuffer;
2065 IWineD3DSurface_AddRef(This->renderTarget);
2066 /* Depth Stencil support */
2067 This->stencilBufferTarget = This->depthStencilBuffer;
2068 if (NULL != This->stencilBufferTarget) {
2069 IWineD3DSurface_AddRef(This->stencilBufferTarget);
2072 /* Set up some starting GL setup */
2075 * Initialize openGL extension related variables
2076 * with Default values
2079 ((IWineD3DImpl *) This->wineD3D)->isGLInfoValid = IWineD3DImpl_FillGLCaps( This->wineD3D, swapchain->display);
2080 /* Setup all the devices defaults */
2081 IWineD3DStateBlock_InitStartupStateBlock((IWineD3DStateBlock *)This->stateBlock);
2083 IWineD3DImpl_CheckGraphicsMemory();
2087 /* Initialize our list of GLSL programs */
2088 list_init(&This->glsl_shader_progs);
2090 { /* Set a default viewport */
2094 vp.Width = *(pPresentationParameters->BackBufferWidth);
2095 vp.Height = *(pPresentationParameters->BackBufferHeight);
2098 IWineD3DDevice_SetViewport((IWineD3DDevice *)This, &vp);
2101 /* Initialize the current view state */
2102 This->modelview_valid = 1;
2103 This->proj_valid = 0;
2104 This->view_ident = 1;
2105 This->last_was_rhw = 0;
2106 glGetIntegerv(GL_MAX_LIGHTS, &This->maxConcurrentLights);
2107 TRACE("(%p) All defaults now set up, leaving Init3D with %p\n", This, This);
2109 /* Clear the screen */
2110 IWineD3DDevice_Clear((IWineD3DDevice *) This, 0, NULL, D3DCLEAR_STENCIL|D3DCLEAR_ZBUFFER|D3DCLEAR_TARGET, 0x00, 1.0, 0);
2112 This->d3d_initialized = TRUE;
2116 static HRESULT WINAPI IWineD3DDeviceImpl_Uninit3D(IWineD3DDevice *iface) {
2117 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *) iface;
2119 IUnknown* stencilBufferParent;
2120 IUnknown* swapChainParent;
2122 TRACE("(%p)\n", This);
2124 if(!This->d3d_initialized) return WINED3DERR_INVALIDCALL;
2126 /* Delete the mouse cursor texture */
2127 if(This->cursorTexture) {
2129 glDeleteTextures(1, &This->cursorTexture);
2131 This->cursorTexture = 0;
2134 for(sampler = 0; sampler < GL_LIMITS(sampler_stages); ++sampler) {
2135 IWineD3DDevice_SetTexture(iface, sampler, NULL);
2138 /* Release the buffers (with sanity checks)*/
2139 TRACE("Releasing the depth stencil buffer at %p\n", This->stencilBufferTarget);
2140 if(This->stencilBufferTarget != NULL && (IWineD3DSurface_Release(This->stencilBufferTarget) >0)){
2141 if(This->depthStencilBuffer != This->stencilBufferTarget)
2142 FIXME("(%p) Something's still holding the depthStencilBuffer\n",This);
2144 This->stencilBufferTarget = NULL;
2146 TRACE("Releasing the render target at %p\n", This->renderTarget);
2147 if(IWineD3DSurface_Release(This->renderTarget) >0){
2148 /* This check is a bit silly, itshould be in swapchain_release FIXME("(%p) Something's still holding the renderTarget\n",This); */
2150 TRACE("Setting rendertarget to NULL\n");
2151 This->renderTarget = NULL;
2153 if (This->depthStencilBuffer) {
2154 IWineD3DSurface_GetParent(This->depthStencilBuffer, &stencilBufferParent);
2155 IUnknown_Release(stencilBufferParent); /* once for the get parent */
2156 if(IUnknown_Release(stencilBufferParent) >0){ /* the second time for when it was created */
2157 FIXME("(%p) Something's still holding the depthStencilBuffer\n",This);
2159 This->depthStencilBuffer = NULL;
2162 for(i=0; i < This->NumberOfSwapChains; i++) {
2163 TRACE("Releasing the implicit swapchain %d\n", i);
2164 /* Swapchain 0 is special because it's created in startup with a hanging parent, so we have to release its parent now */
2165 IWineD3DSwapChain_GetParent(This->swapchains[i], &swapChainParent);
2166 IUnknown_Release(swapChainParent); /* once for the get parent */
2167 if (IUnknown_Release(swapChainParent) > 0) { /* the second time for when it was created */
2168 FIXME("(%p) Something's still holding the implicit swapchain\n", This);
2172 HeapFree(GetProcessHeap(), 0, This->swapchains);
2173 This->swapchains = NULL;
2174 This->NumberOfSwapChains = 0;
2176 This->d3d_initialized = FALSE;
2180 static void WINAPI IWineD3DDeviceImpl_SetFullscreen(IWineD3DDevice *iface, BOOL fullscreen) {
2181 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *) iface;
2182 TRACE("(%p) Setting DDraw fullscreen mode to %s\n", This, fullscreen ? "true" : "false");
2184 /* DirectDraw apps can change between fullscreen and windowed mode after device creation with
2185 * IDirectDraw7::SetCooperativeLevel. The GDI surface implementation needs to know this.
2186 * DDraw doesn't necessarilly have a swapchain, so we have to store the fullscreen flag
2189 This->ddraw_fullscreen = fullscreen;
2192 static HRESULT WINAPI IWineD3DDeviceImpl_EnumDisplayModes(IWineD3DDevice *iface, DWORD Flags, UINT Width, UINT Height, WINED3DFORMAT pixelformat, LPVOID context, D3DCB_ENUMDISPLAYMODESCALLBACK callback) {
2193 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2197 const PixelFormatDesc *formatDesc = getFormatDescEntry(pixelformat);
2199 TRACE("(%p)->(%lx,%d,%d,%d,%p,%p)\n", This, Flags, Width, Height, pixelformat, context, callback);
2201 for (i = 0; EnumDisplaySettingsExW(NULL, i, &DevModeW, 0); i++) {
2202 /* Ignore some modes if a description was passed */
2203 if ( (Width > 0) && (Width != DevModeW.dmPelsWidth)) continue;
2204 if ( (Height > 0) && (Height != DevModeW.dmPelsHeight)) continue;
2205 if ( (pixelformat != WINED3DFMT_UNKNOWN) && ( formatDesc->bpp != DevModeW.dmBitsPerPel) ) continue;
2207 TRACE("Enumerating %ldx%ld@%s\n", DevModeW.dmPelsWidth, DevModeW.dmPelsHeight, debug_d3dformat(pixelformat_for_depth(DevModeW.dmBitsPerPel)));
2209 if (callback((IUnknown *) This, (UINT) DevModeW.dmPelsWidth, (UINT) DevModeW.dmPelsHeight, pixelformat_for_depth(DevModeW.dmBitsPerPel), 60.0, context) == DDENUMRET_CANCEL)
2216 static HRESULT WINAPI IWineD3DDeviceImpl_SetDisplayMode(IWineD3DDevice *iface, UINT iSwapChain, WINED3DDISPLAYMODE* pMode) {
2218 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2220 const PixelFormatDesc *formatDesc = getFormatDescEntry(pMode->Format);
2222 TRACE("(%p)->(%d,%p) Mode=%dx%dx@%d, %s\n", This, iSwapChain, pMode, pMode->Width, pMode->Height, pMode->RefreshRate, debug_d3dformat(pMode->Format));
2224 /* Resize the screen even without a window:
2225 * The app could have unset it with SetCooperativeLevel, but not called
2226 * RestoreDisplayMode first. Then the release will call RestoreDisplayMode,
2227 * but we don't have any hwnd
2230 devmode.dmFields = DM_BITSPERPEL | DM_PELSWIDTH | DM_PELSHEIGHT;
2231 devmode.dmBitsPerPel = formatDesc->bpp * 8;
2232 if(devmode.dmBitsPerPel == 24) devmode.dmBitsPerPel = 32;
2233 devmode.dmPelsWidth = pMode->Width;
2234 devmode.dmPelsHeight = pMode->Height;
2236 devmode.dmDisplayFrequency = pMode->RefreshRate;
2237 if (pMode->RefreshRate != 0) {
2238 devmode.dmFields |= DM_DISPLAYFREQUENCY;
2241 /* Only change the mode if necessary */
2242 if( (This->ddraw_width == pMode->Width) &&
2243 (This->ddraw_height == pMode->Height) &&
2244 (This->ddraw_format == pMode->Format) &&
2245 (pMode->RefreshRate == 0) ) {
2249 ret = ChangeDisplaySettingsExW(NULL, &devmode, NULL, CDS_FULLSCREEN, NULL);
2250 if (ret != DISP_CHANGE_SUCCESSFUL) {
2251 if(devmode.dmDisplayFrequency != 0) {
2252 WARN("ChangeDisplaySettingsExW failed, trying without the refresh rate\n");
2253 devmode.dmFields &= ~DM_DISPLAYFREQUENCY;
2254 devmode.dmDisplayFrequency = 0;
2255 ret = ChangeDisplaySettingsExW(NULL, &devmode, NULL, CDS_FULLSCREEN, NULL) != DISP_CHANGE_SUCCESSFUL;
2257 if(ret != DISP_CHANGE_SUCCESSFUL) {
2258 return DDERR_INVALIDMODE;
2262 /* Store the new values */
2263 This->ddraw_width = pMode->Width;
2264 This->ddraw_height = pMode->Height;
2265 This->ddraw_format = pMode->Format;
2267 /* Only do this with a window of course */
2268 if(This->ddraw_window)
2269 MoveWindow(This->ddraw_window, 0, 0, pMode->Width, pMode->Height, TRUE);
2274 static HRESULT WINAPI IWineD3DDeviceImpl_GetDirect3D(IWineD3DDevice *iface, IWineD3D **ppD3D) {
2275 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2276 *ppD3D= This->wineD3D;
2277 TRACE("(%p) : wineD3D returning %p\n", This, *ppD3D);
2278 IWineD3D_AddRef(*ppD3D);
2282 static UINT WINAPI IWineD3DDeviceImpl_GetAvailableTextureMem(IWineD3DDevice *iface) {
2283 /** NOTE: There's a probably a hack-around for this one by putting as many pbuffers, VBO's (or whatever)
2284 * Into the video ram as possible and seeing how many fit
2285 * you can also get the correct initial value from nvidia and ATI's driver via X
2286 * texture memory is video memory + AGP memory
2287 *******************/
2288 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2289 static BOOL showfixmes = TRUE;
2291 FIXME("(%p) : stub, simulating %dMB for now, returning %dMB left\n", This,
2292 (wined3d_settings.emulated_textureram/(1024*1024)),
2293 ((wined3d_settings.emulated_textureram - wineD3DGlobalStatistics->glsurfaceram) / (1024*1024)));
2296 TRACE("(%p) : simulating %dMB, returning %dMB left\n", This,
2297 (wined3d_settings.emulated_textureram/(1024*1024)),
2298 ((wined3d_settings.emulated_textureram - wineD3DGlobalStatistics->glsurfaceram) / (1024*1024)));
2299 /* return simulated texture memory left */
2300 return (wined3d_settings.emulated_textureram - wineD3DGlobalStatistics->glsurfaceram);
2308 static HRESULT WINAPI IWineD3DDeviceImpl_SetFVF(IWineD3DDevice *iface, DWORD fvf) {
2309 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2310 HRESULT hr = WINED3D_OK;
2312 /* Update the current state block */
2313 This->updateStateBlock->fvf = fvf;
2314 This->updateStateBlock->changed.fvf = TRUE;
2315 This->updateStateBlock->set.fvf = TRUE;
2317 TRACE("(%p) : FVF Shader FVF set to %lx\n", This, fvf);
2322 static HRESULT WINAPI IWineD3DDeviceImpl_GetFVF(IWineD3DDevice *iface, DWORD *pfvf) {
2323 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2324 TRACE("(%p) : GetFVF returning %lx\n", This, This->stateBlock->fvf);
2325 *pfvf = This->stateBlock->fvf;
2330 * Get / Set Stream Source
2332 static HRESULT WINAPI IWineD3DDeviceImpl_SetStreamSource(IWineD3DDevice *iface, UINT StreamNumber,IWineD3DVertexBuffer* pStreamData, UINT OffsetInBytes, UINT Stride) {
2333 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2334 IWineD3DVertexBuffer *oldSrc;
2336 /**TODO: instance and index data, see
2337 http://msdn.microsoft.com/library/default.asp?url=/library/en-us/directx9_c/directx/graphics/programmingguide/advancedtopics/DrawingMultipleInstances.asp
2339 http://msdn.microsoft.com/library/default.asp?url=/library/en-us/directx9_c/directx/graphics/reference/d3d/interfaces/idirect3ddevice9/SetStreamSourceFreq.asp
2342 /* D3d9 only, but shouldn't hurt d3d8 */
2345 streamFlags = StreamNumber &(D3DSTREAMSOURCE_INDEXEDDATA | D3DSTREAMSOURCE_INSTANCEDATA);
2347 if (streamFlags & D3DSTREAMSOURCE_INDEXEDDATA) {
2348 FIXME("stream index data not supported\n");
2350 if (streamFlags & D3DSTREAMSOURCE_INDEXEDDATA) {
2351 FIXME("stream instance data not supported\n");
2355 StreamNumber&= ~(D3DSTREAMSOURCE_INDEXEDDATA | D3DSTREAMSOURCE_INSTANCEDATA);
2357 if (StreamNumber >= MAX_STREAMS) {
2358 WARN("Stream out of range %d\n", StreamNumber);
2359 return WINED3DERR_INVALIDCALL;
2362 oldSrc = This->stateBlock->streamSource[StreamNumber];
2363 TRACE("(%p) : StreamNo: %d, OldStream (%p), NewStream (%p), NewStride %d\n", This, StreamNumber, oldSrc, pStreamData, Stride);
2365 This->updateStateBlock->changed.streamSource[StreamNumber] = TRUE;
2366 This->updateStateBlock->set.streamSource[StreamNumber] = TRUE;
2367 This->updateStateBlock->streamStride[StreamNumber] = Stride;
2368 This->updateStateBlock->streamSource[StreamNumber] = pStreamData;
2369 This->updateStateBlock->streamOffset[StreamNumber] = OffsetInBytes;
2370 This->updateStateBlock->streamFlags[StreamNumber] = streamFlags;
2372 /* Handle recording of state blocks */
2373 if (This->isRecordingState) {
2374 TRACE("Recording... not performing anything\n");
2378 /* Same stream object: no action */
2379 if (oldSrc == pStreamData)
2382 /* Need to do a getParent and pass the reffs up */
2383 /* MSDN says ..... When an application no longer holds a references to this interface, the interface will automatically be freed.
2384 which suggests that we shouldn't be ref counting? and do need a _release on the stream source to reset the stream source
2385 so for now, just count internally */
2386 if (pStreamData != NULL) {
2387 IWineD3DVertexBufferImpl *vbImpl = (IWineD3DVertexBufferImpl *) pStreamData;
2388 if( (vbImpl->Flags & VBFLAG_STREAM) && vbImpl->stream != StreamNumber) {
2389 WARN("Assigning a Vertex Buffer to stream %d which is already assigned to stream %d\n", StreamNumber, vbImpl->stream);
2391 vbImpl->stream = StreamNumber;
2392 vbImpl->Flags |= VBFLAG_STREAM;
2393 IWineD3DVertexBuffer_AddRef(pStreamData);
2395 if (oldSrc != NULL) {
2396 ((IWineD3DVertexBufferImpl *) oldSrc)->Flags &= ~VBFLAG_STREAM;
2397 IWineD3DVertexBuffer_Release(oldSrc);
2403 static HRESULT WINAPI IWineD3DDeviceImpl_GetStreamSource(IWineD3DDevice *iface, UINT StreamNumber,IWineD3DVertexBuffer** pStream, UINT *pOffset, UINT* pStride) {
2404 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2407 TRACE("(%p) : StreamNo: %d, Stream (%p), Stride %d\n", This, StreamNumber,
2408 This->stateBlock->streamSource[StreamNumber], This->stateBlock->streamStride[StreamNumber]);
2411 streamFlags = StreamNumber &(D3DSTREAMSOURCE_INDEXEDDATA | D3DSTREAMSOURCE_INSTANCEDATA);
2413 if (streamFlags & D3DSTREAMSOURCE_INDEXEDDATA) {
2414 FIXME("stream index data not supported\n");
2416 if (streamFlags & D3DSTREAMSOURCE_INDEXEDDATA) {
2417 FIXME("stream instance data not supported\n");
2421 StreamNumber&= ~(D3DSTREAMSOURCE_INDEXEDDATA | D3DSTREAMSOURCE_INSTANCEDATA);
2423 if (StreamNumber >= MAX_STREAMS) {
2424 WARN("Stream out of range %d\n", StreamNumber);
2425 return WINED3DERR_INVALIDCALL;
2427 *pStream = This->stateBlock->streamSource[StreamNumber];
2428 *pStride = This->stateBlock->streamStride[StreamNumber];
2430 *pOffset = This->stateBlock->streamOffset[StreamNumber];
2433 if (*pStream == NULL) {
2434 FIXME("Attempting to get an empty stream %d, returning WINED3DERR_INVALIDCALL\n", StreamNumber);
2435 return WINED3DERR_INVALIDCALL;
2438 IWineD3DVertexBuffer_AddRef(*pStream); /* We have created a new reference to the VB */
2442 /*Should be quite easy, just an extension of vertexdata
2444 http://msdn.microsoft.com/archive/default.asp?url=/archive/en-us/directx9_c_Summer_04/directx/graphics/programmingguide/advancedtopics/DrawingMultipleInstances.asp
2446 The divider is a bit odd though
2448 VertexOffset = StartVertex / Divider * StreamStride +
2449 VertexIndex / Divider * StreamStride + StreamOffset
2452 static HRESULT WINAPI IWineD3DDeviceImpl_SetStreamSourceFreq(IWineD3DDevice *iface, UINT StreamNumber, UINT Divider) {
2453 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2455 TRACE("(%p) StreamNumber(%d), Divider(%d)\n", This, StreamNumber, Divider);
2456 This->updateStateBlock->streamFlags[StreamNumber] = Divider & (D3DSTREAMSOURCE_INSTANCEDATA | D3DSTREAMSOURCE_INDEXEDDATA );
2458 This->updateStateBlock->changed.streamFreq[StreamNumber] = TRUE;
2459 This->updateStateBlock->set.streamFreq[StreamNumber] = TRUE;
2460 This->updateStateBlock->streamFreq[StreamNumber] = Divider & 0x7FFFFF;
2462 if (This->updateStateBlock->streamFlags[StreamNumber] || This->updateStateBlock->streamFreq[StreamNumber] != 1) {
2463 FIXME("Stream indexing not fully supported\n");
2469 static HRESULT WINAPI IWineD3DDeviceImpl_GetStreamSourceFreq(IWineD3DDevice *iface, UINT StreamNumber, UINT* Divider) {
2470 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2472 TRACE("(%p) StreamNumber(%d), Divider(%p)\n", This, StreamNumber, Divider);
2473 *Divider = This->updateStateBlock->streamFreq[StreamNumber] | This->updateStateBlock->streamFlags[StreamNumber];
2475 TRACE("(%p) : returning %d\n", This, *Divider);
2481 * Get / Set & Multiply Transform
2483 static HRESULT WINAPI IWineD3DDeviceImpl_SetTransform(IWineD3DDevice *iface, D3DTRANSFORMSTATETYPE d3dts, CONST D3DMATRIX* lpmatrix) {
2484 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2486 /* Most of this routine, comments included copied from ddraw tree initially: */
2487 TRACE("(%p) : Transform State=%s\n", This, debug_d3dtstype(d3dts));
2489 /* Handle recording of state blocks */
2490 if (This->isRecordingState) {
2491 TRACE("Recording... not performing anything\n");
2492 This->updateStateBlock->changed.transform[d3dts] = TRUE;
2493 This->updateStateBlock->set.transform[d3dts] = TRUE;
2494 memcpy(&This->updateStateBlock->transforms[d3dts], lpmatrix, sizeof(D3DMATRIX));
2499 * If the new matrix is the same as the current one,
2500 * we cut off any further processing. this seems to be a reasonable
2501 * optimization because as was noticed, some apps (warcraft3 for example)
2502 * tend towards setting the same matrix repeatedly for some reason.
2504 * From here on we assume that the new matrix is different, wherever it matters.
2506 if (!memcmp(&This->stateBlock->transforms[d3dts].u.m[0][0], lpmatrix, sizeof(D3DMATRIX))) {
2507 TRACE("The app is setting the same matrix over again\n");
2510 conv_mat(lpmatrix, &This->stateBlock->transforms[d3dts].u.m[0][0]);
2514 ScreenCoord = ProjectionMat * ViewMat * WorldMat * ObjectCoord
2515 where ViewMat = Camera space, WorldMat = world space.
2517 In OpenGL, camera and world space is combined into GL_MODELVIEW
2518 matrix. The Projection matrix stay projection matrix.
2521 /* Capture the times we can just ignore the change for now */
2522 if (d3dts == WINED3DTS_WORLDMATRIX(0)) {
2523 This->modelview_valid = FALSE;
2526 } else if (d3dts == WINED3DTS_PROJECTION) {
2527 This->proj_valid = FALSE;
2530 } else if (d3dts >= WINED3DTS_WORLDMATRIX(1) && d3dts <= WINED3DTS_WORLDMATRIX(255)) {
2531 /* Indexed Vertex Blending Matrices 256 -> 511 */
2532 /* Use arb_vertex_blend or NV_VERTEX_WEIGHTING? */
2533 FIXME("WINED3DTS_WORLDMATRIX(1..255) not handled\n");
2537 /* Now we really are going to have to change a matrix */
2540 if (d3dts >= WINED3DTS_TEXTURE0 && d3dts <= WINED3DTS_TEXTURE7) { /* handle texture matrices */
2541 /* This is now set with the texture unit states, it may be a good idea to flag the change though! */
2542 } else if (d3dts == WINED3DTS_VIEW) { /* handle the VIEW matrice */
2545 /* If we are changing the View matrix, reset the light and clipping planes to the new view
2546 * NOTE: We have to reset the positions even if the light/plane is not currently
2547 * enabled, since the call to enable it will not reset the position.
2548 * NOTE2: Apparently texture transforms do NOT need reapplying
2551 PLIGHTINFOEL *lightChain = NULL;
2552 This->modelview_valid = FALSE;
2553 This->view_ident = !memcmp(lpmatrix, identity, 16 * sizeof(float));
2555 glMatrixMode(GL_MODELVIEW);
2556 checkGLcall("glMatrixMode(GL_MODELVIEW)");
2558 glLoadMatrixf((float *)lpmatrix);
2559 checkGLcall("glLoadMatrixf(...)");
2562 lightChain = This->stateBlock->lights;
2563 while (lightChain && lightChain->glIndex != -1) {
2564 glLightfv(GL_LIGHT0 + lightChain->glIndex, GL_POSITION, lightChain->lightPosn);
2565 checkGLcall("glLightfv posn");
2566 glLightfv(GL_LIGHT0 + lightChain->glIndex, GL_SPOT_DIRECTION, lightChain->lightDirn);
2567 checkGLcall("glLightfv dirn");
2568 lightChain = lightChain->next;
2571 /* Reset Clipping Planes if clipping is enabled */
2572 for (k = 0; k < GL_LIMITS(clipplanes); k++) {
2573 glClipPlane(GL_CLIP_PLANE0 + k, This->stateBlock->clipplane[k]);
2574 checkGLcall("glClipPlane");
2578 } else { /* What was requested!?? */
2579 WARN("invalid matrix specified: %i\n", d3dts);
2582 /* Release lock, all done */
2587 static HRESULT WINAPI IWineD3DDeviceImpl_GetTransform(IWineD3DDevice *iface, D3DTRANSFORMSTATETYPE State, D3DMATRIX* pMatrix) {
2588 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2589 TRACE("(%p) : for Transform State %s\n", This, debug_d3dtstype(State));
2590 memcpy(pMatrix, &This->stateBlock->transforms[State], sizeof(D3DMATRIX));
2594 static HRESULT WINAPI IWineD3DDeviceImpl_MultiplyTransform(IWineD3DDevice *iface, D3DTRANSFORMSTATETYPE State, CONST D3DMATRIX* pMatrix) {
2595 D3DMATRIX *mat = NULL;
2598 /* Note: Using 'updateStateBlock' rather than 'stateblock' in the code
2599 * below means it will be recorded in a state block change, but it
2600 * works regardless where it is recorded.
2601 * If this is found to be wrong, change to StateBlock.
2603 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2604 TRACE("(%p) : For state %s\n", This, debug_d3dtstype(State));
2606 if (State < HIGHEST_TRANSFORMSTATE)
2608 mat = &This->updateStateBlock->transforms[State];
2610 FIXME("Unhandled transform state!!\n");
2613 multiply_matrix(&temp, mat, (D3DMATRIX *) pMatrix);
2615 /* Apply change via set transform - will reapply to eg. lights this way */
2616 return IWineD3DDeviceImpl_SetTransform(iface, State, &temp);
2621 * WARNING: This code relies on the fact that D3DLIGHT8 == D3DLIGHT9
2623 /* Note lights are real special cases. Although the device caps state only eg. 8 are supported,
2624 you can reference any indexes you want as long as that number max are enabled at any
2625 one point in time! Therefore since the indexes can be anything, we need a linked list of them.
2626 However, this causes stateblock problems. When capturing the state block, I duplicate the list,
2627 but when recording, just build a chain pretty much of commands to be replayed. */
2629 static HRESULT WINAPI IWineD3DDeviceImpl_SetLight(IWineD3DDevice *iface, DWORD Index, CONST WINED3DLIGHT* pLight) {
2631 PLIGHTINFOEL *object, *temp;
2633 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2634 TRACE("(%p) : Idx(%ld), pLight(%p)\n", This, Index, pLight);
2636 /* If recording state block, just add to end of lights chain */
2637 if (This->isRecordingState) {
2638 object = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(PLIGHTINFOEL));
2639 if (NULL == object) {
2640 return WINED3DERR_OUTOFVIDEOMEMORY;
2642 memcpy(&object->OriginalParms, pLight, sizeof(D3DLIGHT9));
2643 object->OriginalIndex = Index;
2644 object->glIndex = -1;
2645 object->changed = TRUE;
2647 /* Add to the END of the chain of lights changes to be replayed */
2648 if (This->updateStateBlock->lights == NULL) {
2649 This->updateStateBlock->lights = object;
2651 temp = This->updateStateBlock->lights;
2652 while (temp->next != NULL) temp=temp->next;
2653 temp->next = object;
2655 TRACE("Recording... not performing anything more\n");
2659 /* Ok, not recording any longer so do real work */
2660 object = This->stateBlock->lights;
2661 while (object != NULL && object->OriginalIndex != Index) object = object->next;
2663 /* If we didn't find it in the list of lights, time to add it */
2664 if (object == NULL) {
2665 PLIGHTINFOEL *insertAt,*prevPos;
2667 object = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(PLIGHTINFOEL));
2668 if (NULL == object) {
2669 return WINED3DERR_OUTOFVIDEOMEMORY;
2671 object->OriginalIndex = Index;
2672 object->glIndex = -1;
2674 /* Add it to the front of list with the idea that lights will be changed as needed
2675 BUT after any lights currently assigned GL indexes */
2676 insertAt = This->stateBlock->lights;
2678 while (insertAt != NULL && insertAt->glIndex != -1) {
2680 insertAt = insertAt->next;
2683 if (insertAt == NULL && prevPos == NULL) { /* Start of list */
2684 This->stateBlock->lights = object;
2685 } else if (insertAt == NULL) { /* End of list */
2686 prevPos->next = object;
2687 object->prev = prevPos;
2688 } else { /* Middle of chain */
2689 if (prevPos == NULL) {
2690 This->stateBlock->lights = object;
2692 prevPos->next = object;
2694 object->prev = prevPos;
2695 object->next = insertAt;
2696 insertAt->prev = object;
2700 /* Initialize the object */
2701 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,
2702 pLight->Diffuse.r, pLight->Diffuse.g, pLight->Diffuse.b, pLight->Diffuse.a,
2703 pLight->Specular.r, pLight->Specular.g, pLight->Specular.b, pLight->Specular.a,
2704 pLight->Ambient.r, pLight->Ambient.g, pLight->Ambient.b, pLight->Ambient.a);
2705 TRACE("... Pos(%f,%f,%f), Dirn(%f,%f,%f)\n", pLight->Position.x, pLight->Position.y, pLight->Position.z,
2706 pLight->Direction.x, pLight->Direction.y, pLight->Direction.z);
2707 TRACE("... Range(%f), Falloff(%f), Theta(%f), Phi(%f)\n", pLight->Range, pLight->Falloff, pLight->Theta, pLight->Phi);
2709 /* Save away the information */
2710 memcpy(&object->OriginalParms, pLight, sizeof(D3DLIGHT9));
2712 switch (pLight->Type) {
2713 case D3DLIGHT_POINT:
2715 object->lightPosn[0] = pLight->Position.x;
2716 object->lightPosn[1] = pLight->Position.y;
2717 object->lightPosn[2] = pLight->Position.z;
2718 object->lightPosn[3] = 1.0f;
2719 object->cutoff = 180.0f;
2723 case D3DLIGHT_DIRECTIONAL:
2725 object->lightPosn[0] = -pLight->Direction.x;
2726 object->lightPosn[1] = -pLight->Direction.y;
2727 object->lightPosn[2] = -pLight->Direction.z;
2728 object->lightPosn[3] = 0.0;
2729 object->exponent = 0.0f;
2730 object->cutoff = 180.0f;
2735 object->lightPosn[0] = pLight->Position.x;
2736 object->lightPosn[1] = pLight->Position.y;
2737 object->lightPosn[2] = pLight->Position.z;
2738 object->lightPosn[3] = 1.0;
2741 object->lightDirn[0] = pLight->Direction.x;
2742 object->lightDirn[1] = pLight->Direction.y;
2743 object->lightDirn[2] = pLight->Direction.z;
2744 object->lightDirn[3] = 1.0;
2747 * opengl-ish and d3d-ish spot lights use too different models for the
2748 * light "intensity" as a function of the angle towards the main light direction,
2749 * so we only can approximate very roughly.
2750 * however spot lights are rather rarely used in games (if ever used at all).
2751 * furthermore if still used, probably nobody pays attention to such details.
2753 if (pLight->Falloff == 0) {
2756 rho = pLight->Theta + (pLight->Phi - pLight->Theta)/(2*pLight->Falloff);
2758 if (rho < 0.0001) rho = 0.0001f;
2759 object->exponent = -0.3/log(cos(rho/2));
2760 if (object->exponent > 128.0) {
2761 object->exponent = 128.0;
2763 object->cutoff = pLight->Phi*90/M_PI;
2769 FIXME("Unrecognized light type %d\n", pLight->Type);
2772 /* Update the live definitions if the light is currently assigned a glIndex */
2773 if (object->glIndex != -1) {
2774 setup_light(iface, object->glIndex, object);
2779 static HRESULT WINAPI IWineD3DDeviceImpl_GetLight(IWineD3DDevice *iface, DWORD Index, WINED3DLIGHT* pLight) {
2780 PLIGHTINFOEL *lightInfo = NULL;
2781 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2782 TRACE("(%p) : Idx(%ld), pLight(%p)\n", This, Index, pLight);
2784 /* Locate the light in the live lights */
2785 lightInfo = This->stateBlock->lights;
2786 while (lightInfo != NULL && lightInfo->OriginalIndex != Index) lightInfo = lightInfo->next;
2788 if (lightInfo == NULL) {
2789 TRACE("Light information requested but light not defined\n");
2790 return WINED3DERR_INVALIDCALL;
2793 memcpy(pLight, &lightInfo->OriginalParms, sizeof(D3DLIGHT9));
2798 * Get / Set Light Enable
2799 * (Note for consistency, renamed d3dx function by adding the 'set' prefix)
2801 static HRESULT WINAPI IWineD3DDeviceImpl_SetLightEnable(IWineD3DDevice *iface, DWORD Index, BOOL Enable) {
2802 PLIGHTINFOEL *lightInfo = NULL;
2803 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2804 TRACE("(%p) : Idx(%ld), enable? %d\n", This, Index, Enable);
2806 /* Tests show true = 128...not clear why */
2808 Enable = Enable? 128: 0;
2810 /* If recording state block, just add to end of lights chain with changedEnable set to true */
2811 if (This->isRecordingState) {
2812 lightInfo = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(PLIGHTINFOEL));
2813 if (NULL == lightInfo) {
2814 return WINED3DERR_OUTOFVIDEOMEMORY;
2816 lightInfo->OriginalIndex = Index;
2817 lightInfo->glIndex = -1;
2818 lightInfo->enabledChanged = TRUE;
2819 lightInfo->lightEnabled = Enable;
2821 /* Add to the END of the chain of lights changes to be replayed */
2822 if (This->updateStateBlock->lights == NULL) {
2823 This->updateStateBlock->lights = lightInfo;
2825 PLIGHTINFOEL *temp = This->updateStateBlock->lights;
2826 while (temp->next != NULL) temp=temp->next;
2827 temp->next = lightInfo;
2829 TRACE("Recording... not performing anything more\n");
2833 /* Not recording... So, locate the light in the live lights */
2834 lightInfo = This->stateBlock->lights;
2835 while (lightInfo != NULL && lightInfo->OriginalIndex != Index) lightInfo = lightInfo->next;
2837 /* Special case - enabling an undefined light creates one with a strict set of parms! */
2838 if (lightInfo == NULL) {
2840 TRACE("Light enabled requested but light not defined, so defining one!\n");
2841 IWineD3DDeviceImpl_SetLight(iface, Index, &WINED3D_default_light);
2843 /* Search for it again! Should be fairly quick as near head of list */
2844 lightInfo = This->stateBlock->lights;
2845 while (lightInfo != NULL && lightInfo->OriginalIndex != Index) lightInfo = lightInfo->next;
2846 if (lightInfo == NULL) {
2847 FIXME("Adding default lights has failed dismally\n");
2848 return WINED3DERR_INVALIDCALL;
2852 /* OK, we now have a light... */
2853 if (Enable == FALSE) {
2855 /* If we are disabling it, check it was enabled, and
2856 still only do something if it has assigned a glIndex (which it should have!) */
2857 if ((lightInfo->lightEnabled) && (lightInfo->glIndex != -1)) {
2858 TRACE("Disabling light set up at gl idx %ld\n", lightInfo->glIndex);
2860 glDisable(GL_LIGHT0 + lightInfo->glIndex);
2861 checkGLcall("glDisable GL_LIGHT0+Index");
2864 TRACE("Nothing to do as light was not enabled\n");
2866 lightInfo->lightEnabled = Enable;
2869 /* We are enabling it. If it is enabled, it's really simple */
2870 if (lightInfo->lightEnabled) {
2872 TRACE("Nothing to do as light was enabled\n");
2874 /* If it already has a glIndex, it's still simple */
2875 } else if (lightInfo->glIndex != -1) {
2876 TRACE("Reusing light as already set up at gl idx %ld\n", lightInfo->glIndex);
2877 lightInfo->lightEnabled = Enable;
2879 glEnable(GL_LIGHT0 + lightInfo->glIndex);
2880 checkGLcall("glEnable GL_LIGHT0+Index already setup");
2883 /* Otherwise got to find space - lights are ordered gl indexes first */
2885 PLIGHTINFOEL *bsf = NULL;
2886 PLIGHTINFOEL *pos = This->stateBlock->lights;
2887 PLIGHTINFOEL *prev = NULL;
2891 /* Try to minimize changes as much as possible */
2892 while (pos != NULL && pos->glIndex != -1 && Index < This->maxConcurrentLights) {
2894 /* Try to remember which index can be replaced if necessary */
2895 if (bsf==NULL && pos->lightEnabled == FALSE) {
2896 /* Found a light we can replace, save as best replacement */
2900 /* Step to next space */
2906 /* If we have too many active lights, fail the call */
2907 if ((Index == This->maxConcurrentLights) && (bsf == NULL)) {
2908 FIXME("Program requests too many concurrent lights\n");
2909 return WINED3DERR_INVALIDCALL;
2911 /* If we have allocated all lights, but not all are enabled,
2912 reuse one which is not enabled */
2913 } else if (Index == This->maxConcurrentLights) {
2914 /* use bsf - Simply swap the new light and the BSF one */
2915 PLIGHTINFOEL *bsfNext = bsf->next;
2916 PLIGHTINFOEL *bsfPrev = bsf->prev;
2919 if (lightInfo->next != NULL) lightInfo->next->prev = bsf;
2920 if (bsf->prev != NULL) {
2921 bsf->prev->next = lightInfo;
2923 This->stateBlock->lights = lightInfo;
2926 /* If not side by side, lots of chains to update */
2927 if (bsf->next != lightInfo) {
2928 lightInfo->prev->next = bsf;
2929 bsf->next->prev = lightInfo;
2930 bsf->next = lightInfo->next;
2931 bsf->prev = lightInfo->prev;
2932 lightInfo->next = bsfNext;
2933 lightInfo->prev = bsfPrev;
2937 bsf->prev = lightInfo;
2938 bsf->next = lightInfo->next;
2939 lightInfo->next = bsf;
2940 lightInfo->prev = bsfPrev;
2945 glIndex = bsf->glIndex;
2947 lightInfo->glIndex = glIndex;
2948 lightInfo->lightEnabled = Enable;
2950 /* Finally set up the light in gl itself */
2951 TRACE("Replacing light which was set up at gl idx %ld\n", lightInfo->glIndex);
2953 setup_light(iface, glIndex, lightInfo);
2954 glEnable(GL_LIGHT0 + glIndex);
2955 checkGLcall("glEnable GL_LIGHT0 new setup");
2958 /* If we reached the end of the allocated lights, with space in the
2959 gl lights, setup a new light */
2960 } else if (pos->glIndex == -1) {
2962 /* We reached the end of the allocated gl lights, so already
2963 know the index of the next one! */
2965 lightInfo->glIndex = glIndex;
2966 lightInfo->lightEnabled = Enable;
2968 /* In an ideal world, it's already in the right place */
2969 if (lightInfo->prev == NULL || lightInfo->prev->glIndex!=-1) {
2970 /* No need to move it */
2972 /* Remove this light from the list */
2973 lightInfo->prev->next = lightInfo->next;
2974 if (lightInfo->next != NULL) {
2975 lightInfo->next->prev = lightInfo->prev;
2978 /* Add in at appropriate place (inbetween prev and pos) */
2979 lightInfo->prev = prev;
2980 lightInfo->next = pos;
2982 This->stateBlock->lights = lightInfo;
2984 prev->next = lightInfo;
2987 pos->prev = lightInfo;
2991 /* Finally set up the light in gl itself */
2992 TRACE("Defining new light at gl idx %ld\n", lightInfo->glIndex);
2994 setup_light(iface, glIndex, lightInfo);
2995 glEnable(GL_LIGHT0 + glIndex);
2996 checkGLcall("glEnable GL_LIGHT0 new setup");
3005 static HRESULT WINAPI IWineD3DDeviceImpl_GetLightEnable(IWineD3DDevice *iface, DWORD Index,BOOL* pEnable) {
3007 PLIGHTINFOEL *lightInfo = NULL;
3008 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3009 TRACE("(%p) : for idx(%ld)\n", This, Index);
3011 /* Locate the light in the live lights */
3012 lightInfo = This->stateBlock->lights;
3013 while (lightInfo != NULL && lightInfo->OriginalIndex != Index) lightInfo = lightInfo->next;
3015 if (lightInfo == NULL) {
3016 TRACE("Light enabled state requested but light not defined\n");
3017 return WINED3DERR_INVALIDCALL;
3019 *pEnable = lightInfo->lightEnabled;
3024 * Get / Set Clip Planes
3026 static HRESULT WINAPI IWineD3DDeviceImpl_SetClipPlane(IWineD3DDevice *iface, DWORD Index, CONST float *pPlane) {
3027 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3028 TRACE("(%p) : for idx %ld, %p\n", This, Index, pPlane);
3030 /* Validate Index */
3031 if (Index >= GL_LIMITS(clipplanes)) {
3032 TRACE("Application has requested clipplane this device doesn't support\n");
3033 return WINED3DERR_INVALIDCALL;
3036 This->updateStateBlock->changed.clipplane[Index] = TRUE;
3037 This->updateStateBlock->set.clipplane[Index] = TRUE;
3038 This->updateStateBlock->clipplane[Index][0] = pPlane[0];
3039 This->updateStateBlock->clipplane[Index][1] = pPlane[1];
3040 This->updateStateBlock->clipplane[Index][2] = pPlane[2];
3041 This->updateStateBlock->clipplane[Index][3] = pPlane[3];
3043 /* Handle recording of state blocks */
3044 if (This->isRecordingState) {
3045 TRACE("Recording... not performing anything\n");
3053 /* Clip Plane settings are affected by the model view in OpenGL, the View transform in direct3d */
3054 glMatrixMode(GL_MODELVIEW);
3056 glLoadMatrixf((float *) &This->stateBlock->transforms[WINED3DTS_VIEW].u.m[0][0]);
3058 TRACE("Clipplane [%f,%f,%f,%f]\n",
3059 This->updateStateBlock->clipplane[Index][0],
3060 This->updateStateBlock->clipplane[Index][1],
3061 This->updateStateBlock->clipplane[Index][2],
3062 This->updateStateBlock->clipplane[Index][3]);
3063 glClipPlane(GL_CLIP_PLANE0 + Index, This->updateStateBlock->clipplane[Index]);
3064 checkGLcall("glClipPlane");
3072 static HRESULT WINAPI IWineD3DDeviceImpl_GetClipPlane(IWineD3DDevice *iface, DWORD Index, float *pPlane) {
3073 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3074 TRACE("(%p) : for idx %ld\n", This, Index);
3076 /* Validate Index */
3077 if (Index >= GL_LIMITS(clipplanes)) {
3078 TRACE("Application has requested clipplane this device doesn't support\n");
3079 return WINED3DERR_INVALIDCALL;
3082 pPlane[0] = This->stateBlock->clipplane[Index][0];
3083 pPlane[1] = This->stateBlock->clipplane[Index][1];
3084 pPlane[2] = This->stateBlock->clipplane[Index][2];
3085 pPlane[3] = This->stateBlock->clipplane[Index][3];
3090 * Get / Set Clip Plane Status
3091 * WARNING: This code relies on the fact that D3DCLIPSTATUS8 == D3DCLIPSTATUS9
3093 static HRESULT WINAPI IWineD3DDeviceImpl_SetClipStatus(IWineD3DDevice *iface, CONST WINED3DCLIPSTATUS* pClipStatus) {
3094 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3095 FIXME("(%p) : stub\n", This);
3096 if (NULL == pClipStatus) {
3097 return WINED3DERR_INVALIDCALL;
3099 This->updateStateBlock->clip_status.ClipUnion = pClipStatus->ClipUnion;
3100 This->updateStateBlock->clip_status.ClipIntersection = pClipStatus->ClipIntersection;
3104 static HRESULT WINAPI IWineD3DDeviceImpl_GetClipStatus(IWineD3DDevice *iface, WINED3DCLIPSTATUS* pClipStatus) {
3105 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3106 FIXME("(%p) : stub\n", This);
3107 if (NULL == pClipStatus) {
3108 return WINED3DERR_INVALIDCALL;
3110 pClipStatus->ClipUnion = This->updateStateBlock->clip_status.ClipUnion;
3111 pClipStatus->ClipIntersection = This->updateStateBlock->clip_status.ClipIntersection;
3116 * Get / Set Material
3117 * WARNING: This code relies on the fact that D3DMATERIAL8 == D3DMATERIAL9
3119 static HRESULT WINAPI IWineD3DDeviceImpl_SetMaterial(IWineD3DDevice *iface, CONST WINED3DMATERIAL* pMaterial) {
3120 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3122 This->updateStateBlock->changed.material = TRUE;
3123 This->updateStateBlock->set.material = TRUE;
3124 memcpy(&This->updateStateBlock->material, pMaterial, sizeof(WINED3DMATERIAL));
3126 /* Handle recording of state blocks */
3127 if (This->isRecordingState) {
3128 TRACE("Recording... not performing anything\n");
3133 TRACE("(%p) : Diffuse (%f,%f,%f,%f)\n", This, pMaterial->Diffuse.r, pMaterial->Diffuse.g,
3134 pMaterial->Diffuse.b, pMaterial->Diffuse.a);
3135 TRACE("(%p) : Ambient (%f,%f,%f,%f)\n", This, pMaterial->Ambient.r, pMaterial->Ambient.g,
3136 pMaterial->Ambient.b, pMaterial->Ambient.a);
3137 TRACE("(%p) : Specular (%f,%f,%f,%f)\n", This, pMaterial->Specular.r, pMaterial->Specular.g,
3138 pMaterial->Specular.b, pMaterial->Specular.a);
3139 TRACE("(%p) : Emissive (%f,%f,%f,%f)\n", This, pMaterial->Emissive.r, pMaterial->Emissive.g,
3140 pMaterial->Emissive.b, pMaterial->Emissive.a);
3141 TRACE("(%p) : Power (%f)\n", This, pMaterial->Power);
3143 glMaterialfv(GL_FRONT_AND_BACK, GL_AMBIENT, (float*) &This->updateStateBlock->material.Ambient);
3144 checkGLcall("glMaterialfv(GL_AMBIENT)");
3145 glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, (float*) &This->updateStateBlock->material.Diffuse);
3146 checkGLcall("glMaterialfv(GL_DIFFUSE)");
3148 /* Only change material color if specular is enabled, otherwise it is set to black */
3149 if (This->stateBlock->renderState[WINED3DRS_SPECULARENABLE]) {
3150 glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, (float*) &This->updateStateBlock->material.Specular);
3151 checkGLcall("glMaterialfv(GL_SPECULAR");
3153 float black[4] = {0.0f, 0.0f, 0.0f, 0.0f};
3154 glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, &black[0]);
3155 checkGLcall("glMaterialfv(GL_SPECULAR");
3157 glMaterialfv(GL_FRONT_AND_BACK, GL_EMISSION, (float*) &This->updateStateBlock->material.Emissive);
3158 checkGLcall("glMaterialfv(GL_EMISSION)");
3159 glMaterialf(GL_FRONT_AND_BACK, GL_SHININESS, This->updateStateBlock->material.Power);
3160 checkGLcall("glMaterialf(GL_SHININESS");
3166 static HRESULT WINAPI IWineD3DDeviceImpl_GetMaterial(IWineD3DDevice *iface, WINED3DMATERIAL* pMaterial) {
3167 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3168 memcpy(pMaterial, &This->updateStateBlock->material, sizeof (WINED3DMATERIAL));
3169 TRACE("(%p) : Diffuse (%f,%f,%f,%f)\n", This, pMaterial->Diffuse.r, pMaterial->Diffuse.g,
3170 pMaterial->Diffuse.b, pMaterial->Diffuse.a);
3171 TRACE("(%p) : Ambient (%f,%f,%f,%f)\n", This, pMaterial->Ambient.r, pMaterial->Ambient.g,
3172 pMaterial->Ambient.b, pMaterial->Ambient.a);
3173 TRACE("(%p) : Specular (%f,%f,%f,%f)\n", This, pMaterial->Specular.r, pMaterial->Specular.g,
3174 pMaterial->Specular.b, pMaterial->Specular.a);
3175 TRACE("(%p) : Emissive (%f,%f,%f,%f)\n", This, pMaterial->Emissive.r, pMaterial->Emissive.g,
3176 pMaterial->Emissive.b, pMaterial->Emissive.a);
3177 TRACE("(%p) : Power (%f)\n", This, pMaterial->Power);
3185 static HRESULT WINAPI IWineD3DDeviceImpl_SetIndices(IWineD3DDevice *iface, IWineD3DIndexBuffer* pIndexData,
3186 UINT BaseVertexIndex) {
3187 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3188 IWineD3DIndexBuffer *oldIdxs;
3190 TRACE("(%p) : Setting to %p, base %d\n", This, pIndexData, BaseVertexIndex);
3191 oldIdxs = This->updateStateBlock->pIndexData;
3193 This->updateStateBlock->changed.indices = TRUE;
3194 This->updateStateBlock->set.indices = TRUE;
3195 This->updateStateBlock->pIndexData = pIndexData;
3196 This->updateStateBlock->baseVertexIndex = BaseVertexIndex;
3198 /* Handle recording of state blocks */
3199 if (This->isRecordingState) {
3200 TRACE("Recording... not performing anything\n");
3204 if (NULL != pIndexData) {
3205 IWineD3DIndexBuffer_AddRef(pIndexData);
3207 if (NULL != oldIdxs) {
3208 IWineD3DIndexBuffer_Release(oldIdxs);
3213 static HRESULT WINAPI IWineD3DDeviceImpl_GetIndices(IWineD3DDevice *iface, IWineD3DIndexBuffer** ppIndexData, UINT* pBaseVertexIndex) {
3214 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3216 *ppIndexData = This->stateBlock->pIndexData;
3218 /* up ref count on ppindexdata */
3220 IWineD3DIndexBuffer_AddRef(*ppIndexData);
3221 *pBaseVertexIndex = This->stateBlock->baseVertexIndex;
3222 TRACE("(%p) index data set to %p + %u\n", This, ppIndexData, This->stateBlock->baseVertexIndex);
3224 TRACE("(%p) No index data set\n", This);
3226 TRACE("Returning %p %d\n", *ppIndexData, *pBaseVertexIndex);
3232 * Get / Set Viewports
3234 static HRESULT WINAPI IWineD3DDeviceImpl_SetViewport(IWineD3DDevice *iface, CONST WINED3DVIEWPORT* pViewport) {
3235 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3237 TRACE("(%p)\n", This);
3238 This->updateStateBlock->changed.viewport = TRUE;
3239 This->updateStateBlock->set.viewport = TRUE;
3240 memcpy(&This->updateStateBlock->viewport, pViewport, sizeof(WINED3DVIEWPORT));
3242 /* Handle recording of state blocks */
3243 if (This->isRecordingState) {
3244 TRACE("Recording... not performing anything\n");
3247 This->viewport_changed = TRUE;
3251 TRACE("(%p) : x=%ld, y=%ld, wid=%ld, hei=%ld, minz=%f, maxz=%f\n", This,
3252 pViewport->X, pViewport->Y, pViewport->Width, pViewport->Height, pViewport->MinZ, pViewport->MaxZ);
3254 glDepthRange(pViewport->MinZ, pViewport->MaxZ);
3255 checkGLcall("glDepthRange");
3256 /* Note: GL requires lower left, DirectX supplies upper left */
3257 /* TODO: replace usage of renderTarget with context management */
3258 glViewport(pViewport->X,
3259 (((IWineD3DSurfaceImpl *)This->renderTarget)->currentDesc.Height - (pViewport->Y + pViewport->Height)),
3260 pViewport->Width, pViewport->Height);
3262 checkGLcall("glViewport");
3270 static HRESULT WINAPI IWineD3DDeviceImpl_GetViewport(IWineD3DDevice *iface, WINED3DVIEWPORT* pViewport) {
3271 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3272 TRACE("(%p)\n", This);
3273 memcpy(pViewport, &This->stateBlock->viewport, sizeof(WINED3DVIEWPORT));
3277 static void renderstate_stencil_twosided(
3278 IWineD3DDeviceImpl *This,
3285 GLint stencilPass ) {
3286 #if 0 /* Don't use OpenGL 2.0 calls for now */
3287 if(GL_EXTCALL(glStencilFuncSeparate) && GL_EXTCALL(glStencilOpSeparate)) {
3288 GL_EXTCALL(glStencilFuncSeparate(face, func, ref, mask));
3289 checkGLcall("glStencilFuncSeparate(...)");
3290 GL_EXTCALL(glStencilOpSeparate(face, stencilFail, depthFail, stencilPass));
3291 checkGLcall("glStencilOpSeparate(...)");
3295 if(GL_SUPPORT(EXT_STENCIL_TWO_SIDE)) {
3296 glEnable(GL_STENCIL_TEST_TWO_SIDE_EXT);
3297 checkGLcall("glEnable(GL_STENCIL_TEST_TWO_SIDE_EXT)");
3298 GL_EXTCALL(glActiveStencilFaceEXT(face));
3299 checkGLcall("glActiveStencilFaceEXT(...)");
3300 glStencilFunc(func, ref, mask);
3301 checkGLcall("glStencilFunc(...)");
3302 glStencilOp(stencilFail, depthFail, stencilPass);
3303 checkGLcall("glStencilOp(...)");
3304 } else if(GL_SUPPORT(ATI_SEPARATE_STENCIL)) {
3305 GL_EXTCALL(glStencilFuncSeparateATI(face, func, ref, mask));
3306 checkGLcall("glStencilFuncSeparateATI(...)");
3307 GL_EXTCALL(glStencilOpSeparateATI(face, stencilFail, depthFail, stencilPass));
3308 checkGLcall("glStencilOpSeparateATI(...)");
3310 ERR("Separate (two sided) stencil not supported on this version of opengl. Caps weren't honored?\n");
3314 static void renderstate_stencil(IWineD3DDeviceImpl *This, D3DRENDERSTATETYPE State, DWORD Value) {
3315 DWORD onesided_enable = FALSE;
3316 DWORD twosided_enable = FALSE;
3317 GLint func = GL_ALWAYS;
3318 GLint func_ccw = GL_ALWAYS;
3321 GLint stencilFail = GL_KEEP;
3322 GLint depthFail = GL_KEEP;
3323 GLint stencilPass = GL_KEEP;
3324 GLint stencilFail_ccw = GL_KEEP;
3325 GLint depthFail_ccw = GL_KEEP;
3326 GLint stencilPass_ccw = GL_KEEP;
3328 if( This->stateBlock->set.renderState[WINED3DRS_STENCILENABLE] )
3329 onesided_enable = This->stateBlock->renderState[WINED3DRS_STENCILENABLE];
3330 if( This->stateBlock->set.renderState[WINED3DRS_TWOSIDEDSTENCILMODE] )
3331 twosided_enable = This->stateBlock->renderState[WINED3DRS_TWOSIDEDSTENCILMODE];
3332 if( This->stateBlock->set.renderState[WINED3DRS_STENCILFUNC] )
3333 if( !( func = CompareFunc(This->stateBlock->renderState[WINED3DRS_STENCILFUNC]) ) )
3335 if( This->stateBlock->set.renderState[WINED3DRS_CCW_STENCILFUNC] )
3336 if( !( func_ccw = CompareFunc(This->stateBlock->renderState[WINED3DRS_CCW_STENCILFUNC]) ) )
3338 if( This->stateBlock->set.renderState[WINED3DRS_STENCILREF] )
3339 ref = This->stateBlock->renderState[WINED3DRS_STENCILREF];
3340 if( This->stateBlock->set.renderState[WINED3DRS_STENCILMASK] )
3341 mask = This->stateBlock->renderState[WINED3DRS_STENCILMASK];
3342 if( This->stateBlock->set.renderState[WINED3DRS_STENCILFAIL] )
3343 stencilFail = StencilOp(This->stateBlock->renderState[WINED3DRS_STENCILFAIL]);
3344 if( This->stateBlock->set.renderState[WINED3DRS_STENCILZFAIL] )
3345 depthFail = StencilOp(This->stateBlock->renderState[WINED3DRS_STENCILZFAIL]);
3346 if( This->stateBlock->set.renderState[WINED3DRS_STENCILPASS] )
3347 stencilPass = StencilOp(This->stateBlock->renderState[WINED3DRS_STENCILPASS]);
3348 if( This->stateBlock->set.renderState[WINED3DRS_CCW_STENCILFAIL] )
3349 stencilFail_ccw = StencilOp(This->stateBlock->renderState[WINED3DRS_CCW_STENCILFAIL]);
3350 if( This->stateBlock->set.renderState[WINED3DRS_CCW_STENCILZFAIL] )
3351 depthFail_ccw = StencilOp(This->stateBlock->renderState[WINED3DRS_CCW_STENCILZFAIL]);
3352 if( This->stateBlock->set.renderState[WINED3DRS_CCW_STENCILPASS] )
3353 stencilPass_ccw = StencilOp(This->stateBlock->renderState[WINED3DRS_CCW_STENCILPASS]);
3355 TRACE("(onesided %ld, twosided %ld, ref %x, mask %x, \
3356 GL_FRONT: func: %x, fail %x, zfail %x, zpass %x \
3357 GL_BACK: func: %x, fail %x, zfail %x, zpass %x )\n",
3358 onesided_enable, twosided_enable, ref, mask,
3359 func, stencilFail, depthFail, stencilPass,
3360 func_ccw, stencilFail_ccw, depthFail_ccw, stencilPass_ccw);
3362 if (twosided_enable) {
3363 renderstate_stencil_twosided(This, GL_FRONT, func, ref, mask, stencilFail, depthFail, stencilPass);
3364 renderstate_stencil_twosided(This, GL_BACK, func_ccw, ref, mask, stencilFail_ccw, depthFail_ccw, stencilPass_ccw);
3366 if (onesided_enable) {
3367 glEnable(GL_STENCIL_TEST);
3368 checkGLcall("glEnable GL_STENCIL_TEST");
3369 glStencilFunc(func, ref, mask);
3370 checkGLcall("glStencilFunc(...)");
3371 glStencilOp(stencilFail, depthFail, stencilPass);
3372 checkGLcall("glStencilOp(...)");
3374 glDisable(GL_STENCIL_TEST);
3375 checkGLcall("glDisable GL_STENCIL_TEST");
3381 * Get / Set Render States
3382 * TODO: Verify against dx9 definitions
3384 static HRESULT WINAPI IWineD3DDeviceImpl_SetRenderState(IWineD3DDevice *iface, D3DRENDERSTATETYPE State, DWORD Value) {
3386 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3387 DWORD OldValue = This->stateBlock->renderState[State];
3389 /* Simple way of referring to either a DWORD or a 4 byte float */
3395 TRACE("(%p)->state = %s(%d), value = %ld\n", This, debug_d3drenderstate(State), State, Value);
3396 This->updateStateBlock->changed.renderState[State] = TRUE;
3397 This->updateStateBlock->set.renderState[State] = TRUE;
3398 This->updateStateBlock->renderState[State] = Value;
3400 /* Handle recording of state blocks */
3401 if (This->isRecordingState) {
3402 TRACE("Recording... not performing anything\n");
3409 case WINED3DRS_FILLMODE :
3410 switch ((D3DFILLMODE) Value) {
3411 case D3DFILL_POINT : glPolygonMode(GL_FRONT_AND_BACK, GL_POINT); break;
3412 case D3DFILL_WIREFRAME : glPolygonMode(GL_FRONT_AND_BACK, GL_LINE); break;
3413 case D3DFILL_SOLID : glPolygonMode(GL_FRONT_AND_BACK, GL_FILL); break;
3415 FIXME("Unrecognized WINED3DRS_FILLMODE value %ld\n", Value);
3417 checkGLcall("glPolygonMode (fillmode)");
3420 case WINED3DRS_LIGHTING :
3422 glEnable(GL_LIGHTING);
3423 checkGLcall("glEnable GL_LIGHTING");
3425 glDisable(GL_LIGHTING);
3426 checkGLcall("glDisable GL_LIGHTING");
3430 case WINED3DRS_ZENABLE :
3431 switch ((D3DZBUFFERTYPE) Value) {
3433 glDisable(GL_DEPTH_TEST);
3434 checkGLcall("glDisable GL_DEPTH_TEST");
3437 glEnable(GL_DEPTH_TEST);
3438 checkGLcall("glEnable GL_DEPTH_TEST");
3441 glEnable(GL_DEPTH_TEST);
3442 checkGLcall("glEnable GL_DEPTH_TEST");
3443 FIXME("W buffer is not well handled\n");
3446 FIXME("Unrecognized D3DZBUFFERTYPE value %ld\n", Value);
3450 case WINED3DRS_CULLMODE :
3452 /* If we are culling "back faces with clockwise vertices" then
3453 set front faces to be counter clockwise and enable culling
3455 switch ((D3DCULL) Value) {
3457 glDisable(GL_CULL_FACE);
3458 checkGLcall("glDisable GL_CULL_FACE");
3461 glEnable(GL_CULL_FACE);
3462 checkGLcall("glEnable GL_CULL_FACE");
3463 if (This->renderUpsideDown) {
3465 checkGLcall("glFrontFace GL_CW");
3467 glFrontFace(GL_CCW);
3468 checkGLcall("glFrontFace GL_CCW");
3470 glCullFace(GL_BACK);
3473 glEnable(GL_CULL_FACE);
3474 checkGLcall("glEnable GL_CULL_FACE");
3475 if (This->renderUpsideDown) {
3476 glFrontFace(GL_CCW);
3477 checkGLcall("glFrontFace GL_CCW");
3480 checkGLcall("glFrontFace GL_CW");
3482 glCullFace(GL_BACK);
3485 FIXME("Unrecognized/Unhandled D3DCULL value %ld\n", Value);
3489 case WINED3DRS_SHADEMODE :
3490 switch ((D3DSHADEMODE) Value) {
3492 glShadeModel(GL_FLAT);
3493 checkGLcall("glShadeModel");
3495 case D3DSHADE_GOURAUD:
3496 glShadeModel(GL_SMOOTH);
3497 checkGLcall("glShadeModel");
3499 case D3DSHADE_PHONG:
3500 FIXME("D3DSHADE_PHONG isn't supported\n");
3503 FIXME("Unrecognized/Unhandled D3DSHADEMODE value %ld\n", Value);
3507 case WINED3DRS_DITHERENABLE :
3509 glEnable(GL_DITHER);
3510 checkGLcall("glEnable GL_DITHER");
3512 glDisable(GL_DITHER);
3513 checkGLcall("glDisable GL_DITHER");
3517 case WINED3DRS_ZWRITEENABLE :
3520 checkGLcall("glDepthMask");
3523 checkGLcall("glDepthMask");
3527 case WINED3DRS_ZFUNC :
3529 int glParm = CompareFunc(Value);
3532 glDepthFunc(glParm);
3533 checkGLcall("glDepthFunc");
3538 case WINED3DRS_AMBIENT :
3541 D3DCOLORTOGLFLOAT4(Value, col);
3542 TRACE("Setting ambient to (%f,%f,%f,%f)\n", col[0], col[1], col[2], col[3]);
3543 glLightModelfv(GL_LIGHT_MODEL_AMBIENT, col);
3544 checkGLcall("glLightModel for MODEL_AMBIENT");
3549 case WINED3DRS_ALPHABLENDENABLE :
3552 checkGLcall("glEnable GL_BLEND");
3554 glDisable(GL_BLEND);
3555 checkGLcall("glDisable GL_BLEND");
3559 case WINED3DRS_SRCBLEND :
3560 case WINED3DRS_DESTBLEND :
3562 int newVal = GL_ZERO;
3564 case D3DBLEND_ZERO : newVal = GL_ZERO; break;
3565 case D3DBLEND_ONE : newVal = GL_ONE; break;
3566 case D3DBLEND_SRCCOLOR : newVal = GL_SRC_COLOR; break;
3567 case D3DBLEND_INVSRCCOLOR : newVal = GL_ONE_MINUS_SRC_COLOR; break;
3568 case D3DBLEND_SRCALPHA : newVal = GL_SRC_ALPHA; break;
3569 case D3DBLEND_INVSRCALPHA : newVal = GL_ONE_MINUS_SRC_ALPHA; break;
3570 case D3DBLEND_DESTALPHA : newVal = GL_DST_ALPHA; break;
3571 case D3DBLEND_INVDESTALPHA : newVal = GL_ONE_MINUS_DST_ALPHA; break;
3572 case D3DBLEND_DESTCOLOR : newVal = GL_DST_COLOR; break;
3573 case D3DBLEND_INVDESTCOLOR : newVal = GL_ONE_MINUS_DST_COLOR; break;
3574 case D3DBLEND_SRCALPHASAT : newVal = GL_SRC_ALPHA_SATURATE; break;
3576 case D3DBLEND_BOTHSRCALPHA : newVal = GL_SRC_ALPHA;
3577 This->srcBlend = newVal;
3578 This->dstBlend = newVal;
3581 case D3DBLEND_BOTHINVSRCALPHA : newVal = GL_ONE_MINUS_SRC_ALPHA;
3582 This->srcBlend = newVal;
3583 This->dstBlend = newVal;
3585 case D3DBLEND_BLENDFACTOR : newVal = GL_CONSTANT_COLOR; break;
3586 case D3DBLEND_INVBLENDFACTOR : newVal = GL_ONE_MINUS_CONSTANT_COLOR; break;
3588 FIXME("Unrecognized src/dest blend value %ld (%d)\n", Value, State);
3591 if (State == WINED3DRS_SRCBLEND) This->srcBlend = newVal;
3592 if (State == WINED3DRS_DESTBLEND) This->dstBlend = newVal;
3593 TRACE("glBlendFunc src=%x, dst=%x\n", This->srcBlend, This->dstBlend);
3594 glBlendFunc(This->srcBlend, This->dstBlend);
3596 checkGLcall("glBlendFunc");
3600 case WINED3DRS_ALPHATESTENABLE :
3601 case WINED3DRS_ALPHAFUNC :
3602 case WINED3DRS_ALPHAREF :
3603 case WINED3DRS_COLORKEYENABLE :
3607 BOOL enable_ckey = FALSE;
3609 IWineD3DSurfaceImpl *surf;
3611 /* Find out if the texture on the first stage has a ckey set */
3612 if(This->stateBlock->textures[0]) {
3613 surf = (IWineD3DSurfaceImpl *) ((IWineD3DTextureImpl *)This->stateBlock->textures[0])->surfaces[0];
3614 if(surf->CKeyFlags & DDSD_CKSRCBLT) enable_ckey = TRUE;
3617 if (This->stateBlock->renderState[WINED3DRS_ALPHATESTENABLE] ||
3618 (This->stateBlock->renderState[WINED3DRS_COLORKEYENABLE] && enable_ckey)) {
3619 glEnable(GL_ALPHA_TEST);
3620 checkGLcall("glEnable GL_ALPHA_TEST");
3622 glDisable(GL_ALPHA_TEST);
3623 checkGLcall("glDisable GL_ALPHA_TEST");
3624 /* Alpha test is disabled, don't bother setting the params - it will happen on the next
3630 if(This->stateBlock->renderState[WINED3DRS_COLORKEYENABLE] && enable_ckey) {
3631 glParm = GL_NOTEQUAL;
3634 ref = ((float) This->stateBlock->renderState[WINED3DRS_ALPHAREF]) / 255.0f;
3635 glParm = CompareFunc(This->stateBlock->renderState[WINED3DRS_ALPHAFUNC]);
3638 This->alphafunc = glParm;
3639 glAlphaFunc(glParm, ref);
3640 checkGLcall("glAlphaFunc");
3645 case WINED3DRS_CLIPPLANEENABLE :
3646 case WINED3DRS_CLIPPING :
3648 /* Ensure we only do the changed clip planes */
3649 DWORD enable = 0xFFFFFFFF;
3650 DWORD disable = 0x00000000;
3652 /* If enabling / disabling all */
3653 if (State == WINED3DRS_CLIPPING) {
3655 enable = This->stateBlock->renderState[WINED3DRS_CLIPPLANEENABLE];
3658 disable = This->stateBlock->renderState[WINED3DRS_CLIPPLANEENABLE];
3662 enable = Value & ~OldValue;
3663 disable = ~Value & OldValue;
3666 if (enable & D3DCLIPPLANE0) { glEnable(GL_CLIP_PLANE0); checkGLcall("glEnable(clip plane 0)"); }
3667 if (enable & D3DCLIPPLANE1) { glEnable(GL_CLIP_PLANE1); checkGLcall("glEnable(clip plane 1)"); }
3668 if (enable & D3DCLIPPLANE2) { glEnable(GL_CLIP_PLANE2); checkGLcall("glEnable(clip plane 2)"); }
3669 if (enable & D3DCLIPPLANE3) { glEnable(GL_CLIP_PLANE3); checkGLcall("glEnable(clip plane 3)"); }
3670 if (enable & D3DCLIPPLANE4) { glEnable(GL_CLIP_PLANE4); checkGLcall("glEnable(clip plane 4)"); }
3671 if (enable & D3DCLIPPLANE5) { glEnable(GL_CLIP_PLANE5); checkGLcall("glEnable(clip plane 5)"); }
3673 if (disable & D3DCLIPPLANE0) { glDisable(GL_CLIP_PLANE0); checkGLcall("glDisable(clip plane 0)"); }
3674 if (disable & D3DCLIPPLANE1) { glDisable(GL_CLIP_PLANE1); checkGLcall("glDisable(clip plane 1)"); }
3675 if (disable & D3DCLIPPLANE2) { glDisable(GL_CLIP_PLANE2); checkGLcall("glDisable(clip plane 2)"); }
3676 if (disable & D3DCLIPPLANE3) { glDisable(GL_CLIP_PLANE3); checkGLcall("glDisable(clip plane 3)"); }
3677 if (disable & D3DCLIPPLANE4) { glDisable(GL_CLIP_PLANE4); checkGLcall("glDisable(clip plane 4)"); }
3678 if (disable & D3DCLIPPLANE5) { glDisable(GL_CLIP_PLANE5); checkGLcall("glDisable(clip plane 5)"); }
3680 /** update clipping status */
3682 This->stateBlock->clip_status.ClipUnion = 0;
3683 This->stateBlock->clip_status.ClipIntersection = 0xFFFFFFFF;
3685 This->stateBlock->clip_status.ClipUnion = 0;
3686 This->stateBlock->clip_status.ClipIntersection = 0;
3691 case WINED3DRS_BLENDOP :
3693 int glParm = GL_FUNC_ADD;
3695 switch ((D3DBLENDOP) Value) {
3696 case D3DBLENDOP_ADD : glParm = GL_FUNC_ADD; break;
3697 case D3DBLENDOP_SUBTRACT : glParm = GL_FUNC_SUBTRACT; break;
3698 case D3DBLENDOP_REVSUBTRACT : glParm = GL_FUNC_REVERSE_SUBTRACT; break;
3699 case D3DBLENDOP_MIN : glParm = GL_MIN; break;
3700 case D3DBLENDOP_MAX : glParm = GL_MAX; break;
3702 FIXME("Unrecognized/Unhandled D3DBLENDOP value %ld\n", Value);
3705 if(GL_SUPPORT(EXT_BLEND_MINMAX)) {
3706 TRACE("glBlendEquation(%x)\n", glParm);
3707 GL_EXTCALL(glBlendEquation(glParm));
3708 checkGLcall("glBlendEquation");
3710 WARN("Unsupported in local OpenGL implementation: glBlendEquation\n");
3715 case WINED3DRS_TEXTUREFACTOR :
3719 /* Note the texture color applies to all textures whereas
3720 GL_TEXTURE_ENV_COLOR applies to active only */
3722 D3DCOLORTOGLFLOAT4(Value, col);
3724 if (!GL_SUPPORT(NV_REGISTER_COMBINERS)) {
3725 /* And now the default texture color as well */
3726 for (i = 0; i < GL_LIMITS(texture_stages); i++) {
3727 /* Note the D3DRS value applies to all textures, but GL has one
3728 per texture, so apply it now ready to be used! */
3729 if (GL_SUPPORT(ARB_MULTITEXTURE)) {
3730 GL_EXTCALL(glActiveTextureARB(GL_TEXTURE0_ARB + i));
3731 checkGLcall("glActiveTextureARB");
3733 FIXME("Program using multiple concurrent textures which this opengl implementation doesn't support\n");
3736 glTexEnvfv(GL_TEXTURE_ENV, GL_TEXTURE_ENV_COLOR, &col[0]);
3737 checkGLcall("glTexEnvfv(GL_TEXTURE_ENV, GL_TEXTURE_ENV_COLOR, color);");
3743 case WINED3DRS_SPECULARENABLE :
3745 /* Originally this used glLightModeli(GL_LIGHT_MODEL_COLOR_CONTROL,GL_SEPARATE_SPECULAR_COLOR)
3746 and (GL_LIGHT_MODEL_COLOR_CONTROL,GL_SINGLE_COLOR) to swap between enabled/disabled
3747 specular color. This is wrong:
3748 Separate specular color means the specular colour is maintained separately, whereas
3749 single color means it is merged in. However in both cases they are being used to
3751 To disable specular color, set it explicitly to black and turn off GL_COLOR_SUM_EXT
3752 NOTE: If not supported don't give FIXMEs the impact is really minimal and very few people are
3756 * If register combiners are enabled, enabling / disabling GL_COLOR_SUM has no effect.
3757 * Instead, we need to setup the FinalCombiner properly.
3759 * The default setup for the FinalCombiner is:
3761 * <variable> <input> <mapping> <usage>
3762 * GL_VARIABLE_A_NV GL_FOG, GL_UNSIGNED_IDENTITY_NV GL_ALPHA
3763 * GL_VARIABLE_B_NV GL_SPARE0_PLUS_SECONDARY_COLOR_NV GL_UNSIGNED_IDENTITY_NV GL_RGB
3764 * GL_VARIABLE_C_NV GL_FOG GL_UNSIGNED_IDENTITY_NV GL_RGB
3765 * GL_VARIABLE_D_NV GL_ZERO GL_UNSIGNED_IDENTITY_NV GL_RGB
3766 * GL_VARIABLE_E_NV GL_ZERO GL_UNSIGNED_IDENTITY_NV GL_RGB
3767 * GL_VARIABLE_F_NV GL_ZERO GL_UNSIGNED_IDENTITY_NV GL_RGB
3768 * GL_VARIABLE_G_NV GL_SPARE0_NV GL_UNSIGNED_IDENTITY_NV GL_ALPHA
3770 * That's pretty much fine as it is, except for variable B, which needs to take
3771 * either GL_SPARE0_PLUS_SECONDARY_COLOR_NV or GL_SPARE0_NV, depending on
3772 * whether WINED3DRS_SPECULARENABLE is enabled or not.
3776 glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, (float*) &This->updateStateBlock->material.Specular);
3777 checkGLcall("glMaterialfv");
3778 if (GL_SUPPORT(EXT_SECONDARY_COLOR)) {
3779 glEnable(GL_COLOR_SUM_EXT);
3781 TRACE("Specular colors cannot be enabled in this version of opengl\n");
3783 checkGLcall("glEnable(GL_COLOR_SUM)");
3785 if (GL_SUPPORT(NV_REGISTER_COMBINERS)) {
3786 GL_EXTCALL(glFinalCombinerInputNV(GL_VARIABLE_B_NV, GL_SPARE0_PLUS_SECONDARY_COLOR_NV, GL_UNSIGNED_IDENTITY_NV, GL_RGB));
3787 checkGLcall("glFinalCombinerInputNV()");
3790 float black[4] = {0.0f, 0.0f, 0.0f, 0.0f};
3792 /* for the case of enabled lighting: */
3793 glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, &black[0]);
3794 checkGLcall("glMaterialfv");
3796 /* for the case of disabled lighting: */
3797 if (GL_SUPPORT(EXT_SECONDARY_COLOR)) {
3798 glDisable(GL_COLOR_SUM_EXT);
3800 TRACE("Specular colors cannot be disabled in this version of opengl\n");
3802 checkGLcall("glDisable(GL_COLOR_SUM)");
3804 if (GL_SUPPORT(NV_REGISTER_COMBINERS)) {
3805 GL_EXTCALL(glFinalCombinerInputNV(GL_VARIABLE_B_NV, GL_SPARE0_NV, GL_UNSIGNED_IDENTITY_NV, GL_RGB));
3806 checkGLcall("glFinalCombinerInputNV()");
3812 case WINED3DRS_STENCILENABLE :
3813 case WINED3DRS_TWOSIDEDSTENCILMODE :
3814 case WINED3DRS_STENCILFUNC :
3815 case WINED3DRS_CCW_STENCILFUNC :
3816 case WINED3DRS_STENCILREF :
3817 case WINED3DRS_STENCILMASK :
3818 case WINED3DRS_STENCILFAIL :
3819 case WINED3DRS_STENCILZFAIL :
3820 case WINED3DRS_STENCILPASS :
3821 case WINED3DRS_CCW_STENCILFAIL :
3822 case WINED3DRS_CCW_STENCILZFAIL :
3823 case WINED3DRS_CCW_STENCILPASS :
3824 renderstate_stencil(This, State, Value);
3826 case WINED3DRS_STENCILWRITEMASK :
3828 glStencilMask(Value);
3829 TRACE("glStencilMask(%lu)\n", Value);
3830 checkGLcall("glStencilMask");
3834 case WINED3DRS_FOGENABLE :
3838 checkGLcall("glEnable GL_FOG");
3841 checkGLcall("glDisable GL_FOG");
3846 case WINED3DRS_RANGEFOGENABLE :
3849 TRACE("Enabled RANGEFOG\n");
3851 TRACE("Disabled RANGEFOG\n");
3856 case WINED3DRS_FOGCOLOR :
3859 D3DCOLORTOGLFLOAT4(Value, col);
3860 /* Set the default alpha blend color */
3861 glFogfv(GL_FOG_COLOR, &col[0]);
3862 checkGLcall("glFog GL_FOG_COLOR");
3866 case WINED3DRS_FOGTABLEMODE :
3867 case WINED3DRS_FOGVERTEXMODE :
3869 /* 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." */
3870 if(This->stateBlock->renderState[WINED3DRS_FOGTABLEMODE] == D3DFOG_NONE) {
3871 glHint(GL_FOG_HINT, GL_FASTEST);
3872 checkGLcall("glHint(GL_FOG_HINT, GL_FASTEST)");
3873 switch (This->stateBlock->renderState[WINED3DRS_FOGVERTEXMODE]) {
3874 /* Processed vertices have their fog factor stored in the specular value. Fall too the none case.
3875 * If we are drawing untransformed vertices atm, d3ddevice_set_ortho will update the fog
3878 if(!This->last_was_rhw) {
3879 glFogi(GL_FOG_MODE, GL_EXP);
3880 checkGLcall("glFogi(GL_FOG_MODE, GL_EXP");
3881 if(GL_SUPPORT(EXT_FOG_COORD)) {
3882 glFogi(GL_FOG_COORDINATE_SOURCE_EXT, GL_FRAGMENT_DEPTH_EXT);
3883 checkGLcall("glFogi(GL_FOG_COORDINATE_SOURCE_EXT, GL_FRAGMENT_DEPTH_EXT");
3884 IWineD3DDevice_SetRenderState(iface, WINED3DRS_FOGSTART, This->stateBlock->renderState[WINED3DRS_FOGSTART]);
3885 IWineD3DDevice_SetRenderState(iface, WINED3DRS_FOGEND, This->stateBlock->renderState[WINED3DRS_FOGEND]);
3891 if(!This->last_was_rhw) {
3892 glFogi(GL_FOG_MODE, GL_EXP2);
3893 checkGLcall("glFogi(GL_FOG_MODE, GL_EXP2");
3894 if(GL_SUPPORT(EXT_FOG_COORD)) {
3895 glFogi(GL_FOG_COORDINATE_SOURCE_EXT, GL_FRAGMENT_DEPTH_EXT);
3896 checkGLcall("glFogi(GL_FOG_COORDINATE_SOURCE_EXT, GL_FRAGMENT_DEPTH_EXT");
3897 IWineD3DDevice_SetRenderState(iface, WINED3DRS_FOGSTART, This->stateBlock->renderState[WINED3DRS_FOGSTART]);
3898 IWineD3DDevice_SetRenderState(iface, WINED3DRS_FOGEND, This->stateBlock->renderState[WINED3DRS_FOGEND]);
3903 case D3DFOG_LINEAR: {
3904 if(!This->last_was_rhw) {
3905 glFogi(GL_FOG_MODE, GL_LINEAR);
3906 checkGLcall("glFogi(GL_FOG_MODE, GL_LINEAR");
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 /* Both are none? According to msdn the alpha channel of the specular
3918 * color contains a fog factor. Set it in drawStridedSlow.
3919 * Same happens with Vertexfog on transformed vertices
3921 if(GL_SUPPORT(EXT_FOG_COORD)) {
3922 glFogi(GL_FOG_COORDINATE_SOURCE_EXT, GL_FOG_COORDINATE_EXT);
3923 checkGLcall("glFogi(GL_FOG_COORDINATE_SOURCE_EXT, GL_FOG_COORDINATE_EXT)\n");
3924 glFogi(GL_FOG_MODE, GL_LINEAR);
3925 checkGLcall("glFogi(GL_FOG_MODE, GL_LINEAR)");
3926 glFogf(GL_FOG_START, (float) 0xff);
3927 checkGLcall("glFogfv GL_FOG_START");
3928 glFogf(GL_FOG_END, 0.0);
3929 checkGLcall("glFogfv GL_FOG_END");
3931 /* Disable GL fog, handle this in software in drawStridedSlow */
3933 checkGLcall("glDisable(GL_FOG)");
3937 default: FIXME("Unexpected WINED3DRS_FOGVERTEXMODE %ld\n", This->stateBlock->renderState[WINED3DRS_FOGVERTEXMODE]);
3940 glHint(GL_FOG_HINT, GL_NICEST);
3941 checkGLcall("glHint(GL_FOG_HINT, GL_NICEST)");
3942 switch (This->stateBlock->renderState[WINED3DRS_FOGTABLEMODE]) {
3943 case D3DFOG_EXP: glFogi(GL_FOG_MODE, GL_EXP);
3944 checkGLcall("glFogi(GL_FOG_MODE, GL_EXP");
3945 if(GL_SUPPORT(EXT_FOG_COORD)) {
3946 glFogi(GL_FOG_COORDINATE_SOURCE_EXT, GL_FRAGMENT_DEPTH_EXT);
3947 checkGLcall("glFogi(GL_FOG_COORDINATE_SOURCE_EXT, GL_FRAGMENT_DEPTH_EXT");
3948 IWineD3DDevice_SetRenderState(iface, WINED3DRS_FOGSTART, This->stateBlock->renderState[WINED3DRS_FOGSTART]);
3949 IWineD3DDevice_SetRenderState(iface, WINED3DRS_FOGEND, This->stateBlock->renderState[WINED3DRS_FOGEND]);
3952 case D3DFOG_EXP2: glFogi(GL_FOG_MODE, GL_EXP2);
3953 checkGLcall("glFogi(GL_FOG_MODE, GL_EXP2");
3954 if(GL_SUPPORT(EXT_FOG_COORD)) {
3955 glFogi(GL_FOG_COORDINATE_SOURCE_EXT, GL_FRAGMENT_DEPTH_EXT);
3956 checkGLcall("glFogi(GL_FOG_COORDINATE_SOURCE_EXT, GL_FRAGMENT_DEPTH_EXT");
3957 IWineD3DDevice_SetRenderState(iface, WINED3DRS_FOGSTART, This->stateBlock->renderState[WINED3DRS_FOGSTART]);
3958 IWineD3DDevice_SetRenderState(iface, WINED3DRS_FOGEND, This->stateBlock->renderState[WINED3DRS_FOGEND]);
3961 case D3DFOG_LINEAR: glFogi(GL_FOG_MODE, GL_LINEAR);
3962 checkGLcall("glFogi(GL_FOG_MODE, GL_LINEAR");
3963 if(GL_SUPPORT(EXT_FOG_COORD)) {
3964 glFogi(GL_FOG_COORDINATE_SOURCE_EXT, GL_FRAGMENT_DEPTH_EXT);
3965 checkGLcall("glFogi(GL_FOG_COORDINATE_SOURCE_EXT, GL_FRAGMENT_DEPTH_EXT");
3966 IWineD3DDevice_SetRenderState(iface, WINED3DRS_FOGSTART, This->stateBlock->renderState[WINED3DRS_FOGSTART]);
3967 IWineD3DDevice_SetRenderState(iface, WINED3DRS_FOGEND, This->stateBlock->renderState[WINED3DRS_FOGEND]);
3970 case D3DFOG_NONE: /* Won't happen */
3971 default: FIXME("Unexpected WINED3DRS_FOGTABLEMODE %ld\n", This->stateBlock->renderState[WINED3DRS_FOGTABLEMODE]);
3974 if (GL_SUPPORT(NV_FOG_DISTANCE)) {
3975 glFogi(GL_FOG_DISTANCE_MODE_NV, GL_EYE_PLANE_ABSOLUTE_NV);
3980 case WINED3DRS_FOGSTART :
3983 glFogfv(GL_FOG_START, &tmpvalue.f);
3984 checkGLcall("glFogf(GL_FOG_START, (float) Value)");
3985 TRACE("Fog Start == %f\n", tmpvalue.f);
3989 case WINED3DRS_FOGEND :
3992 glFogfv(GL_FOG_END, &tmpvalue.f);
3993 checkGLcall("glFogf(GL_FOG_END, (float) Value)");
3994 TRACE("Fog End == %f\n", tmpvalue.f);
3998 case WINED3DRS_FOGDENSITY :
4001 glFogfv(GL_FOG_DENSITY, &tmpvalue.f);
4002 checkGLcall("glFogf(GL_FOG_DENSITY, (float) Value)");
4006 case WINED3DRS_VERTEXBLEND :
4008 This->updateStateBlock->vertex_blend = (D3DVERTEXBLENDFLAGS) Value;
4009 TRACE("Vertex Blending state to %ld\n", Value);
4013 case WINED3DRS_TWEENFACTOR :
4016 This->updateStateBlock->tween_factor = tmpvalue.f;
4017 TRACE("Vertex Blending Tween Factor to %f\n", This->updateStateBlock->tween_factor);
4021 case WINED3DRS_INDEXEDVERTEXBLENDENABLE :
4023 TRACE("Indexed Vertex Blend Enable to %ul\n", (BOOL) Value);
4027 case WINED3DRS_COLORVERTEX :
4028 case WINED3DRS_DIFFUSEMATERIALSOURCE :
4029 case WINED3DRS_SPECULARMATERIALSOURCE :
4030 case WINED3DRS_AMBIENTMATERIALSOURCE :
4031 case WINED3DRS_EMISSIVEMATERIALSOURCE :
4033 GLenum Parm = GL_AMBIENT_AND_DIFFUSE;
4035 if (This->stateBlock->renderState[WINED3DRS_COLORVERTEX]) {
4036 TRACE("diff %ld, amb %ld, emis %ld, spec %ld\n",
4037 This->stateBlock->renderState[WINED3DRS_DIFFUSEMATERIALSOURCE],
4038 This->stateBlock->renderState[WINED3DRS_AMBIENTMATERIALSOURCE],
4039 This->stateBlock->renderState[WINED3DRS_EMISSIVEMATERIALSOURCE],
4040 This->stateBlock->renderState[WINED3DRS_SPECULARMATERIALSOURCE]);
4042 if (This->stateBlock->renderState[WINED3DRS_DIFFUSEMATERIALSOURCE] == D3DMCS_COLOR1) {
4043 if (This->stateBlock->renderState[WINED3DRS_AMBIENTMATERIALSOURCE] == D3DMCS_COLOR1) {
4044 Parm = GL_AMBIENT_AND_DIFFUSE;
4048 } else if (This->stateBlock->renderState[WINED3DRS_AMBIENTMATERIALSOURCE] == D3DMCS_COLOR1) {
4050 } else if (This->stateBlock->renderState[WINED3DRS_EMISSIVEMATERIALSOURCE] == D3DMCS_COLOR1) {
4052 } else if (This->stateBlock->renderState[WINED3DRS_SPECULARMATERIALSOURCE] == D3DMCS_COLOR1) {
4059 if (This->tracking_color != DISABLED_TRACKING) This->tracking_color = NEEDS_DISABLE;
4061 This->tracking_color = NEEDS_TRACKING;
4062 This->tracking_parm = Parm;
4066 if (This->tracking_color != DISABLED_TRACKING) This->tracking_color = NEEDS_DISABLE;
4071 case WINED3DRS_LINEPATTERN :
4077 tmppattern.d = Value;
4079 TRACE("Line pattern: repeat %d bits %x\n", tmppattern.lp.wRepeatFactor, tmppattern.lp.wLinePattern);
4081 if (tmppattern.lp.wRepeatFactor) {
4082 glLineStipple(tmppattern.lp.wRepeatFactor, tmppattern.lp.wLinePattern);
4083 checkGLcall("glLineStipple(repeat, linepattern)");
4084 glEnable(GL_LINE_STIPPLE);
4085 checkGLcall("glEnable(GL_LINE_STIPPLE);");
4087 glDisable(GL_LINE_STIPPLE);
4088 checkGLcall("glDisable(GL_LINE_STIPPLE);");
4093 case WINED3DRS_ZBIAS : /* D3D8 only */
4097 TRACE("ZBias value %f\n", tmpvalue.f);
4098 glPolygonOffset(0, -tmpvalue.f);
4099 checkGLcall("glPolygonOffset(0, -Value)");
4100 glEnable(GL_POLYGON_OFFSET_FILL);
4101 checkGLcall("glEnable(GL_POLYGON_OFFSET_FILL);");
4102 glEnable(GL_POLYGON_OFFSET_LINE);
4103 checkGLcall("glEnable(GL_POLYGON_OFFSET_LINE);");
4104 glEnable(GL_POLYGON_OFFSET_POINT);
4105 checkGLcall("glEnable(GL_POLYGON_OFFSET_POINT);");
4107 glDisable(GL_POLYGON_OFFSET_FILL);
4108 checkGLcall("glDisable(GL_POLYGON_OFFSET_FILL);");
4109 glDisable(GL_POLYGON_OFFSET_LINE);
4110 checkGLcall("glDisable(GL_POLYGON_OFFSET_LINE);");
4111 glDisable(GL_POLYGON_OFFSET_POINT);
4112 checkGLcall("glDisable(GL_POLYGON_OFFSET_POINT);");
4117 case WINED3DRS_NORMALIZENORMALS :
4119 glEnable(GL_NORMALIZE);
4120 checkGLcall("glEnable(GL_NORMALIZE);");
4122 glDisable(GL_NORMALIZE);
4123 checkGLcall("glDisable(GL_NORMALIZE);");
4127 case WINED3DRS_POINTSIZE :
4128 /* FIXME: check that pointSize isn't outside glGetFloatv( GL_POINT_SIZE_MAX_ARB, &maxSize ); or -ve */
4130 TRACE("Set point size to %f\n", tmpvalue.f);
4131 glPointSize(tmpvalue.f);
4132 checkGLcall("glPointSize(...);");
4135 case WINED3DRS_POINTSIZE_MIN :
4136 if (GL_SUPPORT(EXT_POINT_PARAMETERS)) {
4138 GL_EXTCALL(glPointParameterfEXT)(GL_POINT_SIZE_MIN_EXT, tmpvalue.f);
4139 checkGLcall("glPointParameterfEXT(...);");
4141 FIXME("WINED3DRS_POINTSIZE_MIN not supported on this opengl\n");
4145 case WINED3DRS_POINTSIZE_MAX :
4146 if (GL_SUPPORT(EXT_POINT_PARAMETERS)) {
4148 GL_EXTCALL(glPointParameterfEXT)(GL_POINT_SIZE_MAX_EXT, tmpvalue.f);
4149 checkGLcall("glPointParameterfEXT(...);");
4151 FIXME("WINED3DRS_POINTSIZE_MAX not supported on this opengl\n");
4155 case WINED3DRS_POINTSCALE_A :
4156 case WINED3DRS_POINTSCALE_B :
4157 case WINED3DRS_POINTSCALE_C :
4158 case WINED3DRS_POINTSCALEENABLE :
4161 * POINTSCALEENABLE controls how point size value is treated. If set to
4162 * true, the point size is scaled with respect to height of viewport.
4163 * When set to false point size is in pixels.
4165 * http://msdn.microsoft.com/library/en-us/directx9_c/point_sprites.asp
4168 /* Default values */
4169 GLfloat att[3] = {1.0f, 0.0f, 0.0f};
4172 * Minimum valid point size for OpenGL is 1.0f. For Direct3D it is 0.0f.
4173 * This means that OpenGL will clamp really small point sizes to 1.0f.
4174 * To correct for this we need to multiply by the scale factor when sizes
4175 * are less than 1.0f. scale_factor = 1.0f / point_size.
4177 GLfloat pointSize = *((float*)&This->stateBlock->renderState[WINED3DRS_POINTSIZE]);
4178 if(pointSize > 0.0f) {
4179 GLfloat scaleFactor;
4181 if(pointSize < 1.0f) {
4182 scaleFactor = pointSize * pointSize;
4187 if(This->stateBlock->renderState[WINED3DRS_POINTSCALEENABLE]) {
4188 att[0] = *((float*)&This->stateBlock->renderState[WINED3DRS_POINTSCALE_A]) /
4189 (This->stateBlock->viewport.Height * This->stateBlock->viewport.Height * scaleFactor);
4190 att[1] = *((float*)&This->stateBlock->renderState[WINED3DRS_POINTSCALE_B]) /
4191 (This->stateBlock->viewport.Height * This->stateBlock->viewport.Height * scaleFactor);
4192 att[2] = *((float*)&This->stateBlock->renderState[WINED3DRS_POINTSCALE_C]) /
4193 (This->stateBlock->viewport.Height * This->stateBlock->viewport.Height * scaleFactor);
4197 if(GL_SUPPORT(ARB_POINT_PARAMETERS)) {
4198 GL_EXTCALL(glPointParameterfvARB)(GL_POINT_DISTANCE_ATTENUATION_ARB, att);
4199 checkGLcall("glPointParameterfvARB(GL_DISTANCE_ATTENUATION_ARB, ...");
4201 else if(GL_SUPPORT(EXT_POINT_PARAMETERS)) {
4202 GL_EXTCALL(glPointParameterfvEXT)(GL_DISTANCE_ATTENUATION_EXT, att);
4203 checkGLcall("glPointParameterfvEXT(GL_DISTANCE_ATTENUATION_EXT, ...");
4205 TRACE("POINT_PARAMETERS not supported in this version of opengl\n");
4209 case WINED3DRS_COLORWRITEENABLE :
4211 TRACE("Color mask: r(%d) g(%d) b(%d) a(%d)\n",
4212 Value & D3DCOLORWRITEENABLE_RED ? 1 : 0,
4213 Value & D3DCOLORWRITEENABLE_GREEN ? 1 : 0,
4214 Value & D3DCOLORWRITEENABLE_BLUE ? 1 : 0,
4215 Value & D3DCOLORWRITEENABLE_ALPHA ? 1 : 0);
4216 glColorMask(Value & D3DCOLORWRITEENABLE_RED ? GL_TRUE : GL_FALSE,
4217 Value & D3DCOLORWRITEENABLE_GREEN ? GL_TRUE : GL_FALSE,
4218 Value & D3DCOLORWRITEENABLE_BLUE ? GL_TRUE : GL_FALSE,
4219 Value & D3DCOLORWRITEENABLE_ALPHA ? GL_TRUE : GL_FALSE);
4220 checkGLcall("glColorMask(...)");
4224 case WINED3DRS_LOCALVIEWER :
4226 GLint state = (Value) ? 1 : 0;
4227 TRACE("Local Viewer Enable to %ul\n", (BOOL) Value);
4228 glLightModeli(GL_LIGHT_MODEL_LOCAL_VIEWER, state);
4232 case WINED3DRS_LASTPIXEL :
4235 TRACE("Last Pixel Drawing Enabled\n");
4237 FIXME("Last Pixel Drawing Disabled, not handled yet\n");
4242 case WINED3DRS_SOFTWAREVERTEXPROCESSING :
4245 TRACE("Software Processing Enabled\n");
4247 TRACE("Software Processing Disabled\n");
4252 /** not supported */
4253 case WINED3DRS_ZVISIBLE :
4256 return WINED3DERR_INVALIDCALL;
4258 case WINED3DRS_POINTSPRITEENABLE :
4260 /* TODO: NV_POINT_SPRITE */
4261 if (!GL_SUPPORT(ARB_POINT_SPRITE)) {
4262 TRACE("Point sprites not supported\n");
4267 * Point sprites are always enabled. Value controls texture coordinate
4268 * replacement mode. Must be set true for point sprites to use
4271 glEnable(GL_POINT_SPRITE_ARB);
4272 checkGLcall("glEnable(GL_POINT_SPRITE_ARB)");
4275 glTexEnvf(GL_POINT_SPRITE_ARB, GL_COORD_REPLACE_ARB, TRUE);
4276 checkGLcall("glTexEnvf(GL_POINT_SPRITE, GL_COORD_REPLACE, TRUE)");
4278 glTexEnvf(GL_POINT_SPRITE_ARB, GL_COORD_REPLACE_ARB, FALSE);
4279 checkGLcall("glTexEnvf(GL_POINT_SPRITE, GL_COORD_REPLACE, FALSE)");
4283 case WINED3DRS_EDGEANTIALIAS :
4286 glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
4288 checkGLcall("glEnable(GL_BLEND)");
4289 glEnable(GL_LINE_SMOOTH);
4290 checkGLcall("glEnable(GL_LINE_SMOOTH)");
4292 if(!This->stateBlock->renderState[WINED3DRS_ALPHABLENDENABLE]) {
4293 glDisable(GL_BLEND);
4294 checkGLcall("glDisable(GL_BLEND)");
4296 glDisable(GL_LINE_SMOOTH);
4297 checkGLcall("glDisable(GL_LINE_SMOOTH)");
4301 case WINED3DRS_WRAP0 :
4302 case WINED3DRS_WRAP1 :
4303 case WINED3DRS_WRAP2 :
4304 case WINED3DRS_WRAP3 :
4305 case WINED3DRS_WRAP4 :
4306 case WINED3DRS_WRAP5 :
4307 case WINED3DRS_WRAP6 :
4308 case WINED3DRS_WRAP7 :
4309 case WINED3DRS_WRAP8 :
4310 case WINED3DRS_WRAP9 :
4311 case WINED3DRS_WRAP10 :
4312 case WINED3DRS_WRAP11 :
4313 case WINED3DRS_WRAP12 :
4314 case WINED3DRS_WRAP13 :
4315 case WINED3DRS_WRAP14 :
4316 case WINED3DRS_WRAP15 :
4318 http://www.cosc.brocku.ca/Offerings/3P98/course/lectures/texture/
4319 http://msdn.microsoft.com/archive/default.asp?url=/archive/en-us/directx9_c/directx/graphics/programmingguide/FixedFunction/Textures/texturewrapping.asp
4320 http://www.gamedev.net/reference/programming/features/rendererdll3/page2.asp
4321 Descussion that ways to turn on WRAPing to solve an opengl conversion problem.
4322 http://www.flipcode.org/cgi-bin/fcmsg.cgi?thread_show=10248
4324 so far as I can tell, wrapping and texture-coordinate generate go hand in hand,
4328 ERR("(%p)->(%s,%ld) Texture wraping not yet supported\n",This, debug_d3drenderstate(State), Value);
4333 case WINED3DRS_MULTISAMPLEANTIALIAS :
4335 if( GL_SUPPORT(ARB_MULTISAMPLE) ) {
4337 glEnable(GL_MULTISAMPLE_ARB);
4338 checkGLcall("glEnable(GL_MULTISAMPLE_ARB)");
4340 glDisable(GL_MULTISAMPLE_ARB);
4341 checkGLcall("glDisable(GL_MULTISAMPLE_ARB)");
4345 ERR("Multisample antialiasing not supported by gl\n");
4351 case WINED3DRS_SCISSORTESTENABLE :
4354 glEnable(GL_SCISSOR_TEST);
4355 checkGLcall("glEnable(GL_SCISSOR_TEST)");
4357 glDisable(GL_SCISSOR_TEST);
4358 checkGLcall("glDisable(GL_SCISSOR_TEST)");
4362 case WINED3DRS_SLOPESCALEDEPTHBIAS :
4366 glEnable(GL_POLYGON_OFFSET_FILL);
4367 checkGLcall("glEnable(GL_POLYGON_OFFSET_FILL)");
4368 glPolygonOffset(tmpvalue.f, *((float*)&This->stateBlock->renderState[WINED3DRS_DEPTHBIAS]));
4369 checkGLcall("glPolygonOffset(...)");
4371 glDisable(GL_POLYGON_OFFSET_FILL);
4372 checkGLcall("glDisable(GL_POLYGON_OFFSET_FILL)");
4376 case WINED3DRS_ANTIALIASEDLINEENABLE :
4379 glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
4381 checkGLcall("glEnable(GL_BLEND)");
4382 glEnable(GL_LINE_SMOOTH);
4383 checkGLcall("glEnable(GL_LINE_SMOOTH)");
4385 glDisable(GL_BLEND);
4386 checkGLcall("glDisable(GL_BLEND)");
4387 glDisable(GL_LINE_SMOOTH);
4388 checkGLcall("glDisable(GL_LINE_SMOOTH)");
4392 case WINED3DRS_DEPTHBIAS :
4396 glEnable(GL_POLYGON_OFFSET_FILL);
4397 checkGLcall("glEnable(GL_POLYGON_OFFSET_FILL)");
4398 glPolygonOffset(*((float*)&This->stateBlock->renderState[WINED3DRS_SLOPESCALEDEPTHBIAS]), tmpvalue.f);
4399 checkGLcall("glPolygonOffset(...)");
4401 glDisable(GL_POLYGON_OFFSET_FILL);
4402 checkGLcall("glDisable(GL_POLYGON_OFFSET_FILL)");
4407 case WINED3DRS_TEXTUREPERSPECTIVE :
4410 glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST);
4412 glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_FASTEST);
4416 case WINED3DRS_STIPPLEDALPHA :
4419 ERR(" Stippled Alpha not supported yet.\n");
4422 case WINED3DRS_ANTIALIAS :
4425 ERR(" Antialias not supported yet.\n");
4429 case WINED3DRS_MULTISAMPLEMASK :
4431 if(0xFFFFFFFF != Value)
4432 ERR("(%p)->(%s,%ld) not yet implemented\n", This, debug_d3drenderstate(State), Value);
4436 case WINED3DRS_PATCHEDGESTYLE :
4438 if(D3DPATCHEDGE_DISCRETE != Value)
4439 ERR("(%p)->(%s,%ld) not yet implemented\n", This, debug_d3drenderstate(State), Value);
4443 case WINED3DRS_PATCHSEGMENTS :
4445 /* available in d3d8 but in d3d9 it was replaced by IDirect3DDevice9::SetNPatchMode */
4447 if(tmpvalue.d != Value)
4448 ERR("(%p)->(%s,%ld) not yet implemented\n", This, debug_d3drenderstate(State), Value);
4452 case WINED3DRS_DEBUGMONITORTOKEN :
4454 /* Only useful for "debug builds". */
4455 if(0xbaadcafe != Value) {
4456 /* MSDN says the default is D3DDMT_ENABLE but our tests confirm 0xbaadcafe is the default. */
4457 /* MSDN says anything other than D3DDMT_ENABLE or DISABLE does not change the state,
4458 * but our tests disagree.
4459 * We do not claim to implement a debugging lib, so do not write an ERR
4461 WARN("(%p)->(%s,%ld) not yet implemented\n", This, debug_d3drenderstate(State), Value);
4466 case WINED3DRS_POSITIONDEGREE :
4468 if(D3DDEGREE_CUBIC != Value)
4469 ERR("(%p)->(%s,%ld) not yet implemented\n", This, debug_d3drenderstate(State), Value);
4473 case WINED3DRS_NORMALDEGREE :
4475 if(D3DDEGREE_LINEAR != Value)
4476 ERR("(%p)->(%s,%ld) not yet implemented\n", This, debug_d3drenderstate(State), Value);
4480 case WINED3DRS_MINTESSELLATIONLEVEL :
4481 case WINED3DRS_MAXTESSELLATIONLEVEL :
4482 case WINED3DRS_ADAPTIVETESS_X :
4483 case WINED3DRS_ADAPTIVETESS_Y :
4484 case WINED3DRS_ADAPTIVETESS_Z :
4485 case WINED3DRS_ADAPTIVETESS_W :
4487 if(This->stateBlock->renderState[WINED3DRS_ENABLEADAPTIVETESSELLATION])
4488 FIXME("(%p)->(%s,%ld) not yet implemented\n", This, debug_d3drenderstate(State), Value);
4490 TRACE("(%p)->(%s,%ld): recording state but WINED3DRS_ENABLEADAPTIVETESSELLATION is not enabled\n", This, debug_d3drenderstate(State), Value);
4494 case WINED3DRS_ENABLEADAPTIVETESSELLATION:
4497 ERR("(%p)->(%s,%ld) not yet implemented\n", This, debug_d3drenderstate(State), Value);
4501 case WINED3DRS_COLORWRITEENABLE1 :
4502 case WINED3DRS_COLORWRITEENABLE2 :
4503 case WINED3DRS_COLORWRITEENABLE3 :
4505 /* depends on WINED3DRS_COLORWRITEENABLE. */
4506 if(0x0000000F != Value)
4507 ERR("(%p)->(%s,%ld) not yet implemented. Missing of cap D3DPMISCCAPS_INDEPENDENTWRITEMASKS wasn't honored?\n", This, debug_d3drenderstate(State), Value);
4511 case WINED3DRS_BLENDFACTOR :
4515 TRACE("Setting BlendFactor to %ld\n", Value);
4517 D3DCOLORTOGLFLOAT4(Value, col);
4518 if (0xFFFFFFFF != Value) {
4520 checkGLcall("glEnable(GL_BLEND)");
4523 glDisable(GL_BLEND);
4524 checkGLcall("glDisable(GL_BLEND)");
4526 glBlendColor (col[0],col[1],col[2],col[3]);
4530 case WINED3DRS_SRGBWRITEENABLE :
4533 ERR("(%p)->(%s,%ld) not yet implemented\n", This, debug_d3drenderstate(State), Value);
4537 case WINED3DRS_SEPARATEALPHABLENDENABLE :
4540 ERR("(%p)->(%s,%ld) not yet implemented. Missing of cap D3DPMISCCAPS_SEPARATEALPHABLEND wasn't honored?\n", This, debug_d3drenderstate(State), Value);
4544 case WINED3DRS_SRCBLENDALPHA :
4545 case WINED3DRS_DESTBLENDALPHA :
4546 case WINED3DRS_BLENDOPALPHA :
4548 if(This->stateBlock->renderState[WINED3DRS_SEPARATEALPHABLENDENABLE])
4549 FIXME("(%p)->(%s,%ld) not yet implemented\n", This, debug_d3drenderstate(State), Value);
4551 TRACE("(%p)->(%s,%ld): recording state but WINED3DRS_SEPARATEALPHABLENDENABLE is not enabled\n", This, debug_d3drenderstate(State), Value);
4556 FIXME("(%p)->(%s,%ld) unknown state\n", This, debug_d3drenderstate(State), Value);
4564 static HRESULT WINAPI IWineD3DDeviceImpl_GetRenderState(IWineD3DDevice *iface, D3DRENDERSTATETYPE State, DWORD *pValue) {
4565 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4566 TRACE("(%p) for State %d = %ld\n", This, State, This->stateBlock->renderState[State]);
4567 *pValue = This->stateBlock->renderState[State];
4572 * Get / Set Sampler States
4573 * TODO: Verify against dx9 definitions
4576 static HRESULT WINAPI IWineD3DDeviceImpl_SetSamplerState(IWineD3DDevice *iface, DWORD Sampler, WINED3DSAMPLERSTATETYPE Type, DWORD Value) {
4577 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4579 * SetSampler is designed to allow for more than the standard up to 8 textures
4580 * and Geforce has stopped supporting more than 6 standard textures in openGL.
4581 * So I have to use ARB for Gforce. (maybe if the sampler > 4 then use ARB?)
4583 * http://developer.nvidia.com/object/General_FAQ.html#t6
4585 * There are two new settings for GForce
4587 * GL_MAX_TEXTURE_IMAGE_UNITS_ARB
4588 * and the texture one:
4589 * GL_MAX_TEXTURE_COORDS_ARB.
4590 * Ok GForce say it's ok to use glTexParameter/glGetTexParameter(...).
4592 /** NOTE: States are appled in IWineD3DBaseTextre ApplyStateChanges and IWineD3DDevice SetupTextureStates**/
4593 if(Sampler > GL_LIMITS(sampler_stages) || Sampler < 0 || Type > WINED3D_HIGHEST_SAMPLER_STATE || Type < 0) {
4594 FIXME("sampler %ld type %s(%u) is out of range [max_samplers=%d, highest_state=%d]\n",
4595 Sampler, debug_d3dsamplerstate(Type), Type, GL_LIMITS(sampler_stages), WINED3D_HIGHEST_SAMPLER_STATE);
4596 return WINED3DERR_INVALIDCALL;
4599 TRACE("(%p) : Sampler=%ld, Type=%s(%d), Value=%ld\n", This, Sampler,
4600 debug_d3dsamplerstate(Type), Type, Value);
4601 This->updateStateBlock->samplerState[Sampler][Type] = Value;
4602 This->updateStateBlock->set.samplerState[Sampler][Type] = Value;
4603 This->updateStateBlock->changed.samplerState[Sampler][Type] = Value;
4605 /* Handle recording of state blocks */
4606 if (This->isRecordingState) {
4607 TRACE("Recording... not performing anything\n");
4614 static HRESULT WINAPI IWineD3DDeviceImpl_GetSamplerState(IWineD3DDevice *iface, DWORD Sampler, WINED3DSAMPLERSTATETYPE Type, DWORD* Value) {
4615 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4616 /** TODO: check that sampler is in range **/
4617 *Value = This->updateStateBlock->samplerState[Sampler][Type];
4618 TRACE("(%p) : Sampler %ld Type %u Returning %ld\n", This, Sampler, Type, *Value);
4623 static HRESULT WINAPI IWineD3DDeviceImpl_SetScissorRect(IWineD3DDevice *iface, CONST RECT* pRect) {
4624 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4627 /** FIXME: Windows uses a top,left origin openGL uses a bottom Right? **/
4628 TRACE("(%p)Setting new Scissor Rect to %ld:%ld-%ld:%ld\n", This, pRect->left, pRect->top, pRect->right, pRect->bottom);
4629 glScissor(pRect->left, pRect->top, pRect->right - pRect->left, pRect->bottom - pRect->top);
4635 static HRESULT WINAPI IWineD3DDeviceImpl_GetScissorRect(IWineD3DDevice *iface, RECT* pRect) {
4636 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4637 GLint scissorBox[4];
4640 /** FIXME: Windows uses a top,left origin openGL uses a bottom Right? **/
4641 glGetIntegerv(GL_SCISSOR_BOX, scissorBox);
4642 pRect->left = scissorBox[0];
4643 pRect->top = scissorBox[1];
4644 pRect->right = scissorBox[0] + scissorBox[2];
4645 pRect->bottom = scissorBox[1] + scissorBox[3];
4646 TRACE("(%p)Returning a Scissor Rect of %ld:%ld-%ld:%ld\n", This, pRect->left, pRect->top, pRect->right, pRect->bottom);
4651 static HRESULT WINAPI IWineD3DDeviceImpl_SetVertexDeclaration(IWineD3DDevice* iface, IWineD3DVertexDeclaration* pDecl) {
4652 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *) iface;
4653 IWineD3DVertexDeclaration *oldDecl = This->updateStateBlock->vertexDecl;
4655 TRACE("(%p) : pDecl=%p\n", This, pDecl);
4657 This->updateStateBlock->vertexDecl = pDecl;
4658 This->updateStateBlock->changed.vertexDecl = TRUE;
4659 This->updateStateBlock->set.vertexDecl = TRUE;
4661 if (This->isRecordingState) {
4662 TRACE("Recording... not performing anything\n");
4665 if (NULL != pDecl) {
4666 IWineD3DVertexDeclaration_AddRef(pDecl);
4668 if (NULL != oldDecl) {
4669 IWineD3DVertexDeclaration_Release(oldDecl);
4674 static HRESULT WINAPI IWineD3DDeviceImpl_GetVertexDeclaration(IWineD3DDevice* iface, IWineD3DVertexDeclaration** ppDecl) {
4675 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4677 TRACE("(%p) : ppDecl=%p\n", This, ppDecl);
4679 *ppDecl = This->stateBlock->vertexDecl;
4680 if (NULL != *ppDecl) IWineD3DVertexDeclaration_AddRef(*ppDecl);
4684 static HRESULT WINAPI IWineD3DDeviceImpl_SetVertexShader(IWineD3DDevice *iface, IWineD3DVertexShader* pShader) {
4685 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4686 IWineD3DVertexShader* oldShader = This->updateStateBlock->vertexShader;
4688 This->updateStateBlock->vertexShader = pShader;
4689 This->updateStateBlock->changed.vertexShader = TRUE;
4690 This->updateStateBlock->set.vertexShader = TRUE;
4692 if (This->isRecordingState) {
4693 TRACE("Recording... not performing anything\n");
4696 if (NULL != pShader) {
4697 IWineD3DVertexShader_AddRef(pShader);
4699 if (NULL != oldShader) {
4700 IWineD3DVertexShader_Release(oldShader);
4703 TRACE("(%p) : setting pShader(%p)\n", This, pShader);
4705 * TODO: merge HAL shaders context switching from prototype
4710 static HRESULT WINAPI IWineD3DDeviceImpl_GetVertexShader(IWineD3DDevice *iface, IWineD3DVertexShader** ppShader) {
4711 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4713 if (NULL == ppShader) {
4714 return WINED3DERR_INVALIDCALL;
4716 *ppShader = This->stateBlock->vertexShader;
4717 if( NULL != *ppShader)
4718 IWineD3DVertexShader_AddRef(*ppShader);
4720 TRACE("(%p) : returning %p\n", This, *ppShader);
4724 static HRESULT WINAPI IWineD3DDeviceImpl_SetVertexShaderConstantB(
4725 IWineD3DDevice *iface,
4727 CONST BOOL *srcData,
4730 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4731 int i, cnt = min(count, MAX_CONST_B - start);
4733 TRACE("(iface %p, srcData %p, start %d, count %d)\n",
4734 iface, srcData, start, count);
4736 if (srcData == NULL || cnt < 0)
4737 return WINED3DERR_INVALIDCALL;
4739 memcpy(&This->updateStateBlock->vertexShaderConstantB[start], srcData, cnt * sizeof(BOOL));
4740 for (i = 0; i < cnt; i++)
4741 TRACE("Set BOOL constant %u to %s\n", start + i, srcData[i]? "true":"false");
4743 for (i = start; i < cnt + start; ++i) {
4744 This->updateStateBlock->changed.vertexShaderConstantsB[i] = TRUE;
4745 This->updateStateBlock->set.vertexShaderConstantsB[i] = TRUE;
4751 static HRESULT WINAPI IWineD3DDeviceImpl_GetVertexShaderConstantB(
4752 IWineD3DDevice *iface,
4757 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4758 int cnt = min(count, MAX_CONST_B - start);
4760 TRACE("(iface %p, dstData %p, start %d, count %d)\n",
4761 iface, dstData, start, count);
4763 if (dstData == NULL || cnt < 0)
4764 return WINED3DERR_INVALIDCALL;
4766 memcpy(dstData, &This->stateBlock->vertexShaderConstantB[start], cnt * sizeof(BOOL));
4770 static HRESULT WINAPI IWineD3DDeviceImpl_SetVertexShaderConstantI(
4771 IWineD3DDevice *iface,
4776 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4777 int i, cnt = min(count, MAX_CONST_I - start);
4779 TRACE("(iface %p, srcData %p, start %d, count %d)\n",
4780 iface, srcData, start, count);
4782 if (srcData == NULL || cnt < 0)
4783 return WINED3DERR_INVALIDCALL;
4785 memcpy(&This->updateStateBlock->vertexShaderConstantI[start * 4], srcData, cnt * sizeof(int) * 4);
4786 for (i = 0; i < cnt; i++)
4787 TRACE("Set INT constant %u to { %d, %d, %d, %d }\n", start + i,
4788 srcData[i*4], srcData[i*4+1], srcData[i*4+2], srcData[i*4+3]);
4790 for (i = start; i < cnt + start; ++i) {
4791 This->updateStateBlock->changed.vertexShaderConstantsI[i] = TRUE;
4792 This->updateStateBlock->set.vertexShaderConstantsI[i] = TRUE;
4798 static HRESULT WINAPI IWineD3DDeviceImpl_GetVertexShaderConstantI(
4799 IWineD3DDevice *iface,
4804 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4805 int cnt = min(count, MAX_CONST_I - start);
4807 TRACE("(iface %p, dstData %p, start %d, count %d)\n",
4808 iface, dstData, start, count);
4810 if (dstData == NULL || ((signed int) MAX_CONST_I - (signed int) start) <= (signed int) 0)
4811 return WINED3DERR_INVALIDCALL;
4813 memcpy(dstData, &This->stateBlock->vertexShaderConstantI[start * 4], cnt * sizeof(int) * 4);
4817 static HRESULT WINAPI IWineD3DDeviceImpl_SetVertexShaderConstantF(
4818 IWineD3DDevice *iface,
4820 CONST float *srcData,
4823 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4824 int i, cnt = min(count, GL_LIMITS(vshader_constantsF) - start);
4826 TRACE("(iface %p, srcData %p, start %d, count %d)\n",
4827 iface, srcData, start, count);
4829 if (srcData == NULL || ((signed int) GL_LIMITS(vshader_constantsF) - (signed int) start) <= (signed int) 0)
4830 return WINED3DERR_INVALIDCALL;
4832 memcpy(&This->updateStateBlock->vertexShaderConstantF[start * 4], srcData, cnt * sizeof(float) * 4);
4833 for (i = 0; i < cnt; i++)
4834 TRACE("Set FLOAT constant %u to { %f, %f, %f, %f }\n", start + i,
4835 srcData[i*4], srcData[i*4+1], srcData[i*4+2], srcData[i*4+3]);
4837 for (i = start; i < cnt + start; ++i) {
4838 if (!This->updateStateBlock->set.vertexShaderConstantsF[i]) {
4839 constant_entry *ptr = HeapAlloc(GetProcessHeap(), 0, sizeof(constant_entry));
4841 list_add_head(&This->updateStateBlock->set_vconstantsF, &ptr->entry);
4842 This->updateStateBlock->set.vertexShaderConstantsF[i] = TRUE;
4844 This->updateStateBlock->changed.vertexShaderConstantsF[i] = TRUE;
4850 static HRESULT WINAPI IWineD3DDeviceImpl_GetVertexShaderConstantF(
4851 IWineD3DDevice *iface,
4856 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4857 int cnt = min(count, GL_LIMITS(vshader_constantsF) - start);
4859 TRACE("(iface %p, dstData %p, start %d, count %d)\n",
4860 iface, dstData, start, count);
4862 if (dstData == NULL || cnt < 0)
4863 return WINED3DERR_INVALIDCALL;
4865 memcpy(dstData, &This->stateBlock->vertexShaderConstantF[start * 4], cnt * sizeof(float) * 4);
4869 static HRESULT WINAPI IWineD3DDeviceImpl_SetPixelShader(IWineD3DDevice *iface, IWineD3DPixelShader *pShader) {
4870 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4871 IWineD3DPixelShader *oldShader = This->updateStateBlock->pixelShader;
4872 This->updateStateBlock->pixelShader = pShader;
4873 This->updateStateBlock->changed.pixelShader = TRUE;
4874 This->updateStateBlock->set.pixelShader = TRUE;
4876 /* Handle recording of state blocks */
4877 if (This->isRecordingState) {
4878 TRACE("Recording... not performing anything\n");
4881 if (NULL != pShader) {
4882 IWineD3DPixelShader_AddRef(pShader);
4884 if (NULL != oldShader) {
4885 IWineD3DPixelShader_Release(oldShader);
4888 TRACE("(%p) : setting pShader(%p)\n", This, pShader);
4890 * TODO: merge HAL shaders context switching from prototype
4895 static HRESULT WINAPI IWineD3DDeviceImpl_GetPixelShader(IWineD3DDevice *iface, IWineD3DPixelShader **ppShader) {
4896 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4898 if (NULL == ppShader) {
4899 WARN("(%p) : PShader is NULL, returning INVALIDCALL\n", This);
4900 return WINED3DERR_INVALIDCALL;
4903 *ppShader = This->stateBlock->pixelShader;
4904 if (NULL != *ppShader) {
4905 IWineD3DPixelShader_AddRef(*ppShader);
4907 TRACE("(%p) : returning %p\n", This, *ppShader);
4911 static HRESULT WINAPI IWineD3DDeviceImpl_SetPixelShaderConstantB(
4912 IWineD3DDevice *iface,
4914 CONST BOOL *srcData,
4917 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4918 int i, cnt = min(count, MAX_CONST_B - start);
4920 TRACE("(iface %p, srcData %p, start %d, count %d)\n",
4921 iface, srcData, start, count);
4923 if (srcData == NULL || cnt < 0)
4924 return WINED3DERR_INVALIDCALL;
4926 memcpy(&This->updateStateBlock->pixelShaderConstantB[start], srcData, cnt * sizeof(BOOL));
4927 for (i = 0; i < cnt; i++)
4928 TRACE("Set BOOL constant %u to %s\n", start + i, srcData[i]? "true":"false");
4930 for (i = start; i < cnt + start; ++i) {
4931 This->updateStateBlock->changed.pixelShaderConstantsB[i] = TRUE;
4932 This->updateStateBlock->set.pixelShaderConstantsB[i] = TRUE;
4938 static HRESULT WINAPI IWineD3DDeviceImpl_GetPixelShaderConstantB(
4939 IWineD3DDevice *iface,
4944 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4945 int cnt = min(count, MAX_CONST_B - start);
4947 TRACE("(iface %p, dstData %p, start %d, count %d)\n",
4948 iface, dstData, start, count);
4950 if (dstData == NULL || cnt < 0)
4951 return WINED3DERR_INVALIDCALL;
4953 memcpy(dstData, &This->stateBlock->pixelShaderConstantB[start], cnt * sizeof(BOOL));
4957 static HRESULT WINAPI IWineD3DDeviceImpl_SetPixelShaderConstantI(
4958 IWineD3DDevice *iface,
4963 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4964 int i, cnt = min(count, MAX_CONST_I - start);
4966 TRACE("(iface %p, srcData %p, start %d, count %d)\n",
4967 iface, srcData, start, count);
4969 if (srcData == NULL || cnt < 0)
4970 return WINED3DERR_INVALIDCALL;
4972 memcpy(&This->updateStateBlock->pixelShaderConstantI[start * 4], srcData, cnt * sizeof(int) * 4);
4973 for (i = 0; i < cnt; i++)
4974 TRACE("Set INT constant %u to { %d, %d, %d, %d }\n", start + i,
4975 srcData[i*4], srcData[i*4+1], srcData[i*4+2], srcData[i*4+3]);
4977 for (i = start; i < cnt + start; ++i) {
4978 This->updateStateBlock->changed.pixelShaderConstantsI[i] = TRUE;
4979 This->updateStateBlock->set.pixelShaderConstantsI[i] = TRUE;
4985 static HRESULT WINAPI IWineD3DDeviceImpl_GetPixelShaderConstantI(
4986 IWineD3DDevice *iface,
4991 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4992 int cnt = min(count, MAX_CONST_I - start);
4994 TRACE("(iface %p, dstData %p, start %d, count %d)\n",
4995 iface, dstData, start, count);
4997 if (dstData == NULL || cnt < 0)
4998 return WINED3DERR_INVALIDCALL;
5000 memcpy(dstData, &This->stateBlock->pixelShaderConstantI[start * 4], cnt * sizeof(int) * 4);
5004 static HRESULT WINAPI IWineD3DDeviceImpl_SetPixelShaderConstantF(
5005 IWineD3DDevice *iface,
5007 CONST float *srcData,
5010 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5011 int i, cnt = min(count, GL_LIMITS(pshader_constantsF) - start);
5013 TRACE("(iface %p, srcData %p, start %d, count %d)\n",
5014 iface, srcData, start, count);
5016 if (srcData == NULL || cnt < 0)
5017 return WINED3DERR_INVALIDCALL;
5019 memcpy(&This->updateStateBlock->pixelShaderConstantF[start * 4], srcData, cnt * sizeof(float) * 4);
5020 for (i = 0; i < cnt; i++)
5021 TRACE("Set FLOAT constant %u to { %f, %f, %f, %f }\n", start + i,
5022 srcData[i*4], srcData[i*4+1], srcData[i*4+2], srcData[i*4+3]);
5024 for (i = start; i < cnt + start; ++i) {
5025 if (!This->updateStateBlock->set.pixelShaderConstantsF[i]) {
5026 constant_entry *ptr = HeapAlloc(GetProcessHeap(), 0, sizeof(constant_entry));
5028 list_add_head(&This->updateStateBlock->set_pconstantsF, &ptr->entry);
5029 This->updateStateBlock->set.pixelShaderConstantsF[i] = TRUE;
5031 This->updateStateBlock->changed.pixelShaderConstantsF[i] = TRUE;
5037 static HRESULT WINAPI IWineD3DDeviceImpl_GetPixelShaderConstantF(
5038 IWineD3DDevice *iface,
5043 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5044 int cnt = min(count, GL_LIMITS(pshader_constantsF) - start);
5046 TRACE("(iface %p, dstData %p, start %d, count %d)\n",
5047 iface, dstData, start, count);
5049 if (dstData == NULL || cnt < 0)
5050 return WINED3DERR_INVALIDCALL;
5052 memcpy(dstData, &This->stateBlock->pixelShaderConstantF[start * 4], cnt * sizeof(float) * 4);
5056 #define copy_and_next(dest, src, size) memcpy(dest, src, size); dest += (size)
5058 process_vertices_strided(IWineD3DDeviceImpl *This, DWORD dwDestIndex, DWORD dwCount, WineDirect3DVertexStridedData *lpStrideData, DWORD SrcFVF, IWineD3DVertexBufferImpl *dest, DWORD dwFlags) {
5059 char *dest_ptr, *dest_conv = NULL;
5061 DWORD DestFVF = dest->fvf;
5063 D3DMATRIX mat, proj_mat, view_mat, world_mat;
5067 if (SrcFVF & D3DFVF_NORMAL) {
5068 WARN(" lighting state not saved yet... Some strange stuff may happen !\n");
5071 if ( (SrcFVF & D3DFVF_POSITION_MASK) != D3DFVF_XYZ) {
5072 ERR("Source has no position mask\n");
5073 return WINED3DERR_INVALIDCALL;
5076 /* We might access VBOs from this code, so hold the lock */
5079 if (dest->resource.allocatedMemory == NULL) {
5080 /* This may happen if we do direct locking into a vbo. Unlikely,
5081 * but theoretically possible(ddraw processvertices test)
5083 dest->resource.allocatedMemory = HeapAlloc(GetProcessHeap(), 0, dest->resource.size);
5084 if(!dest->resource.allocatedMemory) {
5086 ERR("Out of memory\n");
5087 return E_OUTOFMEMORY;
5091 GL_EXTCALL(glBindBufferARB(GL_ARRAY_BUFFER_ARB, dest->vbo));
5092 checkGLcall("glBindBufferARB");
5093 src = GL_EXTCALL(glMapBufferARB(GL_ARRAY_BUFFER_ARB, GL_READ_ONLY_ARB));
5095 memcpy(dest->resource.allocatedMemory, src, dest->resource.size);
5097 GL_EXTCALL(glUnmapBufferARB(GL_ARRAY_BUFFER_ARB));
5098 checkGLcall("glUnmapBufferARB");
5102 /* Get a pointer into the destination vbo(create one if none exists) and
5103 * write correct opengl data into it. It's cheap and allows us to run drawStridedFast
5105 if(!dest->vbo && GL_SUPPORT(ARB_VERTEX_BUFFER_OBJECT)) {
5110 GL_EXTCALL(glBindBufferARB(GL_ARRAY_BUFFER_ARB, dest->vbo));
5111 dest_conv = GL_EXTCALL(glMapBufferARB(GL_ARRAY_BUFFER_ARB, GL_WRITE_ONLY_ARB));
5113 ERR("glMapBuffer failed\n");
5114 /* Continue without storing converted vertices */
5119 * a) D3DRS_CLIPPING is enabled
5120 * b) WINED3DVOP_CLIP is passed
5122 if(This->stateBlock->renderState[WINED3DRS_CLIPPING]) {
5123 static BOOL warned = FALSE;
5125 * The clipping code is not quite correct. Some things need
5126 * to be checked against IDirect3DDevice3 (!), d3d8 and d3d9,
5127 * so disable clipping for now.
5128 * (The graphics in Half-Life are broken, and my processvertices
5129 * test crashes with IDirect3DDevice3)
5135 FIXME("Clipping is broken and disabled for now\n");
5137 } else doClip = FALSE;
5138 dest_ptr = ((char *) dest->resource.allocatedMemory) + dwDestIndex * get_flexible_vertex_size(DestFVF);
5140 dest_conv = ((char *) dest_conv) + dwDestIndex * get_flexible_vertex_size(DestFVF);
5143 IWineD3DDevice_GetTransform( (IWineD3DDevice *) This,
5146 IWineD3DDevice_GetTransform( (IWineD3DDevice *) This,
5147 WINED3DTS_PROJECTION,
5149 IWineD3DDevice_GetTransform( (IWineD3DDevice *) This,
5150 WINED3DTS_WORLDMATRIX(0),
5153 TRACE("View mat:\n");
5154 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); \
5155 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); \
5156 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); \
5157 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); \
5159 TRACE("Proj mat:\n");
5160 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); \
5161 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); \
5162 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); \
5163 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); \
5165 TRACE("World mat:\n");
5166 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); \
5167 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); \
5168 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); \
5169 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); \
5171 /* Get the viewport */
5172 IWineD3DDevice_GetViewport( (IWineD3DDevice *) This, &vp);
5173 TRACE("Viewport: X=%ld, Y=%ld, Width=%ld, Height=%ld, MinZ=%f, MaxZ=%f\n",
5174 vp.X, vp.Y, vp.Width, vp.Height, vp.MinZ, vp.MaxZ);
5176 multiply_matrix(&mat,&view_mat,&world_mat);
5177 multiply_matrix(&mat,&proj_mat,&mat);
5179 numTextures = (DestFVF & D3DFVF_TEXCOUNT_MASK) >> D3DFVF_TEXCOUNT_SHIFT;
5181 for (i = 0; i < dwCount; i+= 1) {
5182 unsigned int tex_index;
5184 if ( ((DestFVF & D3DFVF_POSITION_MASK) == D3DFVF_XYZ ) ||
5185 ((DestFVF & D3DFVF_POSITION_MASK) == D3DFVF_XYZRHW ) ) {
5186 /* The position first */
5188 (float *) (((char *) lpStrideData->u.s.position.lpData) + i * lpStrideData->u.s.position.dwStride);
5190 TRACE("In: ( %06.2f %06.2f %06.2f )\n", p[0], p[1], p[2]);
5192 /* Multiplication with world, view and projection matrix */
5193 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);
5194 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);
5195 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);
5196 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);
5198 TRACE("x=%f y=%f z=%f rhw=%f\n", x, y, z, rhw);
5200 /* WARNING: The following things are taken from d3d7 and were not yet checked
5201 * against d3d8 or d3d9!
5204 /* Clipping conditions: From
5205 * http://msdn.microsoft.com/archive/default.asp?url=/archive/en-us/directx9_c/directx/graphics/programmingguide/fixedfunction/viewportsclipping/clippingvolumes.asp
5207 * A vertex is clipped if it does not match the following requirements
5211 * 0 < rhw ( Not in d3d7, but tested in d3d7)
5213 * If clipping is on is determined by the D3DVOP_CLIP flag in D3D7, and
5214 * by the D3DRS_CLIPPING in D3D9(according to the msdn, not checked)
5218 if( doClip == FALSE ||
5219 ( (-rhw -eps < x) && (-rhw -eps < y) && ( -eps < z) &&
5220 (x <= rhw + eps) && (y <= rhw + eps ) && (z <= rhw + eps) &&
5223 /* "Normal" viewport transformation (not clipped)
5224 * 1) The values are divided by rhw
5225 * 2) The y axis is negative, so multiply it with -1
5226 * 3) Screen coordinates go from -(Width/2) to +(Width/2) and
5227 * -(Height/2) to +(Height/2). The z range is MinZ to MaxZ
5228 * 4) Multiply x with Width/2 and add Width/2
5229 * 5) The same for the height
5230 * 6) Add the viewpoint X and Y to the 2D coordinates and
5231 * The minimum Z value to z
5232 * 7) rhw = 1 / rhw Reciprocal of Homogeneous W....
5234 * Well, basically it's simply a linear transformation into viewport
5246 z *= vp.MaxZ - vp.MinZ;
5248 x += vp.Width / 2 + vp.X;
5249 y += vp.Height / 2 + vp.Y;
5254 /* That vertex got clipped
5255 * Contrary to OpenGL it is not dropped completely, it just
5256 * undergoes a different calculation.
5258 TRACE("Vertex got clipped\n");
5265 /* Msdn mentions that Direct3D9 keeps a list of clipped vertices
5266 * outside of the main vertex buffer memory. That needs some more
5271 TRACE("Writing (%f %f %f) %f\n", x, y, z, rhw);
5274 ( (float *) dest_ptr)[0] = x;
5275 ( (float *) dest_ptr)[1] = y;
5276 ( (float *) dest_ptr)[2] = z;
5277 ( (float *) dest_ptr)[3] = rhw; /* SIC, see ddraw test! */
5279 dest_ptr += 3 * sizeof(float);
5281 if((DestFVF & D3DFVF_POSITION_MASK) == D3DFVF_XYZRHW) {
5282 dest_ptr += sizeof(float);
5287 ( (float *) dest_conv)[0] = x * w;
5288 ( (float *) dest_conv)[1] = y * w;
5289 ( (float *) dest_conv)[2] = z * w;
5290 ( (float *) dest_conv)[3] = w;
5292 dest_conv += 3 * sizeof(float);
5294 if((DestFVF & D3DFVF_POSITION_MASK) == D3DFVF_XYZRHW) {
5295 dest_conv += sizeof(float);
5299 if (DestFVF & D3DFVF_PSIZE) {
5300 dest_ptr += sizeof(DWORD);
5301 if(dest_conv) dest_conv += sizeof(DWORD);
5303 if (DestFVF & D3DFVF_NORMAL) {
5305 (float *) (((float *) lpStrideData->u.s.normal.lpData) + i * lpStrideData->u.s.normal.dwStride);
5306 /* AFAIK this should go into the lighting information */
5307 FIXME("Didn't expect the destination to have a normal\n");
5308 copy_and_next(dest_ptr, normal, 3 * sizeof(float));
5310 copy_and_next(dest_conv, normal, 3 * sizeof(float));
5314 if (DestFVF & D3DFVF_DIFFUSE) {
5316 (DWORD *) (((char *) lpStrideData->u.s.diffuse.lpData) + i * lpStrideData->u.s.diffuse.dwStride);
5318 static BOOL warned = FALSE;
5320 if(warned == FALSE) {
5321 ERR("No diffuse color in source, but destination has one\n");
5325 *( (DWORD *) dest_ptr) = 0xffffffff;
5326 dest_ptr += sizeof(DWORD);
5329 *( (DWORD *) dest_conv) = 0xffffffff;
5330 dest_conv += sizeof(DWORD);
5334 copy_and_next(dest_ptr, color_d, sizeof(DWORD));
5336 *( (DWORD *) dest_conv) = (*color_d & 0xff00ff00) ; /* Alpha + green */
5337 *( (DWORD *) dest_conv) |= (*color_d & 0x00ff0000) >> 16; /* Red */
5338 *( (DWORD *) dest_conv) |= (*color_d & 0xff0000ff) << 16; /* Blue */
5339 dest_conv += sizeof(DWORD);
5344 if (DestFVF & D3DFVF_SPECULAR) {
5345 /* What's the color value in the feedback buffer? */
5347 (DWORD *) (((char *) lpStrideData->u.s.specular.lpData) + i * lpStrideData->u.s.specular.dwStride);
5349 static BOOL warned = FALSE;
5351 if(warned == FALSE) {
5352 ERR("No specular color in source, but destination has one\n");
5356 *( (DWORD *) dest_ptr) = 0xFF000000;
5357 dest_ptr += sizeof(DWORD);
5360 *( (DWORD *) dest_conv) = 0xFF000000;
5361 dest_conv += sizeof(DWORD);
5365 copy_and_next(dest_ptr, color_s, sizeof(DWORD));
5367 *( (DWORD *) dest_conv) = (*color_s & 0xff00ff00) ; /* Alpha + green */
5368 *( (DWORD *) dest_conv) |= (*color_s & 0x00ff0000) >> 16; /* Red */
5369 *( (DWORD *) dest_conv) |= (*color_s & 0xff0000ff) << 16; /* Blue */
5370 dest_conv += sizeof(DWORD);
5375 for (tex_index = 0; tex_index < numTextures; tex_index++) {
5377 (float *) (((char *) lpStrideData->u.s.texCoords[tex_index].lpData) +
5378 i * lpStrideData->u.s.texCoords[tex_index].dwStride);
5380 ERR("No source texture, but destination requests one\n");
5381 dest_ptr+=GET_TEXCOORD_SIZE_FROM_FVF(DestFVF, tex_index) * sizeof(float);
5382 if(dest_conv) dest_conv += GET_TEXCOORD_SIZE_FROM_FVF(DestFVF, tex_index) * sizeof(float);
5385 copy_and_next(dest_ptr, tex_coord, GET_TEXCOORD_SIZE_FROM_FVF(DestFVF, tex_index) * sizeof(float));
5387 copy_and_next(dest_conv, tex_coord, GET_TEXCOORD_SIZE_FROM_FVF(DestFVF, tex_index) * sizeof(float));
5394 GL_EXTCALL(glUnmapBufferARB(GL_ARRAY_BUFFER_ARB));
5395 checkGLcall("glUnmapBufferARB(GL_ARRAY_BUFFER_ARB)");
5402 #undef copy_and_next
5404 static HRESULT WINAPI IWineD3DDeviceImpl_ProcessVertices(IWineD3DDevice *iface, UINT SrcStartIndex, UINT DestIndex, UINT VertexCount, IWineD3DVertexBuffer* pDestBuffer, IWineD3DVertexBuffer* pVertexDecl, DWORD Flags) {
5405 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5406 IWineD3DVertexBufferImpl *SrcImpl = (IWineD3DVertexBufferImpl *) pVertexDecl;
5407 WineDirect3DVertexStridedData strided;
5408 TRACE("(%p)->(%d,%d,%d,%p,%p,%ld\n", This, SrcStartIndex, DestIndex, VertexCount, pDestBuffer, pVertexDecl, Flags);
5411 WARN("NULL source vertex buffer\n");
5412 return WINED3DERR_INVALIDCALL;
5414 /* We don't need the source vbo because this buffer is only used as
5415 * a source for ProcessVertices. Avoid wasting resources by converting the
5416 * buffer and loading the VBO
5419 TRACE("Releaseing the source vbo, it won't be needed\n");
5421 if(!SrcImpl->resource.allocatedMemory) {
5422 /* Rescue the data from the buffer */
5424 SrcImpl->resource.allocatedMemory = HeapAlloc(GetProcessHeap(), 0, SrcImpl->resource.size);
5425 if(!SrcImpl->resource.allocatedMemory) {
5426 ERR("Out of memory\n");
5427 return E_OUTOFMEMORY;
5431 GL_EXTCALL(glBindBufferARB(GL_ARRAY_BUFFER_ARB, SrcImpl->vbo));
5432 checkGLcall("glBindBufferARB");
5434 src = GL_EXTCALL(glMapBufferARB(GL_ARRAY_BUFFER_ARB, GL_READ_ONLY_ARB));
5436 memcpy(SrcImpl->resource.allocatedMemory, src, SrcImpl->resource.size);
5439 GL_EXTCALL(glUnmapBufferARB(GL_ARRAY_BUFFER_ARB));
5440 checkGLcall("glUnmapBufferARB");
5445 GL_EXTCALL(glBindBufferARB(GL_ARRAY_BUFFER_ARB, 0));
5446 checkGLcall("glBindBufferARB");
5447 GL_EXTCALL(glDeleteBuffersARB(1, &SrcImpl->vbo));
5448 checkGLcall("glDeleteBuffersARB");
5454 memset(&strided, 0, sizeof(strided));
5455 primitiveConvertFVFtoOffset(SrcImpl->fvf, get_flexible_vertex_size(SrcImpl->fvf), SrcImpl->resource.allocatedMemory + get_flexible_vertex_size(SrcImpl->fvf) * SrcStartIndex, &strided, 0);
5457 return process_vertices_strided(This, DestIndex, VertexCount, &strided, SrcImpl->fvf, (IWineD3DVertexBufferImpl *) pDestBuffer, Flags);
5461 * Apply / Get / Set Texture Stage States
5462 * TODO: Verify against dx9 definitions
5465 /* 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 */
5466 static void WINAPI IWineD3DDeviceImpl_ApplyTextureUnitState(IWineD3DDevice *iface, DWORD Stage, WINED3DTEXTURESTAGESTATETYPE Type) {
5467 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5468 DWORD Value = This->updateStateBlock->textureState[Stage][Type];
5469 /* FIXME: Handle 3d textures? What if TSS value set before set texture? Need to reapply all values? */
5471 TRACE("(%p) : Stage=%ld, Type=%s(%d), Value=%ld\n", This, Stage, debug_d3dtexturestate(Type), Type, Value);
5473 /* Check that the stage is within limits */
5474 if (Stage >= GL_LIMITS(texture_stages) || Stage < 0) {
5475 TRACE("Attempt to access invalid texture rejected\n");
5482 case WINED3DTSS_ALPHAOP :
5483 case WINED3DTSS_COLOROP :
5484 /* nothing to do as moved to drawprim for now */
5486 case WINED3DTSS_ADDRESSW :
5487 #if 0 /* I'm not sure what D3D does about ADDRESSW appearing twice */
5488 if (Value < minLookup[WINELOOKUP_WARPPARAM] || Value > maxLookup[WINELOOKUP_WARPPARAM]) {
5489 FIXME("Unrecognized or unsupported D3DTADDRESS_* value %ld, state %d\n", Value, Type);
5492 GLint wrapParm = stateLookup[WINELOOKUP_WARPPARAM][Value - minLookup[WINELOOKUP_WARPPARAM]];
5493 TRACE("Setting WRAP_R to %d for %x\n", wrapParm, This->stateBlock->textureDimensions[Stage]);
5494 glTexParameteri(This->stateBlock->textureDimensions[Stage], GL_TEXTURE_WRAP_R, wrapParm);
5495 checkGLcall("glTexParameteri(..., GL_TEXTURE_WRAP_R, wrapParm)");
5498 case WINED3DTSS_TEXCOORDINDEX :
5500 /* Values 0-7 are indexes into the FVF tex coords - See comments in DrawPrimitive */
5502 /* FIXME: From MSDN: The WINED3DTSS_TCI_* flags are mutually exclusive. If you include
5503 one flag, you can still specify an index value, which the system uses to
5504 determine the texture wrapping mode.
5505 eg. SetTextureStageState( 0, D3DTSS_TEXCOORDINDEX, D3DTSS_TCI_CAMERASPACEPOSITION | 1 );
5506 means use the vertex position (camera-space) as the input texture coordinates
5507 for this texture stage, and the wrap mode set in the WINED3DRS_WRAP1 render
5508 state. We do not (yet) support the D3DRENDERSTATE_WRAPx values, nor tie them up
5509 to the TEXCOORDINDEX value */
5512 * Be careful the value of the mask 0xF0000 come from d3d8types.h infos
5514 switch (Value & 0xFFFF0000) {
5515 case D3DTSS_TCI_PASSTHRU:
5516 /*Use the specified texture coordinates contained within the vertex format. This value resolves to zero.*/
5517 glDisable(GL_TEXTURE_GEN_S);
5518 glDisable(GL_TEXTURE_GEN_T);
5519 glDisable(GL_TEXTURE_GEN_R);
5520 glDisable(GL_TEXTURE_GEN_Q);
5521 checkGLcall("glDisable(GL_TEXTURE_GEN_S,T,R,Q)");
5524 case D3DTSS_TCI_CAMERASPACEPOSITION:
5525 /* CameraSpacePosition means use the vertex position, transformed to camera space,
5526 as the input texture coordinates for this stage's texture transformation. This
5527 equates roughly to EYE_LINEAR */
5529 float s_plane[] = { 1.0, 0.0, 0.0, 0.0 };
5530 float t_plane[] = { 0.0, 1.0, 0.0, 0.0 };
5531 float r_plane[] = { 0.0, 0.0, 1.0, 0.0 };
5532 float q_plane[] = { 0.0, 0.0, 0.0, 1.0 };
5533 TRACE("WINED3DTSS_TCI_CAMERASPACEPOSITION - Set eye plane\n");
5535 glMatrixMode(GL_MODELVIEW);
5538 glTexGenfv(GL_S, GL_EYE_PLANE, s_plane);
5539 glTexGenfv(GL_T, GL_EYE_PLANE, t_plane);
5540 glTexGenfv(GL_R, GL_EYE_PLANE, r_plane);
5541 glTexGenfv(GL_Q, GL_EYE_PLANE, q_plane);
5544 TRACE("WINED3DTSS_TCI_CAMERASPACEPOSITION - Set GL_TEXTURE_GEN_x and GL_x, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR\n");
5545 glEnable(GL_TEXTURE_GEN_S);
5546 checkGLcall("glEnable(GL_TEXTURE_GEN_S);");
5547 glTexGeni(GL_S, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR);
5548 checkGLcall("glTexGeni(GL_S, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR)");
5549 glEnable(GL_TEXTURE_GEN_T);
5550 checkGLcall("glEnable(GL_TEXTURE_GEN_T);");
5551 glTexGeni(GL_T, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR);
5552 checkGLcall("glTexGeni(GL_T, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR)");
5553 glEnable(GL_TEXTURE_GEN_R);
5554 checkGLcall("glEnable(GL_TEXTURE_GEN_R);");
5555 glTexGeni(GL_R, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR);
5556 checkGLcall("glTexGeni(GL_R, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR)");
5560 case D3DTSS_TCI_CAMERASPACENORMAL:
5562 if (GL_SUPPORT(NV_TEXGEN_REFLECTION)) {
5563 float s_plane[] = { 1.0, 0.0, 0.0, 0.0 };
5564 float t_plane[] = { 0.0, 1.0, 0.0, 0.0 };
5565 float r_plane[] = { 0.0, 0.0, 1.0, 0.0 };
5566 float q_plane[] = { 0.0, 0.0, 0.0, 1.0 };
5567 TRACE("WINED3DTSS_TCI_CAMERASPACENORMAL - Set eye plane\n");
5569 glMatrixMode(GL_MODELVIEW);
5572 glTexGenfv(GL_S, GL_EYE_PLANE, s_plane);
5573 glTexGenfv(GL_T, GL_EYE_PLANE, t_plane);
5574 glTexGenfv(GL_R, GL_EYE_PLANE, r_plane);
5575 glTexGenfv(GL_Q, GL_EYE_PLANE, q_plane);
5578 glEnable(GL_TEXTURE_GEN_S);
5579 checkGLcall("glEnable(GL_TEXTURE_GEN_S);");
5580 glTexGeni(GL_S, GL_TEXTURE_GEN_MODE, GL_NORMAL_MAP_NV);
5581 checkGLcall("glTexGeni(GL_S, GL_TEXTURE_GEN_MODE, GL_NORMAL_MAP_NV)");
5582 glEnable(GL_TEXTURE_GEN_T);
5583 checkGLcall("glEnable(GL_TEXTURE_GEN_T);");
5584 glTexGeni(GL_T, GL_TEXTURE_GEN_MODE, GL_NORMAL_MAP_NV);
5585 checkGLcall("glTexGeni(GL_T, GL_TEXTURE_GEN_MODE, GL_NORMAL_MAP_NV)");
5586 glEnable(GL_TEXTURE_GEN_R);
5587 checkGLcall("glEnable(GL_TEXTURE_GEN_R);");
5588 glTexGeni(GL_R, GL_TEXTURE_GEN_MODE, GL_NORMAL_MAP_NV);
5589 checkGLcall("glTexGeni(GL_R, GL_TEXTURE_GEN_MODE, GL_NORMAL_MAP_NV)");
5594 case D3DTSS_TCI_CAMERASPACEREFLECTIONVECTOR:
5596 if (GL_SUPPORT(NV_TEXGEN_REFLECTION)) {
5597 float s_plane[] = { 1.0, 0.0, 0.0, 0.0 };
5598 float t_plane[] = { 0.0, 1.0, 0.0, 0.0 };
5599 float r_plane[] = { 0.0, 0.0, 1.0, 0.0 };
5600 float q_plane[] = { 0.0, 0.0, 0.0, 1.0 };
5601 TRACE("WINED3DTSS_TCI_CAMERASPACEREFLECTIONVECTOR - Set eye plane\n");
5603 glMatrixMode(GL_MODELVIEW);
5606 glTexGenfv(GL_S, GL_EYE_PLANE, s_plane);
5607 glTexGenfv(GL_T, GL_EYE_PLANE, t_plane);
5608 glTexGenfv(GL_R, GL_EYE_PLANE, r_plane);
5609 glTexGenfv(GL_Q, GL_EYE_PLANE, q_plane);
5612 glEnable(GL_TEXTURE_GEN_S);
5613 checkGLcall("glEnable(GL_TEXTURE_GEN_S);");
5614 glTexGeni(GL_S, GL_TEXTURE_GEN_MODE, GL_REFLECTION_MAP_NV);
5615 checkGLcall("glTexGeni(GL_S, GL_TEXTURE_GEN_MODE, GL_REFLECTION_MAP_NV)");
5616 glEnable(GL_TEXTURE_GEN_T);
5617 checkGLcall("glEnable(GL_TEXTURE_GEN_T);");
5618 glTexGeni(GL_T, GL_TEXTURE_GEN_MODE, GL_REFLECTION_MAP_NV);
5619 checkGLcall("glTexGeni(GL_T, GL_TEXTURE_GEN_MODE, GL_REFLECTION_MAP_NV)");
5620 glEnable(GL_TEXTURE_GEN_R);
5621 checkGLcall("glEnable(GL_TEXTURE_GEN_R);");
5622 glTexGeni(GL_R, GL_TEXTURE_GEN_MODE, GL_REFLECTION_MAP_NV);
5623 checkGLcall("glTexGeni(GL_R, GL_TEXTURE_GEN_MODE, GL_REFLECTION_MAP_NV)");
5628 /* Unhandled types: */
5631 /* ? disable GL_TEXTURE_GEN_n ? */
5632 glDisable(GL_TEXTURE_GEN_S);
5633 glDisable(GL_TEXTURE_GEN_T);
5634 glDisable(GL_TEXTURE_GEN_R);
5635 glDisable(GL_TEXTURE_GEN_Q);
5636 FIXME("Unhandled WINED3DTSS_TEXCOORDINDEX %lx\n", Value);
5643 case WINED3DTSS_TEXTURETRANSFORMFLAGS :
5644 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);
5647 case WINED3DTSS_BUMPENVMAT00 :
5648 case WINED3DTSS_BUMPENVMAT01 :
5649 TRACE("BUMPENVMAT0%u Stage=%ld, Type=%d, Value =%ld\n", Type - WINED3DTSS_BUMPENVMAT00, Stage, Type, Value);
5651 case WINED3DTSS_BUMPENVMAT10 :
5652 case WINED3DTSS_BUMPENVMAT11 :
5653 TRACE("BUMPENVMAT1%u Stage=%ld, Type=%d, Value =%ld\n", Type - WINED3DTSS_BUMPENVMAT10, Stage, Type, Value);
5656 case WINED3DTSS_BUMPENVLSCALE :
5657 TRACE("BUMPENVLSCALE Stage=%ld, Type=%d, Value =%ld\n", Stage, Type, Value);
5660 case WINED3DTSS_BUMPENVLOFFSET :
5661 TRACE("BUMPENVLOFFSET Stage=%ld, Type=%d, Value =%ld\n", Stage, Type, Value);
5664 case WINED3DTSS_RESULTARG :
5665 TRACE("RESULTARG Still a stub, Stage=%ld, Type=%d, Value =%ld\n", Stage, Type, Value);
5669 /* Put back later: FIXME("(%p) : stub, Stage=%ld, Type=%d, Value =%ld\n", This, Stage, Type, Value); */
5670 TRACE("Still a stub, Stage=%ld, Type=%d, Value =%ld\n", Stage, Type, Value);
5679 * Get / Set Texture Stage States
5680 * TODO: Verify against dx9 definitions
5682 static HRESULT WINAPI IWineD3DDeviceImpl_SetTextureStageState(IWineD3DDevice *iface, DWORD Stage, WINED3DTEXTURESTAGESTATETYPE Type, DWORD Value) {
5683 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5685 /* FIXME: Handle 3d textures? What if TSS value set before set texture? Need to reapply all values? */
5687 TRACE("(%p) : Stage=%ld, Type=%s(%d), Value=%ld\n", This, Stage, debug_d3dtexturestate(Type), Type, Value);
5689 /* Reject invalid texture units */
5690 if (Stage >= GL_LIMITS(texture_stages)) {
5691 TRACE("Attempt to access invalid texture rejected\n");
5692 return WINED3DERR_INVALIDCALL;
5695 This->updateStateBlock->changed.textureState[Stage][Type] = TRUE;
5696 This->updateStateBlock->set.textureState[Stage][Type] = TRUE;
5697 This->updateStateBlock->textureState[Stage][Type] = Value;
5702 static HRESULT WINAPI IWineD3DDeviceImpl_GetTextureStageState(IWineD3DDevice *iface, DWORD Stage, WINED3DTEXTURESTAGESTATETYPE Type, DWORD* pValue) {
5703 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5704 TRACE("(%p) : requesting Stage %ld, Type %d getting %ld\n", This, Stage, Type, This->updateStateBlock->textureState[Stage][Type]);
5705 *pValue = This->updateStateBlock->textureState[Stage][Type];
5712 static HRESULT WINAPI IWineD3DDeviceImpl_SetTexture(IWineD3DDevice *iface, DWORD Stage, IWineD3DBaseTexture* pTexture) {
5714 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5715 IWineD3DBaseTexture *oldTexture;
5717 oldTexture = This->updateStateBlock->textures[Stage];
5718 TRACE("(%p) : Stage(%ld), Texture (%p)\n", This, Stage, pTexture);
5720 #if 0 /* TODO: check so vertex textures */
5721 if (Stage >= D3DVERTEXTEXTURESAMPLER && Stage <= D3DVERTEXTEXTURESAMPLER3){
5722 This->updateStateBlock->vertexTextures[Stage - D3DVERTEXTEXTURESAMPLER] = pTexture;
5727 /* Reject invalid texture units */
5728 if (Stage >= GL_LIMITS(sampler_stages) || Stage < 0) {
5729 WARN("Attempt to access invalid texture rejected\n");
5730 return WINED3DERR_INVALIDCALL;
5733 if(pTexture != NULL) {
5734 /* SetTexture isn't allowed on textures in WINED3DPOOL_SCRATCH;
5736 if(((IWineD3DTextureImpl*)pTexture)->resource.pool == WINED3DPOOL_SCRATCH) {
5737 WARN("(%p) Attempt to set scratch texture rejected\n", pTexture);
5738 return WINED3DERR_INVALIDCALL;
5742 oldTexture = This->updateStateBlock->textures[Stage];
5743 TRACE("GL_LIMITS %d\n",GL_LIMITS(sampler_stages));
5744 TRACE("(%p) : oldtexture(%p)\n", This,oldTexture);
5746 This->updateStateBlock->set.textures[Stage] = TRUE;
5747 This->updateStateBlock->changed.textures[Stage] = TRUE;
5748 TRACE("(%p) : setting new texture to %p\n", This, pTexture);
5749 This->updateStateBlock->textures[Stage] = pTexture;
5751 /* Handle recording of state blocks */
5752 if (This->isRecordingState) {
5753 TRACE("Recording... not performing anything\n");
5757 /** NOTE: MSDN says that setTexture increases the reference count,
5758 * and the the application nust set the texture back to null (or have a leaky application),
5759 * This means we should pass the refcount up to the parent
5760 *******************************/
5761 if (NULL != This->updateStateBlock->textures[Stage]) {
5762 IWineD3DBaseTexture_AddRef(This->updateStateBlock->textures[Stage]);
5765 if (NULL != oldTexture) {
5766 IWineD3DBaseTexture_Release(oldTexture);
5769 /* Reset color keying */
5770 if(Stage == 0 && This->stateBlock->renderState[WINED3DRS_COLORKEYENABLE]) {
5771 BOOL enable_ckey = FALSE;
5774 IWineD3DSurfaceImpl *surf = (IWineD3DSurfaceImpl *) ((IWineD3DTextureImpl *)pTexture)->surfaces[0];
5775 if(surf->CKeyFlags & DDSD_CKSRCBLT) enable_ckey = TRUE;
5779 glAlphaFunc(GL_NOTEQUAL, 0.0);
5780 checkGLcall("glAlphaFunc");
5787 static HRESULT WINAPI IWineD3DDeviceImpl_GetTexture(IWineD3DDevice *iface, DWORD Stage, IWineD3DBaseTexture** ppTexture) {
5788 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5789 TRACE("(%p) : (%ld /* Stage */,%p /* ppTexture */)\n", This, Stage, ppTexture);
5791 /* Reject invalid texture units */
5792 if (Stage >= GL_LIMITS(sampler_stages)) {
5793 TRACE("Attempt to access invalid texture rejected\n");
5794 return WINED3DERR_INVALIDCALL;
5796 *ppTexture=This->updateStateBlock->textures[Stage];
5798 IWineD3DBaseTexture_AddRef(*ppTexture);
5800 return WINED3DERR_INVALIDCALL;
5807 static HRESULT WINAPI IWineD3DDeviceImpl_GetBackBuffer(IWineD3DDevice *iface, UINT iSwapChain, UINT BackBuffer, WINED3DBACKBUFFER_TYPE Type,
5808 IWineD3DSurface **ppBackBuffer) {
5809 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5810 IWineD3DSwapChain *swapChain;
5813 TRACE("(%p) : BackBuf %d Type %d SwapChain %d returning %p\n", This, BackBuffer, Type, iSwapChain, *ppBackBuffer);
5815 hr = IWineD3DDeviceImpl_GetSwapChain(iface, iSwapChain, &swapChain);
5816 if (hr == WINED3D_OK) {
5817 hr = IWineD3DSwapChain_GetBackBuffer(swapChain, BackBuffer, Type, ppBackBuffer);
5818 IWineD3DSwapChain_Release(swapChain);
5820 *ppBackBuffer = NULL;
5825 static HRESULT WINAPI IWineD3DDeviceImpl_GetDeviceCaps(IWineD3DDevice *iface, WINED3DCAPS* pCaps) {
5826 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5827 WARN("(%p) : stub, calling idirect3d for now\n", This);
5828 return IWineD3D_GetDeviceCaps(This->wineD3D, This->adapterNo, This->devType, pCaps);
5831 static HRESULT WINAPI IWineD3DDeviceImpl_GetDisplayMode(IWineD3DDevice *iface, UINT iSwapChain, WINED3DDISPLAYMODE* pMode) {
5832 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5833 IWineD3DSwapChain *swapChain;
5836 if(iSwapChain > 0) {
5837 hr = IWineD3DDeviceImpl_GetSwapChain(iface, iSwapChain, (IWineD3DSwapChain **)&swapChain);
5838 if (hr == WINED3D_OK) {
5839 hr = IWineD3DSwapChain_GetDisplayMode(swapChain, pMode);
5840 IWineD3DSwapChain_Release(swapChain);
5842 FIXME("(%p) Error getting display mode\n", This);
5845 /* Don't read the real display mode,
5846 but return the stored mode instead. X11 can't change the color
5847 depth, and some apps are pretty angry if they SetDisplayMode from
5848 24 to 16 bpp and find out that GetDisplayMode still returns 24 bpp
5850 Also don't relay to the swapchain because with ddraw it's possible
5851 that there isn't a swapchain at all */
5852 pMode->Width = This->ddraw_width;
5853 pMode->Height = This->ddraw_height;
5854 pMode->Format = This->ddraw_format;
5855 pMode->RefreshRate = 0;
5862 static HRESULT WINAPI IWineD3DDeviceImpl_SetHWND(IWineD3DDevice *iface, HWND hWnd) {
5863 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5864 TRACE("(%p)->(%p)\n", This, hWnd);
5866 This->ddraw_window = hWnd;
5870 static HRESULT WINAPI IWineD3DDeviceImpl_GetHWND(IWineD3DDevice *iface, HWND *hWnd) {
5871 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5872 TRACE("(%p)->(%p)\n", This, hWnd);
5874 *hWnd = This->ddraw_window;
5879 * Stateblock related functions
5882 static HRESULT WINAPI IWineD3DDeviceImpl_BeginStateBlock(IWineD3DDevice *iface) {
5883 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5884 IWineD3DStateBlockImpl *object;
5885 HRESULT temp_result;
5887 TRACE("(%p)", This);
5889 if (This->isRecordingState) {
5890 return WINED3DERR_INVALIDCALL;
5893 object = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(IWineD3DStateBlockImpl));
5894 if (NULL == object ) {
5895 FIXME("(%p)Error allocating memory for stateblock\n", This);
5896 return E_OUTOFMEMORY;
5898 TRACE("(%p) created object %p\n", This, object);
5899 object->wineD3DDevice= This;
5900 /** FIXME: object->parent = parent; **/
5901 object->parent = NULL;
5902 object->blockType = WINED3DSBT_ALL;
5904 object->lpVtbl = &IWineD3DStateBlock_Vtbl;
5906 temp_result = allocate_shader_constants(object);
5907 if (WINED3D_OK != temp_result)
5910 IWineD3DStateBlock_Release((IWineD3DStateBlock*)This->updateStateBlock);
5911 This->updateStateBlock = object;
5912 This->isRecordingState = TRUE;
5914 TRACE("(%p) recording stateblock %p\n",This , object);
5918 static HRESULT WINAPI IWineD3DDeviceImpl_EndStateBlock(IWineD3DDevice *iface, IWineD3DStateBlock** ppStateBlock) {
5919 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5921 if (!This->isRecordingState) {
5922 FIXME("(%p) not recording! returning error\n", This);
5923 *ppStateBlock = NULL;
5924 return WINED3DERR_INVALIDCALL;
5927 *ppStateBlock = (IWineD3DStateBlock*)This->updateStateBlock;
5928 This->isRecordingState = FALSE;
5929 This->updateStateBlock = This->stateBlock;
5930 IWineD3DStateBlock_AddRef((IWineD3DStateBlock*)This->updateStateBlock);
5931 /* IWineD3DStateBlock_AddRef(*ppStateBlock); don't need to do this, since we should really just release UpdateStateBlock first */
5932 TRACE("(%p) returning token (ptr to stateblock) of %p\n", This, *ppStateBlock);
5937 * Scene related functions
5939 static HRESULT WINAPI IWineD3DDeviceImpl_BeginScene(IWineD3DDevice *iface) {
5940 /* At the moment we have no need for any functionality at the beginning
5942 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5943 TRACE("(%p) : stub\n", This);
5947 static HRESULT WINAPI IWineD3DDeviceImpl_EndScene(IWineD3DDevice *iface) {
5948 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5949 TRACE("(%p)\n", This);
5951 /* We only have to do this if we need to read the, swapbuffers performs a flush for us */
5953 checkGLcall("glFlush");
5955 TRACE("End Scene\n");
5956 if(This->renderTarget != NULL) {
5958 /* If the container of the rendertarget is a texture then we need to save the data from the pbuffer */
5959 IUnknown *targetContainer = NULL;
5960 if (WINED3D_OK == IWineD3DSurface_GetContainer(This->renderTarget, &IID_IWineD3DBaseTexture, (void **)&targetContainer)
5961 || WINED3D_OK == IWineD3DSurface_GetContainer(This->renderTarget, &IID_IWineD3DDevice, (void **)&targetContainer)) {
5962 TRACE("(%p) : Texture rendertarget %p\n", This ,This->renderTarget);
5963 /** always dirtify for now. we must find a better way to see that surface have been modified
5964 (Modifications should will only occur via draw-primitive, but we do need better locking
5965 switching to render-to-texture should remove the overhead though.
5967 IWineD3DSurface_SetPBufferState(This->renderTarget, TRUE /* inPBuffer */, FALSE /* inTexture */);
5968 IWineD3DSurface_AddDirtyRect(This->renderTarget, NULL);
5969 IWineD3DSurface_PreLoad(This->renderTarget);
5970 IWineD3DSurface_SetPBufferState(This->renderTarget, FALSE /* inPBuffer */, FALSE /* inTexture */);
5971 IUnknown_Release(targetContainer);
5974 This->sceneEnded = TRUE;
5979 static HRESULT WINAPI IWineD3DDeviceImpl_Present(IWineD3DDevice *iface,
5980 CONST RECT* pSourceRect, CONST RECT* pDestRect,
5981 HWND hDestWindowOverride, CONST RGNDATA* pDirtyRegion) {
5982 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5983 IWineD3DSwapChain *swapChain = NULL;
5985 int swapchains = IWineD3DDeviceImpl_GetNumberOfSwapChains(iface);
5987 TRACE("(%p) Presenting the frame\n", This);
5989 for(i = 0 ; i < swapchains ; i ++) {
5991 IWineD3DDeviceImpl_GetSwapChain(iface, i , (IWineD3DSwapChain **)&swapChain);
5992 TRACE("presentinng chain %d, %p\n", i, swapChain);
5993 IWineD3DSwapChain_Present(swapChain, pSourceRect, pDestRect, hDestWindowOverride, pDirtyRegion, 0);
5994 IWineD3DSwapChain_Release(swapChain);
6000 static HRESULT WINAPI IWineD3DDeviceImpl_Clear(IWineD3DDevice *iface, DWORD Count, CONST D3DRECT* pRects,
6001 DWORD Flags, D3DCOLOR Color, float Z, DWORD Stencil) {
6002 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
6004 /* TODO: From MSDN This method fails if you specify the D3DCLEAR_ZBUFFER or D3DCLEAR_STENCIL flags when the
6005 render target does not have an attached depth buffer. Similarly, if you specify the D3DCLEAR_STENCIL flag
6006 when the depth-buffer format does not contain stencil buffer information, this method fails. */
6007 GLbitfield glMask = 0;
6008 GLboolean old_ztest;
6009 GLfloat old_z_clear_value;
6010 GLint old_stencil_clear_value;
6011 GLfloat old_color_clear_value[4];
6013 CONST D3DRECT* curRect;
6015 TRACE("(%p) Count (%ld), pRects (%p), Flags (%lx), Z (%f), Stencil (%ld)\n", This,
6016 Count, pRects, Flags, Z, Stencil);
6020 glEnable(GL_SCISSOR_TEST);
6021 checkGLcall("glEnable GL_SCISSOR_TEST");
6023 if (Count > 0 && pRects) {
6029 /* Only set the values up once, as they are not changing */
6030 if (Flags & D3DCLEAR_STENCIL) {
6031 glGetIntegerv(GL_STENCIL_CLEAR_VALUE, &old_stencil_clear_value);
6032 glClearStencil(Stencil);
6033 checkGLcall("glClearStencil");
6034 glMask = glMask | GL_STENCIL_BUFFER_BIT;
6035 glStencilMask(0xFFFFFFFF);
6038 if (Flags & D3DCLEAR_ZBUFFER) {
6039 glGetBooleanv(GL_DEPTH_WRITEMASK, &old_ztest);
6040 glDepthMask(GL_TRUE);
6041 glGetFloatv(GL_DEPTH_CLEAR_VALUE, &old_z_clear_value);
6043 checkGLcall("glClearDepth");
6044 glMask = glMask | GL_DEPTH_BUFFER_BIT;
6047 if (Flags & D3DCLEAR_TARGET) {
6048 TRACE("Clearing screen with glClear to color %lx\n", Color);
6049 glGetFloatv(GL_COLOR_CLEAR_VALUE, old_color_clear_value);
6050 glClearColor(D3DCOLOR_R(Color),
6054 checkGLcall("glClearColor");
6056 /* Clear ALL colors! */
6057 glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
6058 glMask = glMask | GL_COLOR_BUFFER_BIT;
6061 /* Now process each rect in turn */
6062 for (i = 0; i < Count || i == 0; i++) {
6065 /* Note gl uses lower left, width/height */
6066 TRACE("(%p) %p Rect=(%ld,%ld)->(%ld,%ld) glRect=(%ld,%ld), len=%ld, hei=%ld\n", This, curRect,
6067 curRect->x1, curRect->y1, curRect->x2, curRect->y2,
6068 curRect->x1, (((IWineD3DSurfaceImpl *)This->renderTarget)->currentDesc.Height - curRect->y2),
6069 curRect->x2 - curRect->x1, curRect->y2 - curRect->y1);
6070 glScissor(curRect->x1, (((IWineD3DSurfaceImpl *)This->renderTarget)->currentDesc.Height - curRect->y2),
6071 curRect->x2 - curRect->x1, curRect->y2 - curRect->y1);
6072 checkGLcall("glScissor");
6074 glScissor(This->stateBlock->viewport.X,
6075 (((IWineD3DSurfaceImpl *)This->renderTarget)->currentDesc.Height -
6076 (This->stateBlock->viewport.Y + This->stateBlock->viewport.Height)),
6077 This->stateBlock->viewport.Width,
6078 This->stateBlock->viewport.Height);
6079 checkGLcall("glScissor");
6082 /* Clear the selected rectangle (or full screen) */
6084 checkGLcall("glClear");
6086 /* Step to the next rectangle */
6087 if (curRect) curRect = curRect + sizeof(D3DRECT);
6090 /* Restore the old values (why..?) */
6091 if (Flags & D3DCLEAR_STENCIL) {
6092 glClearStencil(old_stencil_clear_value);
6093 glStencilMask(This->stateBlock->renderState[WINED3DRS_STENCILWRITEMASK]);
6095 if (Flags & D3DCLEAR_ZBUFFER) {
6096 glDepthMask(old_ztest);
6097 glClearDepth(old_z_clear_value);
6099 if (Flags & D3DCLEAR_TARGET) {
6100 glClearColor(old_color_clear_value[0],
6101 old_color_clear_value[1],
6102 old_color_clear_value[2],
6103 old_color_clear_value[3]);
6104 glColorMask(This->stateBlock->renderState[WINED3DRS_COLORWRITEENABLE] & D3DCOLORWRITEENABLE_RED ? GL_TRUE : GL_FALSE,
6105 This->stateBlock->renderState[WINED3DRS_COLORWRITEENABLE] & D3DCOLORWRITEENABLE_GREEN ? GL_TRUE : GL_FALSE,
6106 This->stateBlock->renderState[WINED3DRS_COLORWRITEENABLE] & D3DCOLORWRITEENABLE_BLUE ? GL_TRUE : GL_FALSE,
6107 This->stateBlock->renderState[WINED3DRS_COLORWRITEENABLE] & D3DCOLORWRITEENABLE_ALPHA ? GL_TRUE : GL_FALSE);
6110 glDisable(GL_SCISSOR_TEST);
6111 checkGLcall("glDisable");
6120 static HRESULT WINAPI IWineD3DDeviceImpl_DrawPrimitive(IWineD3DDevice *iface, D3DPRIMITIVETYPE PrimitiveType, UINT StartVertex,
6121 UINT PrimitiveCount) {
6123 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
6124 This->stateBlock->streamIsUP = FALSE;
6126 TRACE("(%p) : Type=(%d,%s), Start=%d, Count=%d\n", This, PrimitiveType,
6127 debug_d3dprimitivetype(PrimitiveType),
6128 StartVertex, PrimitiveCount);
6129 drawPrimitive(iface, PrimitiveType, PrimitiveCount, StartVertex, 0/* NumVertices */, -1 /* indxStart */,
6130 0 /* indxSize */, NULL /* indxData */, 0 /* minIndex */, NULL);
6136 /* TODO: baseVIndex needs to be provided from This->stateBlock->baseVertexIndex when called from d3d8 */
6137 static HRESULT WINAPI IWineD3DDeviceImpl_DrawIndexedPrimitive(IWineD3DDevice *iface,
6138 D3DPRIMITIVETYPE PrimitiveType,
6139 INT baseVIndex, UINT minIndex,
6140 UINT NumVertices, UINT startIndex, UINT primCount) {
6142 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
6144 IWineD3DIndexBuffer *pIB;
6145 WINED3DINDEXBUFFER_DESC IdxBufDsc;
6147 pIB = This->stateBlock->pIndexData;
6148 This->stateBlock->streamIsUP = FALSE;
6150 TRACE("(%p) : Type=(%d,%s), min=%d, CountV=%d, startIdx=%d, baseVidx=%d, countP=%d\n", This,
6151 PrimitiveType, debug_d3dprimitivetype(PrimitiveType),
6152 minIndex, NumVertices, startIndex, baseVIndex, primCount);
6154 IWineD3DIndexBuffer_GetDesc(pIB, &IdxBufDsc);
6155 if (IdxBufDsc.Format == WINED3DFMT_INDEX16) {
6161 drawPrimitive(iface, PrimitiveType, primCount, baseVIndex, NumVertices, startIndex,
6162 idxStride, ((IWineD3DIndexBufferImpl *) pIB)->resource.allocatedMemory, minIndex, NULL);
6167 static HRESULT WINAPI IWineD3DDeviceImpl_DrawPrimitiveUP(IWineD3DDevice *iface, D3DPRIMITIVETYPE PrimitiveType,
6168 UINT PrimitiveCount, CONST void* pVertexStreamZeroData,
6169 UINT VertexStreamZeroStride) {
6170 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
6172 TRACE("(%p) : Type=(%d,%s), pCount=%d, pVtxData=%p, Stride=%d\n", This, PrimitiveType,
6173 debug_d3dprimitivetype(PrimitiveType),
6174 PrimitiveCount, pVertexStreamZeroData, VertexStreamZeroStride);
6176 /* release the stream source */
6177 if (This->stateBlock->streamSource[0] != NULL) {
6178 IWineD3DVertexBuffer_Release(This->stateBlock->streamSource[0]);
6181 /* Note in the following, it's not this type, but that's the purpose of streamIsUP */
6182 This->stateBlock->streamSource[0] = (IWineD3DVertexBuffer *)pVertexStreamZeroData;
6183 This->stateBlock->streamStride[0] = VertexStreamZeroStride;
6184 This->stateBlock->streamIsUP = TRUE;
6186 drawPrimitive(iface, PrimitiveType, PrimitiveCount, 0 /* start vertex */, 0 /* NumVertices */,
6187 0 /* indxStart*/, 0 /* indxSize*/, NULL /* indxData */, 0 /* indxMin */, NULL);
6189 /* MSDN specifies stream zero settings must be set to NULL */
6190 This->stateBlock->streamStride[0] = 0;
6191 This->stateBlock->streamSource[0] = NULL;
6193 /*stream zero settings set to null at end, as per the msdn */
6197 static HRESULT WINAPI IWineD3DDeviceImpl_DrawIndexedPrimitiveUP(IWineD3DDevice *iface, D3DPRIMITIVETYPE PrimitiveType,
6198 UINT MinVertexIndex, UINT NumVertices,
6199 UINT PrimitiveCount, CONST void* pIndexData,
6200 WINED3DFORMAT IndexDataFormat,CONST void* pVertexStreamZeroData,
6201 UINT VertexStreamZeroStride) {
6203 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
6205 TRACE("(%p) : Type=(%d,%s), MinVtxIdx=%d, NumVIdx=%d, PCount=%d, pidxdata=%p, IdxFmt=%d, pVtxdata=%p, stride=%d\n",
6206 This, PrimitiveType, debug_d3dprimitivetype(PrimitiveType),
6207 MinVertexIndex, NumVertices, PrimitiveCount, pIndexData,
6208 IndexDataFormat, pVertexStreamZeroData, VertexStreamZeroStride);
6210 if (IndexDataFormat == WINED3DFMT_INDEX16) {
6216 /* release the stream and index data */
6217 if (This->stateBlock->streamSource[0] != NULL) {
6218 IWineD3DVertexBuffer_Release(This->stateBlock->streamSource[0]);
6220 if (This->stateBlock->pIndexData) {
6221 IWineD3DIndexBuffer_Release(This->stateBlock->pIndexData);
6224 /* Note in the following, it's not this type, but that's the purpose of streamIsUP */
6225 This->stateBlock->streamSource[0] = (IWineD3DVertexBuffer *)pVertexStreamZeroData;
6226 This->stateBlock->streamIsUP = TRUE;
6227 This->stateBlock->streamStride[0] = VertexStreamZeroStride;
6229 drawPrimitive(iface, PrimitiveType, PrimitiveCount, 0 /* vertexStart */, NumVertices, 0 /* indxStart */, idxStride, pIndexData, MinVertexIndex, NULL);
6231 /* MSDN specifies stream zero settings and index buffer must be set to NULL */
6232 This->stateBlock->streamSource[0] = NULL;
6233 This->stateBlock->streamStride[0] = 0;
6234 This->stateBlock->pIndexData = NULL;
6239 static HRESULT WINAPI IWineD3DDeviceImpl_DrawPrimitiveStrided (IWineD3DDevice *iface, D3DPRIMITIVETYPE PrimitiveType, UINT PrimitiveCount, WineDirect3DVertexStridedData *DrawPrimStrideData) {
6241 drawPrimitive(iface, PrimitiveType, PrimitiveCount, 0, 0, 0, 0, NULL, 0, DrawPrimStrideData);
6244 /* Yet another way to update a texture, some apps use this to load default textures instead of using surface/texture lock/unlock */
6245 static HRESULT WINAPI IWineD3DDeviceImpl_UpdateTexture (IWineD3DDevice *iface, IWineD3DBaseTexture *pSourceTexture, IWineD3DBaseTexture *pDestinationTexture){
6246 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
6247 HRESULT hr = WINED3D_OK;
6248 WINED3DRESOURCETYPE sourceType;
6249 WINED3DRESOURCETYPE destinationType;
6252 /* TODO: think about moving the code into IWineD3DBaseTexture */
6254 TRACE("(%p) Source %p Destination %p\n", This, pSourceTexture, pDestinationTexture);
6256 /* verify that the source and destination textures aren't NULL */
6257 if (NULL == pSourceTexture || NULL == pDestinationTexture) {
6258 WARN("(%p) : source (%p) and destination (%p) textures must not be NULL, returning WINED3DERR_INVALIDCALL\n",
6259 This, pSourceTexture, pDestinationTexture);
6260 hr = WINED3DERR_INVALIDCALL;
6263 if (pSourceTexture == pDestinationTexture) {
6264 WARN("(%p) : source (%p) and destination (%p) textures must be different, returning WINED3DERR_INVALIDCALL\n",
6265 This, pSourceTexture, pDestinationTexture);
6266 hr = WINED3DERR_INVALIDCALL;
6268 /* Verify that the source and destination textures are the same type */
6269 sourceType = IWineD3DBaseTexture_GetType(pSourceTexture);
6270 destinationType = IWineD3DBaseTexture_GetType(pDestinationTexture);
6272 if (sourceType != destinationType) {
6273 WARN("(%p) Sorce and destination types must match, returning WINED3DERR_INVALIDCALL\n",
6275 hr = WINED3DERR_INVALIDCALL;
6278 /* check that both textures have the identical numbers of levels */
6279 if (IWineD3DBaseTexture_GetLevelCount(pDestinationTexture) != IWineD3DBaseTexture_GetLevelCount(pSourceTexture)) {
6280 WARN("(%p) : source (%p) and destination (%p) textures must have identicle numbers of levels, returning WINED3DERR_INVALIDCALL\n", This, pSourceTexture, pDestinationTexture);
6281 hr = WINED3DERR_INVALIDCALL;
6284 if (WINED3D_OK == hr) {
6286 /* Make sure that the destination texture is loaded */
6287 IWineD3DBaseTexture_PreLoad(pDestinationTexture);
6289 /* Update every surface level of the texture */
6290 levels = IWineD3DBaseTexture_GetLevelCount(pDestinationTexture);
6292 switch (sourceType) {
6293 case WINED3DRTYPE_TEXTURE:
6295 IWineD3DSurface *srcSurface;
6296 IWineD3DSurface *destSurface;
6298 for (i = 0 ; i < levels ; ++i) {
6299 IWineD3DTexture_GetSurfaceLevel((IWineD3DTexture *)pSourceTexture, i, &srcSurface);
6300 IWineD3DTexture_GetSurfaceLevel((IWineD3DTexture *)pDestinationTexture, i, &destSurface);
6301 hr = IWineD3DDevice_UpdateSurface(iface, srcSurface, NULL, destSurface, NULL);
6302 IWineD3DSurface_Release(srcSurface);
6303 IWineD3DSurface_Release(destSurface);
6304 if (WINED3D_OK != hr) {
6305 WARN("(%p) : Call to update surface failed\n", This);
6311 case WINED3DRTYPE_CUBETEXTURE:
6313 IWineD3DSurface *srcSurface;
6314 IWineD3DSurface *destSurface;
6315 WINED3DCUBEMAP_FACES faceType;
6317 for (i = 0 ; i < levels ; ++i) {
6318 /* Update each cube face */
6319 for (faceType = D3DCUBEMAP_FACE_POSITIVE_X; faceType <= D3DCUBEMAP_FACE_NEGATIVE_Z; ++faceType){
6320 hr = IWineD3DCubeTexture_GetCubeMapSurface((IWineD3DCubeTexture *)pSourceTexture, faceType, i, &srcSurface);
6321 if (WINED3D_OK != hr) {
6322 FIXME("(%p) : Failed to get src cube surface facetype %d, level %d\n", This, faceType, i);
6324 TRACE("Got srcSurface %p\n", srcSurface);
6326 hr = IWineD3DCubeTexture_GetCubeMapSurface((IWineD3DCubeTexture *)pDestinationTexture, faceType, i, &destSurface);
6327 if (WINED3D_OK != hr) {
6328 FIXME("(%p) : Failed to get src cube surface facetype %d, level %d\n", This, faceType, i);
6330 TRACE("Got desrSurface %p\n", destSurface);
6332 hr = IWineD3DDevice_UpdateSurface(iface, srcSurface, NULL, destSurface, NULL);
6333 IWineD3DSurface_Release(srcSurface);
6334 IWineD3DSurface_Release(destSurface);
6335 if (WINED3D_OK != hr) {
6336 WARN("(%p) : Call to update surface failed\n", This);
6343 #if 0 /* TODO: Add support for volume textures */
6344 case WINED3DRTYPE_VOLUMETEXTURE:
6346 IWineD3DVolume srcVolume = NULL;
6347 IWineD3DSurface destVolume = NULL;
6349 for (i = 0 ; i < levels ; ++i) {
6350 IWineD3DVolumeTexture_GetVolume((IWineD3DVolumeTexture *)pSourceTexture, i, &srcVolume);
6351 IWineD3DVolumeTexture_GetVolume((IWineD3DVolumeTexture *)pDestinationTexture, i, &destVolume);
6352 hr = IWineD3DFoo_UpdateVolume(iface, srcVolume, NULL, destVolume, NULL);
6353 IWineD3DVolume_Release(srcSurface);
6354 IWineD3DVolume_Release(destSurface);
6355 if (WINED3D_OK != hr) {
6356 WARN("(%p) : Call to update volume failed\n", This);
6364 FIXME("(%p) : Unsupported source and destination type\n", This);
6365 hr = WINED3DERR_INVALIDCALL;
6372 static HRESULT WINAPI IWineD3DDeviceImpl_StretchRect(IWineD3DDevice *iface, IWineD3DSurface *pSourceSurface,
6373 CONST RECT* pSourceRect, IWineD3DSurface *pDestinationSurface,
6374 CONST RECT* pDestRect, WINED3DTEXTUREFILTERTYPE Filter) {
6375 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
6377 TRACE("(%p) : stub\n", This);
6380 static HRESULT WINAPI IWineD3DDeviceImpl_GetRenderTargetData(IWineD3DDevice *iface, IWineD3DSurface *pRenderTarget, IWineD3DSurface *pSurface) {
6381 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
6382 /** TODO: remove remove casts to IWineD3DSurfaceImpl *
6383 * NOTE It may be best to move the code into surface to occomplish this
6384 ****************************************/
6386 WINED3DSURFACE_DESC surfaceDesc;
6387 unsigned int surfaceWidth, surfaceHeight;
6388 glDescriptor *targetGlDescription = NULL;
6389 glDescriptor *surfaceGlDescription = NULL;
6390 IWineD3DSwapChainImpl *container = NULL;
6392 IWineD3DSurface_GetGlDesc(pRenderTarget, &targetGlDescription);
6393 IWineD3DSurface_GetGlDesc(pSurface, &surfaceGlDescription);
6394 memset(&surfaceDesc, 0, sizeof(surfaceDesc));
6396 surfaceDesc.Width = &surfaceWidth;
6397 surfaceDesc.Height = &surfaceHeight;
6398 IWineD3DSurface_GetDesc(pSurface, &surfaceDesc);
6399 /* check to see if it's the backbuffer or the frontbuffer being requested (to make sure the data is up to date)*/
6401 /* Ok, I may need to setup some kind of active swapchain reference on the device */
6402 IWineD3DSurface_GetContainer(pRenderTarget, &IID_IWineD3DSwapChain, (void **)&container);
6404 /* TODO: opengl Context switching for swapchains etc... */
6405 if (NULL != container || pRenderTarget == This->renderTarget || pRenderTarget == This->depthStencilBuffer) {
6406 if (NULL != container && (pRenderTarget == container->backBuffer[0])) {
6407 glReadBuffer(GL_BACK);
6408 vcheckGLcall("glReadBuffer(GL_BACK)");
6409 } else if ((NULL != container && (pRenderTarget == container->frontBuffer)) || (pRenderTarget == This->renderTarget)) {
6410 glReadBuffer(GL_FRONT);
6411 vcheckGLcall("glReadBuffer(GL_FRONT)");
6412 } else if (pRenderTarget == This->depthStencilBuffer) {
6413 FIXME("Reading of depthstencil not yet supported\n");
6416 glReadPixels(surfaceGlDescription->target,
6417 surfaceGlDescription->level,
6420 surfaceGlDescription->glFormat,
6421 surfaceGlDescription->glType,
6422 (void *)IWineD3DSurface_GetData(pSurface));
6423 vcheckGLcall("glReadPixels(...)");
6424 if(NULL != container ){
6425 IWineD3DSwapChain_Release((IWineD3DSwapChain*) container);
6428 IWineD3DBaseTexture *container;
6429 GLenum textureDimensions = GL_TEXTURE_2D;
6431 if (WINED3D_OK == IWineD3DSurface_GetContainer(pSurface, &IID_IWineD3DBaseTexture, (void **)&container)) {
6432 textureDimensions = IWineD3DBaseTexture_GetTextureDimensions(container);
6433 IWineD3DBaseTexture_Release(container);
6435 /* TODO: 2D -> Cube surface coppies etc.. */
6436 if (surfaceGlDescription->target != textureDimensions) {
6437 FIXME("(%p) : Texture dimension mismatch\n", This);
6439 glEnable(textureDimensions);
6440 vcheckGLcall("glEnable(GL_TEXTURE_...)");
6441 /* FIXME: this isn't correct, it need to add a dirty rect if nothing else... */
6442 glBindTexture(targetGlDescription->target, targetGlDescription->textureName);
6443 vcheckGLcall("glBindTexture");
6444 glGetTexImage(surfaceGlDescription->target,
6445 surfaceGlDescription->level,
6446 surfaceGlDescription->glFormat,
6447 surfaceGlDescription->glType,
6448 (void *)IWineD3DSurface_GetData(pSurface));
6449 glDisable(textureDimensions);
6450 vcheckGLcall("glDisable(GL_TEXTURE_...)");
6457 static HRESULT WINAPI IWineD3DDeviceImpl_GetFrontBufferData(IWineD3DDevice *iface,UINT iSwapChain, IWineD3DSurface *pDestSurface) {
6458 IWineD3DSwapChain *swapChain;
6460 hr = IWineD3DDeviceImpl_GetSwapChain(iface, iSwapChain, (IWineD3DSwapChain **)&swapChain);
6461 if(hr == WINED3D_OK) {
6462 hr = IWineD3DSwapChain_GetFrontBufferData(swapChain, pDestSurface);
6463 IWineD3DSwapChain_Release(swapChain);
6468 static HRESULT WINAPI IWineD3DDeviceImpl_ValidateDevice(IWineD3DDevice *iface, DWORD* pNumPasses) {
6469 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
6470 /* return a sensible default */
6472 /* TODO: If the window is minimized then validate device should return something other than WINED3D_OK */
6473 FIXME("(%p) : stub\n", This);
6477 static HRESULT WINAPI IWineD3DDeviceImpl_SetPaletteEntries(IWineD3DDevice *iface, UINT PaletteNumber, CONST PALETTEENTRY* pEntries) {
6478 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
6480 TRACE("(%p) : PaletteNumber %u\n", This, PaletteNumber);
6481 if ( PaletteNumber < 0 || PaletteNumber >= MAX_PALETTES) {
6482 WARN("(%p) : (%u) Out of range 0-%u, returning Invalid Call\n", This, PaletteNumber, MAX_PALETTES);
6483 return WINED3DERR_INVALIDCALL;
6485 for (j = 0; j < 256; ++j) {
6486 This->palettes[PaletteNumber][j].peRed = pEntries[j].peRed;
6487 This->palettes[PaletteNumber][j].peGreen = pEntries[j].peGreen;
6488 This->palettes[PaletteNumber][j].peBlue = pEntries[j].peBlue;
6489 This->palettes[PaletteNumber][j].peFlags = pEntries[j].peFlags;
6491 TRACE("(%p) : returning\n", This);
6495 static HRESULT WINAPI IWineD3DDeviceImpl_GetPaletteEntries(IWineD3DDevice *iface, UINT PaletteNumber, PALETTEENTRY* pEntries) {
6496 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
6498 TRACE("(%p) : PaletteNumber %u\n", This, PaletteNumber);
6499 if ( PaletteNumber < 0 || PaletteNumber >= MAX_PALETTES) {
6500 WARN("(%p) : (%u) Out of range 0-%u, returning Invalid Call\n", This, PaletteNumber, MAX_PALETTES);
6501 return WINED3DERR_INVALIDCALL;
6503 for (j = 0; j < 256; ++j) {
6504 pEntries[j].peRed = This->palettes[PaletteNumber][j].peRed;
6505 pEntries[j].peGreen = This->palettes[PaletteNumber][j].peGreen;
6506 pEntries[j].peBlue = This->palettes[PaletteNumber][j].peBlue;
6507 pEntries[j].peFlags = This->palettes[PaletteNumber][j].peFlags;
6509 TRACE("(%p) : returning\n", This);
6513 static HRESULT WINAPI IWineD3DDeviceImpl_SetCurrentTexturePalette(IWineD3DDevice *iface, UINT PaletteNumber) {
6514 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
6515 TRACE("(%p) : PaletteNumber %u\n", This, PaletteNumber);
6516 if ( PaletteNumber < 0 || PaletteNumber >= MAX_PALETTES) {
6517 WARN("(%p) : (%u) Out of range 0-%u, returning Invalid Call\n", This, PaletteNumber, MAX_PALETTES);
6518 return WINED3DERR_INVALIDCALL;
6520 /*TODO: stateblocks */
6521 This->currentPalette = PaletteNumber;
6522 TRACE("(%p) : returning\n", This);
6526 static HRESULT WINAPI IWineD3DDeviceImpl_GetCurrentTexturePalette(IWineD3DDevice *iface, UINT* PaletteNumber) {
6527 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
6528 if (PaletteNumber == NULL) {
6529 WARN("(%p) : returning Invalid Call\n", This);
6530 return WINED3DERR_INVALIDCALL;
6532 /*TODO: stateblocks */
6533 *PaletteNumber = This->currentPalette;
6534 TRACE("(%p) : returning %u\n", This, *PaletteNumber);
6538 static HRESULT WINAPI IWineD3DDeviceImpl_SetSoftwareVertexProcessing(IWineD3DDevice *iface, BOOL bSoftware) {
6539 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
6540 static BOOL showFixmes = TRUE;
6542 FIXME("(%p) : stub\n", This);
6546 This->softwareVertexProcessing = bSoftware;
6551 static BOOL WINAPI IWineD3DDeviceImpl_GetSoftwareVertexProcessing(IWineD3DDevice *iface) {
6552 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
6553 static BOOL showFixmes = TRUE;
6555 FIXME("(%p) : stub\n", This);
6558 return This->softwareVertexProcessing;
6562 static HRESULT WINAPI IWineD3DDeviceImpl_GetRasterStatus(IWineD3DDevice *iface, UINT iSwapChain, WINED3DRASTER_STATUS* pRasterStatus) {
6563 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
6564 IWineD3DSwapChain *swapChain;
6567 TRACE("(%p) : SwapChain %d returning %p\n", This, iSwapChain, pRasterStatus);
6569 hr = IWineD3DDeviceImpl_GetSwapChain(iface, iSwapChain, (IWineD3DSwapChain **)&swapChain);
6570 if(hr == WINED3D_OK){
6571 hr = IWineD3DSwapChain_GetRasterStatus(swapChain, pRasterStatus);
6572 IWineD3DSwapChain_Release(swapChain);
6574 FIXME("(%p) IWineD3DSwapChain_GetRasterStatus returned in error\n", This);
6580 static HRESULT WINAPI IWineD3DDeviceImpl_SetNPatchMode(IWineD3DDevice *iface, float nSegments) {
6581 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
6582 static BOOL showfixmes = TRUE;
6583 if(nSegments != 0.0f) {
6585 FIXME("(%p) : stub nSegments(%f)\n", This, nSegments);
6592 static float WINAPI IWineD3DDeviceImpl_GetNPatchMode(IWineD3DDevice *iface) {
6593 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
6594 static BOOL showfixmes = TRUE;
6596 FIXME("(%p) : stub returning(%f)\n", This, 0.0f);
6602 static HRESULT WINAPI IWineD3DDeviceImpl_UpdateSurface(IWineD3DDevice *iface, IWineD3DSurface *pSourceSurface, CONST RECT* pSourceRect, IWineD3DSurface *pDestinationSurface, CONST POINT* pDestPoint) {
6603 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *) iface;
6604 /** TODO: remove casts to IWineD3DSurfaceImpl
6605 * NOTE: move code to surface to accomplish this
6606 ****************************************/
6607 IWineD3DSurfaceImpl *pSrcSurface = (IWineD3DSurfaceImpl *)pSourceSurface;
6608 int srcWidth, srcHeight;
6609 unsigned int srcSurfaceWidth, srcSurfaceHeight, destSurfaceWidth, destSurfaceHeight;
6610 WINED3DFORMAT destFormat, srcFormat;
6612 int destLeft, destTop;
6613 WINED3DPOOL srcPool, destPool;
6615 int rowoffset = 0; /* how many bytes to add onto the end of a row to wraparound to the beginning of the next */
6616 glDescriptor *glDescription = NULL;
6617 GLenum textureDimensions = GL_TEXTURE_2D;
6618 IWineD3DBaseTexture *baseTexture;
6620 WINED3DSURFACE_DESC winedesc;
6622 TRACE("(%p) : Source (%p) Rect (%p) Destination (%p) Point(%p)\n", This, pSourceSurface, pSourceRect, pDestinationSurface, pDestPoint);
6623 memset(&winedesc, 0, sizeof(winedesc));
6624 winedesc.Width = &srcSurfaceWidth;
6625 winedesc.Height = &srcSurfaceHeight;
6626 winedesc.Pool = &srcPool;
6627 winedesc.Format = &srcFormat;
6629 IWineD3DSurface_GetDesc(pSourceSurface, &winedesc);
6631 winedesc.Width = &destSurfaceWidth;
6632 winedesc.Height = &destSurfaceHeight;
6633 winedesc.Pool = &destPool;
6634 winedesc.Format = &destFormat;
6635 winedesc.Size = &destSize;
6637 IWineD3DSurface_GetDesc(pDestinationSurface, &winedesc);
6639 if(srcPool != WINED3DPOOL_SYSTEMMEM || destPool != WINED3DPOOL_DEFAULT){
6640 WARN("source %p must be SYSTEMMEM and dest %p must be DEFAULT, returning WINED3DERR_INVALIDCALL\n", pSourceSurface, pDestinationSurface);
6641 return WINED3DERR_INVALIDCALL;
6644 if (destFormat == WINED3DFMT_UNKNOWN) {
6645 TRACE("(%p) : Converting destination surface from WINED3DFMT_UNKNOWN to the source format\n", This);
6646 IWineD3DSurface_SetFormat(pDestinationSurface, srcFormat);
6648 /* Get the update surface description */
6649 IWineD3DSurface_GetDesc(pDestinationSurface, &winedesc);
6652 /* Make sure the surface is loaded and up to date */
6653 IWineD3DSurface_PreLoad(pDestinationSurface);
6655 IWineD3DSurface_GetGlDesc(pDestinationSurface, &glDescription);
6659 /* this needs to be done in lines if the sourceRect != the sourceWidth */
6660 srcWidth = pSourceRect ? pSourceRect->right - pSourceRect->left : srcSurfaceWidth;
6661 srcHeight = pSourceRect ? pSourceRect->top - pSourceRect->bottom : srcSurfaceHeight;
6662 destLeft = pDestPoint ? pDestPoint->x : 0;
6663 destTop = pDestPoint ? pDestPoint->y : 0;
6666 /* This function doesn't support compressed textures
6667 the pitch is just bytesPerPixel * width */
6668 if(srcWidth != srcSurfaceWidth || (pSourceRect != NULL && pSourceRect->left != 0) ){
6669 rowoffset = (srcSurfaceWidth - srcWidth) * pSrcSurface->bytesPerPixel;
6670 offset += pSourceRect->left * pSrcSurface->bytesPerPixel;
6671 /* TODO: do we ever get 3bpp?, would a shift and an add be quicker than a mul (well maybe a cycle or two) */
6673 /* TODO DXT formats */
6675 if(pSourceRect != NULL && pSourceRect->top != 0){
6676 offset += pSourceRect->top * srcWidth * pSrcSurface->bytesPerPixel;
6678 TRACE("(%p) glTexSubImage2D, Level %d, left %d, top %d, width %d, height %d , ftm %d, type %d, memory %p\n"
6680 ,glDescription->level
6685 ,glDescription->glFormat
6686 ,glDescription->glType
6687 ,IWineD3DSurface_GetData(pSourceSurface)
6691 if (IWineD3DSurface_GetData(pSourceSurface) == NULL) {
6693 /* need to lock the surface to get the data */
6694 FIXME("Surfaces has no allocated memory, but should be an in memory only surface\n");
6697 /* TODO: Cube and volume support */
6699 /* not a whole row so we have to do it a line at a time */
6702 /* hopefully using pointer addtion will be quicker than using a point + j * rowoffset */
6703 unsigned char* data =((unsigned char *)IWineD3DSurface_GetData(pSourceSurface)) + offset;
6705 for(j = destTop ; j < (srcHeight + destTop) ; j++){
6707 glTexSubImage2D(glDescription->target
6708 ,glDescription->level
6713 ,glDescription->glFormat
6714 ,glDescription->glType
6715 ,data /* could be quicker using */
6720 } else { /* Full width, so just write out the whole texture */
6722 if (WINED3DFMT_DXT1 == destFormat ||
6723 WINED3DFMT_DXT2 == destFormat ||
6724 WINED3DFMT_DXT3 == destFormat ||
6725 WINED3DFMT_DXT4 == destFormat ||
6726 WINED3DFMT_DXT5 == destFormat) {
6727 if (GL_SUPPORT(EXT_TEXTURE_COMPRESSION_S3TC)) {
6728 if (destSurfaceHeight != srcHeight || destSurfaceWidth != srcWidth) {
6729 /* FIXME: The easy way to do this is lock the destination, and copy the bits accross */
6730 FIXME("Updating part of a compressed texture is not supported at the moment\n");
6731 } if (destFormat != srcFormat) {
6732 FIXME("Updating mixed format compressed texture is not curretly support\n");
6734 GL_EXTCALL(glCompressedTexImage2DARB)(glDescription->target,
6735 glDescription->level,
6736 glDescription->glFormatInternal,
6741 IWineD3DSurface_GetData(pSourceSurface));
6744 FIXME("Attempting to update a DXT compressed texture without hardware support\n");
6749 if (NP2_REPACK == wined3d_settings.nonpower2_mode) {
6751 /* some applications cannot handle odd pitches returned by soft non-power2, so we have
6752 to repack the data from pow2Width/Height to expected Width,Height, this makes the
6753 data returned by GetData non-power2 width/height with hardware non-power2
6754 pow2Width/height are set to surface width height, repacking isn't needed so it
6755 doesn't matter which function gets called. */
6756 glTexSubImage2D(glDescription->target
6757 ,glDescription->level
6762 ,glDescription->glFormat
6763 ,glDescription->glType
6764 ,IWineD3DSurface_GetData(pSourceSurface)
6768 /* not repacked, the data returned by IWineD3DSurface_GetData is pow2Width x pow2Height */
6769 glTexSubImage2D(glDescription->target
6770 ,glDescription->level
6773 ,((IWineD3DSurfaceImpl *)pSourceSurface)->pow2Width
6774 ,((IWineD3DSurfaceImpl *)pSourceSurface)->pow2Height
6775 ,glDescription->glFormat
6776 ,glDescription->glType
6777 ,IWineD3DSurface_GetData(pSourceSurface)
6783 checkGLcall("glTexSubImage2D");
6784 ((IWineD3DSurfaceImpl *)pDestinationSurface)->Flags |= SFLAG_GLDIRTY;
6786 /* I only need to look up baseTexture here, so it may be a good idea to hava a GL_TARGET ->
6787 * GL_DIMENSIONS lookup, or maybe store the dimensions on the surface (but that's making the
6788 * surface bigger than it needs to be hmm.. */
6789 if (WINED3D_OK == IWineD3DSurface_GetContainer(pDestinationSurface, &IID_IWineD3DBaseTexture, (void **)&baseTexture)) {
6790 textureDimensions = IWineD3DBaseTexture_GetTextureDimensions(baseTexture);
6791 IWineD3DBaseTexture_Release(baseTexture);
6794 glDisable(textureDimensions); /* This needs to be managed better.... */
6800 /* Used by DirectX 8 */
6801 static HRESULT WINAPI IWineD3DDeviceImpl_CopyRects(IWineD3DDevice *iface,
6802 IWineD3DSurface* pSourceSurface, CONST RECT* pSourceRectsArray, UINT cRects,
6803 IWineD3DSurface* pDestinationSurface, CONST POINT* pDestPointsArray) {
6805 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
6806 HRESULT hr = WINED3D_OK;
6807 WINED3DFORMAT srcFormat, destFormat;
6808 UINT srcWidth, destWidth;
6809 UINT srcHeight, destHeight;
6811 WINED3DSURFACE_DESC winedesc;
6813 TRACE("(%p) pSrcSur=%p, pSourceRects=%p, cRects=%d, pDstSur=%p, pDestPtsArr=%p\n", This,
6814 pSourceSurface, pSourceRectsArray, cRects, pDestinationSurface, pDestPointsArray);
6817 /* Check that the source texture is in WINED3DPOOL_SYSTEMMEM and the destination texture is in WINED3DPOOL_DEFAULT */
6818 memset(&winedesc, 0, sizeof(winedesc));
6820 winedesc.Format = &srcFormat;
6821 winedesc.Width = &srcWidth;
6822 winedesc.Height = &srcHeight;
6823 winedesc.Size = &srcSize;
6824 IWineD3DSurface_GetDesc(pSourceSurface, &winedesc);
6826 winedesc.Format = &destFormat;
6827 winedesc.Width = &destWidth;
6828 winedesc.Height = &destHeight;
6829 winedesc.Size = NULL;
6830 IWineD3DSurface_GetDesc(pDestinationSurface, &winedesc);
6832 /* Check that the source and destination formats match */
6833 if (srcFormat != destFormat && WINED3DFMT_UNKNOWN != destFormat) {
6834 WARN("(%p) source %p format must match the dest %p format, returning WINED3DERR_INVALIDCALL\n", This, pSourceSurface, pDestinationSurface);
6835 return WINED3DERR_INVALIDCALL;
6836 } else if (WINED3DFMT_UNKNOWN == destFormat) {
6837 TRACE("(%p) : Converting destination surface from WINED3DFMT_UNKNOWN to the source format\n", This);
6838 IWineD3DSurface_SetFormat(pDestinationSurface, srcFormat);
6839 destFormat = srcFormat;
6842 /* Quick if complete copy ... */
6843 if (cRects == 0 && pSourceRectsArray == NULL && pDestPointsArray == NULL) {
6845 if (srcWidth == destWidth && srcHeight == destHeight) {
6846 WINED3DLOCKED_RECT lrSrc;
6847 WINED3DLOCKED_RECT lrDst;
6848 IWineD3DSurface_LockRect(pSourceSurface, &lrSrc, NULL, WINED3DLOCK_READONLY);
6849 IWineD3DSurface_LockRect(pDestinationSurface, &lrDst, NULL, 0L);
6850 TRACE("Locked src and dst, Direct copy as surfaces are equal, w=%d, h=%d\n", srcWidth, srcHeight);
6852 memcpy(lrDst.pBits, lrSrc.pBits, srcSize);
6854 IWineD3DSurface_UnlockRect(pSourceSurface);
6855 IWineD3DSurface_UnlockRect(pDestinationSurface);
6856 TRACE("Unlocked src and dst\n");
6860 FIXME("Wanted to copy all surfaces but size not compatible, returning WINED3DERR_INVALIDCALL\n");
6861 hr = WINED3DERR_INVALIDCALL;
6866 if (NULL != pSourceRectsArray && NULL != pDestPointsArray) {
6868 int bytesPerPixel = ((IWineD3DSurfaceImpl *) pSourceSurface)->bytesPerPixel;
6871 /* Copy rect by rect */
6872 for (i = 0; i < cRects; ++i) {
6873 CONST RECT* r = &pSourceRectsArray[i];
6874 CONST POINT* p = &pDestPointsArray[i];
6877 WINED3DLOCKED_RECT lrSrc;
6878 WINED3DLOCKED_RECT lrDst;
6881 TRACE("Copying rect %d (%ld,%ld),(%ld,%ld) -> (%ld,%ld)\n", i, r->left, r->top, r->right, r->bottom, p->x, p->y);
6882 if (srcFormat == WINED3DFMT_DXT1) {
6883 copyperline = ((r->right - r->left) * bytesPerPixel) / 2; /* DXT1 is half byte per pixel */
6885 copyperline = ((r->right - r->left) * bytesPerPixel);
6888 IWineD3DSurface_LockRect(pSourceSurface, &lrSrc, r, WINED3DLOCK_READONLY);
6889 dest_rect.left = p->x;
6890 dest_rect.top = p->y;
6891 dest_rect.right = p->x + (r->right - r->left);
6892 dest_rect.bottom= p->y + (r->bottom - r->top);
6893 IWineD3DSurface_LockRect(pDestinationSurface, &lrDst, &dest_rect, 0L);
6894 TRACE("Locked src and dst\n");
6896 /* Find where to start */
6897 for (j = 0; j < (r->bottom - r->top - 1); ++j) {
6898 memcpy((char*) lrDst.pBits + (j * lrDst.Pitch), (char*) lrSrc.pBits + (j * lrSrc.Pitch), copyperline);
6900 IWineD3DSurface_UnlockRect(pSourceSurface);
6901 IWineD3DSurface_UnlockRect(pDestinationSurface);
6902 TRACE("Unlocked src and dst\n");
6906 int bytesPerPixel = ((IWineD3DSurfaceImpl *) pSourceSurface)->bytesPerPixel;
6909 WINED3DLOCKED_RECT lrSrc;
6910 WINED3DLOCKED_RECT lrDst;
6913 for(i=0; i < cRects; i++) {
6914 CONST RECT* r = &pSourceRectsArray[i];
6916 TRACE("Copying rect %d (%ld,%ld),(%ld,%ld) -> (0, 0)\n", i, r->left, r->top, r->right, r->bottom);
6917 if (srcFormat == WINED3DFMT_DXT1) {
6918 copyperline = ((r->right - r->left) * bytesPerPixel) / 2; /* DXT1 is half byte per pixel */
6920 copyperline = ((r->right - r->left) * bytesPerPixel);
6922 IWineD3DSurface_LockRect(pSourceSurface, &lrSrc, r, WINED3DLOCK_READONLY);
6925 dest_rect.right = r->right - r->left;
6926 dest_rect.bottom= r->bottom - r->top;
6927 IWineD3DSurface_LockRect(pDestinationSurface, &lrDst, &dest_rect, 0L);
6928 TRACE("Locked src and dst\n");
6929 /* Find where to start */
6930 for (j = 0; j < (r->bottom - r->top - 1); ++j) {
6931 memcpy((char*) lrDst.pBits + (j * lrDst.Pitch), (char*) lrSrc.pBits + (j * lrSrc.Pitch), copyperline);
6933 IWineD3DSurface_UnlockRect(pSourceSurface);
6934 IWineD3DSurface_UnlockRect(pDestinationSurface);
6935 TRACE("Unlocked src and dst\n");
6943 /* Implementation details at http://developer.nvidia.com/attach/6494
6945 http://oss.sgi.com/projects/ogl-sample/registry/NV/evaluators.txt
6946 hmm.. no longer supported use
6947 OpenGL evaluators or tessellate surfaces within your application.
6950 /* http://msdn.microsoft.com/library/default.asp?url=/library/en-us/directx9_c/directx/graphics/reference/d3d/interfaces/idirect3ddevice9/DrawRectPatch.asp */
6951 static HRESULT WINAPI IWineD3DDeviceImpl_DrawRectPatch(IWineD3DDevice *iface, UINT Handle, CONST float* pNumSegs, CONST WINED3DRECTPATCH_INFO* pRectPatchInfo) {
6952 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
6953 TRACE("(%p) Handle(%d) noSegs(%p) rectpatch(%p)\n", This, Handle, pNumSegs, pRectPatchInfo);
6954 FIXME("(%p) : Stub\n", This);
6959 /* http://msdn.microsoft.com/library/default.asp?url=/library/en-us/directx9_c/directx/graphics/reference/d3d/interfaces/idirect3ddevice9/DrawTriPatch.asp */
6960 static HRESULT WINAPI IWineD3DDeviceImpl_DrawTriPatch(IWineD3DDevice *iface, UINT Handle, CONST float* pNumSegs, CONST WINED3DTRIPATCH_INFO* pTriPatchInfo) {
6961 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
6962 TRACE("(%p) Handle(%d) noSegs(%p) tripatch(%p)\n", This, Handle, pNumSegs, pTriPatchInfo);
6963 FIXME("(%p) : Stub\n", This);
6967 static HRESULT WINAPI IWineD3DDeviceImpl_DeletePatch(IWineD3DDevice *iface, UINT Handle) {
6968 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
6969 TRACE("(%p) Handle(%d)\n", This, Handle);
6970 FIXME("(%p) : Stub\n", This);
6974 static HRESULT WINAPI IWineD3DDeviceImpl_ColorFill(IWineD3DDevice *iface, IWineD3DSurface *pSurface, CONST D3DRECT* pRect, D3DCOLOR color) {
6975 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *) iface;
6976 IWineD3DSurfaceImpl *surface = (IWineD3DSurfaceImpl *) pSurface;
6978 TRACE("(%p) Colour fill Surface: %p rect: %p color: %ld\n", This, pSurface, pRect, color);
6980 if (surface->resource.pool != WINED3DPOOL_DEFAULT && surface->resource.pool != WINED3DPOOL_SYSTEMMEM) {
6981 FIXME("call to colorfill with non WINED3DPOOL_DEFAULT or WINED3DPOOL_SYSTEMMEM surface\n");
6982 return WINED3DERR_INVALIDCALL;
6985 /* Just forward this to the DirectDraw blitting engine */
6986 memset(&BltFx, 0, sizeof(BltFx));
6987 BltFx.dwSize = sizeof(BltFx);
6988 BltFx.u5.dwFillColor = color;
6989 return IWineD3DSurface_Blt(pSurface, (RECT *) pRect, NULL, NULL, DDBLT_COLORFILL, &BltFx);
6992 /* rendertarget and deptth stencil functions */
6993 static HRESULT WINAPI IWineD3DDeviceImpl_GetRenderTarget(IWineD3DDevice* iface,DWORD RenderTargetIndex, IWineD3DSurface **ppRenderTarget) {
6994 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
6996 /* FIXME: Implelent RenderTargetIndex >0 */
6997 if(RenderTargetIndex > 0)
6998 FIXME("(%p) : RenderTargetIndex %ld >0 not currently supported\n", This, RenderTargetIndex);
7000 *ppRenderTarget = This->renderTarget;
7001 TRACE("(%p) : RenderTarget %ld Index returning %p\n", This, RenderTargetIndex, *ppRenderTarget);
7002 /* Note inc ref on returned surface */
7003 if(*ppRenderTarget != NULL)
7004 IWineD3DSurface_AddRef(*ppRenderTarget);
7008 static HRESULT WINAPI IWineD3DDeviceImpl_SetFrontBackBuffers(IWineD3DDevice *iface, IWineD3DSurface *Front, IWineD3DSurface *Back) {
7009 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
7010 IWineD3DSurfaceImpl *FrontImpl = (IWineD3DSurfaceImpl *) Front;
7011 IWineD3DSurfaceImpl *BackImpl = (IWineD3DSurfaceImpl *) Back;
7012 IWineD3DSwapChainImpl *Swapchain;
7015 TRACE("(%p)->(%p,%p)\n", This, FrontImpl, BackImpl);
7017 hr = IWineD3DDevice_GetSwapChain(iface, 0, (IWineD3DSwapChain **) &Swapchain);
7018 if(hr != WINED3D_OK) {
7019 ERR("Can't get the swapchain\n");
7023 /* Make sure to release the swapchain */
7024 IWineD3DSwapChain_Release((IWineD3DSwapChain *) Swapchain);
7026 if(FrontImpl && !(FrontImpl->resource.usage & WINED3DUSAGE_RENDERTARGET) ) {
7027 ERR("Trying to set a front buffer which doesn't have WINED3DUSAGE_RENDERTARGET usage\n");
7028 return WINED3DERR_INVALIDCALL;
7030 else if(BackImpl && !(BackImpl->resource.usage & WINED3DUSAGE_RENDERTARGET)) {
7031 ERR("Trying to set a back buffer which doesn't have WINED3DUSAGE_RENDERTARGET usage\n");
7032 return WINED3DERR_INVALIDCALL;
7035 if(Swapchain->frontBuffer != Front) {
7036 TRACE("Changing the front buffer from %p to %p\n", Swapchain->frontBuffer, Front);
7038 if(Swapchain->frontBuffer)
7039 IWineD3DSurface_SetContainer(Swapchain->frontBuffer, NULL);
7040 Swapchain->frontBuffer = Front;
7042 if(Swapchain->frontBuffer) {
7043 IWineD3DSurface_SetContainer(Swapchain->frontBuffer, (IWineD3DBase *) Swapchain);
7047 if(Back && !Swapchain->backBuffer) {
7048 /* We need memory for the back buffer array - only one back buffer this way */
7049 Swapchain->backBuffer = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(IWineD3DSurface *));
7050 if(!Swapchain->backBuffer) {
7051 ERR("Out of memory\n");
7052 return E_OUTOFMEMORY;
7056 if(Swapchain->backBuffer[0] != Back) {
7057 TRACE("Changing the back buffer from %p to %p\n", Swapchain->backBuffer, Back);
7059 if(!Swapchain->backBuffer[0]) {
7060 /* GL was told to draw to the front buffer at creation,
7063 glDrawBuffer(GL_BACK);
7064 checkGLcall("glDrawBuffer(GL_BACK)");
7065 /* Set the backbuffer count to 1 because other code uses it to fing the back buffers */
7066 Swapchain->presentParms.BackBufferCount = 1;
7068 /* That makes problems - disable for now */
7069 /* glDrawBuffer(GL_FRONT); */
7070 checkGLcall("glDrawBuffer(GL_FRONT)");
7071 /* We have lost our back buffer, set this to 0 to avoid confusing other code */
7072 Swapchain->presentParms.BackBufferCount = 0;
7076 if(Swapchain->backBuffer[0])
7077 IWineD3DSurface_SetContainer(Swapchain->backBuffer[0], NULL);
7078 Swapchain->backBuffer[0] = Back;
7080 if(Swapchain->backBuffer[0]) {
7081 IWineD3DSurface_SetContainer(Swapchain->backBuffer[0], (IWineD3DBase *) Swapchain);
7083 HeapFree(GetProcessHeap(), 0, Swapchain->backBuffer);
7091 static HRESULT WINAPI IWineD3DDeviceImpl_GetDepthStencilSurface(IWineD3DDevice* iface, IWineD3DSurface **ppZStencilSurface) {
7092 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
7093 *ppZStencilSurface = This->depthStencilBuffer;
7094 TRACE("(%p) : zStencilSurface returning %p\n", This, *ppZStencilSurface);
7096 if(*ppZStencilSurface != NULL) {
7097 /* Note inc ref on returned surface */
7098 IWineD3DSurface_AddRef(*ppZStencilSurface);
7103 /* internal static helper functions */
7104 static HRESULT WINAPI IWineD3DDeviceImpl_ActiveRender(IWineD3DDevice* iface,
7105 IWineD3DSurface *RenderSurface);
7107 static HRESULT WINAPI IWineD3DDeviceImpl_SetRenderTarget(IWineD3DDevice *iface, DWORD RenderTargetIndex, IWineD3DSurface *pRenderTarget) {
7108 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
7109 HRESULT hr = WINED3D_OK;
7110 WINED3DVIEWPORT viewport;
7112 TRACE("(%p) Swapping rendertarget\n",This);
7113 if (RenderTargetIndex > 0) {
7114 FIXME("(%p) Render targets other than the first are not supported\n",This);
7115 RenderTargetIndex = 0;
7118 /* MSDN says that null disables the render target
7119 but a device must always be associated with a render target
7120 nope MSDN says that we return invalid call to a null rendertarget with an index of 0
7122 see http://msdn.microsoft.com/library/default.asp?url=/library/en-us/directx9_c/directx/graphics/programmingguide/AdvancedTopics/PixelPipe/MultipleRenderTarget.asp
7125 if (RenderTargetIndex == 0 && pRenderTarget == NULL) {
7126 FIXME("Trying to set render target 0 to NULL\n");
7127 return WINED3DERR_INVALIDCALL;
7129 /* TODO: replace Impl* usage with interface usage */
7130 if (!((IWineD3DSurfaceImpl *)pRenderTarget)->resource.usage & WINED3DUSAGE_RENDERTARGET) {
7131 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);
7132 return WINED3DERR_INVALIDCALL;
7134 /** TODO: check that the depth stencil format matches the render target, this is only done in debug
7135 * builds, but I think wine counts as a 'debug' build for now.
7136 ******************************/
7137 /* If we are trying to set what we already have, don't bother */
7138 if (pRenderTarget == This->renderTarget) {
7139 TRACE("Trying to do a NOP SetRenderTarget operation\n");
7141 /* Otherwise, set the render target up */
7143 if (FALSE == This->sceneEnded) {
7144 IWineD3DDevice_EndScene(iface);
7146 TRACE("clearing renderer\n");
7147 /* IWineD3DDeviceImpl_CleanRender(iface); */
7148 /* OpenGL doesn't support 'sharing' of the stencilBuffer so we may incure an extra memory overhead
7149 depending on the renter target implementation being used.
7150 A shared context implementation will share all buffers between all rendertargets (including swapchains),
7151 implementations that use separate pbuffers for different swapchains or rendertargets will have to duplicate the
7152 stencil buffer and incure an extra memory overhead */
7153 hr = IWineD3DDeviceImpl_ActiveRender(iface, pRenderTarget);
7156 if (SUCCEEDED(hr)) {
7157 /* Finally, reset the viewport as the MSDN states. */
7158 /* TODO: Replace impl usage */
7159 viewport.Height = ((IWineD3DSurfaceImpl *)This->renderTarget)->currentDesc.Height;
7160 viewport.Width = ((IWineD3DSurfaceImpl *)This->renderTarget)->currentDesc.Width;
7163 viewport.MaxZ = 1.0f;
7164 viewport.MinZ = 0.0f;
7165 IWineD3DDeviceImpl_SetViewport(iface, &viewport);
7167 FIXME("Unknown error setting the render target\n");
7169 This->sceneEnded = FALSE;
7173 static HRESULT WINAPI IWineD3DDeviceImpl_SetDepthStencilSurface(IWineD3DDevice *iface, IWineD3DSurface *pNewZStencil) {
7174 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
7175 HRESULT hr = WINED3D_OK;
7176 IWineD3DSurface *tmp;
7178 TRACE("(%p) Swapping z-buffer\n",This);
7180 if (pNewZStencil == This->stencilBufferTarget) {
7181 TRACE("Trying to do a NOP SetRenderTarget operation\n");
7183 /** OpenGL doesn't support 'sharing' of the stencilBuffer so we may incure an extra memory overhead
7184 * depending on the renter target implementation being used.
7185 * A shared context implementation will share all buffers between all rendertargets (including swapchains),
7186 * implementations that use separate pbuffers for different swapchains or rendertargets will have to duplicate the
7187 * stencil buffer and incure an extra memory overhead
7188 ******************************************************/
7191 tmp = This->stencilBufferTarget;
7192 This->stencilBufferTarget = pNewZStencil;
7193 /* should we be calling the parent or the wined3d surface? */
7194 if (NULL != This->stencilBufferTarget) IWineD3DSurface_AddRef(This->stencilBufferTarget);
7195 if (NULL != tmp) IWineD3DSurface_Release(tmp);
7197 /** TODO: glEnable/glDisable on depth/stencil depending on
7198 * pNewZStencil is NULL and the depth/stencil is enabled in d3d
7199 **********************************************************/
7206 #ifdef GL_VERSION_1_3
7207 /* Internal functions not in DirectX */
7208 /** TODO: move this off to the opengl context manager
7209 *(the swapchain doesn't need to know anything about offscreen rendering!)
7210 ****************************************************/
7212 static HRESULT WINAPI IWineD3DDeviceImpl_CleanRender(IWineD3DDevice* iface, IWineD3DSwapChainImpl *swapchain)
7214 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
7216 TRACE("(%p), %p\n", This, swapchain);
7218 if (swapchain->win != swapchain->drawable) {
7219 /* Set everything back the way it ws */
7220 swapchain->render_ctx = swapchain->glCtx;
7221 swapchain->drawable = swapchain->win;
7226 /* TODO: move this off into a context manager so that GLX_ATI_render_texture and other types of surface can be used. */
7227 static HRESULT WINAPI IWineD3DDeviceImpl_FindGLContext(IWineD3DDevice *iface, IWineD3DSurface *pSurface, glContext **context) {
7228 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
7231 unsigned int height;
7232 WINED3DFORMAT format;
7233 WINED3DSURFACE_DESC surfaceDesc;
7234 memset(&surfaceDesc, 0, sizeof(surfaceDesc));
7235 surfaceDesc.Width = &width;
7236 surfaceDesc.Height = &height;
7237 surfaceDesc.Format = &format;
7238 IWineD3DSurface_GetDesc(pSurface, &surfaceDesc);
7240 /* I need a get width/height function (and should do something with the format) */
7241 for (i = 0; i < CONTEXT_CACHE; ++i) {
7242 /** NOTE: the contextCache[i].pSurface == pSurface check ceates onepbuffer per surface
7243 ATI cards don't destroy pbuffers, but as soon as resource releasing callbacks are inplace
7244 the pSurface can be set to 0 allowing it to be reused from cache **/
7245 if (This->contextCache[i].Width == width && This->contextCache[i].Height == height
7246 && (pbuffer_per_surface == FALSE || This->contextCache[i].pSurface == pSurface || This->contextCache[i].pSurface == NULL)) {
7247 *context = &This->contextCache[i];
7250 if (This->contextCache[i].Width == 0) {
7251 This->contextCache[i].pSurface = pSurface;
7252 This->contextCache[i].Width = width;
7253 This->contextCache[i].Height = height;
7254 *context = &This->contextCache[i];
7258 if (i == CONTEXT_CACHE) {
7259 int minUsage = 0x7FFFFFFF; /* MAX_INT */
7260 glContext *dropContext = 0;
7261 for (i = 0; i < CONTEXT_CACHE; i++) {
7262 if (This->contextCache[i].usedcount < minUsage) {
7263 dropContext = &This->contextCache[i];
7264 minUsage = This->contextCache[i].usedcount;
7267 /* clean up the context (this doesn't work for ATI at the moment */
7269 glXDestroyContext(swapchain->display, dropContext->context);
7270 glXDestroyPbuffer(swapchain->display, dropContext->drawable);
7273 dropContext->Width = 0;
7274 dropContext->pSurface = pSurface;
7275 *context = dropContext;
7277 if (++This->contextCache[i].usedcount == 0x7FFFFFFF /* MAX_INT */ - 1 ) {
7278 for (i = 0; i < CONTEXT_CACHE; i++) {
7279 This->contextCache[i].usedcount = max(0, This->contextCache[i].usedcount - (0x7FFFFFFF /* MAX_INT */ >> 1));
7283 if (*context != NULL)
7286 return E_OUTOFMEMORY;
7290 /* Reapply the device stateblock */
7291 static void device_reapply_stateblock(IWineD3DDeviceImpl* This) {
7294 IWineD3DStateBlockImpl *oldUpdateStateBlock;
7296 /* Disable recording */
7297 oldUpdateStateBlock = This->updateStateBlock;
7298 oldRecording= This->isRecordingState;
7299 This->isRecordingState = FALSE;
7300 This->updateStateBlock = This->stateBlock;
7302 /* Reapply the state block */
7303 IWineD3DStateBlock_Apply((IWineD3DStateBlock *)This->stateBlock);
7305 /* Restore recording */
7306 This->isRecordingState = oldRecording;
7307 This->updateStateBlock = oldUpdateStateBlock;
7310 /* Set the device to render to a texture, or not.
7311 * This involves changing renderUpsideDown */
7313 static void device_render_to_texture(IWineD3DDeviceImpl* This, BOOL isTexture) {
7317 IWineD3DStateBlockImpl *oldUpdateStateBlock;
7319 /* Disable recording */
7320 oldUpdateStateBlock = This->updateStateBlock;
7321 oldRecording= This->isRecordingState;
7322 This->isRecordingState = FALSE;
7323 This->updateStateBlock = This->stateBlock;
7325 /* Set upside-down rendering, and update the cull mode */
7326 /* The surface must be rendered upside down to cancel the flip produced by glCopyTexImage */
7327 This->renderUpsideDown = isTexture;
7328 This->last_was_rhw = FALSE;
7329 This->proj_valid = FALSE;
7330 IWineD3DDevice_GetRenderState((IWineD3DDevice*) This, WINED3DRS_CULLMODE, &cullMode);
7331 IWineD3DDevice_SetRenderState((IWineD3DDevice*) This, WINED3DRS_CULLMODE, cullMode);
7333 /* Restore recording */
7334 This->isRecordingState = oldRecording;
7335 This->updateStateBlock = oldUpdateStateBlock;
7338 /* Returns an array of compatible FBconfig(s).
7339 * The array must be freed with XFree. Requires ENTER_GL() */
7341 static GLXFBConfig* device_find_fbconfigs(
7342 IWineD3DDeviceImpl* This,
7343 IWineD3DSwapChainImpl* implicitSwapchainImpl,
7344 IWineD3DSurface* RenderSurface) {
7346 GLXFBConfig* cfgs = NULL;
7351 IWineD3DSurface *StencilSurface = This->stencilBufferTarget;
7352 D3DFORMAT BackBufferFormat = ((IWineD3DSurfaceImpl *) RenderSurface)->resource.format;
7353 D3DFORMAT StencilBufferFormat = (NULL != StencilSurface) ? ((IWineD3DSurfaceImpl *) StencilSurface)->resource.format : 0;
7356 if StencilSurface == NULL && zBufferTarget != NULL then switch the zbuffer off,
7357 it StencilSurface != NULL && zBufferTarget == NULL switch it on
7360 #define PUSH1(att) attribs[nAttribs++] = (att);
7361 #define PUSH2(att,value) attribs[nAttribs++] = (att); attribs[nAttribs++] = (value);
7363 /* PUSH2(GLX_BIND_TO_TEXTURE_RGBA_ATI, True); examples of this are few and far between (but I've got a nice working one!)*/
7365 PUSH2(GLX_DRAWABLE_TYPE, GLX_PBUFFER_BIT);
7366 PUSH2(GLX_X_RENDERABLE, TRUE);
7367 PUSH2(GLX_DOUBLEBUFFER, TRUE);
7368 TRACE("calling makeglcfg\n");
7369 D3DFmtMakeGlCfg(BackBufferFormat, StencilBufferFormat, attribs, &nAttribs, FALSE /* alternate */);
7371 TRACE("calling chooseFGConfig\n");
7372 cfgs = glXChooseFBConfig(implicitSwapchainImpl->display,
7373 DefaultScreen(implicitSwapchainImpl->display),
7376 /* OK we didn't find the exact config, so use any reasonable match */
7377 /* TODO: fill in the 'requested' and 'current' depths, and make sure that's
7379 static BOOL show_message = TRUE;
7381 ERR("Failed to find exact match, finding alternative but you may "
7382 "suffer performance issues, try changing xfree's depth to match the requested depth\n");
7383 show_message = FALSE;
7386 PUSH2(GLX_DRAWABLE_TYPE, GLX_PBUFFER_BIT | GLX_WINDOW_BIT);
7387 /* PUSH2(GLX_X_RENDERABLE, TRUE); */
7388 PUSH2(GLX_RENDER_TYPE, GLX_RGBA_BIT);
7389 PUSH2(GLX_DOUBLEBUFFER, FALSE);
7390 TRACE("calling makeglcfg\n");
7391 D3DFmtMakeGlCfg(BackBufferFormat, StencilBufferFormat, attribs, &nAttribs, TRUE /* alternate */);
7393 cfgs = glXChooseFBConfig(implicitSwapchainImpl->display,
7394 DefaultScreen(implicitSwapchainImpl->display),
7399 ERR("Could not get a valid FBConfig for (%u,%s)/(%u,%s)\n",
7400 BackBufferFormat, debug_d3dformat(BackBufferFormat),
7401 StencilBufferFormat, debug_d3dformat(StencilBufferFormat));
7405 for (i = 0; i < nCfgs; ++i) {
7406 TRACE("for (%u,%s)/(%u,%s) found config[%d]@%p\n", BackBufferFormat,
7407 debug_d3dformat(BackBufferFormat), StencilBufferFormat,
7408 debug_d3dformat(StencilBufferFormat), i, cfgs[i]);
7410 if (NULL != This->renderTarget) {
7412 vcheckGLcall("glFlush");
7413 /** This is only useful if the old render target was a swapchain,
7414 * we need to supercede this with a function that displays
7415 * the current buffer on the screen. This is easy to do in glx1.3 but
7416 * we need to do copy-write pixels in glx 1.2.
7417 ************************************************/
7418 glXSwapBuffers(implicitSwapChainImpl->display,
7419 implicitSwapChainImpl->drawable);
7420 printf("Hit Enter to get next frame ...\n");
7431 /** FIXME: This is currently used called whenever SetRenderTarget or SetStencilBuffer are called
7432 * the functionality needs splitting up so that we don't do more than we should do.
7433 * this only seems to impact performance a little.
7434 ******************************/
7435 static HRESULT WINAPI IWineD3DDeviceImpl_ActiveRender(IWineD3DDevice* iface,
7436 IWineD3DSurface *RenderSurface) {
7439 * Currently only active for GLX >= 1.3
7440 * for others versions we'll have to use GLXPixmaps
7442 * normally we must test GLX_VERSION_1_3 but nvidia headers are not correct
7443 * as they implement GLX 1.3 but only define GLX_VERSION_1_2
7444 * so only check OpenGL version
7445 * ..........................
7446 * I don't believe that it is a problem with NVidia headers,
7447 * XFree only supports GLX1.2, nVidia (and ATI to some extent) provide 1.3 functions
7448 * in GLX 1.2, there is no mention of the correct way to tell if the extensions are provided.
7450 * Your application will report GLX version 1.2 on glXQueryVersion.
7451 * However, it is safe to call the GLX 1.3 functions as described below.
7453 #if defined(GL_VERSION_1_3)
7455 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
7456 GLXFBConfig* cfgs = NULL;
7457 IWineD3DSwapChain *currentSwapchain;
7458 IWineD3DSwapChainImpl *currentSwapchainImpl;
7459 IWineD3DSwapChain *implicitSwapchain;
7460 IWineD3DSwapChainImpl *implicitSwapchainImpl;
7461 IWineD3DSwapChain *renderSurfaceSwapchain;
7462 IWineD3DSwapChainImpl *renderSurfaceSwapchainImpl;
7464 /* Obtain a reference to the device implicit swapchain,
7465 * the swapchain of the current render target,
7466 * and the swapchain of the new render target.
7467 * Fallback to device implicit swapchain if the current render target doesn't have one */
7468 IWineD3DDevice_GetSwapChain(iface, 0, &implicitSwapchain);
7469 IWineD3DSurface_GetContainer(RenderSurface, &IID_IWineD3DSwapChain, (void**) &renderSurfaceSwapchain);
7470 IWineD3DSurface_GetContainer(This->renderTarget, &IID_IWineD3DSwapChain, (void **)¤tSwapchain);
7471 if (currentSwapchain == NULL)
7472 IWineD3DDevice_GetSwapChain(iface, 0, ¤tSwapchain);
7474 currentSwapchainImpl = (IWineD3DSwapChainImpl*) currentSwapchain;
7475 implicitSwapchainImpl = (IWineD3DSwapChainImpl*) implicitSwapchain;
7476 renderSurfaceSwapchainImpl = (IWineD3DSwapChainImpl*) renderSurfaceSwapchain;
7481 * TODO: remove the use of IWineD3DSwapChainImpl, a context manager will help since it will replace the
7482 * renderTarget = swapchain->backBuffer[i] bit and anything to do with *glContexts
7483 **********************************************************************/
7484 if (renderSurfaceSwapchain != NULL) {
7486 /* We also need to make sure that the lights &co are also in the context of the swapchains */
7487 /* FIXME: If the render target gets sent to the frontBuffer should be be presenting it raw? */
7488 TRACE("making swapchain active\n");
7489 if (RenderSurface != This->renderTarget) {
7490 BOOL backbuf = FALSE;
7493 for(i = 0; i < renderSurfaceSwapchainImpl->presentParms.BackBufferCount; i++) {
7494 if(RenderSurface == renderSurfaceSwapchainImpl->backBuffer[i]) {
7502 /* This could be flagged so that some operations work directly with the front buffer */
7503 FIXME("Attempting to set the renderTarget to the frontBuffer\n");
7505 if (glXMakeCurrent(renderSurfaceSwapchainImpl->display,
7506 renderSurfaceSwapchainImpl->win,
7507 renderSurfaceSwapchainImpl->glCtx) == False) {
7509 TRACE("Error in setting current context: context %p drawable %ld !\n",
7510 implicitSwapchainImpl->glCtx, implicitSwapchainImpl->win);
7512 checkGLcall("glXMakeContextCurrent");
7514 /* Clean up the old context */
7515 IWineD3DDeviceImpl_CleanRender(iface, currentSwapchainImpl);
7517 /* Reapply the stateblock, and set the device not to render to texture */
7518 device_reapply_stateblock(This);
7519 device_render_to_texture(This, FALSE);
7522 /* Offscreen rendering: PBuffers (currently disabled).
7523 * Also note that this path is never reached if FBOs are supported */
7524 } else if (pbuffer_support &&
7525 (cfgs = device_find_fbconfigs(This, implicitSwapchainImpl, RenderSurface)) != NULL) {
7527 /** ********************************************************************
7528 * This is a quickly hacked out implementation of offscreen textures.
7529 * It will work in most cases but there may be problems if the client
7530 * modifies the texture directly, or expects the contents of the rendertarget
7533 * There are some real speed vs compatibility issues here:
7534 * we should really use a new context for every texture, but that eats ram.
7535 * we should also be restoring the texture to the pbuffer but that eats CPU
7536 * we can also 'reuse' the current pbuffer if the size is larger than the requested buffer,
7537 * but if this means reusing the display backbuffer then we need to make sure that
7538 * states are correctly preserved.
7539 * In many cases I would expect that we can 'skip' some functions, such as preserving states,
7540 * and gain a good performance increase at the cost of compatibility.
7541 * I would suggest that, when this is the case, a user configurable flag be made
7542 * available, allowing the user to choose the best emulated experience for them.
7543 *********************************************************************/
7545 XVisualInfo *visinfo;
7546 glContext *newContext;
7548 /* Here were using a shared context model */
7549 if (WINED3D_OK != IWineD3DDeviceImpl_FindGLContext(iface, RenderSurface, &newContext)) {
7550 FIXME("(%p) : Failed to find a context for surface %p\n", iface, RenderSurface);
7553 /* If the context doesn't exist then create a new one */
7554 /* TODO: This should really be part of findGlContext */
7555 if (NULL == newContext->context) {
7560 TRACE("making new buffer\n");
7561 attribs[nAttribs++] = GLX_PBUFFER_WIDTH;
7562 attribs[nAttribs++] = newContext->Width;
7563 attribs[nAttribs++] = GLX_PBUFFER_HEIGHT;
7564 attribs[nAttribs++] = newContext->Height;
7565 attribs[nAttribs++] = None;
7567 newContext->drawable = glXCreatePbuffer(implicitSwapchainImpl->display, cfgs[0], attribs);
7569 /** ****************************************
7570 *GLX1.3 isn't supported by XFree 'yet' until that point ATI emulates pBuffers
7572 * In future releases, we may provide the calls glXCreateNewContext,
7573 * glXQueryDrawable and glXMakeContextCurrent.
7574 * so until then we have to use glXGetVisualFromFBConfig &co..
7575 ********************************************/
7577 visinfo = glXGetVisualFromFBConfig(implicitSwapchainImpl->display, cfgs[0]);
7579 ERR("Error: couldn't get an RGBA, double-buffered visual\n");
7581 newContext->context = glXCreateContext(
7582 implicitSwapchainImpl->display, visinfo,
7583 implicitSwapchainImpl->glCtx, GL_TRUE);
7588 if (NULL == newContext || NULL == newContext->context) {
7589 ERR("(%p) : Failed to find a context for surface %p\n", iface, RenderSurface);
7591 /* Debug logging, (this function leaks), change to a TRACE when the leak is plugged */
7592 if (glXMakeCurrent(implicitSwapchainImpl->display,
7593 newContext->drawable, newContext->context) == False) {
7595 TRACE("Error in setting current context: context %p drawable %ld\n",
7596 newContext->context, newContext->drawable);
7598 checkGLcall("glXMakeContextCurrent");
7600 /* Clean up the old context */
7601 IWineD3DDeviceImpl_CleanRender(iface, currentSwapchainImpl);
7603 /* Reapply stateblock, and set device to render to a texture */
7604 device_reapply_stateblock(This);
7605 device_render_to_texture(This, TRUE);
7607 /* Set the current context of the swapchain to the new context */
7608 implicitSwapchainImpl->drawable = newContext->drawable;
7609 implicitSwapchainImpl->render_ctx = newContext->context;
7612 /* Same context, but update renderUpsideDown and cull mode */
7613 device_render_to_texture(This, TRUE);
7616 /* Replace the render target */
7617 if (This->renderTarget != RenderSurface) {
7618 IWineD3DSurface_Release(This->renderTarget);
7619 This->renderTarget = RenderSurface;
7620 IWineD3DSurface_AddRef(RenderSurface);
7623 if (cfgs != NULL) XFree(cfgs);
7624 if (implicitSwapchain != NULL) IWineD3DSwapChain_Release(implicitSwapchain);
7625 if (currentSwapchain != NULL) IWineD3DSwapChain_Release(currentSwapchain);
7626 if (renderSurfaceSwapchain != NULL) IWineD3DSwapChain_Release(renderSurfaceSwapchain);
7632 static HRESULT WINAPI IWineD3DDeviceImpl_SetCursorProperties(IWineD3DDevice* iface, UINT XHotSpot,
7633 UINT YHotSpot, IWineD3DSurface *pCursorBitmap) {
7634 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *) iface;
7635 /* TODO: the use of Impl is deprecated. */
7636 IWineD3DSurfaceImpl * pSur = (IWineD3DSurfaceImpl *) pCursorBitmap;
7638 TRACE("(%p) : Spot Pos(%u,%u)\n", This, XHotSpot, YHotSpot);
7640 /* some basic validation checks */
7641 if(This->cursorTexture) {
7643 glDeleteTextures(1, &This->cursorTexture);
7645 This->cursorTexture = 0;
7649 /* MSDN: Cursor must be A8R8G8B8 */
7650 if (WINED3DFMT_A8R8G8B8 != pSur->resource.format) {
7651 ERR("(%p) : surface(%p) has an invalid format\n", This, pCursorBitmap);
7652 return WINED3DERR_INVALIDCALL;
7655 /* MSDN: Cursor must be smaller than the display mode */
7656 if(pSur->currentDesc.Width > This->ddraw_width ||
7657 pSur->currentDesc.Height > This->ddraw_height) {
7658 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);
7659 return WINED3DERR_INVALIDCALL;
7662 /* TODO: MSDN: Cursor sizes must be a power of 2 */
7663 /* This is to tell our texture code to load a SCRATCH surface. This allows us to use out
7664 * Texture and Blitting code to draw the cursor
7666 pSur->Flags |= SFLAG_FORCELOAD;
7667 IWineD3DSurface_PreLoad(pCursorBitmap);
7668 pSur->Flags &= ~SFLAG_FORCELOAD;
7669 /* Do not store the surface's pointer because the application may release
7670 * it after setting the cursor image. Windows doesn't addref the set surface, so we can't
7671 * do this either without creating circular refcount dependencies. Copy out the gl texture instead.
7673 This->cursorTexture = pSur->glDescription.textureName;
7674 This->cursorWidth = pSur->currentDesc.Width;
7675 This->cursorHeight = pSur->currentDesc.Height;
7676 pSur->glDescription.textureName = 0; /* Prevent the texture from being changed or deleted */
7679 This->xHotSpot = XHotSpot;
7680 This->yHotSpot = YHotSpot;
7684 static void WINAPI IWineD3DDeviceImpl_SetCursorPosition(IWineD3DDevice* iface, int XScreenSpace, int YScreenSpace, DWORD Flags) {
7685 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *) iface;
7686 TRACE("(%p) : SetPos to (%u,%u)\n", This, XScreenSpace, YScreenSpace);
7688 This->xScreenSpace = XScreenSpace;
7689 This->yScreenSpace = YScreenSpace;
7695 static BOOL WINAPI IWineD3DDeviceImpl_ShowCursor(IWineD3DDevice* iface, BOOL bShow) {
7696 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *) iface;
7697 BOOL oldVisible = This->bCursorVisible;
7698 TRACE("(%p) : visible(%d)\n", This, bShow);
7700 if(This->cursorTexture)
7701 This->bCursorVisible = bShow;
7706 static HRESULT WINAPI IWineD3DDeviceImpl_TestCooperativeLevel(IWineD3DDevice* iface) {
7707 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *) iface;
7708 TRACE("(%p) : state (%lu)\n", This, This->state);
7709 /* TODO: Implement wrapping of the WndProc so that mimimize and maxamise can be monitored and the states adjusted. */
7710 switch (This->state) {
7713 case WINED3DERR_DEVICELOST:
7715 ResourceList *resourceList = This->resources;
7716 while (NULL != resourceList) {
7717 if (((IWineD3DResourceImpl *)resourceList->resource)->resource.pool == WINED3DPOOL_DEFAULT /* TODO: IWineD3DResource_GetPool(resourceList->resource)*/)
7718 return WINED3DERR_DEVICENOTRESET;
7719 resourceList = resourceList->next;
7721 return WINED3DERR_DEVICELOST;
7723 case WINED3DERR_DRIVERINTERNALERROR:
7724 return WINED3DERR_DRIVERINTERNALERROR;
7728 return WINED3DERR_DRIVERINTERNALERROR;
7732 static HRESULT WINAPI IWineD3DDeviceImpl_EvictManagedResources(IWineD3DDevice* iface) {
7733 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *) iface;
7734 /** FIXME: Resource tracking needs to be done,
7735 * The closes we can do to this is set the priorities of all managed textures low
7736 * and then reset them.
7737 ***********************************************************/
7738 FIXME("(%p) : stub\n", This);
7742 static HRESULT WINAPI IWineD3DDeviceImpl_Reset(IWineD3DDevice* iface, WINED3DPRESENT_PARAMETERS* pPresentationParameters) {
7743 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *) iface;
7744 /** FIXME: Resource trascking needs to be done.
7745 * in effect this pulls all non only default
7746 * textures out of video memory and deletes all glTextures (glDeleteTextures)
7747 * and should clear down the context and set it up according to pPresentationParameters
7748 ***********************************************************/
7749 FIXME("(%p) : stub\n", This);
7753 static HRESULT WINAPI IWineD3DDeviceImpl_SetDialogBoxMode(IWineD3DDevice *iface, BOOL bEnableDialogs) {
7754 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
7755 /** FIXME: always true at the moment **/
7756 if(bEnableDialogs == FALSE) {
7757 FIXME("(%p) Dialogs cannot be disabled yet\n", This);
7763 static HRESULT WINAPI IWineD3DDeviceImpl_GetCreationParameters(IWineD3DDevice *iface, WINED3DDEVICE_CREATION_PARAMETERS *pParameters) {
7764 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *) iface;
7765 TRACE("(%p) : pParameters %p\n", This, pParameters);
7767 *pParameters = This->createParms;
7771 static void WINAPI IWineD3DDeviceImpl_SetGammaRamp(IWineD3DDevice * iface, UINT iSwapChain, DWORD Flags, CONST WINED3DGAMMARAMP* pRamp) {
7772 IWineD3DSwapChain *swapchain;
7773 HRESULT hrc = WINED3D_OK;
7775 TRACE("Relaying to swapchain\n");
7777 if ((hrc = IWineD3DDeviceImpl_GetSwapChain(iface, iSwapChain, &swapchain)) == WINED3D_OK) {
7778 IWineD3DSwapChain_SetGammaRamp(swapchain, Flags, (WINED3DGAMMARAMP *)pRamp);
7779 IWineD3DSwapChain_Release(swapchain);
7784 static void WINAPI IWineD3DDeviceImpl_GetGammaRamp(IWineD3DDevice *iface, UINT iSwapChain, WINED3DGAMMARAMP* pRamp) {
7785 IWineD3DSwapChain *swapchain;
7786 HRESULT hrc = WINED3D_OK;
7788 TRACE("Relaying to swapchain\n");
7790 if ((hrc = IWineD3DDeviceImpl_GetSwapChain(iface, iSwapChain, &swapchain)) == WINED3D_OK) {
7791 hrc =IWineD3DSwapChain_GetGammaRamp(swapchain, pRamp);
7792 IWineD3DSwapChain_Release(swapchain);
7798 /** ********************************************************
7799 * Notification functions
7800 ** ********************************************************/
7801 /** This function must be called in the release of a resource when ref == 0,
7802 * the contents of resource must still be correct,
7803 * any handels to other resource held by the caller must be closed
7804 * (e.g. a texture should release all held surfaces because telling the device that it's been released.)
7805 *****************************************************/
7806 static void WINAPI IWineD3DDeviceImpl_AddResource(IWineD3DDevice *iface, IWineD3DResource *resource){
7807 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
7808 ResourceList* resourceList;
7810 TRACE("(%p) : resource %p\n", This, resource);
7812 EnterCriticalSection(&resourceStoreCriticalSection);
7814 /* add a new texture to the frot of the linked list */
7815 resourceList = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(ResourceList));
7816 resourceList->resource = resource;
7818 /* Get the old head */
7819 resourceList->next = This->resources;
7821 This->resources = resourceList;
7822 TRACE("Added resource %p with element %p pointing to %p\n", resource, resourceList, resourceList->next);
7825 LeaveCriticalSection(&resourceStoreCriticalSection);
7830 static void WINAPI IWineD3DDeviceImpl_RemoveResource(IWineD3DDevice *iface, IWineD3DResource *resource){
7831 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
7832 ResourceList* resourceList = NULL;
7833 ResourceList* previousResourceList = NULL;
7835 TRACE("(%p) : resource %p\n", This, resource);
7838 EnterCriticalSection(&resourceStoreCriticalSection);
7840 resourceList = This->resources;
7842 while (resourceList != NULL) {
7843 if(resourceList->resource == resource) break;
7844 previousResourceList = resourceList;
7845 resourceList = resourceList->next;
7848 if (resourceList == NULL) {
7849 FIXME("Attempted to remove resource %p that hasn't been stored\n", resource);
7851 LeaveCriticalSection(&resourceStoreCriticalSection);
7855 TRACE("Found resource %p with element %p pointing to %p (previous %p)\n", resourceList->resource, resourceList, resourceList->next, previousResourceList);
7857 /* make sure we don't leave a hole in the list */
7858 if (previousResourceList != NULL) {
7859 previousResourceList->next = resourceList->next;
7861 This->resources = resourceList->next;
7865 LeaveCriticalSection(&resourceStoreCriticalSection);
7871 static void WINAPI IWineD3DDeviceImpl_ResourceReleased(IWineD3DDevice *iface, IWineD3DResource *resource){
7872 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *) iface;
7875 TRACE("(%p) : resource %p\n", This, resource);
7876 switch(IWineD3DResource_GetType(resource)){
7877 case WINED3DRTYPE_SURFACE:
7878 /* TODO: check front and back buffers, rendertargets etc.. possibly swapchains? */
7880 case WINED3DRTYPE_TEXTURE:
7881 case WINED3DRTYPE_CUBETEXTURE:
7882 case WINED3DRTYPE_VOLUMETEXTURE:
7883 for (counter = 0; counter < GL_LIMITS(sampler_stages); counter++) {
7884 if (This->stateBlock != NULL && This->stateBlock->textures[counter] == (IWineD3DBaseTexture *)resource) {
7885 WARN("Texture being released is still by a stateblock, Stage = %u Texture = %p\n", counter, resource);
7886 This->stateBlock->textures[counter] = NULL;
7888 if (This->updateStateBlock != This->stateBlock ){
7889 if (This->updateStateBlock->textures[counter] == (IWineD3DBaseTexture *)resource) {
7890 WARN("Texture being released is still by a stateblock, Stage = %u Texture = %p\n", counter, resource);
7891 This->updateStateBlock->textures[counter] = NULL;
7896 case WINED3DRTYPE_VOLUME:
7897 /* TODO: nothing really? */
7899 case WINED3DRTYPE_VERTEXBUFFER:
7900 /* MSDN: When an application no longer holds a references to this interface, the interface will automatically be freed. */
7903 TRACE("Cleaning up stream pointers\n");
7905 for(streamNumber = 0; streamNumber < MAX_STREAMS; streamNumber ++){
7906 /* FINDOUT: should a warn be generated if were recording and updateStateBlock->streamSource is lost?
7907 FINDOUT: should changes.streamSource[StreamNumber] be set ?
7909 if (This->updateStateBlock != NULL ) { /* ==NULL when device is being destroyed */
7910 if ((IWineD3DResource *)This->updateStateBlock->streamSource[streamNumber] == resource) {
7911 FIXME("Vertex buffer released whlst bound to a state block stream %d\n", streamNumber);
7912 This->updateStateBlock->streamSource[streamNumber] = 0;
7913 /* Set changed flag? */
7916 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) */
7917 if ((IWineD3DResource *)This->stateBlock->streamSource[streamNumber] == resource) {
7918 TRACE("Vertex buffer released whlst bound to a state block stream %d\n", streamNumber);
7919 This->stateBlock->streamSource[streamNumber] = 0;
7922 #if 0 /* TODO: Manage internal tracking properly so that 'this shouldn't happen' */
7923 else { /* This shouldn't happen */
7924 FIXME("Calling application has released the device before relasing all the resources bound to the device\n");
7931 case WINED3DRTYPE_INDEXBUFFER:
7932 /* MSDN: When an application no longer holds a references to this interface, the interface will automatically be freed.*/
7933 if (This->updateStateBlock != NULL ) { /* ==NULL when device is being destroyed */
7934 if (This->updateStateBlock->pIndexData == (IWineD3DIndexBuffer *)resource) {
7935 This->updateStateBlock->pIndexData = NULL;
7938 if (This->stateBlock != NULL ) { /* ==NULL when device is being destroyed */
7939 if (This->stateBlock->pIndexData == (IWineD3DIndexBuffer *)resource) {
7940 This->stateBlock->pIndexData = NULL;
7946 FIXME("(%p) unknown resource type %p %u\n", This, resource, IWineD3DResource_GetType(resource));
7951 /* Remove the resoruce from the resourceStore */
7952 IWineD3DDeviceImpl_RemoveResource(iface, resource);
7954 TRACE("Resource released\n");
7958 /**********************************************************
7959 * IWineD3DDevice VTbl follows
7960 **********************************************************/
7962 const IWineD3DDeviceVtbl IWineD3DDevice_Vtbl =
7964 /*** IUnknown methods ***/
7965 IWineD3DDeviceImpl_QueryInterface,
7966 IWineD3DDeviceImpl_AddRef,
7967 IWineD3DDeviceImpl_Release,
7968 /*** IWineD3DDevice methods ***/
7969 IWineD3DDeviceImpl_GetParent,
7970 /*** Creation methods**/
7971 IWineD3DDeviceImpl_CreateVertexBuffer,
7972 IWineD3DDeviceImpl_CreateIndexBuffer,
7973 IWineD3DDeviceImpl_CreateStateBlock,
7974 IWineD3DDeviceImpl_CreateSurface,
7975 IWineD3DDeviceImpl_CreateTexture,
7976 IWineD3DDeviceImpl_CreateVolumeTexture,
7977 IWineD3DDeviceImpl_CreateVolume,
7978 IWineD3DDeviceImpl_CreateCubeTexture,
7979 IWineD3DDeviceImpl_CreateQuery,
7980 IWineD3DDeviceImpl_CreateAdditionalSwapChain,
7981 IWineD3DDeviceImpl_CreateVertexDeclaration,
7982 IWineD3DDeviceImpl_CreateVertexShader,
7983 IWineD3DDeviceImpl_CreatePixelShader,
7984 IWineD3DDeviceImpl_CreatePalette,
7985 /*** Odd functions **/
7986 IWineD3DDeviceImpl_Init3D,
7987 IWineD3DDeviceImpl_Uninit3D,
7988 IWineD3DDeviceImpl_SetFullscreen,
7989 IWineD3DDeviceImpl_EnumDisplayModes,
7990 IWineD3DDeviceImpl_EvictManagedResources,
7991 IWineD3DDeviceImpl_GetAvailableTextureMem,
7992 IWineD3DDeviceImpl_GetBackBuffer,
7993 IWineD3DDeviceImpl_GetCreationParameters,
7994 IWineD3DDeviceImpl_GetDeviceCaps,
7995 IWineD3DDeviceImpl_GetDirect3D,
7996 IWineD3DDeviceImpl_GetDisplayMode,
7997 IWineD3DDeviceImpl_SetDisplayMode,
7998 IWineD3DDeviceImpl_GetHWND,
7999 IWineD3DDeviceImpl_SetHWND,
8000 IWineD3DDeviceImpl_GetNumberOfSwapChains,
8001 IWineD3DDeviceImpl_GetRasterStatus,
8002 IWineD3DDeviceImpl_GetSwapChain,
8003 IWineD3DDeviceImpl_Reset,
8004 IWineD3DDeviceImpl_SetDialogBoxMode,
8005 IWineD3DDeviceImpl_SetCursorProperties,
8006 IWineD3DDeviceImpl_SetCursorPosition,
8007 IWineD3DDeviceImpl_ShowCursor,
8008 IWineD3DDeviceImpl_TestCooperativeLevel,
8009 /*** Getters and setters **/
8010 IWineD3DDeviceImpl_SetClipPlane,
8011 IWineD3DDeviceImpl_GetClipPlane,
8012 IWineD3DDeviceImpl_SetClipStatus,
8013 IWineD3DDeviceImpl_GetClipStatus,
8014 IWineD3DDeviceImpl_SetCurrentTexturePalette,
8015 IWineD3DDeviceImpl_GetCurrentTexturePalette,
8016 IWineD3DDeviceImpl_SetDepthStencilSurface,
8017 IWineD3DDeviceImpl_GetDepthStencilSurface,
8018 IWineD3DDeviceImpl_SetFVF,
8019 IWineD3DDeviceImpl_GetFVF,
8020 IWineD3DDeviceImpl_SetGammaRamp,
8021 IWineD3DDeviceImpl_GetGammaRamp,
8022 IWineD3DDeviceImpl_SetIndices,
8023 IWineD3DDeviceImpl_GetIndices,
8024 IWineD3DDeviceImpl_SetLight,
8025 IWineD3DDeviceImpl_GetLight,
8026 IWineD3DDeviceImpl_SetLightEnable,
8027 IWineD3DDeviceImpl_GetLightEnable,
8028 IWineD3DDeviceImpl_SetMaterial,
8029 IWineD3DDeviceImpl_GetMaterial,
8030 IWineD3DDeviceImpl_SetNPatchMode,
8031 IWineD3DDeviceImpl_GetNPatchMode,
8032 IWineD3DDeviceImpl_SetPaletteEntries,
8033 IWineD3DDeviceImpl_GetPaletteEntries,
8034 IWineD3DDeviceImpl_SetPixelShader,
8035 IWineD3DDeviceImpl_GetPixelShader,
8036 IWineD3DDeviceImpl_SetPixelShaderConstantB,
8037 IWineD3DDeviceImpl_GetPixelShaderConstantB,
8038 IWineD3DDeviceImpl_SetPixelShaderConstantI,
8039 IWineD3DDeviceImpl_GetPixelShaderConstantI,
8040 IWineD3DDeviceImpl_SetPixelShaderConstantF,
8041 IWineD3DDeviceImpl_GetPixelShaderConstantF,
8042 IWineD3DDeviceImpl_SetRenderState,
8043 IWineD3DDeviceImpl_GetRenderState,
8044 IWineD3DDeviceImpl_SetRenderTarget,
8045 IWineD3DDeviceImpl_GetRenderTarget,
8046 IWineD3DDeviceImpl_SetFrontBackBuffers,
8047 IWineD3DDeviceImpl_SetSamplerState,
8048 IWineD3DDeviceImpl_GetSamplerState,
8049 IWineD3DDeviceImpl_SetScissorRect,
8050 IWineD3DDeviceImpl_GetScissorRect,
8051 IWineD3DDeviceImpl_SetSoftwareVertexProcessing,
8052 IWineD3DDeviceImpl_GetSoftwareVertexProcessing,
8053 IWineD3DDeviceImpl_SetStreamSource,
8054 IWineD3DDeviceImpl_GetStreamSource,
8055 IWineD3DDeviceImpl_SetStreamSourceFreq,
8056 IWineD3DDeviceImpl_GetStreamSourceFreq,
8057 IWineD3DDeviceImpl_SetTexture,
8058 IWineD3DDeviceImpl_GetTexture,
8059 IWineD3DDeviceImpl_SetTextureStageState,
8060 IWineD3DDeviceImpl_GetTextureStageState,
8061 IWineD3DDeviceImpl_SetTransform,
8062 IWineD3DDeviceImpl_GetTransform,
8063 IWineD3DDeviceImpl_SetVertexDeclaration,
8064 IWineD3DDeviceImpl_GetVertexDeclaration,
8065 IWineD3DDeviceImpl_SetVertexShader,
8066 IWineD3DDeviceImpl_GetVertexShader,
8067 IWineD3DDeviceImpl_SetVertexShaderConstantB,
8068 IWineD3DDeviceImpl_GetVertexShaderConstantB,
8069 IWineD3DDeviceImpl_SetVertexShaderConstantI,
8070 IWineD3DDeviceImpl_GetVertexShaderConstantI,
8071 IWineD3DDeviceImpl_SetVertexShaderConstantF,
8072 IWineD3DDeviceImpl_GetVertexShaderConstantF,
8073 IWineD3DDeviceImpl_SetViewport,
8074 IWineD3DDeviceImpl_GetViewport,
8075 IWineD3DDeviceImpl_MultiplyTransform,
8076 IWineD3DDeviceImpl_ValidateDevice,
8077 IWineD3DDeviceImpl_ProcessVertices,
8078 /*** State block ***/
8079 IWineD3DDeviceImpl_BeginStateBlock,
8080 IWineD3DDeviceImpl_EndStateBlock,
8081 /*** Scene management ***/
8082 IWineD3DDeviceImpl_BeginScene,
8083 IWineD3DDeviceImpl_EndScene,
8084 IWineD3DDeviceImpl_Present,
8085 IWineD3DDeviceImpl_Clear,
8087 IWineD3DDeviceImpl_DrawPrimitive,
8088 IWineD3DDeviceImpl_DrawIndexedPrimitive,
8089 IWineD3DDeviceImpl_DrawPrimitiveUP,
8090 IWineD3DDeviceImpl_DrawIndexedPrimitiveUP,
8091 IWineD3DDeviceImpl_DrawPrimitiveStrided,
8092 IWineD3DDeviceImpl_DrawRectPatch,
8093 IWineD3DDeviceImpl_DrawTriPatch,
8094 IWineD3DDeviceImpl_DeletePatch,
8095 IWineD3DDeviceImpl_ColorFill,
8096 IWineD3DDeviceImpl_UpdateTexture,
8097 IWineD3DDeviceImpl_UpdateSurface,
8098 IWineD3DDeviceImpl_CopyRects,
8099 IWineD3DDeviceImpl_StretchRect,
8100 IWineD3DDeviceImpl_GetRenderTargetData,
8101 IWineD3DDeviceImpl_GetFrontBufferData,
8102 /*** Internal use IWineD3DDevice methods ***/
8103 IWineD3DDeviceImpl_SetupTextureStates,
8104 /*** object tracking ***/
8105 IWineD3DDeviceImpl_ResourceReleased
8109 const DWORD SavedPixelStates_R[NUM_SAVEDPIXELSTATES_R] = {
8110 WINED3DRS_ALPHABLENDENABLE ,
8111 WINED3DRS_ALPHAFUNC ,
8112 WINED3DRS_ALPHAREF ,
8113 WINED3DRS_ALPHATESTENABLE ,
8115 WINED3DRS_COLORWRITEENABLE ,
8116 WINED3DRS_DESTBLEND ,
8117 WINED3DRS_DITHERENABLE ,
8118 WINED3DRS_FILLMODE ,
8119 WINED3DRS_FOGDENSITY ,
8121 WINED3DRS_FOGSTART ,
8122 WINED3DRS_LASTPIXEL ,
8123 WINED3DRS_SHADEMODE ,
8124 WINED3DRS_SRCBLEND ,
8125 WINED3DRS_STENCILENABLE ,
8126 WINED3DRS_STENCILFAIL ,
8127 WINED3DRS_STENCILFUNC ,
8128 WINED3DRS_STENCILMASK ,
8129 WINED3DRS_STENCILPASS ,
8130 WINED3DRS_STENCILREF ,
8131 WINED3DRS_STENCILWRITEMASK ,
8132 WINED3DRS_STENCILZFAIL ,
8133 WINED3DRS_TEXTUREFACTOR ,
8144 WINED3DRS_ZWRITEENABLE
8147 const DWORD SavedPixelStates_T[NUM_SAVEDPIXELSTATES_T] = {
8148 WINED3DTSS_ADDRESSW ,
8149 WINED3DTSS_ALPHAARG0 ,
8150 WINED3DTSS_ALPHAARG1 ,
8151 WINED3DTSS_ALPHAARG2 ,
8152 WINED3DTSS_ALPHAOP ,
8153 WINED3DTSS_BUMPENVLOFFSET ,
8154 WINED3DTSS_BUMPENVLSCALE ,
8155 WINED3DTSS_BUMPENVMAT00 ,
8156 WINED3DTSS_BUMPENVMAT01 ,
8157 WINED3DTSS_BUMPENVMAT10 ,
8158 WINED3DTSS_BUMPENVMAT11 ,
8159 WINED3DTSS_COLORARG0 ,
8160 WINED3DTSS_COLORARG1 ,
8161 WINED3DTSS_COLORARG2 ,
8162 WINED3DTSS_COLOROP ,
8163 WINED3DTSS_RESULTARG ,
8164 WINED3DTSS_TEXCOORDINDEX ,
8165 WINED3DTSS_TEXTURETRANSFORMFLAGS
8168 const DWORD SavedPixelStates_S[NUM_SAVEDPIXELSTATES_S] = {
8169 WINED3DSAMP_ADDRESSU ,
8170 WINED3DSAMP_ADDRESSV ,
8171 WINED3DSAMP_ADDRESSW ,
8172 WINED3DSAMP_BORDERCOLOR ,
8173 WINED3DSAMP_MAGFILTER ,
8174 WINED3DSAMP_MINFILTER ,
8175 WINED3DSAMP_MIPFILTER ,
8176 WINED3DSAMP_MIPMAPLODBIAS ,
8177 WINED3DSAMP_MAXMIPLEVEL ,
8178 WINED3DSAMP_MAXANISOTROPY ,
8179 WINED3DSAMP_SRGBTEXTURE ,
8180 WINED3DSAMP_ELEMENTINDEX
8183 const DWORD SavedVertexStates_R[NUM_SAVEDVERTEXSTATES_R] = {
8185 WINED3DRS_AMBIENTMATERIALSOURCE ,
8186 WINED3DRS_CLIPPING ,
8187 WINED3DRS_CLIPPLANEENABLE ,
8188 WINED3DRS_COLORVERTEX ,
8189 WINED3DRS_DIFFUSEMATERIALSOURCE ,
8190 WINED3DRS_EMISSIVEMATERIALSOURCE ,
8191 WINED3DRS_FOGDENSITY ,
8193 WINED3DRS_FOGSTART ,
8194 WINED3DRS_FOGTABLEMODE ,
8195 WINED3DRS_FOGVERTEXMODE ,
8196 WINED3DRS_INDEXEDVERTEXBLENDENABLE ,
8197 WINED3DRS_LIGHTING ,
8198 WINED3DRS_LOCALVIEWER ,
8199 WINED3DRS_MULTISAMPLEANTIALIAS ,
8200 WINED3DRS_MULTISAMPLEMASK ,
8201 WINED3DRS_NORMALIZENORMALS ,
8202 WINED3DRS_PATCHEDGESTYLE ,
8203 WINED3DRS_POINTSCALE_A ,
8204 WINED3DRS_POINTSCALE_B ,
8205 WINED3DRS_POINTSCALE_C ,
8206 WINED3DRS_POINTSCALEENABLE ,
8207 WINED3DRS_POINTSIZE ,
8208 WINED3DRS_POINTSIZE_MAX ,
8209 WINED3DRS_POINTSIZE_MIN ,
8210 WINED3DRS_POINTSPRITEENABLE ,
8211 WINED3DRS_RANGEFOGENABLE ,
8212 WINED3DRS_SPECULARMATERIALSOURCE ,
8213 WINED3DRS_TWEENFACTOR ,
8214 WINED3DRS_VERTEXBLEND
8217 const DWORD SavedVertexStates_T[NUM_SAVEDVERTEXSTATES_T] = {
8218 WINED3DTSS_TEXCOORDINDEX ,
8219 WINED3DTSS_TEXTURETRANSFORMFLAGS
8222 const DWORD SavedVertexStates_S[NUM_SAVEDVERTEXSTATES_S] = {
8223 WINED3DSAMP_DMAPOFFSET