2 * IWineD3DDevice implementation
4 * Copyright 2002 Lionel Ulmer
5 * Copyright 2002-2005 Jason Edmeades
6 * Copyright 2003-2004 Raphael Junqueira
7 * Copyright 2004 Christian Costa
8 * Copyright 2005 Oliver Stieber
9 * Copyright 2006 Stefan Dösinger for CodeWeavers
10 * Copyright 2006 Henri Verbeet
12 * This library is free software; you can redistribute it and/or
13 * modify it under the terms of the GNU Lesser General Public
14 * License as published by the Free Software Foundation; either
15 * version 2.1 of the License, or (at your option) any later version.
17 * This library is distributed in the hope that it will be useful,
18 * but WITHOUT ANY WARRANTY; without even the implied warranty of
19 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
20 * Lesser General Public License for more details.
22 * You should have received a copy of the GNU Lesser General Public
23 * License along with this library; if not, write to the Free Software
24 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
32 #include "wined3d_private.h"
34 WINE_DEFAULT_DEBUG_CHANNEL(d3d);
35 WINE_DECLARE_DEBUG_CHANNEL(d3d_shader);
36 #define GLINFO_LOCATION ((IWineD3DImpl *)(This->wineD3D))->gl_info
38 /* Define the default light parameters as specified by MSDN */
39 const WINED3DLIGHT WINED3D_default_light = {
41 D3DLIGHT_DIRECTIONAL, /* Type */
42 { 1.0, 1.0, 1.0, 0.0 }, /* Diffuse r,g,b,a */
43 { 0.0, 0.0, 0.0, 0.0 }, /* Specular r,g,b,a */
44 { 0.0, 0.0, 0.0, 0.0 }, /* Ambient r,g,b,a, */
45 { 0.0, 0.0, 0.0 }, /* Position x,y,z */
46 { 0.0, 0.0, 1.0 }, /* Direction x,y,z */
49 0.0, 0.0, 0.0, /* Attenuation 0,1,2 */
54 /* x11drv GDI escapes */
55 #define X11DRV_ESCAPE 6789
56 enum x11drv_escape_codes
58 X11DRV_GET_DISPLAY, /* get X11 display for a DC */
59 X11DRV_GET_DRAWABLE, /* get current drawable for a DC */
60 X11DRV_GET_FONT, /* get current X font for a DC */
63 /* retrieve the X display to use on a given DC */
64 inline static Display *get_display( HDC hdc )
67 enum x11drv_escape_codes escape = X11DRV_GET_DISPLAY;
69 if (!ExtEscape( hdc, X11DRV_ESCAPE, sizeof(escape), (LPCSTR)&escape,
70 sizeof(display), (LPSTR)&display )) display = NULL;
74 /* TODO: setup some flags in the regestry to enable, disable pbuffer support */
75 /* enable pbuffer support for offscreen textures */
76 BOOL pbuffer_support = FALSE;
77 /* allocate one pbuffer per surface */
78 BOOL pbuffer_per_surface = FALSE;
80 /* static function declarations */
81 static void WINAPI IWineD3DDeviceImpl_AddResource(IWineD3DDevice *iface, IWineD3DResource *resource);
83 static void WINAPI IWineD3DDeviceImpl_ApplyTextureUnitState(IWineD3DDevice *iface, DWORD Stage, WINED3DTEXTURESTAGESTATETYPE Type);
86 #define D3DMEMCHECK(object, ppResult) if(NULL == object) { *ppResult = NULL; WARN("Out of memory\n"); return WINED3DERR_OUTOFVIDEOMEMORY;}
88 #define D3DCREATEOBJECTINSTANCE(object, type) { \
89 object=HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(IWineD3D##type##Impl)); \
90 D3DMEMCHECK(object, pp##type); \
91 object->lpVtbl = &IWineD3D##type##_Vtbl; \
92 object->wineD3DDevice = This; \
93 object->parent = parent; \
95 *pp##type = (IWineD3D##type *) object; \
98 #define D3DCREATERESOURCEOBJECTINSTANCE(object, type, d3dtype, _size){ \
99 object=HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(IWineD3D##type##Impl)); \
100 D3DMEMCHECK(object, pp##type); \
101 object->lpVtbl = &IWineD3D##type##_Vtbl; \
102 object->resource.wineD3DDevice = This; \
103 object->resource.parent = parent; \
104 object->resource.resourceType = d3dtype; \
105 object->resource.ref = 1; \
106 object->resource.pool = Pool; \
107 object->resource.format = Format; \
108 object->resource.usage = Usage; \
109 object->resource.size = _size; \
110 /* Check that we have enough video ram left */ \
111 if (Pool == WINED3DPOOL_DEFAULT) { \
112 if (IWineD3DDevice_GetAvailableTextureMem(iface) <= _size) { \
113 WARN("Out of 'bogus' video memory\n"); \
114 HeapFree(GetProcessHeap(), 0, object); \
116 return WINED3DERR_OUTOFVIDEOMEMORY; \
118 globalChangeGlRam(_size); \
120 object->resource.allocatedMemory = (0 == _size ? NULL : Pool == WINED3DPOOL_DEFAULT ? NULL : HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, _size)); \
121 if (object->resource.allocatedMemory == NULL && _size != 0 && Pool != WINED3DPOOL_DEFAULT) { \
122 FIXME("Out of memory!\n"); \
123 HeapFree(GetProcessHeap(), 0, object); \
125 return WINED3DERR_OUTOFVIDEOMEMORY; \
127 *pp##type = (IWineD3D##type *) object; \
128 IWineD3DDeviceImpl_AddResource(iface, (IWineD3DResource *)object) ;\
129 TRACE("(%p) : Created resource %p\n", This, object); \
132 #define D3DINITIALIZEBASETEXTURE(_basetexture) { \
133 _basetexture.levels = Levels; \
134 _basetexture.filterType = (Usage & WINED3DUSAGE_AUTOGENMIPMAP) ? WINED3DTEXF_LINEAR : WINED3DTEXF_NONE; \
135 _basetexture.LOD = 0; \
136 _basetexture.dirty = TRUE; \
139 /**********************************************************
140 * Global variable / Constants follow
141 **********************************************************/
142 const float identity[16] = {1,0,0,0, 0,1,0,0, 0,0,1,0, 0,0,0,1}; /* When needed for comparisons */
144 /**********************************************************
145 * Utility functions follow
146 **********************************************************/
147 /* Convert the D3DLIGHT properties into equivalent gl lights */
148 static void setup_light(IWineD3DDevice *iface, LONG Index, PLIGHTINFOEL *lightInfo) {
151 float colRGBA[] = {0.0, 0.0, 0.0, 0.0};
152 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
154 /* Light settings are affected by the model view in OpenGL, the View transform in direct3d*/
155 glMatrixMode(GL_MODELVIEW);
157 glLoadMatrixf((float *)&This->stateBlock->transforms[WINED3DTS_VIEW].u.m[0][0]);
160 colRGBA[0] = lightInfo->OriginalParms.Diffuse.r;
161 colRGBA[1] = lightInfo->OriginalParms.Diffuse.g;
162 colRGBA[2] = lightInfo->OriginalParms.Diffuse.b;
163 colRGBA[3] = lightInfo->OriginalParms.Diffuse.a;
164 glLightfv(GL_LIGHT0+Index, GL_DIFFUSE, colRGBA);
165 checkGLcall("glLightfv");
168 colRGBA[0] = lightInfo->OriginalParms.Specular.r;
169 colRGBA[1] = lightInfo->OriginalParms.Specular.g;
170 colRGBA[2] = lightInfo->OriginalParms.Specular.b;
171 colRGBA[3] = lightInfo->OriginalParms.Specular.a;
172 glLightfv(GL_LIGHT0+Index, GL_SPECULAR, colRGBA);
173 checkGLcall("glLightfv");
176 colRGBA[0] = lightInfo->OriginalParms.Ambient.r;
177 colRGBA[1] = lightInfo->OriginalParms.Ambient.g;
178 colRGBA[2] = lightInfo->OriginalParms.Ambient.b;
179 colRGBA[3] = lightInfo->OriginalParms.Ambient.a;
180 glLightfv(GL_LIGHT0+Index, GL_AMBIENT, colRGBA);
181 checkGLcall("glLightfv");
183 /* Attenuation - Are these right? guessing... */
184 glLightf(GL_LIGHT0+Index, GL_CONSTANT_ATTENUATION, lightInfo->OriginalParms.Attenuation0);
185 checkGLcall("glLightf");
186 glLightf(GL_LIGHT0+Index, GL_LINEAR_ATTENUATION, lightInfo->OriginalParms.Attenuation1);
187 checkGLcall("glLightf");
189 if ((lightInfo->OriginalParms.Range *lightInfo->OriginalParms.Range) >= FLT_MIN) {
190 quad_att = 1.4/(lightInfo->OriginalParms.Range *lightInfo->OriginalParms.Range);
192 quad_att = 0; /* 0 or MAX? (0 seems to be ok) */
195 if (quad_att < lightInfo->OriginalParms.Attenuation2) quad_att = lightInfo->OriginalParms.Attenuation2;
196 glLightf(GL_LIGHT0+Index, GL_QUADRATIC_ATTENUATION, quad_att);
197 checkGLcall("glLightf");
199 switch (lightInfo->OriginalParms.Type) {
202 glLightfv(GL_LIGHT0+Index, GL_POSITION, &lightInfo->lightPosn[0]);
203 checkGLcall("glLightfv");
204 glLightf(GL_LIGHT0 + Index, GL_SPOT_CUTOFF, lightInfo->cutoff);
205 checkGLcall("glLightf");
211 glLightfv(GL_LIGHT0+Index, GL_POSITION, &lightInfo->lightPosn[0]);
212 checkGLcall("glLightfv");
214 glLightfv(GL_LIGHT0+Index, GL_SPOT_DIRECTION, &lightInfo->lightDirn[0]);
215 checkGLcall("glLightfv");
216 glLightf(GL_LIGHT0 + Index, GL_SPOT_EXPONENT, lightInfo->exponent);
217 checkGLcall("glLightf");
218 glLightf(GL_LIGHT0 + Index, GL_SPOT_CUTOFF, lightInfo->cutoff);
219 checkGLcall("glLightf");
223 case D3DLIGHT_DIRECTIONAL:
225 glLightfv(GL_LIGHT0+Index, GL_POSITION, &lightInfo->lightPosn[0]); /* Note gl uses w position of 0 for direction! */
226 checkGLcall("glLightfv");
227 glLightf(GL_LIGHT0+Index, GL_SPOT_CUTOFF, lightInfo->cutoff);
228 checkGLcall("glLightf");
229 glLightf(GL_LIGHT0+Index, GL_SPOT_EXPONENT, 0.0f);
230 checkGLcall("glLightf");
234 FIXME("Unrecognized light type %d\n", lightInfo->OriginalParms.Type);
237 /* Restore the modelview matrix */
241 /**********************************************************
242 * GLSL helper functions follow
243 **********************************************************/
245 /** Attach a GLSL pixel or vertex shader object to the shader program */
246 static void attach_glsl_shader(IWineD3DDevice *iface, IWineD3DBaseShader* shader) {
248 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
249 GLhandleARB shaderObj = ((IWineD3DBaseShaderImpl*)shader)->baseShader.prgId;
250 if (This->stateBlock->glsl_program && shaderObj != 0) {
251 TRACE_(d3d_shader)("Attaching GLSL shader object %u to program %u\n", shaderObj, This->stateBlock->glsl_program->programId);
252 GL_EXTCALL(glAttachObjectARB(This->stateBlock->glsl_program->programId, shaderObj));
253 checkGLcall("glAttachObjectARB");
257 /** Sets the GLSL program ID for the given pixel and vertex shader combination.
258 * It sets the programId on the current StateBlock (because it should be called
259 * inside of the DrawPrimitive() part of the render loop).
261 * If a program for the given combination does not exist, create one, and store
262 * the program in the list. If it creates a program, it will link the given
265 * We keep the shader programs around on a list because linking
266 * shader objects together is an expensive operation. It's much
267 * faster to loop through a list of pre-compiled & linked programs
268 * each time that the application sets a new pixel or vertex shader
269 * than it is to re-link them together at that time.
271 * The list will be deleted in IWineD3DDevice::Release().
273 void set_glsl_shader_program(IWineD3DDevice *iface) {
275 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
276 IWineD3DPixelShader *pshader = This->stateBlock->pixelShader;
277 IWineD3DVertexShader *vshader = This->stateBlock->vertexShader;
278 struct glsl_shader_prog_link *curLink = NULL;
279 struct glsl_shader_prog_link *newLink = NULL;
280 struct list *ptr = NULL;
281 GLhandleARB programId = 0;
285 ptr = list_head( &This->glsl_shader_progs );
287 /* At least one program exists - see if it matches our ps/vs combination */
288 curLink = LIST_ENTRY( ptr, struct glsl_shader_prog_link, entry );
289 if (vshader == curLink->vertexShader && pshader == curLink->pixelShader) {
290 /* Existing Program found, use it */
291 TRACE_(d3d_shader)("Found existing program (%u) for this vertex/pixel shader combination\n",
293 This->stateBlock->glsl_program = curLink;
296 /* This isn't the entry we need - try the next one */
297 ptr = list_next( &This->glsl_shader_progs, ptr );
300 /* If we get to this point, then no matching program exists, so we create one */
301 programId = GL_EXTCALL(glCreateProgramObjectARB());
302 TRACE_(d3d_shader)("Created new GLSL shader program %u\n", programId);
304 /* Allocate a new link for the list of programs */
305 newLink = HeapAlloc(GetProcessHeap(), 0, sizeof(struct glsl_shader_prog_link));
306 newLink->programId = programId;
307 This->stateBlock->glsl_program = newLink;
309 /* Attach GLSL vshader */
310 if (NULL != vshader && wined3d_settings.vs_selected_mode == SHADER_GLSL) {
312 int max_attribs = 16; /* TODO: Will this always be the case? It is at the moment... */
315 TRACE("Attaching vertex shader to GLSL program\n");
316 attach_glsl_shader(iface, (IWineD3DBaseShader*)vshader);
318 /* Bind vertex attributes to a corresponding index number to match
319 * the same index numbers as ARB_vertex_programs (makes loading
320 * vertex attributes simpler). With this method, we can use the
321 * exact same code to load the attributes later for both ARB and
324 * We have to do this here because we need to know the Program ID
325 * in order to make the bindings work, and it has to be done prior
326 * to linking the GLSL program. */
327 for (i = 0; i < max_attribs; ++i) {
328 snprintf(tmp_name, sizeof(tmp_name), "attrib%i", i);
329 GL_EXTCALL(glBindAttribLocationARB(programId, i, tmp_name));
331 checkGLcall("glBindAttribLocationARB");
332 newLink->vertexShader = vshader;
335 /* Attach GLSL pshader */
336 if (NULL != pshader && wined3d_settings.ps_selected_mode == SHADER_GLSL) {
337 TRACE("Attaching pixel shader to GLSL program\n");
338 attach_glsl_shader(iface, (IWineD3DBaseShader*)pshader);
339 newLink->pixelShader = pshader;
342 /* Link the program */
343 TRACE_(d3d_shader)("Linking GLSL shader program %u\n", programId);
344 GL_EXTCALL(glLinkProgramARB(programId));
345 print_glsl_info_log(&GLINFO_LOCATION, programId);
346 list_add_head( &This->glsl_shader_progs, &newLink->entry);
348 newLink->vuniformF_locations = HeapAlloc(GetProcessHeap(), 0, sizeof(GLhandleARB) * GL_LIMITS(vshader_constantsF));
349 for (i = 0; i < GL_LIMITS(vshader_constantsF); ++i) {
350 snprintf(glsl_name, sizeof(glsl_name), "VC[%i]", i);
351 newLink->vuniformF_locations[i] = GL_EXTCALL(glGetUniformLocationARB(programId, glsl_name));
353 newLink->puniformF_locations = HeapAlloc(GetProcessHeap(), 0, sizeof(GLhandleARB) * GL_LIMITS(pshader_constantsF));
354 for (i = 0; i < GL_LIMITS(pshader_constantsF); ++i) {
355 snprintf(glsl_name, sizeof(glsl_name), "PC[%i]", i);
356 newLink->puniformF_locations[i] = GL_EXTCALL(glGetUniformLocationARB(programId, glsl_name));
362 /** Detach the GLSL pixel or vertex shader object from the shader program */
363 static void detach_glsl_shader(IWineD3DDevice *iface, GLhandleARB shaderObj, GLhandleARB programId) {
365 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
367 if (shaderObj != 0 && programId != 0) {
368 TRACE_(d3d_shader)("Detaching GLSL shader object %u from program %u\n", shaderObj, programId);
369 GL_EXTCALL(glDetachObjectARB(programId, shaderObj));
370 checkGLcall("glDetachObjectARB");
374 /** Delete a GLSL shader program */
375 static void delete_glsl_shader_program(IWineD3DDevice *iface, GLhandleARB obj) {
377 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
380 TRACE_(d3d_shader)("Deleting GLSL shader program %u\n", obj);
381 GL_EXTCALL(glDeleteObjectARB(obj));
382 checkGLcall("glDeleteObjectARB");
386 /** Delete the list of linked programs this shader is associated with.
387 * Also at this point, check to see if there are any objects left attached
388 * to each GLSL program. If not, delete the GLSL program object.
389 * This will be run when a device is released. */
390 static void delete_glsl_shader_list(IWineD3DDevice* iface) {
392 struct list *ptr = NULL;
393 struct glsl_shader_prog_link *curLink = NULL;
394 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
398 GLhandleARB objList[2]; /* There should never be more than 2 objects attached
399 (one pixel shader and one vertex shader at most) */
401 ptr = list_head( &This->glsl_shader_progs );
403 /* First, get the current item,
404 * save the link to the next pointer,
405 * detach and delete shader objects,
406 * then de-allocate the list item's memory */
407 curLink = LIST_ENTRY( ptr, struct glsl_shader_prog_link, entry );
408 ptr = list_next( &This->glsl_shader_progs, ptr );
410 /* See if this object is still attached to the program - it may have been detached already */
411 GL_EXTCALL(glGetAttachedObjectsARB(curLink->programId, 2, &numAttached, objList));
412 TRACE_(d3d_shader)("%i GLSL objects are currently attached to program %u\n", numAttached, curLink->programId);
413 for (i = 0; i < numAttached; i++) {
414 detach_glsl_shader(iface, objList[i], curLink->programId);
417 delete_glsl_shader_program(iface, curLink->programId);
419 /* Free the uniform locations */
420 HeapFree(GetProcessHeap(), 0, curLink->vuniformF_locations);
421 HeapFree(GetProcessHeap(), 0, curLink->puniformF_locations);
423 /* Free the memory for this list item */
424 HeapFree(GetProcessHeap(), 0, curLink);
429 /* Apply the current values to the specified texture stage */
430 static void WINAPI IWineD3DDeviceImpl_SetupTextureStates(IWineD3DDevice *iface, DWORD Sampler, DWORD texture_idx, DWORD Flags) {
431 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
439 /* In addition, IDirect3DDevice9::SetSamplerState will now be used for filtering, tiling,
440 clamping, MIPLOD, etc. This will work for up to 16 samplers.
443 if (Sampler >= GL_LIMITS(sampler_stages)) {
444 FIXME("Trying to set the state of more samplers %ld than are supported %d by this openGL implementation\n", Sampler, GL_LIMITS(sampler_stages));
447 VTRACE(("Activating appropriate texture state %ld\n", Sampler));
448 if (GL_SUPPORT(ARB_MULTITEXTURE)) {
450 GL_EXTCALL(glActiveTextureARB(GL_TEXTURE0_ARB + texture_idx));
451 checkGLcall("glActiveTextureARB");
453 /* Could we use bindTexture and then apply the states instead of GLACTIVETEXTURE */
454 } else if (Sampler > 0) {
455 FIXME("Program using multiple concurrent textures which this opengl implementation doesn't support\n");
459 /* TODO: change this to a lookup table
460 LOOKUP_TEXTURE_STATES lists all texture states that should be applied.
461 LOOKUP_CONTEXT_SATES list all context applicable states that can be applied
462 etc.... it's a lot cleaner, quicker and possibly easier to maintain than running a switch and setting a skip flag...
463 especially when there are a number of groups of states. */
465 TRACE("-----------------------> Updating the texture at Sampler %ld to have new texture state information\n", Sampler);
467 /* The list of states not to apply is a big as the list of states to apply, so it makes sense to produce an inclusive list */
468 #define APPLY_STATE(_state) IWineD3DDeviceImpl_ApplyTextureUnitState(iface, Sampler, _state)
469 /* these are the only two supported states that need to be applied */
470 APPLY_STATE(WINED3DTSS_TEXCOORDINDEX);
471 APPLY_STATE(WINED3DTSS_TEXTURETRANSFORMFLAGS);
472 #if 0 /* not supported at the moment */
473 APPLY_STATE(WINED3DTSS_BUMPENVMAT00);
474 APPLY_STATE(WINED3DTSS_BUMPENVMAT01);
475 APPLY_STATE(WINED3DTSS_BUMPENVMAT10);
476 APPLY_STATE(WINED3DTSS_BUMPENVMAT11);
477 APPLY_STATE(WINED3DTSS_BUMPENVLSCALE);
478 APPLY_STATE(WINED3DTSS_BUMPENVLOFFSET);
479 APPLY_STATE(WINED3DTSS_RESULTARG);
480 APPLY_STATE(WINED3DTSS_CONSTANT);
482 /* a quick sanity check in case someone forgot to update this function */
483 if (WINED3D_HIGHEST_TEXTURE_STATE > WINED3DTSS_CONSTANT) {
484 FIXME("(%p) : There are more texture states than expected, update device.c to match\n", This);
488 /* apply any sampler states that always need applying */
489 if (GL_SUPPORT(EXT_TEXTURE_LOD_BIAS)) {
490 tmpvalue.d = This->stateBlock->samplerState[Sampler][WINED3DSAMP_MIPMAPLODBIAS];
491 glTexEnvf(GL_TEXTURE_FILTER_CONTROL_EXT,
492 GL_TEXTURE_LOD_BIAS_EXT,
494 checkGLcall("glTexEnvi GL_TEXTURE_LOD_BIAS_EXT ...");
497 D3DCOLORTOGLFLOAT4(This->stateBlock->renderState[WINED3DRS_TEXTUREFACTOR], col);
498 glTexEnvfv(GL_TEXTURE_ENV, GL_TEXTURE_ENV_COLOR, &col[0]);
499 checkGLcall("glTexEnvfv(GL_TEXTURE_ENV, GL_TEXTURE_ENV_COLOR, color);");
501 /* TODO: NV_POINT_SPRITE */
502 if (GL_SUPPORT(ARB_POINT_SPRITE)) {
503 if (This->stateBlock->renderState[WINED3DRS_POINTSPRITEENABLE] != FALSE) {
504 /* Doesn't work with GL_POINT_SMOOTH on on my ATI 9600, but then ATI drivers are buggered! */
505 glDisable(GL_POINT_SMOOTH);
507 /* Centre the texture on the vertex */
508 VTRACE(("glTexEnvf( GL_POINT_SPRITE_ARB, GL_COORD_REPLACE_ARB, GL_TRUE)\n"));
509 glTexEnvf( GL_POINT_SPRITE_ARB, GL_COORD_REPLACE_ARB, GL_TRUE);
511 VTRACE(("glTexEnvf( GL_POINT_SPRITE_ARB, GL_COORD_REPLACE_ARB, GL_TRUE)\n"));
512 glTexEnvf( GL_POINT_SPRITE_ARB, GL_COORD_REPLACE_ARB, GL_TRUE);
513 checkGLcall("glTexEnvf(...)");
514 VTRACE(("glEnable( GL_POINT_SPRITE_ARB )\n"));
515 glEnable( GL_POINT_SPRITE_ARB );
516 checkGLcall("glEnable(...)");
518 VTRACE(("glDisable( GL_POINT_SPRITE_ARB )\n"));
519 glDisable( GL_POINT_SPRITE_ARB );
520 checkGLcall("glEnable(...)");
524 TRACE("-----------------------> Updated the texture at Sampler %ld to have new texture state information\n", Sampler);
527 /**********************************************************
528 * IUnknown parts follows
529 **********************************************************/
531 static HRESULT WINAPI IWineD3DDeviceImpl_QueryInterface(IWineD3DDevice *iface,REFIID riid,LPVOID *ppobj)
533 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
535 TRACE("(%p)->(%s,%p)\n",This,debugstr_guid(riid),ppobj);
536 if (IsEqualGUID(riid, &IID_IUnknown)
537 || IsEqualGUID(riid, &IID_IWineD3DBase)
538 || IsEqualGUID(riid, &IID_IWineD3DDevice)) {
539 IUnknown_AddRef(iface);
544 return E_NOINTERFACE;
547 static ULONG WINAPI IWineD3DDeviceImpl_AddRef(IWineD3DDevice *iface) {
548 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
549 ULONG refCount = InterlockedIncrement(&This->ref);
551 TRACE("(%p) : AddRef increasing from %ld\n", This, refCount - 1);
555 static ULONG WINAPI IWineD3DDeviceImpl_Release(IWineD3DDevice *iface) {
556 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
557 ULONG refCount = InterlockedDecrement(&This->ref);
559 TRACE("(%p) : Releasing from %ld\n", This, refCount + 1);
562 /* TODO: Clean up all the surfaces and textures! */
563 /* NOTE: You must release the parent if the object was created via a callback
564 ** ***************************/
566 /* Delete any GLSL shader programs that may exist */
567 if (wined3d_settings.vs_selected_mode == SHADER_GLSL ||
568 wined3d_settings.ps_selected_mode == SHADER_GLSL)
569 delete_glsl_shader_list(iface);
571 /* Release the update stateblock */
572 if(IWineD3DStateBlock_Release((IWineD3DStateBlock *)This->updateStateBlock) > 0){
573 if(This->updateStateBlock != This->stateBlock)
574 FIXME("(%p) Something's still holding the Update stateblock\n",This);
576 This->updateStateBlock = NULL;
577 { /* because were not doing proper internal refcounts releasing the primary state block
578 causes recursion with the extra checks in ResourceReleased, to avoid this we have
579 to set this->stateBlock = NULL; first */
580 IWineD3DStateBlock *stateBlock = (IWineD3DStateBlock *)This->stateBlock;
581 This->stateBlock = NULL;
583 /* Release the stateblock */
584 if(IWineD3DStateBlock_Release(stateBlock) > 0){
585 FIXME("(%p) Something's still holding the Update stateblock\n",This);
589 if (This->resources != NULL ) {
590 FIXME("(%p) Device released with resources still bound, acceptable but unexpected\n", This);
591 dumpResources(This->resources);
595 IWineD3D_Release(This->wineD3D);
596 This->wineD3D = NULL;
597 HeapFree(GetProcessHeap(), 0, This);
598 TRACE("Freed device %p\n", This);
604 /**********************************************************
605 * IWineD3DDevice implementation follows
606 **********************************************************/
607 static HRESULT WINAPI IWineD3DDeviceImpl_GetParent(IWineD3DDevice *iface, IUnknown **pParent) {
608 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
609 *pParent = This->parent;
610 IUnknown_AddRef(This->parent);
614 static void CreateVBO(IWineD3DVertexBufferImpl *object) {
615 IWineD3DDeviceImpl *This = object->resource.wineD3DDevice; /* Needed for GL_EXTCALL */
616 GLenum error, glUsage;
617 DWORD vboUsage = object->resource.usage;
618 if(object->Flags & VBFLAG_VBOCREATEFAIL) {
619 WARN("Creating a vbo failed once, not trying again\n");
623 TRACE("Creating an OpenGL vertex buffer object for IWineD3DVertexBuffer %p Usage(%s)\n", object, debug_d3dusage(vboUsage));
626 /* Make sure that the gl error is cleared. Do not use checkGLcall
627 * here because checkGLcall just prints a fixme and continues. However,
628 * if an error during VBO creation occurs we can fall back to non-vbo operation
629 * with full functionality(but performance loss)
631 while(glGetError() != GL_NO_ERROR);
633 /* Basically the FVF parameter passed to CreateVertexBuffer is no good
634 * It is the FVF set with IWineD3DDevice::SetFVF or the Vertex Declaration set with
635 * IWineD3DDevice::SetVertexDeclaration that decides how the vertices in the buffer
636 * look like. This means that on each DrawPrimitive call the vertex buffer has to be verified
637 * to check if the rhw and color values are in the correct format.
640 GL_EXTCALL(glGenBuffersARB(1, &object->vbo));
641 error = glGetError();
642 if(object->vbo == 0 || error != GL_NO_ERROR) {
643 WARN("Failed to create a VBO with error %d\n", error);
647 GL_EXTCALL(glBindBufferARB(GL_ARRAY_BUFFER_ARB, object->vbo));
648 error = glGetError();
649 if(error != GL_NO_ERROR) {
650 WARN("Failed to bind the VBO, error %d\n", error);
654 /* Transformed vertices are horribly inflexible. If the app specifies an
655 * vertex buffer with transformed vertices in default pool without DYNAMIC
656 * usage assume DYNAMIC usage and print a warning. The app will have to update
657 * the vertices regularily for them to be useful
659 if(((object->fvf & D3DFVF_POSITION_MASK) == D3DFVF_XYZRHW) &&
660 !(vboUsage & WINED3DUSAGE_DYNAMIC)) {
661 WARN("Application creates a vertex buffer holding transformed vertices which doesn't specify dynamic usage\n");
662 vboUsage |= WINED3DUSAGE_DYNAMIC;
665 /* Don't use static, because dx apps tend to update the buffer
666 * quite often even if they specify 0 usage
668 switch(vboUsage & (D3DUSAGE_WRITEONLY | D3DUSAGE_DYNAMIC) ) {
669 case D3DUSAGE_WRITEONLY | D3DUSAGE_DYNAMIC:
670 TRACE("Gl usage = GL_STREAM_DRAW\n");
671 glUsage = GL_STREAM_DRAW_ARB;
673 case D3DUSAGE_WRITEONLY:
674 TRACE("Gl usage = GL_DYNAMIC_DRAW\n");
675 glUsage = GL_DYNAMIC_DRAW_ARB;
677 case D3DUSAGE_DYNAMIC:
678 TRACE("Gl usage = GL_STREAM_COPY\n");
679 glUsage = GL_STREAM_COPY_ARB;
682 TRACE("Gl usage = GL_DYNAMIC_COPY\n");
683 glUsage = GL_DYNAMIC_COPY_ARB;
687 /* Reserve memory for the buffer. The amount of data won't change
688 * so we are safe with calling glBufferData once with a NULL ptr and
689 * calling glBufferSubData on updates
691 GL_EXTCALL(glBufferDataARB(GL_ARRAY_BUFFER_ARB, object->resource.size, NULL, glUsage));
692 error = glGetError();
693 if(error != GL_NO_ERROR) {
694 WARN("glBufferDataARB failed with error %d\n", error);
702 /* Clean up all vbo init, but continue because we can work without a vbo :-) */
703 FIXME("Failed to create a vertex buffer object. Continuing, but performance issues can occur\n");
704 if(object->vbo) GL_EXTCALL(glDeleteBuffersARB(1, &object->vbo));
706 object->Flags |= VBFLAG_VBOCREATEFAIL;
711 static HRESULT WINAPI IWineD3DDeviceImpl_CreateVertexBuffer(IWineD3DDevice *iface, UINT Size, DWORD Usage,
712 DWORD FVF, WINED3DPOOL Pool, IWineD3DVertexBuffer** ppVertexBuffer, HANDLE *sharedHandle,
714 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
715 IWineD3DVertexBufferImpl *object;
716 WINED3DFORMAT Format = WINED3DFMT_VERTEXDATA; /* Dummy format for now */
717 int dxVersion = ( (IWineD3DImpl *) This->wineD3D)->dxVersion;
719 D3DCREATERESOURCEOBJECTINSTANCE(object, VertexBuffer, WINED3DRTYPE_VERTEXBUFFER, Size)
721 TRACE("(%p) : Size=%d, Usage=%ld, FVF=%lx, Pool=%d - Memory@%p, Iface@%p\n", This, Size, Usage, FVF, Pool, object->resource.allocatedMemory, object);
722 *ppVertexBuffer = (IWineD3DVertexBuffer *)object;
724 if(Size == 0) return WINED3DERR_INVALIDCALL;
726 if (Pool == WINED3DPOOL_DEFAULT ) { /* Allocate some system memory for now */
727 object->resource.allocatedMemory = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, object->resource.size);
731 /* Observations show that drawStridedSlow is faster on dynamic VBs than converting +
732 * drawStridedFast (half-life 2).
734 * Basically converting the vertices in the buffer is quite expensive, and observations
735 * show that drawStridedSlow is faster than converting + uploading + drawStridedFast.
736 * Therefore do not create a VBO for WINED3DUSAGE_DYNAMIC buffers.
738 * Direct3D7 has another problem: Its vertexbuffer api doesn't offer a way to specify
739 * the range of vertices being locked, so each lock will require the whole buffer to be transformed.
740 * Moreover geometry data in dx7 is quite simple, so drawStridedSlow isn't a big hit. A plus
741 * is that the vertex buffers fvf can be trusted in dx7. So only create non-converted vbos for
743 * There is a IDirect3DVertexBuffer7::Optimize call after which the buffer can't be locked any
744 * more. In this call we can convert dx7 buffers too.
746 conv = ((FVF & D3DFVF_POSITION_MASK) == D3DFVF_XYZRHW ) || (FVF & (D3DFVF_DIFFUSE | D3DFVF_SPECULAR));
747 if( GL_SUPPORT(ARB_VERTEX_BUFFER_OBJECT) && Pool != WINED3DPOOL_SYSTEMMEM && !(Usage & WINED3DUSAGE_DYNAMIC) &&
748 (dxVersion > 7 || !conv) ) {
751 /* DX7 buffers can be locked directly into the VBO (no conversion, see above */
752 if(dxVersion == 7 && object->vbo) {
753 HeapFree(GetProcessHeap(), 0, object->resource.allocatedMemory);
754 object->resource.allocatedMemory = NULL;
761 static HRESULT WINAPI IWineD3DDeviceImpl_CreateIndexBuffer(IWineD3DDevice *iface, UINT Length, DWORD Usage,
762 WINED3DFORMAT Format, WINED3DPOOL Pool, IWineD3DIndexBuffer** ppIndexBuffer,
763 HANDLE *sharedHandle, IUnknown *parent) {
764 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
765 IWineD3DIndexBufferImpl *object;
766 TRACE("(%p) Creating index buffer\n", This);
768 /* Allocate the storage for the device */
769 D3DCREATERESOURCEOBJECTINSTANCE(object,IndexBuffer,WINED3DRTYPE_INDEXBUFFER, Length)
772 if (Pool == WINED3DPOOL_DEFAULT ) { /* Allocate some system memory for now */
773 object->resource.allocatedMemory = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,object->resource.size);
776 TRACE("(%p) : Len=%d, Use=%lx, Format=(%u,%s), Pool=%d - Memory@%p, Iface@%p\n", This, Length, Usage, Format,
777 debug_d3dformat(Format), Pool, object, object->resource.allocatedMemory);
778 *ppIndexBuffer = (IWineD3DIndexBuffer *) object;
783 static HRESULT WINAPI IWineD3DDeviceImpl_CreateStateBlock(IWineD3DDevice* iface, WINED3DSTATEBLOCKTYPE Type, IWineD3DStateBlock** ppStateBlock, IUnknown *parent) {
785 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
786 IWineD3DStateBlockImpl *object;
790 D3DCREATEOBJECTINSTANCE(object, StateBlock)
791 object->blockType = Type;
793 /* Special case - Used during initialization to produce a placeholder stateblock
794 so other functions called can update a state block */
795 if (Type == WINED3DSBT_INIT) {
796 /* Don't bother increasing the reference count otherwise a device will never
797 be freed due to circular dependencies */
801 temp_result = allocate_shader_constants(object);
802 if (WINED3D_OK != temp_result)
805 /* Otherwise, might as well set the whole state block to the appropriate values */
806 if (This->stateBlock != NULL)
807 stateblock_copy((IWineD3DStateBlock*) object, (IWineD3DStateBlock*) This->stateBlock);
809 memset(object->streamFreq, 1, sizeof(object->streamFreq));
811 /* Reset the ref and type after kludging it */
812 object->wineD3DDevice = This;
814 object->blockType = Type;
816 TRACE("Updating changed flags appropriate for type %d\n", Type);
818 if (Type == WINED3DSBT_ALL) {
820 TRACE("ALL => Pretend everything has changed\n");
821 stateblock_savedstates_set((IWineD3DStateBlock*) object, &object->changed, TRUE);
823 } else if (Type == WINED3DSBT_PIXELSTATE) {
825 TRACE("PIXELSTATE => Pretend all pixel shates have changed\n");
826 stateblock_savedstates_set((IWineD3DStateBlock*) object, &object->changed, FALSE);
828 object->changed.pixelShader = TRUE;
830 /* Pixel Shader Constants */
831 for (i = 0; i < GL_LIMITS(pshader_constantsF); ++i)
832 object->changed.pixelShaderConstantsF[i] = TRUE;
833 for (i = 0; i < MAX_CONST_B; ++i)
834 object->changed.pixelShaderConstantsB[i] = TRUE;
835 for (i = 0; i < MAX_CONST_I; ++i)
836 object->changed.pixelShaderConstantsI[i] = TRUE;
838 for (i = 0; i < NUM_SAVEDPIXELSTATES_R; i++) {
839 object->changed.renderState[SavedPixelStates_R[i]] = TRUE;
841 for (j = 0; j < GL_LIMITS(texture_stages); j++) {
842 for (i = 0; i < NUM_SAVEDPIXELSTATES_T; i++) {
843 object->changed.textureState[j][SavedPixelStates_T[i]] = TRUE;
846 for (j = 0 ; j < 16; j++) {
847 for (i =0; i < NUM_SAVEDPIXELSTATES_S;i++) {
849 object->changed.samplerState[j][SavedPixelStates_S[i]] = TRUE;
853 } else if (Type == WINED3DSBT_VERTEXSTATE) {
855 TRACE("VERTEXSTATE => Pretend all vertex shates have changed\n");
856 stateblock_savedstates_set((IWineD3DStateBlock*) object, &object->changed, FALSE);
858 object->changed.vertexShader = TRUE;
860 /* Vertex Shader Constants */
861 for (i = 0; i < GL_LIMITS(vshader_constantsF); ++i)
862 object->changed.vertexShaderConstantsF[i] = TRUE;
863 for (i = 0; i < MAX_CONST_B; ++i)
864 object->changed.vertexShaderConstantsB[i] = TRUE;
865 for (i = 0; i < MAX_CONST_I; ++i)
866 object->changed.vertexShaderConstantsI[i] = TRUE;
868 for (i = 0; i < NUM_SAVEDVERTEXSTATES_R; i++) {
869 object->changed.renderState[SavedVertexStates_R[i]] = TRUE;
871 for (j = 0; j < GL_LIMITS(texture_stages); j++) {
872 for (i = 0; i < NUM_SAVEDVERTEXSTATES_T; i++) {
873 object->changed.textureState[j][SavedVertexStates_T[i]] = TRUE;
876 for (j = 0 ; j < 16; j++){
877 for (i =0; i < NUM_SAVEDVERTEXSTATES_S;i++) {
878 object->changed.samplerState[j][SavedVertexStates_S[i]] = TRUE;
882 /* Duplicate light chain */
884 PLIGHTINFOEL *src = NULL;
885 PLIGHTINFOEL *dst = NULL;
886 PLIGHTINFOEL *newEl = NULL;
887 src = This->stateBlock->lights;
888 object->lights = NULL;
892 newEl = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(PLIGHTINFOEL));
893 if (newEl == NULL) return WINED3DERR_OUTOFVIDEOMEMORY;
894 memcpy(newEl, src, sizeof(PLIGHTINFOEL));
896 newEl->changed = TRUE;
897 newEl->enabledChanged = TRUE;
899 object->lights = newEl;
910 FIXME("Unrecognized state block type %d\n", Type);
913 TRACE("(%p) returning token (ptr to stateblock) of %p\n", This, object);
918 /* ************************************
920 [in] Render targets are not lockable unless the application specifies TRUE for Lockable. Note that lockable render targets reduce performance on some graphics hardware.
923 [in] Set this flag to TRUE to enable z-buffer discarding, and FALSE otherwise.
925 If this flag is set, the contents of the depth stencil buffer will be invalid after calling either IDirect3DDevice9::Present or IDirect3DDevice9::SetDepthStencilSurface with a different depth surface.
927 ******************************** */
929 static HRESULT WINAPI IWineD3DDeviceImpl_CreateSurface(IWineD3DDevice *iface, UINT Width, UINT Height, WINED3DFORMAT Format, BOOL Lockable, BOOL Discard, UINT Level, IWineD3DSurface **ppSurface,WINED3DRESOURCETYPE Type, DWORD Usage, WINED3DPOOL Pool, WINED3DMULTISAMPLE_TYPE MultiSample ,DWORD MultisampleQuality, HANDLE* pSharedHandle, WINED3DSURFTYPE Impl, IUnknown *parent) {
930 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
931 IWineD3DSurfaceImpl *object; /*NOTE: impl ref allowed since this is a create function */
932 unsigned int pow2Width, pow2Height;
933 unsigned int Size = 1;
934 const PixelFormatDesc *tableEntry = getFormatDescEntry(Format);
935 TRACE("(%p) Create surface\n",This);
937 /** FIXME: Check ranges on the inputs are valid
940 * [in] Quality level. The valid range is between zero and one less than the level
941 * returned by pQualityLevels used by IDirect3D9::CheckDeviceMultiSampleType.
942 * Passing a larger value returns the error WINED3DERR_INVALIDCALL. The MultisampleQuality
943 * values of paired render targets, depth stencil surfaces, and the MultiSample type
945 *******************************/
950 * [in] Set this flag to TRUE to enable z-buffer discarding, and FALSE otherwise.
952 * If this flag is set, the contents of the depth stencil buffer will be
953 * invalid after calling either IDirect3DDevice9::Present or * IDirect3DDevice9::SetDepthStencilSurface
954 * with a different depth surface.
956 *This flag has the same behavior as the constant, D3DPRESENTFLAG_DISCARD_DEPTHSTENCIL, in D3DPRESENTFLAG.
957 ***************************/
959 if(MultisampleQuality < 0) {
960 FIXME("Invalid multisample level %ld\n", MultisampleQuality);
961 return WINED3DERR_INVALIDCALL; /* TODO: Check that this is the case! */
964 if(MultisampleQuality > 0) {
965 FIXME("MultisampleQuality set to %ld, substituting 0\n", MultisampleQuality);
966 MultisampleQuality=0;
969 /** FIXME: Check that the format is supported
971 *******************************/
973 /* Non-power2 support */
975 /* Find the nearest pow2 match */
976 pow2Width = pow2Height = 1;
977 while (pow2Width < Width) pow2Width <<= 1;
978 while (pow2Height < Height) pow2Height <<= 1;
980 if (pow2Width > Width || pow2Height > Height) {
981 /** TODO: add support for non power two compressed textures (OpenGL 2 provices support for * non-power-two textures gratis) **/
982 if (Format == WINED3DFMT_DXT1 || Format == WINED3DFMT_DXT2 || Format == WINED3DFMT_DXT3
983 || Format == WINED3DFMT_DXT4 || Format == WINED3DFMT_DXT5) {
984 FIXME("(%p) Compressed non-power-two textures are not supported w(%d) h(%d)\n",
985 This, Width, Height);
986 return WINED3DERR_NOTAVAILABLE;
990 /** DXTn mipmaps use the same number of 'levels' down to eg. 8x1, but since
991 * it is based around 4x4 pixel blocks it requires padding, so allocate enough
993 *********************************/
994 if (WINED3DFMT_UNKNOWN == Format) {
996 } else if (Format == WINED3DFMT_DXT1) {
997 /* DXT1 is half byte per pixel */
998 Size = ((max(pow2Width,4) * tableEntry->bpp) * max(pow2Height,4)) >> 1;
1000 } else if (Format == WINED3DFMT_DXT2 || Format == WINED3DFMT_DXT3 ||
1001 Format == WINED3DFMT_DXT4 || Format == WINED3DFMT_DXT5) {
1002 Size = ((max(pow2Width,4) * tableEntry->bpp) * max(pow2Height,4));
1004 Size = (pow2Width * tableEntry->bpp) * pow2Height;
1007 /** Create and initialise the surface resource **/
1008 D3DCREATERESOURCEOBJECTINSTANCE(object,Surface,WINED3DRTYPE_SURFACE, Size)
1009 /* "Standalone" surface */
1010 IWineD3DSurface_SetContainer((IWineD3DSurface *)object, NULL);
1012 object->currentDesc.Width = Width;
1013 object->currentDesc.Height = Height;
1014 object->currentDesc.MultiSampleType = MultiSample;
1015 object->currentDesc.MultiSampleQuality = MultisampleQuality;
1017 /* Setup some glformat defaults */
1018 object->glDescription.glFormat = tableEntry->glFormat;
1019 object->glDescription.glFormatInternal = tableEntry->glInternal;
1020 object->glDescription.glType = tableEntry->glType;
1022 object->glDescription.textureName = 0;
1023 object->glDescription.level = Level;
1024 object->glDescription.target = GL_TEXTURE_2D;
1027 object->pow2Width = pow2Width;
1028 object->pow2Height = pow2Height;
1031 object->Flags = 0; /* We start without flags set */
1032 object->Flags |= (pow2Width != Width || pow2Height != Height) ? SFLAG_NONPOW2 : 0;
1033 object->Flags |= Discard ? SFLAG_DISCARD : 0;
1034 object->Flags |= (WINED3DFMT_D16_LOCKABLE == Format) ? SFLAG_LOCKABLE : 0;
1035 object->Flags |= Lockable ? SFLAG_LOCKABLE : 0;
1038 if (WINED3DFMT_UNKNOWN != Format) {
1039 object->bytesPerPixel = tableEntry->bpp;
1040 object->pow2Size = (pow2Width * object->bytesPerPixel) * pow2Height;
1042 object->bytesPerPixel = 0;
1043 object->pow2Size = 0;
1046 /** TODO: change this into a texture transform matrix so that it's processed in hardware **/
1048 TRACE("Pool %d %d %d %d",Pool, WINED3DPOOL_DEFAULT, WINED3DPOOL_MANAGED, WINED3DPOOL_SYSTEMMEM);
1050 /** Quick lockable sanity check TODO: remove this after surfaces, usage and locablility have been debugged properly
1051 * this function is too deap to need to care about things like this.
1052 * Levels need to be checked too, and possibly Type wince they all affect what can be done.
1053 * ****************************************/
1055 case WINED3DPOOL_SCRATCH:
1056 if(Lockable == FALSE)
1057 FIXME("Create suface called with a pool of SCRATCH and a Lockable of FALSE \
1058 which are mutually exclusive, setting lockable to true\n");
1061 case WINED3DPOOL_SYSTEMMEM:
1062 if(Lockable == FALSE) FIXME("Create surface called with a pool of SYSTEMMEM and a Lockable of FALSE, \
1063 this is acceptable but unexpected (I can't know how the surface can be usable!)\n");
1064 case WINED3DPOOL_MANAGED:
1065 if(Usage == WINED3DUSAGE_DYNAMIC) FIXME("Create surface called with a pool of MANAGED and a \
1066 Usage of DYNAMIC which are mutually exclusive, not doing \
1067 anything just telling you.\n");
1069 case WINED3DPOOL_DEFAULT: /*TODO: Create offscreen plain can cause this check to fail..., find out if it should */
1070 if(!(Usage & WINED3DUSAGE_DYNAMIC) && !(Usage & WINED3DUSAGE_RENDERTARGET)
1071 && !(Usage && WINED3DUSAGE_DEPTHSTENCIL ) && Lockable)
1072 WARN("Creating a surface with a POOL of DEFAULT with Lockable true, that doesn't specify DYNAMIC usage.\n");
1075 FIXME("(%p) Unknown pool %d\n", This, Pool);
1079 if (Usage & WINED3DUSAGE_RENDERTARGET && Pool != WINED3DPOOL_DEFAULT) {
1080 FIXME("Trying to create a render target that isn't in the default pool\n");
1083 /* mark the texture as dirty so that it get's loaded first time around*/
1084 IWineD3DSurface_AddDirtyRect(*ppSurface, NULL);
1085 TRACE("(%p) : w(%d) h(%d) fmt(%d,%s) lockable(%d) surf@%p, surfmem@%p, %d bytes\n",
1086 This, Width, Height, Format, debug_d3dformat(Format),
1087 (WINED3DFMT_D16_LOCKABLE == Format), *ppSurface, object->resource.allocatedMemory, object->resource.size);
1089 /* Store the DirectDraw primary surface. This is the first rendertarget surface created */
1090 if( (Usage & WINED3DUSAGE_RENDERTARGET) && (!This->ddraw_primary) )
1091 This->ddraw_primary = (IWineD3DSurface *) object;
1093 /* Look at the implementation and set the correct Vtable */
1095 case SURFACE_OPENGL:
1096 /* Nothing to do, it's set already */
1100 object->lpVtbl = &IWineGDISurface_Vtbl;
1104 /* To be sure to catch this */
1105 ERR("Unknown requested surface implementation %d!\n", Impl);
1106 IWineD3DSurface_Release((IWineD3DSurface *) object);
1107 return WINED3DERR_INVALIDCALL;
1110 /* Call the private setup routine */
1111 return IWineD3DSurface_PrivateSetup( (IWineD3DSurface *) object );
1115 static HRESULT WINAPI IWineD3DDeviceImpl_CreateTexture(IWineD3DDevice *iface, UINT Width, UINT Height, UINT Levels,
1116 DWORD Usage, WINED3DFORMAT Format, WINED3DPOOL Pool,
1117 IWineD3DTexture** ppTexture, HANDLE* pSharedHandle, IUnknown *parent,
1118 D3DCB_CREATESURFACEFN D3DCB_CreateSurface) {
1120 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
1121 IWineD3DTextureImpl *object;
1126 unsigned int pow2Width = Width;
1127 unsigned int pow2Height = Height;
1130 TRACE("(%p) : Width %d, Height %d, Levels %d, Usage %#lx\n", This, Width, Height, Levels, Usage);
1131 TRACE("Format %#x (%s), Pool %#x, ppTexture %p, pSharedHandle %p, parent %p\n",
1132 Format, debug_d3dformat(Format), Pool, ppTexture, pSharedHandle, parent);
1134 /* TODO: It should only be possible to create textures for formats
1135 that are reported as supported */
1136 if (WINED3DFMT_UNKNOWN >= Format) {
1137 WARN("(%p) : Texture cannot be created with a format of D3DFMT_UNKNOWN\n", This);
1138 return WINED3DERR_INVALIDCALL;
1141 D3DCREATERESOURCEOBJECTINSTANCE(object, Texture, WINED3DRTYPE_TEXTURE, 0);
1142 D3DINITIALIZEBASETEXTURE(object->baseTexture);
1143 object->width = Width;
1144 object->height = Height;
1146 /** Non-power2 support **/
1147 /* Find the nearest pow2 match */
1148 pow2Width = pow2Height = 1;
1149 while (pow2Width < Width) pow2Width <<= 1;
1150 while (pow2Height < Height) pow2Height <<= 1;
1152 /** FIXME: add support for real non-power-two if it's provided by the video card **/
1153 /* Precalculated scaling for 'faked' non power of two texture coords */
1154 object->pow2scalingFactorX = (((float)Width) / ((float)pow2Width));
1155 object->pow2scalingFactorY = (((float)Height) / ((float)pow2Height));
1156 TRACE(" xf(%f) yf(%f)\n", object->pow2scalingFactorX, object->pow2scalingFactorY);
1158 /* Calculate levels for mip mapping */
1160 TRACE("calculating levels %d\n", object->baseTexture.levels);
1161 object->baseTexture.levels++;
1164 while (tmpW > 1 || tmpH > 1) {
1165 tmpW = max(1, tmpW >> 1);
1166 tmpH = max(1, tmpH >> 1);
1167 object->baseTexture.levels++;
1169 TRACE("Calculated levels = %d\n", object->baseTexture.levels);
1172 /* Generate all the surfaces */
1175 for (i = 0; i < object->baseTexture.levels; i++)
1177 /* use the callback to create the texture surface */
1178 hr = D3DCB_CreateSurface(This->parent, tmpW, tmpH, Format, Usage, Pool, i, &object->surfaces[i],NULL);
1179 if (hr!= WINED3D_OK || ( (IWineD3DSurfaceImpl *) object->surfaces[i])->Flags & SFLAG_OVERSIZE) {
1180 FIXME("Failed to create surface %p\n", object);
1182 object->surfaces[i] = NULL;
1183 IWineD3DTexture_Release((IWineD3DTexture *)object);
1189 IWineD3DSurface_SetContainer(object->surfaces[i], (IWineD3DBase *)object);
1190 TRACE("Created surface level %d @ %p\n", i, object->surfaces[i]);
1191 /* calculate the next mipmap level */
1192 tmpW = max(1, tmpW >> 1);
1193 tmpH = max(1, tmpH >> 1);
1196 TRACE("(%p) : Created texture %p\n", This, object);
1200 static HRESULT WINAPI IWineD3DDeviceImpl_CreateVolumeTexture(IWineD3DDevice *iface,
1201 UINT Width, UINT Height, UINT Depth,
1202 UINT Levels, DWORD Usage,
1203 WINED3DFORMAT Format, WINED3DPOOL Pool,
1204 IWineD3DVolumeTexture **ppVolumeTexture,
1205 HANDLE *pSharedHandle, IUnknown *parent,
1206 D3DCB_CREATEVOLUMEFN D3DCB_CreateVolume) {
1208 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
1209 IWineD3DVolumeTextureImpl *object;
1215 /* TODO: It should only be possible to create textures for formats
1216 that are reported as supported */
1217 if (WINED3DFMT_UNKNOWN >= Format) {
1218 WARN("(%p) : Texture cannot be created with a format of D3DFMT_UNKNOWN\n", This);
1219 return WINED3DERR_INVALIDCALL;
1222 D3DCREATERESOURCEOBJECTINSTANCE(object, VolumeTexture, WINED3DRTYPE_VOLUMETEXTURE, 0);
1223 D3DINITIALIZEBASETEXTURE(object->baseTexture);
1225 TRACE("(%p) : W(%d) H(%d) D(%d), Lvl(%d) Usage(%ld), Fmt(%u,%s), Pool(%s)\n", This, Width, Height,
1226 Depth, Levels, Usage, Format, debug_d3dformat(Format), debug_d3dpool(Pool));
1228 object->width = Width;
1229 object->height = Height;
1230 object->depth = Depth;
1232 /* Calculate levels for mip mapping */
1234 object->baseTexture.levels++;
1238 while (tmpW > 1 || tmpH > 1 || tmpD > 1) {
1239 tmpW = max(1, tmpW >> 1);
1240 tmpH = max(1, tmpH >> 1);
1241 tmpD = max(1, tmpD >> 1);
1242 object->baseTexture.levels++;
1244 TRACE("Calculated levels = %d\n", object->baseTexture.levels);
1247 /* Generate all the surfaces */
1252 for (i = 0; i < object->baseTexture.levels; i++)
1254 /* Create the volume */
1255 D3DCB_CreateVolume(This->parent, Width, Height, Depth, Format, Pool, Usage,
1256 (IWineD3DVolume **)&object->volumes[i], pSharedHandle);
1258 /* Set it's container to this object */
1259 IWineD3DVolume_SetContainer(object->volumes[i], (IWineD3DBase *)object);
1261 /* calcualte the next mipmap level */
1262 tmpW = max(1, tmpW >> 1);
1263 tmpH = max(1, tmpH >> 1);
1264 tmpD = max(1, tmpD >> 1);
1267 *ppVolumeTexture = (IWineD3DVolumeTexture *) object;
1268 TRACE("(%p) : Created volume texture %p\n", This, object);
1272 static HRESULT WINAPI IWineD3DDeviceImpl_CreateVolume(IWineD3DDevice *iface,
1273 UINT Width, UINT Height, UINT Depth,
1275 WINED3DFORMAT Format, WINED3DPOOL Pool,
1276 IWineD3DVolume** ppVolume,
1277 HANDLE* pSharedHandle, IUnknown *parent) {
1279 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
1280 IWineD3DVolumeImpl *object; /** NOTE: impl ref allowed since this is a create function **/
1281 const PixelFormatDesc *formatDesc = getFormatDescEntry(Format);
1283 D3DCREATERESOURCEOBJECTINSTANCE(object, Volume, WINED3DRTYPE_VOLUME, ((Width * formatDesc->bpp) * Height * Depth))
1285 TRACE("(%p) : W(%d) H(%d) D(%d), Usage(%ld), Fmt(%u,%s), Pool(%s)\n", This, Width, Height,
1286 Depth, Usage, Format, debug_d3dformat(Format), debug_d3dpool(Pool));
1288 object->currentDesc.Width = Width;
1289 object->currentDesc.Height = Height;
1290 object->currentDesc.Depth = Depth;
1291 object->bytesPerPixel = formatDesc->bpp;
1293 /** Note: Volume textures cannot be dxtn, hence no need to check here **/
1294 object->lockable = TRUE;
1295 object->locked = FALSE;
1296 memset(&object->lockedBox, 0, sizeof(WINED3DBOX));
1297 object->dirty = TRUE;
1299 return IWineD3DVolume_AddDirtyBox((IWineD3DVolume *) object, NULL);
1302 static HRESULT WINAPI IWineD3DDeviceImpl_CreateCubeTexture(IWineD3DDevice *iface, UINT EdgeLength,
1303 UINT Levels, DWORD Usage,
1304 WINED3DFORMAT Format, WINED3DPOOL Pool,
1305 IWineD3DCubeTexture **ppCubeTexture,
1306 HANDLE *pSharedHandle, IUnknown *parent,
1307 D3DCB_CREATESURFACEFN D3DCB_CreateSurface) {
1309 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
1310 IWineD3DCubeTextureImpl *object; /** NOTE: impl ref allowed since this is a create function **/
1314 unsigned int pow2EdgeLength = EdgeLength;
1316 /* TODO: It should only be possible to create textures for formats
1317 that are reported as supported */
1318 if (WINED3DFMT_UNKNOWN >= Format) {
1319 WARN("(%p) : Texture cannot be created with a format of D3DFMT_UNKNOWN\n", This);
1320 return WINED3DERR_INVALIDCALL;
1323 D3DCREATERESOURCEOBJECTINSTANCE(object, CubeTexture, WINED3DRTYPE_CUBETEXTURE, 0);
1324 D3DINITIALIZEBASETEXTURE(object->baseTexture);
1326 TRACE("(%p) Create Cube Texture\n", This);
1328 /** Non-power2 support **/
1330 /* Find the nearest pow2 match */
1332 while (pow2EdgeLength < EdgeLength) pow2EdgeLength <<= 1;
1334 object->edgeLength = EdgeLength;
1335 /* TODO: support for native non-power 2 */
1336 /* Precalculated scaling for 'faked' non power of two texture coords */
1337 object->pow2scalingFactor = ((float)EdgeLength) / ((float)pow2EdgeLength);
1339 /* Calculate levels for mip mapping */
1341 object->baseTexture.levels++;
1344 tmpW = max(1, tmpW >> 1);
1345 object->baseTexture.levels++;
1347 TRACE("Calculated levels = %d\n", object->baseTexture.levels);
1350 /* Generate all the surfaces */
1352 for (i = 0; i < object->baseTexture.levels; i++) {
1354 /* Create the 6 faces */
1355 for (j = 0; j < 6; j++) {
1357 hr=D3DCB_CreateSurface(This->parent, tmpW, tmpW, Format, Usage, Pool,
1358 i /* Level */, &object->surfaces[j][i],pSharedHandle);
1360 if(hr!= WINED3D_OK) {
1364 for (l = 0; l < j; l++) {
1365 IWineD3DSurface_Release(object->surfaces[j][i]);
1367 for (k = 0; k < i; k++) {
1368 for (l = 0; l < 6; l++) {
1369 IWineD3DSurface_Release(object->surfaces[l][j]);
1373 FIXME("(%p) Failed to create surface\n",object);
1374 HeapFree(GetProcessHeap(),0,object);
1375 *ppCubeTexture = NULL;
1378 IWineD3DSurface_SetContainer(object->surfaces[j][i], (IWineD3DBase *)object);
1379 TRACE("Created surface level %d @ %p,\n", i, object->surfaces[j][i]);
1381 tmpW = max(1, tmpW >> 1);
1384 TRACE("(%p) : Created Cube Texture %p\n", This, object);
1385 *ppCubeTexture = (IWineD3DCubeTexture *) object;
1389 static HRESULT WINAPI IWineD3DDeviceImpl_CreateQuery(IWineD3DDevice *iface, WINED3DQUERYTYPE Type, IWineD3DQuery **ppQuery, IUnknown* parent) {
1390 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
1391 IWineD3DQueryImpl *object; /*NOTE: impl ref allowed since this is a create function */
1393 if (NULL == ppQuery) {
1394 /* Just a check to see if we support this type of query */
1395 HRESULT hr = WINED3DERR_NOTAVAILABLE;
1397 case WINED3DQUERYTYPE_OCCLUSION:
1398 TRACE("(%p) occlusion query\n", This);
1399 if (GL_SUPPORT(ARB_OCCLUSION_QUERY))
1402 WARN("Unsupported in local OpenGL implementation: ARB_OCCLUSION_QUERY/NV_OCCLUSION_QUERY\n");
1404 case WINED3DQUERYTYPE_VCACHE:
1405 case WINED3DQUERYTYPE_RESOURCEMANAGER:
1406 case WINED3DQUERYTYPE_VERTEXSTATS:
1407 case WINED3DQUERYTYPE_EVENT:
1408 case WINED3DQUERYTYPE_TIMESTAMP:
1409 case WINED3DQUERYTYPE_TIMESTAMPDISJOINT:
1410 case WINED3DQUERYTYPE_TIMESTAMPFREQ:
1411 case WINED3DQUERYTYPE_PIPELINETIMINGS:
1412 case WINED3DQUERYTYPE_INTERFACETIMINGS:
1413 case WINED3DQUERYTYPE_VERTEXTIMINGS:
1414 case WINED3DQUERYTYPE_PIXELTIMINGS:
1415 case WINED3DQUERYTYPE_BANDWIDTHTIMINGS:
1416 case WINED3DQUERYTYPE_CACHEUTILIZATION:
1418 FIXME("(%p) Unhandled query type %d\n", This, Type);
1423 D3DCREATEOBJECTINSTANCE(object, Query)
1424 object->type = Type;
1425 /* allocated the 'extended' data based on the type of query requested */
1427 case D3DQUERYTYPE_OCCLUSION:
1428 if(GL_SUPPORT(ARB_OCCLUSION_QUERY)) {
1429 TRACE("(%p) Allocating data for an occlusion query\n", This);
1430 object->extendedData = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(WineQueryOcclusionData));
1431 GL_EXTCALL(glGenQueriesARB(1, &((WineQueryOcclusionData *)(object->extendedData))->queryId));
1434 case D3DQUERYTYPE_VCACHE:
1435 case D3DQUERYTYPE_RESOURCEMANAGER:
1436 case D3DQUERYTYPE_VERTEXSTATS:
1437 case D3DQUERYTYPE_EVENT:
1438 case D3DQUERYTYPE_TIMESTAMP:
1439 case D3DQUERYTYPE_TIMESTAMPDISJOINT:
1440 case D3DQUERYTYPE_TIMESTAMPFREQ:
1441 case D3DQUERYTYPE_PIPELINETIMINGS:
1442 case D3DQUERYTYPE_INTERFACETIMINGS:
1443 case D3DQUERYTYPE_VERTEXTIMINGS:
1444 case D3DQUERYTYPE_PIXELTIMINGS:
1445 case D3DQUERYTYPE_BANDWIDTHTIMINGS:
1446 case D3DQUERYTYPE_CACHEUTILIZATION:
1448 object->extendedData = 0;
1449 FIXME("(%p) Unhandled query type %d\n",This , Type);
1451 TRACE("(%p) : Created Query %p\n", This, object);
1455 /* example at http://www.fairyengine.com/articles/dxmultiviews.htm */
1456 static HRESULT WINAPI IWineD3DDeviceImpl_CreateAdditionalSwapChain(IWineD3DDevice* iface, WINED3DPRESENT_PARAMETERS* pPresentationParameters, IWineD3DSwapChain** ppSwapChain,
1458 D3DCB_CREATERENDERTARGETFN D3DCB_CreateRenderTarget,
1459 D3DCB_CREATEDEPTHSTENCILSURFACEFN D3DCB_CreateDepthStencil) {
1460 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
1463 IWineD3DSwapChainImpl *object; /** NOTE: impl ref allowed since this is a create function **/
1465 XVisualInfo template;
1466 GLXContext oldContext;
1467 Drawable oldDrawable;
1468 HRESULT hr = WINED3D_OK;
1470 TRACE("(%p) : Created Aditional Swap Chain\n", This);
1472 /** FIXME: Test under windows to find out what the life cycle of a swap chain is,
1473 * does a device hold a reference to a swap chain giving them a lifetime of the device
1474 * or does the swap chain notify the device of its destruction.
1475 *******************************/
1477 /* Check the params */
1478 if(*pPresentationParameters->BackBufferCount > D3DPRESENT_BACK_BUFFER_MAX) {
1479 ERR("App requested %d back buffers, this is not supported for now\n", *pPresentationParameters->BackBufferCount);
1480 return WINED3DERR_INVALIDCALL;
1481 } else if (*pPresentationParameters->BackBufferCount > 1) {
1482 FIXME("The app requests more than one back buffer, this can't be supported properly. Please configure the application to use double buffering(=1 back buffer) if possible\n");
1485 D3DCREATEOBJECTINSTANCE(object, SwapChain)
1487 /*********************
1488 * Lookup the window Handle and the relating X window handle
1489 ********************/
1491 /* Setup hwnd we are using, plus which display this equates to */
1492 object->win_handle = *(pPresentationParameters->hDeviceWindow);
1493 if (!object->win_handle) {
1494 object->win_handle = This->createParms.hFocusWindow;
1497 object->win_handle = GetAncestor(object->win_handle, GA_ROOT);
1498 if ( !( object->win = (Window)GetPropA(object->win_handle, "__wine_x11_whole_window") ) ) {
1499 ERR("Can't get drawable (window), HWND:%p doesn't have the property __wine_x11_whole_window\n", object->win_handle);
1500 return WINED3DERR_NOTAVAILABLE;
1502 hDc = GetDC(object->win_handle);
1503 object->display = get_display(hDc);
1504 ReleaseDC(object->win_handle, hDc);
1505 TRACE("Using a display of %p %p\n", object->display, hDc);
1507 if (NULL == object->display || NULL == hDc) {
1508 WARN("Failed to get a display and HDc for Window %p\n", object->win_handle);
1509 return WINED3DERR_NOTAVAILABLE;
1512 if (object->win == 0) {
1513 WARN("Failed to get a valid XVisuial ID for the window %p\n", object->win_handle);
1514 return WINED3DERR_NOTAVAILABLE;
1517 * Create an opengl context for the display visual
1518 * NOTE: the visual is chosen as the window is created and the glcontext cannot
1519 * use different properties after that point in time. FIXME: How to handle when requested format
1520 * doesn't match actual visual? Cannot choose one here - code removed as it ONLY works if the one
1521 * it chooses is identical to the one already being used!
1522 **********************************/
1524 /** FIXME: Handle stencil appropriately via EnableAutoDepthStencil / AutoDepthStencilFormat **/
1527 /* Create a new context for this swapchain */
1528 template.visualid = (VisualID)GetPropA(GetDesktopWindow(), "__wine_x11_visual_id");
1529 /* TODO: change this to find a similar visual, but one with a stencil/zbuffer buffer that matches the request
1530 (or the best possible if none is requested) */
1531 TRACE("Found x visual ID : %ld\n", template.visualid);
1533 object->visInfo = XGetVisualInfo(object->display, VisualIDMask, &template, &num);
1534 if (NULL == object->visInfo) {
1535 ERR("cannot really get XVisual\n");
1537 return WINED3DERR_NOTAVAILABLE;
1540 /* Write out some debug info about the visual/s */
1541 TRACE("Using x visual ID : %ld\n", template.visualid);
1542 TRACE(" visual info: %p\n", object->visInfo);
1543 TRACE(" num items : %d\n", num);
1544 for (n = 0;n < num; n++) {
1545 TRACE("=====item=====: %d\n", n + 1);
1546 TRACE(" visualid : %ld\n", object->visInfo[n].visualid);
1547 TRACE(" screen : %d\n", object->visInfo[n].screen);
1548 TRACE(" depth : %u\n", object->visInfo[n].depth);
1549 TRACE(" class : %d\n", object->visInfo[n].class);
1550 TRACE(" red_mask : %ld\n", object->visInfo[n].red_mask);
1551 TRACE(" green_mask : %ld\n", object->visInfo[n].green_mask);
1552 TRACE(" blue_mask : %ld\n", object->visInfo[n].blue_mask);
1553 TRACE(" colormap_size : %d\n", object->visInfo[n].colormap_size);
1554 TRACE(" bits_per_rgb : %d\n", object->visInfo[n].bits_per_rgb);
1555 /* log some extra glx info */
1556 glXGetConfig(object->display, object->visInfo, GLX_AUX_BUFFERS, &value);
1557 TRACE(" gl_aux_buffers : %d\n", value);
1558 glXGetConfig(object->display, object->visInfo, GLX_BUFFER_SIZE ,&value);
1559 TRACE(" gl_buffer_size : %d\n", value);
1560 glXGetConfig(object->display, object->visInfo, GLX_RED_SIZE, &value);
1561 TRACE(" gl_red_size : %d\n", value);
1562 glXGetConfig(object->display, object->visInfo, GLX_GREEN_SIZE, &value);
1563 TRACE(" gl_green_size : %d\n", value);
1564 glXGetConfig(object->display, object->visInfo, GLX_BLUE_SIZE, &value);
1565 TRACE(" gl_blue_size : %d\n", value);
1566 glXGetConfig(object->display, object->visInfo, GLX_ALPHA_SIZE, &value);
1567 TRACE(" gl_alpha_size : %d\n", value);
1568 glXGetConfig(object->display, object->visInfo, GLX_DEPTH_SIZE ,&value);
1569 TRACE(" gl_depth_size : %d\n", value);
1570 glXGetConfig(object->display, object->visInfo, GLX_STENCIL_SIZE, &value);
1571 TRACE(" gl_stencil_size : %d\n", value);
1573 /* Now choose a simila visual ID*/
1575 #ifdef USE_CONTEXT_MANAGER
1577 /** TODO: use a context mamager **/
1581 IWineD3DSwapChain *implSwapChain;
1582 if (WINED3D_OK != IWineD3DDevice_GetSwapChain(iface, 0, &implSwapChain)) {
1583 /* The first time around we create the context that is shared with all other swapchains and render targets */
1584 object->glCtx = glXCreateContext(object->display, object->visInfo, NULL, GL_TRUE);
1585 TRACE("Creating implicit context for vis %p, hwnd %p\n", object->display, object->visInfo);
1588 TRACE("Creating context for vis %p, hwnd %p\n", object->display, object->visInfo);
1589 /* TODO: don't use Impl structures outside of create functions! (a context manager will replace the ->glCtx) */
1590 /* and create a new context with the implicit swapchains context as the shared context */
1591 object->glCtx = glXCreateContext(object->display, object->visInfo, ((IWineD3DSwapChainImpl *)implSwapChain)->glCtx, GL_TRUE);
1592 IWineD3DSwapChain_Release(implSwapChain);
1597 XFree(object->visInfo);
1598 object->visInfo = NULL;
1602 if (!object->glCtx) {
1603 ERR("Failed to create GLX context\n");
1604 return WINED3DERR_NOTAVAILABLE;
1606 TRACE("Context created (HWND=%p, glContext=%p, Window=%ld, VisInfo=%p)\n",
1607 object->win_handle, object->glCtx, object->win, object->visInfo);
1610 /*********************
1611 * Windowed / Fullscreen
1612 *******************/
1615 * TODO: MSDN says that we are only allowed one fullscreen swapchain per device,
1616 * so we should really check to see if there is a fullscreen swapchain already
1617 * I think Windows and X have different ideas about fullscreen, does a single head count as full screen?
1618 **************************************/
1620 if (!*(pPresentationParameters->Windowed)) {
1626 /* Get info on the current display setup */
1627 hdc = CreateDCA("DISPLAY", NULL, NULL, NULL);
1628 bpp = GetDeviceCaps(hdc, BITSPIXEL);
1631 /* Change the display settings */
1632 memset(&devmode, 0, sizeof(DEVMODEW));
1633 devmode.dmFields = DM_BITSPERPEL | DM_PELSWIDTH | DM_PELSHEIGHT;
1634 devmode.dmBitsPerPel = (bpp >= 24) ? 32 : bpp; /* Stupid XVidMode cannot change bpp */
1635 devmode.dmPelsWidth = *(pPresentationParameters->BackBufferWidth);
1636 devmode.dmPelsHeight = *(pPresentationParameters->BackBufferHeight);
1637 MultiByteToWideChar(CP_ACP, 0, "Gamers CG", -1, devmode.dmDeviceName, CCHDEVICENAME);
1638 ChangeDisplaySettingsExW(devmode.dmDeviceName, &devmode, object->win_handle, CDS_FULLSCREEN, NULL);
1640 /* Make popup window */
1641 SetWindowLongA(object->win_handle, GWL_STYLE, WS_POPUP);
1642 SetWindowPos(object->win_handle, HWND_TOP, 0, 0,
1643 *(pPresentationParameters->BackBufferWidth),
1644 *(pPresentationParameters->BackBufferHeight), SWP_SHOWWINDOW | SWP_FRAMECHANGED);
1646 /* For GetDisplayMode */
1647 This->ddraw_width = devmode.dmPelsWidth;
1648 This->ddraw_height = devmode.dmPelsHeight;
1649 This->ddraw_format = *(pPresentationParameters->BackBufferFormat);
1653 /** MSDN: If Windowed is TRUE and either of the BackBufferWidth/Height values is zero,
1654 * then the corresponding dimension of the client area of the hDeviceWindow
1655 * (or the focus window, if hDeviceWindow is NULL) is taken.
1656 **********************/
1658 if (*(pPresentationParameters->Windowed) &&
1659 ((*(pPresentationParameters->BackBufferWidth) == 0) ||
1660 (*(pPresentationParameters->BackBufferHeight) == 0))) {
1663 GetClientRect(object->win_handle, &Rect);
1665 if (*(pPresentationParameters->BackBufferWidth) == 0) {
1666 *(pPresentationParameters->BackBufferWidth) = Rect.right;
1667 TRACE("Updating width to %d\n", *(pPresentationParameters->BackBufferWidth));
1669 if (*(pPresentationParameters->BackBufferHeight) == 0) {
1670 *(pPresentationParameters->BackBufferHeight) = Rect.bottom;
1671 TRACE("Updating height to %d\n", *(pPresentationParameters->BackBufferHeight));
1675 /*********************
1676 * finish off parameter initialization
1677 *******************/
1679 /* Put the correct figures in the presentation parameters */
1680 TRACE("Coppying accross presentaion paraneters\n");
1681 object->presentParms.BackBufferWidth = *(pPresentationParameters->BackBufferWidth);
1682 object->presentParms.BackBufferHeight = *(pPresentationParameters->BackBufferHeight);
1683 object->presentParms.BackBufferFormat = *(pPresentationParameters->BackBufferFormat);
1684 object->presentParms.BackBufferCount = *(pPresentationParameters->BackBufferCount);
1685 object->presentParms.MultiSampleType = *(pPresentationParameters->MultiSampleType);
1686 object->presentParms.MultiSampleQuality = NULL == pPresentationParameters->MultiSampleQuality ? 0 : *(pPresentationParameters->MultiSampleQuality);
1687 object->presentParms.SwapEffect = *(pPresentationParameters->SwapEffect);
1688 object->presentParms.hDeviceWindow = *(pPresentationParameters->hDeviceWindow);
1689 object->presentParms.Windowed = *(pPresentationParameters->Windowed);
1690 object->presentParms.EnableAutoDepthStencil = *(pPresentationParameters->EnableAutoDepthStencil);
1691 object->presentParms.AutoDepthStencilFormat = *(pPresentationParameters->AutoDepthStencilFormat);
1692 object->presentParms.Flags = *(pPresentationParameters->Flags);
1693 object->presentParms.FullScreen_RefreshRateInHz = *(pPresentationParameters->FullScreen_RefreshRateInHz);
1694 object->presentParms.PresentationInterval = *(pPresentationParameters->PresentationInterval);
1697 /*********************
1698 * Create the back, front and stencil buffers
1699 *******************/
1701 TRACE("calling rendertarget CB\n");
1702 hr = D3DCB_CreateRenderTarget((IUnknown *) This->parent,
1703 object->presentParms.BackBufferWidth,
1704 object->presentParms.BackBufferHeight,
1705 object->presentParms.BackBufferFormat,
1706 object->presentParms.MultiSampleType,
1707 object->presentParms.MultiSampleQuality,
1708 TRUE /* Lockable */,
1709 &object->frontBuffer,
1710 NULL /* pShared (always null)*/);
1711 if (object->frontBuffer != NULL)
1712 IWineD3DSurface_SetContainer(object->frontBuffer, (IWineD3DBase *)object);
1714 if(object->presentParms.BackBufferCount > 0) {
1717 object->backBuffer = HeapAlloc(GetProcessHeap(), 0, sizeof(IWineD3DSurface *) * object->presentParms.BackBufferCount);
1718 if(!object->backBuffer) {
1719 ERR("Out of memory\n");
1721 if (object->frontBuffer) {
1722 IUnknown *bufferParent;
1723 IWineD3DSurface_GetParent(object->frontBuffer, &bufferParent);
1724 IUnknown_Release(bufferParent); /* once for the get parent */
1725 if (IUnknown_Release(bufferParent) > 0) {
1726 FIXME("(%p) Something's still holding the front buffer\n",This);
1729 HeapFree(GetProcessHeap(), 0, object);
1730 return E_OUTOFMEMORY;
1733 for(i = 0; i < object->presentParms.BackBufferCount; i++) {
1734 TRACE("calling rendertarget CB\n");
1735 hr = D3DCB_CreateRenderTarget((IUnknown *) This->parent,
1736 object->presentParms.BackBufferWidth,
1737 object->presentParms.BackBufferHeight,
1738 object->presentParms.BackBufferFormat,
1739 object->presentParms.MultiSampleType,
1740 object->presentParms.MultiSampleQuality,
1741 TRUE /* Lockable */,
1742 &object->backBuffer[i],
1743 NULL /* pShared (always null)*/);
1744 if(hr == WINED3D_OK && object->backBuffer[i]) {
1745 IWineD3DSurface_SetContainer(object->backBuffer[i], (IWineD3DBase *)object);
1751 object->backBuffer = NULL;
1754 if (object->backBuffer != NULL) {
1756 glDrawBuffer(GL_BACK);
1757 checkGLcall("glDrawBuffer(GL_BACK)");
1760 /* Single buffering - draw to front buffer */
1762 glDrawBuffer(GL_FRONT);
1763 checkGLcall("glDrawBuffer(GL_FRONT)");
1767 /* Under directX swapchains share the depth stencil, so only create one depth-stencil */
1768 if (*(pPresentationParameters->EnableAutoDepthStencil) && hr == WINED3D_OK) {
1769 TRACE("Creating depth stencil buffer\n");
1770 if (This->depthStencilBuffer == NULL ) {
1771 hr = D3DCB_CreateDepthStencil((IUnknown *) This->parent,
1772 object->presentParms.BackBufferWidth,
1773 object->presentParms.BackBufferHeight,
1774 object->presentParms.AutoDepthStencilFormat,
1775 object->presentParms.MultiSampleType,
1776 object->presentParms.MultiSampleQuality,
1777 FALSE /* FIXME: Discard */,
1778 &This->depthStencilBuffer,
1779 NULL /* pShared (always null)*/ );
1780 if (This->depthStencilBuffer != NULL)
1781 IWineD3DSurface_SetContainer(This->depthStencilBuffer, 0);
1784 /** TODO: A check on width, height and multisample types
1785 *(since the zbuffer must be at least as large as the render target and have the same multisample parameters)
1786 ****************************/
1787 object->wantsDepthStencilBuffer = TRUE;
1789 object->wantsDepthStencilBuffer = FALSE;
1792 TRACE("FrontBuf @ %p, BackBuf @ %p, DepthStencil %d\n",object->frontBuffer, object->backBuffer ? object->backBuffer[0] : NULL, object->wantsDepthStencilBuffer);
1795 /*********************
1796 * init the default renderTarget management
1797 *******************/
1798 object->drawable = object->win;
1799 object->render_ctx = object->glCtx;
1801 if (hr == WINED3D_OK) {
1802 /*********************
1803 * Setup some defaults and clear down the buffers
1804 *******************/
1806 /** save current context and drawable **/
1807 oldContext = glXGetCurrentContext();
1808 oldDrawable = glXGetCurrentDrawable();
1810 TRACE("Activating context (display %p context %p drawable %ld)!\n", object->display, object->glCtx, object->win);
1811 if (glXMakeCurrent(object->display, object->win, object->glCtx) == False) {
1812 ERR("Error in setting current context (display %p context %p drawable %ld)!\n", object->display, object->glCtx, object->win);
1814 checkGLcall("glXMakeCurrent");
1816 TRACE("Setting up the screen\n");
1817 /* Clear the screen */
1818 glClearColor(1.0, 0.0, 0.0, 0.0);
1819 checkGLcall("glClearColor");
1822 glClearStencil(0xffff);
1824 checkGLcall("glClear");
1826 glColor3f(1.0, 1.0, 1.0);
1827 checkGLcall("glColor3f");
1829 glEnable(GL_LIGHTING);
1830 checkGLcall("glEnable");
1832 glLightModeli(GL_LIGHT_MODEL_LOCAL_VIEWER, GL_TRUE);
1833 checkGLcall("glLightModeli(GL_LIGHT_MODEL_LOCAL_VIEWER, GL_TRUE);");
1835 glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE_EXT);
1836 checkGLcall("glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE_EXT);");
1838 glLightModeli(GL_LIGHT_MODEL_COLOR_CONTROL, GL_SEPARATE_SPECULAR_COLOR);
1839 checkGLcall("glLightModeli(GL_LIGHT_MODEL_COLOR_CONTROL, GL_SEPARATE_SPECULAR_COLOR);");
1841 /* switch back to the original context (if there was one)*/
1842 if (This->swapchains) {
1843 /** TODO: restore the context and drawable **/
1844 glXMakeCurrent(object->display, oldDrawable, oldContext);
1849 TRACE("Set swapchain to %p\n", object);
1850 } else { /* something went wrong so clean up */
1851 IUnknown* bufferParent;
1852 if (object->frontBuffer) {
1854 IWineD3DSurface_GetParent(object->frontBuffer, &bufferParent);
1855 IUnknown_Release(bufferParent); /* once for the get parent */
1856 if (IUnknown_Release(bufferParent) > 0) {
1857 FIXME("(%p) Something's still holding the front buffer\n",This);
1860 if (object->backBuffer) {
1862 for(i = 0; i < object->presentParms.BackBufferCount; i++) {
1863 if(object->backBuffer[i]) {
1864 IWineD3DSurface_GetParent(object->backBuffer[i], &bufferParent);
1865 IUnknown_Release(bufferParent); /* once for the get parent */
1866 if (IUnknown_Release(bufferParent) > 0) {
1867 FIXME("(%p) Something's still holding the back buffer\n",This);
1871 HeapFree(GetProcessHeap(), 0, object->backBuffer);
1872 object->backBuffer = NULL;
1874 /* NOTE: don't clean up the depthstencil buffer because it belongs to the device */
1875 /* Clean up the context */
1876 /* check that we are the current context first (we shouldn't be though!) */
1877 if (object->glCtx != 0) {
1878 if(glXGetCurrentContext() == object->glCtx) {
1879 glXMakeCurrent(object->display, None, NULL);
1881 glXDestroyContext(object->display, object->glCtx);
1883 HeapFree(GetProcessHeap(), 0, object);
1890 /** NOTE: These are ahead of the other getters and setters to save using a forward declaration **/
1891 static UINT WINAPI IWineD3DDeviceImpl_GetNumberOfSwapChains(IWineD3DDevice *iface) {
1892 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
1893 TRACE("(%p)\n", This);
1895 return This->NumberOfSwapChains;
1898 static HRESULT WINAPI IWineD3DDeviceImpl_GetSwapChain(IWineD3DDevice *iface, UINT iSwapChain, IWineD3DSwapChain **pSwapChain) {
1899 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
1900 TRACE("(%p) : swapchain %d\n", This, iSwapChain);
1902 if(iSwapChain < This->NumberOfSwapChains) {
1903 *pSwapChain = This->swapchains[iSwapChain];
1904 IWineD3DSwapChain_AddRef(*pSwapChain);
1905 TRACE("(%p) returning %p\n", This, *pSwapChain);
1908 TRACE("Swapchain out of range\n");
1910 return WINED3DERR_INVALIDCALL;
1915 * Vertex Declaration
1917 static HRESULT WINAPI IWineD3DDeviceImpl_CreateVertexDeclaration(IWineD3DDevice* iface, CONST VOID* pDeclaration, IWineD3DVertexDeclaration** ppVertexDeclaration, IUnknown *parent) {
1918 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
1919 IWineD3DVertexDeclarationImpl *object = NULL;
1920 HRESULT hr = WINED3D_OK;
1921 TRACE("(%p) : directXVersion=%u, pFunction=%p, ppDecl=%p\n", This, ((IWineD3DImpl *)This->wineD3D)->dxVersion, pDeclaration, ppVertexDeclaration);
1922 D3DCREATEOBJECTINSTANCE(object, VertexDeclaration)
1925 hr = IWineD3DVertexDeclaration_SetDeclaration((IWineD3DVertexDeclaration *)object, (void *)pDeclaration);
1930 /* http://msdn.microsoft.com/archive/default.asp?url=/archive/en-us/directx9_c/directx/graphics/programmingguide/programmable/vertexshaders/vscreate.asp */
1931 static HRESULT WINAPI IWineD3DDeviceImpl_CreateVertexShader(IWineD3DDevice *iface, CONST DWORD *pDeclaration, CONST DWORD *pFunction, IWineD3DVertexShader **ppVertexShader, IUnknown *parent) {
1932 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
1933 IWineD3DVertexShaderImpl *object; /* NOTE: impl usage is ok, this is a create */
1934 HRESULT hr = WINED3D_OK;
1935 D3DCREATEOBJECTINSTANCE(object, VertexShader)
1936 object->baseShader.shader_ins = IWineD3DVertexShaderImpl_shader_ins;
1938 TRACE("(%p) : Created Vertex shader %p\n", This, *ppVertexShader);
1940 /* If a vertex declaration has been passed, save it to the vertex shader, this affects d3d8 only. */
1941 /* Further it needs to be set before calling SetFunction as SetFunction needs the declaration. */
1942 if (pDeclaration != NULL) {
1943 IWineD3DVertexDeclaration *vertexDeclaration;
1944 hr = IWineD3DDevice_CreateVertexDeclaration(iface, pDeclaration, &vertexDeclaration ,NULL);
1945 if (WINED3D_OK == hr) {
1946 TRACE("(%p) : Setting vertex declaration to %p\n", This, vertexDeclaration);
1947 object->vertexDeclaration = vertexDeclaration;
1949 FIXME("(%p) : Failed to set the declaration, returning WINED3DERR_INVALIDCALL\n", iface);
1950 IWineD3DVertexShader_Release(*ppVertexShader);
1951 return WINED3DERR_INVALIDCALL;
1955 hr = IWineD3DVertexShader_SetFunction(*ppVertexShader, pFunction);
1957 if (WINED3D_OK != hr) {
1958 FIXME("(%p) : Failed to set the function, returning WINED3DERR_INVALIDCALL\n", iface);
1959 IWineD3DVertexShader_Release(*ppVertexShader);
1960 return WINED3DERR_INVALIDCALL;
1963 #if 0 /* TODO: In D3D* SVP is atatched to the shader, in D3D9 it's attached to the device and isn't stored in the stateblock. */
1964 if(Usage == WINED3DUSAGE_SOFTWAREVERTEXPROCESSING) {
1975 static HRESULT WINAPI IWineD3DDeviceImpl_CreatePixelShader(IWineD3DDevice *iface, CONST DWORD *pFunction, IWineD3DPixelShader **ppPixelShader, IUnknown *parent) {
1976 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
1977 IWineD3DPixelShaderImpl *object; /* NOTE: impl allowed, this is a create */
1978 HRESULT hr = WINED3D_OK;
1980 D3DCREATEOBJECTINSTANCE(object, PixelShader)
1981 object->baseShader.shader_ins = IWineD3DPixelShaderImpl_shader_ins;
1982 hr = IWineD3DPixelShader_SetFunction(*ppPixelShader, pFunction);
1983 if (WINED3D_OK == hr) {
1984 TRACE("(%p) : Created Pixel shader %p\n", This, *ppPixelShader);
1986 WARN("(%p) : Failed to create pixel shader\n", This);
1992 static HRESULT WINAPI IWineD3DDeviceImpl_CreatePalette(IWineD3DDevice *iface, DWORD Flags, PALETTEENTRY *PalEnt, IWineD3DPalette **Palette, IUnknown *Parent) {
1993 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *) iface;
1994 IWineD3DPaletteImpl *object;
1996 TRACE("(%p)->(%lx, %p, %p, %p)\n", This, Flags, PalEnt, Palette, Parent);
1998 /* Create the new object */
1999 object = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(IWineD3DPaletteImpl));
2001 ERR("Out of memory when allocating memory for a IWineD3DPalette implementation\n");
2002 return E_OUTOFMEMORY;
2005 object->lpVtbl = &IWineD3DPalette_Vtbl;
2007 object->Flags = Flags;
2008 object->parent = Parent;
2009 object->wineD3DDevice = This;
2010 object->palNumEntries = IWineD3DPaletteImpl_Size(Flags);
2012 object->hpal = CreatePalette((const LOGPALETTE*)&(object->palVersion));
2015 HeapFree( GetProcessHeap(), 0, object);
2016 return E_OUTOFMEMORY;
2019 hr = IWineD3DPalette_SetEntries((IWineD3DPalette *) object, 0, 0, IWineD3DPaletteImpl_Size(Flags), PalEnt);
2021 IWineD3DPalette_Release((IWineD3DPalette *) object);
2025 *Palette = (IWineD3DPalette *) object;
2030 static HRESULT WINAPI IWineD3DDeviceImpl_Init3D(IWineD3DDevice *iface, WINED3DPRESENT_PARAMETERS* pPresentationParameters, D3DCB_CREATEADDITIONALSWAPCHAIN D3DCB_CreateAdditionalSwapChain) {
2031 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *) iface;
2032 IWineD3DSwapChainImpl *swapchain;
2034 TRACE("(%p)->(%p,%p)\n", This, pPresentationParameters, D3DCB_CreateAdditionalSwapChain);
2035 if(This->d3d_initialized) return WINED3DERR_INVALIDCALL;
2037 /* TODO: Test if OpenGL is compiled in and loaded */
2039 /* Setup the implicit swapchain */
2040 TRACE("Creating implicit swapchain\n");
2041 if (D3D_OK != D3DCB_CreateAdditionalSwapChain((IUnknown *) This->parent, pPresentationParameters, (IWineD3DSwapChain **)&swapchain) || swapchain == NULL) {
2042 WARN("Failed to create implicit swapchain\n");
2043 return WINED3DERR_INVALIDCALL;
2046 This->NumberOfSwapChains = 1;
2047 This->swapchains = HeapAlloc(GetProcessHeap(), 0, This->NumberOfSwapChains * sizeof(IWineD3DSwapChain *));
2048 if(!This->swapchains) {
2049 ERR("Out of memory!\n");
2050 IWineD3DSwapChain_Release( (IWineD3DSwapChain *) swapchain);
2051 return E_OUTOFMEMORY;
2053 This->swapchains[0] = (IWineD3DSwapChain *) swapchain;
2055 if(swapchain->backBuffer && swapchain->backBuffer[0]) {
2056 TRACE("Setting rendertarget to %p\n", swapchain->backBuffer);
2057 This->renderTarget = swapchain->backBuffer[0];
2060 TRACE("Setting rendertarget to %p\n", swapchain->frontBuffer);
2061 This->renderTarget = swapchain->frontBuffer;
2063 IWineD3DSurface_AddRef(This->renderTarget);
2064 /* Depth Stencil support */
2065 This->stencilBufferTarget = This->depthStencilBuffer;
2066 if (NULL != This->stencilBufferTarget) {
2067 IWineD3DSurface_AddRef(This->stencilBufferTarget);
2070 /* Set up some starting GL setup */
2073 * Initialize openGL extension related variables
2074 * with Default values
2077 ((IWineD3DImpl *) This->wineD3D)->isGLInfoValid = IWineD3DImpl_FillGLCaps( This->wineD3D, swapchain->display);
2078 /* Setup all the devices defaults */
2079 IWineD3DStateBlock_InitStartupStateBlock((IWineD3DStateBlock *)This->stateBlock);
2081 IWineD3DImpl_CheckGraphicsMemory();
2085 /* Initialize our list of GLSL programs */
2086 list_init(&This->glsl_shader_progs);
2088 { /* Set a default viewport */
2092 vp.Width = *(pPresentationParameters->BackBufferWidth);
2093 vp.Height = *(pPresentationParameters->BackBufferHeight);
2096 IWineD3DDevice_SetViewport((IWineD3DDevice *)This, &vp);
2099 /* Initialize the current view state */
2100 This->modelview_valid = 1;
2101 This->proj_valid = 0;
2102 This->view_ident = 1;
2103 This->last_was_rhw = 0;
2104 glGetIntegerv(GL_MAX_LIGHTS, &This->maxConcurrentLights);
2105 TRACE("(%p) All defaults now set up, leaving Init3D with %p\n", This, This);
2107 /* Clear the screen */
2108 IWineD3DDevice_Clear((IWineD3DDevice *) This, 0, NULL, D3DCLEAR_STENCIL|D3DCLEAR_ZBUFFER|D3DCLEAR_TARGET, 0x00, 1.0, 0);
2110 This->d3d_initialized = TRUE;
2114 static HRESULT WINAPI IWineD3DDeviceImpl_Uninit3D(IWineD3DDevice *iface) {
2115 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *) iface;
2117 IUnknown* stencilBufferParent;
2118 IUnknown* swapChainParent;
2120 TRACE("(%p)\n", This);
2122 if(!This->d3d_initialized) return WINED3DERR_INVALIDCALL;
2124 /* Delete the mouse cursor texture */
2125 if(This->cursorTexture) {
2127 glDeleteTextures(1, &This->cursorTexture);
2129 This->cursorTexture = 0;
2132 for(sampler = 0; sampler < GL_LIMITS(sampler_stages); ++sampler) {
2133 IWineD3DDevice_SetTexture(iface, sampler, NULL);
2136 /* Release the buffers (with sanity checks)*/
2137 TRACE("Releasing the depth stencil buffer at %p\n", This->stencilBufferTarget);
2138 if(This->stencilBufferTarget != NULL && (IWineD3DSurface_Release(This->stencilBufferTarget) >0)){
2139 if(This->depthStencilBuffer != This->stencilBufferTarget)
2140 FIXME("(%p) Something's still holding the depthStencilBuffer\n",This);
2142 This->stencilBufferTarget = NULL;
2144 TRACE("Releasing the render target at %p\n", This->renderTarget);
2145 if(IWineD3DSurface_Release(This->renderTarget) >0){
2146 /* This check is a bit silly, itshould be in swapchain_release FIXME("(%p) Something's still holding the renderTarget\n",This); */
2148 TRACE("Setting rendertarget to NULL\n");
2149 This->renderTarget = NULL;
2151 if (This->depthStencilBuffer) {
2152 IWineD3DSurface_GetParent(This->depthStencilBuffer, &stencilBufferParent);
2153 IUnknown_Release(stencilBufferParent); /* once for the get parent */
2154 if(IUnknown_Release(stencilBufferParent) >0){ /* the second time for when it was created */
2155 FIXME("(%p) Something's still holding the depthStencilBuffer\n",This);
2157 This->depthStencilBuffer = NULL;
2160 for(i=0; i < This->NumberOfSwapChains; i++) {
2161 TRACE("Releasing the implicit swapchain %d\n", i);
2162 /* Swapchain 0 is special because it's created in startup with a hanging parent, so we have to release its parent now */
2163 IWineD3DSwapChain_GetParent(This->swapchains[i], &swapChainParent);
2164 IUnknown_Release(swapChainParent); /* once for the get parent */
2165 if (IUnknown_Release(swapChainParent) > 0) { /* the second time for when it was created */
2166 FIXME("(%p) Something's still holding the implicit swapchain\n", This);
2170 HeapFree(GetProcessHeap(), 0, This->swapchains);
2171 This->swapchains = NULL;
2172 This->NumberOfSwapChains = 0;
2174 This->d3d_initialized = FALSE;
2178 static void WINAPI IWineD3DDeviceImpl_SetFullscreen(IWineD3DDevice *iface, BOOL fullscreen) {
2179 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *) iface;
2180 TRACE("(%p) Setting DDraw fullscreen mode to %s\n", This, fullscreen ? "true" : "false");
2182 /* DirectDraw apps can change between fullscreen and windowed mode after device creation with
2183 * IDirectDraw7::SetCooperativeLevel. The GDI surface implementation needs to know this.
2184 * DDraw doesn't necessarilly have a swapchain, so we have to store the fullscreen flag
2187 This->ddraw_fullscreen = fullscreen;
2190 static HRESULT WINAPI IWineD3DDeviceImpl_EnumDisplayModes(IWineD3DDevice *iface, DWORD Flags, UINT Width, UINT Height, WINED3DFORMAT pixelformat, LPVOID context, D3DCB_ENUMDISPLAYMODESCALLBACK callback) {
2191 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2195 const PixelFormatDesc *formatDesc = getFormatDescEntry(pixelformat);
2197 TRACE("(%p)->(%lx,%d,%d,%d,%p,%p)\n", This, Flags, Width, Height, pixelformat, context, callback);
2199 for (i = 0; EnumDisplaySettingsExW(NULL, i, &DevModeW, 0); i++) {
2200 /* Ignore some modes if a description was passed */
2201 if ( (Width > 0) && (Width != DevModeW.dmPelsWidth)) continue;
2202 if ( (Height > 0) && (Height != DevModeW.dmPelsHeight)) continue;
2203 if ( (pixelformat != WINED3DFMT_UNKNOWN) && ( formatDesc->bpp != DevModeW.dmBitsPerPel) ) continue;
2205 TRACE("Enumerating %ldx%ld@%s\n", DevModeW.dmPelsWidth, DevModeW.dmPelsHeight, debug_d3dformat(pixelformat_for_depth(DevModeW.dmBitsPerPel)));
2207 if (callback((IUnknown *) This, (UINT) DevModeW.dmPelsWidth, (UINT) DevModeW.dmPelsHeight, pixelformat_for_depth(DevModeW.dmBitsPerPel), 60.0, context) == DDENUMRET_CANCEL)
2214 static HRESULT WINAPI IWineD3DDeviceImpl_SetDisplayMode(IWineD3DDevice *iface, UINT iSwapChain, WINED3DDISPLAYMODE* pMode) {
2216 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2218 const PixelFormatDesc *formatDesc = getFormatDescEntry(pMode->Format);
2220 TRACE("(%p)->(%d,%p) Mode=%dx%dx@%d, %s\n", This, iSwapChain, pMode, pMode->Width, pMode->Height, pMode->RefreshRate, debug_d3dformat(pMode->Format));
2222 /* Resize the screen even without a window:
2223 * The app could have unset it with SetCooperativeLevel, but not called
2224 * RestoreDisplayMode first. Then the release will call RestoreDisplayMode,
2225 * but we don't have any hwnd
2228 devmode.dmFields = DM_BITSPERPEL | DM_PELSWIDTH | DM_PELSHEIGHT;
2229 devmode.dmBitsPerPel = formatDesc->bpp * 8;
2230 if(devmode.dmBitsPerPel == 24) devmode.dmBitsPerPel = 32;
2231 devmode.dmPelsWidth = pMode->Width;
2232 devmode.dmPelsHeight = pMode->Height;
2234 devmode.dmDisplayFrequency = pMode->RefreshRate;
2235 if (pMode->RefreshRate != 0) {
2236 devmode.dmFields |= DM_DISPLAYFREQUENCY;
2239 /* Only change the mode if necessary */
2240 if( (This->ddraw_width == pMode->Width) &&
2241 (This->ddraw_height == pMode->Height) &&
2242 (This->ddraw_format == pMode->Format) &&
2243 (pMode->RefreshRate == 0) ) {
2247 ret = ChangeDisplaySettingsExW(NULL, &devmode, NULL, CDS_FULLSCREEN, NULL);
2248 if (ret != DISP_CHANGE_SUCCESSFUL) {
2249 if(devmode.dmDisplayFrequency != 0) {
2250 WARN("ChangeDisplaySettingsExW failed, trying without the refresh rate\n");
2251 devmode.dmFields &= ~DM_DISPLAYFREQUENCY;
2252 devmode.dmDisplayFrequency = 0;
2253 ret = ChangeDisplaySettingsExW(NULL, &devmode, NULL, CDS_FULLSCREEN, NULL) != DISP_CHANGE_SUCCESSFUL;
2255 if(ret != DISP_CHANGE_SUCCESSFUL) {
2256 return DDERR_INVALIDMODE;
2260 /* Store the new values */
2261 This->ddraw_width = pMode->Width;
2262 This->ddraw_height = pMode->Height;
2263 This->ddraw_format = pMode->Format;
2265 /* Only do this with a window of course */
2266 if(This->ddraw_window)
2267 MoveWindow(This->ddraw_window, 0, 0, pMode->Width, pMode->Height, TRUE);
2272 static HRESULT WINAPI IWineD3DDeviceImpl_GetDirect3D(IWineD3DDevice *iface, IWineD3D **ppD3D) {
2273 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2274 *ppD3D= This->wineD3D;
2275 TRACE("(%p) : wineD3D returning %p\n", This, *ppD3D);
2276 IWineD3D_AddRef(*ppD3D);
2280 static UINT WINAPI IWineD3DDeviceImpl_GetAvailableTextureMem(IWineD3DDevice *iface) {
2281 /** NOTE: There's a probably a hack-around for this one by putting as many pbuffers, VBO's (or whatever)
2282 * Into the video ram as possible and seeing how many fit
2283 * you can also get the correct initial value from nvidia and ATI's driver via X
2284 * texture memory is video memory + AGP memory
2285 *******************/
2286 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2287 static BOOL showfixmes = TRUE;
2289 FIXME("(%p) : stub, simulating %dMB for now, returning %dMB left\n", This,
2290 (wined3d_settings.emulated_textureram/(1024*1024)),
2291 ((wined3d_settings.emulated_textureram - wineD3DGlobalStatistics->glsurfaceram) / (1024*1024)));
2294 TRACE("(%p) : simulating %dMB, returning %dMB left\n", This,
2295 (wined3d_settings.emulated_textureram/(1024*1024)),
2296 ((wined3d_settings.emulated_textureram - wineD3DGlobalStatistics->glsurfaceram) / (1024*1024)));
2297 /* return simulated texture memory left */
2298 return (wined3d_settings.emulated_textureram - wineD3DGlobalStatistics->glsurfaceram);
2306 static HRESULT WINAPI IWineD3DDeviceImpl_SetFVF(IWineD3DDevice *iface, DWORD fvf) {
2307 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2308 HRESULT hr = WINED3D_OK;
2310 /* Update the current state block */
2311 This->updateStateBlock->fvf = fvf;
2312 This->updateStateBlock->changed.fvf = TRUE;
2313 This->updateStateBlock->set.fvf = TRUE;
2315 TRACE("(%p) : FVF Shader FVF set to %lx\n", This, fvf);
2320 static HRESULT WINAPI IWineD3DDeviceImpl_GetFVF(IWineD3DDevice *iface, DWORD *pfvf) {
2321 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2322 TRACE("(%p) : GetFVF returning %lx\n", This, This->stateBlock->fvf);
2323 *pfvf = This->stateBlock->fvf;
2328 * Get / Set Stream Source
2330 static HRESULT WINAPI IWineD3DDeviceImpl_SetStreamSource(IWineD3DDevice *iface, UINT StreamNumber,IWineD3DVertexBuffer* pStreamData, UINT OffsetInBytes, UINT Stride) {
2331 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2332 IWineD3DVertexBuffer *oldSrc;
2334 /**TODO: instance and index data, see
2335 http://msdn.microsoft.com/library/default.asp?url=/library/en-us/directx9_c/directx/graphics/programmingguide/advancedtopics/DrawingMultipleInstances.asp
2337 http://msdn.microsoft.com/library/default.asp?url=/library/en-us/directx9_c/directx/graphics/reference/d3d/interfaces/idirect3ddevice9/SetStreamSourceFreq.asp
2340 /* D3d9 only, but shouldn't hurt d3d8 */
2343 streamFlags = StreamNumber &(D3DSTREAMSOURCE_INDEXEDDATA | D3DSTREAMSOURCE_INSTANCEDATA);
2345 if (streamFlags & D3DSTREAMSOURCE_INDEXEDDATA) {
2346 FIXME("stream index data not supported\n");
2348 if (streamFlags & D3DSTREAMSOURCE_INDEXEDDATA) {
2349 FIXME("stream instance data not supported\n");
2353 StreamNumber&= ~(D3DSTREAMSOURCE_INDEXEDDATA | D3DSTREAMSOURCE_INSTANCEDATA);
2355 if (StreamNumber >= MAX_STREAMS) {
2356 WARN("Stream out of range %d\n", StreamNumber);
2357 return WINED3DERR_INVALIDCALL;
2360 oldSrc = This->stateBlock->streamSource[StreamNumber];
2361 TRACE("(%p) : StreamNo: %d, OldStream (%p), NewStream (%p), NewStride %d\n", This, StreamNumber, oldSrc, pStreamData, Stride);
2363 This->updateStateBlock->changed.streamSource[StreamNumber] = TRUE;
2364 This->updateStateBlock->set.streamSource[StreamNumber] = TRUE;
2365 This->updateStateBlock->streamStride[StreamNumber] = Stride;
2366 This->updateStateBlock->streamSource[StreamNumber] = pStreamData;
2367 This->updateStateBlock->streamOffset[StreamNumber] = OffsetInBytes;
2368 This->updateStateBlock->streamFlags[StreamNumber] = streamFlags;
2370 /* Handle recording of state blocks */
2371 if (This->isRecordingState) {
2372 TRACE("Recording... not performing anything\n");
2376 /* Same stream object: no action */
2377 if (oldSrc == pStreamData)
2380 /* Need to do a getParent and pass the reffs up */
2381 /* MSDN says ..... When an application no longer holds a references to this interface, the interface will automatically be freed.
2382 which suggests that we shouldn't be ref counting? and do need a _release on the stream source to reset the stream source
2383 so for now, just count internally */
2384 if (pStreamData != NULL) {
2385 IWineD3DVertexBufferImpl *vbImpl = (IWineD3DVertexBufferImpl *) pStreamData;
2386 if( (vbImpl->Flags & VBFLAG_STREAM) && vbImpl->stream != StreamNumber) {
2387 WARN("Assigning a Vertex Buffer to stream %d which is already assigned to stream %d\n", StreamNumber, vbImpl->stream);
2389 vbImpl->stream = StreamNumber;
2390 vbImpl->Flags |= VBFLAG_STREAM;
2391 IWineD3DVertexBuffer_AddRef(pStreamData);
2393 if (oldSrc != NULL) {
2394 ((IWineD3DVertexBufferImpl *) oldSrc)->Flags &= ~VBFLAG_STREAM;
2395 IWineD3DVertexBuffer_Release(oldSrc);
2401 static HRESULT WINAPI IWineD3DDeviceImpl_GetStreamSource(IWineD3DDevice *iface, UINT StreamNumber,IWineD3DVertexBuffer** pStream, UINT *pOffset, UINT* pStride) {
2402 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2405 TRACE("(%p) : StreamNo: %d, Stream (%p), Stride %d\n", This, StreamNumber,
2406 This->stateBlock->streamSource[StreamNumber], This->stateBlock->streamStride[StreamNumber]);
2409 streamFlags = StreamNumber &(D3DSTREAMSOURCE_INDEXEDDATA | D3DSTREAMSOURCE_INSTANCEDATA);
2411 if (streamFlags & D3DSTREAMSOURCE_INDEXEDDATA) {
2412 FIXME("stream index data not supported\n");
2414 if (streamFlags & D3DSTREAMSOURCE_INDEXEDDATA) {
2415 FIXME("stream instance data not supported\n");
2419 StreamNumber&= ~(D3DSTREAMSOURCE_INDEXEDDATA | D3DSTREAMSOURCE_INSTANCEDATA);
2421 if (StreamNumber >= MAX_STREAMS) {
2422 WARN("Stream out of range %d\n", StreamNumber);
2423 return WINED3DERR_INVALIDCALL;
2425 *pStream = This->stateBlock->streamSource[StreamNumber];
2426 *pStride = This->stateBlock->streamStride[StreamNumber];
2428 *pOffset = This->stateBlock->streamOffset[StreamNumber];
2431 if (*pStream == NULL) {
2432 FIXME("Attempting to get an empty stream %d, returning WINED3DERR_INVALIDCALL\n", StreamNumber);
2433 return WINED3DERR_INVALIDCALL;
2436 IWineD3DVertexBuffer_AddRef(*pStream); /* We have created a new reference to the VB */
2440 /*Should be quite easy, just an extension of vertexdata
2442 http://msdn.microsoft.com/archive/default.asp?url=/archive/en-us/directx9_c_Summer_04/directx/graphics/programmingguide/advancedtopics/DrawingMultipleInstances.asp
2444 The divider is a bit odd though
2446 VertexOffset = StartVertex / Divider * StreamStride +
2447 VertexIndex / Divider * StreamStride + StreamOffset
2450 static HRESULT WINAPI IWineD3DDeviceImpl_SetStreamSourceFreq(IWineD3DDevice *iface, UINT StreamNumber, UINT Divider) {
2451 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2453 TRACE("(%p) StreamNumber(%d), Divider(%d)\n", This, StreamNumber, Divider);
2454 This->updateStateBlock->streamFlags[StreamNumber] = Divider & (D3DSTREAMSOURCE_INSTANCEDATA | D3DSTREAMSOURCE_INDEXEDDATA );
2456 This->updateStateBlock->changed.streamFreq[StreamNumber] = TRUE;
2457 This->updateStateBlock->set.streamFreq[StreamNumber] = TRUE;
2458 This->updateStateBlock->streamFreq[StreamNumber] = Divider & 0x7FFFFF;
2460 if (This->updateStateBlock->streamFlags[StreamNumber] || This->updateStateBlock->streamFreq[StreamNumber] != 1) {
2461 FIXME("Stream indexing not fully supported\n");
2467 static HRESULT WINAPI IWineD3DDeviceImpl_GetStreamSourceFreq(IWineD3DDevice *iface, UINT StreamNumber, UINT* Divider) {
2468 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2470 TRACE("(%p) StreamNumber(%d), Divider(%p)\n", This, StreamNumber, Divider);
2471 *Divider = This->updateStateBlock->streamFreq[StreamNumber] | This->updateStateBlock->streamFlags[StreamNumber];
2473 TRACE("(%p) : returning %d\n", This, *Divider);
2479 * Get / Set & Multiply Transform
2481 static HRESULT WINAPI IWineD3DDeviceImpl_SetTransform(IWineD3DDevice *iface, D3DTRANSFORMSTATETYPE d3dts, CONST D3DMATRIX* lpmatrix) {
2482 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2484 /* Most of this routine, comments included copied from ddraw tree initially: */
2485 TRACE("(%p) : Transform State=%s\n", This, debug_d3dtstype(d3dts));
2487 /* Handle recording of state blocks */
2488 if (This->isRecordingState) {
2489 TRACE("Recording... not performing anything\n");
2490 This->updateStateBlock->changed.transform[d3dts] = TRUE;
2491 This->updateStateBlock->set.transform[d3dts] = TRUE;
2492 memcpy(&This->updateStateBlock->transforms[d3dts], lpmatrix, sizeof(D3DMATRIX));
2497 * If the new matrix is the same as the current one,
2498 * we cut off any further processing. this seems to be a reasonable
2499 * optimization because as was noticed, some apps (warcraft3 for example)
2500 * tend towards setting the same matrix repeatedly for some reason.
2502 * From here on we assume that the new matrix is different, wherever it matters.
2504 if (!memcmp(&This->stateBlock->transforms[d3dts].u.m[0][0], lpmatrix, sizeof(D3DMATRIX))) {
2505 TRACE("The app is setting the same matrix over again\n");
2508 conv_mat(lpmatrix, &This->stateBlock->transforms[d3dts].u.m[0][0]);
2512 ScreenCoord = ProjectionMat * ViewMat * WorldMat * ObjectCoord
2513 where ViewMat = Camera space, WorldMat = world space.
2515 In OpenGL, camera and world space is combined into GL_MODELVIEW
2516 matrix. The Projection matrix stay projection matrix.
2519 /* Capture the times we can just ignore the change for now */
2520 if (d3dts == WINED3DTS_WORLDMATRIX(0)) {
2521 This->modelview_valid = FALSE;
2524 } else if (d3dts == WINED3DTS_PROJECTION) {
2525 This->proj_valid = FALSE;
2528 } else if (d3dts >= WINED3DTS_WORLDMATRIX(1) && d3dts <= WINED3DTS_WORLDMATRIX(255)) {
2529 /* Indexed Vertex Blending Matrices 256 -> 511 */
2530 /* Use arb_vertex_blend or NV_VERTEX_WEIGHTING? */
2531 FIXME("WINED3DTS_WORLDMATRIX(1..255) not handled\n");
2535 /* Now we really are going to have to change a matrix */
2538 if (d3dts >= WINED3DTS_TEXTURE0 && d3dts <= WINED3DTS_TEXTURE7) { /* handle texture matrices */
2539 /* This is now set with the texture unit states, it may be a good idea to flag the change though! */
2540 } else if (d3dts == WINED3DTS_VIEW) { /* handle the VIEW matrice */
2543 /* If we are changing the View matrix, reset the light and clipping planes to the new view
2544 * NOTE: We have to reset the positions even if the light/plane is not currently
2545 * enabled, since the call to enable it will not reset the position.
2546 * NOTE2: Apparently texture transforms do NOT need reapplying
2549 PLIGHTINFOEL *lightChain = NULL;
2550 This->modelview_valid = FALSE;
2551 This->view_ident = !memcmp(lpmatrix, identity, 16 * sizeof(float));
2553 glMatrixMode(GL_MODELVIEW);
2554 checkGLcall("glMatrixMode(GL_MODELVIEW)");
2556 glLoadMatrixf((float *)lpmatrix);
2557 checkGLcall("glLoadMatrixf(...)");
2560 lightChain = This->stateBlock->lights;
2561 while (lightChain && lightChain->glIndex != -1) {
2562 glLightfv(GL_LIGHT0 + lightChain->glIndex, GL_POSITION, lightChain->lightPosn);
2563 checkGLcall("glLightfv posn");
2564 glLightfv(GL_LIGHT0 + lightChain->glIndex, GL_SPOT_DIRECTION, lightChain->lightDirn);
2565 checkGLcall("glLightfv dirn");
2566 lightChain = lightChain->next;
2569 /* Reset Clipping Planes if clipping is enabled */
2570 for (k = 0; k < GL_LIMITS(clipplanes); k++) {
2571 glClipPlane(GL_CLIP_PLANE0 + k, This->stateBlock->clipplane[k]);
2572 checkGLcall("glClipPlane");
2576 } else { /* What was requested!?? */
2577 WARN("invalid matrix specified: %i\n", d3dts);
2580 /* Release lock, all done */
2585 static HRESULT WINAPI IWineD3DDeviceImpl_GetTransform(IWineD3DDevice *iface, D3DTRANSFORMSTATETYPE State, D3DMATRIX* pMatrix) {
2586 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2587 TRACE("(%p) : for Transform State %s\n", This, debug_d3dtstype(State));
2588 memcpy(pMatrix, &This->stateBlock->transforms[State], sizeof(D3DMATRIX));
2592 static HRESULT WINAPI IWineD3DDeviceImpl_MultiplyTransform(IWineD3DDevice *iface, D3DTRANSFORMSTATETYPE State, CONST D3DMATRIX* pMatrix) {
2593 D3DMATRIX *mat = NULL;
2596 /* Note: Using 'updateStateBlock' rather than 'stateblock' in the code
2597 * below means it will be recorded in a state block change, but it
2598 * works regardless where it is recorded.
2599 * If this is found to be wrong, change to StateBlock.
2601 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2602 TRACE("(%p) : For state %s\n", This, debug_d3dtstype(State));
2604 if (State < HIGHEST_TRANSFORMSTATE)
2606 mat = &This->updateStateBlock->transforms[State];
2608 FIXME("Unhandled transform state!!\n");
2611 multiply_matrix(&temp, mat, (D3DMATRIX *) pMatrix);
2613 /* Apply change via set transform - will reapply to eg. lights this way */
2614 return IWineD3DDeviceImpl_SetTransform(iface, State, &temp);
2619 * WARNING: This code relies on the fact that D3DLIGHT8 == D3DLIGHT9
2621 /* Note lights are real special cases. Although the device caps state only eg. 8 are supported,
2622 you can reference any indexes you want as long as that number max are enabled at any
2623 one point in time! Therefore since the indexes can be anything, we need a linked list of them.
2624 However, this causes stateblock problems. When capturing the state block, I duplicate the list,
2625 but when recording, just build a chain pretty much of commands to be replayed. */
2627 static HRESULT WINAPI IWineD3DDeviceImpl_SetLight(IWineD3DDevice *iface, DWORD Index, CONST WINED3DLIGHT* pLight) {
2629 PLIGHTINFOEL *object, *temp;
2631 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2632 TRACE("(%p) : Idx(%ld), pLight(%p)\n", This, Index, pLight);
2634 /* If recording state block, just add to end of lights chain */
2635 if (This->isRecordingState) {
2636 object = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(PLIGHTINFOEL));
2637 if (NULL == object) {
2638 return WINED3DERR_OUTOFVIDEOMEMORY;
2640 memcpy(&object->OriginalParms, pLight, sizeof(D3DLIGHT9));
2641 object->OriginalIndex = Index;
2642 object->glIndex = -1;
2643 object->changed = TRUE;
2645 /* Add to the END of the chain of lights changes to be replayed */
2646 if (This->updateStateBlock->lights == NULL) {
2647 This->updateStateBlock->lights = object;
2649 temp = This->updateStateBlock->lights;
2650 while (temp->next != NULL) temp=temp->next;
2651 temp->next = object;
2653 TRACE("Recording... not performing anything more\n");
2657 /* Ok, not recording any longer so do real work */
2658 object = This->stateBlock->lights;
2659 while (object != NULL && object->OriginalIndex != Index) object = object->next;
2661 /* If we didn't find it in the list of lights, time to add it */
2662 if (object == NULL) {
2663 PLIGHTINFOEL *insertAt,*prevPos;
2665 object = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(PLIGHTINFOEL));
2666 if (NULL == object) {
2667 return WINED3DERR_OUTOFVIDEOMEMORY;
2669 object->OriginalIndex = Index;
2670 object->glIndex = -1;
2672 /* Add it to the front of list with the idea that lights will be changed as needed
2673 BUT after any lights currently assigned GL indexes */
2674 insertAt = This->stateBlock->lights;
2676 while (insertAt != NULL && insertAt->glIndex != -1) {
2678 insertAt = insertAt->next;
2681 if (insertAt == NULL && prevPos == NULL) { /* Start of list */
2682 This->stateBlock->lights = object;
2683 } else if (insertAt == NULL) { /* End of list */
2684 prevPos->next = object;
2685 object->prev = prevPos;
2686 } else { /* Middle of chain */
2687 if (prevPos == NULL) {
2688 This->stateBlock->lights = object;
2690 prevPos->next = object;
2692 object->prev = prevPos;
2693 object->next = insertAt;
2694 insertAt->prev = object;
2698 /* Initialize the object */
2699 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,
2700 pLight->Diffuse.r, pLight->Diffuse.g, pLight->Diffuse.b, pLight->Diffuse.a,
2701 pLight->Specular.r, pLight->Specular.g, pLight->Specular.b, pLight->Specular.a,
2702 pLight->Ambient.r, pLight->Ambient.g, pLight->Ambient.b, pLight->Ambient.a);
2703 TRACE("... Pos(%f,%f,%f), Dirn(%f,%f,%f)\n", pLight->Position.x, pLight->Position.y, pLight->Position.z,
2704 pLight->Direction.x, pLight->Direction.y, pLight->Direction.z);
2705 TRACE("... Range(%f), Falloff(%f), Theta(%f), Phi(%f)\n", pLight->Range, pLight->Falloff, pLight->Theta, pLight->Phi);
2707 /* Save away the information */
2708 memcpy(&object->OriginalParms, pLight, sizeof(D3DLIGHT9));
2710 switch (pLight->Type) {
2711 case D3DLIGHT_POINT:
2713 object->lightPosn[0] = pLight->Position.x;
2714 object->lightPosn[1] = pLight->Position.y;
2715 object->lightPosn[2] = pLight->Position.z;
2716 object->lightPosn[3] = 1.0f;
2717 object->cutoff = 180.0f;
2721 case D3DLIGHT_DIRECTIONAL:
2723 object->lightPosn[0] = -pLight->Direction.x;
2724 object->lightPosn[1] = -pLight->Direction.y;
2725 object->lightPosn[2] = -pLight->Direction.z;
2726 object->lightPosn[3] = 0.0;
2727 object->exponent = 0.0f;
2728 object->cutoff = 180.0f;
2733 object->lightPosn[0] = pLight->Position.x;
2734 object->lightPosn[1] = pLight->Position.y;
2735 object->lightPosn[2] = pLight->Position.z;
2736 object->lightPosn[3] = 1.0;
2739 object->lightDirn[0] = pLight->Direction.x;
2740 object->lightDirn[1] = pLight->Direction.y;
2741 object->lightDirn[2] = pLight->Direction.z;
2742 object->lightDirn[3] = 1.0;
2745 * opengl-ish and d3d-ish spot lights use too different models for the
2746 * light "intensity" as a function of the angle towards the main light direction,
2747 * so we only can approximate very roughly.
2748 * however spot lights are rather rarely used in games (if ever used at all).
2749 * furthermore if still used, probably nobody pays attention to such details.
2751 if (pLight->Falloff == 0) {
2754 rho = pLight->Theta + (pLight->Phi - pLight->Theta)/(2*pLight->Falloff);
2756 if (rho < 0.0001) rho = 0.0001f;
2757 object->exponent = -0.3/log(cos(rho/2));
2758 if (object->exponent > 128.0) {
2759 object->exponent = 128.0;
2761 object->cutoff = pLight->Phi*90/M_PI;
2767 FIXME("Unrecognized light type %d\n", pLight->Type);
2770 /* Update the live definitions if the light is currently assigned a glIndex */
2771 if (object->glIndex != -1) {
2772 setup_light(iface, object->glIndex, object);
2777 static HRESULT WINAPI IWineD3DDeviceImpl_GetLight(IWineD3DDevice *iface, DWORD Index, WINED3DLIGHT* pLight) {
2778 PLIGHTINFOEL *lightInfo = NULL;
2779 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2780 TRACE("(%p) : Idx(%ld), pLight(%p)\n", This, Index, pLight);
2782 /* Locate the light in the live lights */
2783 lightInfo = This->stateBlock->lights;
2784 while (lightInfo != NULL && lightInfo->OriginalIndex != Index) lightInfo = lightInfo->next;
2786 if (lightInfo == NULL) {
2787 TRACE("Light information requested but light not defined\n");
2788 return WINED3DERR_INVALIDCALL;
2791 memcpy(pLight, &lightInfo->OriginalParms, sizeof(D3DLIGHT9));
2796 * Get / Set Light Enable
2797 * (Note for consistency, renamed d3dx function by adding the 'set' prefix)
2799 static HRESULT WINAPI IWineD3DDeviceImpl_SetLightEnable(IWineD3DDevice *iface, DWORD Index, BOOL Enable) {
2800 PLIGHTINFOEL *lightInfo = NULL;
2801 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2802 TRACE("(%p) : Idx(%ld), enable? %d\n", This, Index, Enable);
2804 /* Tests show true = 128...not clear why */
2806 Enable = Enable? 128: 0;
2808 /* If recording state block, just add to end of lights chain with changedEnable set to true */
2809 if (This->isRecordingState) {
2810 lightInfo = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(PLIGHTINFOEL));
2811 if (NULL == lightInfo) {
2812 return WINED3DERR_OUTOFVIDEOMEMORY;
2814 lightInfo->OriginalIndex = Index;
2815 lightInfo->glIndex = -1;
2816 lightInfo->enabledChanged = TRUE;
2817 lightInfo->lightEnabled = Enable;
2819 /* Add to the END of the chain of lights changes to be replayed */
2820 if (This->updateStateBlock->lights == NULL) {
2821 This->updateStateBlock->lights = lightInfo;
2823 PLIGHTINFOEL *temp = This->updateStateBlock->lights;
2824 while (temp->next != NULL) temp=temp->next;
2825 temp->next = lightInfo;
2827 TRACE("Recording... not performing anything more\n");
2831 /* Not recording... So, locate the light in the live lights */
2832 lightInfo = This->stateBlock->lights;
2833 while (lightInfo != NULL && lightInfo->OriginalIndex != Index) lightInfo = lightInfo->next;
2835 /* Special case - enabling an undefined light creates one with a strict set of parms! */
2836 if (lightInfo == NULL) {
2838 TRACE("Light enabled requested but light not defined, so defining one!\n");
2839 IWineD3DDeviceImpl_SetLight(iface, Index, &WINED3D_default_light);
2841 /* Search for it again! Should be fairly quick as near head of list */
2842 lightInfo = This->stateBlock->lights;
2843 while (lightInfo != NULL && lightInfo->OriginalIndex != Index) lightInfo = lightInfo->next;
2844 if (lightInfo == NULL) {
2845 FIXME("Adding default lights has failed dismally\n");
2846 return WINED3DERR_INVALIDCALL;
2850 /* OK, we now have a light... */
2851 if (Enable == FALSE) {
2853 /* If we are disabling it, check it was enabled, and
2854 still only do something if it has assigned a glIndex (which it should have!) */
2855 if ((lightInfo->lightEnabled) && (lightInfo->glIndex != -1)) {
2856 TRACE("Disabling light set up at gl idx %ld\n", lightInfo->glIndex);
2858 glDisable(GL_LIGHT0 + lightInfo->glIndex);
2859 checkGLcall("glDisable GL_LIGHT0+Index");
2862 TRACE("Nothing to do as light was not enabled\n");
2864 lightInfo->lightEnabled = Enable;
2867 /* We are enabling it. If it is enabled, it's really simple */
2868 if (lightInfo->lightEnabled) {
2870 TRACE("Nothing to do as light was enabled\n");
2872 /* If it already has a glIndex, it's still simple */
2873 } else if (lightInfo->glIndex != -1) {
2874 TRACE("Reusing light as already set up at gl idx %ld\n", lightInfo->glIndex);
2875 lightInfo->lightEnabled = Enable;
2877 glEnable(GL_LIGHT0 + lightInfo->glIndex);
2878 checkGLcall("glEnable GL_LIGHT0+Index already setup");
2881 /* Otherwise got to find space - lights are ordered gl indexes first */
2883 PLIGHTINFOEL *bsf = NULL;
2884 PLIGHTINFOEL *pos = This->stateBlock->lights;
2885 PLIGHTINFOEL *prev = NULL;
2889 /* Try to minimize changes as much as possible */
2890 while (pos != NULL && pos->glIndex != -1 && Index < This->maxConcurrentLights) {
2892 /* Try to remember which index can be replaced if necessary */
2893 if (bsf==NULL && pos->lightEnabled == FALSE) {
2894 /* Found a light we can replace, save as best replacement */
2898 /* Step to next space */
2904 /* If we have too many active lights, fail the call */
2905 if ((Index == This->maxConcurrentLights) && (bsf == NULL)) {
2906 FIXME("Program requests too many concurrent lights\n");
2907 return WINED3DERR_INVALIDCALL;
2909 /* If we have allocated all lights, but not all are enabled,
2910 reuse one which is not enabled */
2911 } else if (Index == This->maxConcurrentLights) {
2912 /* use bsf - Simply swap the new light and the BSF one */
2913 PLIGHTINFOEL *bsfNext = bsf->next;
2914 PLIGHTINFOEL *bsfPrev = bsf->prev;
2917 if (lightInfo->next != NULL) lightInfo->next->prev = bsf;
2918 if (bsf->prev != NULL) {
2919 bsf->prev->next = lightInfo;
2921 This->stateBlock->lights = lightInfo;
2924 /* If not side by side, lots of chains to update */
2925 if (bsf->next != lightInfo) {
2926 lightInfo->prev->next = bsf;
2927 bsf->next->prev = lightInfo;
2928 bsf->next = lightInfo->next;
2929 bsf->prev = lightInfo->prev;
2930 lightInfo->next = bsfNext;
2931 lightInfo->prev = bsfPrev;
2935 bsf->prev = lightInfo;
2936 bsf->next = lightInfo->next;
2937 lightInfo->next = bsf;
2938 lightInfo->prev = bsfPrev;
2943 glIndex = bsf->glIndex;
2945 lightInfo->glIndex = glIndex;
2946 lightInfo->lightEnabled = Enable;
2948 /* Finally set up the light in gl itself */
2949 TRACE("Replacing light which was set up at gl idx %ld\n", lightInfo->glIndex);
2951 setup_light(iface, glIndex, lightInfo);
2952 glEnable(GL_LIGHT0 + glIndex);
2953 checkGLcall("glEnable GL_LIGHT0 new setup");
2956 /* If we reached the end of the allocated lights, with space in the
2957 gl lights, setup a new light */
2958 } else if (pos->glIndex == -1) {
2960 /* We reached the end of the allocated gl lights, so already
2961 know the index of the next one! */
2963 lightInfo->glIndex = glIndex;
2964 lightInfo->lightEnabled = Enable;
2966 /* In an ideal world, it's already in the right place */
2967 if (lightInfo->prev == NULL || lightInfo->prev->glIndex!=-1) {
2968 /* No need to move it */
2970 /* Remove this light from the list */
2971 lightInfo->prev->next = lightInfo->next;
2972 if (lightInfo->next != NULL) {
2973 lightInfo->next->prev = lightInfo->prev;
2976 /* Add in at appropriate place (inbetween prev and pos) */
2977 lightInfo->prev = prev;
2978 lightInfo->next = pos;
2980 This->stateBlock->lights = lightInfo;
2982 prev->next = lightInfo;
2985 pos->prev = lightInfo;
2989 /* Finally set up the light in gl itself */
2990 TRACE("Defining new light at gl idx %ld\n", lightInfo->glIndex);
2992 setup_light(iface, glIndex, lightInfo);
2993 glEnable(GL_LIGHT0 + glIndex);
2994 checkGLcall("glEnable GL_LIGHT0 new setup");
3003 static HRESULT WINAPI IWineD3DDeviceImpl_GetLightEnable(IWineD3DDevice *iface, DWORD Index,BOOL* pEnable) {
3005 PLIGHTINFOEL *lightInfo = NULL;
3006 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3007 TRACE("(%p) : for idx(%ld)\n", This, Index);
3009 /* Locate the light in the live lights */
3010 lightInfo = This->stateBlock->lights;
3011 while (lightInfo != NULL && lightInfo->OriginalIndex != Index) lightInfo = lightInfo->next;
3013 if (lightInfo == NULL) {
3014 TRACE("Light enabled state requested but light not defined\n");
3015 return WINED3DERR_INVALIDCALL;
3017 *pEnable = lightInfo->lightEnabled;
3022 * Get / Set Clip Planes
3024 static HRESULT WINAPI IWineD3DDeviceImpl_SetClipPlane(IWineD3DDevice *iface, DWORD Index, CONST float *pPlane) {
3025 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3026 TRACE("(%p) : for idx %ld, %p\n", This, Index, pPlane);
3028 /* Validate Index */
3029 if (Index >= GL_LIMITS(clipplanes)) {
3030 TRACE("Application has requested clipplane this device doesn't support\n");
3031 return WINED3DERR_INVALIDCALL;
3034 This->updateStateBlock->changed.clipplane[Index] = TRUE;
3035 This->updateStateBlock->set.clipplane[Index] = TRUE;
3036 This->updateStateBlock->clipplane[Index][0] = pPlane[0];
3037 This->updateStateBlock->clipplane[Index][1] = pPlane[1];
3038 This->updateStateBlock->clipplane[Index][2] = pPlane[2];
3039 This->updateStateBlock->clipplane[Index][3] = pPlane[3];
3041 /* Handle recording of state blocks */
3042 if (This->isRecordingState) {
3043 TRACE("Recording... not performing anything\n");
3051 /* Clip Plane settings are affected by the model view in OpenGL, the View transform in direct3d */
3052 glMatrixMode(GL_MODELVIEW);
3054 glLoadMatrixf((float *) &This->stateBlock->transforms[WINED3DTS_VIEW].u.m[0][0]);
3056 TRACE("Clipplane [%f,%f,%f,%f]\n",
3057 This->updateStateBlock->clipplane[Index][0],
3058 This->updateStateBlock->clipplane[Index][1],
3059 This->updateStateBlock->clipplane[Index][2],
3060 This->updateStateBlock->clipplane[Index][3]);
3061 glClipPlane(GL_CLIP_PLANE0 + Index, This->updateStateBlock->clipplane[Index]);
3062 checkGLcall("glClipPlane");
3070 static HRESULT WINAPI IWineD3DDeviceImpl_GetClipPlane(IWineD3DDevice *iface, DWORD Index, float *pPlane) {
3071 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3072 TRACE("(%p) : for idx %ld\n", This, Index);
3074 /* Validate Index */
3075 if (Index >= GL_LIMITS(clipplanes)) {
3076 TRACE("Application has requested clipplane this device doesn't support\n");
3077 return WINED3DERR_INVALIDCALL;
3080 pPlane[0] = This->stateBlock->clipplane[Index][0];
3081 pPlane[1] = This->stateBlock->clipplane[Index][1];
3082 pPlane[2] = This->stateBlock->clipplane[Index][2];
3083 pPlane[3] = This->stateBlock->clipplane[Index][3];
3088 * Get / Set Clip Plane Status
3089 * WARNING: This code relies on the fact that D3DCLIPSTATUS8 == D3DCLIPSTATUS9
3091 static HRESULT WINAPI IWineD3DDeviceImpl_SetClipStatus(IWineD3DDevice *iface, CONST WINED3DCLIPSTATUS* pClipStatus) {
3092 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3093 FIXME("(%p) : stub\n", This);
3094 if (NULL == pClipStatus) {
3095 return WINED3DERR_INVALIDCALL;
3097 This->updateStateBlock->clip_status.ClipUnion = pClipStatus->ClipUnion;
3098 This->updateStateBlock->clip_status.ClipIntersection = pClipStatus->ClipIntersection;
3102 static HRESULT WINAPI IWineD3DDeviceImpl_GetClipStatus(IWineD3DDevice *iface, WINED3DCLIPSTATUS* pClipStatus) {
3103 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3104 FIXME("(%p) : stub\n", This);
3105 if (NULL == pClipStatus) {
3106 return WINED3DERR_INVALIDCALL;
3108 pClipStatus->ClipUnion = This->updateStateBlock->clip_status.ClipUnion;
3109 pClipStatus->ClipIntersection = This->updateStateBlock->clip_status.ClipIntersection;
3114 * Get / Set Material
3115 * WARNING: This code relies on the fact that D3DMATERIAL8 == D3DMATERIAL9
3117 static HRESULT WINAPI IWineD3DDeviceImpl_SetMaterial(IWineD3DDevice *iface, CONST WINED3DMATERIAL* pMaterial) {
3118 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3120 This->updateStateBlock->changed.material = TRUE;
3121 This->updateStateBlock->set.material = TRUE;
3122 memcpy(&This->updateStateBlock->material, pMaterial, sizeof(WINED3DMATERIAL));
3124 /* Handle recording of state blocks */
3125 if (This->isRecordingState) {
3126 TRACE("Recording... not performing anything\n");
3131 TRACE("(%p) : Diffuse (%f,%f,%f,%f)\n", This, pMaterial->Diffuse.r, pMaterial->Diffuse.g,
3132 pMaterial->Diffuse.b, pMaterial->Diffuse.a);
3133 TRACE("(%p) : Ambient (%f,%f,%f,%f)\n", This, pMaterial->Ambient.r, pMaterial->Ambient.g,
3134 pMaterial->Ambient.b, pMaterial->Ambient.a);
3135 TRACE("(%p) : Specular (%f,%f,%f,%f)\n", This, pMaterial->Specular.r, pMaterial->Specular.g,
3136 pMaterial->Specular.b, pMaterial->Specular.a);
3137 TRACE("(%p) : Emissive (%f,%f,%f,%f)\n", This, pMaterial->Emissive.r, pMaterial->Emissive.g,
3138 pMaterial->Emissive.b, pMaterial->Emissive.a);
3139 TRACE("(%p) : Power (%f)\n", This, pMaterial->Power);
3141 glMaterialfv(GL_FRONT_AND_BACK, GL_AMBIENT, (float*) &This->updateStateBlock->material.Ambient);
3142 checkGLcall("glMaterialfv(GL_AMBIENT)");
3143 glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, (float*) &This->updateStateBlock->material.Diffuse);
3144 checkGLcall("glMaterialfv(GL_DIFFUSE)");
3146 /* Only change material color if specular is enabled, otherwise it is set to black */
3147 if (This->stateBlock->renderState[WINED3DRS_SPECULARENABLE]) {
3148 glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, (float*) &This->updateStateBlock->material.Specular);
3149 checkGLcall("glMaterialfv(GL_SPECULAR");
3151 float black[4] = {0.0f, 0.0f, 0.0f, 0.0f};
3152 glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, &black[0]);
3153 checkGLcall("glMaterialfv(GL_SPECULAR");
3155 glMaterialfv(GL_FRONT_AND_BACK, GL_EMISSION, (float*) &This->updateStateBlock->material.Emissive);
3156 checkGLcall("glMaterialfv(GL_EMISSION)");
3157 glMaterialf(GL_FRONT_AND_BACK, GL_SHININESS, This->updateStateBlock->material.Power);
3158 checkGLcall("glMaterialf(GL_SHININESS");
3164 static HRESULT WINAPI IWineD3DDeviceImpl_GetMaterial(IWineD3DDevice *iface, WINED3DMATERIAL* pMaterial) {
3165 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3166 memcpy(pMaterial, &This->updateStateBlock->material, sizeof (WINED3DMATERIAL));
3167 TRACE("(%p) : Diffuse (%f,%f,%f,%f)\n", This, pMaterial->Diffuse.r, pMaterial->Diffuse.g,
3168 pMaterial->Diffuse.b, pMaterial->Diffuse.a);
3169 TRACE("(%p) : Ambient (%f,%f,%f,%f)\n", This, pMaterial->Ambient.r, pMaterial->Ambient.g,
3170 pMaterial->Ambient.b, pMaterial->Ambient.a);
3171 TRACE("(%p) : Specular (%f,%f,%f,%f)\n", This, pMaterial->Specular.r, pMaterial->Specular.g,
3172 pMaterial->Specular.b, pMaterial->Specular.a);
3173 TRACE("(%p) : Emissive (%f,%f,%f,%f)\n", This, pMaterial->Emissive.r, pMaterial->Emissive.g,
3174 pMaterial->Emissive.b, pMaterial->Emissive.a);
3175 TRACE("(%p) : Power (%f)\n", This, pMaterial->Power);
3183 static HRESULT WINAPI IWineD3DDeviceImpl_SetIndices(IWineD3DDevice *iface, IWineD3DIndexBuffer* pIndexData,
3184 UINT BaseVertexIndex) {
3185 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3186 IWineD3DIndexBuffer *oldIdxs;
3188 TRACE("(%p) : Setting to %p, base %d\n", This, pIndexData, BaseVertexIndex);
3189 oldIdxs = This->updateStateBlock->pIndexData;
3191 This->updateStateBlock->changed.indices = TRUE;
3192 This->updateStateBlock->set.indices = TRUE;
3193 This->updateStateBlock->pIndexData = pIndexData;
3194 This->updateStateBlock->baseVertexIndex = BaseVertexIndex;
3196 /* Handle recording of state blocks */
3197 if (This->isRecordingState) {
3198 TRACE("Recording... not performing anything\n");
3202 if (NULL != pIndexData) {
3203 IWineD3DIndexBuffer_AddRef(pIndexData);
3205 if (NULL != oldIdxs) {
3206 IWineD3DIndexBuffer_Release(oldIdxs);
3211 static HRESULT WINAPI IWineD3DDeviceImpl_GetIndices(IWineD3DDevice *iface, IWineD3DIndexBuffer** ppIndexData, UINT* pBaseVertexIndex) {
3212 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3214 *ppIndexData = This->stateBlock->pIndexData;
3216 /* up ref count on ppindexdata */
3218 IWineD3DIndexBuffer_AddRef(*ppIndexData);
3219 *pBaseVertexIndex = This->stateBlock->baseVertexIndex;
3220 TRACE("(%p) index data set to %p + %u\n", This, ppIndexData, This->stateBlock->baseVertexIndex);
3222 TRACE("(%p) No index data set\n", This);
3224 TRACE("Returning %p %d\n", *ppIndexData, *pBaseVertexIndex);
3230 * Get / Set Viewports
3232 static HRESULT WINAPI IWineD3DDeviceImpl_SetViewport(IWineD3DDevice *iface, CONST WINED3DVIEWPORT* pViewport) {
3233 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3235 TRACE("(%p)\n", This);
3236 This->updateStateBlock->changed.viewport = TRUE;
3237 This->updateStateBlock->set.viewport = TRUE;
3238 memcpy(&This->updateStateBlock->viewport, pViewport, sizeof(WINED3DVIEWPORT));
3240 /* Handle recording of state blocks */
3241 if (This->isRecordingState) {
3242 TRACE("Recording... not performing anything\n");
3245 This->viewport_changed = TRUE;
3249 TRACE("(%p) : x=%ld, y=%ld, wid=%ld, hei=%ld, minz=%f, maxz=%f\n", This,
3250 pViewport->X, pViewport->Y, pViewport->Width, pViewport->Height, pViewport->MinZ, pViewport->MaxZ);
3252 glDepthRange(pViewport->MinZ, pViewport->MaxZ);
3253 checkGLcall("glDepthRange");
3254 /* Note: GL requires lower left, DirectX supplies upper left */
3255 /* TODO: replace usage of renderTarget with context management */
3256 glViewport(pViewport->X,
3257 (((IWineD3DSurfaceImpl *)This->renderTarget)->currentDesc.Height - (pViewport->Y + pViewport->Height)),
3258 pViewport->Width, pViewport->Height);
3260 checkGLcall("glViewport");
3268 static HRESULT WINAPI IWineD3DDeviceImpl_GetViewport(IWineD3DDevice *iface, WINED3DVIEWPORT* pViewport) {
3269 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3270 TRACE("(%p)\n", This);
3271 memcpy(pViewport, &This->stateBlock->viewport, sizeof(WINED3DVIEWPORT));
3275 static void renderstate_stencil_twosided(
3276 IWineD3DDeviceImpl *This,
3283 GLint stencilPass ) {
3284 #if 0 /* Don't use OpenGL 2.0 calls for now */
3285 if(GL_EXTCALL(glStencilFuncSeparate) && GL_EXTCALL(glStencilOpSeparate)) {
3286 GL_EXTCALL(glStencilFuncSeparate(face, func, ref, mask));
3287 checkGLcall("glStencilFuncSeparate(...)");
3288 GL_EXTCALL(glStencilOpSeparate(face, stencilFail, depthFail, stencilPass));
3289 checkGLcall("glStencilOpSeparate(...)");
3293 if(GL_SUPPORT(EXT_STENCIL_TWO_SIDE)) {
3294 glEnable(GL_STENCIL_TEST_TWO_SIDE_EXT);
3295 checkGLcall("glEnable(GL_STENCIL_TEST_TWO_SIDE_EXT)");
3296 GL_EXTCALL(glActiveStencilFaceEXT(face));
3297 checkGLcall("glActiveStencilFaceEXT(...)");
3298 glStencilFunc(func, ref, mask);
3299 checkGLcall("glStencilFunc(...)");
3300 glStencilOp(stencilFail, depthFail, stencilPass);
3301 checkGLcall("glStencilOp(...)");
3302 } else if(GL_SUPPORT(ATI_SEPARATE_STENCIL)) {
3303 GL_EXTCALL(glStencilFuncSeparateATI(face, func, ref, mask));
3304 checkGLcall("glStencilFuncSeparateATI(...)");
3305 GL_EXTCALL(glStencilOpSeparateATI(face, stencilFail, depthFail, stencilPass));
3306 checkGLcall("glStencilOpSeparateATI(...)");
3308 ERR("Separate (two sided) stencil not supported on this version of opengl. Caps weren't honored?\n");
3312 static void renderstate_stencil(IWineD3DDeviceImpl *This, D3DRENDERSTATETYPE State, DWORD Value) {
3313 DWORD onesided_enable = FALSE;
3314 DWORD twosided_enable = FALSE;
3315 GLint func = GL_ALWAYS;
3316 GLint func_ccw = GL_ALWAYS;
3319 GLint stencilFail = GL_KEEP;
3320 GLint depthFail = GL_KEEP;
3321 GLint stencilPass = GL_KEEP;
3322 GLint stencilFail_ccw = GL_KEEP;
3323 GLint depthFail_ccw = GL_KEEP;
3324 GLint stencilPass_ccw = GL_KEEP;
3326 if( This->stateBlock->set.renderState[WINED3DRS_STENCILENABLE] )
3327 onesided_enable = This->stateBlock->renderState[WINED3DRS_STENCILENABLE];
3328 if( This->stateBlock->set.renderState[WINED3DRS_TWOSIDEDSTENCILMODE] )
3329 twosided_enable = This->stateBlock->renderState[WINED3DRS_TWOSIDEDSTENCILMODE];
3330 if( This->stateBlock->set.renderState[WINED3DRS_STENCILFUNC] )
3331 if( !( func = CompareFunc(This->stateBlock->renderState[WINED3DRS_STENCILFUNC]) ) )
3333 if( This->stateBlock->set.renderState[WINED3DRS_CCW_STENCILFUNC] )
3334 if( !( func_ccw = CompareFunc(This->stateBlock->renderState[WINED3DRS_CCW_STENCILFUNC]) ) )
3336 if( This->stateBlock->set.renderState[WINED3DRS_STENCILREF] )
3337 ref = This->stateBlock->renderState[WINED3DRS_STENCILREF];
3338 if( This->stateBlock->set.renderState[WINED3DRS_STENCILMASK] )
3339 mask = This->stateBlock->renderState[WINED3DRS_STENCILMASK];
3340 if( This->stateBlock->set.renderState[WINED3DRS_STENCILFAIL] )
3341 stencilFail = StencilOp(This->stateBlock->renderState[WINED3DRS_STENCILFAIL]);
3342 if( This->stateBlock->set.renderState[WINED3DRS_STENCILZFAIL] )
3343 depthFail = StencilOp(This->stateBlock->renderState[WINED3DRS_STENCILZFAIL]);
3344 if( This->stateBlock->set.renderState[WINED3DRS_STENCILPASS] )
3345 stencilPass = StencilOp(This->stateBlock->renderState[WINED3DRS_STENCILPASS]);
3346 if( This->stateBlock->set.renderState[WINED3DRS_CCW_STENCILFAIL] )
3347 stencilFail_ccw = StencilOp(This->stateBlock->renderState[WINED3DRS_CCW_STENCILFAIL]);
3348 if( This->stateBlock->set.renderState[WINED3DRS_CCW_STENCILZFAIL] )
3349 depthFail_ccw = StencilOp(This->stateBlock->renderState[WINED3DRS_CCW_STENCILZFAIL]);
3350 if( This->stateBlock->set.renderState[WINED3DRS_CCW_STENCILPASS] )
3351 stencilPass_ccw = StencilOp(This->stateBlock->renderState[WINED3DRS_CCW_STENCILPASS]);
3353 TRACE("(onesided %ld, twosided %ld, ref %x, mask %x, \
3354 GL_FRONT: func: %x, fail %x, zfail %x, zpass %x \
3355 GL_BACK: func: %x, fail %x, zfail %x, zpass %x )\n",
3356 onesided_enable, twosided_enable, ref, mask,
3357 func, stencilFail, depthFail, stencilPass,
3358 func_ccw, stencilFail_ccw, depthFail_ccw, stencilPass_ccw);
3360 if (twosided_enable) {
3361 renderstate_stencil_twosided(This, GL_FRONT, func, ref, mask, stencilFail, depthFail, stencilPass);
3362 renderstate_stencil_twosided(This, GL_BACK, func_ccw, ref, mask, stencilFail_ccw, depthFail_ccw, stencilPass_ccw);
3364 if (onesided_enable) {
3365 glEnable(GL_STENCIL_TEST);
3366 checkGLcall("glEnable GL_STENCIL_TEST");
3367 glStencilFunc(func, ref, mask);
3368 checkGLcall("glStencilFunc(...)");
3369 glStencilOp(stencilFail, depthFail, stencilPass);
3370 checkGLcall("glStencilOp(...)");
3372 glDisable(GL_STENCIL_TEST);
3373 checkGLcall("glDisable GL_STENCIL_TEST");
3379 * Get / Set Render States
3380 * TODO: Verify against dx9 definitions
3382 static HRESULT WINAPI IWineD3DDeviceImpl_SetRenderState(IWineD3DDevice *iface, D3DRENDERSTATETYPE State, DWORD Value) {
3384 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3385 DWORD OldValue = This->stateBlock->renderState[State];
3387 /* Simple way of referring to either a DWORD or a 4 byte float */
3393 TRACE("(%p)->state = %s(%d), value = %ld\n", This, debug_d3drenderstate(State), State, Value);
3394 This->updateStateBlock->changed.renderState[State] = TRUE;
3395 This->updateStateBlock->set.renderState[State] = TRUE;
3396 This->updateStateBlock->renderState[State] = Value;
3398 /* Handle recording of state blocks */
3399 if (This->isRecordingState) {
3400 TRACE("Recording... not performing anything\n");
3407 case WINED3DRS_FILLMODE :
3408 switch ((D3DFILLMODE) Value) {
3409 case D3DFILL_POINT : glPolygonMode(GL_FRONT_AND_BACK, GL_POINT); break;
3410 case D3DFILL_WIREFRAME : glPolygonMode(GL_FRONT_AND_BACK, GL_LINE); break;
3411 case D3DFILL_SOLID : glPolygonMode(GL_FRONT_AND_BACK, GL_FILL); break;
3413 FIXME("Unrecognized WINED3DRS_FILLMODE value %ld\n", Value);
3415 checkGLcall("glPolygonMode (fillmode)");
3418 case WINED3DRS_LIGHTING :
3420 glEnable(GL_LIGHTING);
3421 checkGLcall("glEnable GL_LIGHTING");
3423 glDisable(GL_LIGHTING);
3424 checkGLcall("glDisable GL_LIGHTING");
3428 case WINED3DRS_ZENABLE :
3429 switch ((D3DZBUFFERTYPE) Value) {
3431 glDisable(GL_DEPTH_TEST);
3432 checkGLcall("glDisable GL_DEPTH_TEST");
3435 glEnable(GL_DEPTH_TEST);
3436 checkGLcall("glEnable GL_DEPTH_TEST");
3439 glEnable(GL_DEPTH_TEST);
3440 checkGLcall("glEnable GL_DEPTH_TEST");
3441 FIXME("W buffer is not well handled\n");
3444 FIXME("Unrecognized D3DZBUFFERTYPE value %ld\n", Value);
3448 case WINED3DRS_CULLMODE :
3450 /* If we are culling "back faces with clockwise vertices" then
3451 set front faces to be counter clockwise and enable culling
3453 switch ((D3DCULL) Value) {
3455 glDisable(GL_CULL_FACE);
3456 checkGLcall("glDisable GL_CULL_FACE");
3459 glEnable(GL_CULL_FACE);
3460 checkGLcall("glEnable GL_CULL_FACE");
3461 if (This->renderUpsideDown) {
3463 checkGLcall("glFrontFace GL_CW");
3465 glFrontFace(GL_CCW);
3466 checkGLcall("glFrontFace GL_CCW");
3468 glCullFace(GL_BACK);
3471 glEnable(GL_CULL_FACE);
3472 checkGLcall("glEnable GL_CULL_FACE");
3473 if (This->renderUpsideDown) {
3474 glFrontFace(GL_CCW);
3475 checkGLcall("glFrontFace GL_CCW");
3478 checkGLcall("glFrontFace GL_CW");
3480 glCullFace(GL_BACK);
3483 FIXME("Unrecognized/Unhandled D3DCULL value %ld\n", Value);
3487 case WINED3DRS_SHADEMODE :
3488 switch ((D3DSHADEMODE) Value) {
3490 glShadeModel(GL_FLAT);
3491 checkGLcall("glShadeModel");
3493 case D3DSHADE_GOURAUD:
3494 glShadeModel(GL_SMOOTH);
3495 checkGLcall("glShadeModel");
3497 case D3DSHADE_PHONG:
3498 FIXME("D3DSHADE_PHONG isn't supported\n");
3501 FIXME("Unrecognized/Unhandled D3DSHADEMODE value %ld\n", Value);
3505 case WINED3DRS_DITHERENABLE :
3507 glEnable(GL_DITHER);
3508 checkGLcall("glEnable GL_DITHER");
3510 glDisable(GL_DITHER);
3511 checkGLcall("glDisable GL_DITHER");
3515 case WINED3DRS_ZWRITEENABLE :
3518 checkGLcall("glDepthMask");
3521 checkGLcall("glDepthMask");
3525 case WINED3DRS_ZFUNC :
3527 int glParm = CompareFunc(Value);
3530 glDepthFunc(glParm);
3531 checkGLcall("glDepthFunc");
3536 case WINED3DRS_AMBIENT :
3539 D3DCOLORTOGLFLOAT4(Value, col);
3540 TRACE("Setting ambient to (%f,%f,%f,%f)\n", col[0], col[1], col[2], col[3]);
3541 glLightModelfv(GL_LIGHT_MODEL_AMBIENT, col);
3542 checkGLcall("glLightModel for MODEL_AMBIENT");
3547 case WINED3DRS_ALPHABLENDENABLE :
3550 checkGLcall("glEnable GL_BLEND");
3552 glDisable(GL_BLEND);
3553 checkGLcall("glDisable GL_BLEND");
3557 case WINED3DRS_SRCBLEND :
3558 case WINED3DRS_DESTBLEND :
3560 int newVal = GL_ZERO;
3562 case D3DBLEND_ZERO : newVal = GL_ZERO; break;
3563 case D3DBLEND_ONE : newVal = GL_ONE; break;
3564 case D3DBLEND_SRCCOLOR : newVal = GL_SRC_COLOR; break;
3565 case D3DBLEND_INVSRCCOLOR : newVal = GL_ONE_MINUS_SRC_COLOR; break;
3566 case D3DBLEND_SRCALPHA : newVal = GL_SRC_ALPHA; break;
3567 case D3DBLEND_INVSRCALPHA : newVal = GL_ONE_MINUS_SRC_ALPHA; break;
3568 case D3DBLEND_DESTALPHA : newVal = GL_DST_ALPHA; break;
3569 case D3DBLEND_INVDESTALPHA : newVal = GL_ONE_MINUS_DST_ALPHA; break;
3570 case D3DBLEND_DESTCOLOR : newVal = GL_DST_COLOR; break;
3571 case D3DBLEND_INVDESTCOLOR : newVal = GL_ONE_MINUS_DST_COLOR; break;
3572 case D3DBLEND_SRCALPHASAT : newVal = GL_SRC_ALPHA_SATURATE; break;
3574 case D3DBLEND_BOTHSRCALPHA : newVal = GL_SRC_ALPHA;
3575 This->srcBlend = newVal;
3576 This->dstBlend = newVal;
3579 case D3DBLEND_BOTHINVSRCALPHA : newVal = GL_ONE_MINUS_SRC_ALPHA;
3580 This->srcBlend = newVal;
3581 This->dstBlend = newVal;
3583 case D3DBLEND_BLENDFACTOR : newVal = GL_CONSTANT_COLOR; break;
3584 case D3DBLEND_INVBLENDFACTOR : newVal = GL_ONE_MINUS_CONSTANT_COLOR; break;
3586 FIXME("Unrecognized src/dest blend value %ld (%d)\n", Value, State);
3589 if (State == WINED3DRS_SRCBLEND) This->srcBlend = newVal;
3590 if (State == WINED3DRS_DESTBLEND) This->dstBlend = newVal;
3591 TRACE("glBlendFunc src=%x, dst=%x\n", This->srcBlend, This->dstBlend);
3592 glBlendFunc(This->srcBlend, This->dstBlend);
3594 checkGLcall("glBlendFunc");
3598 case WINED3DRS_ALPHATESTENABLE :
3599 case WINED3DRS_ALPHAFUNC :
3600 case WINED3DRS_ALPHAREF :
3601 case WINED3DRS_COLORKEYENABLE :
3605 BOOL enable_ckey = FALSE;
3607 IWineD3DSurfaceImpl *surf;
3609 /* Find out if the texture on the first stage has a ckey set */
3610 if(This->stateBlock->textures[0]) {
3611 surf = (IWineD3DSurfaceImpl *) ((IWineD3DTextureImpl *)This->stateBlock->textures[0])->surfaces[0];
3612 if(surf->CKeyFlags & DDSD_CKSRCBLT) enable_ckey = TRUE;
3615 if (This->stateBlock->renderState[WINED3DRS_ALPHATESTENABLE] ||
3616 (This->stateBlock->renderState[WINED3DRS_COLORKEYENABLE] && enable_ckey)) {
3617 glEnable(GL_ALPHA_TEST);
3618 checkGLcall("glEnable GL_ALPHA_TEST");
3620 glDisable(GL_ALPHA_TEST);
3621 checkGLcall("glDisable GL_ALPHA_TEST");
3622 /* Alpha test is disabled, don't bother setting the params - it will happen on the next
3628 if(This->stateBlock->renderState[WINED3DRS_COLORKEYENABLE] && enable_ckey) {
3629 glParm = GL_NOTEQUAL;
3632 ref = ((float) This->stateBlock->renderState[WINED3DRS_ALPHAREF]) / 255.0f;
3633 glParm = CompareFunc(This->stateBlock->renderState[WINED3DRS_ALPHAFUNC]);
3636 This->alphafunc = glParm;
3637 glAlphaFunc(glParm, ref);
3638 checkGLcall("glAlphaFunc");
3643 case WINED3DRS_CLIPPLANEENABLE :
3644 case WINED3DRS_CLIPPING :
3646 /* Ensure we only do the changed clip planes */
3647 DWORD enable = 0xFFFFFFFF;
3648 DWORD disable = 0x00000000;
3650 /* If enabling / disabling all */
3651 if (State == WINED3DRS_CLIPPING) {
3653 enable = This->stateBlock->renderState[WINED3DRS_CLIPPLANEENABLE];
3656 disable = This->stateBlock->renderState[WINED3DRS_CLIPPLANEENABLE];
3660 enable = Value & ~OldValue;
3661 disable = ~Value & OldValue;
3664 if (enable & D3DCLIPPLANE0) { glEnable(GL_CLIP_PLANE0); checkGLcall("glEnable(clip plane 0)"); }
3665 if (enable & D3DCLIPPLANE1) { glEnable(GL_CLIP_PLANE1); checkGLcall("glEnable(clip plane 1)"); }
3666 if (enable & D3DCLIPPLANE2) { glEnable(GL_CLIP_PLANE2); checkGLcall("glEnable(clip plane 2)"); }
3667 if (enable & D3DCLIPPLANE3) { glEnable(GL_CLIP_PLANE3); checkGLcall("glEnable(clip plane 3)"); }
3668 if (enable & D3DCLIPPLANE4) { glEnable(GL_CLIP_PLANE4); checkGLcall("glEnable(clip plane 4)"); }
3669 if (enable & D3DCLIPPLANE5) { glEnable(GL_CLIP_PLANE5); checkGLcall("glEnable(clip plane 5)"); }
3671 if (disable & D3DCLIPPLANE0) { glDisable(GL_CLIP_PLANE0); checkGLcall("glDisable(clip plane 0)"); }
3672 if (disable & D3DCLIPPLANE1) { glDisable(GL_CLIP_PLANE1); checkGLcall("glDisable(clip plane 1)"); }
3673 if (disable & D3DCLIPPLANE2) { glDisable(GL_CLIP_PLANE2); checkGLcall("glDisable(clip plane 2)"); }
3674 if (disable & D3DCLIPPLANE3) { glDisable(GL_CLIP_PLANE3); checkGLcall("glDisable(clip plane 3)"); }
3675 if (disable & D3DCLIPPLANE4) { glDisable(GL_CLIP_PLANE4); checkGLcall("glDisable(clip plane 4)"); }
3676 if (disable & D3DCLIPPLANE5) { glDisable(GL_CLIP_PLANE5); checkGLcall("glDisable(clip plane 5)"); }
3678 /** update clipping status */
3680 This->stateBlock->clip_status.ClipUnion = 0;
3681 This->stateBlock->clip_status.ClipIntersection = 0xFFFFFFFF;
3683 This->stateBlock->clip_status.ClipUnion = 0;
3684 This->stateBlock->clip_status.ClipIntersection = 0;
3689 case WINED3DRS_BLENDOP :
3691 int glParm = GL_FUNC_ADD;
3693 switch ((D3DBLENDOP) Value) {
3694 case D3DBLENDOP_ADD : glParm = GL_FUNC_ADD; break;
3695 case D3DBLENDOP_SUBTRACT : glParm = GL_FUNC_SUBTRACT; break;
3696 case D3DBLENDOP_REVSUBTRACT : glParm = GL_FUNC_REVERSE_SUBTRACT; break;
3697 case D3DBLENDOP_MIN : glParm = GL_MIN; break;
3698 case D3DBLENDOP_MAX : glParm = GL_MAX; break;
3700 FIXME("Unrecognized/Unhandled D3DBLENDOP value %ld\n", Value);
3703 if(GL_SUPPORT(ARB_IMAGING)) {
3704 TRACE("glBlendEquation(%x)\n", glParm);
3705 GL_EXTCALL(glBlendEquation(glParm));
3706 checkGLcall("glBlendEquation");
3708 WARN("Unsupported in local OpenGL implementation: glBlendEquation\n");
3713 case WINED3DRS_TEXTUREFACTOR :
3717 /* Note the texture color applies to all textures whereas
3718 GL_TEXTURE_ENV_COLOR applies to active only */
3720 D3DCOLORTOGLFLOAT4(Value, col);
3722 if (!GL_SUPPORT(NV_REGISTER_COMBINERS)) {
3723 /* And now the default texture color as well */
3724 for (i = 0; i < GL_LIMITS(texture_stages); i++) {
3725 /* Note the D3DRS value applies to all textures, but GL has one
3726 per texture, so apply it now ready to be used! */
3727 if (GL_SUPPORT(ARB_MULTITEXTURE)) {
3728 GL_EXTCALL(glActiveTextureARB(GL_TEXTURE0_ARB + i));
3729 checkGLcall("glActiveTextureARB");
3731 FIXME("Program using multiple concurrent textures which this opengl implementation doesn't support\n");
3734 glTexEnvfv(GL_TEXTURE_ENV, GL_TEXTURE_ENV_COLOR, &col[0]);
3735 checkGLcall("glTexEnvfv(GL_TEXTURE_ENV, GL_TEXTURE_ENV_COLOR, color);");
3741 case WINED3DRS_SPECULARENABLE :
3743 /* Originally this used glLightModeli(GL_LIGHT_MODEL_COLOR_CONTROL,GL_SEPARATE_SPECULAR_COLOR)
3744 and (GL_LIGHT_MODEL_COLOR_CONTROL,GL_SINGLE_COLOR) to swap between enabled/disabled
3745 specular color. This is wrong:
3746 Separate specular color means the specular colour is maintained separately, whereas
3747 single color means it is merged in. However in both cases they are being used to
3749 To disable specular color, set it explicitly to black and turn off GL_COLOR_SUM_EXT
3750 NOTE: If not supported don't give FIXMEs the impact is really minimal and very few people are
3754 * If register combiners are enabled, enabling / disabling GL_COLOR_SUM has no effect.
3755 * Instead, we need to setup the FinalCombiner properly.
3757 * The default setup for the FinalCombiner is:
3759 * <variable> <input> <mapping> <usage>
3760 * GL_VARIABLE_A_NV GL_FOG, GL_UNSIGNED_IDENTITY_NV GL_ALPHA
3761 * GL_VARIABLE_B_NV GL_SPARE0_PLUS_SECONDARY_COLOR_NV GL_UNSIGNED_IDENTITY_NV GL_RGB
3762 * GL_VARIABLE_C_NV GL_FOG GL_UNSIGNED_IDENTITY_NV GL_RGB
3763 * GL_VARIABLE_D_NV GL_ZERO GL_UNSIGNED_IDENTITY_NV GL_RGB
3764 * GL_VARIABLE_E_NV GL_ZERO GL_UNSIGNED_IDENTITY_NV GL_RGB
3765 * GL_VARIABLE_F_NV GL_ZERO GL_UNSIGNED_IDENTITY_NV GL_RGB
3766 * GL_VARIABLE_G_NV GL_SPARE0_NV GL_UNSIGNED_IDENTITY_NV GL_ALPHA
3768 * That's pretty much fine as it is, except for variable B, which needs to take
3769 * either GL_SPARE0_PLUS_SECONDARY_COLOR_NV or GL_SPARE0_NV, depending on
3770 * whether WINED3DRS_SPECULARENABLE is enabled or not.
3774 glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, (float*) &This->updateStateBlock->material.Specular);
3775 checkGLcall("glMaterialfv");
3776 if (GL_SUPPORT(EXT_SECONDARY_COLOR)) {
3777 glEnable(GL_COLOR_SUM_EXT);
3779 TRACE("Specular colors cannot be enabled in this version of opengl\n");
3781 checkGLcall("glEnable(GL_COLOR_SUM)");
3783 if (GL_SUPPORT(NV_REGISTER_COMBINERS)) {
3784 GL_EXTCALL(glFinalCombinerInputNV(GL_VARIABLE_B_NV, GL_SPARE0_PLUS_SECONDARY_COLOR_NV, GL_UNSIGNED_IDENTITY_NV, GL_RGB));
3785 checkGLcall("glFinalCombinerInputNV()");
3788 float black[4] = {0.0f, 0.0f, 0.0f, 0.0f};
3790 /* for the case of enabled lighting: */
3791 glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, &black[0]);
3792 checkGLcall("glMaterialfv");
3794 /* for the case of disabled lighting: */
3795 if (GL_SUPPORT(EXT_SECONDARY_COLOR)) {
3796 glDisable(GL_COLOR_SUM_EXT);
3798 TRACE("Specular colors cannot be disabled in this version of opengl\n");
3800 checkGLcall("glDisable(GL_COLOR_SUM)");
3802 if (GL_SUPPORT(NV_REGISTER_COMBINERS)) {
3803 GL_EXTCALL(glFinalCombinerInputNV(GL_VARIABLE_B_NV, GL_SPARE0_NV, GL_UNSIGNED_IDENTITY_NV, GL_RGB));
3804 checkGLcall("glFinalCombinerInputNV()");
3810 case WINED3DRS_STENCILENABLE :
3811 case WINED3DRS_TWOSIDEDSTENCILMODE :
3812 case WINED3DRS_STENCILFUNC :
3813 case WINED3DRS_CCW_STENCILFUNC :
3814 case WINED3DRS_STENCILREF :
3815 case WINED3DRS_STENCILMASK :
3816 case WINED3DRS_STENCILFAIL :
3817 case WINED3DRS_STENCILZFAIL :
3818 case WINED3DRS_STENCILPASS :
3819 case WINED3DRS_CCW_STENCILFAIL :
3820 case WINED3DRS_CCW_STENCILZFAIL :
3821 case WINED3DRS_CCW_STENCILPASS :
3822 renderstate_stencil(This, State, Value);
3824 case WINED3DRS_STENCILWRITEMASK :
3826 glStencilMask(Value);
3827 TRACE("glStencilMask(%lu)\n", Value);
3828 checkGLcall("glStencilMask");
3832 case WINED3DRS_FOGENABLE :
3836 checkGLcall("glEnable GL_FOG");
3839 checkGLcall("glDisable GL_FOG");
3844 case WINED3DRS_RANGEFOGENABLE :
3847 TRACE("Enabled RANGEFOG\n");
3849 TRACE("Disabled RANGEFOG\n");
3854 case WINED3DRS_FOGCOLOR :
3857 D3DCOLORTOGLFLOAT4(Value, col);
3858 /* Set the default alpha blend color */
3859 glFogfv(GL_FOG_COLOR, &col[0]);
3860 checkGLcall("glFog GL_FOG_COLOR");
3864 case WINED3DRS_FOGTABLEMODE :
3865 case WINED3DRS_FOGVERTEXMODE :
3867 /* 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." */
3868 if(This->stateBlock->renderState[WINED3DRS_FOGTABLEMODE] == D3DFOG_NONE) {
3869 glHint(GL_FOG_HINT, GL_FASTEST);
3870 checkGLcall("glHint(GL_FOG_HINT, GL_FASTEST)");
3871 switch (This->stateBlock->renderState[WINED3DRS_FOGVERTEXMODE]) {
3872 /* Processed vertices have their fog factor stored in the specular value. Fall too the none case.
3873 * If we are drawing untransformed vertices atm, d3ddevice_set_ortho will update the fog
3876 if(!This->last_was_rhw) {
3877 glFogi(GL_FOG_MODE, GL_EXP);
3878 checkGLcall("glFogi(GL_FOG_MODE, GL_EXP");
3879 if(GL_SUPPORT(EXT_FOG_COORD)) {
3880 glFogi(GL_FOG_COORDINATE_SOURCE_EXT, GL_FRAGMENT_DEPTH_EXT);
3881 checkGLcall("glFogi(GL_FOG_COORDINATE_SOURCE_EXT, GL_FRAGMENT_DEPTH_EXT");
3882 IWineD3DDevice_SetRenderState(iface, WINED3DRS_FOGSTART, This->stateBlock->renderState[WINED3DRS_FOGSTART]);
3883 IWineD3DDevice_SetRenderState(iface, WINED3DRS_FOGEND, This->stateBlock->renderState[WINED3DRS_FOGEND]);
3889 if(!This->last_was_rhw) {
3890 glFogi(GL_FOG_MODE, GL_EXP2);
3891 checkGLcall("glFogi(GL_FOG_MODE, GL_EXP2");
3892 if(GL_SUPPORT(EXT_FOG_COORD)) {
3893 glFogi(GL_FOG_COORDINATE_SOURCE_EXT, GL_FRAGMENT_DEPTH_EXT);
3894 checkGLcall("glFogi(GL_FOG_COORDINATE_SOURCE_EXT, GL_FRAGMENT_DEPTH_EXT");
3895 IWineD3DDevice_SetRenderState(iface, WINED3DRS_FOGSTART, This->stateBlock->renderState[WINED3DRS_FOGSTART]);
3896 IWineD3DDevice_SetRenderState(iface, WINED3DRS_FOGEND, This->stateBlock->renderState[WINED3DRS_FOGEND]);
3901 case D3DFOG_LINEAR: {
3902 if(!This->last_was_rhw) {
3903 glFogi(GL_FOG_MODE, GL_LINEAR);
3904 checkGLcall("glFogi(GL_FOG_MODE, GL_LINEAR");
3905 if(GL_SUPPORT(EXT_FOG_COORD)) {
3906 glFogi(GL_FOG_COORDINATE_SOURCE_EXT, GL_FRAGMENT_DEPTH_EXT);
3907 checkGLcall("glFogi(GL_FOG_COORDINATE_SOURCE_EXT, GL_FRAGMENT_DEPTH_EXT");
3908 IWineD3DDevice_SetRenderState(iface, WINED3DRS_FOGSTART, This->stateBlock->renderState[WINED3DRS_FOGSTART]);
3909 IWineD3DDevice_SetRenderState(iface, WINED3DRS_FOGEND, This->stateBlock->renderState[WINED3DRS_FOGEND]);
3915 /* Both are none? According to msdn the alpha channel of the specular
3916 * color contains a fog factor. Set it in drawStridedSlow.
3917 * Same happens with Vertexfog on transformed vertices
3919 if(GL_SUPPORT(EXT_FOG_COORD)) {
3920 glFogi(GL_FOG_COORDINATE_SOURCE_EXT, GL_FOG_COORDINATE_EXT);
3921 checkGLcall("glFogi(GL_FOG_COORDINATE_SOURCE_EXT, GL_FOG_COORDINATE_EXT)\n");
3922 glFogi(GL_FOG_MODE, GL_LINEAR);
3923 checkGLcall("glFogi(GL_FOG_MODE, GL_LINEAR)");
3924 glFogf(GL_FOG_START, (float) 0xff);
3925 checkGLcall("glFogfv GL_FOG_START");
3926 glFogf(GL_FOG_END, 0.0);
3927 checkGLcall("glFogfv GL_FOG_END");
3929 /* Disable GL fog, handle this in software in drawStridedSlow */
3931 checkGLcall("glDisable(GL_FOG)");
3935 default: FIXME("Unexpected WINED3DRS_FOGVERTEXMODE %ld\n", This->stateBlock->renderState[WINED3DRS_FOGVERTEXMODE]);
3938 glHint(GL_FOG_HINT, GL_NICEST);
3939 checkGLcall("glHint(GL_FOG_HINT, GL_NICEST)");
3940 switch (This->stateBlock->renderState[WINED3DRS_FOGTABLEMODE]) {
3941 case D3DFOG_EXP: glFogi(GL_FOG_MODE, GL_EXP);
3942 checkGLcall("glFogi(GL_FOG_MODE, GL_EXP");
3943 if(GL_SUPPORT(EXT_FOG_COORD)) {
3944 glFogi(GL_FOG_COORDINATE_SOURCE_EXT, GL_FRAGMENT_DEPTH_EXT);
3945 checkGLcall("glFogi(GL_FOG_COORDINATE_SOURCE_EXT, GL_FRAGMENT_DEPTH_EXT");
3946 IWineD3DDevice_SetRenderState(iface, WINED3DRS_FOGSTART, This->stateBlock->renderState[WINED3DRS_FOGSTART]);
3947 IWineD3DDevice_SetRenderState(iface, WINED3DRS_FOGEND, This->stateBlock->renderState[WINED3DRS_FOGEND]);
3950 case D3DFOG_EXP2: glFogi(GL_FOG_MODE, GL_EXP2);
3951 checkGLcall("glFogi(GL_FOG_MODE, GL_EXP2");
3952 if(GL_SUPPORT(EXT_FOG_COORD)) {
3953 glFogi(GL_FOG_COORDINATE_SOURCE_EXT, GL_FRAGMENT_DEPTH_EXT);
3954 checkGLcall("glFogi(GL_FOG_COORDINATE_SOURCE_EXT, GL_FRAGMENT_DEPTH_EXT");
3955 IWineD3DDevice_SetRenderState(iface, WINED3DRS_FOGSTART, This->stateBlock->renderState[WINED3DRS_FOGSTART]);
3956 IWineD3DDevice_SetRenderState(iface, WINED3DRS_FOGEND, This->stateBlock->renderState[WINED3DRS_FOGEND]);
3959 case D3DFOG_LINEAR: glFogi(GL_FOG_MODE, GL_LINEAR);
3960 checkGLcall("glFogi(GL_FOG_MODE, GL_LINEAR");
3961 if(GL_SUPPORT(EXT_FOG_COORD)) {
3962 glFogi(GL_FOG_COORDINATE_SOURCE_EXT, GL_FRAGMENT_DEPTH_EXT);
3963 checkGLcall("glFogi(GL_FOG_COORDINATE_SOURCE_EXT, GL_FRAGMENT_DEPTH_EXT");
3964 IWineD3DDevice_SetRenderState(iface, WINED3DRS_FOGSTART, This->stateBlock->renderState[WINED3DRS_FOGSTART]);
3965 IWineD3DDevice_SetRenderState(iface, WINED3DRS_FOGEND, This->stateBlock->renderState[WINED3DRS_FOGEND]);
3968 case D3DFOG_NONE: /* Won't happen */
3969 default: FIXME("Unexpected WINED3DRS_FOGTABLEMODE %ld\n", This->stateBlock->renderState[WINED3DRS_FOGTABLEMODE]);
3972 if (GL_SUPPORT(NV_FOG_DISTANCE)) {
3973 glFogi(GL_FOG_DISTANCE_MODE_NV, GL_EYE_PLANE_ABSOLUTE_NV);
3978 case WINED3DRS_FOGSTART :
3981 glFogfv(GL_FOG_START, &tmpvalue.f);
3982 checkGLcall("glFogf(GL_FOG_START, (float) Value)");
3983 TRACE("Fog Start == %f\n", tmpvalue.f);
3987 case WINED3DRS_FOGEND :
3990 glFogfv(GL_FOG_END, &tmpvalue.f);
3991 checkGLcall("glFogf(GL_FOG_END, (float) Value)");
3992 TRACE("Fog End == %f\n", tmpvalue.f);
3996 case WINED3DRS_FOGDENSITY :
3999 glFogfv(GL_FOG_DENSITY, &tmpvalue.f);
4000 checkGLcall("glFogf(GL_FOG_DENSITY, (float) Value)");
4004 case WINED3DRS_VERTEXBLEND :
4006 This->updateStateBlock->vertex_blend = (D3DVERTEXBLENDFLAGS) Value;
4007 TRACE("Vertex Blending state to %ld\n", Value);
4011 case WINED3DRS_TWEENFACTOR :
4014 This->updateStateBlock->tween_factor = tmpvalue.f;
4015 TRACE("Vertex Blending Tween Factor to %f\n", This->updateStateBlock->tween_factor);
4019 case WINED3DRS_INDEXEDVERTEXBLENDENABLE :
4021 TRACE("Indexed Vertex Blend Enable to %ul\n", (BOOL) Value);
4025 case WINED3DRS_COLORVERTEX :
4026 case WINED3DRS_DIFFUSEMATERIALSOURCE :
4027 case WINED3DRS_SPECULARMATERIALSOURCE :
4028 case WINED3DRS_AMBIENTMATERIALSOURCE :
4029 case WINED3DRS_EMISSIVEMATERIALSOURCE :
4031 GLenum Parm = GL_AMBIENT_AND_DIFFUSE;
4033 if (This->stateBlock->renderState[WINED3DRS_COLORVERTEX]) {
4034 TRACE("diff %ld, amb %ld, emis %ld, spec %ld\n",
4035 This->stateBlock->renderState[WINED3DRS_DIFFUSEMATERIALSOURCE],
4036 This->stateBlock->renderState[WINED3DRS_AMBIENTMATERIALSOURCE],
4037 This->stateBlock->renderState[WINED3DRS_EMISSIVEMATERIALSOURCE],
4038 This->stateBlock->renderState[WINED3DRS_SPECULARMATERIALSOURCE]);
4040 if (This->stateBlock->renderState[WINED3DRS_DIFFUSEMATERIALSOURCE] == D3DMCS_COLOR1) {
4041 if (This->stateBlock->renderState[WINED3DRS_AMBIENTMATERIALSOURCE] == D3DMCS_COLOR1) {
4042 Parm = GL_AMBIENT_AND_DIFFUSE;
4046 } else if (This->stateBlock->renderState[WINED3DRS_AMBIENTMATERIALSOURCE] == D3DMCS_COLOR1) {
4048 } else if (This->stateBlock->renderState[WINED3DRS_EMISSIVEMATERIALSOURCE] == D3DMCS_COLOR1) {
4050 } else if (This->stateBlock->renderState[WINED3DRS_SPECULARMATERIALSOURCE] == D3DMCS_COLOR1) {
4057 if (This->tracking_color != DISABLED_TRACKING) This->tracking_color = NEEDS_DISABLE;
4059 This->tracking_color = NEEDS_TRACKING;
4060 This->tracking_parm = Parm;
4064 if (This->tracking_color != DISABLED_TRACKING) This->tracking_color = NEEDS_DISABLE;
4069 case WINED3DRS_LINEPATTERN :
4075 tmppattern.d = Value;
4077 TRACE("Line pattern: repeat %d bits %x\n", tmppattern.lp.wRepeatFactor, tmppattern.lp.wLinePattern);
4079 if (tmppattern.lp.wRepeatFactor) {
4080 glLineStipple(tmppattern.lp.wRepeatFactor, tmppattern.lp.wLinePattern);
4081 checkGLcall("glLineStipple(repeat, linepattern)");
4082 glEnable(GL_LINE_STIPPLE);
4083 checkGLcall("glEnable(GL_LINE_STIPPLE);");
4085 glDisable(GL_LINE_STIPPLE);
4086 checkGLcall("glDisable(GL_LINE_STIPPLE);");
4091 case WINED3DRS_ZBIAS : /* D3D8 only */
4095 TRACE("ZBias value %f\n", tmpvalue.f);
4096 glPolygonOffset(0, -tmpvalue.f);
4097 checkGLcall("glPolygonOffset(0, -Value)");
4098 glEnable(GL_POLYGON_OFFSET_FILL);
4099 checkGLcall("glEnable(GL_POLYGON_OFFSET_FILL);");
4100 glEnable(GL_POLYGON_OFFSET_LINE);
4101 checkGLcall("glEnable(GL_POLYGON_OFFSET_LINE);");
4102 glEnable(GL_POLYGON_OFFSET_POINT);
4103 checkGLcall("glEnable(GL_POLYGON_OFFSET_POINT);");
4105 glDisable(GL_POLYGON_OFFSET_FILL);
4106 checkGLcall("glDisable(GL_POLYGON_OFFSET_FILL);");
4107 glDisable(GL_POLYGON_OFFSET_LINE);
4108 checkGLcall("glDisable(GL_POLYGON_OFFSET_LINE);");
4109 glDisable(GL_POLYGON_OFFSET_POINT);
4110 checkGLcall("glDisable(GL_POLYGON_OFFSET_POINT);");
4115 case WINED3DRS_NORMALIZENORMALS :
4117 glEnable(GL_NORMALIZE);
4118 checkGLcall("glEnable(GL_NORMALIZE);");
4120 glDisable(GL_NORMALIZE);
4121 checkGLcall("glDisable(GL_NORMALIZE);");
4125 case WINED3DRS_POINTSIZE :
4126 /* FIXME: check that pointSize isn't outside glGetFloatv( GL_POINT_SIZE_MAX_ARB, &maxSize ); or -ve */
4128 TRACE("Set point size to %f\n", tmpvalue.f);
4129 glPointSize(tmpvalue.f);
4130 checkGLcall("glPointSize(...);");
4133 case WINED3DRS_POINTSIZE_MIN :
4134 if (GL_SUPPORT(EXT_POINT_PARAMETERS)) {
4136 GL_EXTCALL(glPointParameterfEXT)(GL_POINT_SIZE_MIN_EXT, tmpvalue.f);
4137 checkGLcall("glPointParameterfEXT(...);");
4139 FIXME("WINED3DRS_POINTSIZE_MIN not supported on this opengl\n");
4143 case WINED3DRS_POINTSIZE_MAX :
4144 if (GL_SUPPORT(EXT_POINT_PARAMETERS)) {
4146 GL_EXTCALL(glPointParameterfEXT)(GL_POINT_SIZE_MAX_EXT, tmpvalue.f);
4147 checkGLcall("glPointParameterfEXT(...);");
4149 FIXME("WINED3DRS_POINTSIZE_MAX not supported on this opengl\n");
4153 case WINED3DRS_POINTSCALE_A :
4154 case WINED3DRS_POINTSCALE_B :
4155 case WINED3DRS_POINTSCALE_C :
4156 case WINED3DRS_POINTSCALEENABLE :
4159 * POINTSCALEENABLE controls how point size value is treated. If set to
4160 * true, the point size is scaled with respect to height of viewport.
4161 * When set to false point size is in pixels.
4163 * http://msdn.microsoft.com/library/en-us/directx9_c/point_sprites.asp
4166 /* Default values */
4167 GLfloat att[3] = {1.0f, 0.0f, 0.0f};
4170 * Minimum valid point size for OpenGL is 1.0f. For Direct3D it is 0.0f.
4171 * This means that OpenGL will clamp really small point sizes to 1.0f.
4172 * To correct for this we need to multiply by the scale factor when sizes
4173 * are less than 1.0f. scale_factor = 1.0f / point_size.
4175 GLfloat pointSize = *((float*)&This->stateBlock->renderState[WINED3DRS_POINTSIZE]);
4176 if(pointSize > 0.0f) {
4177 GLfloat scaleFactor;
4179 if(pointSize < 1.0f) {
4180 scaleFactor = pointSize * pointSize;
4185 if(This->stateBlock->renderState[WINED3DRS_POINTSCALEENABLE]) {
4186 att[0] = *((float*)&This->stateBlock->renderState[WINED3DRS_POINTSCALE_A]) /
4187 (This->stateBlock->viewport.Height * This->stateBlock->viewport.Height * scaleFactor);
4188 att[1] = *((float*)&This->stateBlock->renderState[WINED3DRS_POINTSCALE_B]) /
4189 (This->stateBlock->viewport.Height * This->stateBlock->viewport.Height * scaleFactor);
4190 att[2] = *((float*)&This->stateBlock->renderState[WINED3DRS_POINTSCALE_C]) /
4191 (This->stateBlock->viewport.Height * This->stateBlock->viewport.Height * scaleFactor);
4195 if(GL_SUPPORT(ARB_POINT_PARAMETERS)) {
4196 GL_EXTCALL(glPointParameterfvARB)(GL_POINT_DISTANCE_ATTENUATION_ARB, att);
4197 checkGLcall("glPointParameterfvARB(GL_DISTANCE_ATTENUATION_ARB, ...");
4199 else if(GL_SUPPORT(EXT_POINT_PARAMETERS)) {
4200 GL_EXTCALL(glPointParameterfvEXT)(GL_DISTANCE_ATTENUATION_EXT, att);
4201 checkGLcall("glPointParameterfvEXT(GL_DISTANCE_ATTENUATION_EXT, ...");
4203 TRACE("POINT_PARAMETERS not supported in this version of opengl\n");
4207 case WINED3DRS_COLORWRITEENABLE :
4209 TRACE("Color mask: r(%d) g(%d) b(%d) a(%d)\n",
4210 Value & D3DCOLORWRITEENABLE_RED ? 1 : 0,
4211 Value & D3DCOLORWRITEENABLE_GREEN ? 1 : 0,
4212 Value & D3DCOLORWRITEENABLE_BLUE ? 1 : 0,
4213 Value & D3DCOLORWRITEENABLE_ALPHA ? 1 : 0);
4214 glColorMask(Value & D3DCOLORWRITEENABLE_RED ? GL_TRUE : GL_FALSE,
4215 Value & D3DCOLORWRITEENABLE_GREEN ? GL_TRUE : GL_FALSE,
4216 Value & D3DCOLORWRITEENABLE_BLUE ? GL_TRUE : GL_FALSE,
4217 Value & D3DCOLORWRITEENABLE_ALPHA ? GL_TRUE : GL_FALSE);
4218 checkGLcall("glColorMask(...)");
4222 case WINED3DRS_LOCALVIEWER :
4224 GLint state = (Value) ? 1 : 0;
4225 TRACE("Local Viewer Enable to %ul\n", (BOOL) Value);
4226 glLightModeli(GL_LIGHT_MODEL_LOCAL_VIEWER, state);
4230 case WINED3DRS_LASTPIXEL :
4233 TRACE("Last Pixel Drawing Enabled\n");
4235 FIXME("Last Pixel Drawing Disabled, not handled yet\n");
4240 case WINED3DRS_SOFTWAREVERTEXPROCESSING :
4243 TRACE("Software Processing Enabled\n");
4245 TRACE("Software Processing Disabled\n");
4250 /** not supported */
4251 case WINED3DRS_ZVISIBLE :
4254 return WINED3DERR_INVALIDCALL;
4256 case WINED3DRS_POINTSPRITEENABLE :
4258 /* TODO: NV_POINT_SPRITE */
4259 if (!GL_SUPPORT(ARB_POINT_SPRITE)) {
4260 TRACE("Point sprites not supported\n");
4265 * Point sprites are always enabled. Value controls texture coordinate
4266 * replacement mode. Must be set true for point sprites to use
4269 glEnable(GL_POINT_SPRITE_ARB);
4270 checkGLcall("glEnable(GL_POINT_SPRITE_ARB)");
4273 glTexEnvf(GL_POINT_SPRITE_ARB, GL_COORD_REPLACE_ARB, TRUE);
4274 checkGLcall("glTexEnvf(GL_POINT_SPRITE, GL_COORD_REPLACE, TRUE)");
4276 glTexEnvf(GL_POINT_SPRITE_ARB, GL_COORD_REPLACE_ARB, FALSE);
4277 checkGLcall("glTexEnvf(GL_POINT_SPRITE, GL_COORD_REPLACE, FALSE)");
4281 case WINED3DRS_EDGEANTIALIAS :
4284 glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
4286 checkGLcall("glEnable(GL_BLEND)");
4287 glEnable(GL_LINE_SMOOTH);
4288 checkGLcall("glEnable(GL_LINE_SMOOTH)");
4290 if(!This->stateBlock->renderState[WINED3DRS_ALPHABLENDENABLE]) {
4291 glDisable(GL_BLEND);
4292 checkGLcall("glDisable(GL_BLEND)");
4294 glDisable(GL_LINE_SMOOTH);
4295 checkGLcall("glDisable(GL_LINE_SMOOTH)");
4299 case WINED3DRS_WRAP0 :
4300 case WINED3DRS_WRAP1 :
4301 case WINED3DRS_WRAP2 :
4302 case WINED3DRS_WRAP3 :
4303 case WINED3DRS_WRAP4 :
4304 case WINED3DRS_WRAP5 :
4305 case WINED3DRS_WRAP6 :
4306 case WINED3DRS_WRAP7 :
4307 case WINED3DRS_WRAP8 :
4308 case WINED3DRS_WRAP9 :
4309 case WINED3DRS_WRAP10 :
4310 case WINED3DRS_WRAP11 :
4311 case WINED3DRS_WRAP12 :
4312 case WINED3DRS_WRAP13 :
4313 case WINED3DRS_WRAP14 :
4314 case WINED3DRS_WRAP15 :
4316 http://www.cosc.brocku.ca/Offerings/3P98/course/lectures/texture/
4317 http://msdn.microsoft.com/archive/default.asp?url=/archive/en-us/directx9_c/directx/graphics/programmingguide/FixedFunction/Textures/texturewrapping.asp
4318 http://www.gamedev.net/reference/programming/features/rendererdll3/page2.asp
4319 Descussion that ways to turn on WRAPing to solve an opengl conversion problem.
4320 http://www.flipcode.org/cgi-bin/fcmsg.cgi?thread_show=10248
4322 so far as I can tell, wrapping and texture-coordinate generate go hand in hand,
4326 ERR("(%p)->(%s,%ld) Texture wraping not yet supported\n",This, debug_d3drenderstate(State), Value);
4331 case WINED3DRS_MULTISAMPLEANTIALIAS :
4333 if( GL_SUPPORT(ARB_MULTISAMPLE) ) {
4335 glEnable(GL_MULTISAMPLE_ARB);
4336 checkGLcall("glEnable(GL_MULTISAMPLE_ARB)");
4338 glDisable(GL_MULTISAMPLE_ARB);
4339 checkGLcall("glDisable(GL_MULTISAMPLE_ARB)");
4343 ERR("Multisample antialiasing not supported by gl\n");
4349 case WINED3DRS_SCISSORTESTENABLE :
4352 glEnable(GL_SCISSOR_TEST);
4353 checkGLcall("glEnable(GL_SCISSOR_TEST)");
4355 glDisable(GL_SCISSOR_TEST);
4356 checkGLcall("glDisable(GL_SCISSOR_TEST)");
4360 case WINED3DRS_SLOPESCALEDEPTHBIAS :
4364 glEnable(GL_POLYGON_OFFSET_FILL);
4365 checkGLcall("glEnable(GL_POLYGON_OFFSET_FILL)");
4366 glPolygonOffset(tmpvalue.f, *((float*)&This->stateBlock->renderState[WINED3DRS_DEPTHBIAS]));
4367 checkGLcall("glPolygonOffset(...)");
4369 glDisable(GL_POLYGON_OFFSET_FILL);
4370 checkGLcall("glDisable(GL_POLYGON_OFFSET_FILL)");
4374 case WINED3DRS_ANTIALIASEDLINEENABLE :
4377 glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
4379 checkGLcall("glEnable(GL_BLEND)");
4380 glEnable(GL_LINE_SMOOTH);
4381 checkGLcall("glEnable(GL_LINE_SMOOTH)");
4383 glDisable(GL_BLEND);
4384 checkGLcall("glDisable(GL_BLEND)");
4385 glDisable(GL_LINE_SMOOTH);
4386 checkGLcall("glDisable(GL_LINE_SMOOTH)");
4390 case WINED3DRS_DEPTHBIAS :
4394 glEnable(GL_POLYGON_OFFSET_FILL);
4395 checkGLcall("glEnable(GL_POLYGON_OFFSET_FILL)");
4396 glPolygonOffset(*((float*)&This->stateBlock->renderState[WINED3DRS_SLOPESCALEDEPTHBIAS]), tmpvalue.f);
4397 checkGLcall("glPolygonOffset(...)");
4399 glDisable(GL_POLYGON_OFFSET_FILL);
4400 checkGLcall("glDisable(GL_POLYGON_OFFSET_FILL)");
4405 case WINED3DRS_TEXTUREPERSPECTIVE :
4408 glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST);
4410 glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_FASTEST);
4414 case WINED3DRS_STIPPLEDALPHA :
4417 ERR(" Stippled Alpha not supported yet.\n");
4420 case WINED3DRS_ANTIALIAS :
4423 ERR(" Antialias not supported yet.\n");
4427 case WINED3DRS_MULTISAMPLEMASK :
4429 if(0xFFFFFFFF != Value)
4430 ERR("(%p)->(%s,%ld) not yet implemented\n", This, debug_d3drenderstate(State), Value);
4434 case WINED3DRS_PATCHEDGESTYLE :
4436 if(D3DPATCHEDGE_DISCRETE != Value)
4437 ERR("(%p)->(%s,%ld) not yet implemented\n", This, debug_d3drenderstate(State), Value);
4441 case WINED3DRS_PATCHSEGMENTS :
4443 /* available in d3d8 but in d3d9 it was replaced by IDirect3DDevice9::SetNPatchMode */
4445 if(tmpvalue.d != Value)
4446 ERR("(%p)->(%s,%ld) not yet implemented\n", This, debug_d3drenderstate(State), Value);
4450 case WINED3DRS_DEBUGMONITORTOKEN :
4452 /* Only useful for "debug builds". */
4453 if(0xbaadcafe != Value) {
4454 /* MSDN says the default is D3DDMT_ENABLE but our tests confirm 0xbaadcafe is the default. */
4455 /* MSDN says anything other than D3DDMT_ENABLE or DISABLE does not change the state,
4456 * but our tests disagree.
4457 * We do not claim to implement a debugging lib, so do not write an ERR
4459 WARN("(%p)->(%s,%ld) not yet implemented\n", This, debug_d3drenderstate(State), Value);
4464 case WINED3DRS_POSITIONDEGREE :
4466 if(D3DDEGREE_CUBIC != Value)
4467 ERR("(%p)->(%s,%ld) not yet implemented\n", This, debug_d3drenderstate(State), Value);
4471 case WINED3DRS_NORMALDEGREE :
4473 if(D3DDEGREE_LINEAR != Value)
4474 ERR("(%p)->(%s,%ld) not yet implemented\n", This, debug_d3drenderstate(State), Value);
4478 case WINED3DRS_MINTESSELLATIONLEVEL :
4479 case WINED3DRS_MAXTESSELLATIONLEVEL :
4480 case WINED3DRS_ADAPTIVETESS_X :
4481 case WINED3DRS_ADAPTIVETESS_Y :
4482 case WINED3DRS_ADAPTIVETESS_Z :
4483 case WINED3DRS_ADAPTIVETESS_W :
4485 if(This->stateBlock->renderState[WINED3DRS_ENABLEADAPTIVETESSELLATION])
4486 FIXME("(%p)->(%s,%ld) not yet implemented\n", This, debug_d3drenderstate(State), Value);
4488 TRACE("(%p)->(%s,%ld): recording state but WINED3DRS_ENABLEADAPTIVETESSELLATION is not enabled\n", This, debug_d3drenderstate(State), Value);
4492 case WINED3DRS_ENABLEADAPTIVETESSELLATION:
4495 ERR("(%p)->(%s,%ld) not yet implemented\n", This, debug_d3drenderstate(State), Value);
4499 case WINED3DRS_COLORWRITEENABLE1 :
4500 case WINED3DRS_COLORWRITEENABLE2 :
4501 case WINED3DRS_COLORWRITEENABLE3 :
4503 /* depends on WINED3DRS_COLORWRITEENABLE. */
4504 if(0x0000000F != Value)
4505 ERR("(%p)->(%s,%ld) not yet implemented. Missing of cap D3DPMISCCAPS_INDEPENDENTWRITEMASKS wasn't honored?\n", This, debug_d3drenderstate(State), Value);
4509 case WINED3DRS_BLENDFACTOR :
4512 if (GL_SUPPORT(ARB_IMAGING)) {
4514 TRACE("Setting BlendFactor to %ld", Value);
4516 D3DCOLORTOGLFLOAT4(Value, col);
4517 if (0xFFFFFFFF != Value) {
4519 checkGLcall("glEnable(GL_BLEND)");
4522 glDisable(GL_BLEND);
4523 checkGLcall("glDisable(GL_BLEND)");
4525 glBlendColor (col[0],col[1],col[2],col[3]);
4527 WARN("Unsupported in local OpenGL implementation: glBlendColor\n");
4532 case WINED3DRS_SRGBWRITEENABLE :
4535 ERR("(%p)->(%s,%ld) not yet implemented\n", This, debug_d3drenderstate(State), Value);
4539 case WINED3DRS_SEPARATEALPHABLENDENABLE :
4542 ERR("(%p)->(%s,%ld) not yet implemented. Missing of cap D3DPMISCCAPS_SEPARATEALPHABLEND wasn't honored?\n", This, debug_d3drenderstate(State), Value);
4546 case WINED3DRS_SRCBLENDALPHA :
4547 case WINED3DRS_DESTBLENDALPHA :
4548 case WINED3DRS_BLENDOPALPHA :
4550 if(This->stateBlock->renderState[WINED3DRS_SEPARATEALPHABLENDENABLE])
4551 FIXME("(%p)->(%s,%ld) not yet implemented\n", This, debug_d3drenderstate(State), Value);
4553 TRACE("(%p)->(%s,%ld): recording state but WINED3DRS_SEPARATEALPHABLENDENABLE is not enabled\n", This, debug_d3drenderstate(State), Value);
4558 FIXME("(%p)->(%s,%ld) unknown state\n", This, debug_d3drenderstate(State), Value);
4566 static HRESULT WINAPI IWineD3DDeviceImpl_GetRenderState(IWineD3DDevice *iface, D3DRENDERSTATETYPE State, DWORD *pValue) {
4567 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4568 TRACE("(%p) for State %d = %ld\n", This, State, This->stateBlock->renderState[State]);
4569 *pValue = This->stateBlock->renderState[State];
4574 * Get / Set Sampler States
4575 * TODO: Verify against dx9 definitions
4578 static HRESULT WINAPI IWineD3DDeviceImpl_SetSamplerState(IWineD3DDevice *iface, DWORD Sampler, WINED3DSAMPLERSTATETYPE Type, DWORD Value) {
4579 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4581 * SetSampler is designed to allow for more than the standard up to 8 textures
4582 * and Geforce has stopped supporting more than 6 standard textures in openGL.
4583 * So I have to use ARB for Gforce. (maybe if the sampler > 4 then use ARB?)
4585 * http://developer.nvidia.com/object/General_FAQ.html#t6
4587 * There are two new settings for GForce
4589 * GL_MAX_TEXTURE_IMAGE_UNITS_ARB
4590 * and the texture one:
4591 * GL_MAX_TEXTURE_COORDS_ARB.
4592 * Ok GForce say it's ok to use glTexParameter/glGetTexParameter(...).
4594 /** NOTE: States are appled in IWineD3DBaseTextre ApplyStateChanges and IWineD3DDevice SetupTextureStates**/
4595 if(Sampler > GL_LIMITS(sampler_stages) || Sampler < 0 || Type > WINED3D_HIGHEST_SAMPLER_STATE || Type < 0) {
4596 FIXME("sampler %ld type %s(%u) is out of range [max_samplers=%d, highest_state=%d]\n",
4597 Sampler, debug_d3dsamplerstate(Type), Type, GL_LIMITS(sampler_stages), WINED3D_HIGHEST_SAMPLER_STATE);
4598 return WINED3DERR_INVALIDCALL;
4601 TRACE("(%p) : Sampler=%ld, Type=%s(%d), Value=%ld\n", This, Sampler,
4602 debug_d3dsamplerstate(Type), Type, Value);
4603 This->updateStateBlock->samplerState[Sampler][Type] = Value;
4604 This->updateStateBlock->set.samplerState[Sampler][Type] = Value;
4605 This->updateStateBlock->changed.samplerState[Sampler][Type] = Value;
4607 /* Handle recording of state blocks */
4608 if (This->isRecordingState) {
4609 TRACE("Recording... not performing anything\n");
4616 static HRESULT WINAPI IWineD3DDeviceImpl_GetSamplerState(IWineD3DDevice *iface, DWORD Sampler, WINED3DSAMPLERSTATETYPE Type, DWORD* Value) {
4617 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4618 /** TODO: check that sampler is in range **/
4619 *Value = This->updateStateBlock->samplerState[Sampler][Type];
4620 TRACE("(%p) : Sampler %ld Type %u Returning %ld\n", This, Sampler, Type, *Value);
4625 static HRESULT WINAPI IWineD3DDeviceImpl_SetScissorRect(IWineD3DDevice *iface, CONST RECT* pRect) {
4626 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4629 /** FIXME: Windows uses a top,left origin openGL uses a bottom Right? **/
4630 TRACE("(%p)Setting new Scissor Rect to %ld:%ld-%ld:%ld\n", This, pRect->left, pRect->top, pRect->right, pRect->bottom);
4631 glScissor(pRect->left, pRect->top, pRect->right - pRect->left, pRect->bottom - pRect->top);
4637 static HRESULT WINAPI IWineD3DDeviceImpl_GetScissorRect(IWineD3DDevice *iface, RECT* pRect) {
4638 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4639 GLint scissorBox[4];
4642 /** FIXME: Windows uses a top,left origin openGL uses a bottom Right? **/
4643 glGetIntegerv(GL_SCISSOR_BOX, scissorBox);
4644 pRect->left = scissorBox[0];
4645 pRect->top = scissorBox[1];
4646 pRect->right = scissorBox[0] + scissorBox[2];
4647 pRect->bottom = scissorBox[1] + scissorBox[3];
4648 TRACE("(%p)Returning a Scissor Rect of %ld:%ld-%ld:%ld\n", This, pRect->left, pRect->top, pRect->right, pRect->bottom);
4653 static HRESULT WINAPI IWineD3DDeviceImpl_SetVertexDeclaration(IWineD3DDevice* iface, IWineD3DVertexDeclaration* pDecl) {
4654 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *) iface;
4655 IWineD3DVertexDeclaration *oldDecl = This->updateStateBlock->vertexDecl;
4657 TRACE("(%p) : pDecl=%p\n", This, pDecl);
4659 This->updateStateBlock->vertexDecl = pDecl;
4660 This->updateStateBlock->changed.vertexDecl = TRUE;
4661 This->updateStateBlock->set.vertexDecl = TRUE;
4663 if (This->isRecordingState) {
4664 TRACE("Recording... not performing anything\n");
4667 if (NULL != pDecl) {
4668 IWineD3DVertexDeclaration_AddRef(pDecl);
4670 if (NULL != oldDecl) {
4671 IWineD3DVertexDeclaration_Release(oldDecl);
4676 static HRESULT WINAPI IWineD3DDeviceImpl_GetVertexDeclaration(IWineD3DDevice* iface, IWineD3DVertexDeclaration** ppDecl) {
4677 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4679 TRACE("(%p) : ppDecl=%p\n", This, ppDecl);
4681 *ppDecl = This->stateBlock->vertexDecl;
4682 if (NULL != *ppDecl) IWineD3DVertexDeclaration_AddRef(*ppDecl);
4686 static HRESULT WINAPI IWineD3DDeviceImpl_SetVertexShader(IWineD3DDevice *iface, IWineD3DVertexShader* pShader) {
4687 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4688 IWineD3DVertexShader* oldShader = This->updateStateBlock->vertexShader;
4690 This->updateStateBlock->vertexShader = pShader;
4691 This->updateStateBlock->changed.vertexShader = TRUE;
4692 This->updateStateBlock->set.vertexShader = TRUE;
4694 if (This->isRecordingState) {
4695 TRACE("Recording... not performing anything\n");
4698 if (NULL != pShader) {
4699 IWineD3DVertexShader_AddRef(pShader);
4701 if (NULL != oldShader) {
4702 IWineD3DVertexShader_Release(oldShader);
4705 TRACE("(%p) : setting pShader(%p)\n", This, pShader);
4707 * TODO: merge HAL shaders context switching from prototype
4712 static HRESULT WINAPI IWineD3DDeviceImpl_GetVertexShader(IWineD3DDevice *iface, IWineD3DVertexShader** ppShader) {
4713 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4715 if (NULL == ppShader) {
4716 return WINED3DERR_INVALIDCALL;
4718 *ppShader = This->stateBlock->vertexShader;
4719 if( NULL != *ppShader)
4720 IWineD3DVertexShader_AddRef(*ppShader);
4722 TRACE("(%p) : returning %p\n", This, *ppShader);
4726 static HRESULT WINAPI IWineD3DDeviceImpl_SetVertexShaderConstantB(
4727 IWineD3DDevice *iface,
4729 CONST BOOL *srcData,
4732 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4733 int i, cnt = min(count, MAX_CONST_B - start);
4735 TRACE("(iface %p, srcData %p, start %d, count %d)\n",
4736 iface, srcData, start, count);
4738 if (srcData == NULL || cnt < 0)
4739 return WINED3DERR_INVALIDCALL;
4741 memcpy(&This->updateStateBlock->vertexShaderConstantB[start], srcData, cnt * sizeof(BOOL));
4742 for (i = 0; i < cnt; i++)
4743 TRACE("Set BOOL constant %u to %s\n", start + i, srcData[i]? "true":"false");
4745 for (i = start; i < cnt + start; ++i) {
4746 This->updateStateBlock->changed.vertexShaderConstantsB[i] = TRUE;
4747 This->updateStateBlock->set.vertexShaderConstantsB[i] = TRUE;
4753 static HRESULT WINAPI IWineD3DDeviceImpl_GetVertexShaderConstantB(
4754 IWineD3DDevice *iface,
4759 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4760 int cnt = min(count, MAX_CONST_B - start);
4762 TRACE("(iface %p, dstData %p, start %d, count %d)\n",
4763 iface, dstData, start, count);
4765 if (dstData == NULL || cnt < 0)
4766 return WINED3DERR_INVALIDCALL;
4768 memcpy(dstData, &This->stateBlock->vertexShaderConstantB[start], cnt * sizeof(BOOL));
4772 static HRESULT WINAPI IWineD3DDeviceImpl_SetVertexShaderConstantI(
4773 IWineD3DDevice *iface,
4778 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4779 int i, cnt = min(count, MAX_CONST_I - start);
4781 TRACE("(iface %p, srcData %p, start %d, count %d)\n",
4782 iface, srcData, start, count);
4784 if (srcData == NULL || cnt < 0)
4785 return WINED3DERR_INVALIDCALL;
4787 memcpy(&This->updateStateBlock->vertexShaderConstantI[start * 4], srcData, cnt * sizeof(int) * 4);
4788 for (i = 0; i < cnt; i++)
4789 TRACE("Set INT constant %u to { %d, %d, %d, %d }\n", start + i,
4790 srcData[i*4], srcData[i*4+1], srcData[i*4+2], srcData[i*4+3]);
4792 for (i = start; i < cnt + start; ++i) {
4793 This->updateStateBlock->changed.vertexShaderConstantsI[i] = TRUE;
4794 This->updateStateBlock->set.vertexShaderConstantsI[i] = TRUE;
4800 static HRESULT WINAPI IWineD3DDeviceImpl_GetVertexShaderConstantI(
4801 IWineD3DDevice *iface,
4806 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4807 int cnt = min(count, MAX_CONST_I - start);
4809 TRACE("(iface %p, dstData %p, start %d, count %d)\n",
4810 iface, dstData, start, count);
4812 if (dstData == NULL || ((signed int) MAX_CONST_I - (signed int) start) <= (signed int) 0)
4813 return WINED3DERR_INVALIDCALL;
4815 memcpy(dstData, &This->stateBlock->vertexShaderConstantI[start * 4], cnt * sizeof(int) * 4);
4819 static HRESULT WINAPI IWineD3DDeviceImpl_SetVertexShaderConstantF(
4820 IWineD3DDevice *iface,
4822 CONST float *srcData,
4825 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4826 int i, cnt = min(count, GL_LIMITS(vshader_constantsF) - start);
4828 TRACE("(iface %p, srcData %p, start %d, count %d)\n",
4829 iface, srcData, start, count);
4831 if (srcData == NULL || ((signed int) GL_LIMITS(vshader_constantsF) - (signed int) start) <= (signed int) 0)
4832 return WINED3DERR_INVALIDCALL;
4834 memcpy(&This->updateStateBlock->vertexShaderConstantF[start * 4], srcData, cnt * sizeof(float) * 4);
4835 for (i = 0; i < cnt; i++)
4836 TRACE("Set FLOAT constant %u to { %f, %f, %f, %f }\n", start + i,
4837 srcData[i*4], srcData[i*4+1], srcData[i*4+2], srcData[i*4+3]);
4839 for (i = start; i < cnt + start; ++i) {
4840 if (!This->updateStateBlock->set.vertexShaderConstantsF[i]) {
4841 constant_entry *ptr = HeapAlloc(GetProcessHeap(), 0, sizeof(constant_entry));
4843 list_add_head(&This->updateStateBlock->set_vconstantsF, &ptr->entry);
4844 This->updateStateBlock->set.vertexShaderConstantsF[i] = TRUE;
4846 This->updateStateBlock->changed.vertexShaderConstantsF[i] = TRUE;
4852 static HRESULT WINAPI IWineD3DDeviceImpl_GetVertexShaderConstantF(
4853 IWineD3DDevice *iface,
4858 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4859 int cnt = min(count, GL_LIMITS(vshader_constantsF) - start);
4861 TRACE("(iface %p, dstData %p, start %d, count %d)\n",
4862 iface, dstData, start, count);
4864 if (dstData == NULL || cnt < 0)
4865 return WINED3DERR_INVALIDCALL;
4867 memcpy(dstData, &This->stateBlock->vertexShaderConstantF[start * 4], cnt * sizeof(float) * 4);
4871 static HRESULT WINAPI IWineD3DDeviceImpl_SetPixelShader(IWineD3DDevice *iface, IWineD3DPixelShader *pShader) {
4872 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4873 IWineD3DPixelShader *oldShader = This->updateStateBlock->pixelShader;
4874 This->updateStateBlock->pixelShader = pShader;
4875 This->updateStateBlock->changed.pixelShader = TRUE;
4876 This->updateStateBlock->set.pixelShader = TRUE;
4878 /* Handle recording of state blocks */
4879 if (This->isRecordingState) {
4880 TRACE("Recording... not performing anything\n");
4883 if (NULL != pShader) {
4884 IWineD3DPixelShader_AddRef(pShader);
4886 if (NULL != oldShader) {
4887 IWineD3DPixelShader_Release(oldShader);
4890 TRACE("(%p) : setting pShader(%p)\n", This, pShader);
4892 * TODO: merge HAL shaders context switching from prototype
4897 static HRESULT WINAPI IWineD3DDeviceImpl_GetPixelShader(IWineD3DDevice *iface, IWineD3DPixelShader **ppShader) {
4898 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4900 if (NULL == ppShader) {
4901 WARN("(%p) : PShader is NULL, returning INVALIDCALL\n", This);
4902 return WINED3DERR_INVALIDCALL;
4905 *ppShader = This->stateBlock->pixelShader;
4906 if (NULL != *ppShader) {
4907 IWineD3DPixelShader_AddRef(*ppShader);
4909 TRACE("(%p) : returning %p\n", This, *ppShader);
4913 static HRESULT WINAPI IWineD3DDeviceImpl_SetPixelShaderConstantB(
4914 IWineD3DDevice *iface,
4916 CONST BOOL *srcData,
4919 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4920 int i, cnt = min(count, MAX_CONST_B - start);
4922 TRACE("(iface %p, srcData %p, start %d, count %d)\n",
4923 iface, srcData, start, count);
4925 if (srcData == NULL || cnt < 0)
4926 return WINED3DERR_INVALIDCALL;
4928 memcpy(&This->updateStateBlock->pixelShaderConstantB[start], srcData, cnt * sizeof(BOOL));
4929 for (i = 0; i < cnt; i++)
4930 TRACE("Set BOOL constant %u to %s\n", start + i, srcData[i]? "true":"false");
4932 for (i = start; i < cnt + start; ++i) {
4933 This->updateStateBlock->changed.pixelShaderConstantsB[i] = TRUE;
4934 This->updateStateBlock->set.pixelShaderConstantsB[i] = TRUE;
4940 static HRESULT WINAPI IWineD3DDeviceImpl_GetPixelShaderConstantB(
4941 IWineD3DDevice *iface,
4946 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4947 int cnt = min(count, MAX_CONST_B - start);
4949 TRACE("(iface %p, dstData %p, start %d, count %d)\n",
4950 iface, dstData, start, count);
4952 if (dstData == NULL || cnt < 0)
4953 return WINED3DERR_INVALIDCALL;
4955 memcpy(dstData, &This->stateBlock->pixelShaderConstantB[start], cnt * sizeof(BOOL));
4959 static HRESULT WINAPI IWineD3DDeviceImpl_SetPixelShaderConstantI(
4960 IWineD3DDevice *iface,
4965 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4966 int i, cnt = min(count, MAX_CONST_I - start);
4968 TRACE("(iface %p, srcData %p, start %d, count %d)\n",
4969 iface, srcData, start, count);
4971 if (srcData == NULL || cnt < 0)
4972 return WINED3DERR_INVALIDCALL;
4974 memcpy(&This->updateStateBlock->pixelShaderConstantI[start * 4], srcData, cnt * sizeof(int) * 4);
4975 for (i = 0; i < cnt; i++)
4976 TRACE("Set INT constant %u to { %d, %d, %d, %d }\n", start + i,
4977 srcData[i*4], srcData[i*4+1], srcData[i*4+2], srcData[i*4+3]);
4979 for (i = start; i < cnt + start; ++i) {
4980 This->updateStateBlock->changed.pixelShaderConstantsI[i] = TRUE;
4981 This->updateStateBlock->set.pixelShaderConstantsI[i] = TRUE;
4987 static HRESULT WINAPI IWineD3DDeviceImpl_GetPixelShaderConstantI(
4988 IWineD3DDevice *iface,
4993 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4994 int cnt = min(count, MAX_CONST_I - start);
4996 TRACE("(iface %p, dstData %p, start %d, count %d)\n",
4997 iface, dstData, start, count);
4999 if (dstData == NULL || cnt < 0)
5000 return WINED3DERR_INVALIDCALL;
5002 memcpy(dstData, &This->stateBlock->pixelShaderConstantI[start * 4], cnt * sizeof(int) * 4);
5006 static HRESULT WINAPI IWineD3DDeviceImpl_SetPixelShaderConstantF(
5007 IWineD3DDevice *iface,
5009 CONST float *srcData,
5012 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5013 int i, cnt = min(count, GL_LIMITS(pshader_constantsF) - start);
5015 TRACE("(iface %p, srcData %p, start %d, count %d)\n",
5016 iface, srcData, start, count);
5018 if (srcData == NULL || cnt < 0)
5019 return WINED3DERR_INVALIDCALL;
5021 memcpy(&This->updateStateBlock->pixelShaderConstantF[start * 4], srcData, cnt * sizeof(float) * 4);
5022 for (i = 0; i < cnt; i++)
5023 TRACE("Set FLOAT constant %u to { %f, %f, %f, %f }\n", start + i,
5024 srcData[i*4], srcData[i*4+1], srcData[i*4+2], srcData[i*4+3]);
5026 for (i = start; i < cnt + start; ++i) {
5027 if (!This->updateStateBlock->set.pixelShaderConstantsF[i]) {
5028 constant_entry *ptr = HeapAlloc(GetProcessHeap(), 0, sizeof(constant_entry));
5030 list_add_head(&This->updateStateBlock->set_pconstantsF, &ptr->entry);
5031 This->updateStateBlock->set.pixelShaderConstantsF[i] = TRUE;
5033 This->updateStateBlock->changed.pixelShaderConstantsF[i] = TRUE;
5039 static HRESULT WINAPI IWineD3DDeviceImpl_GetPixelShaderConstantF(
5040 IWineD3DDevice *iface,
5045 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5046 int cnt = min(count, GL_LIMITS(pshader_constantsF) - start);
5048 TRACE("(iface %p, dstData %p, start %d, count %d)\n",
5049 iface, dstData, start, count);
5051 if (dstData == NULL || cnt < 0)
5052 return WINED3DERR_INVALIDCALL;
5054 memcpy(dstData, &This->stateBlock->pixelShaderConstantF[start * 4], cnt * sizeof(float) * 4);
5058 #define copy_and_next(dest, src, size) memcpy(dest, src, size); dest += (size)
5060 process_vertices_strided(IWineD3DDeviceImpl *This, DWORD dwDestIndex, DWORD dwCount, WineDirect3DVertexStridedData *lpStrideData, DWORD SrcFVF, IWineD3DVertexBufferImpl *dest, DWORD dwFlags) {
5061 char *dest_ptr, *dest_conv = NULL;
5063 DWORD DestFVF = dest->fvf;
5065 D3DMATRIX mat, proj_mat, view_mat, world_mat;
5069 if (SrcFVF & D3DFVF_NORMAL) {
5070 WARN(" lighting state not saved yet... Some strange stuff may happen !\n");
5073 if ( (SrcFVF & D3DFVF_POSITION_MASK) != D3DFVF_XYZ) {
5074 ERR("Source has no position mask\n");
5075 return WINED3DERR_INVALIDCALL;
5078 /* We might access VBOs from this code, so hold the lock */
5081 if (dest->resource.allocatedMemory == NULL) {
5082 /* This may happen if we do direct locking into a vbo. Unlikely,
5083 * but theoretically possible(ddraw processvertices test)
5085 dest->resource.allocatedMemory = HeapAlloc(GetProcessHeap(), 0, dest->resource.size);
5086 if(!dest->resource.allocatedMemory) {
5088 ERR("Out of memory\n");
5089 return E_OUTOFMEMORY;
5093 GL_EXTCALL(glBindBufferARB(GL_ARRAY_BUFFER_ARB, dest->vbo));
5094 checkGLcall("glBindBufferARB");
5095 src = GL_EXTCALL(glMapBufferARB(GL_ARRAY_BUFFER_ARB, GL_READ_ONLY_ARB));
5097 memcpy(dest->resource.allocatedMemory, src, dest->resource.size);
5099 GL_EXTCALL(glUnmapBufferARB(GL_ARRAY_BUFFER_ARB));
5100 checkGLcall("glUnmapBufferARB");
5104 /* Get a pointer into the destination vbo(create one if none exists) and
5105 * write correct opengl data into it. It's cheap and allows us to run drawStridedFast
5107 if(!dest->vbo && GL_SUPPORT(ARB_VERTEX_BUFFER_OBJECT)) {
5112 GL_EXTCALL(glBindBufferARB(GL_ARRAY_BUFFER_ARB, dest->vbo));
5113 dest_conv = GL_EXTCALL(glMapBufferARB(GL_ARRAY_BUFFER_ARB, GL_WRITE_ONLY_ARB));
5115 ERR("glMapBuffer failed\n");
5116 /* Continue without storing converted vertices */
5121 * a) D3DRS_CLIPPING is enabled
5122 * b) WINED3DVOP_CLIP is passed
5124 if(This->stateBlock->renderState[WINED3DRS_CLIPPING]) {
5125 static BOOL warned = FALSE;
5127 * The clipping code is not quite correct. Some things need
5128 * to be checked against IDirect3DDevice3 (!), d3d8 and d3d9,
5129 * so disable clipping for now.
5130 * (The graphics in Half-Life are broken, and my processvertices
5131 * test crashes with IDirect3DDevice3)
5137 FIXME("Clipping is broken and disabled for now\n");
5139 } else doClip = FALSE;
5140 dest_ptr = ((char *) dest->resource.allocatedMemory) + dwDestIndex * get_flexible_vertex_size(DestFVF);
5142 dest_conv = ((char *) dest_conv) + dwDestIndex * get_flexible_vertex_size(DestFVF);
5145 IWineD3DDevice_GetTransform( (IWineD3DDevice *) This,
5148 IWineD3DDevice_GetTransform( (IWineD3DDevice *) This,
5149 WINED3DTS_PROJECTION,
5151 IWineD3DDevice_GetTransform( (IWineD3DDevice *) This,
5152 WINED3DTS_WORLDMATRIX(0),
5155 TRACE("View mat:\n");
5156 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); \
5157 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); \
5158 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); \
5159 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); \
5161 TRACE("Proj mat:\n");
5162 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); \
5163 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); \
5164 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); \
5165 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); \
5167 TRACE("World mat:\n");
5168 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); \
5169 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); \
5170 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); \
5171 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); \
5173 /* Get the viewport */
5174 IWineD3DDevice_GetViewport( (IWineD3DDevice *) This, &vp);
5175 TRACE("Viewport: X=%ld, Y=%ld, Width=%ld, Height=%ld, MinZ=%f, MaxZ=%f\n",
5176 vp.X, vp.Y, vp.Width, vp.Height, vp.MinZ, vp.MaxZ);
5178 multiply_matrix(&mat,&view_mat,&world_mat);
5179 multiply_matrix(&mat,&proj_mat,&mat);
5181 numTextures = (DestFVF & D3DFVF_TEXCOUNT_MASK) >> D3DFVF_TEXCOUNT_SHIFT;
5183 for (i = 0; i < dwCount; i+= 1) {
5184 unsigned int tex_index;
5186 if ( ((DestFVF & D3DFVF_POSITION_MASK) == D3DFVF_XYZ ) ||
5187 ((DestFVF & D3DFVF_POSITION_MASK) == D3DFVF_XYZRHW ) ) {
5188 /* The position first */
5190 (float *) (((char *) lpStrideData->u.s.position.lpData) + i * lpStrideData->u.s.position.dwStride);
5192 TRACE("In: ( %06.2f %06.2f %06.2f )\n", p[0], p[1], p[2]);
5194 /* Multiplication with world, view and projection matrix */
5195 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);
5196 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);
5197 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);
5198 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);
5200 TRACE("x=%f y=%f z=%f rhw=%f\n", x, y, z, rhw);
5202 /* WARNING: The following things are taken from d3d7 and were not yet checked
5203 * against d3d8 or d3d9!
5206 /* Clipping conditions: From
5207 * http://msdn.microsoft.com/archive/default.asp?url=/archive/en-us/directx9_c/directx/graphics/programmingguide/fixedfunction/viewportsclipping/clippingvolumes.asp
5209 * A vertex is clipped if it does not match the following requirements
5213 * 0 < rhw ( Not in d3d7, but tested in d3d7)
5215 * If clipping is on is determined by the D3DVOP_CLIP flag in D3D7, and
5216 * by the D3DRS_CLIPPING in D3D9(according to the msdn, not checked)
5220 if( doClip == FALSE ||
5221 ( (-rhw -eps < x) && (-rhw -eps < y) && ( -eps < z) &&
5222 (x <= rhw + eps) && (y <= rhw + eps ) && (z <= rhw + eps) &&
5225 /* "Normal" viewport transformation (not clipped)
5226 * 1) The values are divided by rhw
5227 * 2) The y axis is negative, so multiply it with -1
5228 * 3) Screen coordinates go from -(Width/2) to +(Width/2) and
5229 * -(Height/2) to +(Height/2). The z range is MinZ to MaxZ
5230 * 4) Multiply x with Width/2 and add Width/2
5231 * 5) The same for the height
5232 * 6) Add the viewpoint X and Y to the 2D coordinates and
5233 * The minimum Z value to z
5234 * 7) rhw = 1 / rhw Reciprocal of Homogeneous W....
5236 * Well, basically it's simply a linear transformation into viewport
5248 z *= vp.MaxZ - vp.MinZ;
5250 x += vp.Width / 2 + vp.X;
5251 y += vp.Height / 2 + vp.Y;
5256 /* That vertex got clipped
5257 * Contrary to OpenGL it is not dropped completely, it just
5258 * undergoes a different calculation.
5260 TRACE("Vertex got clipped\n");
5267 /* Msdn mentions that Direct3D9 keeps a list of clipped vertices
5268 * outside of the main vertex buffer memory. That needs some more
5273 TRACE("Writing (%f %f %f) %f\n", x, y, z, rhw);
5276 ( (float *) dest_ptr)[0] = x;
5277 ( (float *) dest_ptr)[1] = y;
5278 ( (float *) dest_ptr)[2] = z;
5279 ( (float *) dest_ptr)[3] = rhw; /* SIC, see ddraw test! */
5281 dest_ptr += 3 * sizeof(float);
5283 if((DestFVF & D3DFVF_POSITION_MASK) == D3DFVF_XYZRHW) {
5284 dest_ptr += sizeof(float);
5289 ( (float *) dest_conv)[0] = x * w;
5290 ( (float *) dest_conv)[1] = y * w;
5291 ( (float *) dest_conv)[2] = z * w;
5292 ( (float *) dest_conv)[3] = w;
5294 dest_conv += 3 * sizeof(float);
5296 if((DestFVF & D3DFVF_POSITION_MASK) == D3DFVF_XYZRHW) {
5297 dest_conv += sizeof(float);
5301 if (DestFVF & D3DFVF_PSIZE) {
5302 dest_ptr += sizeof(DWORD);
5303 if(dest_conv) dest_conv += sizeof(DWORD);
5305 if (DestFVF & D3DFVF_NORMAL) {
5307 (float *) (((float *) lpStrideData->u.s.normal.lpData) + i * lpStrideData->u.s.normal.dwStride);
5308 /* AFAIK this should go into the lighting information */
5309 FIXME("Didn't expect the destination to have a normal\n");
5310 copy_and_next(dest_ptr, normal, 3 * sizeof(float));
5312 copy_and_next(dest_conv, normal, 3 * sizeof(float));
5316 if (DestFVF & D3DFVF_DIFFUSE) {
5318 (DWORD *) (((char *) lpStrideData->u.s.diffuse.lpData) + i * lpStrideData->u.s.diffuse.dwStride);
5320 static BOOL warned = FALSE;
5322 if(warned == FALSE) {
5323 ERR("No diffuse color in source, but destination has one\n");
5327 *( (DWORD *) dest_ptr) = 0xffffffff;
5328 dest_ptr += sizeof(DWORD);
5331 *( (DWORD *) dest_conv) = 0xffffffff;
5332 dest_conv += sizeof(DWORD);
5336 copy_and_next(dest_ptr, color_d, sizeof(DWORD));
5338 *( (DWORD *) dest_conv) = (*color_d & 0xff00ff00) ; /* Alpha + green */
5339 *( (DWORD *) dest_conv) |= (*color_d & 0x00ff0000) >> 16; /* Red */
5340 *( (DWORD *) dest_conv) |= (*color_d & 0xff0000ff) << 16; /* Blue */
5341 dest_conv += sizeof(DWORD);
5346 if (DestFVF & D3DFVF_SPECULAR) {
5347 /* What's the color value in the feedback buffer? */
5349 (DWORD *) (((char *) lpStrideData->u.s.specular.lpData) + i * lpStrideData->u.s.specular.dwStride);
5351 static BOOL warned = FALSE;
5353 if(warned == FALSE) {
5354 ERR("No specular color in source, but destination has one\n");
5358 *( (DWORD *) dest_ptr) = 0xFF000000;
5359 dest_ptr += sizeof(DWORD);
5362 *( (DWORD *) dest_conv) = 0xFF000000;
5363 dest_conv += sizeof(DWORD);
5367 copy_and_next(dest_ptr, color_s, sizeof(DWORD));
5369 *( (DWORD *) dest_conv) = (*color_s & 0xff00ff00) ; /* Alpha + green */
5370 *( (DWORD *) dest_conv) |= (*color_s & 0x00ff0000) >> 16; /* Red */
5371 *( (DWORD *) dest_conv) |= (*color_s & 0xff0000ff) << 16; /* Blue */
5372 dest_conv += sizeof(DWORD);
5377 for (tex_index = 0; tex_index < numTextures; tex_index++) {
5379 (float *) (((char *) lpStrideData->u.s.texCoords[tex_index].lpData) +
5380 i * lpStrideData->u.s.texCoords[tex_index].dwStride);
5382 ERR("No source texture, but destination requests one\n");
5383 dest_ptr+=GET_TEXCOORD_SIZE_FROM_FVF(DestFVF, tex_index) * sizeof(float);
5384 if(dest_conv) dest_conv += GET_TEXCOORD_SIZE_FROM_FVF(DestFVF, tex_index) * sizeof(float);
5387 copy_and_next(dest_ptr, tex_coord, GET_TEXCOORD_SIZE_FROM_FVF(DestFVF, tex_index) * sizeof(float));
5389 copy_and_next(dest_conv, tex_coord, GET_TEXCOORD_SIZE_FROM_FVF(DestFVF, tex_index) * sizeof(float));
5396 GL_EXTCALL(glUnmapBufferARB(GL_ARRAY_BUFFER_ARB));
5397 checkGLcall("glUnmapBufferARB(GL_ARRAY_BUFFER_ARB)");
5404 #undef copy_and_next
5406 static HRESULT WINAPI IWineD3DDeviceImpl_ProcessVertices(IWineD3DDevice *iface, UINT SrcStartIndex, UINT DestIndex, UINT VertexCount, IWineD3DVertexBuffer* pDestBuffer, IWineD3DVertexBuffer* pVertexDecl, DWORD Flags) {
5407 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5408 IWineD3DVertexBufferImpl *SrcImpl = (IWineD3DVertexBufferImpl *) pVertexDecl;
5409 WineDirect3DVertexStridedData strided;
5410 TRACE("(%p)->(%d,%d,%d,%p,%p,%ld\n", This, SrcStartIndex, DestIndex, VertexCount, pDestBuffer, pVertexDecl, Flags);
5413 WARN("NULL source vertex buffer\n");
5414 return WINED3DERR_INVALIDCALL;
5416 /* We don't need the source vbo because this buffer is only used as
5417 * a source for ProcessVertices. Avoid wasting resources by converting the
5418 * buffer and loading the VBO
5421 TRACE("Releaseing the source vbo, it won't be needed\n");
5423 if(!SrcImpl->resource.allocatedMemory) {
5424 /* Rescue the data from the buffer */
5426 SrcImpl->resource.allocatedMemory = HeapAlloc(GetProcessHeap(), 0, SrcImpl->resource.size);
5427 if(!SrcImpl->resource.allocatedMemory) {
5428 ERR("Out of memory\n");
5429 return E_OUTOFMEMORY;
5433 GL_EXTCALL(glBindBufferARB(GL_ARRAY_BUFFER_ARB, SrcImpl->vbo));
5434 checkGLcall("glBindBufferARB");
5436 src = GL_EXTCALL(glMapBufferARB(GL_ARRAY_BUFFER_ARB, GL_READ_ONLY_ARB));
5438 memcpy(SrcImpl->resource.allocatedMemory, src, SrcImpl->resource.size);
5441 GL_EXTCALL(glUnmapBufferARB(GL_ARRAY_BUFFER_ARB));
5442 checkGLcall("glUnmapBufferARB");
5447 GL_EXTCALL(glBindBufferARB(GL_ARRAY_BUFFER_ARB, 0));
5448 checkGLcall("glBindBufferARB");
5449 GL_EXTCALL(glDeleteBuffersARB(1, &SrcImpl->vbo));
5450 checkGLcall("glDeleteBuffersARB");
5456 memset(&strided, 0, sizeof(strided));
5457 primitiveConvertFVFtoOffset(SrcImpl->fvf, get_flexible_vertex_size(SrcImpl->fvf), SrcImpl->resource.allocatedMemory + get_flexible_vertex_size(SrcImpl->fvf) * SrcStartIndex, &strided, 0);
5459 return process_vertices_strided(This, DestIndex, VertexCount, &strided, SrcImpl->fvf, (IWineD3DVertexBufferImpl *) pDestBuffer, Flags);
5463 * Apply / Get / Set Texture Stage States
5464 * TODO: Verify against dx9 definitions
5467 /* 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 */
5468 static void WINAPI IWineD3DDeviceImpl_ApplyTextureUnitState(IWineD3DDevice *iface, DWORD Stage, WINED3DTEXTURESTAGESTATETYPE Type) {
5469 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5470 DWORD Value = This->updateStateBlock->textureState[Stage][Type];
5471 /* FIXME: Handle 3d textures? What if TSS value set before set texture? Need to reapply all values? */
5473 TRACE("(%p) : Stage=%ld, Type=%s(%d), Value=%ld\n", This, Stage, debug_d3dtexturestate(Type), Type, Value);
5475 /* Check that the stage is within limits */
5476 if (Stage >= GL_LIMITS(texture_stages) || Stage < 0) {
5477 TRACE("Attempt to access invalid texture rejected\n");
5484 case WINED3DTSS_ALPHAOP :
5485 case WINED3DTSS_COLOROP :
5486 /* nothing to do as moved to drawprim for now */
5488 case WINED3DTSS_ADDRESSW :
5489 #if 0 /* I'm not sure what D3D does about ADDRESSW appearing twice */
5490 if (Value < minLookup[WINELOOKUP_WARPPARAM] || Value > maxLookup[WINELOOKUP_WARPPARAM]) {
5491 FIXME("Unrecognized or unsupported D3DTADDRESS_* value %ld, state %d\n", Value, Type);
5494 GLint wrapParm = stateLookup[WINELOOKUP_WARPPARAM][Value - minLookup[WINELOOKUP_WARPPARAM]];
5495 TRACE("Setting WRAP_R to %d for %x\n", wrapParm, This->stateBlock->textureDimensions[Stage]);
5496 glTexParameteri(This->stateBlock->textureDimensions[Stage], GL_TEXTURE_WRAP_R, wrapParm);
5497 checkGLcall("glTexParameteri(..., GL_TEXTURE_WRAP_R, wrapParm)");
5500 case WINED3DTSS_TEXCOORDINDEX :
5502 /* Values 0-7 are indexes into the FVF tex coords - See comments in DrawPrimitive */
5504 /* FIXME: From MSDN: The WINED3DTSS_TCI_* flags are mutually exclusive. If you include
5505 one flag, you can still specify an index value, which the system uses to
5506 determine the texture wrapping mode.
5507 eg. SetTextureStageState( 0, D3DTSS_TEXCOORDINDEX, D3DTSS_TCI_CAMERASPACEPOSITION | 1 );
5508 means use the vertex position (camera-space) as the input texture coordinates
5509 for this texture stage, and the wrap mode set in the WINED3DRS_WRAP1 render
5510 state. We do not (yet) support the D3DRENDERSTATE_WRAPx values, nor tie them up
5511 to the TEXCOORDINDEX value */
5514 * Be careful the value of the mask 0xF0000 come from d3d8types.h infos
5516 switch (Value & 0xFFFF0000) {
5517 case D3DTSS_TCI_PASSTHRU:
5518 /*Use the specified texture coordinates contained within the vertex format. This value resolves to zero.*/
5519 glDisable(GL_TEXTURE_GEN_S);
5520 glDisable(GL_TEXTURE_GEN_T);
5521 glDisable(GL_TEXTURE_GEN_R);
5522 glDisable(GL_TEXTURE_GEN_Q);
5523 checkGLcall("glDisable(GL_TEXTURE_GEN_S,T,R,Q)");
5526 case D3DTSS_TCI_CAMERASPACEPOSITION:
5527 /* CameraSpacePosition means use the vertex position, transformed to camera space,
5528 as the input texture coordinates for this stage's texture transformation. This
5529 equates roughly to EYE_LINEAR */
5531 float s_plane[] = { 1.0, 0.0, 0.0, 0.0 };
5532 float t_plane[] = { 0.0, 1.0, 0.0, 0.0 };
5533 float r_plane[] = { 0.0, 0.0, 1.0, 0.0 };
5534 float q_plane[] = { 0.0, 0.0, 0.0, 1.0 };
5535 TRACE("WINED3DTSS_TCI_CAMERASPACEPOSITION - Set eye plane\n");
5537 glMatrixMode(GL_MODELVIEW);
5540 glTexGenfv(GL_S, GL_EYE_PLANE, s_plane);
5541 glTexGenfv(GL_T, GL_EYE_PLANE, t_plane);
5542 glTexGenfv(GL_R, GL_EYE_PLANE, r_plane);
5543 glTexGenfv(GL_Q, GL_EYE_PLANE, q_plane);
5546 TRACE("WINED3DTSS_TCI_CAMERASPACEPOSITION - Set GL_TEXTURE_GEN_x and GL_x, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR\n");
5547 glEnable(GL_TEXTURE_GEN_S);
5548 checkGLcall("glEnable(GL_TEXTURE_GEN_S);");
5549 glTexGeni(GL_S, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR);
5550 checkGLcall("glTexGeni(GL_S, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR)");
5551 glEnable(GL_TEXTURE_GEN_T);
5552 checkGLcall("glEnable(GL_TEXTURE_GEN_T);");
5553 glTexGeni(GL_T, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR);
5554 checkGLcall("glTexGeni(GL_T, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR)");
5555 glEnable(GL_TEXTURE_GEN_R);
5556 checkGLcall("glEnable(GL_TEXTURE_GEN_R);");
5557 glTexGeni(GL_R, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR);
5558 checkGLcall("glTexGeni(GL_R, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR)");
5562 case D3DTSS_TCI_CAMERASPACENORMAL:
5564 if (GL_SUPPORT(NV_TEXGEN_REFLECTION)) {
5565 float s_plane[] = { 1.0, 0.0, 0.0, 0.0 };
5566 float t_plane[] = { 0.0, 1.0, 0.0, 0.0 };
5567 float r_plane[] = { 0.0, 0.0, 1.0, 0.0 };
5568 float q_plane[] = { 0.0, 0.0, 0.0, 1.0 };
5569 TRACE("WINED3DTSS_TCI_CAMERASPACENORMAL - Set eye plane\n");
5571 glMatrixMode(GL_MODELVIEW);
5574 glTexGenfv(GL_S, GL_EYE_PLANE, s_plane);
5575 glTexGenfv(GL_T, GL_EYE_PLANE, t_plane);
5576 glTexGenfv(GL_R, GL_EYE_PLANE, r_plane);
5577 glTexGenfv(GL_Q, GL_EYE_PLANE, q_plane);
5580 glEnable(GL_TEXTURE_GEN_S);
5581 checkGLcall("glEnable(GL_TEXTURE_GEN_S);");
5582 glTexGeni(GL_S, GL_TEXTURE_GEN_MODE, GL_NORMAL_MAP_NV);
5583 checkGLcall("glTexGeni(GL_S, GL_TEXTURE_GEN_MODE, GL_NORMAL_MAP_NV)");
5584 glEnable(GL_TEXTURE_GEN_T);
5585 checkGLcall("glEnable(GL_TEXTURE_GEN_T);");
5586 glTexGeni(GL_T, GL_TEXTURE_GEN_MODE, GL_NORMAL_MAP_NV);
5587 checkGLcall("glTexGeni(GL_T, GL_TEXTURE_GEN_MODE, GL_NORMAL_MAP_NV)");
5588 glEnable(GL_TEXTURE_GEN_R);
5589 checkGLcall("glEnable(GL_TEXTURE_GEN_R);");
5590 glTexGeni(GL_R, GL_TEXTURE_GEN_MODE, GL_NORMAL_MAP_NV);
5591 checkGLcall("glTexGeni(GL_R, GL_TEXTURE_GEN_MODE, GL_NORMAL_MAP_NV)");
5596 case D3DTSS_TCI_CAMERASPACEREFLECTIONVECTOR:
5598 if (GL_SUPPORT(NV_TEXGEN_REFLECTION)) {
5599 float s_plane[] = { 1.0, 0.0, 0.0, 0.0 };
5600 float t_plane[] = { 0.0, 1.0, 0.0, 0.0 };
5601 float r_plane[] = { 0.0, 0.0, 1.0, 0.0 };
5602 float q_plane[] = { 0.0, 0.0, 0.0, 1.0 };
5603 TRACE("WINED3DTSS_TCI_CAMERASPACEREFLECTIONVECTOR - Set eye plane\n");
5605 glMatrixMode(GL_MODELVIEW);
5608 glTexGenfv(GL_S, GL_EYE_PLANE, s_plane);
5609 glTexGenfv(GL_T, GL_EYE_PLANE, t_plane);
5610 glTexGenfv(GL_R, GL_EYE_PLANE, r_plane);
5611 glTexGenfv(GL_Q, GL_EYE_PLANE, q_plane);
5614 glEnable(GL_TEXTURE_GEN_S);
5615 checkGLcall("glEnable(GL_TEXTURE_GEN_S);");
5616 glTexGeni(GL_S, GL_TEXTURE_GEN_MODE, GL_REFLECTION_MAP_NV);
5617 checkGLcall("glTexGeni(GL_S, GL_TEXTURE_GEN_MODE, GL_REFLECTION_MAP_NV)");
5618 glEnable(GL_TEXTURE_GEN_T);
5619 checkGLcall("glEnable(GL_TEXTURE_GEN_T);");
5620 glTexGeni(GL_T, GL_TEXTURE_GEN_MODE, GL_REFLECTION_MAP_NV);
5621 checkGLcall("glTexGeni(GL_T, GL_TEXTURE_GEN_MODE, GL_REFLECTION_MAP_NV)");
5622 glEnable(GL_TEXTURE_GEN_R);
5623 checkGLcall("glEnable(GL_TEXTURE_GEN_R);");
5624 glTexGeni(GL_R, GL_TEXTURE_GEN_MODE, GL_REFLECTION_MAP_NV);
5625 checkGLcall("glTexGeni(GL_R, GL_TEXTURE_GEN_MODE, GL_REFLECTION_MAP_NV)");
5630 /* Unhandled types: */
5633 /* ? disable GL_TEXTURE_GEN_n ? */
5634 glDisable(GL_TEXTURE_GEN_S);
5635 glDisable(GL_TEXTURE_GEN_T);
5636 glDisable(GL_TEXTURE_GEN_R);
5637 glDisable(GL_TEXTURE_GEN_Q);
5638 FIXME("Unhandled WINED3DTSS_TEXCOORDINDEX %lx\n", Value);
5645 case WINED3DTSS_TEXTURETRANSFORMFLAGS :
5646 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);
5649 case WINED3DTSS_BUMPENVMAT00 :
5650 case WINED3DTSS_BUMPENVMAT01 :
5651 TRACE("BUMPENVMAT0%u Stage=%ld, Type=%d, Value =%ld\n", Type - WINED3DTSS_BUMPENVMAT00, Stage, Type, Value);
5653 case WINED3DTSS_BUMPENVMAT10 :
5654 case WINED3DTSS_BUMPENVMAT11 :
5655 TRACE("BUMPENVMAT1%u Stage=%ld, Type=%d, Value =%ld\n", Type - WINED3DTSS_BUMPENVMAT10, Stage, Type, Value);
5658 case WINED3DTSS_BUMPENVLSCALE :
5659 TRACE("BUMPENVLSCALE Stage=%ld, Type=%d, Value =%ld\n", Stage, Type, Value);
5662 case WINED3DTSS_BUMPENVLOFFSET :
5663 TRACE("BUMPENVLOFFSET Stage=%ld, Type=%d, Value =%ld\n", Stage, Type, Value);
5666 case WINED3DTSS_RESULTARG :
5667 TRACE("RESULTARG Still a stub, Stage=%ld, Type=%d, Value =%ld\n", Stage, Type, Value);
5671 /* Put back later: FIXME("(%p) : stub, Stage=%ld, Type=%d, Value =%ld\n", This, Stage, Type, Value); */
5672 TRACE("Still a stub, Stage=%ld, Type=%d, Value =%ld\n", Stage, Type, Value);
5681 * Get / Set Texture Stage States
5682 * TODO: Verify against dx9 definitions
5684 static HRESULT WINAPI IWineD3DDeviceImpl_SetTextureStageState(IWineD3DDevice *iface, DWORD Stage, WINED3DTEXTURESTAGESTATETYPE Type, DWORD Value) {
5685 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5687 /* FIXME: Handle 3d textures? What if TSS value set before set texture? Need to reapply all values? */
5689 TRACE("(%p) : Stage=%ld, Type=%s(%d), Value=%ld\n", This, Stage, debug_d3dtexturestate(Type), Type, Value);
5691 /* Reject invalid texture units */
5692 if (Stage >= GL_LIMITS(texture_stages)) {
5693 TRACE("Attempt to access invalid texture rejected\n");
5694 return WINED3DERR_INVALIDCALL;
5697 This->updateStateBlock->changed.textureState[Stage][Type] = TRUE;
5698 This->updateStateBlock->set.textureState[Stage][Type] = TRUE;
5699 This->updateStateBlock->textureState[Stage][Type] = Value;
5704 static HRESULT WINAPI IWineD3DDeviceImpl_GetTextureStageState(IWineD3DDevice *iface, DWORD Stage, WINED3DTEXTURESTAGESTATETYPE Type, DWORD* pValue) {
5705 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5706 TRACE("(%p) : requesting Stage %ld, Type %d getting %ld\n", This, Stage, Type, This->updateStateBlock->textureState[Stage][Type]);
5707 *pValue = This->updateStateBlock->textureState[Stage][Type];
5714 static HRESULT WINAPI IWineD3DDeviceImpl_SetTexture(IWineD3DDevice *iface, DWORD Stage, IWineD3DBaseTexture* pTexture) {
5716 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5717 IWineD3DBaseTexture *oldTexture;
5719 oldTexture = This->updateStateBlock->textures[Stage];
5720 TRACE("(%p) : Stage(%ld), Texture (%p)\n", This, Stage, pTexture);
5722 #if 0 /* TODO: check so vertex textures */
5723 if (Stage >= D3DVERTEXTEXTURESAMPLER && Stage <= D3DVERTEXTEXTURESAMPLER3){
5724 This->updateStateBlock->vertexTextures[Stage - D3DVERTEXTEXTURESAMPLER] = pTexture;
5729 /* Reject invalid texture units */
5730 if (Stage >= GL_LIMITS(sampler_stages) || Stage < 0) {
5731 WARN("Attempt to access invalid texture rejected\n");
5732 return WINED3DERR_INVALIDCALL;
5735 if(pTexture != NULL) {
5736 /* SetTexture isn't allowed on textures in WINED3DPOOL_SCRATCH;
5738 if(((IWineD3DTextureImpl*)pTexture)->resource.pool == WINED3DPOOL_SCRATCH) {
5739 WARN("(%p) Attempt to set scratch texture rejected\n", pTexture);
5740 return WINED3DERR_INVALIDCALL;
5744 oldTexture = This->updateStateBlock->textures[Stage];
5745 TRACE("GL_LIMITS %d\n",GL_LIMITS(sampler_stages));
5746 TRACE("(%p) : oldtexture(%p)\n", This,oldTexture);
5748 This->updateStateBlock->set.textures[Stage] = TRUE;
5749 This->updateStateBlock->changed.textures[Stage] = TRUE;
5750 TRACE("(%p) : setting new texture to %p\n", This, pTexture);
5751 This->updateStateBlock->textures[Stage] = pTexture;
5753 /* Handle recording of state blocks */
5754 if (This->isRecordingState) {
5755 TRACE("Recording... not performing anything\n");
5759 /** NOTE: MSDN says that setTexture increases the reference count,
5760 * and the the application nust set the texture back to null (or have a leaky application),
5761 * This means we should pass the refcount up to the parent
5762 *******************************/
5763 if (NULL != This->updateStateBlock->textures[Stage]) {
5764 IWineD3DBaseTexture_AddRef(This->updateStateBlock->textures[Stage]);
5767 if (NULL != oldTexture) {
5768 IWineD3DBaseTexture_Release(oldTexture);
5771 /* Reset color keying */
5772 if(Stage == 0 && This->stateBlock->renderState[WINED3DRS_COLORKEYENABLE]) {
5773 BOOL enable_ckey = FALSE;
5776 IWineD3DSurfaceImpl *surf = (IWineD3DSurfaceImpl *) ((IWineD3DTextureImpl *)pTexture)->surfaces[0];
5777 if(surf->CKeyFlags & DDSD_CKSRCBLT) enable_ckey = TRUE;
5781 glAlphaFunc(GL_NOTEQUAL, 0.0);
5782 checkGLcall("glAlphaFunc");
5789 static HRESULT WINAPI IWineD3DDeviceImpl_GetTexture(IWineD3DDevice *iface, DWORD Stage, IWineD3DBaseTexture** ppTexture) {
5790 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5791 TRACE("(%p) : (%ld /* Stage */,%p /* ppTexture */)\n", This, Stage, ppTexture);
5793 /* Reject invalid texture units */
5794 if (Stage >= GL_LIMITS(sampler_stages)) {
5795 TRACE("Attempt to access invalid texture rejected\n");
5796 return WINED3DERR_INVALIDCALL;
5798 *ppTexture=This->updateStateBlock->textures[Stage];
5800 IWineD3DBaseTexture_AddRef(*ppTexture);
5802 return WINED3DERR_INVALIDCALL;
5809 static HRESULT WINAPI IWineD3DDeviceImpl_GetBackBuffer(IWineD3DDevice *iface, UINT iSwapChain, UINT BackBuffer, WINED3DBACKBUFFER_TYPE Type,
5810 IWineD3DSurface **ppBackBuffer) {
5811 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5812 IWineD3DSwapChain *swapChain;
5815 TRACE("(%p) : BackBuf %d Type %d SwapChain %d returning %p\n", This, BackBuffer, Type, iSwapChain, *ppBackBuffer);
5817 hr = IWineD3DDeviceImpl_GetSwapChain(iface, iSwapChain, &swapChain);
5818 if (hr == WINED3D_OK) {
5819 hr = IWineD3DSwapChain_GetBackBuffer(swapChain, BackBuffer, Type, ppBackBuffer);
5820 IWineD3DSwapChain_Release(swapChain);
5822 *ppBackBuffer = NULL;
5827 static HRESULT WINAPI IWineD3DDeviceImpl_GetDeviceCaps(IWineD3DDevice *iface, WINED3DCAPS* pCaps) {
5828 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5829 WARN("(%p) : stub, calling idirect3d for now\n", This);
5830 return IWineD3D_GetDeviceCaps(This->wineD3D, This->adapterNo, This->devType, pCaps);
5833 static HRESULT WINAPI IWineD3DDeviceImpl_GetDisplayMode(IWineD3DDevice *iface, UINT iSwapChain, WINED3DDISPLAYMODE* pMode) {
5834 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5835 IWineD3DSwapChain *swapChain;
5838 if(iSwapChain > 0) {
5839 hr = IWineD3DDeviceImpl_GetSwapChain(iface, iSwapChain, (IWineD3DSwapChain **)&swapChain);
5840 if (hr == WINED3D_OK) {
5841 hr = IWineD3DSwapChain_GetDisplayMode(swapChain, pMode);
5842 IWineD3DSwapChain_Release(swapChain);
5844 FIXME("(%p) Error getting display mode\n", This);
5847 /* Don't read the real display mode,
5848 but return the stored mode instead. X11 can't change the color
5849 depth, and some apps are pretty angry if they SetDisplayMode from
5850 24 to 16 bpp and find out that GetDisplayMode still returns 24 bpp
5852 Also don't relay to the swapchain because with ddraw it's possible
5853 that there isn't a swapchain at all */
5854 pMode->Width = This->ddraw_width;
5855 pMode->Height = This->ddraw_height;
5856 pMode->Format = This->ddraw_format;
5857 pMode->RefreshRate = 0;
5864 static HRESULT WINAPI IWineD3DDeviceImpl_SetHWND(IWineD3DDevice *iface, HWND hWnd) {
5865 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5866 TRACE("(%p)->(%p)\n", This, hWnd);
5868 This->ddraw_window = hWnd;
5872 static HRESULT WINAPI IWineD3DDeviceImpl_GetHWND(IWineD3DDevice *iface, HWND *hWnd) {
5873 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5874 TRACE("(%p)->(%p)\n", This, hWnd);
5876 *hWnd = This->ddraw_window;
5881 * Stateblock related functions
5884 static HRESULT WINAPI IWineD3DDeviceImpl_BeginStateBlock(IWineD3DDevice *iface) {
5885 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5886 IWineD3DStateBlockImpl *object;
5887 HRESULT temp_result;
5889 TRACE("(%p)", This);
5891 if (This->isRecordingState) {
5892 return WINED3DERR_INVALIDCALL;
5895 object = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(IWineD3DStateBlockImpl));
5896 if (NULL == object ) {
5897 FIXME("(%p)Error allocating memory for stateblock\n", This);
5898 return E_OUTOFMEMORY;
5900 TRACE("(%p) created object %p\n", This, object);
5901 object->wineD3DDevice= This;
5902 /** FIXME: object->parent = parent; **/
5903 object->parent = NULL;
5904 object->blockType = WINED3DSBT_ALL;
5906 object->lpVtbl = &IWineD3DStateBlock_Vtbl;
5908 temp_result = allocate_shader_constants(object);
5909 if (WINED3D_OK != temp_result)
5912 IWineD3DStateBlock_Release((IWineD3DStateBlock*)This->updateStateBlock);
5913 This->updateStateBlock = object;
5914 This->isRecordingState = TRUE;
5916 TRACE("(%p) recording stateblock %p\n",This , object);
5920 static HRESULT WINAPI IWineD3DDeviceImpl_EndStateBlock(IWineD3DDevice *iface, IWineD3DStateBlock** ppStateBlock) {
5921 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5923 if (!This->isRecordingState) {
5924 FIXME("(%p) not recording! returning error\n", This);
5925 *ppStateBlock = NULL;
5926 return WINED3DERR_INVALIDCALL;
5929 *ppStateBlock = (IWineD3DStateBlock*)This->updateStateBlock;
5930 This->isRecordingState = FALSE;
5931 This->updateStateBlock = This->stateBlock;
5932 IWineD3DStateBlock_AddRef((IWineD3DStateBlock*)This->updateStateBlock);
5933 /* IWineD3DStateBlock_AddRef(*ppStateBlock); don't need to do this, since we should really just release UpdateStateBlock first */
5934 TRACE("(%p) returning token (ptr to stateblock) of %p\n", This, *ppStateBlock);
5939 * Scene related functions
5941 static HRESULT WINAPI IWineD3DDeviceImpl_BeginScene(IWineD3DDevice *iface) {
5942 /* At the moment we have no need for any functionality at the beginning
5944 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5945 TRACE("(%p) : stub\n", This);
5949 static HRESULT WINAPI IWineD3DDeviceImpl_EndScene(IWineD3DDevice *iface) {
5950 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5951 TRACE("(%p)\n", This);
5953 /* We only have to do this if we need to read the, swapbuffers performs a flush for us */
5955 checkGLcall("glFlush");
5957 TRACE("End Scene\n");
5958 if(This->renderTarget != NULL) {
5960 /* If the container of the rendertarget is a texture then we need to save the data from the pbuffer */
5961 IUnknown *targetContainer = NULL;
5962 if (WINED3D_OK == IWineD3DSurface_GetContainer(This->renderTarget, &IID_IWineD3DBaseTexture, (void **)&targetContainer)
5963 || WINED3D_OK == IWineD3DSurface_GetContainer(This->renderTarget, &IID_IWineD3DDevice, (void **)&targetContainer)) {
5964 TRACE("(%p) : Texture rendertarget %p\n", This ,This->renderTarget);
5965 /** always dirtify for now. we must find a better way to see that surface have been modified
5966 (Modifications should will only occur via draw-primitive, but we do need better locking
5967 switching to render-to-texture should remove the overhead though.
5969 IWineD3DSurface_SetPBufferState(This->renderTarget, TRUE /* inPBuffer */, FALSE /* inTexture */);
5970 IWineD3DSurface_AddDirtyRect(This->renderTarget, NULL);
5971 IWineD3DSurface_PreLoad(This->renderTarget);
5972 IWineD3DSurface_SetPBufferState(This->renderTarget, FALSE /* inPBuffer */, FALSE /* inTexture */);
5973 IUnknown_Release(targetContainer);
5976 This->sceneEnded = TRUE;
5981 static HRESULT WINAPI IWineD3DDeviceImpl_Present(IWineD3DDevice *iface,
5982 CONST RECT* pSourceRect, CONST RECT* pDestRect,
5983 HWND hDestWindowOverride, CONST RGNDATA* pDirtyRegion) {
5984 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5985 IWineD3DSwapChain *swapChain = NULL;
5987 int swapchains = IWineD3DDeviceImpl_GetNumberOfSwapChains(iface);
5989 TRACE("(%p) Presenting the frame\n", This);
5991 for(i = 0 ; i < swapchains ; i ++) {
5993 IWineD3DDeviceImpl_GetSwapChain(iface, i , (IWineD3DSwapChain **)&swapChain);
5994 TRACE("presentinng chain %d, %p\n", i, swapChain);
5995 IWineD3DSwapChain_Present(swapChain, pSourceRect, pDestRect, hDestWindowOverride, pDirtyRegion, 0);
5996 IWineD3DSwapChain_Release(swapChain);
6002 static HRESULT WINAPI IWineD3DDeviceImpl_Clear(IWineD3DDevice *iface, DWORD Count, CONST D3DRECT* pRects,
6003 DWORD Flags, D3DCOLOR Color, float Z, DWORD Stencil) {
6004 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
6006 /* TODO: From MSDN This method fails if you specify the D3DCLEAR_ZBUFFER or D3DCLEAR_STENCIL flags when the
6007 render target does not have an attached depth buffer. Similarly, if you specify the D3DCLEAR_STENCIL flag
6008 when the depth-buffer format does not contain stencil buffer information, this method fails. */
6009 GLbitfield glMask = 0;
6010 GLboolean old_ztest;
6011 GLfloat old_z_clear_value;
6012 GLint old_stencil_clear_value;
6013 GLfloat old_color_clear_value[4];
6015 CONST D3DRECT* curRect;
6017 TRACE("(%p) Count (%ld), pRects (%p), Flags (%lx), Z (%f), Stencil (%ld)\n", This,
6018 Count, pRects, Flags, Z, Stencil);
6022 glEnable(GL_SCISSOR_TEST);
6023 checkGLcall("glEnable GL_SCISSOR_TEST");
6025 if (Count > 0 && pRects) {
6031 /* Only set the values up once, as they are not changing */
6032 if (Flags & D3DCLEAR_STENCIL) {
6033 glGetIntegerv(GL_STENCIL_CLEAR_VALUE, &old_stencil_clear_value);
6034 glClearStencil(Stencil);
6035 checkGLcall("glClearStencil");
6036 glMask = glMask | GL_STENCIL_BUFFER_BIT;
6037 glStencilMask(0xFFFFFFFF);
6040 if (Flags & D3DCLEAR_ZBUFFER) {
6041 glGetBooleanv(GL_DEPTH_WRITEMASK, &old_ztest);
6042 glDepthMask(GL_TRUE);
6043 glGetFloatv(GL_DEPTH_CLEAR_VALUE, &old_z_clear_value);
6045 checkGLcall("glClearDepth");
6046 glMask = glMask | GL_DEPTH_BUFFER_BIT;
6049 if (Flags & D3DCLEAR_TARGET) {
6050 TRACE("Clearing screen with glClear to color %lx\n", Color);
6051 glGetFloatv(GL_COLOR_CLEAR_VALUE, old_color_clear_value);
6052 glClearColor(D3DCOLOR_R(Color),
6056 checkGLcall("glClearColor");
6058 /* Clear ALL colors! */
6059 glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
6060 glMask = glMask | GL_COLOR_BUFFER_BIT;
6063 /* Now process each rect in turn */
6064 for (i = 0; i < Count || i == 0; i++) {
6067 /* Note gl uses lower left, width/height */
6068 TRACE("(%p) %p Rect=(%ld,%ld)->(%ld,%ld) glRect=(%ld,%ld), len=%ld, hei=%ld\n", This, curRect,
6069 curRect->x1, curRect->y1, curRect->x2, curRect->y2,
6070 curRect->x1, (((IWineD3DSurfaceImpl *)This->renderTarget)->currentDesc.Height - curRect->y2),
6071 curRect->x2 - curRect->x1, curRect->y2 - curRect->y1);
6072 glScissor(curRect->x1, (((IWineD3DSurfaceImpl *)This->renderTarget)->currentDesc.Height - curRect->y2),
6073 curRect->x2 - curRect->x1, curRect->y2 - curRect->y1);
6074 checkGLcall("glScissor");
6076 glScissor(This->stateBlock->viewport.X,
6077 (((IWineD3DSurfaceImpl *)This->renderTarget)->currentDesc.Height -
6078 (This->stateBlock->viewport.Y + This->stateBlock->viewport.Height)),
6079 This->stateBlock->viewport.Width,
6080 This->stateBlock->viewport.Height);
6081 checkGLcall("glScissor");
6084 /* Clear the selected rectangle (or full screen) */
6086 checkGLcall("glClear");
6088 /* Step to the next rectangle */
6089 if (curRect) curRect = curRect + sizeof(D3DRECT);
6092 /* Restore the old values (why..?) */
6093 if (Flags & D3DCLEAR_STENCIL) {
6094 glClearStencil(old_stencil_clear_value);
6095 glStencilMask(This->stateBlock->renderState[WINED3DRS_STENCILWRITEMASK]);
6097 if (Flags & D3DCLEAR_ZBUFFER) {
6098 glDepthMask(old_ztest);
6099 glClearDepth(old_z_clear_value);
6101 if (Flags & D3DCLEAR_TARGET) {
6102 glClearColor(old_color_clear_value[0],
6103 old_color_clear_value[1],
6104 old_color_clear_value[2],
6105 old_color_clear_value[3]);
6106 glColorMask(This->stateBlock->renderState[WINED3DRS_COLORWRITEENABLE] & D3DCOLORWRITEENABLE_RED ? GL_TRUE : GL_FALSE,
6107 This->stateBlock->renderState[WINED3DRS_COLORWRITEENABLE] & D3DCOLORWRITEENABLE_GREEN ? GL_TRUE : GL_FALSE,
6108 This->stateBlock->renderState[WINED3DRS_COLORWRITEENABLE] & D3DCOLORWRITEENABLE_BLUE ? GL_TRUE : GL_FALSE,
6109 This->stateBlock->renderState[WINED3DRS_COLORWRITEENABLE] & D3DCOLORWRITEENABLE_ALPHA ? GL_TRUE : GL_FALSE);
6112 glDisable(GL_SCISSOR_TEST);
6113 checkGLcall("glDisable");
6122 static HRESULT WINAPI IWineD3DDeviceImpl_DrawPrimitive(IWineD3DDevice *iface, D3DPRIMITIVETYPE PrimitiveType, UINT StartVertex,
6123 UINT PrimitiveCount) {
6125 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
6126 This->stateBlock->streamIsUP = FALSE;
6128 TRACE("(%p) : Type=(%d,%s), Start=%d, Count=%d\n", This, PrimitiveType,
6129 debug_d3dprimitivetype(PrimitiveType),
6130 StartVertex, PrimitiveCount);
6131 drawPrimitive(iface, PrimitiveType, PrimitiveCount, StartVertex, 0/* NumVertices */, -1 /* indxStart */,
6132 0 /* indxSize */, NULL /* indxData */, 0 /* minIndex */, NULL);
6138 /* TODO: baseVIndex needs to be provided from This->stateBlock->baseVertexIndex when called from d3d8 */
6139 static HRESULT WINAPI IWineD3DDeviceImpl_DrawIndexedPrimitive(IWineD3DDevice *iface,
6140 D3DPRIMITIVETYPE PrimitiveType,
6141 INT baseVIndex, UINT minIndex,
6142 UINT NumVertices, UINT startIndex, UINT primCount) {
6144 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
6146 IWineD3DIndexBuffer *pIB;
6147 WINED3DINDEXBUFFER_DESC IdxBufDsc;
6149 pIB = This->stateBlock->pIndexData;
6150 This->stateBlock->streamIsUP = FALSE;
6152 TRACE("(%p) : Type=(%d,%s), min=%d, CountV=%d, startIdx=%d, baseVidx=%d, countP=%d\n", This,
6153 PrimitiveType, debug_d3dprimitivetype(PrimitiveType),
6154 minIndex, NumVertices, startIndex, baseVIndex, primCount);
6156 IWineD3DIndexBuffer_GetDesc(pIB, &IdxBufDsc);
6157 if (IdxBufDsc.Format == WINED3DFMT_INDEX16) {
6163 drawPrimitive(iface, PrimitiveType, primCount, baseVIndex, NumVertices, startIndex,
6164 idxStride, ((IWineD3DIndexBufferImpl *) pIB)->resource.allocatedMemory, minIndex, NULL);
6169 static HRESULT WINAPI IWineD3DDeviceImpl_DrawPrimitiveUP(IWineD3DDevice *iface, D3DPRIMITIVETYPE PrimitiveType,
6170 UINT PrimitiveCount, CONST void* pVertexStreamZeroData,
6171 UINT VertexStreamZeroStride) {
6172 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
6174 TRACE("(%p) : Type=(%d,%s), pCount=%d, pVtxData=%p, Stride=%d\n", This, PrimitiveType,
6175 debug_d3dprimitivetype(PrimitiveType),
6176 PrimitiveCount, pVertexStreamZeroData, VertexStreamZeroStride);
6178 /* release the stream source */
6179 if (This->stateBlock->streamSource[0] != NULL) {
6180 IWineD3DVertexBuffer_Release(This->stateBlock->streamSource[0]);
6183 /* Note in the following, it's not this type, but that's the purpose of streamIsUP */
6184 This->stateBlock->streamSource[0] = (IWineD3DVertexBuffer *)pVertexStreamZeroData;
6185 This->stateBlock->streamStride[0] = VertexStreamZeroStride;
6186 This->stateBlock->streamIsUP = TRUE;
6188 drawPrimitive(iface, PrimitiveType, PrimitiveCount, 0 /* start vertex */, 0 /* NumVertices */,
6189 0 /* indxStart*/, 0 /* indxSize*/, NULL /* indxData */, 0 /* indxMin */, NULL);
6191 /* MSDN specifies stream zero settings must be set to NULL */
6192 This->stateBlock->streamStride[0] = 0;
6193 This->stateBlock->streamSource[0] = NULL;
6195 /*stream zero settings set to null at end, as per the msdn */
6199 static HRESULT WINAPI IWineD3DDeviceImpl_DrawIndexedPrimitiveUP(IWineD3DDevice *iface, D3DPRIMITIVETYPE PrimitiveType,
6200 UINT MinVertexIndex, UINT NumVertices,
6201 UINT PrimitiveCount, CONST void* pIndexData,
6202 WINED3DFORMAT IndexDataFormat,CONST void* pVertexStreamZeroData,
6203 UINT VertexStreamZeroStride) {
6205 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
6207 TRACE("(%p) : Type=(%d,%s), MinVtxIdx=%d, NumVIdx=%d, PCount=%d, pidxdata=%p, IdxFmt=%d, pVtxdata=%p, stride=%d\n",
6208 This, PrimitiveType, debug_d3dprimitivetype(PrimitiveType),
6209 MinVertexIndex, NumVertices, PrimitiveCount, pIndexData,
6210 IndexDataFormat, pVertexStreamZeroData, VertexStreamZeroStride);
6212 if (IndexDataFormat == WINED3DFMT_INDEX16) {
6218 /* release the stream and index data */
6219 if (This->stateBlock->streamSource[0] != NULL) {
6220 IWineD3DVertexBuffer_Release(This->stateBlock->streamSource[0]);
6222 if (This->stateBlock->pIndexData) {
6223 IWineD3DIndexBuffer_Release(This->stateBlock->pIndexData);
6226 /* Note in the following, it's not this type, but that's the purpose of streamIsUP */
6227 This->stateBlock->streamSource[0] = (IWineD3DVertexBuffer *)pVertexStreamZeroData;
6228 This->stateBlock->streamIsUP = TRUE;
6229 This->stateBlock->streamStride[0] = VertexStreamZeroStride;
6231 drawPrimitive(iface, PrimitiveType, PrimitiveCount, 0 /* vertexStart */, NumVertices, 0 /* indxStart */, idxStride, pIndexData, MinVertexIndex, NULL);
6233 /* MSDN specifies stream zero settings and index buffer must be set to NULL */
6234 This->stateBlock->streamSource[0] = NULL;
6235 This->stateBlock->streamStride[0] = 0;
6236 This->stateBlock->pIndexData = NULL;
6241 static HRESULT WINAPI IWineD3DDeviceImpl_DrawPrimitiveStrided (IWineD3DDevice *iface, D3DPRIMITIVETYPE PrimitiveType, UINT PrimitiveCount, WineDirect3DVertexStridedData *DrawPrimStrideData) {
6243 drawPrimitive(iface, PrimitiveType, PrimitiveCount, 0, 0, 0, 0, NULL, 0, DrawPrimStrideData);
6246 /* Yet another way to update a texture, some apps use this to load default textures instead of using surface/texture lock/unlock */
6247 static HRESULT WINAPI IWineD3DDeviceImpl_UpdateTexture (IWineD3DDevice *iface, IWineD3DBaseTexture *pSourceTexture, IWineD3DBaseTexture *pDestinationTexture){
6248 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
6249 HRESULT hr = WINED3D_OK;
6250 WINED3DRESOURCETYPE sourceType;
6251 WINED3DRESOURCETYPE destinationType;
6254 /* TODO: think about moving the code into IWineD3DBaseTexture */
6256 TRACE("(%p) Source %p Destination %p\n", This, pSourceTexture, pDestinationTexture);
6258 /* verify that the source and destination textures aren't NULL */
6259 if (NULL == pSourceTexture || NULL == pDestinationTexture) {
6260 WARN("(%p) : source (%p) and destination (%p) textures must not be NULL, returning WINED3DERR_INVALIDCALL\n",
6261 This, pSourceTexture, pDestinationTexture);
6262 hr = WINED3DERR_INVALIDCALL;
6265 if (pSourceTexture == pDestinationTexture) {
6266 WARN("(%p) : source (%p) and destination (%p) textures must be different, returning WINED3DERR_INVALIDCALL\n",
6267 This, pSourceTexture, pDestinationTexture);
6268 hr = WINED3DERR_INVALIDCALL;
6270 /* Verify that the source and destination textures are the same type */
6271 sourceType = IWineD3DBaseTexture_GetType(pSourceTexture);
6272 destinationType = IWineD3DBaseTexture_GetType(pDestinationTexture);
6274 if (sourceType != destinationType) {
6275 WARN("(%p) Sorce and destination types must match, returning WINED3DERR_INVALIDCALL\n",
6277 hr = WINED3DERR_INVALIDCALL;
6280 /* check that both textures have the identical numbers of levels */
6281 if (IWineD3DBaseTexture_GetLevelCount(pDestinationTexture) != IWineD3DBaseTexture_GetLevelCount(pSourceTexture)) {
6282 WARN("(%p) : source (%p) and destination (%p) textures must have identicle numbers of levels, returning WINED3DERR_INVALIDCALL\n", This, pSourceTexture, pDestinationTexture);
6283 hr = WINED3DERR_INVALIDCALL;
6286 if (WINED3D_OK == hr) {
6288 /* Make sure that the destination texture is loaded */
6289 IWineD3DBaseTexture_PreLoad(pDestinationTexture);
6291 /* Update every surface level of the texture */
6292 levels = IWineD3DBaseTexture_GetLevelCount(pDestinationTexture);
6294 switch (sourceType) {
6295 case WINED3DRTYPE_TEXTURE:
6297 IWineD3DSurface *srcSurface;
6298 IWineD3DSurface *destSurface;
6300 for (i = 0 ; i < levels ; ++i) {
6301 IWineD3DTexture_GetSurfaceLevel((IWineD3DTexture *)pSourceTexture, i, &srcSurface);
6302 IWineD3DTexture_GetSurfaceLevel((IWineD3DTexture *)pDestinationTexture, i, &destSurface);
6303 hr = IWineD3DDevice_UpdateSurface(iface, srcSurface, NULL, destSurface, NULL);
6304 IWineD3DSurface_Release(srcSurface);
6305 IWineD3DSurface_Release(destSurface);
6306 if (WINED3D_OK != hr) {
6307 WARN("(%p) : Call to update surface failed\n", This);
6313 case WINED3DRTYPE_CUBETEXTURE:
6315 IWineD3DSurface *srcSurface;
6316 IWineD3DSurface *destSurface;
6317 WINED3DCUBEMAP_FACES faceType;
6319 for (i = 0 ; i < levels ; ++i) {
6320 /* Update each cube face */
6321 for (faceType = D3DCUBEMAP_FACE_POSITIVE_X; faceType <= D3DCUBEMAP_FACE_NEGATIVE_Z; ++faceType){
6322 hr = IWineD3DCubeTexture_GetCubeMapSurface((IWineD3DCubeTexture *)pSourceTexture, faceType, i, &srcSurface);
6323 if (WINED3D_OK != hr) {
6324 FIXME("(%p) : Failed to get src cube surface facetype %d, level %d\n", This, faceType, i);
6326 TRACE("Got srcSurface %p\n", srcSurface);
6328 hr = IWineD3DCubeTexture_GetCubeMapSurface((IWineD3DCubeTexture *)pDestinationTexture, faceType, i, &destSurface);
6329 if (WINED3D_OK != hr) {
6330 FIXME("(%p) : Failed to get src cube surface facetype %d, level %d\n", This, faceType, i);
6332 TRACE("Got desrSurface %p\n", destSurface);
6334 hr = IWineD3DDevice_UpdateSurface(iface, srcSurface, NULL, destSurface, NULL);
6335 IWineD3DSurface_Release(srcSurface);
6336 IWineD3DSurface_Release(destSurface);
6337 if (WINED3D_OK != hr) {
6338 WARN("(%p) : Call to update surface failed\n", This);
6345 #if 0 /* TODO: Add support for volume textures */
6346 case WINED3DRTYPE_VOLUMETEXTURE:
6348 IWineD3DVolume srcVolume = NULL;
6349 IWineD3DSurface destVolume = NULL;
6351 for (i = 0 ; i < levels ; ++i) {
6352 IWineD3DVolumeTexture_GetVolume((IWineD3DVolumeTexture *)pSourceTexture, i, &srcVolume);
6353 IWineD3DVolumeTexture_GetVolume((IWineD3DVolumeTexture *)pDestinationTexture, i, &destVolume);
6354 hr = IWineD3DFoo_UpdateVolume(iface, srcVolume, NULL, destVolume, NULL);
6355 IWineD3DVolume_Release(srcSurface);
6356 IWineD3DVolume_Release(destSurface);
6357 if (WINED3D_OK != hr) {
6358 WARN("(%p) : Call to update volume failed\n", This);
6366 FIXME("(%p) : Unsupported source and destination type\n", This);
6367 hr = WINED3DERR_INVALIDCALL;
6374 static HRESULT WINAPI IWineD3DDeviceImpl_StretchRect(IWineD3DDevice *iface, IWineD3DSurface *pSourceSurface,
6375 CONST RECT* pSourceRect, IWineD3DSurface *pDestinationSurface,
6376 CONST RECT* pDestRect, WINED3DTEXTUREFILTERTYPE Filter) {
6377 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
6379 TRACE("(%p) : stub\n", This);
6382 static HRESULT WINAPI IWineD3DDeviceImpl_GetRenderTargetData(IWineD3DDevice *iface, IWineD3DSurface *pRenderTarget, IWineD3DSurface *pSurface) {
6383 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
6384 /** TODO: remove remove casts to IWineD3DSurfaceImpl *
6385 * NOTE It may be best to move the code into surface to occomplish this
6386 ****************************************/
6388 WINED3DSURFACE_DESC surfaceDesc;
6389 unsigned int surfaceWidth, surfaceHeight;
6390 glDescriptor *targetGlDescription = NULL;
6391 glDescriptor *surfaceGlDescription = NULL;
6392 IWineD3DSwapChainImpl *container = NULL;
6394 IWineD3DSurface_GetGlDesc(pRenderTarget, &targetGlDescription);
6395 IWineD3DSurface_GetGlDesc(pSurface, &surfaceGlDescription);
6396 memset(&surfaceDesc, 0, sizeof(surfaceDesc));
6398 surfaceDesc.Width = &surfaceWidth;
6399 surfaceDesc.Height = &surfaceHeight;
6400 IWineD3DSurface_GetDesc(pSurface, &surfaceDesc);
6401 /* check to see if it's the backbuffer or the frontbuffer being requested (to make sure the data is up to date)*/
6403 /* Ok, I may need to setup some kind of active swapchain reference on the device */
6404 IWineD3DSurface_GetContainer(pRenderTarget, &IID_IWineD3DSwapChain, (void **)&container);
6406 /* TODO: opengl Context switching for swapchains etc... */
6407 if (NULL != container || pRenderTarget == This->renderTarget || pRenderTarget == This->depthStencilBuffer) {
6408 if (NULL != container && (pRenderTarget == container->backBuffer[0])) {
6409 glReadBuffer(GL_BACK);
6410 vcheckGLcall("glReadBuffer(GL_BACK)");
6411 } else if ((NULL != container && (pRenderTarget == container->frontBuffer)) || (pRenderTarget == This->renderTarget)) {
6412 glReadBuffer(GL_FRONT);
6413 vcheckGLcall("glReadBuffer(GL_FRONT)");
6414 } else if (pRenderTarget == This->depthStencilBuffer) {
6415 FIXME("Reading of depthstencil not yet supported\n");
6418 glReadPixels(surfaceGlDescription->target,
6419 surfaceGlDescription->level,
6422 surfaceGlDescription->glFormat,
6423 surfaceGlDescription->glType,
6424 (void *)IWineD3DSurface_GetData(pSurface));
6425 vcheckGLcall("glReadPixels(...)");
6426 if(NULL != container ){
6427 IWineD3DSwapChain_Release((IWineD3DSwapChain*) container);
6430 IWineD3DBaseTexture *container;
6431 GLenum textureDimensions = GL_TEXTURE_2D;
6433 if (WINED3D_OK == IWineD3DSurface_GetContainer(pSurface, &IID_IWineD3DBaseTexture, (void **)&container)) {
6434 textureDimensions = IWineD3DBaseTexture_GetTextureDimensions(container);
6435 IWineD3DBaseTexture_Release(container);
6437 /* TODO: 2D -> Cube surface coppies etc.. */
6438 if (surfaceGlDescription->target != textureDimensions) {
6439 FIXME("(%p) : Texture dimension mismatch\n", This);
6441 glEnable(textureDimensions);
6442 vcheckGLcall("glEnable(GL_TEXTURE_...)");
6443 /* FIXME: this isn't correct, it need to add a dirty rect if nothing else... */
6444 glBindTexture(targetGlDescription->target, targetGlDescription->textureName);
6445 vcheckGLcall("glBindTexture");
6446 glGetTexImage(surfaceGlDescription->target,
6447 surfaceGlDescription->level,
6448 surfaceGlDescription->glFormat,
6449 surfaceGlDescription->glType,
6450 (void *)IWineD3DSurface_GetData(pSurface));
6451 glDisable(textureDimensions);
6452 vcheckGLcall("glDisable(GL_TEXTURE_...)");
6459 static HRESULT WINAPI IWineD3DDeviceImpl_GetFrontBufferData(IWineD3DDevice *iface,UINT iSwapChain, IWineD3DSurface *pDestSurface) {
6460 IWineD3DSwapChain *swapChain;
6462 hr = IWineD3DDeviceImpl_GetSwapChain(iface, iSwapChain, (IWineD3DSwapChain **)&swapChain);
6463 if(hr == WINED3D_OK) {
6464 hr = IWineD3DSwapChain_GetFrontBufferData(swapChain, pDestSurface);
6465 IWineD3DSwapChain_Release(swapChain);
6470 static HRESULT WINAPI IWineD3DDeviceImpl_ValidateDevice(IWineD3DDevice *iface, DWORD* pNumPasses) {
6471 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
6472 /* return a sensible default */
6474 /* TODO: If the window is minimized then validate device should return something other than WINED3D_OK */
6475 FIXME("(%p) : stub\n", This);
6479 static HRESULT WINAPI IWineD3DDeviceImpl_SetPaletteEntries(IWineD3DDevice *iface, UINT PaletteNumber, CONST PALETTEENTRY* pEntries) {
6480 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
6482 TRACE("(%p) : PaletteNumber %u\n", This, PaletteNumber);
6483 if ( PaletteNumber < 0 || PaletteNumber >= MAX_PALETTES) {
6484 WARN("(%p) : (%u) Out of range 0-%u, returning Invalid Call\n", This, PaletteNumber, MAX_PALETTES);
6485 return WINED3DERR_INVALIDCALL;
6487 for (j = 0; j < 256; ++j) {
6488 This->palettes[PaletteNumber][j].peRed = pEntries[j].peRed;
6489 This->palettes[PaletteNumber][j].peGreen = pEntries[j].peGreen;
6490 This->palettes[PaletteNumber][j].peBlue = pEntries[j].peBlue;
6491 This->palettes[PaletteNumber][j].peFlags = pEntries[j].peFlags;
6493 TRACE("(%p) : returning\n", This);
6497 static HRESULT WINAPI IWineD3DDeviceImpl_GetPaletteEntries(IWineD3DDevice *iface, UINT PaletteNumber, PALETTEENTRY* pEntries) {
6498 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
6500 TRACE("(%p) : PaletteNumber %u\n", This, PaletteNumber);
6501 if ( PaletteNumber < 0 || PaletteNumber >= MAX_PALETTES) {
6502 WARN("(%p) : (%u) Out of range 0-%u, returning Invalid Call\n", This, PaletteNumber, MAX_PALETTES);
6503 return WINED3DERR_INVALIDCALL;
6505 for (j = 0; j < 256; ++j) {
6506 pEntries[j].peRed = This->palettes[PaletteNumber][j].peRed;
6507 pEntries[j].peGreen = This->palettes[PaletteNumber][j].peGreen;
6508 pEntries[j].peBlue = This->palettes[PaletteNumber][j].peBlue;
6509 pEntries[j].peFlags = This->palettes[PaletteNumber][j].peFlags;
6511 TRACE("(%p) : returning\n", This);
6515 static HRESULT WINAPI IWineD3DDeviceImpl_SetCurrentTexturePalette(IWineD3DDevice *iface, UINT PaletteNumber) {
6516 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
6517 TRACE("(%p) : PaletteNumber %u\n", This, PaletteNumber);
6518 if ( PaletteNumber < 0 || PaletteNumber >= MAX_PALETTES) {
6519 WARN("(%p) : (%u) Out of range 0-%u, returning Invalid Call\n", This, PaletteNumber, MAX_PALETTES);
6520 return WINED3DERR_INVALIDCALL;
6522 /*TODO: stateblocks */
6523 This->currentPalette = PaletteNumber;
6524 TRACE("(%p) : returning\n", This);
6528 static HRESULT WINAPI IWineD3DDeviceImpl_GetCurrentTexturePalette(IWineD3DDevice *iface, UINT* PaletteNumber) {
6529 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
6530 if (PaletteNumber == NULL) {
6531 WARN("(%p) : returning Invalid Call\n", This);
6532 return WINED3DERR_INVALIDCALL;
6534 /*TODO: stateblocks */
6535 *PaletteNumber = This->currentPalette;
6536 TRACE("(%p) : returning %u\n", This, *PaletteNumber);
6540 static HRESULT WINAPI IWineD3DDeviceImpl_SetSoftwareVertexProcessing(IWineD3DDevice *iface, BOOL bSoftware) {
6541 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
6542 static BOOL showFixmes = TRUE;
6544 FIXME("(%p) : stub\n", This);
6548 This->softwareVertexProcessing = bSoftware;
6553 static BOOL WINAPI IWineD3DDeviceImpl_GetSoftwareVertexProcessing(IWineD3DDevice *iface) {
6554 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
6555 static BOOL showFixmes = TRUE;
6557 FIXME("(%p) : stub\n", This);
6560 return This->softwareVertexProcessing;
6564 static HRESULT WINAPI IWineD3DDeviceImpl_GetRasterStatus(IWineD3DDevice *iface, UINT iSwapChain, WINED3DRASTER_STATUS* pRasterStatus) {
6565 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
6566 IWineD3DSwapChain *swapChain;
6569 TRACE("(%p) : SwapChain %d returning %p\n", This, iSwapChain, pRasterStatus);
6571 hr = IWineD3DDeviceImpl_GetSwapChain(iface, iSwapChain, (IWineD3DSwapChain **)&swapChain);
6572 if(hr == WINED3D_OK){
6573 hr = IWineD3DSwapChain_GetRasterStatus(swapChain, pRasterStatus);
6574 IWineD3DSwapChain_Release(swapChain);
6576 FIXME("(%p) IWineD3DSwapChain_GetRasterStatus returned in error\n", This);
6582 static HRESULT WINAPI IWineD3DDeviceImpl_SetNPatchMode(IWineD3DDevice *iface, float nSegments) {
6583 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
6584 static BOOL showfixmes = TRUE;
6585 if(nSegments != 0.0f) {
6587 FIXME("(%p) : stub nSegments(%f)\n", This, nSegments);
6594 static float WINAPI IWineD3DDeviceImpl_GetNPatchMode(IWineD3DDevice *iface) {
6595 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
6596 static BOOL showfixmes = TRUE;
6598 FIXME("(%p) : stub returning(%f)\n", This, 0.0f);
6604 static HRESULT WINAPI IWineD3DDeviceImpl_UpdateSurface(IWineD3DDevice *iface, IWineD3DSurface *pSourceSurface, CONST RECT* pSourceRect, IWineD3DSurface *pDestinationSurface, CONST POINT* pDestPoint) {
6605 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *) iface;
6606 /** TODO: remove casts to IWineD3DSurfaceImpl
6607 * NOTE: move code to surface to accomplish this
6608 ****************************************/
6609 IWineD3DSurfaceImpl *pSrcSurface = (IWineD3DSurfaceImpl *)pSourceSurface;
6610 int srcWidth, srcHeight;
6611 unsigned int srcSurfaceWidth, srcSurfaceHeight, destSurfaceWidth, destSurfaceHeight;
6612 WINED3DFORMAT destFormat, srcFormat;
6614 int destLeft, destTop;
6615 WINED3DPOOL srcPool, destPool;
6617 int rowoffset = 0; /* how many bytes to add onto the end of a row to wraparound to the beginning of the next */
6618 glDescriptor *glDescription = NULL;
6619 GLenum textureDimensions = GL_TEXTURE_2D;
6620 IWineD3DBaseTexture *baseTexture;
6622 WINED3DSURFACE_DESC winedesc;
6624 TRACE("(%p) : Source (%p) Rect (%p) Destination (%p) Point(%p)\n", This, pSourceSurface, pSourceRect, pDestinationSurface, pDestPoint);
6625 memset(&winedesc, 0, sizeof(winedesc));
6626 winedesc.Width = &srcSurfaceWidth;
6627 winedesc.Height = &srcSurfaceHeight;
6628 winedesc.Pool = &srcPool;
6629 winedesc.Format = &srcFormat;
6631 IWineD3DSurface_GetDesc(pSourceSurface, &winedesc);
6633 winedesc.Width = &destSurfaceWidth;
6634 winedesc.Height = &destSurfaceHeight;
6635 winedesc.Pool = &destPool;
6636 winedesc.Format = &destFormat;
6637 winedesc.Size = &destSize;
6639 IWineD3DSurface_GetDesc(pDestinationSurface, &winedesc);
6641 if(srcPool != WINED3DPOOL_SYSTEMMEM || destPool != WINED3DPOOL_DEFAULT){
6642 WARN("source %p must be SYSTEMMEM and dest %p must be DEFAULT, returning WINED3DERR_INVALIDCALL\n", pSourceSurface, pDestinationSurface);
6643 return WINED3DERR_INVALIDCALL;
6646 if (destFormat == WINED3DFMT_UNKNOWN) {
6647 TRACE("(%p) : Converting destination surface from WINED3DFMT_UNKNOWN to the source format\n", This);
6648 IWineD3DSurface_SetFormat(pDestinationSurface, srcFormat);
6650 /* Get the update surface description */
6651 IWineD3DSurface_GetDesc(pDestinationSurface, &winedesc);
6654 /* Make sure the surface is loaded and up to date */
6655 IWineD3DSurface_PreLoad(pDestinationSurface);
6657 IWineD3DSurface_GetGlDesc(pDestinationSurface, &glDescription);
6661 /* this needs to be done in lines if the sourceRect != the sourceWidth */
6662 srcWidth = pSourceRect ? pSourceRect->right - pSourceRect->left : srcSurfaceWidth;
6663 srcHeight = pSourceRect ? pSourceRect->top - pSourceRect->bottom : srcSurfaceHeight;
6664 destLeft = pDestPoint ? pDestPoint->x : 0;
6665 destTop = pDestPoint ? pDestPoint->y : 0;
6668 /* This function doesn't support compressed textures
6669 the pitch is just bytesPerPixel * width */
6670 if(srcWidth != srcSurfaceWidth || (pSourceRect != NULL && pSourceRect->left != 0) ){
6671 rowoffset = (srcSurfaceWidth - srcWidth) * pSrcSurface->bytesPerPixel;
6672 offset += pSourceRect->left * pSrcSurface->bytesPerPixel;
6673 /* TODO: do we ever get 3bpp?, would a shift and an add be quicker than a mul (well maybe a cycle or two) */
6675 /* TODO DXT formats */
6677 if(pSourceRect != NULL && pSourceRect->top != 0){
6678 offset += pSourceRect->top * srcWidth * pSrcSurface->bytesPerPixel;
6680 TRACE("(%p) glTexSubImage2D, Level %d, left %d, top %d, width %d, height %d , ftm %d, type %d, memory %p\n"
6682 ,glDescription->level
6687 ,glDescription->glFormat
6688 ,glDescription->glType
6689 ,IWineD3DSurface_GetData(pSourceSurface)
6693 if (IWineD3DSurface_GetData(pSourceSurface) == NULL) {
6695 /* need to lock the surface to get the data */
6696 FIXME("Surfaces has no allocated memory, but should be an in memory only surface\n");
6699 /* TODO: Cube and volume support */
6701 /* not a whole row so we have to do it a line at a time */
6704 /* hopefully using pointer addtion will be quicker than using a point + j * rowoffset */
6705 unsigned char* data =((unsigned char *)IWineD3DSurface_GetData(pSourceSurface)) + offset;
6707 for(j = destTop ; j < (srcHeight + destTop) ; j++){
6709 glTexSubImage2D(glDescription->target
6710 ,glDescription->level
6715 ,glDescription->glFormat
6716 ,glDescription->glType
6717 ,data /* could be quicker using */
6722 } else { /* Full width, so just write out the whole texture */
6724 if (WINED3DFMT_DXT1 == destFormat ||
6725 WINED3DFMT_DXT2 == destFormat ||
6726 WINED3DFMT_DXT3 == destFormat ||
6727 WINED3DFMT_DXT4 == destFormat ||
6728 WINED3DFMT_DXT5 == destFormat) {
6729 if (GL_SUPPORT(EXT_TEXTURE_COMPRESSION_S3TC)) {
6730 if (destSurfaceHeight != srcHeight || destSurfaceWidth != srcWidth) {
6731 /* FIXME: The easy way to do this is lock the destination, and copy the bits accross */
6732 FIXME("Updating part of a compressed texture is not supported at the moment\n");
6733 } if (destFormat != srcFormat) {
6734 FIXME("Updating mixed format compressed texture is not curretly support\n");
6736 GL_EXTCALL(glCompressedTexImage2DARB)(glDescription->target,
6737 glDescription->level,
6738 glDescription->glFormatInternal,
6743 IWineD3DSurface_GetData(pSourceSurface));
6746 FIXME("Attempting to update a DXT compressed texture without hardware support\n");
6751 if (NP2_REPACK == wined3d_settings.nonpower2_mode) {
6753 /* some applications cannot handle odd pitches returned by soft non-power2, so we have
6754 to repack the data from pow2Width/Height to expected Width,Height, this makes the
6755 data returned by GetData non-power2 width/height with hardware non-power2
6756 pow2Width/height are set to surface width height, repacking isn't needed so it
6757 doesn't matter which function gets called. */
6758 glTexSubImage2D(glDescription->target
6759 ,glDescription->level
6764 ,glDescription->glFormat
6765 ,glDescription->glType
6766 ,IWineD3DSurface_GetData(pSourceSurface)
6770 /* not repacked, the data returned by IWineD3DSurface_GetData is pow2Width x pow2Height */
6771 glTexSubImage2D(glDescription->target
6772 ,glDescription->level
6775 ,((IWineD3DSurfaceImpl *)pSourceSurface)->pow2Width
6776 ,((IWineD3DSurfaceImpl *)pSourceSurface)->pow2Height
6777 ,glDescription->glFormat
6778 ,glDescription->glType
6779 ,IWineD3DSurface_GetData(pSourceSurface)
6785 checkGLcall("glTexSubImage2D");
6786 ((IWineD3DSurfaceImpl *)pDestinationSurface)->Flags |= SFLAG_GLDIRTY;
6788 /* I only need to look up baseTexture here, so it may be a good idea to hava a GL_TARGET ->
6789 * GL_DIMENSIONS lookup, or maybe store the dimensions on the surface (but that's making the
6790 * surface bigger than it needs to be hmm.. */
6791 if (WINED3D_OK == IWineD3DSurface_GetContainer(pDestinationSurface, &IID_IWineD3DBaseTexture, (void **)&baseTexture)) {
6792 textureDimensions = IWineD3DBaseTexture_GetTextureDimensions(baseTexture);
6793 IWineD3DBaseTexture_Release(baseTexture);
6796 glDisable(textureDimensions); /* This needs to be managed better.... */
6802 /* Used by DirectX 8 */
6803 static HRESULT WINAPI IWineD3DDeviceImpl_CopyRects(IWineD3DDevice *iface,
6804 IWineD3DSurface* pSourceSurface, CONST RECT* pSourceRectsArray, UINT cRects,
6805 IWineD3DSurface* pDestinationSurface, CONST POINT* pDestPointsArray) {
6807 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
6808 HRESULT hr = WINED3D_OK;
6809 WINED3DFORMAT srcFormat, destFormat;
6810 UINT srcWidth, destWidth;
6811 UINT srcHeight, destHeight;
6813 WINED3DSURFACE_DESC winedesc;
6815 TRACE("(%p) pSrcSur=%p, pSourceRects=%p, cRects=%d, pDstSur=%p, pDestPtsArr=%p\n", This,
6816 pSourceSurface, pSourceRectsArray, cRects, pDestinationSurface, pDestPointsArray);
6819 /* Check that the source texture is in WINED3DPOOL_SYSTEMMEM and the destination texture is in WINED3DPOOL_DEFAULT */
6820 memset(&winedesc, 0, sizeof(winedesc));
6822 winedesc.Format = &srcFormat;
6823 winedesc.Width = &srcWidth;
6824 winedesc.Height = &srcHeight;
6825 winedesc.Size = &srcSize;
6826 IWineD3DSurface_GetDesc(pSourceSurface, &winedesc);
6828 winedesc.Format = &destFormat;
6829 winedesc.Width = &destWidth;
6830 winedesc.Height = &destHeight;
6831 winedesc.Size = NULL;
6832 IWineD3DSurface_GetDesc(pDestinationSurface, &winedesc);
6834 /* Check that the source and destination formats match */
6835 if (srcFormat != destFormat && WINED3DFMT_UNKNOWN != destFormat) {
6836 WARN("(%p) source %p format must match the dest %p format, returning WINED3DERR_INVALIDCALL\n", This, pSourceSurface, pDestinationSurface);
6837 return WINED3DERR_INVALIDCALL;
6838 } else if (WINED3DFMT_UNKNOWN == destFormat) {
6839 TRACE("(%p) : Converting destination surface from WINED3DFMT_UNKNOWN to the source format\n", This);
6840 IWineD3DSurface_SetFormat(pDestinationSurface, srcFormat);
6841 destFormat = srcFormat;
6844 /* Quick if complete copy ... */
6845 if (cRects == 0 && pSourceRectsArray == NULL && pDestPointsArray == NULL) {
6847 if (srcWidth == destWidth && srcHeight == destHeight) {
6848 WINED3DLOCKED_RECT lrSrc;
6849 WINED3DLOCKED_RECT lrDst;
6850 IWineD3DSurface_LockRect(pSourceSurface, &lrSrc, NULL, WINED3DLOCK_READONLY);
6851 IWineD3DSurface_LockRect(pDestinationSurface, &lrDst, NULL, 0L);
6852 TRACE("Locked src and dst, Direct copy as surfaces are equal, w=%d, h=%d\n", srcWidth, srcHeight);
6854 memcpy(lrDst.pBits, lrSrc.pBits, srcSize);
6856 IWineD3DSurface_UnlockRect(pSourceSurface);
6857 IWineD3DSurface_UnlockRect(pDestinationSurface);
6858 TRACE("Unlocked src and dst\n");
6862 FIXME("Wanted to copy all surfaces but size not compatible, returning WINED3DERR_INVALIDCALL\n");
6863 hr = WINED3DERR_INVALIDCALL;
6868 if (NULL != pSourceRectsArray && NULL != pDestPointsArray) {
6870 int bytesPerPixel = ((IWineD3DSurfaceImpl *) pSourceSurface)->bytesPerPixel;
6873 /* Copy rect by rect */
6874 for (i = 0; i < cRects; ++i) {
6875 CONST RECT* r = &pSourceRectsArray[i];
6876 CONST POINT* p = &pDestPointsArray[i];
6879 WINED3DLOCKED_RECT lrSrc;
6880 WINED3DLOCKED_RECT lrDst;
6883 TRACE("Copying rect %d (%ld,%ld),(%ld,%ld) -> (%ld,%ld)\n", i, r->left, r->top, r->right, r->bottom, p->x, p->y);
6884 if (srcFormat == WINED3DFMT_DXT1) {
6885 copyperline = ((r->right - r->left) * bytesPerPixel) / 2; /* DXT1 is half byte per pixel */
6887 copyperline = ((r->right - r->left) * bytesPerPixel);
6890 IWineD3DSurface_LockRect(pSourceSurface, &lrSrc, r, WINED3DLOCK_READONLY);
6891 dest_rect.left = p->x;
6892 dest_rect.top = p->y;
6893 dest_rect.right = p->x + (r->right - r->left);
6894 dest_rect.bottom= p->y + (r->bottom - r->top);
6895 IWineD3DSurface_LockRect(pDestinationSurface, &lrDst, &dest_rect, 0L);
6896 TRACE("Locked src and dst\n");
6898 /* Find where to start */
6899 for (j = 0; j < (r->bottom - r->top - 1); ++j) {
6900 memcpy((char*) lrDst.pBits + (j * lrDst.Pitch), (char*) lrSrc.pBits + (j * lrSrc.Pitch), copyperline);
6902 IWineD3DSurface_UnlockRect(pSourceSurface);
6903 IWineD3DSurface_UnlockRect(pDestinationSurface);
6904 TRACE("Unlocked src and dst\n");
6908 int bytesPerPixel = ((IWineD3DSurfaceImpl *) pSourceSurface)->bytesPerPixel;
6911 WINED3DLOCKED_RECT lrSrc;
6912 WINED3DLOCKED_RECT lrDst;
6915 for(i=0; i < cRects; i++) {
6916 CONST RECT* r = &pSourceRectsArray[i];
6918 TRACE("Copying rect %d (%ld,%ld),(%ld,%ld) -> (0, 0)\n", i, r->left, r->top, r->right, r->bottom);
6919 if (srcFormat == WINED3DFMT_DXT1) {
6920 copyperline = ((r->right - r->left) * bytesPerPixel) / 2; /* DXT1 is half byte per pixel */
6922 copyperline = ((r->right - r->left) * bytesPerPixel);
6924 IWineD3DSurface_LockRect(pSourceSurface, &lrSrc, r, WINED3DLOCK_READONLY);
6927 dest_rect.right = r->right - r->left;
6928 dest_rect.bottom= r->bottom - r->top;
6929 IWineD3DSurface_LockRect(pDestinationSurface, &lrDst, &dest_rect, 0L);
6930 TRACE("Locked src and dst\n");
6931 /* Find where to start */
6932 for (j = 0; j < (r->bottom - r->top - 1); ++j) {
6933 memcpy((char*) lrDst.pBits + (j * lrDst.Pitch), (char*) lrSrc.pBits + (j * lrSrc.Pitch), copyperline);
6935 IWineD3DSurface_UnlockRect(pSourceSurface);
6936 IWineD3DSurface_UnlockRect(pDestinationSurface);
6937 TRACE("Unlocked src and dst\n");
6945 /* Implementation details at http://developer.nvidia.com/attach/6494
6947 http://oss.sgi.com/projects/ogl-sample/registry/NV/evaluators.txt
6948 hmm.. no longer supported use
6949 OpenGL evaluators or tessellate surfaces within your application.
6952 /* http://msdn.microsoft.com/library/default.asp?url=/library/en-us/directx9_c/directx/graphics/reference/d3d/interfaces/idirect3ddevice9/DrawRectPatch.asp */
6953 static HRESULT WINAPI IWineD3DDeviceImpl_DrawRectPatch(IWineD3DDevice *iface, UINT Handle, CONST float* pNumSegs, CONST WINED3DRECTPATCH_INFO* pRectPatchInfo) {
6954 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
6955 TRACE("(%p) Handle(%d) noSegs(%p) rectpatch(%p)\n", This, Handle, pNumSegs, pRectPatchInfo);
6956 FIXME("(%p) : Stub\n", This);
6961 /* http://msdn.microsoft.com/library/default.asp?url=/library/en-us/directx9_c/directx/graphics/reference/d3d/interfaces/idirect3ddevice9/DrawTriPatch.asp */
6962 static HRESULT WINAPI IWineD3DDeviceImpl_DrawTriPatch(IWineD3DDevice *iface, UINT Handle, CONST float* pNumSegs, CONST WINED3DTRIPATCH_INFO* pTriPatchInfo) {
6963 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
6964 TRACE("(%p) Handle(%d) noSegs(%p) tripatch(%p)\n", This, Handle, pNumSegs, pTriPatchInfo);
6965 FIXME("(%p) : Stub\n", This);
6969 static HRESULT WINAPI IWineD3DDeviceImpl_DeletePatch(IWineD3DDevice *iface, UINT Handle) {
6970 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
6971 TRACE("(%p) Handle(%d)\n", This, Handle);
6972 FIXME("(%p) : Stub\n", This);
6976 static HRESULT WINAPI IWineD3DDeviceImpl_ColorFill(IWineD3DDevice *iface, IWineD3DSurface *pSurface, CONST D3DRECT* pRect, D3DCOLOR color) {
6977 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *) iface;
6978 IWineD3DSurfaceImpl *surface = (IWineD3DSurfaceImpl *) pSurface;
6980 TRACE("(%p) Colour fill Surface: %p rect: %p color: %ld\n", This, pSurface, pRect, color);
6982 if (surface->resource.pool != WINED3DPOOL_DEFAULT && surface->resource.pool != WINED3DPOOL_SYSTEMMEM) {
6983 FIXME("call to colorfill with non WINED3DPOOL_DEFAULT or WINED3DPOOL_SYSTEMMEM surface\n");
6984 return WINED3DERR_INVALIDCALL;
6987 /* Just forward this to the DirectDraw blitting engine */
6988 memset(&BltFx, 0, sizeof(BltFx));
6989 BltFx.dwSize = sizeof(BltFx);
6990 BltFx.u5.dwFillColor = color;
6991 return IWineD3DSurface_Blt(pSurface, (RECT *) pRect, NULL, NULL, DDBLT_COLORFILL, &BltFx);
6994 /* rendertarget and deptth stencil functions */
6995 static HRESULT WINAPI IWineD3DDeviceImpl_GetRenderTarget(IWineD3DDevice* iface,DWORD RenderTargetIndex, IWineD3DSurface **ppRenderTarget) {
6996 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
6998 /* FIXME: Implelent RenderTargetIndex >0 */
6999 if(RenderTargetIndex > 0)
7000 FIXME("(%p) : RenderTargetIndex %ld >0 not currently supported\n", This, RenderTargetIndex);
7002 *ppRenderTarget = This->renderTarget;
7003 TRACE("(%p) : RenderTarget %ld Index returning %p\n", This, RenderTargetIndex, *ppRenderTarget);
7004 /* Note inc ref on returned surface */
7005 if(*ppRenderTarget != NULL)
7006 IWineD3DSurface_AddRef(*ppRenderTarget);
7010 static HRESULT WINAPI IWineD3DDeviceImpl_SetFrontBackBuffers(IWineD3DDevice *iface, IWineD3DSurface *Front, IWineD3DSurface *Back) {
7011 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
7012 IWineD3DSurfaceImpl *FrontImpl = (IWineD3DSurfaceImpl *) Front;
7013 IWineD3DSurfaceImpl *BackImpl = (IWineD3DSurfaceImpl *) Back;
7014 IWineD3DSwapChainImpl *Swapchain;
7017 TRACE("(%p)->(%p,%p)\n", This, FrontImpl, BackImpl);
7019 hr = IWineD3DDevice_GetSwapChain(iface, 0, (IWineD3DSwapChain **) &Swapchain);
7020 if(hr != WINED3D_OK) {
7021 ERR("Can't get the swapchain\n");
7025 /* Make sure to release the swapchain */
7026 IWineD3DSwapChain_Release((IWineD3DSwapChain *) Swapchain);
7028 if(FrontImpl && !(FrontImpl->resource.usage & WINED3DUSAGE_RENDERTARGET) ) {
7029 ERR("Trying to set a front buffer which doesn't have WINED3DUSAGE_RENDERTARGET usage\n");
7030 return WINED3DERR_INVALIDCALL;
7032 else if(BackImpl && !(BackImpl->resource.usage & WINED3DUSAGE_RENDERTARGET)) {
7033 ERR("Trying to set a back buffer which doesn't have WINED3DUSAGE_RENDERTARGET usage\n");
7034 return WINED3DERR_INVALIDCALL;
7037 if(Swapchain->frontBuffer != Front) {
7038 TRACE("Changing the front buffer from %p to %p\n", Swapchain->frontBuffer, Front);
7040 if(Swapchain->frontBuffer)
7041 IWineD3DSurface_SetContainer(Swapchain->frontBuffer, NULL);
7042 Swapchain->frontBuffer = Front;
7044 if(Swapchain->frontBuffer) {
7045 IWineD3DSurface_SetContainer(Swapchain->frontBuffer, (IWineD3DBase *) Swapchain);
7049 if(Back && !Swapchain->backBuffer) {
7050 /* We need memory for the back buffer array - only one back buffer this way */
7051 Swapchain->backBuffer = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(IWineD3DSurface *));
7052 if(!Swapchain->backBuffer) {
7053 ERR("Out of memory\n");
7054 return E_OUTOFMEMORY;
7058 if(Swapchain->backBuffer[0] != Back) {
7059 TRACE("Changing the back buffer from %p to %p\n", Swapchain->backBuffer, Back);
7061 if(!Swapchain->backBuffer[0]) {
7062 /* GL was told to draw to the front buffer at creation,
7065 glDrawBuffer(GL_BACK);
7066 checkGLcall("glDrawBuffer(GL_BACK)");
7067 /* Set the backbuffer count to 1 because other code uses it to fing the back buffers */
7068 Swapchain->presentParms.BackBufferCount = 1;
7070 /* That makes problems - disable for now */
7071 /* glDrawBuffer(GL_FRONT); */
7072 checkGLcall("glDrawBuffer(GL_FRONT)");
7073 /* We have lost our back buffer, set this to 0 to avoid confusing other code */
7074 Swapchain->presentParms.BackBufferCount = 0;
7078 if(Swapchain->backBuffer[0])
7079 IWineD3DSurface_SetContainer(Swapchain->backBuffer[0], NULL);
7080 Swapchain->backBuffer[0] = Back;
7082 if(Swapchain->backBuffer[0]) {
7083 IWineD3DSurface_SetContainer(Swapchain->backBuffer[0], (IWineD3DBase *) Swapchain);
7085 HeapFree(GetProcessHeap(), 0, Swapchain->backBuffer);
7093 static HRESULT WINAPI IWineD3DDeviceImpl_GetDepthStencilSurface(IWineD3DDevice* iface, IWineD3DSurface **ppZStencilSurface) {
7094 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
7095 *ppZStencilSurface = This->depthStencilBuffer;
7096 TRACE("(%p) : zStencilSurface returning %p\n", This, *ppZStencilSurface);
7098 if(*ppZStencilSurface != NULL) {
7099 /* Note inc ref on returned surface */
7100 IWineD3DSurface_AddRef(*ppZStencilSurface);
7105 /* internal static helper functions */
7106 static HRESULT WINAPI IWineD3DDeviceImpl_ActiveRender(IWineD3DDevice* iface,
7107 IWineD3DSurface *RenderSurface);
7109 static HRESULT WINAPI IWineD3DDeviceImpl_SetRenderTarget(IWineD3DDevice *iface, DWORD RenderTargetIndex, IWineD3DSurface *pRenderTarget) {
7110 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
7111 HRESULT hr = WINED3D_OK;
7112 WINED3DVIEWPORT viewport;
7114 TRACE("(%p) Swapping rendertarget\n",This);
7115 if (RenderTargetIndex > 0) {
7116 FIXME("(%p) Render targets other than the first are not supported\n",This);
7117 RenderTargetIndex = 0;
7120 /* MSDN says that null disables the render target
7121 but a device must always be associated with a render target
7122 nope MSDN says that we return invalid call to a null rendertarget with an index of 0
7124 see http://msdn.microsoft.com/library/default.asp?url=/library/en-us/directx9_c/directx/graphics/programmingguide/AdvancedTopics/PixelPipe/MultipleRenderTarget.asp
7127 if (RenderTargetIndex == 0 && pRenderTarget == NULL) {
7128 FIXME("Trying to set render target 0 to NULL\n");
7129 return WINED3DERR_INVALIDCALL;
7131 /* TODO: replace Impl* usage with interface usage */
7132 if (!((IWineD3DSurfaceImpl *)pRenderTarget)->resource.usage & WINED3DUSAGE_RENDERTARGET) {
7133 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);
7134 return WINED3DERR_INVALIDCALL;
7136 /** TODO: check that the depth stencil format matches the render target, this is only done in debug
7137 * builds, but I think wine counts as a 'debug' build for now.
7138 ******************************/
7139 /* If we are trying to set what we already have, don't bother */
7140 if (pRenderTarget == This->renderTarget) {
7141 TRACE("Trying to do a NOP SetRenderTarget operation\n");
7143 /* Otherwise, set the render target up */
7145 if (FALSE == This->sceneEnded) {
7146 IWineD3DDevice_EndScene(iface);
7148 TRACE("clearing renderer\n");
7149 /* IWineD3DDeviceImpl_CleanRender(iface); */
7150 /* OpenGL doesn't support 'sharing' of the stencilBuffer so we may incure an extra memory overhead
7151 depending on the renter target implementation being used.
7152 A shared context implementation will share all buffers between all rendertargets (including swapchains),
7153 implementations that use separate pbuffers for different swapchains or rendertargets will have to duplicate the
7154 stencil buffer and incure an extra memory overhead */
7155 hr = IWineD3DDeviceImpl_ActiveRender(iface, pRenderTarget);
7158 if (SUCCEEDED(hr)) {
7159 /* Finally, reset the viewport as the MSDN states. */
7160 /* TODO: Replace impl usage */
7161 viewport.Height = ((IWineD3DSurfaceImpl *)This->renderTarget)->currentDesc.Height;
7162 viewport.Width = ((IWineD3DSurfaceImpl *)This->renderTarget)->currentDesc.Width;
7165 viewport.MaxZ = 1.0f;
7166 viewport.MinZ = 0.0f;
7167 IWineD3DDeviceImpl_SetViewport(iface, &viewport);
7169 FIXME("Unknown error setting the render target\n");
7171 This->sceneEnded = FALSE;
7175 static HRESULT WINAPI IWineD3DDeviceImpl_SetDepthStencilSurface(IWineD3DDevice *iface, IWineD3DSurface *pNewZStencil) {
7176 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
7177 HRESULT hr = WINED3D_OK;
7178 IWineD3DSurface *tmp;
7180 TRACE("(%p) Swapping z-buffer\n",This);
7182 if (pNewZStencil == This->stencilBufferTarget) {
7183 TRACE("Trying to do a NOP SetRenderTarget operation\n");
7185 /** OpenGL doesn't support 'sharing' of the stencilBuffer so we may incure an extra memory overhead
7186 * depending on the renter target implementation being used.
7187 * A shared context implementation will share all buffers between all rendertargets (including swapchains),
7188 * implementations that use separate pbuffers for different swapchains or rendertargets will have to duplicate the
7189 * stencil buffer and incure an extra memory overhead
7190 ******************************************************/
7193 tmp = This->stencilBufferTarget;
7194 This->stencilBufferTarget = pNewZStencil;
7195 /* should we be calling the parent or the wined3d surface? */
7196 if (NULL != This->stencilBufferTarget) IWineD3DSurface_AddRef(This->stencilBufferTarget);
7197 if (NULL != tmp) IWineD3DSurface_Release(tmp);
7199 /** TODO: glEnable/glDisable on depth/stencil depending on
7200 * pNewZStencil is NULL and the depth/stencil is enabled in d3d
7201 **********************************************************/
7208 #ifdef GL_VERSION_1_3
7209 /* Internal functions not in DirectX */
7210 /** TODO: move this off to the opengl context manager
7211 *(the swapchain doesn't need to know anything about offscreen rendering!)
7212 ****************************************************/
7214 static HRESULT WINAPI IWineD3DDeviceImpl_CleanRender(IWineD3DDevice* iface, IWineD3DSwapChainImpl *swapchain)
7216 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
7218 TRACE("(%p), %p\n", This, swapchain);
7220 if (swapchain->win != swapchain->drawable) {
7221 /* Set everything back the way it ws */
7222 swapchain->render_ctx = swapchain->glCtx;
7223 swapchain->drawable = swapchain->win;
7228 /* TODO: move this off into a context manager so that GLX_ATI_render_texture and other types of surface can be used. */
7229 static HRESULT WINAPI IWineD3DDeviceImpl_FindGLContext(IWineD3DDevice *iface, IWineD3DSurface *pSurface, glContext **context) {
7230 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
7233 unsigned int height;
7234 WINED3DFORMAT format;
7235 WINED3DSURFACE_DESC surfaceDesc;
7236 memset(&surfaceDesc, 0, sizeof(surfaceDesc));
7237 surfaceDesc.Width = &width;
7238 surfaceDesc.Height = &height;
7239 surfaceDesc.Format = &format;
7240 IWineD3DSurface_GetDesc(pSurface, &surfaceDesc);
7242 /* I need a get width/height function (and should do something with the format) */
7243 for (i = 0; i < CONTEXT_CACHE; ++i) {
7244 /** NOTE: the contextCache[i].pSurface == pSurface check ceates onepbuffer per surface
7245 ATI cards don't destroy pbuffers, but as soon as resource releasing callbacks are inplace
7246 the pSurface can be set to 0 allowing it to be reused from cache **/
7247 if (This->contextCache[i].Width == width && This->contextCache[i].Height == height
7248 && (pbuffer_per_surface == FALSE || This->contextCache[i].pSurface == pSurface || This->contextCache[i].pSurface == NULL)) {
7249 *context = &This->contextCache[i];
7252 if (This->contextCache[i].Width == 0) {
7253 This->contextCache[i].pSurface = pSurface;
7254 This->contextCache[i].Width = width;
7255 This->contextCache[i].Height = height;
7256 *context = &This->contextCache[i];
7260 if (i == CONTEXT_CACHE) {
7261 int minUsage = 0x7FFFFFFF; /* MAX_INT */
7262 glContext *dropContext = 0;
7263 for (i = 0; i < CONTEXT_CACHE; i++) {
7264 if (This->contextCache[i].usedcount < minUsage) {
7265 dropContext = &This->contextCache[i];
7266 minUsage = This->contextCache[i].usedcount;
7269 /* clean up the context (this doesn't work for ATI at the moment */
7271 glXDestroyContext(swapchain->display, dropContext->context);
7272 glXDestroyPbuffer(swapchain->display, dropContext->drawable);
7275 dropContext->Width = 0;
7276 dropContext->pSurface = pSurface;
7277 *context = dropContext;
7279 if (++This->contextCache[i].usedcount == 0x7FFFFFFF /* MAX_INT */ - 1 ) {
7280 for (i = 0; i < CONTEXT_CACHE; i++) {
7281 This->contextCache[i].usedcount = max(0, This->contextCache[i].usedcount - (0x7FFFFFFF /* MAX_INT */ >> 1));
7285 if (*context != NULL)
7288 return E_OUTOFMEMORY;
7292 /* Reapply the device stateblock */
7293 static void device_reapply_stateblock(IWineD3DDeviceImpl* This) {
7296 IWineD3DStateBlockImpl *oldUpdateStateBlock;
7298 /* Disable recording */
7299 oldUpdateStateBlock = This->updateStateBlock;
7300 oldRecording= This->isRecordingState;
7301 This->isRecordingState = FALSE;
7302 This->updateStateBlock = This->stateBlock;
7304 /* Reapply the state block */
7305 IWineD3DStateBlock_Apply((IWineD3DStateBlock *)This->stateBlock);
7307 /* Restore recording */
7308 This->isRecordingState = oldRecording;
7309 This->updateStateBlock = oldUpdateStateBlock;
7312 /* Set the device to render to a texture, or not.
7313 * This involves changing renderUpsideDown */
7315 static void device_render_to_texture(IWineD3DDeviceImpl* This, BOOL isTexture) {
7319 IWineD3DStateBlockImpl *oldUpdateStateBlock;
7321 /* Disable recording */
7322 oldUpdateStateBlock = This->updateStateBlock;
7323 oldRecording= This->isRecordingState;
7324 This->isRecordingState = FALSE;
7325 This->updateStateBlock = This->stateBlock;
7327 /* Set upside-down rendering, and update the cull mode */
7328 /* The surface must be rendered upside down to cancel the flip produced by glCopyTexImage */
7329 This->renderUpsideDown = isTexture;
7330 This->last_was_rhw = FALSE;
7331 This->proj_valid = FALSE;
7332 IWineD3DDevice_GetRenderState((IWineD3DDevice*) This, WINED3DRS_CULLMODE, &cullMode);
7333 IWineD3DDevice_SetRenderState((IWineD3DDevice*) This, WINED3DRS_CULLMODE, cullMode);
7335 /* Restore recording */
7336 This->isRecordingState = oldRecording;
7337 This->updateStateBlock = oldUpdateStateBlock;
7340 /* Returns an array of compatible FBconfig(s).
7341 * The array must be freed with XFree. Requires ENTER_GL() */
7343 static GLXFBConfig* device_find_fbconfigs(
7344 IWineD3DDeviceImpl* This,
7345 IWineD3DSwapChainImpl* implicitSwapchainImpl,
7346 IWineD3DSurface* RenderSurface) {
7348 GLXFBConfig* cfgs = NULL;
7353 IWineD3DSurface *StencilSurface = This->stencilBufferTarget;
7354 D3DFORMAT BackBufferFormat = ((IWineD3DSurfaceImpl *) RenderSurface)->resource.format;
7355 D3DFORMAT StencilBufferFormat = (NULL != StencilSurface) ? ((IWineD3DSurfaceImpl *) StencilSurface)->resource.format : 0;
7358 if StencilSurface == NULL && zBufferTarget != NULL then switch the zbuffer off,
7359 it StencilSurface != NULL && zBufferTarget == NULL switch it on
7362 #define PUSH1(att) attribs[nAttribs++] = (att);
7363 #define PUSH2(att,value) attribs[nAttribs++] = (att); attribs[nAttribs++] = (value);
7365 /* PUSH2(GLX_BIND_TO_TEXTURE_RGBA_ATI, True); examples of this are few and far between (but I've got a nice working one!)*/
7367 PUSH2(GLX_DRAWABLE_TYPE, GLX_PBUFFER_BIT);
7368 PUSH2(GLX_X_RENDERABLE, TRUE);
7369 PUSH2(GLX_DOUBLEBUFFER, TRUE);
7370 TRACE("calling makeglcfg\n");
7371 D3DFmtMakeGlCfg(BackBufferFormat, StencilBufferFormat, attribs, &nAttribs, FALSE /* alternate */);
7373 TRACE("calling chooseFGConfig\n");
7374 cfgs = glXChooseFBConfig(implicitSwapchainImpl->display,
7375 DefaultScreen(implicitSwapchainImpl->display),
7378 /* OK we didn't find the exact config, so use any reasonable match */
7379 /* TODO: fill in the 'requested' and 'current' depths, also make sure that's
7380 why we failed and only show this message once! */
7381 MESSAGE("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");
7384 PUSH2(GLX_DRAWABLE_TYPE, GLX_PBUFFER_BIT | GLX_WINDOW_BIT);
7385 /* PUSH2(GLX_X_RENDERABLE, TRUE); */
7386 PUSH2(GLX_RENDER_TYPE, GLX_RGBA_BIT);
7387 PUSH2(GLX_DOUBLEBUFFER, FALSE);
7388 TRACE("calling makeglcfg\n");
7389 D3DFmtMakeGlCfg(BackBufferFormat, StencilBufferFormat, attribs, &nAttribs, TRUE /* alternate */);
7391 cfgs = glXChooseFBConfig(implicitSwapchainImpl->display,
7392 DefaultScreen(implicitSwapchainImpl->display),
7397 ERR("Could not get a valid FBConfig for (%u,%s)/(%u,%s)\n",
7398 BackBufferFormat, debug_d3dformat(BackBufferFormat),
7399 StencilBufferFormat, debug_d3dformat(StencilBufferFormat));
7403 for (i = 0; i < nCfgs; ++i) {
7404 TRACE("for (%u,%s)/(%u,%s) found config[%d]@%p\n", BackBufferFormat,
7405 debug_d3dformat(BackBufferFormat), StencilBufferFormat,
7406 debug_d3dformat(StencilBufferFormat), i, cfgs[i]);
7408 if (NULL != This->renderTarget) {
7410 vcheckGLcall("glFlush");
7411 /** This is only useful if the old render target was a swapchain,
7412 * we need to supercede this with a function that displays
7413 * the current buffer on the screen. This is easy to do in glx1.3 but
7414 * we need to do copy-write pixels in glx 1.2.
7415 ************************************************/
7416 glXSwapBuffers(implicitSwapChainImpl->display,
7417 implicitSwapChainImpl->drawable);
7418 printf("Hit Enter to get next frame ...\n");
7429 /** FIXME: This is currently used called whenever SetRenderTarget or SetStencilBuffer are called
7430 * the functionality needs splitting up so that we don't do more than we should do.
7431 * this only seems to impact performance a little.
7432 ******************************/
7433 static HRESULT WINAPI IWineD3DDeviceImpl_ActiveRender(IWineD3DDevice* iface,
7434 IWineD3DSurface *RenderSurface) {
7437 * Currently only active for GLX >= 1.3
7438 * for others versions we'll have to use GLXPixmaps
7440 * normally we must test GLX_VERSION_1_3 but nvidia headers are not correct
7441 * as they implement GLX 1.3 but only define GLX_VERSION_1_2
7442 * so only check OpenGL version
7443 * ..........................
7444 * I don't believe that it is a problem with NVidia headers,
7445 * XFree only supports GLX1.2, nVidia (and ATI to some extent) provide 1.3 functions
7446 * in GLX 1.2, there is no mention of the correct way to tell if the extensions are provided.
7448 * Your application will report GLX version 1.2 on glXQueryVersion.
7449 * However, it is safe to call the GLX 1.3 functions as described below.
7451 #if defined(GL_VERSION_1_3)
7453 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
7454 IWineD3DSurface *tmp;
7455 GLXFBConfig* cfgs = NULL;
7456 IWineD3DSwapChain *currentSwapchain;
7457 IWineD3DSwapChainImpl *currentSwapchainImpl;
7458 IWineD3DSwapChain *implicitSwapchain;
7459 IWineD3DSwapChainImpl *implicitSwapchainImpl;
7460 IWineD3DSwapChain *renderSurfaceSwapchain;
7461 IWineD3DSwapChainImpl *renderSurfaceSwapchainImpl;
7463 /* Obtain a reference to the device implicit swapchain,
7464 * the swapchain of the current render target,
7465 * and the swapchain of the new render target.
7466 * Fallback to device implicit swapchain if the current render target doesn't have one */
7467 IWineD3DDevice_GetSwapChain(iface, 0, &implicitSwapchain);
7468 IWineD3DSurface_GetContainer(RenderSurface, &IID_IWineD3DSwapChain, (void**) &renderSurfaceSwapchain);
7469 IWineD3DSurface_GetContainer(This->renderTarget, &IID_IWineD3DSwapChain, (void **)¤tSwapchain);
7470 if (currentSwapchain == NULL)
7471 IWineD3DDevice_GetSwapChain(iface, 0, ¤tSwapchain);
7473 currentSwapchainImpl = (IWineD3DSwapChainImpl*) currentSwapchain;
7474 implicitSwapchainImpl = (IWineD3DSwapChainImpl*) implicitSwapchain;
7475 renderSurfaceSwapchainImpl = (IWineD3DSwapChainImpl*) renderSurfaceSwapchain;
7480 * TODO: remove the use of IWineD3DSwapChainImpl, a context manager will help since it will replace the
7481 * renderTarget = swapchain->backBuffer[i] bit and anything to do with *glContexts
7482 **********************************************************************/
7483 if (renderSurfaceSwapchain != NULL) {
7485 /* We also need to make sure that the lights &co are also in the context of the swapchains */
7486 /* FIXME: If the render target gets sent to the frontBuffer should be be presenting it raw? */
7487 TRACE("making swapchain active\n");
7488 if (RenderSurface != This->renderTarget) {
7489 BOOL backbuf = FALSE;
7492 for(i = 0; i < renderSurfaceSwapchainImpl->presentParms.BackBufferCount; i++) {
7493 if(RenderSurface == renderSurfaceSwapchainImpl->backBuffer[i]) {
7501 /* This could be flagged so that some operations work directly with the front buffer */
7502 FIXME("Attempting to set the renderTarget to the frontBuffer\n");
7504 if (glXMakeCurrent(renderSurfaceSwapchainImpl->display,
7505 renderSurfaceSwapchainImpl->win,
7506 renderSurfaceSwapchainImpl->glCtx) == False) {
7508 TRACE("Error in setting current context: context %p drawable %ld !\n",
7509 implicitSwapchainImpl->glCtx, implicitSwapchainImpl->win);
7511 checkGLcall("glXMakeContextCurrent");
7513 /* Clean up the old context */
7514 IWineD3DDeviceImpl_CleanRender(iface, currentSwapchainImpl);
7516 /* Reapply the stateblock, and set the device not to render to texture */
7517 device_reapply_stateblock(This);
7518 device_render_to_texture(This, FALSE);
7521 /* Offscreen rendering: PBuffers (currently disabled).
7522 * Also note that this path is never reached if FBOs are supported */
7523 } else if (pbuffer_support &&
7524 (cfgs = device_find_fbconfigs(This, implicitSwapchainImpl, RenderSurface)) != NULL) {
7526 /** ********************************************************************
7527 * This is a quickly hacked out implementation of offscreen textures.
7528 * It will work in most cases but there may be problems if the client
7529 * modifies the texture directly, or expects the contents of the rendertarget
7532 * There are some real speed vs compatibility issues here:
7533 * we should really use a new context for every texture, but that eats ram.
7534 * we should also be restoring the texture to the pbuffer but that eats CPU
7535 * we can also 'reuse' the current pbuffer if the size is larger than the requested buffer,
7536 * but if this means reusing the display backbuffer then we need to make sure that
7537 * states are correctly preserved.
7538 * In many cases I would expect that we can 'skip' some functions, such as preserving states,
7539 * and gain a good performance increase at the cost of compatibility.
7540 * I would suggest that, when this is the case, a user configurable flag be made
7541 * available, allowing the user to choose the best emulated experience for them.
7542 *********************************************************************/
7544 XVisualInfo *visinfo;
7545 glContext *newContext;
7547 /* Here were using a shared context model */
7548 if (WINED3D_OK != IWineD3DDeviceImpl_FindGLContext(iface, RenderSurface, &newContext)) {
7549 FIXME("(%p) : Failed to find a context for surface %p\n", iface, RenderSurface);
7552 /* If the context doesn't exist then create a new one */
7553 /* TODO: This should really be part of findGlContext */
7554 if (NULL == newContext->context) {
7559 TRACE("making new buffer\n");
7560 attribs[nAttribs++] = GLX_PBUFFER_WIDTH;
7561 attribs[nAttribs++] = newContext->Width;
7562 attribs[nAttribs++] = GLX_PBUFFER_HEIGHT;
7563 attribs[nAttribs++] = newContext->Height;
7564 attribs[nAttribs++] = None;
7566 newContext->drawable = glXCreatePbuffer(implicitSwapchainImpl->display, cfgs[0], attribs);
7568 /** ****************************************
7569 *GLX1.3 isn't supported by XFree 'yet' until that point ATI emulates pBuffers
7571 * In future releases, we may provide the calls glXCreateNewContext,
7572 * glXQueryDrawable and glXMakeContextCurrent.
7573 * so until then we have to use glXGetVisualFromFBConfig &co..
7574 ********************************************/
7576 visinfo = glXGetVisualFromFBConfig(implicitSwapchainImpl->display, cfgs[0]);
7578 ERR("Error: couldn't get an RGBA, double-buffered visual\n");
7580 newContext->context = glXCreateContext(
7581 implicitSwapchainImpl->display, visinfo,
7582 implicitSwapchainImpl->glCtx, GL_TRUE);
7587 if (NULL == newContext || NULL == newContext->context) {
7588 ERR("(%p) : Failed to find a context for surface %p\n", iface, RenderSurface);
7590 /* Debug logging, (this function leaks), change to a TRACE when the leak is plugged */
7591 if (glXMakeCurrent(implicitSwapchainImpl->display,
7592 newContext->drawable, newContext->context) == False) {
7594 TRACE("Error in setting current context: context %p drawable %ld\n",
7595 newContext->context, newContext->drawable);
7597 checkGLcall("glXMakeContextCurrent");
7599 /* Clean up the old context */
7600 IWineD3DDeviceImpl_CleanRender(iface, currentSwapchainImpl);
7602 /* Reapply stateblock, and set device to render to a texture */
7603 device_reapply_stateblock(This);
7604 device_render_to_texture(This, TRUE);
7606 /* Set the current context of the swapchain to the new context */
7607 implicitSwapchainImpl->drawable = newContext->drawable;
7608 implicitSwapchainImpl->render_ctx = newContext->context;
7612 /* Replace the render target */
7613 tmp = This->renderTarget;
7614 This->renderTarget = RenderSurface;
7615 IWineD3DSurface_AddRef(This->renderTarget);
7616 IWineD3DSurface_Release(tmp);
7618 if (cfgs != NULL) XFree(cfgs);
7619 if (implicitSwapchain != NULL) IWineD3DSwapChain_Release(implicitSwapchain);
7620 if (currentSwapchain != NULL) IWineD3DSwapChain_Release(currentSwapchain);
7621 if (renderSurfaceSwapchain != NULL) IWineD3DSwapChain_Release(renderSurfaceSwapchain);
7627 static HRESULT WINAPI IWineD3DDeviceImpl_SetCursorProperties(IWineD3DDevice* iface, UINT XHotSpot,
7628 UINT YHotSpot, IWineD3DSurface *pCursorBitmap) {
7629 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *) iface;
7630 /* TODO: the use of Impl is deprecated. */
7631 IWineD3DSurfaceImpl * pSur = (IWineD3DSurfaceImpl *) pCursorBitmap;
7633 TRACE("(%p) : Spot Pos(%u,%u)\n", This, XHotSpot, YHotSpot);
7635 /* some basic validation checks */
7636 if(This->cursorTexture) {
7638 glDeleteTextures(1, &This->cursorTexture);
7640 This->cursorTexture = 0;
7644 /* MSDN: Cursor must be A8R8G8B8 */
7645 if (WINED3DFMT_A8R8G8B8 != pSur->resource.format) {
7646 ERR("(%p) : surface(%p) has an invalid format\n", This, pCursorBitmap);
7647 return WINED3DERR_INVALIDCALL;
7650 /* MSDN: Cursor must be smaller than the display mode */
7651 if(pSur->currentDesc.Width > This->ddraw_width ||
7652 pSur->currentDesc.Height > This->ddraw_height) {
7653 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);
7654 return WINED3DERR_INVALIDCALL;
7657 /* TODO: MSDN: Cursor sizes must be a power of 2 */
7658 /* This is to tell our texture code to load a SCRATCH surface. This allows us to use out
7659 * Texture and Blitting code to draw the cursor
7661 pSur->Flags |= SFLAG_FORCELOAD;
7662 IWineD3DSurface_PreLoad(pCursorBitmap);
7663 pSur->Flags &= ~SFLAG_FORCELOAD;
7664 /* Do not store the surface's pointer because the application may release
7665 * it after setting the cursor image. Windows doesn't addref the set surface, so we can't
7666 * do this either without creating circular refcount dependencies. Copy out the gl texture instead.
7668 This->cursorTexture = pSur->glDescription.textureName;
7669 This->cursorWidth = pSur->currentDesc.Width;
7670 This->cursorHeight = pSur->currentDesc.Height;
7671 pSur->glDescription.textureName = 0; /* Prevent the texture from being changed or deleted */
7674 This->xHotSpot = XHotSpot;
7675 This->yHotSpot = YHotSpot;
7679 static void WINAPI IWineD3DDeviceImpl_SetCursorPosition(IWineD3DDevice* iface, int XScreenSpace, int YScreenSpace, DWORD Flags) {
7680 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *) iface;
7681 TRACE("(%p) : SetPos to (%u,%u)\n", This, XScreenSpace, YScreenSpace);
7683 This->xScreenSpace = XScreenSpace;
7684 This->yScreenSpace = YScreenSpace;
7690 static BOOL WINAPI IWineD3DDeviceImpl_ShowCursor(IWineD3DDevice* iface, BOOL bShow) {
7691 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *) iface;
7692 BOOL oldVisible = This->bCursorVisible;
7693 TRACE("(%p) : visible(%d)\n", This, bShow);
7695 if(This->cursorTexture)
7696 This->bCursorVisible = bShow;
7701 static HRESULT WINAPI IWineD3DDeviceImpl_TestCooperativeLevel(IWineD3DDevice* iface) {
7702 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *) iface;
7703 TRACE("(%p) : state (%lu)\n", This, This->state);
7704 /* TODO: Implement wrapping of the WndProc so that mimimize and maxamise can be monitored and the states adjusted. */
7705 switch (This->state) {
7708 case WINED3DERR_DEVICELOST:
7710 ResourceList *resourceList = This->resources;
7711 while (NULL != resourceList) {
7712 if (((IWineD3DResourceImpl *)resourceList->resource)->resource.pool == WINED3DPOOL_DEFAULT /* TODO: IWineD3DResource_GetPool(resourceList->resource)*/)
7713 return WINED3DERR_DEVICENOTRESET;
7714 resourceList = resourceList->next;
7716 return WINED3DERR_DEVICELOST;
7718 case WINED3DERR_DRIVERINTERNALERROR:
7719 return WINED3DERR_DRIVERINTERNALERROR;
7723 return WINED3DERR_DRIVERINTERNALERROR;
7727 static HRESULT WINAPI IWineD3DDeviceImpl_EvictManagedResources(IWineD3DDevice* iface) {
7728 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *) iface;
7729 /** FIXME: Resource tracking needs to be done,
7730 * The closes we can do to this is set the priorities of all managed textures low
7731 * and then reset them.
7732 ***********************************************************/
7733 FIXME("(%p) : stub\n", This);
7737 static HRESULT WINAPI IWineD3DDeviceImpl_Reset(IWineD3DDevice* iface, WINED3DPRESENT_PARAMETERS* pPresentationParameters) {
7738 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *) iface;
7739 /** FIXME: Resource trascking needs to be done.
7740 * in effect this pulls all non only default
7741 * textures out of video memory and deletes all glTextures (glDeleteTextures)
7742 * and should clear down the context and set it up according to pPresentationParameters
7743 ***********************************************************/
7744 FIXME("(%p) : stub\n", This);
7748 static HRESULT WINAPI IWineD3DDeviceImpl_SetDialogBoxMode(IWineD3DDevice *iface, BOOL bEnableDialogs) {
7749 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
7750 /** FIXME: always true at the moment **/
7751 if(bEnableDialogs == FALSE) {
7752 FIXME("(%p) Dialogs cannot be disabled yet\n", This);
7758 static HRESULT WINAPI IWineD3DDeviceImpl_GetCreationParameters(IWineD3DDevice *iface, WINED3DDEVICE_CREATION_PARAMETERS *pParameters) {
7759 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *) iface;
7760 TRACE("(%p) : pParameters %p\n", This, pParameters);
7762 *pParameters = This->createParms;
7766 static void WINAPI IWineD3DDeviceImpl_SetGammaRamp(IWineD3DDevice * iface, UINT iSwapChain, DWORD Flags, CONST WINED3DGAMMARAMP* pRamp) {
7767 IWineD3DSwapChain *swapchain;
7768 HRESULT hrc = WINED3D_OK;
7770 TRACE("Relaying to swapchain\n");
7772 if ((hrc = IWineD3DDeviceImpl_GetSwapChain(iface, iSwapChain, &swapchain)) == WINED3D_OK) {
7773 IWineD3DSwapChain_SetGammaRamp(swapchain, Flags, (WINED3DGAMMARAMP *)pRamp);
7774 IWineD3DSwapChain_Release(swapchain);
7779 static void WINAPI IWineD3DDeviceImpl_GetGammaRamp(IWineD3DDevice *iface, UINT iSwapChain, WINED3DGAMMARAMP* pRamp) {
7780 IWineD3DSwapChain *swapchain;
7781 HRESULT hrc = WINED3D_OK;
7783 TRACE("Relaying to swapchain\n");
7785 if ((hrc = IWineD3DDeviceImpl_GetSwapChain(iface, iSwapChain, &swapchain)) == WINED3D_OK) {
7786 hrc =IWineD3DSwapChain_GetGammaRamp(swapchain, pRamp);
7787 IWineD3DSwapChain_Release(swapchain);
7793 /** ********************************************************
7794 * Notification functions
7795 ** ********************************************************/
7796 /** This function must be called in the release of a resource when ref == 0,
7797 * the contents of resource must still be correct,
7798 * any handels to other resource held by the caller must be closed
7799 * (e.g. a texture should release all held surfaces because telling the device that it's been released.)
7800 *****************************************************/
7801 static void WINAPI IWineD3DDeviceImpl_AddResource(IWineD3DDevice *iface, IWineD3DResource *resource){
7802 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
7803 ResourceList* resourceList;
7805 TRACE("(%p) : resource %p\n", This, resource);
7807 EnterCriticalSection(&resourceStoreCriticalSection);
7809 /* add a new texture to the frot of the linked list */
7810 resourceList = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(ResourceList));
7811 resourceList->resource = resource;
7813 /* Get the old head */
7814 resourceList->next = This->resources;
7816 This->resources = resourceList;
7817 TRACE("Added resource %p with element %p pointing to %p\n", resource, resourceList, resourceList->next);
7820 LeaveCriticalSection(&resourceStoreCriticalSection);
7825 static void WINAPI IWineD3DDeviceImpl_RemoveResource(IWineD3DDevice *iface, IWineD3DResource *resource){
7826 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
7827 ResourceList* resourceList = NULL;
7828 ResourceList* previousResourceList = NULL;
7830 TRACE("(%p) : resource %p\n", This, resource);
7833 EnterCriticalSection(&resourceStoreCriticalSection);
7835 resourceList = This->resources;
7837 while (resourceList != NULL) {
7838 if(resourceList->resource == resource) break;
7839 previousResourceList = resourceList;
7840 resourceList = resourceList->next;
7843 if (resourceList == NULL) {
7844 FIXME("Attempted to remove resource %p that hasn't been stored\n", resource);
7846 LeaveCriticalSection(&resourceStoreCriticalSection);
7850 TRACE("Found resource %p with element %p pointing to %p (previous %p)\n", resourceList->resource, resourceList, resourceList->next, previousResourceList);
7852 /* make sure we don't leave a hole in the list */
7853 if (previousResourceList != NULL) {
7854 previousResourceList->next = resourceList->next;
7856 This->resources = resourceList->next;
7860 LeaveCriticalSection(&resourceStoreCriticalSection);
7866 static void WINAPI IWineD3DDeviceImpl_ResourceReleased(IWineD3DDevice *iface, IWineD3DResource *resource){
7867 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *) iface;
7870 TRACE("(%p) : resource %p\n", This, resource);
7871 switch(IWineD3DResource_GetType(resource)){
7872 case WINED3DRTYPE_SURFACE:
7873 /* TODO: check front and back buffers, rendertargets etc.. possibly swapchains? */
7875 case WINED3DRTYPE_TEXTURE:
7876 case WINED3DRTYPE_CUBETEXTURE:
7877 case WINED3DRTYPE_VOLUMETEXTURE:
7878 for (counter = 0; counter < GL_LIMITS(sampler_stages); counter++) {
7879 if (This->stateBlock != NULL && This->stateBlock->textures[counter] == (IWineD3DBaseTexture *)resource) {
7880 WARN("Texture being released is still by a stateblock, Stage = %u Texture = %p\n", counter, resource);
7881 This->stateBlock->textures[counter] = NULL;
7883 if (This->updateStateBlock != This->stateBlock ){
7884 if (This->updateStateBlock->textures[counter] == (IWineD3DBaseTexture *)resource) {
7885 WARN("Texture being released is still by a stateblock, Stage = %u Texture = %p\n", counter, resource);
7886 This->updateStateBlock->textures[counter] = NULL;
7891 case WINED3DRTYPE_VOLUME:
7892 /* TODO: nothing really? */
7894 case WINED3DRTYPE_VERTEXBUFFER:
7895 /* MSDN: When an application no longer holds a references to this interface, the interface will automatically be freed. */
7898 TRACE("Cleaning up stream pointers\n");
7900 for(streamNumber = 0; streamNumber < MAX_STREAMS; streamNumber ++){
7901 /* FINDOUT: should a warn be generated if were recording and updateStateBlock->streamSource is lost?
7902 FINDOUT: should changes.streamSource[StreamNumber] be set ?
7904 if (This->updateStateBlock != NULL ) { /* ==NULL when device is being destroyed */
7905 if ((IWineD3DResource *)This->updateStateBlock->streamSource[streamNumber] == resource) {
7906 FIXME("Vertex buffer released whlst bound to a state block stream %d\n", streamNumber);
7907 This->updateStateBlock->streamSource[streamNumber] = 0;
7908 /* Set changed flag? */
7911 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) */
7912 if ((IWineD3DResource *)This->stateBlock->streamSource[streamNumber] == resource) {
7913 TRACE("Vertex buffer released whlst bound to a state block stream %d\n", streamNumber);
7914 This->stateBlock->streamSource[streamNumber] = 0;
7917 #if 0 /* TODO: Manage internal tracking properly so that 'this shouldn't happen' */
7918 else { /* This shouldn't happen */
7919 FIXME("Calling application has released the device before relasing all the resources bound to the device\n");
7926 case WINED3DRTYPE_INDEXBUFFER:
7927 /* MSDN: When an application no longer holds a references to this interface, the interface will automatically be freed.*/
7928 if (This->updateStateBlock != NULL ) { /* ==NULL when device is being destroyed */
7929 if (This->updateStateBlock->pIndexData == (IWineD3DIndexBuffer *)resource) {
7930 This->updateStateBlock->pIndexData = NULL;
7933 if (This->stateBlock != NULL ) { /* ==NULL when device is being destroyed */
7934 if (This->stateBlock->pIndexData == (IWineD3DIndexBuffer *)resource) {
7935 This->stateBlock->pIndexData = NULL;
7941 FIXME("(%p) unknown resource type %p %u\n", This, resource, IWineD3DResource_GetType(resource));
7946 /* Remove the resoruce from the resourceStore */
7947 IWineD3DDeviceImpl_RemoveResource(iface, resource);
7949 TRACE("Resource released\n");
7953 /**********************************************************
7954 * IWineD3DDevice VTbl follows
7955 **********************************************************/
7957 const IWineD3DDeviceVtbl IWineD3DDevice_Vtbl =
7959 /*** IUnknown methods ***/
7960 IWineD3DDeviceImpl_QueryInterface,
7961 IWineD3DDeviceImpl_AddRef,
7962 IWineD3DDeviceImpl_Release,
7963 /*** IWineD3DDevice methods ***/
7964 IWineD3DDeviceImpl_GetParent,
7965 /*** Creation methods**/
7966 IWineD3DDeviceImpl_CreateVertexBuffer,
7967 IWineD3DDeviceImpl_CreateIndexBuffer,
7968 IWineD3DDeviceImpl_CreateStateBlock,
7969 IWineD3DDeviceImpl_CreateSurface,
7970 IWineD3DDeviceImpl_CreateTexture,
7971 IWineD3DDeviceImpl_CreateVolumeTexture,
7972 IWineD3DDeviceImpl_CreateVolume,
7973 IWineD3DDeviceImpl_CreateCubeTexture,
7974 IWineD3DDeviceImpl_CreateQuery,
7975 IWineD3DDeviceImpl_CreateAdditionalSwapChain,
7976 IWineD3DDeviceImpl_CreateVertexDeclaration,
7977 IWineD3DDeviceImpl_CreateVertexShader,
7978 IWineD3DDeviceImpl_CreatePixelShader,
7979 IWineD3DDeviceImpl_CreatePalette,
7980 /*** Odd functions **/
7981 IWineD3DDeviceImpl_Init3D,
7982 IWineD3DDeviceImpl_Uninit3D,
7983 IWineD3DDeviceImpl_SetFullscreen,
7984 IWineD3DDeviceImpl_EnumDisplayModes,
7985 IWineD3DDeviceImpl_EvictManagedResources,
7986 IWineD3DDeviceImpl_GetAvailableTextureMem,
7987 IWineD3DDeviceImpl_GetBackBuffer,
7988 IWineD3DDeviceImpl_GetCreationParameters,
7989 IWineD3DDeviceImpl_GetDeviceCaps,
7990 IWineD3DDeviceImpl_GetDirect3D,
7991 IWineD3DDeviceImpl_GetDisplayMode,
7992 IWineD3DDeviceImpl_SetDisplayMode,
7993 IWineD3DDeviceImpl_GetHWND,
7994 IWineD3DDeviceImpl_SetHWND,
7995 IWineD3DDeviceImpl_GetNumberOfSwapChains,
7996 IWineD3DDeviceImpl_GetRasterStatus,
7997 IWineD3DDeviceImpl_GetSwapChain,
7998 IWineD3DDeviceImpl_Reset,
7999 IWineD3DDeviceImpl_SetDialogBoxMode,
8000 IWineD3DDeviceImpl_SetCursorProperties,
8001 IWineD3DDeviceImpl_SetCursorPosition,
8002 IWineD3DDeviceImpl_ShowCursor,
8003 IWineD3DDeviceImpl_TestCooperativeLevel,
8004 /*** Getters and setters **/
8005 IWineD3DDeviceImpl_SetClipPlane,
8006 IWineD3DDeviceImpl_GetClipPlane,
8007 IWineD3DDeviceImpl_SetClipStatus,
8008 IWineD3DDeviceImpl_GetClipStatus,
8009 IWineD3DDeviceImpl_SetCurrentTexturePalette,
8010 IWineD3DDeviceImpl_GetCurrentTexturePalette,
8011 IWineD3DDeviceImpl_SetDepthStencilSurface,
8012 IWineD3DDeviceImpl_GetDepthStencilSurface,
8013 IWineD3DDeviceImpl_SetFVF,
8014 IWineD3DDeviceImpl_GetFVF,
8015 IWineD3DDeviceImpl_SetGammaRamp,
8016 IWineD3DDeviceImpl_GetGammaRamp,
8017 IWineD3DDeviceImpl_SetIndices,
8018 IWineD3DDeviceImpl_GetIndices,
8019 IWineD3DDeviceImpl_SetLight,
8020 IWineD3DDeviceImpl_GetLight,
8021 IWineD3DDeviceImpl_SetLightEnable,
8022 IWineD3DDeviceImpl_GetLightEnable,
8023 IWineD3DDeviceImpl_SetMaterial,
8024 IWineD3DDeviceImpl_GetMaterial,
8025 IWineD3DDeviceImpl_SetNPatchMode,
8026 IWineD3DDeviceImpl_GetNPatchMode,
8027 IWineD3DDeviceImpl_SetPaletteEntries,
8028 IWineD3DDeviceImpl_GetPaletteEntries,
8029 IWineD3DDeviceImpl_SetPixelShader,
8030 IWineD3DDeviceImpl_GetPixelShader,
8031 IWineD3DDeviceImpl_SetPixelShaderConstantB,
8032 IWineD3DDeviceImpl_GetPixelShaderConstantB,
8033 IWineD3DDeviceImpl_SetPixelShaderConstantI,
8034 IWineD3DDeviceImpl_GetPixelShaderConstantI,
8035 IWineD3DDeviceImpl_SetPixelShaderConstantF,
8036 IWineD3DDeviceImpl_GetPixelShaderConstantF,
8037 IWineD3DDeviceImpl_SetRenderState,
8038 IWineD3DDeviceImpl_GetRenderState,
8039 IWineD3DDeviceImpl_SetRenderTarget,
8040 IWineD3DDeviceImpl_GetRenderTarget,
8041 IWineD3DDeviceImpl_SetFrontBackBuffers,
8042 IWineD3DDeviceImpl_SetSamplerState,
8043 IWineD3DDeviceImpl_GetSamplerState,
8044 IWineD3DDeviceImpl_SetScissorRect,
8045 IWineD3DDeviceImpl_GetScissorRect,
8046 IWineD3DDeviceImpl_SetSoftwareVertexProcessing,
8047 IWineD3DDeviceImpl_GetSoftwareVertexProcessing,
8048 IWineD3DDeviceImpl_SetStreamSource,
8049 IWineD3DDeviceImpl_GetStreamSource,
8050 IWineD3DDeviceImpl_SetStreamSourceFreq,
8051 IWineD3DDeviceImpl_GetStreamSourceFreq,
8052 IWineD3DDeviceImpl_SetTexture,
8053 IWineD3DDeviceImpl_GetTexture,
8054 IWineD3DDeviceImpl_SetTextureStageState,
8055 IWineD3DDeviceImpl_GetTextureStageState,
8056 IWineD3DDeviceImpl_SetTransform,
8057 IWineD3DDeviceImpl_GetTransform,
8058 IWineD3DDeviceImpl_SetVertexDeclaration,
8059 IWineD3DDeviceImpl_GetVertexDeclaration,
8060 IWineD3DDeviceImpl_SetVertexShader,
8061 IWineD3DDeviceImpl_GetVertexShader,
8062 IWineD3DDeviceImpl_SetVertexShaderConstantB,
8063 IWineD3DDeviceImpl_GetVertexShaderConstantB,
8064 IWineD3DDeviceImpl_SetVertexShaderConstantI,
8065 IWineD3DDeviceImpl_GetVertexShaderConstantI,
8066 IWineD3DDeviceImpl_SetVertexShaderConstantF,
8067 IWineD3DDeviceImpl_GetVertexShaderConstantF,
8068 IWineD3DDeviceImpl_SetViewport,
8069 IWineD3DDeviceImpl_GetViewport,
8070 IWineD3DDeviceImpl_MultiplyTransform,
8071 IWineD3DDeviceImpl_ValidateDevice,
8072 IWineD3DDeviceImpl_ProcessVertices,
8073 /*** State block ***/
8074 IWineD3DDeviceImpl_BeginStateBlock,
8075 IWineD3DDeviceImpl_EndStateBlock,
8076 /*** Scene management ***/
8077 IWineD3DDeviceImpl_BeginScene,
8078 IWineD3DDeviceImpl_EndScene,
8079 IWineD3DDeviceImpl_Present,
8080 IWineD3DDeviceImpl_Clear,
8082 IWineD3DDeviceImpl_DrawPrimitive,
8083 IWineD3DDeviceImpl_DrawIndexedPrimitive,
8084 IWineD3DDeviceImpl_DrawPrimitiveUP,
8085 IWineD3DDeviceImpl_DrawIndexedPrimitiveUP,
8086 IWineD3DDeviceImpl_DrawPrimitiveStrided,
8087 IWineD3DDeviceImpl_DrawRectPatch,
8088 IWineD3DDeviceImpl_DrawTriPatch,
8089 IWineD3DDeviceImpl_DeletePatch,
8090 IWineD3DDeviceImpl_ColorFill,
8091 IWineD3DDeviceImpl_UpdateTexture,
8092 IWineD3DDeviceImpl_UpdateSurface,
8093 IWineD3DDeviceImpl_CopyRects,
8094 IWineD3DDeviceImpl_StretchRect,
8095 IWineD3DDeviceImpl_GetRenderTargetData,
8096 IWineD3DDeviceImpl_GetFrontBufferData,
8097 /*** Internal use IWineD3DDevice methods ***/
8098 IWineD3DDeviceImpl_SetupTextureStates,
8099 /*** object tracking ***/
8100 IWineD3DDeviceImpl_ResourceReleased
8104 const DWORD SavedPixelStates_R[NUM_SAVEDPIXELSTATES_R] = {
8105 WINED3DRS_ALPHABLENDENABLE ,
8106 WINED3DRS_ALPHAFUNC ,
8107 WINED3DRS_ALPHAREF ,
8108 WINED3DRS_ALPHATESTENABLE ,
8110 WINED3DRS_COLORWRITEENABLE ,
8111 WINED3DRS_DESTBLEND ,
8112 WINED3DRS_DITHERENABLE ,
8113 WINED3DRS_FILLMODE ,
8114 WINED3DRS_FOGDENSITY ,
8116 WINED3DRS_FOGSTART ,
8117 WINED3DRS_LASTPIXEL ,
8118 WINED3DRS_SHADEMODE ,
8119 WINED3DRS_SRCBLEND ,
8120 WINED3DRS_STENCILENABLE ,
8121 WINED3DRS_STENCILFAIL ,
8122 WINED3DRS_STENCILFUNC ,
8123 WINED3DRS_STENCILMASK ,
8124 WINED3DRS_STENCILPASS ,
8125 WINED3DRS_STENCILREF ,
8126 WINED3DRS_STENCILWRITEMASK ,
8127 WINED3DRS_STENCILZFAIL ,
8128 WINED3DRS_TEXTUREFACTOR ,
8139 WINED3DRS_ZWRITEENABLE
8142 const DWORD SavedPixelStates_T[NUM_SAVEDPIXELSTATES_T] = {
8143 WINED3DTSS_ADDRESSW ,
8144 WINED3DTSS_ALPHAARG0 ,
8145 WINED3DTSS_ALPHAARG1 ,
8146 WINED3DTSS_ALPHAARG2 ,
8147 WINED3DTSS_ALPHAOP ,
8148 WINED3DTSS_BUMPENVLOFFSET ,
8149 WINED3DTSS_BUMPENVLSCALE ,
8150 WINED3DTSS_BUMPENVMAT00 ,
8151 WINED3DTSS_BUMPENVMAT01 ,
8152 WINED3DTSS_BUMPENVMAT10 ,
8153 WINED3DTSS_BUMPENVMAT11 ,
8154 WINED3DTSS_COLORARG0 ,
8155 WINED3DTSS_COLORARG1 ,
8156 WINED3DTSS_COLORARG2 ,
8157 WINED3DTSS_COLOROP ,
8158 WINED3DTSS_RESULTARG ,
8159 WINED3DTSS_TEXCOORDINDEX ,
8160 WINED3DTSS_TEXTURETRANSFORMFLAGS
8163 const DWORD SavedPixelStates_S[NUM_SAVEDPIXELSTATES_S] = {
8164 WINED3DSAMP_ADDRESSU ,
8165 WINED3DSAMP_ADDRESSV ,
8166 WINED3DSAMP_ADDRESSW ,
8167 WINED3DSAMP_BORDERCOLOR ,
8168 WINED3DSAMP_MAGFILTER ,
8169 WINED3DSAMP_MINFILTER ,
8170 WINED3DSAMP_MIPFILTER ,
8171 WINED3DSAMP_MIPMAPLODBIAS ,
8172 WINED3DSAMP_MAXMIPLEVEL ,
8173 WINED3DSAMP_MAXANISOTROPY ,
8174 WINED3DSAMP_SRGBTEXTURE ,
8175 WINED3DSAMP_ELEMENTINDEX
8178 const DWORD SavedVertexStates_R[NUM_SAVEDVERTEXSTATES_R] = {
8180 WINED3DRS_AMBIENTMATERIALSOURCE ,
8181 WINED3DRS_CLIPPING ,
8182 WINED3DRS_CLIPPLANEENABLE ,
8183 WINED3DRS_COLORVERTEX ,
8184 WINED3DRS_DIFFUSEMATERIALSOURCE ,
8185 WINED3DRS_EMISSIVEMATERIALSOURCE ,
8186 WINED3DRS_FOGDENSITY ,
8188 WINED3DRS_FOGSTART ,
8189 WINED3DRS_FOGTABLEMODE ,
8190 WINED3DRS_FOGVERTEXMODE ,
8191 WINED3DRS_INDEXEDVERTEXBLENDENABLE ,
8192 WINED3DRS_LIGHTING ,
8193 WINED3DRS_LOCALVIEWER ,
8194 WINED3DRS_MULTISAMPLEANTIALIAS ,
8195 WINED3DRS_MULTISAMPLEMASK ,
8196 WINED3DRS_NORMALIZENORMALS ,
8197 WINED3DRS_PATCHEDGESTYLE ,
8198 WINED3DRS_POINTSCALE_A ,
8199 WINED3DRS_POINTSCALE_B ,
8200 WINED3DRS_POINTSCALE_C ,
8201 WINED3DRS_POINTSCALEENABLE ,
8202 WINED3DRS_POINTSIZE ,
8203 WINED3DRS_POINTSIZE_MAX ,
8204 WINED3DRS_POINTSIZE_MIN ,
8205 WINED3DRS_POINTSPRITEENABLE ,
8206 WINED3DRS_RANGEFOGENABLE ,
8207 WINED3DRS_SPECULARMATERIALSOURCE ,
8208 WINED3DRS_TWEENFACTOR ,
8209 WINED3DRS_VERTEXBLEND
8212 const DWORD SavedVertexStates_T[NUM_SAVEDVERTEXSTATES_T] = {
8213 WINED3DTSS_TEXCOORDINDEX ,
8214 WINED3DTSS_TEXTURETRANSFORMFLAGS
8217 const DWORD SavedVertexStates_S[NUM_SAVEDVERTEXSTATES_S] = {
8218 WINED3DSAMP_DMAPOFFSET