2 * IWineD3DDevice implementation
4 * Copyright 2002 Lionel Ulmer
5 * Copyright 2002-2005 Jason Edmeades
6 * Copyright 2003-2004 Raphael Junqueira
7 * Copyright 2004 Christian Costa
8 * Copyright 2005 Oliver Stieber
9 * Copyright 2006 Stefan Dösinger for CodeWeavers
10 * Copyright 2006 Henri Verbeet
12 * This library is free software; you can redistribute it and/or
13 * modify it under the terms of the GNU Lesser General Public
14 * License as published by the Free Software Foundation; either
15 * version 2.1 of the License, or (at your option) any later version.
17 * This library is distributed in the hope that it will be useful,
18 * but WITHOUT ANY WARRANTY; without even the implied warranty of
19 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
20 * Lesser General Public License for more details.
22 * You should have received a copy of the GNU Lesser General Public
23 * License along with this library; if not, write to the Free Software
24 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
32 #include "wined3d_private.h"
34 WINE_DEFAULT_DEBUG_CHANNEL(d3d);
35 WINE_DECLARE_DEBUG_CHANNEL(d3d_shader);
36 #define GLINFO_LOCATION ((IWineD3DImpl *)(This->wineD3D))->gl_info
38 /* Define the default light parameters as specified by MSDN */
39 const WINED3DLIGHT WINED3D_default_light = {
41 WINED3DLIGHT_DIRECTIONAL, /* Type */
42 { 1.0, 1.0, 1.0, 0.0 }, /* Diffuse r,g,b,a */
43 { 0.0, 0.0, 0.0, 0.0 }, /* Specular r,g,b,a */
44 { 0.0, 0.0, 0.0, 0.0 }, /* Ambient r,g,b,a, */
45 { 0.0, 0.0, 0.0 }, /* Position x,y,z */
46 { 0.0, 0.0, 1.0 }, /* Direction x,y,z */
49 0.0, 0.0, 0.0, /* Attenuation 0,1,2 */
54 /* x11drv GDI escapes */
55 #define X11DRV_ESCAPE 6789
56 enum x11drv_escape_codes
58 X11DRV_GET_DISPLAY, /* get X11 display for a DC */
59 X11DRV_GET_DRAWABLE, /* get current drawable for a DC */
60 X11DRV_GET_FONT, /* get current X font for a DC */
63 /* retrieve the X display to use on a given DC */
64 inline static Display *get_display( HDC hdc )
67 enum x11drv_escape_codes escape = X11DRV_GET_DISPLAY;
69 if (!ExtEscape( hdc, X11DRV_ESCAPE, sizeof(escape), (LPCSTR)&escape,
70 sizeof(display), (LPSTR)&display )) display = NULL;
74 /* allocate one pbuffer per surface */
75 BOOL pbuffer_per_surface = FALSE;
77 /* static function declarations */
78 static void WINAPI IWineD3DDeviceImpl_AddResource(IWineD3DDevice *iface, IWineD3DResource *resource);
80 static void WINAPI IWineD3DDeviceImpl_ApplyTextureUnitState(IWineD3DDevice *iface, DWORD Stage, WINED3DTEXTURESTAGESTATETYPE Type);
82 static void set_depth_stencil_fbo(IWineD3DDevice *iface, IWineD3DSurface *depth_stencil);
85 #define D3DMEMCHECK(object, ppResult) if(NULL == object) { *ppResult = NULL; WARN("Out of memory\n"); return WINED3DERR_OUTOFVIDEOMEMORY;}
87 #define D3DCREATEOBJECTINSTANCE(object, type) { \
88 object=HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(IWineD3D##type##Impl)); \
89 D3DMEMCHECK(object, pp##type); \
90 object->lpVtbl = &IWineD3D##type##_Vtbl; \
91 object->wineD3DDevice = This; \
92 object->parent = parent; \
94 *pp##type = (IWineD3D##type *) object; \
97 #define D3DCREATESHADEROBJECTINSTANCE(object, type) { \
98 object=HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(IWineD3D##type##Impl)); \
99 D3DMEMCHECK(object, pp##type); \
100 object->lpVtbl = &IWineD3D##type##_Vtbl; \
101 object->parent = parent; \
103 object->baseShader.device = (IWineD3DDevice*) This; \
104 *pp##type = (IWineD3D##type *) object; \
107 #define D3DCREATERESOURCEOBJECTINSTANCE(object, type, d3dtype, _size){ \
108 object=HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(IWineD3D##type##Impl)); \
109 D3DMEMCHECK(object, pp##type); \
110 object->lpVtbl = &IWineD3D##type##_Vtbl; \
111 object->resource.wineD3DDevice = This; \
112 object->resource.parent = parent; \
113 object->resource.resourceType = d3dtype; \
114 object->resource.ref = 1; \
115 object->resource.pool = Pool; \
116 object->resource.format = Format; \
117 object->resource.usage = Usage; \
118 object->resource.size = _size; \
119 /* Check that we have enough video ram left */ \
120 if (Pool == WINED3DPOOL_DEFAULT) { \
121 if (IWineD3DDevice_GetAvailableTextureMem(iface) <= _size) { \
122 WARN("Out of 'bogus' video memory\n"); \
123 HeapFree(GetProcessHeap(), 0, object); \
125 return WINED3DERR_OUTOFVIDEOMEMORY; \
127 globalChangeGlRam(_size); \
129 object->resource.allocatedMemory = (0 == _size ? NULL : Pool == WINED3DPOOL_DEFAULT ? NULL : HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, _size)); \
130 if (object->resource.allocatedMemory == NULL && _size != 0 && Pool != WINED3DPOOL_DEFAULT) { \
131 FIXME("Out of memory!\n"); \
132 HeapFree(GetProcessHeap(), 0, object); \
134 return WINED3DERR_OUTOFVIDEOMEMORY; \
136 *pp##type = (IWineD3D##type *) object; \
137 IWineD3DDeviceImpl_AddResource(iface, (IWineD3DResource *)object) ;\
138 TRACE("(%p) : Created resource %p\n", This, object); \
141 #define D3DINITIALIZEBASETEXTURE(_basetexture) { \
142 _basetexture.levels = Levels; \
143 _basetexture.filterType = (Usage & WINED3DUSAGE_AUTOGENMIPMAP) ? WINED3DTEXF_LINEAR : WINED3DTEXF_NONE; \
144 _basetexture.LOD = 0; \
145 _basetexture.dirty = TRUE; \
148 /**********************************************************
149 * Global variable / Constants follow
150 **********************************************************/
151 const float identity[16] = {1,0,0,0, 0,1,0,0, 0,0,1,0, 0,0,0,1}; /* When needed for comparisons */
153 /**********************************************************
154 * Utility functions follow
155 **********************************************************/
156 /* Convert the WINED3DLIGHT properties into equivalent gl lights */
157 static void setup_light(IWineD3DDevice *iface, LONG Index, PLIGHTINFOEL *lightInfo) {
160 float colRGBA[] = {0.0, 0.0, 0.0, 0.0};
161 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
163 /* Light settings are affected by the model view in OpenGL, the View transform in direct3d*/
164 glMatrixMode(GL_MODELVIEW);
166 glLoadMatrixf((float *)&This->stateBlock->transforms[WINED3DTS_VIEW].u.m[0][0]);
169 colRGBA[0] = lightInfo->OriginalParms.Diffuse.r;
170 colRGBA[1] = lightInfo->OriginalParms.Diffuse.g;
171 colRGBA[2] = lightInfo->OriginalParms.Diffuse.b;
172 colRGBA[3] = lightInfo->OriginalParms.Diffuse.a;
173 glLightfv(GL_LIGHT0+Index, GL_DIFFUSE, colRGBA);
174 checkGLcall("glLightfv");
177 colRGBA[0] = lightInfo->OriginalParms.Specular.r;
178 colRGBA[1] = lightInfo->OriginalParms.Specular.g;
179 colRGBA[2] = lightInfo->OriginalParms.Specular.b;
180 colRGBA[3] = lightInfo->OriginalParms.Specular.a;
181 glLightfv(GL_LIGHT0+Index, GL_SPECULAR, colRGBA);
182 checkGLcall("glLightfv");
185 colRGBA[0] = lightInfo->OriginalParms.Ambient.r;
186 colRGBA[1] = lightInfo->OriginalParms.Ambient.g;
187 colRGBA[2] = lightInfo->OriginalParms.Ambient.b;
188 colRGBA[3] = lightInfo->OriginalParms.Ambient.a;
189 glLightfv(GL_LIGHT0+Index, GL_AMBIENT, colRGBA);
190 checkGLcall("glLightfv");
192 /* Attenuation - Are these right? guessing... */
193 glLightf(GL_LIGHT0+Index, GL_CONSTANT_ATTENUATION, lightInfo->OriginalParms.Attenuation0);
194 checkGLcall("glLightf");
195 glLightf(GL_LIGHT0+Index, GL_LINEAR_ATTENUATION, lightInfo->OriginalParms.Attenuation1);
196 checkGLcall("glLightf");
198 if ((lightInfo->OriginalParms.Range *lightInfo->OriginalParms.Range) >= FLT_MIN) {
199 quad_att = 1.4/(lightInfo->OriginalParms.Range *lightInfo->OriginalParms.Range);
201 quad_att = 0; /* 0 or MAX? (0 seems to be ok) */
204 if (quad_att < lightInfo->OriginalParms.Attenuation2) quad_att = lightInfo->OriginalParms.Attenuation2;
205 glLightf(GL_LIGHT0+Index, GL_QUADRATIC_ATTENUATION, quad_att);
206 checkGLcall("glLightf");
208 switch (lightInfo->OriginalParms.Type) {
209 case WINED3DLIGHT_POINT:
211 glLightfv(GL_LIGHT0+Index, GL_POSITION, &lightInfo->lightPosn[0]);
212 checkGLcall("glLightfv");
213 glLightf(GL_LIGHT0 + Index, GL_SPOT_CUTOFF, lightInfo->cutoff);
214 checkGLcall("glLightf");
218 case WINED3DLIGHT_SPOT:
220 glLightfv(GL_LIGHT0+Index, GL_POSITION, &lightInfo->lightPosn[0]);
221 checkGLcall("glLightfv");
223 glLightfv(GL_LIGHT0+Index, GL_SPOT_DIRECTION, &lightInfo->lightDirn[0]);
224 checkGLcall("glLightfv");
225 glLightf(GL_LIGHT0 + Index, GL_SPOT_EXPONENT, lightInfo->exponent);
226 checkGLcall("glLightf");
227 glLightf(GL_LIGHT0 + Index, GL_SPOT_CUTOFF, lightInfo->cutoff);
228 checkGLcall("glLightf");
232 case WINED3DLIGHT_DIRECTIONAL:
234 glLightfv(GL_LIGHT0+Index, GL_POSITION, &lightInfo->lightPosn[0]); /* Note gl uses w position of 0 for direction! */
235 checkGLcall("glLightfv");
236 glLightf(GL_LIGHT0+Index, GL_SPOT_CUTOFF, lightInfo->cutoff);
237 checkGLcall("glLightf");
238 glLightf(GL_LIGHT0+Index, GL_SPOT_EXPONENT, 0.0f);
239 checkGLcall("glLightf");
243 FIXME("Unrecognized light type %d\n", lightInfo->OriginalParms.Type);
246 /* Restore the modelview matrix */
250 /**********************************************************
251 * GLSL helper functions follow
252 **********************************************************/
254 /** Attach a GLSL pixel or vertex shader object to the shader program */
255 static void attach_glsl_shader(IWineD3DDevice *iface, IWineD3DBaseShader* shader) {
257 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
258 GLhandleARB shaderObj = ((IWineD3DBaseShaderImpl*)shader)->baseShader.prgId;
259 if (This->stateBlock->glsl_program && shaderObj != 0) {
260 TRACE_(d3d_shader)("Attaching GLSL shader object %u to program %u\n", shaderObj, This->stateBlock->glsl_program->programId);
261 GL_EXTCALL(glAttachObjectARB(This->stateBlock->glsl_program->programId, shaderObj));
262 checkGLcall("glAttachObjectARB");
266 /** Sets the GLSL program ID for the given pixel and vertex shader combination.
267 * It sets the programId on the current StateBlock (because it should be called
268 * inside of the DrawPrimitive() part of the render loop).
270 * If a program for the given combination does not exist, create one, and store
271 * the program in the list. If it creates a program, it will link the given
274 * We keep the shader programs around on a list because linking
275 * shader objects together is an expensive operation. It's much
276 * faster to loop through a list of pre-compiled & linked programs
277 * each time that the application sets a new pixel or vertex shader
278 * than it is to re-link them together at that time.
280 * The list will be deleted in IWineD3DDevice::Release().
282 void set_glsl_shader_program(IWineD3DDevice *iface) {
284 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
285 IWineD3DPixelShader *pshader = This->stateBlock->pixelShader;
286 IWineD3DVertexShader *vshader = This->stateBlock->vertexShader;
287 struct glsl_shader_prog_link *curLink = NULL;
288 struct glsl_shader_prog_link *newLink = NULL;
289 struct list *ptr = NULL;
290 GLhandleARB programId = 0;
294 ptr = list_head( &This->glsl_shader_progs );
296 /* At least one program exists - see if it matches our ps/vs combination */
297 curLink = LIST_ENTRY( ptr, struct glsl_shader_prog_link, entry );
298 if (vshader == curLink->vertexShader && pshader == curLink->pixelShader) {
299 /* Existing Program found, use it */
300 TRACE_(d3d_shader)("Found existing program (%u) for this vertex/pixel shader combination\n",
302 This->stateBlock->glsl_program = curLink;
305 /* This isn't the entry we need - try the next one */
306 ptr = list_next( &This->glsl_shader_progs, ptr );
309 /* If we get to this point, then no matching program exists, so we create one */
310 programId = GL_EXTCALL(glCreateProgramObjectARB());
311 TRACE_(d3d_shader)("Created new GLSL shader program %u\n", programId);
313 /* Allocate a new link for the list of programs */
314 newLink = HeapAlloc(GetProcessHeap(), 0, sizeof(struct glsl_shader_prog_link));
315 newLink->programId = programId;
316 This->stateBlock->glsl_program = newLink;
318 /* Attach GLSL vshader */
319 if (NULL != vshader && This->vs_selected_mode == SHADER_GLSL) {
321 int max_attribs = 16; /* TODO: Will this always be the case? It is at the moment... */
324 TRACE("Attaching vertex shader to GLSL program\n");
325 attach_glsl_shader(iface, (IWineD3DBaseShader*)vshader);
327 /* Bind vertex attributes to a corresponding index number to match
328 * the same index numbers as ARB_vertex_programs (makes loading
329 * vertex attributes simpler). With this method, we can use the
330 * exact same code to load the attributes later for both ARB and
333 * We have to do this here because we need to know the Program ID
334 * in order to make the bindings work, and it has to be done prior
335 * to linking the GLSL program. */
336 for (i = 0; i < max_attribs; ++i) {
337 snprintf(tmp_name, sizeof(tmp_name), "attrib%i", i);
338 GL_EXTCALL(glBindAttribLocationARB(programId, i, tmp_name));
340 checkGLcall("glBindAttribLocationARB");
341 newLink->vertexShader = vshader;
344 /* Attach GLSL pshader */
345 if (NULL != pshader && This->ps_selected_mode == SHADER_GLSL) {
346 TRACE("Attaching pixel shader to GLSL program\n");
347 attach_glsl_shader(iface, (IWineD3DBaseShader*)pshader);
348 newLink->pixelShader = pshader;
351 /* Link the program */
352 TRACE_(d3d_shader)("Linking GLSL shader program %u\n", programId);
353 GL_EXTCALL(glLinkProgramARB(programId));
354 print_glsl_info_log(&GLINFO_LOCATION, programId);
355 list_add_head( &This->glsl_shader_progs, &newLink->entry);
357 newLink->vuniformF_locations = HeapAlloc(GetProcessHeap(), 0, sizeof(GLhandleARB) * GL_LIMITS(vshader_constantsF));
358 for (i = 0; i < GL_LIMITS(vshader_constantsF); ++i) {
359 snprintf(glsl_name, sizeof(glsl_name), "VC[%i]", i);
360 newLink->vuniformF_locations[i] = GL_EXTCALL(glGetUniformLocationARB(programId, glsl_name));
362 newLink->puniformF_locations = HeapAlloc(GetProcessHeap(), 0, sizeof(GLhandleARB) * GL_LIMITS(pshader_constantsF));
363 for (i = 0; i < GL_LIMITS(pshader_constantsF); ++i) {
364 snprintf(glsl_name, sizeof(glsl_name), "PC[%i]", i);
365 newLink->puniformF_locations[i] = GL_EXTCALL(glGetUniformLocationARB(programId, glsl_name));
371 /** Detach the GLSL pixel or vertex shader object from the shader program */
372 static void detach_glsl_shader(IWineD3DDevice *iface, GLhandleARB shaderObj, GLhandleARB programId) {
374 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
376 if (shaderObj != 0 && programId != 0) {
377 TRACE_(d3d_shader)("Detaching GLSL shader object %u from program %u\n", shaderObj, programId);
378 GL_EXTCALL(glDetachObjectARB(programId, shaderObj));
379 checkGLcall("glDetachObjectARB");
383 /** Delete a GLSL shader program */
384 static void delete_glsl_shader_program(IWineD3DDevice *iface, GLhandleARB obj) {
386 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
389 TRACE_(d3d_shader)("Deleting GLSL shader program %u\n", obj);
390 GL_EXTCALL(glDeleteObjectARB(obj));
391 checkGLcall("glDeleteObjectARB");
395 /** Delete the list of linked programs this shader is associated with.
396 * Also at this point, check to see if there are any objects left attached
397 * to each GLSL program. If not, delete the GLSL program object.
398 * This will be run when a device is released. */
399 static void delete_glsl_shader_list(IWineD3DDevice* iface) {
401 struct list *ptr = NULL;
402 struct glsl_shader_prog_link *curLink = NULL;
403 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
407 GLhandleARB objList[2]; /* There should never be more than 2 objects attached
408 (one pixel shader and one vertex shader at most) */
410 ptr = list_head( &This->glsl_shader_progs );
412 /* First, get the current item,
413 * save the link to the next pointer,
414 * detach and delete shader objects,
415 * then de-allocate the list item's memory */
416 curLink = LIST_ENTRY( ptr, struct glsl_shader_prog_link, entry );
417 ptr = list_next( &This->glsl_shader_progs, ptr );
419 /* See if this object is still attached to the program - it may have been detached already */
420 GL_EXTCALL(glGetAttachedObjectsARB(curLink->programId, 2, &numAttached, objList));
421 TRACE_(d3d_shader)("%i GLSL objects are currently attached to program %u\n", numAttached, curLink->programId);
422 for (i = 0; i < numAttached; i++) {
423 detach_glsl_shader(iface, objList[i], curLink->programId);
426 delete_glsl_shader_program(iface, curLink->programId);
428 /* Free the uniform locations */
429 HeapFree(GetProcessHeap(), 0, curLink->vuniformF_locations);
430 HeapFree(GetProcessHeap(), 0, curLink->puniformF_locations);
432 /* Free the memory for this list item */
433 HeapFree(GetProcessHeap(), 0, curLink);
438 /* Apply the current values to the specified texture stage */
439 static void WINAPI IWineD3DDeviceImpl_SetupTextureStates(IWineD3DDevice *iface, DWORD Sampler, DWORD texture_idx, DWORD Flags) {
440 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
448 /* In addition, IDirect3DDevice9::SetSamplerState will now be used for filtering, tiling,
449 clamping, MIPLOD, etc. This will work for up to 16 samplers.
452 if (Sampler >= GL_LIMITS(sampler_stages)) {
453 FIXME("Trying to set the state of more samplers %d than are supported %d by this openGL implementation\n", Sampler, GL_LIMITS(sampler_stages));
456 VTRACE(("Activating appropriate texture state %d\n", Sampler));
457 if (GL_SUPPORT(ARB_MULTITEXTURE)) {
459 GL_EXTCALL(glActiveTextureARB(GL_TEXTURE0_ARB + texture_idx));
460 checkGLcall("glActiveTextureARB");
462 /* Could we use bindTexture and then apply the states instead of GLACTIVETEXTURE */
463 } else if (Sampler > 0) {
464 FIXME("Program using multiple concurrent textures which this opengl implementation doesn't support\n");
468 /* TODO: change this to a lookup table
469 LOOKUP_TEXTURE_STATES lists all texture states that should be applied.
470 LOOKUP_CONTEXT_SATES list all context applicable states that can be applied
471 etc.... it's a lot cleaner, quicker and possibly easier to maintain than running a switch and setting a skip flag...
472 especially when there are a number of groups of states. */
474 TRACE("-----------------------> Updating the texture at Sampler %d to have new texture state information\n", Sampler);
476 /* 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 */
477 #define APPLY_STATE(_state) IWineD3DDeviceImpl_ApplyTextureUnitState(iface, Sampler, _state)
478 /* these are the only two supported states that need to be applied */
479 APPLY_STATE(WINED3DTSS_TEXCOORDINDEX);
480 APPLY_STATE(WINED3DTSS_TEXTURETRANSFORMFLAGS);
481 #if 0 /* not supported at the moment */
482 APPLY_STATE(WINED3DTSS_BUMPENVMAT00);
483 APPLY_STATE(WINED3DTSS_BUMPENVMAT01);
484 APPLY_STATE(WINED3DTSS_BUMPENVMAT10);
485 APPLY_STATE(WINED3DTSS_BUMPENVMAT11);
486 APPLY_STATE(WINED3DTSS_BUMPENVLSCALE);
487 APPLY_STATE(WINED3DTSS_BUMPENVLOFFSET);
488 APPLY_STATE(WINED3DTSS_RESULTARG);
489 APPLY_STATE(WINED3DTSS_CONSTANT);
491 /* a quick sanity check in case someone forgot to update this function */
492 if (WINED3D_HIGHEST_TEXTURE_STATE > WINED3DTSS_CONSTANT) {
493 FIXME("(%p) : There are more texture states than expected, update device.c to match\n", This);
497 /* apply any sampler states that always need applying */
498 if (GL_SUPPORT(EXT_TEXTURE_LOD_BIAS)) {
499 tmpvalue.d = This->stateBlock->samplerState[Sampler][WINED3DSAMP_MIPMAPLODBIAS];
500 glTexEnvf(GL_TEXTURE_FILTER_CONTROL_EXT,
501 GL_TEXTURE_LOD_BIAS_EXT,
503 checkGLcall("glTexEnvi GL_TEXTURE_LOD_BIAS_EXT ...");
506 D3DCOLORTOGLFLOAT4(This->stateBlock->renderState[WINED3DRS_TEXTUREFACTOR], col);
507 glTexEnvfv(GL_TEXTURE_ENV, GL_TEXTURE_ENV_COLOR, &col[0]);
508 checkGLcall("glTexEnvfv(GL_TEXTURE_ENV, GL_TEXTURE_ENV_COLOR, color);");
510 /* TODO: NV_POINT_SPRITE */
511 if (GL_SUPPORT(ARB_POINT_SPRITE)) {
512 if (This->stateBlock->renderState[WINED3DRS_POINTSPRITEENABLE]) {
513 /* Doesn't work with GL_POINT_SMOOTH on on my ATI 9600, but then ATI drivers are buggered! */
514 glDisable(GL_POINT_SMOOTH);
516 /* Centre the texture on the vertex */
517 VTRACE(("glTexEnvf( GL_POINT_SPRITE_ARB, GL_COORD_REPLACE_ARB, GL_TRUE)\n"));
518 glTexEnvf( GL_POINT_SPRITE_ARB, GL_COORD_REPLACE_ARB, GL_TRUE);
520 VTRACE(("glTexEnvf( GL_POINT_SPRITE_ARB, GL_COORD_REPLACE_ARB, GL_TRUE)\n"));
521 glTexEnvf( GL_POINT_SPRITE_ARB, GL_COORD_REPLACE_ARB, GL_TRUE);
522 checkGLcall("glTexEnvf(...)");
523 VTRACE(("glEnable( GL_POINT_SPRITE_ARB )\n"));
524 glEnable( GL_POINT_SPRITE_ARB );
525 checkGLcall("glEnable(...)");
527 VTRACE(("glDisable( GL_POINT_SPRITE_ARB )\n"));
528 glDisable( GL_POINT_SPRITE_ARB );
529 checkGLcall("glEnable(...)");
533 TRACE("-----------------------> Updated the texture at Sampler %d to have new texture state information\n", Sampler);
536 /**********************************************************
537 * IUnknown parts follows
538 **********************************************************/
540 static HRESULT WINAPI IWineD3DDeviceImpl_QueryInterface(IWineD3DDevice *iface,REFIID riid,LPVOID *ppobj)
542 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
544 TRACE("(%p)->(%s,%p)\n",This,debugstr_guid(riid),ppobj);
545 if (IsEqualGUID(riid, &IID_IUnknown)
546 || IsEqualGUID(riid, &IID_IWineD3DBase)
547 || IsEqualGUID(riid, &IID_IWineD3DDevice)) {
548 IUnknown_AddRef(iface);
553 return E_NOINTERFACE;
556 static ULONG WINAPI IWineD3DDeviceImpl_AddRef(IWineD3DDevice *iface) {
557 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
558 ULONG refCount = InterlockedIncrement(&This->ref);
560 TRACE("(%p) : AddRef increasing from %d\n", This, refCount - 1);
564 static ULONG WINAPI IWineD3DDeviceImpl_Release(IWineD3DDevice *iface) {
565 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
566 ULONG refCount = InterlockedDecrement(&This->ref);
568 TRACE("(%p) : Releasing from %d\n", This, refCount + 1);
572 GL_EXTCALL(glDeleteFramebuffersEXT(1, &This->fbo));
575 /* TODO: Clean up all the surfaces and textures! */
576 /* NOTE: You must release the parent if the object was created via a callback
577 ** ***************************/
579 /* Delete any GLSL shader programs that may exist */
580 if (This->vs_selected_mode == SHADER_GLSL ||
581 This->ps_selected_mode == SHADER_GLSL)
582 delete_glsl_shader_list(iface);
584 /* Release the update stateblock */
585 if(IWineD3DStateBlock_Release((IWineD3DStateBlock *)This->updateStateBlock) > 0){
586 if(This->updateStateBlock != This->stateBlock)
587 FIXME("(%p) Something's still holding the Update stateblock\n",This);
589 This->updateStateBlock = NULL;
590 { /* because were not doing proper internal refcounts releasing the primary state block
591 causes recursion with the extra checks in ResourceReleased, to avoid this we have
592 to set this->stateBlock = NULL; first */
593 IWineD3DStateBlock *stateBlock = (IWineD3DStateBlock *)This->stateBlock;
594 This->stateBlock = NULL;
596 /* Release the stateblock */
597 if(IWineD3DStateBlock_Release(stateBlock) > 0){
598 FIXME("(%p) Something's still holding the Update stateblock\n",This);
602 if (This->resources != NULL ) {
603 FIXME("(%p) Device released with resources still bound, acceptable but unexpected\n", This);
604 dumpResources(This->resources);
608 IWineD3D_Release(This->wineD3D);
609 This->wineD3D = NULL;
610 HeapFree(GetProcessHeap(), 0, This);
611 TRACE("Freed device %p\n", This);
617 /**********************************************************
618 * IWineD3DDevice implementation follows
619 **********************************************************/
620 static HRESULT WINAPI IWineD3DDeviceImpl_GetParent(IWineD3DDevice *iface, IUnknown **pParent) {
621 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
622 *pParent = This->parent;
623 IUnknown_AddRef(This->parent);
627 static void CreateVBO(IWineD3DVertexBufferImpl *object) {
628 IWineD3DDeviceImpl *This = object->resource.wineD3DDevice; /* Needed for GL_EXTCALL */
629 GLenum error, glUsage;
630 DWORD vboUsage = object->resource.usage;
631 if(object->Flags & VBFLAG_VBOCREATEFAIL) {
632 WARN("Creating a vbo failed once, not trying again\n");
636 TRACE("Creating an OpenGL vertex buffer object for IWineD3DVertexBuffer %p Usage(%s)\n", object, debug_d3dusage(vboUsage));
639 /* Make sure that the gl error is cleared. Do not use checkGLcall
640 * here because checkGLcall just prints a fixme and continues. However,
641 * if an error during VBO creation occurs we can fall back to non-vbo operation
642 * with full functionality(but performance loss)
644 while(glGetError() != GL_NO_ERROR);
646 /* Basically the FVF parameter passed to CreateVertexBuffer is no good
647 * It is the FVF set with IWineD3DDevice::SetFVF or the Vertex Declaration set with
648 * IWineD3DDevice::SetVertexDeclaration that decides how the vertices in the buffer
649 * look like. This means that on each DrawPrimitive call the vertex buffer has to be verified
650 * to check if the rhw and color values are in the correct format.
653 GL_EXTCALL(glGenBuffersARB(1, &object->vbo));
654 error = glGetError();
655 if(object->vbo == 0 || error != GL_NO_ERROR) {
656 WARN("Failed to create a VBO with error %d\n", error);
660 GL_EXTCALL(glBindBufferARB(GL_ARRAY_BUFFER_ARB, object->vbo));
661 error = glGetError();
662 if(error != GL_NO_ERROR) {
663 WARN("Failed to bind the VBO, error %d\n", error);
667 /* Transformed vertices are horribly inflexible. If the app specifies an
668 * vertex buffer with transformed vertices in default pool without DYNAMIC
669 * usage assume DYNAMIC usage and print a warning. The app will have to update
670 * the vertices regularily for them to be useful
672 if(((object->fvf & WINED3DFVF_POSITION_MASK) == WINED3DFVF_XYZRHW) &&
673 !(vboUsage & WINED3DUSAGE_DYNAMIC)) {
674 WARN("Application creates a vertex buffer holding transformed vertices which doesn't specify dynamic usage\n");
675 vboUsage |= WINED3DUSAGE_DYNAMIC;
678 /* Don't use static, because dx apps tend to update the buffer
679 * quite often even if they specify 0 usage
681 switch(vboUsage & (D3DUSAGE_WRITEONLY | D3DUSAGE_DYNAMIC) ) {
682 case D3DUSAGE_WRITEONLY | D3DUSAGE_DYNAMIC:
683 TRACE("Gl usage = GL_STREAM_DRAW\n");
684 glUsage = GL_STREAM_DRAW_ARB;
686 case D3DUSAGE_WRITEONLY:
687 TRACE("Gl usage = GL_DYNAMIC_DRAW\n");
688 glUsage = GL_DYNAMIC_DRAW_ARB;
690 case D3DUSAGE_DYNAMIC:
691 TRACE("Gl usage = GL_STREAM_COPY\n");
692 glUsage = GL_STREAM_COPY_ARB;
695 TRACE("Gl usage = GL_DYNAMIC_COPY\n");
696 glUsage = GL_DYNAMIC_COPY_ARB;
700 /* Reserve memory for the buffer. The amount of data won't change
701 * so we are safe with calling glBufferData once with a NULL ptr and
702 * calling glBufferSubData on updates
704 GL_EXTCALL(glBufferDataARB(GL_ARRAY_BUFFER_ARB, object->resource.size, NULL, glUsage));
705 error = glGetError();
706 if(error != GL_NO_ERROR) {
707 WARN("glBufferDataARB failed with error %d\n", error);
715 /* Clean up all vbo init, but continue because we can work without a vbo :-) */
716 FIXME("Failed to create a vertex buffer object. Continuing, but performance issues can occur\n");
717 if(object->vbo) GL_EXTCALL(glDeleteBuffersARB(1, &object->vbo));
719 object->Flags |= VBFLAG_VBOCREATEFAIL;
724 static HRESULT WINAPI IWineD3DDeviceImpl_CreateVertexBuffer(IWineD3DDevice *iface, UINT Size, DWORD Usage,
725 DWORD FVF, WINED3DPOOL Pool, IWineD3DVertexBuffer** ppVertexBuffer, HANDLE *sharedHandle,
727 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
728 IWineD3DVertexBufferImpl *object;
729 WINED3DFORMAT Format = WINED3DFMT_VERTEXDATA; /* Dummy format for now */
730 int dxVersion = ( (IWineD3DImpl *) This->wineD3D)->dxVersion;
732 D3DCREATERESOURCEOBJECTINSTANCE(object, VertexBuffer, WINED3DRTYPE_VERTEXBUFFER, Size)
734 TRACE("(%p) : Size=%d, Usage=%d, FVF=%x, Pool=%d - Memory@%p, Iface@%p\n", This, Size, Usage, FVF, Pool, object->resource.allocatedMemory, object);
735 *ppVertexBuffer = (IWineD3DVertexBuffer *)object;
737 if(Size == 0) return WINED3DERR_INVALIDCALL;
739 if (Pool == WINED3DPOOL_DEFAULT ) { /* Allocate some system memory for now */
740 object->resource.allocatedMemory = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, object->resource.size);
744 /* Observations show that drawStridedSlow is faster on dynamic VBs than converting +
745 * drawStridedFast (half-life 2).
747 * Basically converting the vertices in the buffer is quite expensive, and observations
748 * show that drawStridedSlow is faster than converting + uploading + drawStridedFast.
749 * Therefore do not create a VBO for WINED3DUSAGE_DYNAMIC buffers.
751 * Direct3D7 has another problem: Its vertexbuffer api doesn't offer a way to specify
752 * the range of vertices being locked, so each lock will require the whole buffer to be transformed.
753 * Moreover geometry data in dx7 is quite simple, so drawStridedSlow isn't a big hit. A plus
754 * is that the vertex buffers fvf can be trusted in dx7. So only create non-converted vbos for
756 * There is a IDirect3DVertexBuffer7::Optimize call after which the buffer can't be locked any
757 * more. In this call we can convert dx7 buffers too.
759 conv = ((FVF & WINED3DFVF_POSITION_MASK) == WINED3DFVF_XYZRHW ) || (FVF & (WINED3DFVF_DIFFUSE | WINED3DFVF_SPECULAR));
760 if( GL_SUPPORT(ARB_VERTEX_BUFFER_OBJECT) && Pool != WINED3DPOOL_SYSTEMMEM && !(Usage & WINED3DUSAGE_DYNAMIC) &&
761 (dxVersion > 7 || !conv) ) {
764 /* DX7 buffers can be locked directly into the VBO (no conversion, see above */
765 if(dxVersion == 7 && object->vbo) {
766 HeapFree(GetProcessHeap(), 0, object->resource.allocatedMemory);
767 object->resource.allocatedMemory = NULL;
774 static HRESULT WINAPI IWineD3DDeviceImpl_CreateIndexBuffer(IWineD3DDevice *iface, UINT Length, DWORD Usage,
775 WINED3DFORMAT Format, WINED3DPOOL Pool, IWineD3DIndexBuffer** ppIndexBuffer,
776 HANDLE *sharedHandle, IUnknown *parent) {
777 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
778 IWineD3DIndexBufferImpl *object;
779 TRACE("(%p) Creating index buffer\n", This);
781 /* Allocate the storage for the device */
782 D3DCREATERESOURCEOBJECTINSTANCE(object,IndexBuffer,WINED3DRTYPE_INDEXBUFFER, Length)
785 if (Pool == WINED3DPOOL_DEFAULT ) { /* Allocate some system memory for now */
786 object->resource.allocatedMemory = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,object->resource.size);
789 TRACE("(%p) : Len=%d, Use=%x, Format=(%u,%s), Pool=%d - Memory@%p, Iface@%p\n", This, Length, Usage, Format,
790 debug_d3dformat(Format), Pool, object, object->resource.allocatedMemory);
791 *ppIndexBuffer = (IWineD3DIndexBuffer *) object;
796 static HRESULT WINAPI IWineD3DDeviceImpl_CreateStateBlock(IWineD3DDevice* iface, WINED3DSTATEBLOCKTYPE Type, IWineD3DStateBlock** ppStateBlock, IUnknown *parent) {
798 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
799 IWineD3DStateBlockImpl *object;
803 D3DCREATEOBJECTINSTANCE(object, StateBlock)
804 object->blockType = Type;
806 /* Special case - Used during initialization to produce a placeholder stateblock
807 so other functions called can update a state block */
808 if (Type == WINED3DSBT_INIT) {
809 /* Don't bother increasing the reference count otherwise a device will never
810 be freed due to circular dependencies */
814 temp_result = allocate_shader_constants(object);
815 if (WINED3D_OK != temp_result)
818 /* Otherwise, might as well set the whole state block to the appropriate values */
819 if (This->stateBlock != NULL)
820 stateblock_copy((IWineD3DStateBlock*) object, (IWineD3DStateBlock*) This->stateBlock);
822 memset(object->streamFreq, 1, sizeof(object->streamFreq));
824 /* Reset the ref and type after kludging it */
825 object->wineD3DDevice = This;
827 object->blockType = Type;
829 TRACE("Updating changed flags appropriate for type %d\n", Type);
831 if (Type == WINED3DSBT_ALL) {
833 TRACE("ALL => Pretend everything has changed\n");
834 stateblock_savedstates_set((IWineD3DStateBlock*) object, &object->changed, TRUE);
836 } else if (Type == WINED3DSBT_PIXELSTATE) {
838 TRACE("PIXELSTATE => Pretend all pixel shates have changed\n");
839 stateblock_savedstates_set((IWineD3DStateBlock*) object, &object->changed, FALSE);
841 object->changed.pixelShader = TRUE;
843 /* Pixel Shader Constants */
844 for (i = 0; i < GL_LIMITS(pshader_constantsF); ++i)
845 object->changed.pixelShaderConstantsF[i] = TRUE;
846 for (i = 0; i < MAX_CONST_B; ++i)
847 object->changed.pixelShaderConstantsB[i] = TRUE;
848 for (i = 0; i < MAX_CONST_I; ++i)
849 object->changed.pixelShaderConstantsI[i] = TRUE;
851 for (i = 0; i < NUM_SAVEDPIXELSTATES_R; i++) {
852 object->changed.renderState[SavedPixelStates_R[i]] = TRUE;
854 for (j = 0; j < GL_LIMITS(texture_stages); j++) {
855 for (i = 0; i < NUM_SAVEDPIXELSTATES_T; i++) {
856 object->changed.textureState[j][SavedPixelStates_T[i]] = TRUE;
859 for (j = 0 ; j < 16; j++) {
860 for (i =0; i < NUM_SAVEDPIXELSTATES_S;i++) {
862 object->changed.samplerState[j][SavedPixelStates_S[i]] = TRUE;
866 } else if (Type == WINED3DSBT_VERTEXSTATE) {
868 TRACE("VERTEXSTATE => Pretend all vertex shates have changed\n");
869 stateblock_savedstates_set((IWineD3DStateBlock*) object, &object->changed, FALSE);
871 object->changed.vertexShader = TRUE;
873 /* Vertex Shader Constants */
874 for (i = 0; i < GL_LIMITS(vshader_constantsF); ++i)
875 object->changed.vertexShaderConstantsF[i] = TRUE;
876 for (i = 0; i < MAX_CONST_B; ++i)
877 object->changed.vertexShaderConstantsB[i] = TRUE;
878 for (i = 0; i < MAX_CONST_I; ++i)
879 object->changed.vertexShaderConstantsI[i] = TRUE;
881 for (i = 0; i < NUM_SAVEDVERTEXSTATES_R; i++) {
882 object->changed.renderState[SavedVertexStates_R[i]] = TRUE;
884 for (j = 0; j < GL_LIMITS(texture_stages); j++) {
885 for (i = 0; i < NUM_SAVEDVERTEXSTATES_T; i++) {
886 object->changed.textureState[j][SavedVertexStates_T[i]] = TRUE;
889 for (j = 0 ; j < 16; j++){
890 for (i =0; i < NUM_SAVEDVERTEXSTATES_S;i++) {
891 object->changed.samplerState[j][SavedVertexStates_S[i]] = TRUE;
895 /* Duplicate light chain */
897 PLIGHTINFOEL *src = NULL;
898 PLIGHTINFOEL *dst = NULL;
899 PLIGHTINFOEL *newEl = NULL;
900 src = This->stateBlock->lights;
901 object->lights = NULL;
905 newEl = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(PLIGHTINFOEL));
906 if (newEl == NULL) return WINED3DERR_OUTOFVIDEOMEMORY;
907 memcpy(newEl, src, sizeof(PLIGHTINFOEL));
909 newEl->changed = TRUE;
910 newEl->enabledChanged = TRUE;
912 object->lights = newEl;
923 FIXME("Unrecognized state block type %d\n", Type);
926 TRACE("(%p) returning token (ptr to stateblock) of %p\n", This, object);
931 /* ************************************
933 [in] Render targets are not lockable unless the application specifies TRUE for Lockable. Note that lockable render targets reduce performance on some graphics hardware.
936 [in] Set this flag to TRUE to enable z-buffer discarding, and FALSE otherwise.
938 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.
940 ******************************** */
942 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) {
943 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
944 IWineD3DSurfaceImpl *object; /*NOTE: impl ref allowed since this is a create function */
945 unsigned int pow2Width, pow2Height;
946 unsigned int Size = 1;
947 const PixelFormatDesc *tableEntry = getFormatDescEntry(Format);
948 TRACE("(%p) Create surface\n",This);
950 /** FIXME: Check ranges on the inputs are valid
953 * [in] Quality level. The valid range is between zero and one less than the level
954 * returned by pQualityLevels used by IDirect3D9::CheckDeviceMultiSampleType.
955 * Passing a larger value returns the error WINED3DERR_INVALIDCALL. The MultisampleQuality
956 * values of paired render targets, depth stencil surfaces, and the MultiSample type
958 *******************************/
963 * [in] Set this flag to TRUE to enable z-buffer discarding, and FALSE otherwise.
965 * If this flag is set, the contents of the depth stencil buffer will be
966 * invalid after calling either IDirect3DDevice9::Present or * IDirect3DDevice9::SetDepthStencilSurface
967 * with a different depth surface.
969 *This flag has the same behavior as the constant, D3DPRESENTFLAG_DISCARD_DEPTHSTENCIL, in D3DPRESENTFLAG.
970 ***************************/
972 if(MultisampleQuality < 0) {
973 FIXME("Invalid multisample level %d\n", MultisampleQuality);
974 return WINED3DERR_INVALIDCALL; /* TODO: Check that this is the case! */
977 if(MultisampleQuality > 0) {
978 FIXME("MultisampleQuality set to %d, substituting 0\n", MultisampleQuality);
979 MultisampleQuality=0;
982 /** FIXME: Check that the format is supported
984 *******************************/
986 /* Non-power2 support */
987 if (wined3d_settings.nonpower2_mode == NP2_NATIVE) {
991 /* Find the nearest pow2 match */
992 pow2Width = pow2Height = 1;
993 while (pow2Width < Width) pow2Width <<= 1;
994 while (pow2Height < Height) pow2Height <<= 1;
997 if (pow2Width > Width || pow2Height > Height) {
998 /** TODO: add support for non power two compressed textures (OpenGL 2 provices support for * non-power-two textures gratis) **/
999 if (Format == WINED3DFMT_DXT1 || Format == WINED3DFMT_DXT2 || Format == WINED3DFMT_DXT3
1000 || Format == WINED3DFMT_DXT4 || Format == WINED3DFMT_DXT5) {
1001 FIXME("(%p) Compressed non-power-two textures are not supported w(%d) h(%d)\n",
1002 This, Width, Height);
1003 return WINED3DERR_NOTAVAILABLE;
1007 /** DXTn mipmaps use the same number of 'levels' down to eg. 8x1, but since
1008 * it is based around 4x4 pixel blocks it requires padding, so allocate enough
1010 *********************************/
1011 if (WINED3DFMT_UNKNOWN == Format) {
1013 } else if (Format == WINED3DFMT_DXT1) {
1014 /* DXT1 is half byte per pixel */
1015 Size = ((max(pow2Width,4) * tableEntry->bpp) * max(pow2Height,4)) >> 1;
1017 } else if (Format == WINED3DFMT_DXT2 || Format == WINED3DFMT_DXT3 ||
1018 Format == WINED3DFMT_DXT4 || Format == WINED3DFMT_DXT5) {
1019 Size = ((max(pow2Width,4) * tableEntry->bpp) * max(pow2Height,4));
1021 /* The pitch is a multiple of 4 bytes */
1022 Size = ((pow2Width * tableEntry->bpp) + SURFACE_ALIGNMENT - 1) & ~(SURFACE_ALIGNMENT - 1);
1026 /** Create and initialise the surface resource **/
1027 D3DCREATERESOURCEOBJECTINSTANCE(object,Surface,WINED3DRTYPE_SURFACE, Size)
1028 /* "Standalone" surface */
1029 IWineD3DSurface_SetContainer((IWineD3DSurface *)object, NULL);
1031 object->currentDesc.Width = Width;
1032 object->currentDesc.Height = Height;
1033 object->currentDesc.MultiSampleType = MultiSample;
1034 object->currentDesc.MultiSampleQuality = MultisampleQuality;
1036 /* Setup some glformat defaults */
1037 object->glDescription.glFormat = tableEntry->glFormat;
1038 object->glDescription.glFormatInternal = tableEntry->glInternal;
1039 object->glDescription.glType = tableEntry->glType;
1041 object->glDescription.textureName = 0;
1042 object->glDescription.level = Level;
1043 object->glDescription.target = GL_TEXTURE_2D;
1046 object->pow2Width = pow2Width;
1047 object->pow2Height = pow2Height;
1050 object->Flags = 0; /* We start without flags set */
1051 object->Flags |= (pow2Width != Width || pow2Height != Height) ? SFLAG_NONPOW2 : 0;
1052 object->Flags |= Discard ? SFLAG_DISCARD : 0;
1053 object->Flags |= (WINED3DFMT_D16_LOCKABLE == Format) ? SFLAG_LOCKABLE : 0;
1054 object->Flags |= Lockable ? SFLAG_LOCKABLE : 0;
1057 if (WINED3DFMT_UNKNOWN != Format) {
1058 object->bytesPerPixel = tableEntry->bpp;
1059 object->pow2Size = ((pow2Width * object->bytesPerPixel) + SURFACE_ALIGNMENT - 1) & ~(SURFACE_ALIGNMENT - 1);
1060 object->pow2Size *= pow2Height;
1062 object->bytesPerPixel = 0;
1063 object->pow2Size = 0;
1066 /** TODO: change this into a texture transform matrix so that it's processed in hardware **/
1068 TRACE("Pool %d %d %d %d\n",Pool, WINED3DPOOL_DEFAULT, WINED3DPOOL_MANAGED, WINED3DPOOL_SYSTEMMEM);
1070 /** Quick lockable sanity check TODO: remove this after surfaces, usage and lockability have been debugged properly
1071 * this function is too deep to need to care about things like this.
1072 * Levels need to be checked too, and possibly Type since they all affect what can be done.
1073 * ****************************************/
1075 case WINED3DPOOL_SCRATCH:
1077 FIXME("Create surface called with a pool of SCRATCH and a Lockable of FALSE \
1078 which are mutually exclusive, setting lockable to true\n");
1081 case WINED3DPOOL_SYSTEMMEM:
1082 if(!Lockable) FIXME("Create surface called with a pool of SYSTEMMEM and a Lockable of FALSE, \
1083 this is acceptable but unexpected (I can't know how the surface can be usable!)\n");
1084 case WINED3DPOOL_MANAGED:
1085 if(Usage == WINED3DUSAGE_DYNAMIC) FIXME("Create surface called with a pool of MANAGED and a \
1086 Usage of DYNAMIC which are mutually exclusive, not doing \
1087 anything just telling you.\n");
1089 case WINED3DPOOL_DEFAULT: /*TODO: Create offscreen plain can cause this check to fail..., find out if it should */
1090 if(!(Usage & WINED3DUSAGE_DYNAMIC) && !(Usage & WINED3DUSAGE_RENDERTARGET)
1091 && !(Usage && WINED3DUSAGE_DEPTHSTENCIL ) && Lockable)
1092 WARN("Creating a surface with a POOL of DEFAULT with Lockable true, that doesn't specify DYNAMIC usage.\n");
1095 FIXME("(%p) Unknown pool %d\n", This, Pool);
1099 if (Usage & WINED3DUSAGE_RENDERTARGET && Pool != WINED3DPOOL_DEFAULT) {
1100 FIXME("Trying to create a render target that isn't in the default pool\n");
1103 /* mark the texture as dirty so that it gets loaded first time around*/
1104 IWineD3DSurface_AddDirtyRect(*ppSurface, NULL);
1105 TRACE("(%p) : w(%d) h(%d) fmt(%d,%s) lockable(%d) surf@%p, surfmem@%p, %d bytes\n",
1106 This, Width, Height, Format, debug_d3dformat(Format),
1107 (WINED3DFMT_D16_LOCKABLE == Format), *ppSurface, object->resource.allocatedMemory, object->resource.size);
1109 /* Store the DirectDraw primary surface. This is the first rendertarget surface created */
1110 if( (Usage & WINED3DUSAGE_RENDERTARGET) && (!This->ddraw_primary) )
1111 This->ddraw_primary = (IWineD3DSurface *) object;
1113 /* Look at the implementation and set the correct Vtable */
1115 case SURFACE_OPENGL:
1116 /* Nothing to do, it's set already */
1120 object->lpVtbl = &IWineGDISurface_Vtbl;
1124 /* To be sure to catch this */
1125 ERR("Unknown requested surface implementation %d!\n", Impl);
1126 IWineD3DSurface_Release((IWineD3DSurface *) object);
1127 return WINED3DERR_INVALIDCALL;
1130 /* Call the private setup routine */
1131 return IWineD3DSurface_PrivateSetup( (IWineD3DSurface *) object );
1135 static HRESULT WINAPI IWineD3DDeviceImpl_CreateTexture(IWineD3DDevice *iface, UINT Width, UINT Height, UINT Levels,
1136 DWORD Usage, WINED3DFORMAT Format, WINED3DPOOL Pool,
1137 IWineD3DTexture** ppTexture, HANDLE* pSharedHandle, IUnknown *parent,
1138 D3DCB_CREATESURFACEFN D3DCB_CreateSurface) {
1140 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
1141 IWineD3DTextureImpl *object;
1146 unsigned int pow2Width;
1147 unsigned int pow2Height;
1150 TRACE("(%p) : Width %d, Height %d, Levels %d, Usage %#x\n", This, Width, Height, Levels, Usage);
1151 TRACE("Format %#x (%s), Pool %#x, ppTexture %p, pSharedHandle %p, parent %p\n",
1152 Format, debug_d3dformat(Format), Pool, ppTexture, pSharedHandle, parent);
1154 /* TODO: It should only be possible to create textures for formats
1155 that are reported as supported */
1156 if (WINED3DFMT_UNKNOWN >= Format) {
1157 WARN("(%p) : Texture cannot be created with a format of WINED3DFMT_UNKNOWN\n", This);
1158 return WINED3DERR_INVALIDCALL;
1161 D3DCREATERESOURCEOBJECTINSTANCE(object, Texture, WINED3DRTYPE_TEXTURE, 0);
1162 D3DINITIALIZEBASETEXTURE(object->baseTexture);
1163 object->width = Width;
1164 object->height = Height;
1166 /** Non-power2 support **/
1167 if (wined3d_settings.nonpower2_mode == NP2_NATIVE) {
1169 pow2Height = Height;
1171 /* Find the nearest pow2 match */
1172 pow2Width = pow2Height = 1;
1173 while (pow2Width < Width) pow2Width <<= 1;
1174 while (pow2Height < Height) pow2Height <<= 1;
1177 /** FIXME: add support for real non-power-two if it's provided by the video card **/
1178 /* Precalculated scaling for 'faked' non power of two texture coords */
1179 object->pow2scalingFactorX = (((float)Width) / ((float)pow2Width));
1180 object->pow2scalingFactorY = (((float)Height) / ((float)pow2Height));
1181 TRACE(" xf(%f) yf(%f)\n", object->pow2scalingFactorX, object->pow2scalingFactorY);
1183 /* Calculate levels for mip mapping */
1185 TRACE("calculating levels %d\n", object->baseTexture.levels);
1186 object->baseTexture.levels++;
1189 while (tmpW > 1 || tmpH > 1) {
1190 tmpW = max(1, tmpW >> 1);
1191 tmpH = max(1, tmpH >> 1);
1192 object->baseTexture.levels++;
1194 TRACE("Calculated levels = %d\n", object->baseTexture.levels);
1197 /* Generate all the surfaces */
1200 for (i = 0; i < object->baseTexture.levels; i++)
1202 /* use the callback to create the texture surface */
1203 hr = D3DCB_CreateSurface(This->parent, parent, tmpW, tmpH, Format, Usage, Pool, i, &object->surfaces[i],NULL);
1204 if (hr!= WINED3D_OK || ( (IWineD3DSurfaceImpl *) object->surfaces[i])->Flags & SFLAG_OVERSIZE) {
1205 FIXME("Failed to create surface %p\n", object);
1207 object->surfaces[i] = NULL;
1208 IWineD3DTexture_Release((IWineD3DTexture *)object);
1214 IWineD3DSurface_SetContainer(object->surfaces[i], (IWineD3DBase *)object);
1215 TRACE("Created surface level %d @ %p\n", i, object->surfaces[i]);
1216 /* calculate the next mipmap level */
1217 tmpW = max(1, tmpW >> 1);
1218 tmpH = max(1, tmpH >> 1);
1221 TRACE("(%p) : Created texture %p\n", This, object);
1225 static HRESULT WINAPI IWineD3DDeviceImpl_CreateVolumeTexture(IWineD3DDevice *iface,
1226 UINT Width, UINT Height, UINT Depth,
1227 UINT Levels, DWORD Usage,
1228 WINED3DFORMAT Format, WINED3DPOOL Pool,
1229 IWineD3DVolumeTexture **ppVolumeTexture,
1230 HANDLE *pSharedHandle, IUnknown *parent,
1231 D3DCB_CREATEVOLUMEFN D3DCB_CreateVolume) {
1233 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
1234 IWineD3DVolumeTextureImpl *object;
1240 /* TODO: It should only be possible to create textures for formats
1241 that are reported as supported */
1242 if (WINED3DFMT_UNKNOWN >= Format) {
1243 WARN("(%p) : Texture cannot be created with a format of WINED3DFMT_UNKNOWN\n", This);
1244 return WINED3DERR_INVALIDCALL;
1247 D3DCREATERESOURCEOBJECTINSTANCE(object, VolumeTexture, WINED3DRTYPE_VOLUMETEXTURE, 0);
1248 D3DINITIALIZEBASETEXTURE(object->baseTexture);
1250 TRACE("(%p) : W(%d) H(%d) D(%d), Lvl(%d) Usage(%d), Fmt(%u,%s), Pool(%s)\n", This, Width, Height,
1251 Depth, Levels, Usage, Format, debug_d3dformat(Format), debug_d3dpool(Pool));
1253 object->width = Width;
1254 object->height = Height;
1255 object->depth = Depth;
1257 /* Calculate levels for mip mapping */
1259 object->baseTexture.levels++;
1263 while (tmpW > 1 || tmpH > 1 || tmpD > 1) {
1264 tmpW = max(1, tmpW >> 1);
1265 tmpH = max(1, tmpH >> 1);
1266 tmpD = max(1, tmpD >> 1);
1267 object->baseTexture.levels++;
1269 TRACE("Calculated levels = %d\n", object->baseTexture.levels);
1272 /* Generate all the surfaces */
1277 for (i = 0; i < object->baseTexture.levels; i++)
1279 /* Create the volume */
1280 D3DCB_CreateVolume(This->parent, parent, Width, Height, Depth, Format, Pool, Usage,
1281 (IWineD3DVolume **)&object->volumes[i], pSharedHandle);
1283 /* Set its container to this object */
1284 IWineD3DVolume_SetContainer(object->volumes[i], (IWineD3DBase *)object);
1286 /* calcualte the next mipmap level */
1287 tmpW = max(1, tmpW >> 1);
1288 tmpH = max(1, tmpH >> 1);
1289 tmpD = max(1, tmpD >> 1);
1292 *ppVolumeTexture = (IWineD3DVolumeTexture *) object;
1293 TRACE("(%p) : Created volume texture %p\n", This, object);
1297 static HRESULT WINAPI IWineD3DDeviceImpl_CreateVolume(IWineD3DDevice *iface,
1298 UINT Width, UINT Height, UINT Depth,
1300 WINED3DFORMAT Format, WINED3DPOOL Pool,
1301 IWineD3DVolume** ppVolume,
1302 HANDLE* pSharedHandle, IUnknown *parent) {
1304 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
1305 IWineD3DVolumeImpl *object; /** NOTE: impl ref allowed since this is a create function **/
1306 const PixelFormatDesc *formatDesc = getFormatDescEntry(Format);
1308 D3DCREATERESOURCEOBJECTINSTANCE(object, Volume, WINED3DRTYPE_VOLUME, ((Width * formatDesc->bpp) * Height * Depth))
1310 TRACE("(%p) : W(%d) H(%d) D(%d), Usage(%d), Fmt(%u,%s), Pool(%s)\n", This, Width, Height,
1311 Depth, Usage, Format, debug_d3dformat(Format), debug_d3dpool(Pool));
1313 object->currentDesc.Width = Width;
1314 object->currentDesc.Height = Height;
1315 object->currentDesc.Depth = Depth;
1316 object->bytesPerPixel = formatDesc->bpp;
1318 /** Note: Volume textures cannot be dxtn, hence no need to check here **/
1319 object->lockable = TRUE;
1320 object->locked = FALSE;
1321 memset(&object->lockedBox, 0, sizeof(WINED3DBOX));
1322 object->dirty = TRUE;
1324 return IWineD3DVolume_AddDirtyBox((IWineD3DVolume *) object, NULL);
1327 static HRESULT WINAPI IWineD3DDeviceImpl_CreateCubeTexture(IWineD3DDevice *iface, UINT EdgeLength,
1328 UINT Levels, DWORD Usage,
1329 WINED3DFORMAT Format, WINED3DPOOL Pool,
1330 IWineD3DCubeTexture **ppCubeTexture,
1331 HANDLE *pSharedHandle, IUnknown *parent,
1332 D3DCB_CREATESURFACEFN D3DCB_CreateSurface) {
1334 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
1335 IWineD3DCubeTextureImpl *object; /** NOTE: impl ref allowed since this is a create function **/
1339 unsigned int pow2EdgeLength = EdgeLength;
1341 /* TODO: It should only be possible to create textures for formats
1342 that are reported as supported */
1343 if (WINED3DFMT_UNKNOWN >= Format) {
1344 WARN("(%p) : Texture cannot be created with a format of WINED3DFMT_UNKNOWN\n", This);
1345 return WINED3DERR_INVALIDCALL;
1348 D3DCREATERESOURCEOBJECTINSTANCE(object, CubeTexture, WINED3DRTYPE_CUBETEXTURE, 0);
1349 D3DINITIALIZEBASETEXTURE(object->baseTexture);
1351 TRACE("(%p) Create Cube Texture\n", This);
1353 /** Non-power2 support **/
1355 /* Find the nearest pow2 match */
1357 while (pow2EdgeLength < EdgeLength) pow2EdgeLength <<= 1;
1359 object->edgeLength = EdgeLength;
1360 /* TODO: support for native non-power 2 */
1361 /* Precalculated scaling for 'faked' non power of two texture coords */
1362 object->pow2scalingFactor = ((float)EdgeLength) / ((float)pow2EdgeLength);
1364 /* Calculate levels for mip mapping */
1366 object->baseTexture.levels++;
1369 tmpW = max(1, tmpW >> 1);
1370 object->baseTexture.levels++;
1372 TRACE("Calculated levels = %d\n", object->baseTexture.levels);
1375 /* Generate all the surfaces */
1377 for (i = 0; i < object->baseTexture.levels; i++) {
1379 /* Create the 6 faces */
1380 for (j = 0; j < 6; j++) {
1382 hr=D3DCB_CreateSurface(This->parent, parent, tmpW, tmpW, Format, Usage, Pool,
1383 i /* Level */, &object->surfaces[j][i],pSharedHandle);
1385 if(hr!= WINED3D_OK) {
1389 for (l = 0; l < j; l++) {
1390 IWineD3DSurface_Release(object->surfaces[j][i]);
1392 for (k = 0; k < i; k++) {
1393 for (l = 0; l < 6; l++) {
1394 IWineD3DSurface_Release(object->surfaces[l][j]);
1398 FIXME("(%p) Failed to create surface\n",object);
1399 HeapFree(GetProcessHeap(),0,object);
1400 *ppCubeTexture = NULL;
1403 IWineD3DSurface_SetContainer(object->surfaces[j][i], (IWineD3DBase *)object);
1404 TRACE("Created surface level %d @ %p,\n", i, object->surfaces[j][i]);
1406 tmpW = max(1, tmpW >> 1);
1409 TRACE("(%p) : Created Cube Texture %p\n", This, object);
1410 *ppCubeTexture = (IWineD3DCubeTexture *) object;
1414 static HRESULT WINAPI IWineD3DDeviceImpl_CreateQuery(IWineD3DDevice *iface, WINED3DQUERYTYPE Type, IWineD3DQuery **ppQuery, IUnknown* parent) {
1415 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
1416 IWineD3DQueryImpl *object; /*NOTE: impl ref allowed since this is a create function */
1418 if (NULL == ppQuery) {
1419 /* Just a check to see if we support this type of query */
1420 HRESULT hr = WINED3DERR_NOTAVAILABLE;
1422 case WINED3DQUERYTYPE_OCCLUSION:
1423 TRACE("(%p) occlusion query\n", This);
1424 if (GL_SUPPORT(ARB_OCCLUSION_QUERY))
1427 WARN("Unsupported in local OpenGL implementation: ARB_OCCLUSION_QUERY/NV_OCCLUSION_QUERY\n");
1429 case WINED3DQUERYTYPE_VCACHE:
1430 case WINED3DQUERYTYPE_RESOURCEMANAGER:
1431 case WINED3DQUERYTYPE_VERTEXSTATS:
1432 case WINED3DQUERYTYPE_EVENT:
1433 case WINED3DQUERYTYPE_TIMESTAMP:
1434 case WINED3DQUERYTYPE_TIMESTAMPDISJOINT:
1435 case WINED3DQUERYTYPE_TIMESTAMPFREQ:
1436 case WINED3DQUERYTYPE_PIPELINETIMINGS:
1437 case WINED3DQUERYTYPE_INTERFACETIMINGS:
1438 case WINED3DQUERYTYPE_VERTEXTIMINGS:
1439 case WINED3DQUERYTYPE_PIXELTIMINGS:
1440 case WINED3DQUERYTYPE_BANDWIDTHTIMINGS:
1441 case WINED3DQUERYTYPE_CACHEUTILIZATION:
1443 FIXME("(%p) Unhandled query type %d\n", This, Type);
1448 D3DCREATEOBJECTINSTANCE(object, Query)
1449 object->type = Type;
1450 /* allocated the 'extended' data based on the type of query requested */
1452 case WINED3DQUERYTYPE_OCCLUSION:
1453 if(GL_SUPPORT(ARB_OCCLUSION_QUERY)) {
1454 TRACE("(%p) Allocating data for an occlusion query\n", This);
1455 object->extendedData = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(WineQueryOcclusionData));
1456 GL_EXTCALL(glGenQueriesARB(1, &((WineQueryOcclusionData *)(object->extendedData))->queryId));
1459 case WINED3DQUERYTYPE_VCACHE:
1460 case WINED3DQUERYTYPE_RESOURCEMANAGER:
1461 case WINED3DQUERYTYPE_VERTEXSTATS:
1462 case WINED3DQUERYTYPE_EVENT:
1463 case WINED3DQUERYTYPE_TIMESTAMP:
1464 case WINED3DQUERYTYPE_TIMESTAMPDISJOINT:
1465 case WINED3DQUERYTYPE_TIMESTAMPFREQ:
1466 case WINED3DQUERYTYPE_PIPELINETIMINGS:
1467 case WINED3DQUERYTYPE_INTERFACETIMINGS:
1468 case WINED3DQUERYTYPE_VERTEXTIMINGS:
1469 case WINED3DQUERYTYPE_PIXELTIMINGS:
1470 case WINED3DQUERYTYPE_BANDWIDTHTIMINGS:
1471 case WINED3DQUERYTYPE_CACHEUTILIZATION:
1473 object->extendedData = 0;
1474 FIXME("(%p) Unhandled query type %d\n",This , Type);
1476 TRACE("(%p) : Created Query %p\n", This, object);
1480 /* example at http://www.fairyengine.com/articles/dxmultiviews.htm */
1481 static HRESULT WINAPI IWineD3DDeviceImpl_CreateAdditionalSwapChain(IWineD3DDevice* iface, WINED3DPRESENT_PARAMETERS* pPresentationParameters, IWineD3DSwapChain** ppSwapChain,
1483 D3DCB_CREATERENDERTARGETFN D3DCB_CreateRenderTarget,
1484 D3DCB_CREATEDEPTHSTENCILSURFACEFN D3DCB_CreateDepthStencil) {
1485 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
1488 IWineD3DSwapChainImpl *object; /** NOTE: impl ref allowed since this is a create function **/
1490 XVisualInfo template;
1491 GLXContext oldContext;
1492 Drawable oldDrawable;
1493 HRESULT hr = WINED3D_OK;
1495 TRACE("(%p) : Created Aditional Swap Chain\n", This);
1497 /** FIXME: Test under windows to find out what the life cycle of a swap chain is,
1498 * does a device hold a reference to a swap chain giving them a lifetime of the device
1499 * or does the swap chain notify the device of its destruction.
1500 *******************************/
1502 /* Check the params */
1503 if(*pPresentationParameters->BackBufferCount > D3DPRESENT_BACK_BUFFER_MAX) {
1504 ERR("App requested %d back buffers, this is not supported for now\n", *pPresentationParameters->BackBufferCount);
1505 return WINED3DERR_INVALIDCALL;
1506 } else if (*pPresentationParameters->BackBufferCount > 1) {
1507 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");
1510 D3DCREATEOBJECTINSTANCE(object, SwapChain)
1512 /*********************
1513 * Lookup the window Handle and the relating X window handle
1514 ********************/
1516 /* Setup hwnd we are using, plus which display this equates to */
1517 object->win_handle = *(pPresentationParameters->hDeviceWindow);
1518 if (!object->win_handle) {
1519 object->win_handle = This->createParms.hFocusWindow;
1522 object->win_handle = GetAncestor(object->win_handle, GA_ROOT);
1523 if ( !( object->win = (Window)GetPropA(object->win_handle, "__wine_x11_whole_window") ) ) {
1524 ERR("Can't get drawable (window), HWND:%p doesn't have the property __wine_x11_whole_window\n", object->win_handle);
1525 return WINED3DERR_NOTAVAILABLE;
1527 hDc = GetDC(object->win_handle);
1528 object->display = get_display(hDc);
1529 ReleaseDC(object->win_handle, hDc);
1530 TRACE("Using a display of %p %p\n", object->display, hDc);
1532 if (NULL == object->display || NULL == hDc) {
1533 WARN("Failed to get a display and HDc for Window %p\n", object->win_handle);
1534 return WINED3DERR_NOTAVAILABLE;
1537 if (object->win == 0) {
1538 WARN("Failed to get a valid XVisuial ID for the window %p\n", object->win_handle);
1539 return WINED3DERR_NOTAVAILABLE;
1542 object->orig_width = GetSystemMetrics(SM_CXSCREEN);
1543 object->orig_height = GetSystemMetrics(SM_CYSCREEN);
1546 * Create an opengl context for the display visual
1547 * NOTE: the visual is chosen as the window is created and the glcontext cannot
1548 * use different properties after that point in time. FIXME: How to handle when requested format
1549 * doesn't match actual visual? Cannot choose one here - code removed as it ONLY works if the one
1550 * it chooses is identical to the one already being used!
1551 **********************************/
1553 /** FIXME: Handle stencil appropriately via EnableAutoDepthStencil / AutoDepthStencilFormat **/
1556 /* Create a new context for this swapchain */
1557 template.visualid = (VisualID)GetPropA(GetDesktopWindow(), "__wine_x11_visual_id");
1558 /* TODO: change this to find a similar visual, but one with a stencil/zbuffer buffer that matches the request
1559 (or the best possible if none is requested) */
1560 TRACE("Found x visual ID : %ld\n", template.visualid);
1562 object->visInfo = XGetVisualInfo(object->display, VisualIDMask, &template, &num);
1563 if (NULL == object->visInfo) {
1564 ERR("cannot really get XVisual\n");
1566 return WINED3DERR_NOTAVAILABLE;
1569 /* Write out some debug info about the visual/s */
1570 TRACE("Using x visual ID : %ld\n", template.visualid);
1571 TRACE(" visual info: %p\n", object->visInfo);
1572 TRACE(" num items : %d\n", num);
1573 for (n = 0;n < num; n++) {
1574 TRACE("=====item=====: %d\n", n + 1);
1575 TRACE(" visualid : %ld\n", object->visInfo[n].visualid);
1576 TRACE(" screen : %d\n", object->visInfo[n].screen);
1577 TRACE(" depth : %u\n", object->visInfo[n].depth);
1578 TRACE(" class : %d\n", object->visInfo[n].class);
1579 TRACE(" red_mask : %ld\n", object->visInfo[n].red_mask);
1580 TRACE(" green_mask : %ld\n", object->visInfo[n].green_mask);
1581 TRACE(" blue_mask : %ld\n", object->visInfo[n].blue_mask);
1582 TRACE(" colormap_size : %d\n", object->visInfo[n].colormap_size);
1583 TRACE(" bits_per_rgb : %d\n", object->visInfo[n].bits_per_rgb);
1584 /* log some extra glx info */
1585 glXGetConfig(object->display, object->visInfo, GLX_AUX_BUFFERS, &value);
1586 TRACE(" gl_aux_buffers : %d\n", value);
1587 glXGetConfig(object->display, object->visInfo, GLX_BUFFER_SIZE ,&value);
1588 TRACE(" gl_buffer_size : %d\n", value);
1589 glXGetConfig(object->display, object->visInfo, GLX_RED_SIZE, &value);
1590 TRACE(" gl_red_size : %d\n", value);
1591 glXGetConfig(object->display, object->visInfo, GLX_GREEN_SIZE, &value);
1592 TRACE(" gl_green_size : %d\n", value);
1593 glXGetConfig(object->display, object->visInfo, GLX_BLUE_SIZE, &value);
1594 TRACE(" gl_blue_size : %d\n", value);
1595 glXGetConfig(object->display, object->visInfo, GLX_ALPHA_SIZE, &value);
1596 TRACE(" gl_alpha_size : %d\n", value);
1597 glXGetConfig(object->display, object->visInfo, GLX_DEPTH_SIZE ,&value);
1598 TRACE(" gl_depth_size : %d\n", value);
1599 glXGetConfig(object->display, object->visInfo, GLX_STENCIL_SIZE, &value);
1600 TRACE(" gl_stencil_size : %d\n", value);
1602 /* Now choose a similar visual ID*/
1604 #ifdef USE_CONTEXT_MANAGER
1606 /** TODO: use a context mamager **/
1610 IWineD3DSwapChain *implSwapChain;
1611 if (WINED3D_OK != IWineD3DDevice_GetSwapChain(iface, 0, &implSwapChain)) {
1612 /* The first time around we create the context that is shared with all other swapchains and render targets */
1613 object->glCtx = glXCreateContext(object->display, object->visInfo, NULL, GL_TRUE);
1614 TRACE("Creating implicit context for vis %p, hwnd %p\n", object->display, object->visInfo);
1617 TRACE("Creating context for vis %p, hwnd %p\n", object->display, object->visInfo);
1618 /* TODO: don't use Impl structures outside of create functions! (a context manager will replace the ->glCtx) */
1619 /* and create a new context with the implicit swapchains context as the shared context */
1620 object->glCtx = glXCreateContext(object->display, object->visInfo, ((IWineD3DSwapChainImpl *)implSwapChain)->glCtx, GL_TRUE);
1621 IWineD3DSwapChain_Release(implSwapChain);
1626 XFree(object->visInfo);
1627 object->visInfo = NULL;
1631 if (!object->glCtx) {
1632 ERR("Failed to create GLX context\n");
1633 return WINED3DERR_NOTAVAILABLE;
1635 TRACE("Context created (HWND=%p, glContext=%p, Window=%ld, VisInfo=%p)\n",
1636 object->win_handle, object->glCtx, object->win, object->visInfo);
1639 /*********************
1640 * Windowed / Fullscreen
1641 *******************/
1644 * TODO: MSDN says that we are only allowed one fullscreen swapchain per device,
1645 * so we should really check to see if there is a fullscreen swapchain already
1646 * I think Windows and X have different ideas about fullscreen, does a single head count as full screen?
1647 **************************************/
1649 if (!*(pPresentationParameters->Windowed)) {
1655 /* Get info on the current display setup */
1656 hdc = CreateDCA("DISPLAY", NULL, NULL, NULL);
1657 bpp = GetDeviceCaps(hdc, BITSPIXEL);
1660 /* Change the display settings */
1661 memset(&devmode, 0, sizeof(DEVMODEW));
1662 devmode.dmFields = DM_BITSPERPEL | DM_PELSWIDTH | DM_PELSHEIGHT;
1663 devmode.dmBitsPerPel = (bpp >= 24) ? 32 : bpp; /* Stupid XVidMode cannot change bpp */
1664 devmode.dmPelsWidth = *(pPresentationParameters->BackBufferWidth);
1665 devmode.dmPelsHeight = *(pPresentationParameters->BackBufferHeight);
1666 MultiByteToWideChar(CP_ACP, 0, "Gamers CG", -1, devmode.dmDeviceName, CCHDEVICENAME);
1667 ChangeDisplaySettingsExW(devmode.dmDeviceName, &devmode, object->win_handle, CDS_FULLSCREEN, NULL);
1669 /* Make popup window */
1670 SetWindowLongA(object->win_handle, GWL_STYLE, WS_POPUP);
1671 SetWindowPos(object->win_handle, HWND_TOP, 0, 0,
1672 *(pPresentationParameters->BackBufferWidth),
1673 *(pPresentationParameters->BackBufferHeight), SWP_SHOWWINDOW | SWP_FRAMECHANGED);
1675 /* For GetDisplayMode */
1676 This->ddraw_width = devmode.dmPelsWidth;
1677 This->ddraw_height = devmode.dmPelsHeight;
1678 This->ddraw_format = *(pPresentationParameters->BackBufferFormat);
1682 /** MSDN: If Windowed is TRUE and either of the BackBufferWidth/Height values is zero,
1683 * then the corresponding dimension of the client area of the hDeviceWindow
1684 * (or the focus window, if hDeviceWindow is NULL) is taken.
1685 **********************/
1687 if (*(pPresentationParameters->Windowed) &&
1688 ((*(pPresentationParameters->BackBufferWidth) == 0) ||
1689 (*(pPresentationParameters->BackBufferHeight) == 0))) {
1692 GetClientRect(object->win_handle, &Rect);
1694 if (*(pPresentationParameters->BackBufferWidth) == 0) {
1695 *(pPresentationParameters->BackBufferWidth) = Rect.right;
1696 TRACE("Updating width to %d\n", *(pPresentationParameters->BackBufferWidth));
1698 if (*(pPresentationParameters->BackBufferHeight) == 0) {
1699 *(pPresentationParameters->BackBufferHeight) = Rect.bottom;
1700 TRACE("Updating height to %d\n", *(pPresentationParameters->BackBufferHeight));
1704 /*********************
1705 * finish off parameter initialization
1706 *******************/
1708 /* Put the correct figures in the presentation parameters */
1709 TRACE("Copying across presentation parameters\n");
1710 object->presentParms.BackBufferWidth = *(pPresentationParameters->BackBufferWidth);
1711 object->presentParms.BackBufferHeight = *(pPresentationParameters->BackBufferHeight);
1712 object->presentParms.BackBufferFormat = *(pPresentationParameters->BackBufferFormat);
1713 object->presentParms.BackBufferCount = *(pPresentationParameters->BackBufferCount);
1714 object->presentParms.MultiSampleType = *(pPresentationParameters->MultiSampleType);
1715 object->presentParms.MultiSampleQuality = NULL == pPresentationParameters->MultiSampleQuality ? 0 : *(pPresentationParameters->MultiSampleQuality);
1716 object->presentParms.SwapEffect = *(pPresentationParameters->SwapEffect);
1717 object->presentParms.hDeviceWindow = *(pPresentationParameters->hDeviceWindow);
1718 object->presentParms.Windowed = *(pPresentationParameters->Windowed);
1719 object->presentParms.EnableAutoDepthStencil = *(pPresentationParameters->EnableAutoDepthStencil);
1720 object->presentParms.AutoDepthStencilFormat = *(pPresentationParameters->AutoDepthStencilFormat);
1721 object->presentParms.Flags = *(pPresentationParameters->Flags);
1722 object->presentParms.FullScreen_RefreshRateInHz = *(pPresentationParameters->FullScreen_RefreshRateInHz);
1723 object->presentParms.PresentationInterval = *(pPresentationParameters->PresentationInterval);
1726 /*********************
1727 * Create the back, front and stencil buffers
1728 *******************/
1730 TRACE("calling rendertarget CB\n");
1731 hr = D3DCB_CreateRenderTarget((IUnknown *) This->parent,
1733 object->presentParms.BackBufferWidth,
1734 object->presentParms.BackBufferHeight,
1735 object->presentParms.BackBufferFormat,
1736 object->presentParms.MultiSampleType,
1737 object->presentParms.MultiSampleQuality,
1738 TRUE /* Lockable */,
1739 &object->frontBuffer,
1740 NULL /* pShared (always null)*/);
1741 if (object->frontBuffer != NULL)
1742 IWineD3DSurface_SetContainer(object->frontBuffer, (IWineD3DBase *)object);
1744 if(object->presentParms.BackBufferCount > 0) {
1747 object->backBuffer = HeapAlloc(GetProcessHeap(), 0, sizeof(IWineD3DSurface *) * object->presentParms.BackBufferCount);
1748 if(!object->backBuffer) {
1749 ERR("Out of memory\n");
1751 if (object->frontBuffer) {
1752 IUnknown *bufferParent;
1753 IWineD3DSurface_GetParent(object->frontBuffer, &bufferParent);
1754 IUnknown_Release(bufferParent); /* once for the get parent */
1755 if (IUnknown_Release(bufferParent) > 0) {
1756 FIXME("(%p) Something's still holding the front buffer\n",This);
1759 HeapFree(GetProcessHeap(), 0, object);
1760 return E_OUTOFMEMORY;
1763 for(i = 0; i < object->presentParms.BackBufferCount; i++) {
1764 TRACE("calling rendertarget CB\n");
1765 hr = D3DCB_CreateRenderTarget((IUnknown *) This->parent,
1767 object->presentParms.BackBufferWidth,
1768 object->presentParms.BackBufferHeight,
1769 object->presentParms.BackBufferFormat,
1770 object->presentParms.MultiSampleType,
1771 object->presentParms.MultiSampleQuality,
1772 TRUE /* Lockable */,
1773 &object->backBuffer[i],
1774 NULL /* pShared (always null)*/);
1775 if(hr == WINED3D_OK && object->backBuffer[i]) {
1776 IWineD3DSurface_SetContainer(object->backBuffer[i], (IWineD3DBase *)object);
1782 object->backBuffer = NULL;
1785 if (object->backBuffer != NULL) {
1787 glDrawBuffer(GL_BACK);
1788 checkGLcall("glDrawBuffer(GL_BACK)");
1791 /* Single buffering - draw to front buffer */
1793 glDrawBuffer(GL_FRONT);
1794 checkGLcall("glDrawBuffer(GL_FRONT)");
1798 /* Under directX swapchains share the depth stencil, so only create one depth-stencil */
1799 if (*(pPresentationParameters->EnableAutoDepthStencil) && hr == WINED3D_OK) {
1800 TRACE("Creating depth stencil buffer\n");
1801 if (This->depthStencilBuffer == NULL ) {
1802 hr = D3DCB_CreateDepthStencil((IUnknown *) This->parent,
1804 object->presentParms.BackBufferWidth,
1805 object->presentParms.BackBufferHeight,
1806 object->presentParms.AutoDepthStencilFormat,
1807 object->presentParms.MultiSampleType,
1808 object->presentParms.MultiSampleQuality,
1809 FALSE /* FIXME: Discard */,
1810 &This->depthStencilBuffer,
1811 NULL /* pShared (always null)*/ );
1812 if (This->depthStencilBuffer != NULL)
1813 IWineD3DSurface_SetContainer(This->depthStencilBuffer, 0);
1816 /** TODO: A check on width, height and multisample types
1817 *(since the zbuffer must be at least as large as the render target and have the same multisample parameters)
1818 ****************************/
1819 object->wantsDepthStencilBuffer = TRUE;
1821 object->wantsDepthStencilBuffer = FALSE;
1824 TRACE("FrontBuf @ %p, BackBuf @ %p, DepthStencil %d\n",object->frontBuffer, object->backBuffer ? object->backBuffer[0] : NULL, object->wantsDepthStencilBuffer);
1827 /*********************
1828 * init the default renderTarget management
1829 *******************/
1830 object->drawable = object->win;
1831 object->render_ctx = object->glCtx;
1833 if (hr == WINED3D_OK) {
1834 /*********************
1835 * Setup some defaults and clear down the buffers
1836 *******************/
1838 /** save current context and drawable **/
1839 oldContext = glXGetCurrentContext();
1840 oldDrawable = glXGetCurrentDrawable();
1842 TRACE("Activating context (display %p context %p drawable %ld)!\n", object->display, object->glCtx, object->win);
1843 if (glXMakeCurrent(object->display, object->win, object->glCtx) == False) {
1844 ERR("Error in setting current context (display %p context %p drawable %ld)!\n", object->display, object->glCtx, object->win);
1846 checkGLcall("glXMakeCurrent");
1848 TRACE("Setting up the screen\n");
1849 /* Clear the screen */
1850 glClearColor(1.0, 0.0, 0.0, 0.0);
1851 checkGLcall("glClearColor");
1854 glClearStencil(0xffff);
1856 checkGLcall("glClear");
1858 glColor3f(1.0, 1.0, 1.0);
1859 checkGLcall("glColor3f");
1861 glEnable(GL_LIGHTING);
1862 checkGLcall("glEnable");
1864 glLightModeli(GL_LIGHT_MODEL_LOCAL_VIEWER, GL_TRUE);
1865 checkGLcall("glLightModeli(GL_LIGHT_MODEL_LOCAL_VIEWER, GL_TRUE);");
1867 glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE_EXT);
1868 checkGLcall("glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE_EXT);");
1870 glLightModeli(GL_LIGHT_MODEL_COLOR_CONTROL, GL_SEPARATE_SPECULAR_COLOR);
1871 checkGLcall("glLightModeli(GL_LIGHT_MODEL_COLOR_CONTROL, GL_SEPARATE_SPECULAR_COLOR);");
1873 /* switch back to the original context (if there was one)*/
1874 if (This->swapchains) {
1875 /** TODO: restore the context and drawable **/
1876 glXMakeCurrent(object->display, oldDrawable, oldContext);
1879 /* Set the surface alignment. This never changes, so we are safe to set it once per context*/
1880 glPixelStorei(GL_PACK_ALIGNMENT, SURFACE_ALIGNMENT);
1881 checkGLcall("glPixelStorei(GL_PACK_ALIGNMENT, SURFACE_ALIGNMENT);");
1882 glPixelStorei(GL_UNPACK_ALIGNMENT, SURFACE_ALIGNMENT);
1883 checkGLcall("glPixelStorei(GL_UNPACK_ALIGNMENT, SURFACE_ALIGNMENT);");
1887 TRACE("Set swapchain to %p\n", object);
1888 } else { /* something went wrong so clean up */
1889 IUnknown* bufferParent;
1890 if (object->frontBuffer) {
1892 IWineD3DSurface_GetParent(object->frontBuffer, &bufferParent);
1893 IUnknown_Release(bufferParent); /* once for the get parent */
1894 if (IUnknown_Release(bufferParent) > 0) {
1895 FIXME("(%p) Something's still holding the front buffer\n",This);
1898 if (object->backBuffer) {
1900 for(i = 0; i < object->presentParms.BackBufferCount; i++) {
1901 if(object->backBuffer[i]) {
1902 IWineD3DSurface_GetParent(object->backBuffer[i], &bufferParent);
1903 IUnknown_Release(bufferParent); /* once for the get parent */
1904 if (IUnknown_Release(bufferParent) > 0) {
1905 FIXME("(%p) Something's still holding the back buffer\n",This);
1909 HeapFree(GetProcessHeap(), 0, object->backBuffer);
1910 object->backBuffer = NULL;
1912 /* NOTE: don't clean up the depthstencil buffer because it belongs to the device */
1913 /* Clean up the context */
1914 /* check that we are the current context first (we shouldn't be though!) */
1915 if (object->glCtx != 0) {
1916 if(glXGetCurrentContext() == object->glCtx) {
1917 glXMakeCurrent(object->display, None, NULL);
1919 glXDestroyContext(object->display, object->glCtx);
1921 HeapFree(GetProcessHeap(), 0, object);
1928 /** NOTE: These are ahead of the other getters and setters to save using a forward declaration **/
1929 static UINT WINAPI IWineD3DDeviceImpl_GetNumberOfSwapChains(IWineD3DDevice *iface) {
1930 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
1931 TRACE("(%p)\n", This);
1933 return This->NumberOfSwapChains;
1936 static HRESULT WINAPI IWineD3DDeviceImpl_GetSwapChain(IWineD3DDevice *iface, UINT iSwapChain, IWineD3DSwapChain **pSwapChain) {
1937 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
1938 TRACE("(%p) : swapchain %d\n", This, iSwapChain);
1940 if(iSwapChain < This->NumberOfSwapChains) {
1941 *pSwapChain = This->swapchains[iSwapChain];
1942 IWineD3DSwapChain_AddRef(*pSwapChain);
1943 TRACE("(%p) returning %p\n", This, *pSwapChain);
1946 TRACE("Swapchain out of range\n");
1948 return WINED3DERR_INVALIDCALL;
1953 * Vertex Declaration
1955 static HRESULT WINAPI IWineD3DDeviceImpl_CreateVertexDeclaration(IWineD3DDevice* iface, CONST VOID* pDeclaration, IWineD3DVertexDeclaration** ppVertexDeclaration, IUnknown *parent) {
1956 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
1957 IWineD3DVertexDeclarationImpl *object = NULL;
1958 HRESULT hr = WINED3D_OK;
1959 TRACE("(%p) : directXVersion=%u, pFunction=%p, ppDecl=%p\n", This, ((IWineD3DImpl *)This->wineD3D)->dxVersion, pDeclaration, ppVertexDeclaration);
1960 D3DCREATEOBJECTINSTANCE(object, VertexDeclaration)
1963 hr = IWineD3DVertexDeclaration_SetDeclaration((IWineD3DVertexDeclaration *)object, (void *)pDeclaration);
1968 /* http://msdn.microsoft.com/archive/default.asp?url=/archive/en-us/directx9_c/directx/graphics/programmingguide/programmable/vertexshaders/vscreate.asp */
1969 static HRESULT WINAPI IWineD3DDeviceImpl_CreateVertexShader(IWineD3DDevice *iface, CONST DWORD *pDeclaration, CONST DWORD *pFunction, IWineD3DVertexShader **ppVertexShader, IUnknown *parent) {
1970 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
1971 IWineD3DVertexShaderImpl *object; /* NOTE: impl usage is ok, this is a create */
1972 HRESULT hr = WINED3D_OK;
1973 D3DCREATESHADEROBJECTINSTANCE(object, VertexShader)
1974 object->baseShader.shader_ins = IWineD3DVertexShaderImpl_shader_ins;
1976 TRACE("(%p) : Created Vertex shader %p\n", This, *ppVertexShader);
1978 /* If a vertex declaration has been passed, save it to the vertex shader, this affects d3d8 only. */
1979 /* Further it needs to be set before calling SetFunction as SetFunction needs the declaration. */
1980 if (pDeclaration != NULL) {
1981 IWineD3DVertexDeclaration *vertexDeclaration;
1982 hr = IWineD3DDevice_CreateVertexDeclaration(iface, pDeclaration, &vertexDeclaration ,NULL);
1983 if (WINED3D_OK == hr) {
1984 TRACE("(%p) : Setting vertex declaration to %p\n", This, vertexDeclaration);
1985 object->vertexDeclaration = vertexDeclaration;
1987 FIXME("(%p) : Failed to set the declaration, returning WINED3DERR_INVALIDCALL\n", iface);
1988 IWineD3DVertexShader_Release(*ppVertexShader);
1989 return WINED3DERR_INVALIDCALL;
1993 hr = IWineD3DVertexShader_SetFunction(*ppVertexShader, pFunction);
1995 if (WINED3D_OK != hr) {
1996 FIXME("(%p) : Failed to set the function, returning WINED3DERR_INVALIDCALL\n", iface);
1997 IWineD3DVertexShader_Release(*ppVertexShader);
1998 return WINED3DERR_INVALIDCALL;
2001 #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. */
2002 if(Usage == WINED3DUSAGE_SOFTWAREVERTEXPROCESSING) {
2013 static HRESULT WINAPI IWineD3DDeviceImpl_CreatePixelShader(IWineD3DDevice *iface, CONST DWORD *pFunction, IWineD3DPixelShader **ppPixelShader, IUnknown *parent) {
2014 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2015 IWineD3DPixelShaderImpl *object; /* NOTE: impl allowed, this is a create */
2016 HRESULT hr = WINED3D_OK;
2018 D3DCREATESHADEROBJECTINSTANCE(object, PixelShader)
2019 object->baseShader.shader_ins = IWineD3DPixelShaderImpl_shader_ins;
2020 hr = IWineD3DPixelShader_SetFunction(*ppPixelShader, pFunction);
2021 if (WINED3D_OK == hr) {
2022 TRACE("(%p) : Created Pixel shader %p\n", This, *ppPixelShader);
2024 WARN("(%p) : Failed to create pixel shader\n", This);
2030 static HRESULT WINAPI IWineD3DDeviceImpl_CreatePalette(IWineD3DDevice *iface, DWORD Flags, PALETTEENTRY *PalEnt, IWineD3DPalette **Palette, IUnknown *Parent) {
2031 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *) iface;
2032 IWineD3DPaletteImpl *object;
2034 TRACE("(%p)->(%x, %p, %p, %p)\n", This, Flags, PalEnt, Palette, Parent);
2036 /* Create the new object */
2037 object = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(IWineD3DPaletteImpl));
2039 ERR("Out of memory when allocating memory for a IWineD3DPalette implementation\n");
2040 return E_OUTOFMEMORY;
2043 object->lpVtbl = &IWineD3DPalette_Vtbl;
2045 object->Flags = Flags;
2046 object->parent = Parent;
2047 object->wineD3DDevice = This;
2048 object->palNumEntries = IWineD3DPaletteImpl_Size(Flags);
2050 object->hpal = CreatePalette((const LOGPALETTE*)&(object->palVersion));
2053 HeapFree( GetProcessHeap(), 0, object);
2054 return E_OUTOFMEMORY;
2057 hr = IWineD3DPalette_SetEntries((IWineD3DPalette *) object, 0, 0, IWineD3DPaletteImpl_Size(Flags), PalEnt);
2059 IWineD3DPalette_Release((IWineD3DPalette *) object);
2063 *Palette = (IWineD3DPalette *) object;
2068 static HRESULT WINAPI IWineD3DDeviceImpl_Init3D(IWineD3DDevice *iface, WINED3DPRESENT_PARAMETERS* pPresentationParameters, D3DCB_CREATEADDITIONALSWAPCHAIN D3DCB_CreateAdditionalSwapChain) {
2069 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *) iface;
2070 IWineD3DSwapChainImpl *swapchain;
2072 TRACE("(%p)->(%p,%p)\n", This, pPresentationParameters, D3DCB_CreateAdditionalSwapChain);
2073 if(This->d3d_initialized) return WINED3DERR_INVALIDCALL;
2075 /* TODO: Test if OpenGL is compiled in and loaded */
2077 /* Setup the implicit swapchain */
2078 TRACE("Creating implicit swapchain\n");
2079 if (D3D_OK != D3DCB_CreateAdditionalSwapChain((IUnknown *) This->parent, pPresentationParameters, (IWineD3DSwapChain **)&swapchain) || swapchain == NULL) {
2080 WARN("Failed to create implicit swapchain\n");
2081 return WINED3DERR_INVALIDCALL;
2084 This->NumberOfSwapChains = 1;
2085 This->swapchains = HeapAlloc(GetProcessHeap(), 0, This->NumberOfSwapChains * sizeof(IWineD3DSwapChain *));
2086 if(!This->swapchains) {
2087 ERR("Out of memory!\n");
2088 IWineD3DSwapChain_Release( (IWineD3DSwapChain *) swapchain);
2089 return E_OUTOFMEMORY;
2091 This->swapchains[0] = (IWineD3DSwapChain *) swapchain;
2093 if(swapchain->backBuffer && swapchain->backBuffer[0]) {
2094 TRACE("Setting rendertarget to %p\n", swapchain->backBuffer);
2095 This->renderTarget = swapchain->backBuffer[0];
2098 TRACE("Setting rendertarget to %p\n", swapchain->frontBuffer);
2099 This->renderTarget = swapchain->frontBuffer;
2101 IWineD3DSurface_AddRef(This->renderTarget);
2102 /* Depth Stencil support */
2103 This->stencilBufferTarget = This->depthStencilBuffer;
2104 if (wined3d_settings.offscreen_rendering_mode == ORM_FBO) {
2105 set_depth_stencil_fbo(iface, This->depthStencilBuffer);
2107 if (NULL != This->stencilBufferTarget) {
2108 IWineD3DSurface_AddRef(This->stencilBufferTarget);
2111 /* Set up some starting GL setup */
2114 * Initialize openGL extension related variables
2115 * with Default values
2118 ((IWineD3DImpl *) This->wineD3D)->isGLInfoValid = IWineD3DImpl_FillGLCaps( This->wineD3D, swapchain->display);
2119 /* Setup all the devices defaults */
2120 IWineD3DStateBlock_InitStartupStateBlock((IWineD3DStateBlock *)This->stateBlock);
2122 IWineD3DImpl_CheckGraphicsMemory();
2126 /* Initialize our list of GLSL programs */
2127 list_init(&This->glsl_shader_progs);
2129 { /* Set a default viewport */
2133 vp.Width = *(pPresentationParameters->BackBufferWidth);
2134 vp.Height = *(pPresentationParameters->BackBufferHeight);
2137 IWineD3DDevice_SetViewport((IWineD3DDevice *)This, &vp);
2140 /* Initialize the current view state */
2141 This->modelview_valid = 1;
2142 This->proj_valid = 0;
2143 This->view_ident = 1;
2144 This->last_was_rhw = 0;
2145 glGetIntegerv(GL_MAX_LIGHTS, &This->maxConcurrentLights);
2146 TRACE("(%p) All defaults now set up, leaving Init3D with %p\n", This, This);
2148 /* Clear the screen */
2149 IWineD3DDevice_Clear((IWineD3DDevice *) This, 0, NULL, WINED3DCLEAR_STENCIL|WINED3DCLEAR_ZBUFFER|WINED3DCLEAR_TARGET, 0x00, 1.0, 0);
2151 This->d3d_initialized = TRUE;
2155 static HRESULT WINAPI IWineD3DDeviceImpl_Uninit3D(IWineD3DDevice *iface, D3DCB_DESTROYSURFACEFN D3DCB_DestroyDepthStencilSurface) {
2156 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *) iface;
2158 IUnknown* swapChainParent;
2160 TRACE("(%p)\n", This);
2162 if(!This->d3d_initialized) return WINED3DERR_INVALIDCALL;
2164 /* Delete the mouse cursor texture */
2165 if(This->cursorTexture) {
2167 glDeleteTextures(1, &This->cursorTexture);
2169 This->cursorTexture = 0;
2172 for(sampler = 0; sampler < GL_LIMITS(sampler_stages); ++sampler) {
2173 IWineD3DDevice_SetTexture(iface, sampler, NULL);
2176 /* Release the buffers (with sanity checks)*/
2177 TRACE("Releasing the depth stencil buffer at %p\n", This->stencilBufferTarget);
2178 if(This->stencilBufferTarget != NULL && (IWineD3DSurface_Release(This->stencilBufferTarget) >0)){
2179 if(This->depthStencilBuffer != This->stencilBufferTarget)
2180 FIXME("(%p) Something's still holding the depthStencilBuffer\n",This);
2182 This->stencilBufferTarget = NULL;
2184 TRACE("Releasing the render target at %p\n", This->renderTarget);
2185 if(IWineD3DSurface_Release(This->renderTarget) >0){
2186 /* This check is a bit silly, itshould be in swapchain_release FIXME("(%p) Something's still holding the renderTarget\n",This); */
2188 TRACE("Setting rendertarget to NULL\n");
2189 This->renderTarget = NULL;
2191 if (This->depthStencilBuffer) {
2192 if(D3DCB_DestroyDepthStencilSurface > 0) {
2193 FIXME("(%p) Something's still holding the depthStencilBuffer\n", This);
2195 This->depthStencilBuffer = NULL;
2198 for(i=0; i < This->NumberOfSwapChains; i++) {
2199 TRACE("Releasing the implicit swapchain %d\n", i);
2200 /* Swapchain 0 is special because it's created in startup with a hanging parent, so we have to release its parent now */
2201 IWineD3DSwapChain_GetParent(This->swapchains[i], &swapChainParent);
2202 IUnknown_Release(swapChainParent); /* once for the get parent */
2203 if (IUnknown_Release(swapChainParent) > 0) { /* the second time for when it was created */
2204 FIXME("(%p) Something's still holding the implicit swapchain\n", This);
2208 HeapFree(GetProcessHeap(), 0, This->swapchains);
2209 This->swapchains = NULL;
2210 This->NumberOfSwapChains = 0;
2212 This->d3d_initialized = FALSE;
2216 static void WINAPI IWineD3DDeviceImpl_SetFullscreen(IWineD3DDevice *iface, BOOL fullscreen) {
2217 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *) iface;
2218 TRACE("(%p) Setting DDraw fullscreen mode to %s\n", This, fullscreen ? "true" : "false");
2220 /* DirectDraw apps can change between fullscreen and windowed mode after device creation with
2221 * IDirectDraw7::SetCooperativeLevel. The GDI surface implementation needs to know this.
2222 * DDraw doesn't necessarily have a swapchain, so we have to store the fullscreen flag
2225 This->ddraw_fullscreen = fullscreen;
2228 static HRESULT WINAPI IWineD3DDeviceImpl_EnumDisplayModes(IWineD3DDevice *iface, DWORD Flags, UINT Width, UINT Height, WINED3DFORMAT pixelformat, LPVOID context, D3DCB_ENUMDISPLAYMODESCALLBACK callback) {
2229 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2233 const PixelFormatDesc *formatDesc = getFormatDescEntry(pixelformat);
2235 TRACE("(%p)->(%x,%d,%d,%d,%p,%p)\n", This, Flags, Width, Height, pixelformat, context, callback);
2237 for (i = 0; EnumDisplaySettingsExW(NULL, i, &DevModeW, 0); i++) {
2238 /* Ignore some modes if a description was passed */
2239 if ( (Width > 0) && (Width != DevModeW.dmPelsWidth)) continue;
2240 if ( (Height > 0) && (Height != DevModeW.dmPelsHeight)) continue;
2241 if ( (pixelformat != WINED3DFMT_UNKNOWN) && ( formatDesc->bpp != DevModeW.dmBitsPerPel) ) continue;
2243 TRACE("Enumerating %dx%d@%s\n", DevModeW.dmPelsWidth, DevModeW.dmPelsHeight, debug_d3dformat(pixelformat_for_depth(DevModeW.dmBitsPerPel)));
2245 if (callback((IUnknown *) This, (UINT) DevModeW.dmPelsWidth, (UINT) DevModeW.dmPelsHeight, pixelformat_for_depth(DevModeW.dmBitsPerPel), 60.0, context) == DDENUMRET_CANCEL)
2252 static HRESULT WINAPI IWineD3DDeviceImpl_SetDisplayMode(IWineD3DDevice *iface, UINT iSwapChain, WINED3DDISPLAYMODE* pMode) {
2254 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2256 const PixelFormatDesc *formatDesc = getFormatDescEntry(pMode->Format);
2258 TRACE("(%p)->(%d,%p) Mode=%dx%dx@%d, %s\n", This, iSwapChain, pMode, pMode->Width, pMode->Height, pMode->RefreshRate, debug_d3dformat(pMode->Format));
2260 /* Resize the screen even without a window:
2261 * The app could have unset it with SetCooperativeLevel, but not called
2262 * RestoreDisplayMode first. Then the release will call RestoreDisplayMode,
2263 * but we don't have any hwnd
2266 devmode.dmFields = DM_BITSPERPEL | DM_PELSWIDTH | DM_PELSHEIGHT;
2267 devmode.dmBitsPerPel = formatDesc->bpp * 8;
2268 if(devmode.dmBitsPerPel == 24) devmode.dmBitsPerPel = 32;
2269 devmode.dmPelsWidth = pMode->Width;
2270 devmode.dmPelsHeight = pMode->Height;
2272 devmode.dmDisplayFrequency = pMode->RefreshRate;
2273 if (pMode->RefreshRate != 0) {
2274 devmode.dmFields |= DM_DISPLAYFREQUENCY;
2277 /* Only change the mode if necessary */
2278 if( (This->ddraw_width == pMode->Width) &&
2279 (This->ddraw_height == pMode->Height) &&
2280 (This->ddraw_format == pMode->Format) &&
2281 (pMode->RefreshRate == 0) ) {
2285 ret = ChangeDisplaySettingsExW(NULL, &devmode, NULL, CDS_FULLSCREEN, NULL);
2286 if (ret != DISP_CHANGE_SUCCESSFUL) {
2287 if(devmode.dmDisplayFrequency != 0) {
2288 WARN("ChangeDisplaySettingsExW failed, trying without the refresh rate\n");
2289 devmode.dmFields &= ~DM_DISPLAYFREQUENCY;
2290 devmode.dmDisplayFrequency = 0;
2291 ret = ChangeDisplaySettingsExW(NULL, &devmode, NULL, CDS_FULLSCREEN, NULL) != DISP_CHANGE_SUCCESSFUL;
2293 if(ret != DISP_CHANGE_SUCCESSFUL) {
2294 return DDERR_INVALIDMODE;
2298 /* Store the new values */
2299 This->ddraw_width = pMode->Width;
2300 This->ddraw_height = pMode->Height;
2301 This->ddraw_format = pMode->Format;
2303 /* Only do this with a window of course */
2304 if(This->ddraw_window)
2305 MoveWindow(This->ddraw_window, 0, 0, pMode->Width, pMode->Height, TRUE);
2310 static HRESULT WINAPI IWineD3DDeviceImpl_GetDirect3D(IWineD3DDevice *iface, IWineD3D **ppD3D) {
2311 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2312 *ppD3D= This->wineD3D;
2313 TRACE("(%p) : wineD3D returning %p\n", This, *ppD3D);
2314 IWineD3D_AddRef(*ppD3D);
2318 static UINT WINAPI IWineD3DDeviceImpl_GetAvailableTextureMem(IWineD3DDevice *iface) {
2319 /** NOTE: There's a probably a hack-around for this one by putting as many pbuffers, VBOs (or whatever)
2320 * into the video ram as possible and seeing how many fit
2321 * you can also get the correct initial value from nvidia and ATI's driver via X
2322 * texture memory is video memory + AGP memory
2323 *******************/
2324 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2325 static BOOL showfixmes = TRUE;
2327 FIXME("(%p) : stub, simulating %dMB for now, returning %dMB left\n", This,
2328 (wined3d_settings.emulated_textureram/(1024*1024)),
2329 ((wined3d_settings.emulated_textureram - wineD3DGlobalStatistics->glsurfaceram) / (1024*1024)));
2332 TRACE("(%p) : simulating %dMB, returning %dMB left\n", This,
2333 (wined3d_settings.emulated_textureram/(1024*1024)),
2334 ((wined3d_settings.emulated_textureram - wineD3DGlobalStatistics->glsurfaceram) / (1024*1024)));
2335 /* return simulated texture memory left */
2336 return (wined3d_settings.emulated_textureram - wineD3DGlobalStatistics->glsurfaceram);
2344 static HRESULT WINAPI IWineD3DDeviceImpl_SetFVF(IWineD3DDevice *iface, DWORD fvf) {
2345 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2346 HRESULT hr = WINED3D_OK;
2348 /* Update the current state block */
2349 This->updateStateBlock->fvf = fvf;
2350 This->updateStateBlock->changed.fvf = TRUE;
2351 This->updateStateBlock->set.fvf = TRUE;
2353 TRACE("(%p) : FVF Shader FVF set to %x\n", This, fvf);
2358 static HRESULT WINAPI IWineD3DDeviceImpl_GetFVF(IWineD3DDevice *iface, DWORD *pfvf) {
2359 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2360 TRACE("(%p) : GetFVF returning %x\n", This, This->stateBlock->fvf);
2361 *pfvf = This->stateBlock->fvf;
2366 * Get / Set Stream Source
2368 static HRESULT WINAPI IWineD3DDeviceImpl_SetStreamSource(IWineD3DDevice *iface, UINT StreamNumber,IWineD3DVertexBuffer* pStreamData, UINT OffsetInBytes, UINT Stride) {
2369 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2370 IWineD3DVertexBuffer *oldSrc;
2372 /**TODO: instance and index data, see
2373 http://msdn.microsoft.com/library/default.asp?url=/library/en-us/directx9_c/directx/graphics/programmingguide/advancedtopics/DrawingMultipleInstances.asp
2375 http://msdn.microsoft.com/library/default.asp?url=/library/en-us/directx9_c/directx/graphics/reference/d3d/interfaces/idirect3ddevice9/SetStreamSourceFreq.asp
2378 /* D3d9 only, but shouldn't hurt d3d8 */
2381 streamFlags = StreamNumber &(WINED3DSTREAMSOURCE_INDEXEDDATA | WINED3DSTREAMSOURCE_INSTANCEDATA);
2383 if (streamFlags & WINED3DSTREAMSOURCE_INDEXEDDATA) {
2384 FIXME("stream index data not supported\n");
2386 if (streamFlags & WINED3DSTREAMSOURCE_INDEXEDDATA) {
2387 FIXME("stream instance data not supported\n");
2391 StreamNumber&= ~(WINED3DSTREAMSOURCE_INDEXEDDATA | WINED3DSTREAMSOURCE_INSTANCEDATA);
2393 if (StreamNumber >= MAX_STREAMS) {
2394 WARN("Stream out of range %d\n", StreamNumber);
2395 return WINED3DERR_INVALIDCALL;
2398 oldSrc = This->stateBlock->streamSource[StreamNumber];
2399 TRACE("(%p) : StreamNo: %d, OldStream (%p), NewStream (%p), NewStride %d\n", This, StreamNumber, oldSrc, pStreamData, Stride);
2401 This->updateStateBlock->changed.streamSource[StreamNumber] = TRUE;
2402 This->updateStateBlock->set.streamSource[StreamNumber] = TRUE;
2403 This->updateStateBlock->streamStride[StreamNumber] = Stride;
2404 This->updateStateBlock->streamSource[StreamNumber] = pStreamData;
2405 This->updateStateBlock->streamOffset[StreamNumber] = OffsetInBytes;
2406 This->updateStateBlock->streamFlags[StreamNumber] = streamFlags;
2408 /* Handle recording of state blocks */
2409 if (This->isRecordingState) {
2410 TRACE("Recording... not performing anything\n");
2414 /* Same stream object: no action */
2415 if (oldSrc == pStreamData)
2418 /* Need to do a getParent and pass the reffs up */
2419 /* MSDN says ..... When an application no longer holds a references to this interface, the interface will automatically be freed.
2420 which suggests that we shouldn't be ref counting? and do need a _release on the stream source to reset the stream source
2421 so for now, just count internally */
2422 if (pStreamData != NULL) {
2423 IWineD3DVertexBufferImpl *vbImpl = (IWineD3DVertexBufferImpl *) pStreamData;
2424 if( (vbImpl->Flags & VBFLAG_STREAM) && vbImpl->stream != StreamNumber) {
2425 WARN("Assigning a Vertex Buffer to stream %d which is already assigned to stream %d\n", StreamNumber, vbImpl->stream);
2427 vbImpl->stream = StreamNumber;
2428 vbImpl->Flags |= VBFLAG_STREAM;
2429 IWineD3DVertexBuffer_AddRef(pStreamData);
2431 if (oldSrc != NULL) {
2432 ((IWineD3DVertexBufferImpl *) oldSrc)->Flags &= ~VBFLAG_STREAM;
2433 IWineD3DVertexBuffer_Release(oldSrc);
2439 static HRESULT WINAPI IWineD3DDeviceImpl_GetStreamSource(IWineD3DDevice *iface, UINT StreamNumber,IWineD3DVertexBuffer** pStream, UINT *pOffset, UINT* pStride) {
2440 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2443 TRACE("(%p) : StreamNo: %d, Stream (%p), Stride %d\n", This, StreamNumber,
2444 This->stateBlock->streamSource[StreamNumber], This->stateBlock->streamStride[StreamNumber]);
2447 streamFlags = StreamNumber &(WINED3DSTREAMSOURCE_INDEXEDDATA | WINED3DSTREAMSOURCE_INSTANCEDATA);
2449 if (streamFlags & WINED3DSTREAMSOURCE_INDEXEDDATA) {
2450 FIXME("stream index data not supported\n");
2452 if (streamFlags & WINED3DSTREAMSOURCE_INDEXEDDATA) {
2453 FIXME("stream instance data not supported\n");
2457 StreamNumber&= ~(WINED3DSTREAMSOURCE_INDEXEDDATA | WINED3DSTREAMSOURCE_INSTANCEDATA);
2459 if (StreamNumber >= MAX_STREAMS) {
2460 WARN("Stream out of range %d\n", StreamNumber);
2461 return WINED3DERR_INVALIDCALL;
2463 *pStream = This->stateBlock->streamSource[StreamNumber];
2464 *pStride = This->stateBlock->streamStride[StreamNumber];
2466 *pOffset = This->stateBlock->streamOffset[StreamNumber];
2469 if (*pStream == NULL) {
2470 FIXME("Attempting to get an empty stream %d, returning WINED3DERR_INVALIDCALL\n", StreamNumber);
2471 return WINED3DERR_INVALIDCALL;
2474 IWineD3DVertexBuffer_AddRef(*pStream); /* We have created a new reference to the VB */
2478 /*Should be quite easy, just an extension of vertexdata
2480 http://msdn.microsoft.com/archive/default.asp?url=/archive/en-us/directx9_c_Summer_04/directx/graphics/programmingguide/advancedtopics/DrawingMultipleInstances.asp
2482 The divider is a bit odd though
2484 VertexOffset = StartVertex / Divider * StreamStride +
2485 VertexIndex / Divider * StreamStride + StreamOffset
2488 static HRESULT WINAPI IWineD3DDeviceImpl_SetStreamSourceFreq(IWineD3DDevice *iface, UINT StreamNumber, UINT Divider) {
2489 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2491 TRACE("(%p) StreamNumber(%d), Divider(%d)\n", This, StreamNumber, Divider);
2492 This->updateStateBlock->streamFlags[StreamNumber] = Divider & (WINED3DSTREAMSOURCE_INSTANCEDATA | WINED3DSTREAMSOURCE_INDEXEDDATA );
2494 This->updateStateBlock->changed.streamFreq[StreamNumber] = TRUE;
2495 This->updateStateBlock->set.streamFreq[StreamNumber] = TRUE;
2496 This->updateStateBlock->streamFreq[StreamNumber] = Divider & 0x7FFFFF;
2498 if (This->updateStateBlock->streamFlags[StreamNumber] || This->updateStateBlock->streamFreq[StreamNumber] != 1) {
2499 FIXME("Stream indexing not fully supported\n");
2505 static HRESULT WINAPI IWineD3DDeviceImpl_GetStreamSourceFreq(IWineD3DDevice *iface, UINT StreamNumber, UINT* Divider) {
2506 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2508 TRACE("(%p) StreamNumber(%d), Divider(%p)\n", This, StreamNumber, Divider);
2509 *Divider = This->updateStateBlock->streamFreq[StreamNumber] | This->updateStateBlock->streamFlags[StreamNumber];
2511 TRACE("(%p) : returning %d\n", This, *Divider);
2517 * Get / Set & Multiply Transform
2519 static HRESULT WINAPI IWineD3DDeviceImpl_SetTransform(IWineD3DDevice *iface, WINED3DTRANSFORMSTATETYPE d3dts, CONST WINED3DMATRIX* lpmatrix) {
2520 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2522 /* Most of this routine, comments included copied from ddraw tree initially: */
2523 TRACE("(%p) : Transform State=%s\n", This, debug_d3dtstype(d3dts));
2525 /* Handle recording of state blocks */
2526 if (This->isRecordingState) {
2527 TRACE("Recording... not performing anything\n");
2528 This->updateStateBlock->changed.transform[d3dts] = TRUE;
2529 This->updateStateBlock->set.transform[d3dts] = TRUE;
2530 memcpy(&This->updateStateBlock->transforms[d3dts], lpmatrix, sizeof(WINED3DMATRIX));
2535 * If the new matrix is the same as the current one,
2536 * we cut off any further processing. this seems to be a reasonable
2537 * optimization because as was noticed, some apps (warcraft3 for example)
2538 * tend towards setting the same matrix repeatedly for some reason.
2540 * From here on we assume that the new matrix is different, wherever it matters.
2542 if (!memcmp(&This->stateBlock->transforms[d3dts].u.m[0][0], lpmatrix, sizeof(WINED3DMATRIX))) {
2543 TRACE("The app is setting the same matrix over again\n");
2546 conv_mat(lpmatrix, &This->stateBlock->transforms[d3dts].u.m[0][0]);
2550 ScreenCoord = ProjectionMat * ViewMat * WorldMat * ObjectCoord
2551 where ViewMat = Camera space, WorldMat = world space.
2553 In OpenGL, camera and world space is combined into GL_MODELVIEW
2554 matrix. The Projection matrix stay projection matrix.
2557 /* Capture the times we can just ignore the change for now */
2558 if (d3dts == WINED3DTS_WORLDMATRIX(0)) {
2559 This->modelview_valid = FALSE;
2562 } else if (d3dts == WINED3DTS_PROJECTION) {
2563 This->proj_valid = FALSE;
2566 } else if (d3dts >= WINED3DTS_WORLDMATRIX(1) && d3dts <= WINED3DTS_WORLDMATRIX(255)) {
2567 /* Indexed Vertex Blending Matrices 256 -> 511 */
2568 /* Use arb_vertex_blend or NV_VERTEX_WEIGHTING? */
2569 FIXME("WINED3DTS_WORLDMATRIX(1..255) not handled\n");
2573 /* Now we really are going to have to change a matrix */
2576 if (d3dts >= WINED3DTS_TEXTURE0 && d3dts <= WINED3DTS_TEXTURE7) { /* handle texture matrices */
2577 /* This is now set with the texture unit states, it may be a good idea to flag the change though! */
2578 } else if (d3dts == WINED3DTS_VIEW) { /* handle the VIEW matrice */
2581 /* If we are changing the View matrix, reset the light and clipping planes to the new view
2582 * NOTE: We have to reset the positions even if the light/plane is not currently
2583 * enabled, since the call to enable it will not reset the position.
2584 * NOTE2: Apparently texture transforms do NOT need reapplying
2587 PLIGHTINFOEL *lightChain = NULL;
2588 This->modelview_valid = FALSE;
2589 This->view_ident = !memcmp(lpmatrix, identity, 16 * sizeof(float));
2591 glMatrixMode(GL_MODELVIEW);
2592 checkGLcall("glMatrixMode(GL_MODELVIEW)");
2594 glLoadMatrixf((const float *)lpmatrix);
2595 checkGLcall("glLoadMatrixf(...)");
2598 lightChain = This->stateBlock->lights;
2599 while (lightChain && lightChain->glIndex != -1) {
2600 glLightfv(GL_LIGHT0 + lightChain->glIndex, GL_POSITION, lightChain->lightPosn);
2601 checkGLcall("glLightfv posn");
2602 glLightfv(GL_LIGHT0 + lightChain->glIndex, GL_SPOT_DIRECTION, lightChain->lightDirn);
2603 checkGLcall("glLightfv dirn");
2604 lightChain = lightChain->next;
2607 /* Reset Clipping Planes if clipping is enabled */
2608 for (k = 0; k < GL_LIMITS(clipplanes); k++) {
2609 glClipPlane(GL_CLIP_PLANE0 + k, This->stateBlock->clipplane[k]);
2610 checkGLcall("glClipPlane");
2614 } else { /* What was requested!?? */
2615 WARN("invalid matrix specified: %i\n", d3dts);
2618 /* Release lock, all done */
2623 static HRESULT WINAPI IWineD3DDeviceImpl_GetTransform(IWineD3DDevice *iface, WINED3DTRANSFORMSTATETYPE State, WINED3DMATRIX* pMatrix) {
2624 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2625 TRACE("(%p) : for Transform State %s\n", This, debug_d3dtstype(State));
2626 memcpy(pMatrix, &This->stateBlock->transforms[State], sizeof(WINED3DMATRIX));
2630 static HRESULT WINAPI IWineD3DDeviceImpl_MultiplyTransform(IWineD3DDevice *iface, WINED3DTRANSFORMSTATETYPE State, CONST WINED3DMATRIX* pMatrix) {
2631 WINED3DMATRIX *mat = NULL;
2634 /* Note: Using 'updateStateBlock' rather than 'stateblock' in the code
2635 * below means it will be recorded in a state block change, but it
2636 * works regardless where it is recorded.
2637 * If this is found to be wrong, change to StateBlock.
2639 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2640 TRACE("(%p) : For state %s\n", This, debug_d3dtstype(State));
2642 if (State < HIGHEST_TRANSFORMSTATE)
2644 mat = &This->updateStateBlock->transforms[State];
2646 FIXME("Unhandled transform state!!\n");
2649 multiply_matrix(&temp, mat, (const WINED3DMATRIX *) pMatrix);
2651 /* Apply change via set transform - will reapply to eg. lights this way */
2652 return IWineD3DDeviceImpl_SetTransform(iface, State, &temp);
2658 /* Note lights are real special cases. Although the device caps state only eg. 8 are supported,
2659 you can reference any indexes you want as long as that number max are enabled at any
2660 one point in time! Therefore since the indexes can be anything, we need a linked list of them.
2661 However, this causes stateblock problems. When capturing the state block, I duplicate the list,
2662 but when recording, just build a chain pretty much of commands to be replayed. */
2664 static HRESULT WINAPI IWineD3DDeviceImpl_SetLight(IWineD3DDevice *iface, DWORD Index, CONST WINED3DLIGHT* pLight) {
2666 PLIGHTINFOEL *object, *temp;
2668 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2669 TRACE("(%p) : Idx(%d), pLight(%p)\n", This, Index, pLight);
2671 /* If recording state block, just add to end of lights chain */
2672 if (This->isRecordingState) {
2673 object = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(PLIGHTINFOEL));
2674 if (NULL == object) {
2675 return WINED3DERR_OUTOFVIDEOMEMORY;
2677 memcpy(&object->OriginalParms, pLight, sizeof(WINED3DLIGHT));
2678 object->OriginalIndex = Index;
2679 object->glIndex = -1;
2680 object->changed = TRUE;
2682 /* Add to the END of the chain of lights changes to be replayed */
2683 if (This->updateStateBlock->lights == NULL) {
2684 This->updateStateBlock->lights = object;
2686 temp = This->updateStateBlock->lights;
2687 while (temp->next != NULL) temp=temp->next;
2688 temp->next = object;
2690 TRACE("Recording... not performing anything more\n");
2694 /* Ok, not recording any longer so do real work */
2695 object = This->stateBlock->lights;
2696 while (object != NULL && object->OriginalIndex != Index) object = object->next;
2698 /* If we didn't find it in the list of lights, time to add it */
2699 if (object == NULL) {
2700 PLIGHTINFOEL *insertAt,*prevPos;
2702 object = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(PLIGHTINFOEL));
2703 if (NULL == object) {
2704 return WINED3DERR_OUTOFVIDEOMEMORY;
2706 object->OriginalIndex = Index;
2707 object->glIndex = -1;
2709 /* Add it to the front of list with the idea that lights will be changed as needed
2710 BUT after any lights currently assigned GL indexes */
2711 insertAt = This->stateBlock->lights;
2713 while (insertAt != NULL && insertAt->glIndex != -1) {
2715 insertAt = insertAt->next;
2718 if (insertAt == NULL && prevPos == NULL) { /* Start of list */
2719 This->stateBlock->lights = object;
2720 } else if (insertAt == NULL) { /* End of list */
2721 prevPos->next = object;
2722 object->prev = prevPos;
2723 } else { /* Middle of chain */
2724 if (prevPos == NULL) {
2725 This->stateBlock->lights = object;
2727 prevPos->next = object;
2729 object->prev = prevPos;
2730 object->next = insertAt;
2731 insertAt->prev = object;
2735 /* Initialize the object */
2736 TRACE("Light %d setting to type %d, Diffuse(%f,%f,%f,%f), Specular(%f,%f,%f,%f), Ambient(%f,%f,%f,%f)\n", Index, pLight->Type,
2737 pLight->Diffuse.r, pLight->Diffuse.g, pLight->Diffuse.b, pLight->Diffuse.a,
2738 pLight->Specular.r, pLight->Specular.g, pLight->Specular.b, pLight->Specular.a,
2739 pLight->Ambient.r, pLight->Ambient.g, pLight->Ambient.b, pLight->Ambient.a);
2740 TRACE("... Pos(%f,%f,%f), Dirn(%f,%f,%f)\n", pLight->Position.x, pLight->Position.y, pLight->Position.z,
2741 pLight->Direction.x, pLight->Direction.y, pLight->Direction.z);
2742 TRACE("... Range(%f), Falloff(%f), Theta(%f), Phi(%f)\n", pLight->Range, pLight->Falloff, pLight->Theta, pLight->Phi);
2744 /* Save away the information */
2745 memcpy(&object->OriginalParms, pLight, sizeof(WINED3DLIGHT));
2747 switch (pLight->Type) {
2748 case WINED3DLIGHT_POINT:
2750 object->lightPosn[0] = pLight->Position.x;
2751 object->lightPosn[1] = pLight->Position.y;
2752 object->lightPosn[2] = pLight->Position.z;
2753 object->lightPosn[3] = 1.0f;
2754 object->cutoff = 180.0f;
2758 case WINED3DLIGHT_DIRECTIONAL:
2760 object->lightPosn[0] = -pLight->Direction.x;
2761 object->lightPosn[1] = -pLight->Direction.y;
2762 object->lightPosn[2] = -pLight->Direction.z;
2763 object->lightPosn[3] = 0.0;
2764 object->exponent = 0.0f;
2765 object->cutoff = 180.0f;
2768 case WINED3DLIGHT_SPOT:
2770 object->lightPosn[0] = pLight->Position.x;
2771 object->lightPosn[1] = pLight->Position.y;
2772 object->lightPosn[2] = pLight->Position.z;
2773 object->lightPosn[3] = 1.0;
2776 object->lightDirn[0] = pLight->Direction.x;
2777 object->lightDirn[1] = pLight->Direction.y;
2778 object->lightDirn[2] = pLight->Direction.z;
2779 object->lightDirn[3] = 1.0;
2782 * opengl-ish and d3d-ish spot lights use too different models for the
2783 * light "intensity" as a function of the angle towards the main light direction,
2784 * so we only can approximate very roughly.
2785 * however spot lights are rather rarely used in games (if ever used at all).
2786 * furthermore if still used, probably nobody pays attention to such details.
2788 if (pLight->Falloff == 0) {
2791 rho = pLight->Theta + (pLight->Phi - pLight->Theta)/(2*pLight->Falloff);
2793 if (rho < 0.0001) rho = 0.0001f;
2794 object->exponent = -0.3/log(cos(rho/2));
2795 if (object->exponent > 128.0) {
2796 object->exponent = 128.0;
2798 object->cutoff = pLight->Phi*90/M_PI;
2804 FIXME("Unrecognized light type %d\n", pLight->Type);
2807 /* Update the live definitions if the light is currently assigned a glIndex */
2808 if (object->glIndex != -1) {
2809 setup_light(iface, object->glIndex, object);
2814 static HRESULT WINAPI IWineD3DDeviceImpl_GetLight(IWineD3DDevice *iface, DWORD Index, WINED3DLIGHT* pLight) {
2815 PLIGHTINFOEL *lightInfo = NULL;
2816 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2817 TRACE("(%p) : Idx(%d), pLight(%p)\n", This, Index, pLight);
2819 /* Locate the light in the live lights */
2820 lightInfo = This->stateBlock->lights;
2821 while (lightInfo != NULL && lightInfo->OriginalIndex != Index) lightInfo = lightInfo->next;
2823 if (lightInfo == NULL) {
2824 TRACE("Light information requested but light not defined\n");
2825 return WINED3DERR_INVALIDCALL;
2828 memcpy(pLight, &lightInfo->OriginalParms, sizeof(WINED3DLIGHT));
2833 * Get / Set Light Enable
2834 * (Note for consistency, renamed d3dx function by adding the 'set' prefix)
2836 static HRESULT WINAPI IWineD3DDeviceImpl_SetLightEnable(IWineD3DDevice *iface, DWORD Index, BOOL Enable) {
2837 PLIGHTINFOEL *lightInfo = NULL;
2838 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2839 TRACE("(%p) : Idx(%d), enable? %d\n", This, Index, Enable);
2841 /* Tests show true = 128...not clear why */
2843 Enable = Enable? 128: 0;
2845 /* If recording state block, just add to end of lights chain with changedEnable set to true */
2846 if (This->isRecordingState) {
2847 lightInfo = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(PLIGHTINFOEL));
2848 if (NULL == lightInfo) {
2849 return WINED3DERR_OUTOFVIDEOMEMORY;
2851 lightInfo->OriginalIndex = Index;
2852 lightInfo->glIndex = -1;
2853 lightInfo->enabledChanged = TRUE;
2854 lightInfo->lightEnabled = Enable;
2856 /* Add to the END of the chain of lights changes to be replayed */
2857 if (This->updateStateBlock->lights == NULL) {
2858 This->updateStateBlock->lights = lightInfo;
2860 PLIGHTINFOEL *temp = This->updateStateBlock->lights;
2861 while (temp->next != NULL) temp=temp->next;
2862 temp->next = lightInfo;
2864 TRACE("Recording... not performing anything more\n");
2868 /* Not recording... So, locate the light in the live lights */
2869 lightInfo = This->stateBlock->lights;
2870 while (lightInfo != NULL && lightInfo->OriginalIndex != Index) lightInfo = lightInfo->next;
2872 /* Special case - enabling an undefined light creates one with a strict set of parms! */
2873 if (lightInfo == NULL) {
2875 TRACE("Light enabled requested but light not defined, so defining one!\n");
2876 IWineD3DDeviceImpl_SetLight(iface, Index, &WINED3D_default_light);
2878 /* Search for it again! Should be fairly quick as near head of list */
2879 lightInfo = This->stateBlock->lights;
2880 while (lightInfo != NULL && lightInfo->OriginalIndex != Index) lightInfo = lightInfo->next;
2881 if (lightInfo == NULL) {
2882 FIXME("Adding default lights has failed dismally\n");
2883 return WINED3DERR_INVALIDCALL;
2887 /* OK, we now have a light... */
2890 /* If we are disabling it, check it was enabled, and
2891 still only do something if it has assigned a glIndex (which it should have!) */
2892 if ((lightInfo->lightEnabled) && (lightInfo->glIndex != -1)) {
2893 TRACE("Disabling light set up at gl idx %d\n", lightInfo->glIndex);
2895 glDisable(GL_LIGHT0 + lightInfo->glIndex);
2896 checkGLcall("glDisable GL_LIGHT0+Index");
2899 TRACE("Nothing to do as light was not enabled\n");
2901 lightInfo->lightEnabled = Enable;
2904 /* We are enabling it. If it is enabled, it's really simple */
2905 if (lightInfo->lightEnabled) {
2907 TRACE("Nothing to do as light was enabled\n");
2909 /* If it already has a glIndex, it's still simple */
2910 } else if (lightInfo->glIndex != -1) {
2911 TRACE("Reusing light as already set up at gl idx %d\n", lightInfo->glIndex);
2912 lightInfo->lightEnabled = Enable;
2914 glEnable(GL_LIGHT0 + lightInfo->glIndex);
2915 checkGLcall("glEnable GL_LIGHT0+Index already setup");
2918 /* Otherwise got to find space - lights are ordered gl indexes first */
2920 PLIGHTINFOEL *bsf = NULL;
2921 PLIGHTINFOEL *pos = This->stateBlock->lights;
2922 PLIGHTINFOEL *prev = NULL;
2926 /* Try to minimize changes as much as possible */
2927 while (pos != NULL && pos->glIndex != -1 && Index < This->maxConcurrentLights) {
2929 /* Try to remember which index can be replaced if necessary */
2930 if (bsf==NULL && !pos->lightEnabled) {
2931 /* Found a light we can replace, save as best replacement */
2935 /* Step to next space */
2941 /* If we have too many active lights, fail the call */
2942 if ((Index == This->maxConcurrentLights) && (bsf == NULL)) {
2943 FIXME("Program requests too many concurrent lights\n");
2944 return WINED3DERR_INVALIDCALL;
2946 /* If we have allocated all lights, but not all are enabled,
2947 reuse one which is not enabled */
2948 } else if (Index == This->maxConcurrentLights) {
2949 /* use bsf - Simply swap the new light and the BSF one */
2950 PLIGHTINFOEL *bsfNext = bsf->next;
2951 PLIGHTINFOEL *bsfPrev = bsf->prev;
2954 if (lightInfo->next != NULL) lightInfo->next->prev = bsf;
2955 if (bsf->prev != NULL) {
2956 bsf->prev->next = lightInfo;
2958 This->stateBlock->lights = lightInfo;
2961 /* If not side by side, lots of chains to update */
2962 if (bsf->next != lightInfo) {
2963 lightInfo->prev->next = bsf;
2964 bsf->next->prev = lightInfo;
2965 bsf->next = lightInfo->next;
2966 bsf->prev = lightInfo->prev;
2967 lightInfo->next = bsfNext;
2968 lightInfo->prev = bsfPrev;
2972 bsf->prev = lightInfo;
2973 bsf->next = lightInfo->next;
2974 lightInfo->next = bsf;
2975 lightInfo->prev = bsfPrev;
2980 glIndex = bsf->glIndex;
2982 lightInfo->glIndex = glIndex;
2983 lightInfo->lightEnabled = Enable;
2985 /* Finally set up the light in gl itself */
2986 TRACE("Replacing light which was set up at gl idx %d\n", lightInfo->glIndex);
2988 setup_light(iface, glIndex, lightInfo);
2989 glEnable(GL_LIGHT0 + glIndex);
2990 checkGLcall("glEnable GL_LIGHT0 new setup");
2993 /* If we reached the end of the allocated lights, with space in the
2994 gl lights, setup a new light */
2995 } else if (pos->glIndex == -1) {
2997 /* We reached the end of the allocated gl lights, so already
2998 know the index of the next one! */
3000 lightInfo->glIndex = glIndex;
3001 lightInfo->lightEnabled = Enable;
3003 /* In an ideal world, it's already in the right place */
3004 if (lightInfo->prev == NULL || lightInfo->prev->glIndex!=-1) {
3005 /* No need to move it */
3007 /* Remove this light from the list */
3008 lightInfo->prev->next = lightInfo->next;
3009 if (lightInfo->next != NULL) {
3010 lightInfo->next->prev = lightInfo->prev;
3013 /* Add in at appropriate place (inbetween prev and pos) */
3014 lightInfo->prev = prev;
3015 lightInfo->next = pos;
3017 This->stateBlock->lights = lightInfo;
3019 prev->next = lightInfo;
3022 pos->prev = lightInfo;
3026 /* Finally set up the light in gl itself */
3027 TRACE("Defining new light at gl idx %d\n", lightInfo->glIndex);
3029 setup_light(iface, glIndex, lightInfo);
3030 glEnable(GL_LIGHT0 + glIndex);
3031 checkGLcall("glEnable GL_LIGHT0 new setup");
3040 static HRESULT WINAPI IWineD3DDeviceImpl_GetLightEnable(IWineD3DDevice *iface, DWORD Index,BOOL* pEnable) {
3042 PLIGHTINFOEL *lightInfo = NULL;
3043 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3044 TRACE("(%p) : for idx(%d)\n", This, Index);
3046 /* Locate the light in the live lights */
3047 lightInfo = This->stateBlock->lights;
3048 while (lightInfo != NULL && lightInfo->OriginalIndex != Index) lightInfo = lightInfo->next;
3050 if (lightInfo == NULL) {
3051 TRACE("Light enabled state requested but light not defined\n");
3052 return WINED3DERR_INVALIDCALL;
3054 *pEnable = lightInfo->lightEnabled;
3059 * Get / Set Clip Planes
3061 static HRESULT WINAPI IWineD3DDeviceImpl_SetClipPlane(IWineD3DDevice *iface, DWORD Index, CONST float *pPlane) {
3062 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3063 TRACE("(%p) : for idx %d, %p\n", This, Index, pPlane);
3065 /* Validate Index */
3066 if (Index >= GL_LIMITS(clipplanes)) {
3067 TRACE("Application has requested clipplane this device doesn't support\n");
3068 return WINED3DERR_INVALIDCALL;
3071 This->updateStateBlock->changed.clipplane[Index] = TRUE;
3072 This->updateStateBlock->set.clipplane[Index] = TRUE;
3073 This->updateStateBlock->clipplane[Index][0] = pPlane[0];
3074 This->updateStateBlock->clipplane[Index][1] = pPlane[1];
3075 This->updateStateBlock->clipplane[Index][2] = pPlane[2];
3076 This->updateStateBlock->clipplane[Index][3] = pPlane[3];
3078 /* Handle recording of state blocks */
3079 if (This->isRecordingState) {
3080 TRACE("Recording... not performing anything\n");
3088 /* Clip Plane settings are affected by the model view in OpenGL, the View transform in direct3d */
3089 glMatrixMode(GL_MODELVIEW);
3091 glLoadMatrixf((float *) &This->stateBlock->transforms[WINED3DTS_VIEW].u.m[0][0]);
3093 TRACE("Clipplane [%f,%f,%f,%f]\n",
3094 This->updateStateBlock->clipplane[Index][0],
3095 This->updateStateBlock->clipplane[Index][1],
3096 This->updateStateBlock->clipplane[Index][2],
3097 This->updateStateBlock->clipplane[Index][3]);
3098 glClipPlane(GL_CLIP_PLANE0 + Index, This->updateStateBlock->clipplane[Index]);
3099 checkGLcall("glClipPlane");
3107 static HRESULT WINAPI IWineD3DDeviceImpl_GetClipPlane(IWineD3DDevice *iface, DWORD Index, float *pPlane) {
3108 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3109 TRACE("(%p) : for idx %d\n", This, Index);
3111 /* Validate Index */
3112 if (Index >= GL_LIMITS(clipplanes)) {
3113 TRACE("Application has requested clipplane this device doesn't support\n");
3114 return WINED3DERR_INVALIDCALL;
3117 pPlane[0] = This->stateBlock->clipplane[Index][0];
3118 pPlane[1] = This->stateBlock->clipplane[Index][1];
3119 pPlane[2] = This->stateBlock->clipplane[Index][2];
3120 pPlane[3] = This->stateBlock->clipplane[Index][3];
3125 * Get / Set Clip Plane Status
3126 * WARNING: This code relies on the fact that D3DCLIPSTATUS8 == D3DCLIPSTATUS9
3128 static HRESULT WINAPI IWineD3DDeviceImpl_SetClipStatus(IWineD3DDevice *iface, CONST WINED3DCLIPSTATUS* pClipStatus) {
3129 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3130 FIXME("(%p) : stub\n", This);
3131 if (NULL == pClipStatus) {
3132 return WINED3DERR_INVALIDCALL;
3134 This->updateStateBlock->clip_status.ClipUnion = pClipStatus->ClipUnion;
3135 This->updateStateBlock->clip_status.ClipIntersection = pClipStatus->ClipIntersection;
3139 static HRESULT WINAPI IWineD3DDeviceImpl_GetClipStatus(IWineD3DDevice *iface, WINED3DCLIPSTATUS* pClipStatus) {
3140 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3141 FIXME("(%p) : stub\n", This);
3142 if (NULL == pClipStatus) {
3143 return WINED3DERR_INVALIDCALL;
3145 pClipStatus->ClipUnion = This->updateStateBlock->clip_status.ClipUnion;
3146 pClipStatus->ClipIntersection = This->updateStateBlock->clip_status.ClipIntersection;
3151 * Get / Set Material
3153 static HRESULT WINAPI IWineD3DDeviceImpl_SetMaterial(IWineD3DDevice *iface, CONST WINED3DMATERIAL* pMaterial) {
3154 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3156 This->updateStateBlock->changed.material = TRUE;
3157 This->updateStateBlock->set.material = TRUE;
3158 memcpy(&This->updateStateBlock->material, pMaterial, sizeof(WINED3DMATERIAL));
3160 /* Handle recording of state blocks */
3161 if (This->isRecordingState) {
3162 TRACE("Recording... not performing anything\n");
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);
3177 glMaterialfv(GL_FRONT_AND_BACK, GL_AMBIENT, (float*) &This->updateStateBlock->material.Ambient);
3178 checkGLcall("glMaterialfv(GL_AMBIENT)");
3179 glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, (float*) &This->updateStateBlock->material.Diffuse);
3180 checkGLcall("glMaterialfv(GL_DIFFUSE)");
3182 /* Only change material color if specular is enabled, otherwise it is set to black */
3183 if (This->stateBlock->renderState[WINED3DRS_SPECULARENABLE]) {
3184 glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, (float*) &This->updateStateBlock->material.Specular);
3185 checkGLcall("glMaterialfv(GL_SPECULAR");
3187 float black[4] = {0.0f, 0.0f, 0.0f, 0.0f};
3188 glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, &black[0]);
3189 checkGLcall("glMaterialfv(GL_SPECULAR");
3191 glMaterialfv(GL_FRONT_AND_BACK, GL_EMISSION, (float*) &This->updateStateBlock->material.Emissive);
3192 checkGLcall("glMaterialfv(GL_EMISSION)");
3193 glMaterialf(GL_FRONT_AND_BACK, GL_SHININESS, This->updateStateBlock->material.Power);
3194 checkGLcall("glMaterialf(GL_SHININESS");
3200 static HRESULT WINAPI IWineD3DDeviceImpl_GetMaterial(IWineD3DDevice *iface, WINED3DMATERIAL* pMaterial) {
3201 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3202 memcpy(pMaterial, &This->updateStateBlock->material, sizeof (WINED3DMATERIAL));
3203 TRACE("(%p) : Diffuse (%f,%f,%f,%f)\n", This, pMaterial->Diffuse.r, pMaterial->Diffuse.g,
3204 pMaterial->Diffuse.b, pMaterial->Diffuse.a);
3205 TRACE("(%p) : Ambient (%f,%f,%f,%f)\n", This, pMaterial->Ambient.r, pMaterial->Ambient.g,
3206 pMaterial->Ambient.b, pMaterial->Ambient.a);
3207 TRACE("(%p) : Specular (%f,%f,%f,%f)\n", This, pMaterial->Specular.r, pMaterial->Specular.g,
3208 pMaterial->Specular.b, pMaterial->Specular.a);
3209 TRACE("(%p) : Emissive (%f,%f,%f,%f)\n", This, pMaterial->Emissive.r, pMaterial->Emissive.g,
3210 pMaterial->Emissive.b, pMaterial->Emissive.a);
3211 TRACE("(%p) : Power (%f)\n", This, pMaterial->Power);
3219 static HRESULT WINAPI IWineD3DDeviceImpl_SetIndices(IWineD3DDevice *iface, IWineD3DIndexBuffer* pIndexData,
3220 UINT BaseVertexIndex) {
3221 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3222 IWineD3DIndexBuffer *oldIdxs;
3224 TRACE("(%p) : Setting to %p, base %d\n", This, pIndexData, BaseVertexIndex);
3225 oldIdxs = This->updateStateBlock->pIndexData;
3227 This->updateStateBlock->changed.indices = TRUE;
3228 This->updateStateBlock->set.indices = TRUE;
3229 This->updateStateBlock->pIndexData = pIndexData;
3230 This->updateStateBlock->baseVertexIndex = BaseVertexIndex;
3232 /* Handle recording of state blocks */
3233 if (This->isRecordingState) {
3234 TRACE("Recording... not performing anything\n");
3238 if (NULL != pIndexData) {
3239 IWineD3DIndexBuffer_AddRef(pIndexData);
3241 if (NULL != oldIdxs) {
3242 IWineD3DIndexBuffer_Release(oldIdxs);
3247 static HRESULT WINAPI IWineD3DDeviceImpl_GetIndices(IWineD3DDevice *iface, IWineD3DIndexBuffer** ppIndexData, UINT* pBaseVertexIndex) {
3248 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3250 *ppIndexData = This->stateBlock->pIndexData;
3252 /* up ref count on ppindexdata */
3254 IWineD3DIndexBuffer_AddRef(*ppIndexData);
3255 *pBaseVertexIndex = This->stateBlock->baseVertexIndex;
3256 TRACE("(%p) index data set to %p + %u\n", This, ppIndexData, This->stateBlock->baseVertexIndex);
3258 TRACE("(%p) No index data set\n", This);
3260 TRACE("Returning %p %d\n", *ppIndexData, *pBaseVertexIndex);
3266 * Get / Set Viewports
3268 static HRESULT WINAPI IWineD3DDeviceImpl_SetViewport(IWineD3DDevice *iface, CONST WINED3DVIEWPORT* pViewport) {
3269 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3271 TRACE("(%p)\n", This);
3272 This->updateStateBlock->changed.viewport = TRUE;
3273 This->updateStateBlock->set.viewport = TRUE;
3274 memcpy(&This->updateStateBlock->viewport, pViewport, sizeof(WINED3DVIEWPORT));
3276 /* Handle recording of state blocks */
3277 if (This->isRecordingState) {
3278 TRACE("Recording... not performing anything\n");
3281 This->viewport_changed = TRUE;
3285 TRACE("(%p) : x=%d, y=%d, wid=%d, hei=%d, minz=%f, maxz=%f\n", This,
3286 pViewport->X, pViewport->Y, pViewport->Width, pViewport->Height, pViewport->MinZ, pViewport->MaxZ);
3288 glDepthRange(pViewport->MinZ, pViewport->MaxZ);
3289 checkGLcall("glDepthRange");
3290 /* Note: GL requires lower left, DirectX supplies upper left */
3291 /* TODO: replace usage of renderTarget with context management */
3292 glViewport(pViewport->X,
3293 (((IWineD3DSurfaceImpl *)This->renderTarget)->currentDesc.Height - (pViewport->Y + pViewport->Height)),
3294 pViewport->Width, pViewport->Height);
3296 checkGLcall("glViewport");
3304 static HRESULT WINAPI IWineD3DDeviceImpl_GetViewport(IWineD3DDevice *iface, WINED3DVIEWPORT* pViewport) {
3305 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3306 TRACE("(%p)\n", This);
3307 memcpy(pViewport, &This->stateBlock->viewport, sizeof(WINED3DVIEWPORT));
3311 static void renderstate_stencil_twosided(
3312 IWineD3DDeviceImpl *This,
3319 GLint stencilPass ) {
3320 #if 0 /* Don't use OpenGL 2.0 calls for now */
3321 if(GL_EXTCALL(glStencilFuncSeparate) && GL_EXTCALL(glStencilOpSeparate)) {
3322 GL_EXTCALL(glStencilFuncSeparate(face, func, ref, mask));
3323 checkGLcall("glStencilFuncSeparate(...)");
3324 GL_EXTCALL(glStencilOpSeparate(face, stencilFail, depthFail, stencilPass));
3325 checkGLcall("glStencilOpSeparate(...)");
3329 if(GL_SUPPORT(EXT_STENCIL_TWO_SIDE)) {
3330 glEnable(GL_STENCIL_TEST_TWO_SIDE_EXT);
3331 checkGLcall("glEnable(GL_STENCIL_TEST_TWO_SIDE_EXT)");
3332 GL_EXTCALL(glActiveStencilFaceEXT(face));
3333 checkGLcall("glActiveStencilFaceEXT(...)");
3334 glStencilFunc(func, ref, mask);
3335 checkGLcall("glStencilFunc(...)");
3336 glStencilOp(stencilFail, depthFail, stencilPass);
3337 checkGLcall("glStencilOp(...)");
3338 } else if(GL_SUPPORT(ATI_SEPARATE_STENCIL)) {
3339 GL_EXTCALL(glStencilFuncSeparateATI(face, func, ref, mask));
3340 checkGLcall("glStencilFuncSeparateATI(...)");
3341 GL_EXTCALL(glStencilOpSeparateATI(face, stencilFail, depthFail, stencilPass));
3342 checkGLcall("glStencilOpSeparateATI(...)");
3344 ERR("Separate (two sided) stencil not supported on this version of opengl. Caps weren't honored?\n");
3348 static void renderstate_stencil(IWineD3DDeviceImpl *This, WINED3DRENDERSTATETYPE State, DWORD Value) {
3349 DWORD onesided_enable = FALSE;
3350 DWORD twosided_enable = FALSE;
3351 GLint func = GL_ALWAYS;
3352 GLint func_ccw = GL_ALWAYS;
3355 GLint stencilFail = GL_KEEP;
3356 GLint depthFail = GL_KEEP;
3357 GLint stencilPass = GL_KEEP;
3358 GLint stencilFail_ccw = GL_KEEP;
3359 GLint depthFail_ccw = GL_KEEP;
3360 GLint stencilPass_ccw = GL_KEEP;
3362 if( This->stateBlock->set.renderState[WINED3DRS_STENCILENABLE] )
3363 onesided_enable = This->stateBlock->renderState[WINED3DRS_STENCILENABLE];
3364 if( This->stateBlock->set.renderState[WINED3DRS_TWOSIDEDSTENCILMODE] )
3365 twosided_enable = This->stateBlock->renderState[WINED3DRS_TWOSIDEDSTENCILMODE];
3366 if( This->stateBlock->set.renderState[WINED3DRS_STENCILFUNC] )
3367 if( !( func = CompareFunc(This->stateBlock->renderState[WINED3DRS_STENCILFUNC]) ) )
3369 if( This->stateBlock->set.renderState[WINED3DRS_CCW_STENCILFUNC] )
3370 if( !( func_ccw = CompareFunc(This->stateBlock->renderState[WINED3DRS_CCW_STENCILFUNC]) ) )
3372 if( This->stateBlock->set.renderState[WINED3DRS_STENCILREF] )
3373 ref = This->stateBlock->renderState[WINED3DRS_STENCILREF];
3374 if( This->stateBlock->set.renderState[WINED3DRS_STENCILMASK] )
3375 mask = This->stateBlock->renderState[WINED3DRS_STENCILMASK];
3376 if( This->stateBlock->set.renderState[WINED3DRS_STENCILFAIL] )
3377 stencilFail = StencilOp(This->stateBlock->renderState[WINED3DRS_STENCILFAIL]);
3378 if( This->stateBlock->set.renderState[WINED3DRS_STENCILZFAIL] )
3379 depthFail = StencilOp(This->stateBlock->renderState[WINED3DRS_STENCILZFAIL]);
3380 if( This->stateBlock->set.renderState[WINED3DRS_STENCILPASS] )
3381 stencilPass = StencilOp(This->stateBlock->renderState[WINED3DRS_STENCILPASS]);
3382 if( This->stateBlock->set.renderState[WINED3DRS_CCW_STENCILFAIL] )
3383 stencilFail_ccw = StencilOp(This->stateBlock->renderState[WINED3DRS_CCW_STENCILFAIL]);
3384 if( This->stateBlock->set.renderState[WINED3DRS_CCW_STENCILZFAIL] )
3385 depthFail_ccw = StencilOp(This->stateBlock->renderState[WINED3DRS_CCW_STENCILZFAIL]);
3386 if( This->stateBlock->set.renderState[WINED3DRS_CCW_STENCILPASS] )
3387 stencilPass_ccw = StencilOp(This->stateBlock->renderState[WINED3DRS_CCW_STENCILPASS]);
3389 TRACE("(onesided %d, twosided %d, ref %x, mask %x, \
3390 GL_FRONT: func: %x, fail %x, zfail %x, zpass %x \
3391 GL_BACK: func: %x, fail %x, zfail %x, zpass %x )\n",
3392 onesided_enable, twosided_enable, ref, mask,
3393 func, stencilFail, depthFail, stencilPass,
3394 func_ccw, stencilFail_ccw, depthFail_ccw, stencilPass_ccw);
3396 if (twosided_enable) {
3397 renderstate_stencil_twosided(This, GL_FRONT, func, ref, mask, stencilFail, depthFail, stencilPass);
3398 renderstate_stencil_twosided(This, GL_BACK, func_ccw, ref, mask, stencilFail_ccw, depthFail_ccw, stencilPass_ccw);
3400 if (onesided_enable) {
3401 glEnable(GL_STENCIL_TEST);
3402 checkGLcall("glEnable GL_STENCIL_TEST");
3403 glStencilFunc(func, ref, mask);
3404 checkGLcall("glStencilFunc(...)");
3405 glStencilOp(stencilFail, depthFail, stencilPass);
3406 checkGLcall("glStencilOp(...)");
3408 glDisable(GL_STENCIL_TEST);
3409 checkGLcall("glDisable GL_STENCIL_TEST");
3415 * Get / Set Render States
3416 * TODO: Verify against dx9 definitions
3418 static HRESULT WINAPI IWineD3DDeviceImpl_SetRenderState(IWineD3DDevice *iface, WINED3DRENDERSTATETYPE State, DWORD Value) {
3420 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3422 /* Simple way of referring to either a DWORD or a 4 byte float */
3428 TRACE("(%p)->state = %s(%d), value = %d\n", This, debug_d3drenderstate(State), State, Value);
3429 This->updateStateBlock->changed.renderState[State] = TRUE;
3430 This->updateStateBlock->set.renderState[State] = TRUE;
3431 This->updateStateBlock->renderState[State] = Value;
3433 /* Handle recording of state blocks */
3434 if (This->isRecordingState) {
3435 TRACE("Recording... not performing anything\n");
3442 case WINED3DRS_FILLMODE :
3443 case WINED3DRS_LIGHTING :
3444 case WINED3DRS_ZENABLE :
3445 case WINED3DRS_CULLMODE :
3446 case WINED3DRS_SHADEMODE :
3447 case WINED3DRS_DITHERENABLE :
3448 case WINED3DRS_ZWRITEENABLE :
3449 case WINED3DRS_ZFUNC :
3450 case WINED3DRS_AMBIENT :
3451 case WINED3DRS_ALPHABLENDENABLE :
3452 case WINED3DRS_SRCBLEND :
3453 case WINED3DRS_DESTBLEND :
3454 case WINED3DRS_ANTIALIASEDLINEENABLE :
3455 case WINED3DRS_BLENDFACTOR :
3456 case WINED3DRS_ALPHATESTENABLE :
3457 case WINED3DRS_ALPHAFUNC :
3458 case WINED3DRS_ALPHAREF :
3459 case WINED3DRS_COLORKEYENABLE :
3460 case WINED3DRS_CLIPPLANEENABLE :
3461 case WINED3DRS_CLIPPING :
3462 StateTable[STATE_RENDER(State)].apply(STATE_RENDER(State), This->stateBlock);
3465 case WINED3DRS_BLENDOP :
3467 int glParm = GL_FUNC_ADD;
3469 switch ((WINED3DBLENDOP) Value) {
3470 case WINED3DBLENDOP_ADD : glParm = GL_FUNC_ADD; break;
3471 case WINED3DBLENDOP_SUBTRACT : glParm = GL_FUNC_SUBTRACT; break;
3472 case WINED3DBLENDOP_REVSUBTRACT : glParm = GL_FUNC_REVERSE_SUBTRACT; break;
3473 case WINED3DBLENDOP_MIN : glParm = GL_MIN; break;
3474 case WINED3DBLENDOP_MAX : glParm = GL_MAX; break;
3476 FIXME("Unrecognized/Unhandled WINED3DBLENDOP value %d\n", Value);
3479 if(GL_SUPPORT(EXT_BLEND_MINMAX)) {
3480 TRACE("glBlendEquation(%x)\n", glParm);
3481 GL_EXTCALL(glBlendEquation(glParm));
3482 checkGLcall("glBlendEquation");
3484 WARN("Unsupported in local OpenGL implementation: glBlendEquation\n");
3489 case WINED3DRS_TEXTUREFACTOR :
3493 /* Note the texture color applies to all textures whereas
3494 GL_TEXTURE_ENV_COLOR applies to active only */
3496 D3DCOLORTOGLFLOAT4(Value, col);
3498 if (!GL_SUPPORT(NV_REGISTER_COMBINERS)) {
3499 /* And now the default texture color as well */
3500 for (i = 0; i < GL_LIMITS(texture_stages); i++) {
3501 /* Note the WINED3DRS value applies to all textures, but GL has one
3502 per texture, so apply it now ready to be used! */
3503 if (GL_SUPPORT(ARB_MULTITEXTURE)) {
3504 GL_EXTCALL(glActiveTextureARB(GL_TEXTURE0_ARB + i));
3505 checkGLcall("glActiveTextureARB");
3507 FIXME("Program using multiple concurrent textures which this opengl implementation doesn't support\n");
3510 glTexEnvfv(GL_TEXTURE_ENV, GL_TEXTURE_ENV_COLOR, &col[0]);
3511 checkGLcall("glTexEnvfv(GL_TEXTURE_ENV, GL_TEXTURE_ENV_COLOR, color);");
3517 case WINED3DRS_SPECULARENABLE :
3519 /* Originally this used glLightModeli(GL_LIGHT_MODEL_COLOR_CONTROL,GL_SEPARATE_SPECULAR_COLOR)
3520 and (GL_LIGHT_MODEL_COLOR_CONTROL,GL_SINGLE_COLOR) to swap between enabled/disabled
3521 specular color. This is wrong:
3522 Separate specular color means the specular colour is maintained separately, whereas
3523 single color means it is merged in. However in both cases they are being used to
3525 To disable specular color, set it explicitly to black and turn off GL_COLOR_SUM_EXT
3526 NOTE: If not supported don't give FIXMEs the impact is really minimal and very few people are
3530 * If register combiners are enabled, enabling / disabling GL_COLOR_SUM has no effect.
3531 * Instead, we need to setup the FinalCombiner properly.
3533 * The default setup for the FinalCombiner is:
3535 * <variable> <input> <mapping> <usage>
3536 * GL_VARIABLE_A_NV GL_FOG, GL_UNSIGNED_IDENTITY_NV GL_ALPHA
3537 * GL_VARIABLE_B_NV GL_SPARE0_PLUS_SECONDARY_COLOR_NV GL_UNSIGNED_IDENTITY_NV GL_RGB
3538 * GL_VARIABLE_C_NV GL_FOG GL_UNSIGNED_IDENTITY_NV GL_RGB
3539 * GL_VARIABLE_D_NV GL_ZERO GL_UNSIGNED_IDENTITY_NV GL_RGB
3540 * GL_VARIABLE_E_NV GL_ZERO GL_UNSIGNED_IDENTITY_NV GL_RGB
3541 * GL_VARIABLE_F_NV GL_ZERO GL_UNSIGNED_IDENTITY_NV GL_RGB
3542 * GL_VARIABLE_G_NV GL_SPARE0_NV GL_UNSIGNED_IDENTITY_NV GL_ALPHA
3544 * That's pretty much fine as it is, except for variable B, which needs to take
3545 * either GL_SPARE0_PLUS_SECONDARY_COLOR_NV or GL_SPARE0_NV, depending on
3546 * whether WINED3DRS_SPECULARENABLE is enabled or not.
3550 glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, (float*) &This->updateStateBlock->material.Specular);
3551 checkGLcall("glMaterialfv");
3552 if (GL_SUPPORT(EXT_SECONDARY_COLOR)) {
3553 glEnable(GL_COLOR_SUM_EXT);
3555 TRACE("Specular colors cannot be enabled in this version of opengl\n");
3557 checkGLcall("glEnable(GL_COLOR_SUM)");
3559 if (GL_SUPPORT(NV_REGISTER_COMBINERS)) {
3560 GL_EXTCALL(glFinalCombinerInputNV(GL_VARIABLE_B_NV, GL_SPARE0_PLUS_SECONDARY_COLOR_NV, GL_UNSIGNED_IDENTITY_NV, GL_RGB));
3561 checkGLcall("glFinalCombinerInputNV()");
3564 float black[4] = {0.0f, 0.0f, 0.0f, 0.0f};
3566 /* for the case of enabled lighting: */
3567 glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, &black[0]);
3568 checkGLcall("glMaterialfv");
3570 /* for the case of disabled lighting: */
3571 if (GL_SUPPORT(EXT_SECONDARY_COLOR)) {
3572 glDisable(GL_COLOR_SUM_EXT);
3574 TRACE("Specular colors cannot be disabled in this version of opengl\n");
3576 checkGLcall("glDisable(GL_COLOR_SUM)");
3578 if (GL_SUPPORT(NV_REGISTER_COMBINERS)) {
3579 GL_EXTCALL(glFinalCombinerInputNV(GL_VARIABLE_B_NV, GL_SPARE0_NV, GL_UNSIGNED_IDENTITY_NV, GL_RGB));
3580 checkGLcall("glFinalCombinerInputNV()");
3586 case WINED3DRS_STENCILENABLE :
3587 case WINED3DRS_TWOSIDEDSTENCILMODE :
3588 case WINED3DRS_STENCILFUNC :
3589 case WINED3DRS_CCW_STENCILFUNC :
3590 case WINED3DRS_STENCILREF :
3591 case WINED3DRS_STENCILMASK :
3592 case WINED3DRS_STENCILFAIL :
3593 case WINED3DRS_STENCILZFAIL :
3594 case WINED3DRS_STENCILPASS :
3595 case WINED3DRS_CCW_STENCILFAIL :
3596 case WINED3DRS_CCW_STENCILZFAIL :
3597 case WINED3DRS_CCW_STENCILPASS :
3598 case WINED3DRS_EDGEANTIALIAS :
3599 renderstate_stencil(This, State, Value);
3601 case WINED3DRS_STENCILWRITEMASK :
3603 glStencilMask(Value);
3604 TRACE("glStencilMask(%u)\n", Value);
3605 checkGLcall("glStencilMask");
3609 case WINED3DRS_FOGENABLE :
3613 checkGLcall("glEnable GL_FOG");
3616 checkGLcall("glDisable GL_FOG");
3621 case WINED3DRS_RANGEFOGENABLE :
3624 TRACE("Enabled RANGEFOG\n");
3626 TRACE("Disabled RANGEFOG\n");
3631 case WINED3DRS_FOGCOLOR :
3634 D3DCOLORTOGLFLOAT4(Value, col);
3635 /* Set the default alpha blend color */
3636 glFogfv(GL_FOG_COLOR, &col[0]);
3637 checkGLcall("glFog GL_FOG_COLOR");
3641 case WINED3DRS_FOGTABLEMODE :
3642 case WINED3DRS_FOGVERTEXMODE :
3644 /* 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." */
3645 if(This->stateBlock->renderState[WINED3DRS_FOGTABLEMODE] == WINED3DFOG_NONE) {
3646 glHint(GL_FOG_HINT, GL_FASTEST);
3647 checkGLcall("glHint(GL_FOG_HINT, GL_FASTEST)");
3648 switch (This->stateBlock->renderState[WINED3DRS_FOGVERTEXMODE]) {
3649 /* Processed vertices have their fog factor stored in the specular value. Fall too the none case.
3650 * If we are drawing untransformed vertices atm, d3ddevice_set_ortho will update the fog
3652 case WINED3DFOG_EXP: {
3653 if(!This->last_was_rhw) {
3654 glFogi(GL_FOG_MODE, GL_EXP);
3655 checkGLcall("glFogi(GL_FOG_MODE, GL_EXP");
3656 if(GL_SUPPORT(EXT_FOG_COORD)) {
3657 glFogi(GL_FOG_COORDINATE_SOURCE_EXT, GL_FRAGMENT_DEPTH_EXT);
3658 checkGLcall("glFogi(GL_FOG_COORDINATE_SOURCE_EXT, GL_FRAGMENT_DEPTH_EXT");
3659 IWineD3DDevice_SetRenderState(iface, WINED3DRS_FOGSTART, This->stateBlock->renderState[WINED3DRS_FOGSTART]);
3660 IWineD3DDevice_SetRenderState(iface, WINED3DRS_FOGEND, This->stateBlock->renderState[WINED3DRS_FOGEND]);
3665 case WINED3DFOG_EXP2: {
3666 if(!This->last_was_rhw) {
3667 glFogi(GL_FOG_MODE, GL_EXP2);
3668 checkGLcall("glFogi(GL_FOG_MODE, GL_EXP2");
3669 if(GL_SUPPORT(EXT_FOG_COORD)) {
3670 glFogi(GL_FOG_COORDINATE_SOURCE_EXT, GL_FRAGMENT_DEPTH_EXT);
3671 checkGLcall("glFogi(GL_FOG_COORDINATE_SOURCE_EXT, GL_FRAGMENT_DEPTH_EXT");
3672 IWineD3DDevice_SetRenderState(iface, WINED3DRS_FOGSTART, This->stateBlock->renderState[WINED3DRS_FOGSTART]);
3673 IWineD3DDevice_SetRenderState(iface, WINED3DRS_FOGEND, This->stateBlock->renderState[WINED3DRS_FOGEND]);
3678 case WINED3DFOG_LINEAR: {
3679 if(!This->last_was_rhw) {
3680 glFogi(GL_FOG_MODE, GL_LINEAR);
3681 checkGLcall("glFogi(GL_FOG_MODE, GL_LINEAR");
3682 if(GL_SUPPORT(EXT_FOG_COORD)) {
3683 glFogi(GL_FOG_COORDINATE_SOURCE_EXT, GL_FRAGMENT_DEPTH_EXT);
3684 checkGLcall("glFogi(GL_FOG_COORDINATE_SOURCE_EXT, GL_FRAGMENT_DEPTH_EXT");
3685 IWineD3DDevice_SetRenderState(iface, WINED3DRS_FOGSTART, This->stateBlock->renderState[WINED3DRS_FOGSTART]);
3686 IWineD3DDevice_SetRenderState(iface, WINED3DRS_FOGEND, This->stateBlock->renderState[WINED3DRS_FOGEND]);
3691 case WINED3DFOG_NONE: {
3692 /* Both are none? According to msdn the alpha channel of the specular
3693 * color contains a fog factor. Set it in drawStridedSlow.
3694 * Same happens with Vertexfog on transformed vertices
3696 if(GL_SUPPORT(EXT_FOG_COORD)) {
3697 glFogi(GL_FOG_COORDINATE_SOURCE_EXT, GL_FOG_COORDINATE_EXT);
3698 checkGLcall("glFogi(GL_FOG_COORDINATE_SOURCE_EXT, GL_FOG_COORDINATE_EXT)\n");
3699 glFogi(GL_FOG_MODE, GL_LINEAR);
3700 checkGLcall("glFogi(GL_FOG_MODE, GL_LINEAR)");
3701 glFogf(GL_FOG_START, (float) 0xff);
3702 checkGLcall("glFogfv GL_FOG_START");
3703 glFogf(GL_FOG_END, 0.0);
3704 checkGLcall("glFogfv GL_FOG_END");
3706 /* Disable GL fog, handle this in software in drawStridedSlow */
3708 checkGLcall("glDisable(GL_FOG)");
3712 default: FIXME("Unexpected WINED3DRS_FOGVERTEXMODE %d\n", This->stateBlock->renderState[WINED3DRS_FOGVERTEXMODE]);
3715 glHint(GL_FOG_HINT, GL_NICEST);
3716 checkGLcall("glHint(GL_FOG_HINT, GL_NICEST)");
3717 switch (This->stateBlock->renderState[WINED3DRS_FOGTABLEMODE]) {
3718 case WINED3DFOG_EXP:
3719 glFogi(GL_FOG_MODE, GL_EXP);
3720 checkGLcall("glFogi(GL_FOG_MODE, GL_EXP");
3721 if(GL_SUPPORT(EXT_FOG_COORD)) {
3722 glFogi(GL_FOG_COORDINATE_SOURCE_EXT, GL_FRAGMENT_DEPTH_EXT);
3723 checkGLcall("glFogi(GL_FOG_COORDINATE_SOURCE_EXT, GL_FRAGMENT_DEPTH_EXT");
3724 IWineD3DDevice_SetRenderState(iface, WINED3DRS_FOGSTART, This->stateBlock->renderState[WINED3DRS_FOGSTART]);
3725 IWineD3DDevice_SetRenderState(iface, WINED3DRS_FOGEND, This->stateBlock->renderState[WINED3DRS_FOGEND]);
3728 case WINED3DFOG_EXP2:
3729 glFogi(GL_FOG_MODE, GL_EXP2);
3730 checkGLcall("glFogi(GL_FOG_MODE, GL_EXP2");
3731 if(GL_SUPPORT(EXT_FOG_COORD)) {
3732 glFogi(GL_FOG_COORDINATE_SOURCE_EXT, GL_FRAGMENT_DEPTH_EXT);
3733 checkGLcall("glFogi(GL_FOG_COORDINATE_SOURCE_EXT, GL_FRAGMENT_DEPTH_EXT");
3734 IWineD3DDevice_SetRenderState(iface, WINED3DRS_FOGSTART, This->stateBlock->renderState[WINED3DRS_FOGSTART]);
3735 IWineD3DDevice_SetRenderState(iface, WINED3DRS_FOGEND, This->stateBlock->renderState[WINED3DRS_FOGEND]);
3738 case WINED3DFOG_LINEAR:
3739 glFogi(GL_FOG_MODE, GL_LINEAR);
3740 checkGLcall("glFogi(GL_FOG_MODE, GL_LINEAR");
3741 if(GL_SUPPORT(EXT_FOG_COORD)) {
3742 glFogi(GL_FOG_COORDINATE_SOURCE_EXT, GL_FRAGMENT_DEPTH_EXT);
3743 checkGLcall("glFogi(GL_FOG_COORDINATE_SOURCE_EXT, GL_FRAGMENT_DEPTH_EXT");
3744 IWineD3DDevice_SetRenderState(iface, WINED3DRS_FOGSTART, This->stateBlock->renderState[WINED3DRS_FOGSTART]);
3745 IWineD3DDevice_SetRenderState(iface, WINED3DRS_FOGEND, This->stateBlock->renderState[WINED3DRS_FOGEND]);
3748 case WINED3DFOG_NONE:
3749 default: /* Won't happen */
3750 FIXME("Unexpected WINED3DRS_FOGTABLEMODE %d\n", This->stateBlock->renderState[WINED3DRS_FOGTABLEMODE]);
3753 if (GL_SUPPORT(NV_FOG_DISTANCE)) {
3754 glFogi(GL_FOG_DISTANCE_MODE_NV, GL_EYE_PLANE_ABSOLUTE_NV);
3759 case WINED3DRS_FOGSTART :
3762 glFogfv(GL_FOG_START, &tmpvalue.f);
3763 checkGLcall("glFogf(GL_FOG_START, (float) Value)");
3764 TRACE("Fog Start == %f\n", tmpvalue.f);
3768 case WINED3DRS_FOGEND :
3771 glFogfv(GL_FOG_END, &tmpvalue.f);
3772 checkGLcall("glFogf(GL_FOG_END, (float) Value)");
3773 TRACE("Fog End == %f\n", tmpvalue.f);
3777 case WINED3DRS_FOGDENSITY :
3780 glFogfv(GL_FOG_DENSITY, &tmpvalue.f);
3781 checkGLcall("glFogf(GL_FOG_DENSITY, (float) Value)");
3785 case WINED3DRS_VERTEXBLEND :
3787 This->updateStateBlock->vertex_blend = (WINED3DVERTEXBLENDFLAGS) Value;
3788 TRACE("Vertex Blending state to %d\n", Value);
3792 case WINED3DRS_TWEENFACTOR :
3795 This->updateStateBlock->tween_factor = tmpvalue.f;
3796 TRACE("Vertex Blending Tween Factor to %f\n", This->updateStateBlock->tween_factor);
3800 case WINED3DRS_INDEXEDVERTEXBLENDENABLE :
3802 TRACE("Indexed Vertex Blend Enable to %u\n", (BOOL) Value);
3806 case WINED3DRS_COLORVERTEX :
3807 case WINED3DRS_DIFFUSEMATERIALSOURCE :
3808 case WINED3DRS_SPECULARMATERIALSOURCE :
3809 case WINED3DRS_AMBIENTMATERIALSOURCE :
3810 case WINED3DRS_EMISSIVEMATERIALSOURCE :
3812 GLenum Parm = GL_AMBIENT_AND_DIFFUSE;
3814 if (This->stateBlock->renderState[WINED3DRS_COLORVERTEX]) {
3815 TRACE("diff %d, amb %d, emis %d, spec %d\n",
3816 This->stateBlock->renderState[WINED3DRS_DIFFUSEMATERIALSOURCE],
3817 This->stateBlock->renderState[WINED3DRS_AMBIENTMATERIALSOURCE],
3818 This->stateBlock->renderState[WINED3DRS_EMISSIVEMATERIALSOURCE],
3819 This->stateBlock->renderState[WINED3DRS_SPECULARMATERIALSOURCE]);
3821 if (This->stateBlock->renderState[WINED3DRS_DIFFUSEMATERIALSOURCE] == WINED3DMCS_COLOR1) {
3822 if (This->stateBlock->renderState[WINED3DRS_AMBIENTMATERIALSOURCE] == WINED3DMCS_COLOR1) {
3823 Parm = GL_AMBIENT_AND_DIFFUSE;
3827 } else if (This->stateBlock->renderState[WINED3DRS_AMBIENTMATERIALSOURCE] == WINED3DMCS_COLOR1) {
3829 } else if (This->stateBlock->renderState[WINED3DRS_EMISSIVEMATERIALSOURCE] == WINED3DMCS_COLOR1) {
3831 } else if (This->stateBlock->renderState[WINED3DRS_SPECULARMATERIALSOURCE] == WINED3DMCS_COLOR1) {
3838 if (This->tracking_color != DISABLED_TRACKING) This->tracking_color = NEEDS_DISABLE;
3840 This->tracking_color = NEEDS_TRACKING;
3841 This->tracking_parm = Parm;
3845 if (This->tracking_color != DISABLED_TRACKING) This->tracking_color = NEEDS_DISABLE;
3850 case WINED3DRS_LINEPATTERN :
3854 WINED3DLINEPATTERN lp;
3856 tmppattern.d = Value;
3858 TRACE("Line pattern: repeat %d bits %x\n", tmppattern.lp.wRepeatFactor, tmppattern.lp.wLinePattern);
3860 if (tmppattern.lp.wRepeatFactor) {
3861 glLineStipple(tmppattern.lp.wRepeatFactor, tmppattern.lp.wLinePattern);
3862 checkGLcall("glLineStipple(repeat, linepattern)");
3863 glEnable(GL_LINE_STIPPLE);
3864 checkGLcall("glEnable(GL_LINE_STIPPLE);");
3866 glDisable(GL_LINE_STIPPLE);
3867 checkGLcall("glDisable(GL_LINE_STIPPLE);");
3872 case WINED3DRS_ZBIAS : /* D3D8 only */
3876 TRACE("ZBias value %f\n", tmpvalue.f);
3877 glPolygonOffset(0, -tmpvalue.f);
3878 checkGLcall("glPolygonOffset(0, -Value)");
3879 glEnable(GL_POLYGON_OFFSET_FILL);
3880 checkGLcall("glEnable(GL_POLYGON_OFFSET_FILL);");
3881 glEnable(GL_POLYGON_OFFSET_LINE);
3882 checkGLcall("glEnable(GL_POLYGON_OFFSET_LINE);");
3883 glEnable(GL_POLYGON_OFFSET_POINT);
3884 checkGLcall("glEnable(GL_POLYGON_OFFSET_POINT);");
3886 glDisable(GL_POLYGON_OFFSET_FILL);
3887 checkGLcall("glDisable(GL_POLYGON_OFFSET_FILL);");
3888 glDisable(GL_POLYGON_OFFSET_LINE);
3889 checkGLcall("glDisable(GL_POLYGON_OFFSET_LINE);");
3890 glDisable(GL_POLYGON_OFFSET_POINT);
3891 checkGLcall("glDisable(GL_POLYGON_OFFSET_POINT);");
3896 case WINED3DRS_NORMALIZENORMALS :
3898 glEnable(GL_NORMALIZE);
3899 checkGLcall("glEnable(GL_NORMALIZE);");
3901 glDisable(GL_NORMALIZE);
3902 checkGLcall("glDisable(GL_NORMALIZE);");
3906 case WINED3DRS_POINTSIZE :
3907 /* FIXME: check that pointSize isn't outside glGetFloatv( GL_POINT_SIZE_MAX_ARB, &maxSize ); or -ve */
3909 TRACE("Set point size to %f\n", tmpvalue.f);
3910 glPointSize(tmpvalue.f);
3911 checkGLcall("glPointSize(...);");
3914 case WINED3DRS_POINTSIZE_MIN :
3915 if (GL_SUPPORT(EXT_POINT_PARAMETERS)) {
3917 GL_EXTCALL(glPointParameterfEXT)(GL_POINT_SIZE_MIN_EXT, tmpvalue.f);
3918 checkGLcall("glPointParameterfEXT(...);");
3920 FIXME("WINED3DRS_POINTSIZE_MIN not supported on this opengl\n");
3924 case WINED3DRS_POINTSIZE_MAX :
3925 if (GL_SUPPORT(EXT_POINT_PARAMETERS)) {
3927 GL_EXTCALL(glPointParameterfEXT)(GL_POINT_SIZE_MAX_EXT, tmpvalue.f);
3928 checkGLcall("glPointParameterfEXT(...);");
3930 FIXME("WINED3DRS_POINTSIZE_MAX not supported on this opengl\n");
3934 case WINED3DRS_POINTSCALE_A :
3935 case WINED3DRS_POINTSCALE_B :
3936 case WINED3DRS_POINTSCALE_C :
3937 case WINED3DRS_POINTSCALEENABLE :
3940 * POINTSCALEENABLE controls how point size value is treated. If set to
3941 * true, the point size is scaled with respect to height of viewport.
3942 * When set to false point size is in pixels.
3944 * http://msdn.microsoft.com/library/en-us/directx9_c/point_sprites.asp
3947 /* Default values */
3948 GLfloat att[3] = {1.0f, 0.0f, 0.0f};
3951 * Minimum valid point size for OpenGL is 1.0f. For Direct3D it is 0.0f.
3952 * This means that OpenGL will clamp really small point sizes to 1.0f.
3953 * To correct for this we need to multiply by the scale factor when sizes
3954 * are less than 1.0f. scale_factor = 1.0f / point_size.
3956 GLfloat pointSize = *((float*)&This->stateBlock->renderState[WINED3DRS_POINTSIZE]);
3957 if(pointSize > 0.0f) {
3958 GLfloat scaleFactor;
3960 if(pointSize < 1.0f) {
3961 scaleFactor = pointSize * pointSize;
3966 if(This->stateBlock->renderState[WINED3DRS_POINTSCALEENABLE]) {
3967 att[0] = *((float*)&This->stateBlock->renderState[WINED3DRS_POINTSCALE_A]) /
3968 (This->stateBlock->viewport.Height * This->stateBlock->viewport.Height * scaleFactor);
3969 att[1] = *((float*)&This->stateBlock->renderState[WINED3DRS_POINTSCALE_B]) /
3970 (This->stateBlock->viewport.Height * This->stateBlock->viewport.Height * scaleFactor);
3971 att[2] = *((float*)&This->stateBlock->renderState[WINED3DRS_POINTSCALE_C]) /
3972 (This->stateBlock->viewport.Height * This->stateBlock->viewport.Height * scaleFactor);
3976 if(GL_SUPPORT(ARB_POINT_PARAMETERS)) {
3977 GL_EXTCALL(glPointParameterfvARB)(GL_POINT_DISTANCE_ATTENUATION_ARB, att);
3978 checkGLcall("glPointParameterfvARB(GL_DISTANCE_ATTENUATION_ARB, ...");
3980 else if(GL_SUPPORT(EXT_POINT_PARAMETERS)) {
3981 GL_EXTCALL(glPointParameterfvEXT)(GL_DISTANCE_ATTENUATION_EXT, att);
3982 checkGLcall("glPointParameterfvEXT(GL_DISTANCE_ATTENUATION_EXT, ...");
3984 TRACE("POINT_PARAMETERS not supported in this version of opengl\n");
3988 case WINED3DRS_COLORWRITEENABLE :
3990 TRACE("Color mask: r(%d) g(%d) b(%d) a(%d)\n",
3991 Value & WINED3DCOLORWRITEENABLE_RED ? 1 : 0,
3992 Value & WINED3DCOLORWRITEENABLE_GREEN ? 1 : 0,
3993 Value & WINED3DCOLORWRITEENABLE_BLUE ? 1 : 0,
3994 Value & WINED3DCOLORWRITEENABLE_ALPHA ? 1 : 0);
3995 glColorMask(Value & WINED3DCOLORWRITEENABLE_RED ? GL_TRUE : GL_FALSE,
3996 Value & WINED3DCOLORWRITEENABLE_GREEN ? GL_TRUE : GL_FALSE,
3997 Value & WINED3DCOLORWRITEENABLE_BLUE ? GL_TRUE : GL_FALSE,
3998 Value & WINED3DCOLORWRITEENABLE_ALPHA ? GL_TRUE : GL_FALSE);
3999 checkGLcall("glColorMask(...)");
4003 case WINED3DRS_LOCALVIEWER :
4005 GLint state = (Value) ? 1 : 0;
4006 TRACE("Local Viewer Enable to %ul\n", (BOOL) Value);
4007 glLightModeli(GL_LIGHT_MODEL_LOCAL_VIEWER, state);
4011 case WINED3DRS_LASTPIXEL :
4014 TRACE("Last Pixel Drawing Enabled\n");
4016 FIXME("Last Pixel Drawing Disabled, not handled yet\n");
4021 case WINED3DRS_SOFTWAREVERTEXPROCESSING :
4024 TRACE("Software Processing Enabled\n");
4026 TRACE("Software Processing Disabled\n");
4031 /** not supported */
4032 case WINED3DRS_ZVISIBLE :
4035 return WINED3DERR_INVALIDCALL;
4037 case WINED3DRS_POINTSPRITEENABLE :
4039 /* TODO: NV_POINT_SPRITE */
4040 if (!GL_SUPPORT(ARB_POINT_SPRITE)) {
4041 TRACE("Point sprites not supported\n");
4046 * Point sprites are always enabled. Value controls texture coordinate
4047 * replacement mode. Must be set true for point sprites to use
4050 glEnable(GL_POINT_SPRITE_ARB);
4051 checkGLcall("glEnable(GL_POINT_SPRITE_ARB)");
4054 glTexEnvf(GL_POINT_SPRITE_ARB, GL_COORD_REPLACE_ARB, TRUE);
4055 checkGLcall("glTexEnvf(GL_POINT_SPRITE, GL_COORD_REPLACE, TRUE)");
4057 glTexEnvf(GL_POINT_SPRITE_ARB, GL_COORD_REPLACE_ARB, FALSE);
4058 checkGLcall("glTexEnvf(GL_POINT_SPRITE, GL_COORD_REPLACE, FALSE)");
4063 case WINED3DRS_WRAP0 :
4064 case WINED3DRS_WRAP1 :
4065 case WINED3DRS_WRAP2 :
4066 case WINED3DRS_WRAP3 :
4067 case WINED3DRS_WRAP4 :
4068 case WINED3DRS_WRAP5 :
4069 case WINED3DRS_WRAP6 :
4070 case WINED3DRS_WRAP7 :
4071 case WINED3DRS_WRAP8 :
4072 case WINED3DRS_WRAP9 :
4073 case WINED3DRS_WRAP10 :
4074 case WINED3DRS_WRAP11 :
4075 case WINED3DRS_WRAP12 :
4076 case WINED3DRS_WRAP13 :
4077 case WINED3DRS_WRAP14 :
4078 case WINED3DRS_WRAP15 :
4080 http://www.cosc.brocku.ca/Offerings/3P98/course/lectures/texture/
4081 http://msdn.microsoft.com/archive/default.asp?url=/archive/en-us/directx9_c/directx/graphics/programmingguide/FixedFunction/Textures/texturewrapping.asp
4082 http://www.gamedev.net/reference/programming/features/rendererdll3/page2.asp
4083 Descussion that ways to turn on WRAPing to solve an opengl conversion problem.
4084 http://www.flipcode.org/cgi-bin/fcmsg.cgi?thread_show=10248
4086 so far as I can tell, wrapping and texture-coordinate generate go hand in hand,
4090 ERR("(%p)->(%s,%d) Texture wraping not yet supported\n",This, debug_d3drenderstate(State), Value);
4095 case WINED3DRS_MULTISAMPLEANTIALIAS :
4097 if( GL_SUPPORT(ARB_MULTISAMPLE) ) {
4099 glEnable(GL_MULTISAMPLE_ARB);
4100 checkGLcall("glEnable(GL_MULTISAMPLE_ARB)");
4102 glDisable(GL_MULTISAMPLE_ARB);
4103 checkGLcall("glDisable(GL_MULTISAMPLE_ARB)");
4107 ERR("Multisample antialiasing not supported by gl\n");
4113 case WINED3DRS_SCISSORTESTENABLE :
4116 glEnable(GL_SCISSOR_TEST);
4117 checkGLcall("glEnable(GL_SCISSOR_TEST)");
4119 glDisable(GL_SCISSOR_TEST);
4120 checkGLcall("glDisable(GL_SCISSOR_TEST)");
4124 case WINED3DRS_SLOPESCALEDEPTHBIAS :
4128 glEnable(GL_POLYGON_OFFSET_FILL);
4129 checkGLcall("glEnable(GL_POLYGON_OFFSET_FILL)");
4130 glPolygonOffset(tmpvalue.f, *((float*)&This->stateBlock->renderState[WINED3DRS_DEPTHBIAS]));
4131 checkGLcall("glPolygonOffset(...)");
4133 glDisable(GL_POLYGON_OFFSET_FILL);
4134 checkGLcall("glDisable(GL_POLYGON_OFFSET_FILL)");
4140 glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
4142 checkGLcall("glEnable(GL_BLEND)");
4143 glEnable(GL_LINE_SMOOTH);
4144 checkGLcall("glEnable(GL_LINE_SMOOTH)");
4146 glDisable(GL_BLEND);
4147 checkGLcall("glDisable(GL_BLEND)");
4148 glDisable(GL_LINE_SMOOTH);
4149 checkGLcall("glDisable(GL_LINE_SMOOTH)");
4154 case WINED3DRS_DEPTHBIAS :
4158 glEnable(GL_POLYGON_OFFSET_FILL);
4159 checkGLcall("glEnable(GL_POLYGON_OFFSET_FILL)");
4160 glPolygonOffset(*((float*)&This->stateBlock->renderState[WINED3DRS_SLOPESCALEDEPTHBIAS]), tmpvalue.f);
4161 checkGLcall("glPolygonOffset(...)");
4163 glDisable(GL_POLYGON_OFFSET_FILL);
4164 checkGLcall("glDisable(GL_POLYGON_OFFSET_FILL)");
4169 case WINED3DRS_TEXTUREPERSPECTIVE :
4172 glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST);
4174 glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_FASTEST);
4178 case WINED3DRS_STIPPLEDALPHA :
4181 ERR(" Stippled Alpha not supported yet.\n");
4184 case WINED3DRS_ANTIALIAS :
4187 ERR(" Antialias not supported yet.\n");
4191 case WINED3DRS_MULTISAMPLEMASK :
4193 if(0xFFFFFFFF != Value)
4194 ERR("(%p)->(%s,%d) not yet implemented\n", This, debug_d3drenderstate(State), Value);
4198 case WINED3DRS_PATCHEDGESTYLE :
4200 if(WINED3DPATCHEDGE_DISCRETE != Value)
4201 ERR("(%p)->(%s,%d) not yet implemented\n", This, debug_d3drenderstate(State), Value);
4205 case WINED3DRS_PATCHSEGMENTS :
4207 /* available in d3d8 but in d3d9 it was replaced by IDirect3DDevice9::SetNPatchMode */
4209 if(tmpvalue.d != Value)
4210 ERR("(%p)->(%s,%d) not yet implemented\n", This, debug_d3drenderstate(State), Value);
4214 case WINED3DRS_DEBUGMONITORTOKEN :
4216 /* Only useful for "debug builds". */
4217 if(0xbaadcafe != Value) {
4218 /* MSDN says the default is D3DDMT_ENABLE but our tests confirm 0xbaadcafe is the default. */
4219 /* MSDN says anything other than D3DDMT_ENABLE or DISABLE does not change the state,
4220 * but our tests disagree.
4221 * We do not claim to implement a debugging lib, so do not write an ERR
4223 WARN("(%p)->(%s,%d) not yet implemented\n", This, debug_d3drenderstate(State), Value);
4228 case WINED3DRS_POSITIONDEGREE :
4230 if(WINED3DDEGREE_CUBIC != Value)
4231 ERR("(%p)->(%s,%d) not yet implemented\n", This, debug_d3drenderstate(State), Value);
4235 case WINED3DRS_NORMALDEGREE :
4237 if(WINED3DDEGREE_LINEAR != Value)
4238 ERR("(%p)->(%s,%d) not yet implemented\n", This, debug_d3drenderstate(State), Value);
4242 case WINED3DRS_MINTESSELLATIONLEVEL :
4243 case WINED3DRS_MAXTESSELLATIONLEVEL :
4244 case WINED3DRS_ADAPTIVETESS_X :
4245 case WINED3DRS_ADAPTIVETESS_Y :
4246 case WINED3DRS_ADAPTIVETESS_Z :
4247 case WINED3DRS_ADAPTIVETESS_W :
4249 if(This->stateBlock->renderState[WINED3DRS_ENABLEADAPTIVETESSELLATION])
4250 FIXME("(%p)->(%s,%d) not yet implemented\n", This, debug_d3drenderstate(State), Value);
4252 TRACE("(%p)->(%s,%d): recording state but WINED3DRS_ENABLEADAPTIVETESSELLATION is not enabled\n", This, debug_d3drenderstate(State), Value);
4256 case WINED3DRS_ENABLEADAPTIVETESSELLATION:
4259 ERR("(%p)->(%s,%d) not yet implemented\n", This, debug_d3drenderstate(State), Value);
4263 case WINED3DRS_COLORWRITEENABLE1 :
4264 case WINED3DRS_COLORWRITEENABLE2 :
4265 case WINED3DRS_COLORWRITEENABLE3 :
4267 /* depends on WINED3DRS_COLORWRITEENABLE. */
4268 if(0x0000000F != Value)
4269 ERR("(%p)->(%s,%d) not yet implemented. Missing of cap D3DPMISCCAPS_INDEPENDENTWRITEMASKS wasn't honored?\n", This, debug_d3drenderstate(State), Value);
4273 case WINED3DRS_SRGBWRITEENABLE :
4276 ERR("(%p)->(%s,%d) not yet implemented\n", This, debug_d3drenderstate(State), Value);
4280 case WINED3DRS_SEPARATEALPHABLENDENABLE :
4283 ERR("(%p)->(%s,%d) not yet implemented. Missing of cap D3DPMISCCAPS_SEPARATEALPHABLEND wasn't honored?\n", This, debug_d3drenderstate(State), Value);
4287 case WINED3DRS_SRCBLENDALPHA :
4288 case WINED3DRS_DESTBLENDALPHA :
4289 case WINED3DRS_BLENDOPALPHA :
4291 if(This->stateBlock->renderState[WINED3DRS_SEPARATEALPHABLENDENABLE])
4292 FIXME("(%p)->(%s,%d) not yet implemented\n", This, debug_d3drenderstate(State), Value);
4294 TRACE("(%p)->(%s,%d): recording state but WINED3DRS_SEPARATEALPHABLENDENABLE is not enabled\n", This, debug_d3drenderstate(State), Value);
4299 FIXME("(%p)->(%s,%d) unknown state\n", This, debug_d3drenderstate(State), Value);
4307 static HRESULT WINAPI IWineD3DDeviceImpl_GetRenderState(IWineD3DDevice *iface, WINED3DRENDERSTATETYPE State, DWORD *pValue) {
4308 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4309 TRACE("(%p) for State %d = %d\n", This, State, This->stateBlock->renderState[State]);
4310 *pValue = This->stateBlock->renderState[State];
4315 * Get / Set Sampler States
4316 * TODO: Verify against dx9 definitions
4319 static HRESULT WINAPI IWineD3DDeviceImpl_SetSamplerState(IWineD3DDevice *iface, DWORD Sampler, WINED3DSAMPLERSTATETYPE Type, DWORD Value) {
4320 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4322 * SetSampler is designed to allow for more than the standard up to 8 textures
4323 * and Geforce has stopped supporting more than 6 standard textures in openGL.
4324 * So I have to use ARB for Gforce. (maybe if the sampler > 4 then use ARB?)
4326 * http://developer.nvidia.com/object/General_FAQ.html#t6
4328 * There are two new settings for GForce
4330 * GL_MAX_TEXTURE_IMAGE_UNITS_ARB
4331 * and the texture one:
4332 * GL_MAX_TEXTURE_COORDS_ARB.
4333 * Ok GForce say it's ok to use glTexParameter/glGetTexParameter(...).
4335 /** NOTE: States are appled in IWineD3DBaseTextre ApplyStateChanges and IWineD3DDevice SetupTextureStates**/
4336 if(Sampler > GL_LIMITS(sampler_stages) || Sampler < 0 || Type > WINED3D_HIGHEST_SAMPLER_STATE || Type < 0) {
4337 FIXME("sampler %d type %s(%u) is out of range [max_samplers=%d, highest_state=%d]\n",
4338 Sampler, debug_d3dsamplerstate(Type), Type, GL_LIMITS(sampler_stages), WINED3D_HIGHEST_SAMPLER_STATE);
4339 return WINED3DERR_INVALIDCALL;
4342 TRACE("(%p) : Sampler=%d, Type=%s(%d), Value=%d\n", This, Sampler,
4343 debug_d3dsamplerstate(Type), Type, Value);
4344 This->updateStateBlock->samplerState[Sampler][Type] = Value;
4345 This->updateStateBlock->set.samplerState[Sampler][Type] = Value;
4346 This->updateStateBlock->changed.samplerState[Sampler][Type] = Value;
4348 /* Handle recording of state blocks */
4349 if (This->isRecordingState) {
4350 TRACE("Recording... not performing anything\n");
4357 static HRESULT WINAPI IWineD3DDeviceImpl_GetSamplerState(IWineD3DDevice *iface, DWORD Sampler, WINED3DSAMPLERSTATETYPE Type, DWORD* Value) {
4358 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4359 /** TODO: check that sampler is in range **/
4360 *Value = This->stateBlock->samplerState[Sampler][Type];
4361 TRACE("(%p) : Sampler %d Type %u Returning %d\n", This, Sampler, Type, *Value);
4366 static HRESULT WINAPI IWineD3DDeviceImpl_SetScissorRect(IWineD3DDevice *iface, CONST RECT* pRect) {
4367 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4371 GetClientRect(((IWineD3DSwapChainImpl *)This->swapchains[0])->win_handle, &windowRect);
4372 /* Warning: glScissor uses window coordinates, not viewport coordinates, so our viewport correction does not apply
4373 * Warning2: Even in windowed mode the coords are relative to the window, not the screen
4375 winHeight = windowRect.bottom - windowRect.top;
4376 TRACE("(%p)Setting new Scissor Rect to %d:%d-%d:%d\n", This, pRect->left, pRect->bottom - winHeight,
4377 pRect->right - pRect->left, pRect->bottom - pRect->top);
4379 glScissor(pRect->left, winHeight - pRect->bottom, pRect->right - pRect->left, pRect->bottom - pRect->top);
4380 checkGLcall("glScissor");
4386 static HRESULT WINAPI IWineD3DDeviceImpl_GetScissorRect(IWineD3DDevice *iface, RECT* pRect) {
4387 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4388 GLint scissorBox[4];
4391 /** FIXME: Windows uses a top,left origin openGL uses a bottom Right? **/
4392 glGetIntegerv(GL_SCISSOR_BOX, scissorBox);
4393 pRect->left = scissorBox[0];
4394 pRect->top = scissorBox[1];
4395 pRect->right = scissorBox[0] + scissorBox[2];
4396 pRect->bottom = scissorBox[1] + scissorBox[3];
4397 TRACE("(%p)Returning a Scissor Rect of %d:%d-%d:%d\n", This, pRect->left, pRect->top, pRect->right, pRect->bottom);
4402 static HRESULT WINAPI IWineD3DDeviceImpl_SetVertexDeclaration(IWineD3DDevice* iface, IWineD3DVertexDeclaration* pDecl) {
4403 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *) iface;
4404 IWineD3DVertexDeclaration *oldDecl = This->updateStateBlock->vertexDecl;
4406 TRACE("(%p) : pDecl=%p\n", This, pDecl);
4408 This->updateStateBlock->vertexDecl = pDecl;
4409 This->updateStateBlock->changed.vertexDecl = TRUE;
4410 This->updateStateBlock->set.vertexDecl = TRUE;
4412 if (This->isRecordingState) {
4413 TRACE("Recording... not performing anything\n");
4416 if (NULL != pDecl) {
4417 IWineD3DVertexDeclaration_AddRef(pDecl);
4419 if (NULL != oldDecl) {
4420 IWineD3DVertexDeclaration_Release(oldDecl);
4425 static HRESULT WINAPI IWineD3DDeviceImpl_GetVertexDeclaration(IWineD3DDevice* iface, IWineD3DVertexDeclaration** ppDecl) {
4426 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4428 TRACE("(%p) : ppDecl=%p\n", This, ppDecl);
4430 *ppDecl = This->stateBlock->vertexDecl;
4431 if (NULL != *ppDecl) IWineD3DVertexDeclaration_AddRef(*ppDecl);
4435 static HRESULT WINAPI IWineD3DDeviceImpl_SetVertexShader(IWineD3DDevice *iface, IWineD3DVertexShader* pShader) {
4436 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4437 IWineD3DVertexShader* oldShader = This->updateStateBlock->vertexShader;
4439 This->updateStateBlock->vertexShader = pShader;
4440 This->updateStateBlock->changed.vertexShader = TRUE;
4441 This->updateStateBlock->set.vertexShader = TRUE;
4443 if (This->isRecordingState) {
4444 TRACE("Recording... not performing anything\n");
4447 if (NULL != pShader) {
4448 IWineD3DVertexShader_AddRef(pShader);
4450 if (NULL != oldShader) {
4451 IWineD3DVertexShader_Release(oldShader);
4454 TRACE("(%p) : setting pShader(%p)\n", This, pShader);
4456 * TODO: merge HAL shaders context switching from prototype
4461 static HRESULT WINAPI IWineD3DDeviceImpl_GetVertexShader(IWineD3DDevice *iface, IWineD3DVertexShader** ppShader) {
4462 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4464 if (NULL == ppShader) {
4465 return WINED3DERR_INVALIDCALL;
4467 *ppShader = This->stateBlock->vertexShader;
4468 if( NULL != *ppShader)
4469 IWineD3DVertexShader_AddRef(*ppShader);
4471 TRACE("(%p) : returning %p\n", This, *ppShader);
4475 static HRESULT WINAPI IWineD3DDeviceImpl_SetVertexShaderConstantB(
4476 IWineD3DDevice *iface,
4478 CONST BOOL *srcData,
4481 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4482 int i, cnt = min(count, MAX_CONST_B - start);
4484 TRACE("(iface %p, srcData %p, start %d, count %d)\n",
4485 iface, srcData, start, count);
4487 if (srcData == NULL || cnt < 0)
4488 return WINED3DERR_INVALIDCALL;
4490 memcpy(&This->updateStateBlock->vertexShaderConstantB[start], srcData, cnt * sizeof(BOOL));
4491 for (i = 0; i < cnt; i++)
4492 TRACE("Set BOOL constant %u to %s\n", start + i, srcData[i]? "true":"false");
4494 for (i = start; i < cnt + start; ++i) {
4495 This->updateStateBlock->changed.vertexShaderConstantsB[i] = TRUE;
4496 This->updateStateBlock->set.vertexShaderConstantsB[i] = TRUE;
4502 static HRESULT WINAPI IWineD3DDeviceImpl_GetVertexShaderConstantB(
4503 IWineD3DDevice *iface,
4508 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4509 int cnt = min(count, MAX_CONST_B - start);
4511 TRACE("(iface %p, dstData %p, start %d, count %d)\n",
4512 iface, dstData, start, count);
4514 if (dstData == NULL || cnt < 0)
4515 return WINED3DERR_INVALIDCALL;
4517 memcpy(dstData, &This->stateBlock->vertexShaderConstantB[start], cnt * sizeof(BOOL));
4521 static HRESULT WINAPI IWineD3DDeviceImpl_SetVertexShaderConstantI(
4522 IWineD3DDevice *iface,
4527 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4528 int i, cnt = min(count, MAX_CONST_I - start);
4530 TRACE("(iface %p, srcData %p, start %d, count %d)\n",
4531 iface, srcData, start, count);
4533 if (srcData == NULL || cnt < 0)
4534 return WINED3DERR_INVALIDCALL;
4536 memcpy(&This->updateStateBlock->vertexShaderConstantI[start * 4], srcData, cnt * sizeof(int) * 4);
4537 for (i = 0; i < cnt; i++)
4538 TRACE("Set INT constant %u to { %d, %d, %d, %d }\n", start + i,
4539 srcData[i*4], srcData[i*4+1], srcData[i*4+2], srcData[i*4+3]);
4541 for (i = start; i < cnt + start; ++i) {
4542 This->updateStateBlock->changed.vertexShaderConstantsI[i] = TRUE;
4543 This->updateStateBlock->set.vertexShaderConstantsI[i] = TRUE;
4549 static HRESULT WINAPI IWineD3DDeviceImpl_GetVertexShaderConstantI(
4550 IWineD3DDevice *iface,
4555 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4556 int cnt = min(count, MAX_CONST_I - start);
4558 TRACE("(iface %p, dstData %p, start %d, count %d)\n",
4559 iface, dstData, start, count);
4561 if (dstData == NULL || ((signed int) MAX_CONST_I - (signed int) start) <= (signed int) 0)
4562 return WINED3DERR_INVALIDCALL;
4564 memcpy(dstData, &This->stateBlock->vertexShaderConstantI[start * 4], cnt * sizeof(int) * 4);
4568 static HRESULT WINAPI IWineD3DDeviceImpl_SetVertexShaderConstantF(
4569 IWineD3DDevice *iface,
4571 CONST float *srcData,
4574 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4575 int i, cnt = min(count, GL_LIMITS(vshader_constantsF) - start);
4577 TRACE("(iface %p, srcData %p, start %d, count %d)\n",
4578 iface, srcData, start, count);
4580 if (srcData == NULL || ((signed int) GL_LIMITS(vshader_constantsF) - (signed int) start) <= (signed int) 0)
4581 return WINED3DERR_INVALIDCALL;
4583 memcpy(&This->updateStateBlock->vertexShaderConstantF[start * 4], srcData, cnt * sizeof(float) * 4);
4584 for (i = 0; i < cnt; i++)
4585 TRACE("Set FLOAT constant %u to { %f, %f, %f, %f }\n", start + i,
4586 srcData[i*4], srcData[i*4+1], srcData[i*4+2], srcData[i*4+3]);
4588 for (i = start; i < cnt + start; ++i) {
4589 if (!This->updateStateBlock->set.vertexShaderConstantsF[i]) {
4590 constant_entry *ptr = HeapAlloc(GetProcessHeap(), 0, sizeof(constant_entry));
4592 list_add_head(&This->updateStateBlock->set_vconstantsF, &ptr->entry);
4593 This->updateStateBlock->set.vertexShaderConstantsF[i] = TRUE;
4595 This->updateStateBlock->changed.vertexShaderConstantsF[i] = TRUE;
4601 static HRESULT WINAPI IWineD3DDeviceImpl_GetVertexShaderConstantF(
4602 IWineD3DDevice *iface,
4607 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4608 int cnt = min(count, GL_LIMITS(vshader_constantsF) - start);
4610 TRACE("(iface %p, dstData %p, start %d, count %d)\n",
4611 iface, dstData, start, count);
4613 if (dstData == NULL || cnt < 0)
4614 return WINED3DERR_INVALIDCALL;
4616 memcpy(dstData, &This->stateBlock->vertexShaderConstantF[start * 4], cnt * sizeof(float) * 4);
4620 static HRESULT WINAPI IWineD3DDeviceImpl_SetPixelShader(IWineD3DDevice *iface, IWineD3DPixelShader *pShader) {
4621 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4622 IWineD3DPixelShader *oldShader = This->updateStateBlock->pixelShader;
4623 This->updateStateBlock->pixelShader = pShader;
4624 This->updateStateBlock->changed.pixelShader = TRUE;
4625 This->updateStateBlock->set.pixelShader = TRUE;
4627 /* Handle recording of state blocks */
4628 if (This->isRecordingState) {
4629 TRACE("Recording... not performing anything\n");
4632 if (NULL != pShader) {
4633 IWineD3DPixelShader_AddRef(pShader);
4635 if (NULL != oldShader) {
4636 IWineD3DPixelShader_Release(oldShader);
4639 TRACE("(%p) : setting pShader(%p)\n", This, pShader);
4641 * TODO: merge HAL shaders context switching from prototype
4646 static HRESULT WINAPI IWineD3DDeviceImpl_GetPixelShader(IWineD3DDevice *iface, IWineD3DPixelShader **ppShader) {
4647 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4649 if (NULL == ppShader) {
4650 WARN("(%p) : PShader is NULL, returning INVALIDCALL\n", This);
4651 return WINED3DERR_INVALIDCALL;
4654 *ppShader = This->stateBlock->pixelShader;
4655 if (NULL != *ppShader) {
4656 IWineD3DPixelShader_AddRef(*ppShader);
4658 TRACE("(%p) : returning %p\n", This, *ppShader);
4662 static HRESULT WINAPI IWineD3DDeviceImpl_SetPixelShaderConstantB(
4663 IWineD3DDevice *iface,
4665 CONST BOOL *srcData,
4668 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4669 int i, cnt = min(count, MAX_CONST_B - start);
4671 TRACE("(iface %p, srcData %p, start %d, count %d)\n",
4672 iface, srcData, start, count);
4674 if (srcData == NULL || cnt < 0)
4675 return WINED3DERR_INVALIDCALL;
4677 memcpy(&This->updateStateBlock->pixelShaderConstantB[start], srcData, cnt * sizeof(BOOL));
4678 for (i = 0; i < cnt; i++)
4679 TRACE("Set BOOL constant %u to %s\n", start + i, srcData[i]? "true":"false");
4681 for (i = start; i < cnt + start; ++i) {
4682 This->updateStateBlock->changed.pixelShaderConstantsB[i] = TRUE;
4683 This->updateStateBlock->set.pixelShaderConstantsB[i] = TRUE;
4689 static HRESULT WINAPI IWineD3DDeviceImpl_GetPixelShaderConstantB(
4690 IWineD3DDevice *iface,
4695 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4696 int cnt = min(count, MAX_CONST_B - start);
4698 TRACE("(iface %p, dstData %p, start %d, count %d)\n",
4699 iface, dstData, start, count);
4701 if (dstData == NULL || cnt < 0)
4702 return WINED3DERR_INVALIDCALL;
4704 memcpy(dstData, &This->stateBlock->pixelShaderConstantB[start], cnt * sizeof(BOOL));
4708 static HRESULT WINAPI IWineD3DDeviceImpl_SetPixelShaderConstantI(
4709 IWineD3DDevice *iface,
4714 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4715 int i, cnt = min(count, MAX_CONST_I - start);
4717 TRACE("(iface %p, srcData %p, start %d, count %d)\n",
4718 iface, srcData, start, count);
4720 if (srcData == NULL || cnt < 0)
4721 return WINED3DERR_INVALIDCALL;
4723 memcpy(&This->updateStateBlock->pixelShaderConstantI[start * 4], srcData, cnt * sizeof(int) * 4);
4724 for (i = 0; i < cnt; i++)
4725 TRACE("Set INT constant %u to { %d, %d, %d, %d }\n", start + i,
4726 srcData[i*4], srcData[i*4+1], srcData[i*4+2], srcData[i*4+3]);
4728 for (i = start; i < cnt + start; ++i) {
4729 This->updateStateBlock->changed.pixelShaderConstantsI[i] = TRUE;
4730 This->updateStateBlock->set.pixelShaderConstantsI[i] = TRUE;
4736 static HRESULT WINAPI IWineD3DDeviceImpl_GetPixelShaderConstantI(
4737 IWineD3DDevice *iface,
4742 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4743 int cnt = min(count, MAX_CONST_I - start);
4745 TRACE("(iface %p, dstData %p, start %d, count %d)\n",
4746 iface, dstData, start, count);
4748 if (dstData == NULL || cnt < 0)
4749 return WINED3DERR_INVALIDCALL;
4751 memcpy(dstData, &This->stateBlock->pixelShaderConstantI[start * 4], cnt * sizeof(int) * 4);
4755 static HRESULT WINAPI IWineD3DDeviceImpl_SetPixelShaderConstantF(
4756 IWineD3DDevice *iface,
4758 CONST float *srcData,
4761 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4762 int i, cnt = min(count, GL_LIMITS(pshader_constantsF) - start);
4764 TRACE("(iface %p, srcData %p, start %d, count %d)\n",
4765 iface, srcData, start, count);
4767 if (srcData == NULL || cnt < 0)
4768 return WINED3DERR_INVALIDCALL;
4770 memcpy(&This->updateStateBlock->pixelShaderConstantF[start * 4], srcData, cnt * sizeof(float) * 4);
4771 for (i = 0; i < cnt; i++)
4772 TRACE("Set FLOAT constant %u to { %f, %f, %f, %f }\n", start + i,
4773 srcData[i*4], srcData[i*4+1], srcData[i*4+2], srcData[i*4+3]);
4775 for (i = start; i < cnt + start; ++i) {
4776 if (!This->updateStateBlock->set.pixelShaderConstantsF[i]) {
4777 constant_entry *ptr = HeapAlloc(GetProcessHeap(), 0, sizeof(constant_entry));
4779 list_add_head(&This->updateStateBlock->set_pconstantsF, &ptr->entry);
4780 This->updateStateBlock->set.pixelShaderConstantsF[i] = TRUE;
4782 This->updateStateBlock->changed.pixelShaderConstantsF[i] = TRUE;
4788 static HRESULT WINAPI IWineD3DDeviceImpl_GetPixelShaderConstantF(
4789 IWineD3DDevice *iface,
4794 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4795 int cnt = min(count, GL_LIMITS(pshader_constantsF) - start);
4797 TRACE("(iface %p, dstData %p, start %d, count %d)\n",
4798 iface, dstData, start, count);
4800 if (dstData == NULL || cnt < 0)
4801 return WINED3DERR_INVALIDCALL;
4803 memcpy(dstData, &This->stateBlock->pixelShaderConstantF[start * 4], cnt * sizeof(float) * 4);
4807 #define copy_and_next(dest, src, size) memcpy(dest, src, size); dest += (size)
4809 process_vertices_strided(IWineD3DDeviceImpl *This, DWORD dwDestIndex, DWORD dwCount, WineDirect3DVertexStridedData *lpStrideData, DWORD SrcFVF, IWineD3DVertexBufferImpl *dest, DWORD dwFlags) {
4810 char *dest_ptr, *dest_conv = NULL;
4812 DWORD DestFVF = dest->fvf;
4814 WINED3DMATRIX mat, proj_mat, view_mat, world_mat;
4818 if (SrcFVF & WINED3DFVF_NORMAL) {
4819 WARN(" lighting state not saved yet... Some strange stuff may happen !\n");
4822 if ( (SrcFVF & WINED3DFVF_POSITION_MASK) != WINED3DFVF_XYZ) {
4823 ERR("Source has no position mask\n");
4824 return WINED3DERR_INVALIDCALL;
4827 /* We might access VBOs from this code, so hold the lock */
4830 if (dest->resource.allocatedMemory == NULL) {
4831 /* This may happen if we do direct locking into a vbo. Unlikely,
4832 * but theoretically possible(ddraw processvertices test)
4834 dest->resource.allocatedMemory = HeapAlloc(GetProcessHeap(), 0, dest->resource.size);
4835 if(!dest->resource.allocatedMemory) {
4837 ERR("Out of memory\n");
4838 return E_OUTOFMEMORY;
4842 GL_EXTCALL(glBindBufferARB(GL_ARRAY_BUFFER_ARB, dest->vbo));
4843 checkGLcall("glBindBufferARB");
4844 src = GL_EXTCALL(glMapBufferARB(GL_ARRAY_BUFFER_ARB, GL_READ_ONLY_ARB));
4846 memcpy(dest->resource.allocatedMemory, src, dest->resource.size);
4848 GL_EXTCALL(glUnmapBufferARB(GL_ARRAY_BUFFER_ARB));
4849 checkGLcall("glUnmapBufferARB");
4853 /* Get a pointer into the destination vbo(create one if none exists) and
4854 * write correct opengl data into it. It's cheap and allows us to run drawStridedFast
4856 if(!dest->vbo && GL_SUPPORT(ARB_VERTEX_BUFFER_OBJECT)) {
4861 GL_EXTCALL(glBindBufferARB(GL_ARRAY_BUFFER_ARB, dest->vbo));
4862 dest_conv = GL_EXTCALL(glMapBufferARB(GL_ARRAY_BUFFER_ARB, GL_WRITE_ONLY_ARB));
4864 ERR("glMapBuffer failed\n");
4865 /* Continue without storing converted vertices */
4870 * a) WINED3DRS_CLIPPING is enabled
4871 * b) WINED3DVOP_CLIP is passed
4873 if(This->stateBlock->renderState[WINED3DRS_CLIPPING]) {
4874 static BOOL warned = FALSE;
4876 * The clipping code is not quite correct. Some things need
4877 * to be checked against IDirect3DDevice3 (!), d3d8 and d3d9,
4878 * so disable clipping for now.
4879 * (The graphics in Half-Life are broken, and my processvertices
4880 * test crashes with IDirect3DDevice3)
4886 FIXME("Clipping is broken and disabled for now\n");
4888 } else doClip = FALSE;
4889 dest_ptr = ((char *) dest->resource.allocatedMemory) + dwDestIndex * get_flexible_vertex_size(DestFVF);
4891 dest_conv = ((char *) dest_conv) + dwDestIndex * get_flexible_vertex_size(DestFVF);
4894 IWineD3DDevice_GetTransform( (IWineD3DDevice *) This,
4897 IWineD3DDevice_GetTransform( (IWineD3DDevice *) This,
4898 WINED3DTS_PROJECTION,
4900 IWineD3DDevice_GetTransform( (IWineD3DDevice *) This,
4901 WINED3DTS_WORLDMATRIX(0),
4904 TRACE("View mat:\n");
4905 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); \
4906 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); \
4907 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); \
4908 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); \
4910 TRACE("Proj mat:\n");
4911 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); \
4912 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); \
4913 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); \
4914 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); \
4916 TRACE("World mat:\n");
4917 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); \
4918 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); \
4919 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); \
4920 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); \
4922 /* Get the viewport */
4923 IWineD3DDevice_GetViewport( (IWineD3DDevice *) This, &vp);
4924 TRACE("Viewport: X=%d, Y=%d, Width=%d, Height=%d, MinZ=%f, MaxZ=%f\n",
4925 vp.X, vp.Y, vp.Width, vp.Height, vp.MinZ, vp.MaxZ);
4927 multiply_matrix(&mat,&view_mat,&world_mat);
4928 multiply_matrix(&mat,&proj_mat,&mat);
4930 numTextures = (DestFVF & WINED3DFVF_TEXCOUNT_MASK) >> WINED3DFVF_TEXCOUNT_SHIFT;
4932 for (i = 0; i < dwCount; i+= 1) {
4933 unsigned int tex_index;
4935 if ( ((DestFVF & WINED3DFVF_POSITION_MASK) == WINED3DFVF_XYZ ) ||
4936 ((DestFVF & WINED3DFVF_POSITION_MASK) == WINED3DFVF_XYZRHW ) ) {
4937 /* The position first */
4939 (float *) (((char *) lpStrideData->u.s.position.lpData) + i * lpStrideData->u.s.position.dwStride);
4941 TRACE("In: ( %06.2f %06.2f %06.2f )\n", p[0], p[1], p[2]);
4943 /* Multiplication with world, view and projection matrix */
4944 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);
4945 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);
4946 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);
4947 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);
4949 TRACE("x=%f y=%f z=%f rhw=%f\n", x, y, z, rhw);
4951 /* WARNING: The following things are taken from d3d7 and were not yet checked
4952 * against d3d8 or d3d9!
4955 /* Clipping conditions: From
4956 * http://msdn.microsoft.com/archive/default.asp?url=/archive/en-us/directx9_c/directx/graphics/programmingguide/fixedfunction/viewportsclipping/clippingvolumes.asp
4958 * A vertex is clipped if it does not match the following requirements
4962 * 0 < rhw ( Not in d3d7, but tested in d3d7)
4964 * If clipping is on is determined by the D3DVOP_CLIP flag in D3D7, and
4965 * by the D3DRS_CLIPPING in D3D9(according to the msdn, not checked)
4970 ( (-rhw -eps < x) && (-rhw -eps < y) && ( -eps < z) &&
4971 (x <= rhw + eps) && (y <= rhw + eps ) && (z <= rhw + eps) &&
4974 /* "Normal" viewport transformation (not clipped)
4975 * 1) The values are divided by rhw
4976 * 2) The y axis is negative, so multiply it with -1
4977 * 3) Screen coordinates go from -(Width/2) to +(Width/2) and
4978 * -(Height/2) to +(Height/2). The z range is MinZ to MaxZ
4979 * 4) Multiply x with Width/2 and add Width/2
4980 * 5) The same for the height
4981 * 6) Add the viewpoint X and Y to the 2D coordinates and
4982 * The minimum Z value to z
4983 * 7) rhw = 1 / rhw Reciprocal of Homogeneous W....
4985 * Well, basically it's simply a linear transformation into viewport
4997 z *= vp.MaxZ - vp.MinZ;
4999 x += vp.Width / 2 + vp.X;
5000 y += vp.Height / 2 + vp.Y;
5005 /* That vertex got clipped
5006 * Contrary to OpenGL it is not dropped completely, it just
5007 * undergoes a different calculation.
5009 TRACE("Vertex got clipped\n");
5016 /* Msdn mentions that Direct3D9 keeps a list of clipped vertices
5017 * outside of the main vertex buffer memory. That needs some more
5022 TRACE("Writing (%f %f %f) %f\n", x, y, z, rhw);
5025 ( (float *) dest_ptr)[0] = x;
5026 ( (float *) dest_ptr)[1] = y;
5027 ( (float *) dest_ptr)[2] = z;
5028 ( (float *) dest_ptr)[3] = rhw; /* SIC, see ddraw test! */
5030 dest_ptr += 3 * sizeof(float);
5032 if((DestFVF & WINED3DFVF_POSITION_MASK) == WINED3DFVF_XYZRHW) {
5033 dest_ptr += sizeof(float);
5038 ( (float *) dest_conv)[0] = x * w;
5039 ( (float *) dest_conv)[1] = y * w;
5040 ( (float *) dest_conv)[2] = z * w;
5041 ( (float *) dest_conv)[3] = w;
5043 dest_conv += 3 * sizeof(float);
5045 if((DestFVF & WINED3DFVF_POSITION_MASK) == WINED3DFVF_XYZRHW) {
5046 dest_conv += sizeof(float);
5050 if (DestFVF & WINED3DFVF_PSIZE) {
5051 dest_ptr += sizeof(DWORD);
5052 if(dest_conv) dest_conv += sizeof(DWORD);
5054 if (DestFVF & WINED3DFVF_NORMAL) {
5056 (float *) (((float *) lpStrideData->u.s.normal.lpData) + i * lpStrideData->u.s.normal.dwStride);
5057 /* AFAIK this should go into the lighting information */
5058 FIXME("Didn't expect the destination to have a normal\n");
5059 copy_and_next(dest_ptr, normal, 3 * sizeof(float));
5061 copy_and_next(dest_conv, normal, 3 * sizeof(float));
5065 if (DestFVF & WINED3DFVF_DIFFUSE) {
5067 (DWORD *) (((char *) lpStrideData->u.s.diffuse.lpData) + i * lpStrideData->u.s.diffuse.dwStride);
5069 static BOOL warned = FALSE;
5072 ERR("No diffuse color in source, but destination has one\n");
5076 *( (DWORD *) dest_ptr) = 0xffffffff;
5077 dest_ptr += sizeof(DWORD);
5080 *( (DWORD *) dest_conv) = 0xffffffff;
5081 dest_conv += sizeof(DWORD);
5085 copy_and_next(dest_ptr, color_d, sizeof(DWORD));
5087 *( (DWORD *) dest_conv) = (*color_d & 0xff00ff00) ; /* Alpha + green */
5088 *( (DWORD *) dest_conv) |= (*color_d & 0x00ff0000) >> 16; /* Red */
5089 *( (DWORD *) dest_conv) |= (*color_d & 0xff0000ff) << 16; /* Blue */
5090 dest_conv += sizeof(DWORD);
5095 if (DestFVF & WINED3DFVF_SPECULAR) {
5096 /* What's the color value in the feedback buffer? */
5098 (DWORD *) (((char *) lpStrideData->u.s.specular.lpData) + i * lpStrideData->u.s.specular.dwStride);
5100 static BOOL warned = FALSE;
5103 ERR("No specular color in source, but destination has one\n");
5107 *( (DWORD *) dest_ptr) = 0xFF000000;
5108 dest_ptr += sizeof(DWORD);
5111 *( (DWORD *) dest_conv) = 0xFF000000;
5112 dest_conv += sizeof(DWORD);
5116 copy_and_next(dest_ptr, color_s, sizeof(DWORD));
5118 *( (DWORD *) dest_conv) = (*color_s & 0xff00ff00) ; /* Alpha + green */
5119 *( (DWORD *) dest_conv) |= (*color_s & 0x00ff0000) >> 16; /* Red */
5120 *( (DWORD *) dest_conv) |= (*color_s & 0xff0000ff) << 16; /* Blue */
5121 dest_conv += sizeof(DWORD);
5126 for (tex_index = 0; tex_index < numTextures; tex_index++) {
5128 (float *) (((char *) lpStrideData->u.s.texCoords[tex_index].lpData) +
5129 i * lpStrideData->u.s.texCoords[tex_index].dwStride);
5131 ERR("No source texture, but destination requests one\n");
5132 dest_ptr+=GET_TEXCOORD_SIZE_FROM_FVF(DestFVF, tex_index) * sizeof(float);
5133 if(dest_conv) dest_conv += GET_TEXCOORD_SIZE_FROM_FVF(DestFVF, tex_index) * sizeof(float);
5136 copy_and_next(dest_ptr, tex_coord, GET_TEXCOORD_SIZE_FROM_FVF(DestFVF, tex_index) * sizeof(float));
5138 copy_and_next(dest_conv, tex_coord, GET_TEXCOORD_SIZE_FROM_FVF(DestFVF, tex_index) * sizeof(float));
5145 GL_EXTCALL(glUnmapBufferARB(GL_ARRAY_BUFFER_ARB));
5146 checkGLcall("glUnmapBufferARB(GL_ARRAY_BUFFER_ARB)");
5153 #undef copy_and_next
5155 static HRESULT WINAPI IWineD3DDeviceImpl_ProcessVertices(IWineD3DDevice *iface, UINT SrcStartIndex, UINT DestIndex, UINT VertexCount, IWineD3DVertexBuffer* pDestBuffer, IWineD3DVertexBuffer* pVertexDecl, DWORD Flags) {
5156 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5157 IWineD3DVertexBufferImpl *SrcImpl = (IWineD3DVertexBufferImpl *) pVertexDecl;
5158 WineDirect3DVertexStridedData strided;
5159 TRACE("(%p)->(%d,%d,%d,%p,%p,%d\n", This, SrcStartIndex, DestIndex, VertexCount, pDestBuffer, pVertexDecl, Flags);
5162 WARN("NULL source vertex buffer\n");
5163 return WINED3DERR_INVALIDCALL;
5165 /* We don't need the source vbo because this buffer is only used as
5166 * a source for ProcessVertices. Avoid wasting resources by converting the
5167 * buffer and loading the VBO
5170 TRACE("Releasing the source vbo, it won't be needed\n");
5172 if(!SrcImpl->resource.allocatedMemory) {
5173 /* Rescue the data from the buffer */
5175 SrcImpl->resource.allocatedMemory = HeapAlloc(GetProcessHeap(), 0, SrcImpl->resource.size);
5176 if(!SrcImpl->resource.allocatedMemory) {
5177 ERR("Out of memory\n");
5178 return E_OUTOFMEMORY;
5182 GL_EXTCALL(glBindBufferARB(GL_ARRAY_BUFFER_ARB, SrcImpl->vbo));
5183 checkGLcall("glBindBufferARB");
5185 src = GL_EXTCALL(glMapBufferARB(GL_ARRAY_BUFFER_ARB, GL_READ_ONLY_ARB));
5187 memcpy(SrcImpl->resource.allocatedMemory, src, SrcImpl->resource.size);
5190 GL_EXTCALL(glUnmapBufferARB(GL_ARRAY_BUFFER_ARB));
5191 checkGLcall("glUnmapBufferARB");
5196 GL_EXTCALL(glBindBufferARB(GL_ARRAY_BUFFER_ARB, 0));
5197 checkGLcall("glBindBufferARB");
5198 GL_EXTCALL(glDeleteBuffersARB(1, &SrcImpl->vbo));
5199 checkGLcall("glDeleteBuffersARB");
5205 memset(&strided, 0, sizeof(strided));
5206 primitiveConvertFVFtoOffset(SrcImpl->fvf, get_flexible_vertex_size(SrcImpl->fvf), SrcImpl->resource.allocatedMemory + get_flexible_vertex_size(SrcImpl->fvf) * SrcStartIndex, &strided, 0);
5208 return process_vertices_strided(This, DestIndex, VertexCount, &strided, SrcImpl->fvf, (IWineD3DVertexBufferImpl *) pDestBuffer, Flags);
5212 * Apply / Get / Set Texture Stage States
5213 * TODO: Verify against dx9 definitions
5216 /* 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 */
5217 static void WINAPI IWineD3DDeviceImpl_ApplyTextureUnitState(IWineD3DDevice *iface, DWORD Stage, WINED3DTEXTURESTAGESTATETYPE Type) {
5218 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5219 DWORD Value = This->updateStateBlock->textureState[Stage][Type];
5220 /* FIXME: Handle 3d textures? What if TSS value set before set texture? Need to reapply all values? */
5222 TRACE("(%p) : Stage=%d, Type=%s(%d), Value=%d\n", This, Stage, debug_d3dtexturestate(Type), Type, Value);
5224 /* Check that the stage is within limits */
5225 if (Stage >= GL_LIMITS(texture_stages) || Stage < 0) {
5226 TRACE("Attempt to access invalid texture rejected\n");
5233 case WINED3DTSS_ALPHAOP :
5234 case WINED3DTSS_COLOROP :
5235 /* nothing to do as moved to drawprim for now */
5237 case WINED3DTSS_ADDRESSW :
5238 #if 0 /* I'm not sure what D3D does about ADDRESSW appearing twice */
5239 if (Value < minLookup[WINELOOKUP_WARPPARAM] || Value > maxLookup[WINELOOKUP_WARPPARAM]) {
5240 FIXME("Unrecognized or unsupported WINED3DTADDRESS_* value %d, state %d\n", Value, Type);
5243 GLint wrapParm = stateLookup[WINELOOKUP_WARPPARAM][Value - minLookup[WINELOOKUP_WARPPARAM]];
5244 TRACE("Setting WRAP_R to %d for %x\n", wrapParm, This->stateBlock->textureDimensions[Stage]);
5245 glTexParameteri(This->stateBlock->textureDimensions[Stage], GL_TEXTURE_WRAP_R, wrapParm);
5246 checkGLcall("glTexParameteri(..., GL_TEXTURE_WRAP_R, wrapParm)");
5249 case WINED3DTSS_TEXCOORDINDEX :
5251 /* Values 0-7 are indexes into the FVF tex coords - See comments in DrawPrimitive */
5253 /* FIXME: From MSDN: The WINED3DTSS_TCI_* flags are mutually exclusive. If you include
5254 one flag, you can still specify an index value, which the system uses to
5255 determine the texture wrapping mode.
5256 eg. SetTextureStageState( 0, WINED3DTSS_TEXCOORDINDEX, WINED3DTSS_TCI_CAMERASPACEPOSITION | 1 );
5257 means use the vertex position (camera-space) as the input texture coordinates
5258 for this texture stage, and the wrap mode set in the WINED3DRS_WRAP1 render
5259 state. We do not (yet) support the WINED3DRENDERSTATE_WRAPx values, nor tie them up
5260 to the TEXCOORDINDEX value */
5263 * Be careful the value of the mask 0xF0000 come from d3d8types.h infos
5265 switch (Value & 0xFFFF0000) {
5266 case WINED3DTSS_TCI_PASSTHRU:
5267 /*Use the specified texture coordinates contained within the vertex format. This value resolves to zero.*/
5268 glDisable(GL_TEXTURE_GEN_S);
5269 glDisable(GL_TEXTURE_GEN_T);
5270 glDisable(GL_TEXTURE_GEN_R);
5271 glDisable(GL_TEXTURE_GEN_Q);
5272 checkGLcall("glDisable(GL_TEXTURE_GEN_S,T,R,Q)");
5275 case WINED3DTSS_TCI_CAMERASPACEPOSITION:
5276 /* CameraSpacePosition means use the vertex position, transformed to camera space,
5277 as the input texture coordinates for this stage's texture transformation. This
5278 equates roughly to EYE_LINEAR */
5280 float s_plane[] = { 1.0, 0.0, 0.0, 0.0 };
5281 float t_plane[] = { 0.0, 1.0, 0.0, 0.0 };
5282 float r_plane[] = { 0.0, 0.0, 1.0, 0.0 };
5283 float q_plane[] = { 0.0, 0.0, 0.0, 1.0 };
5284 TRACE("WINED3DTSS_TCI_CAMERASPACEPOSITION - Set eye plane\n");
5286 glMatrixMode(GL_MODELVIEW);
5289 glTexGenfv(GL_S, GL_EYE_PLANE, s_plane);
5290 glTexGenfv(GL_T, GL_EYE_PLANE, t_plane);
5291 glTexGenfv(GL_R, GL_EYE_PLANE, r_plane);
5292 glTexGenfv(GL_Q, GL_EYE_PLANE, q_plane);
5295 TRACE("WINED3DTSS_TCI_CAMERASPACEPOSITION - Set GL_TEXTURE_GEN_x and GL_x, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR\n");
5296 glEnable(GL_TEXTURE_GEN_S);
5297 checkGLcall("glEnable(GL_TEXTURE_GEN_S);");
5298 glTexGeni(GL_S, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR);
5299 checkGLcall("glTexGeni(GL_S, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR)");
5300 glEnable(GL_TEXTURE_GEN_T);
5301 checkGLcall("glEnable(GL_TEXTURE_GEN_T);");
5302 glTexGeni(GL_T, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR);
5303 checkGLcall("glTexGeni(GL_T, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR)");
5304 glEnable(GL_TEXTURE_GEN_R);
5305 checkGLcall("glEnable(GL_TEXTURE_GEN_R);");
5306 glTexGeni(GL_R, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR);
5307 checkGLcall("glTexGeni(GL_R, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR)");
5311 case WINED3DTSS_TCI_CAMERASPACENORMAL:
5313 if (GL_SUPPORT(NV_TEXGEN_REFLECTION)) {
5314 float s_plane[] = { 1.0, 0.0, 0.0, 0.0 };
5315 float t_plane[] = { 0.0, 1.0, 0.0, 0.0 };
5316 float r_plane[] = { 0.0, 0.0, 1.0, 0.0 };
5317 float q_plane[] = { 0.0, 0.0, 0.0, 1.0 };
5318 TRACE("WINED3DTSS_TCI_CAMERASPACENORMAL - Set eye plane\n");
5320 glMatrixMode(GL_MODELVIEW);
5323 glTexGenfv(GL_S, GL_EYE_PLANE, s_plane);
5324 glTexGenfv(GL_T, GL_EYE_PLANE, t_plane);
5325 glTexGenfv(GL_R, GL_EYE_PLANE, r_plane);
5326 glTexGenfv(GL_Q, GL_EYE_PLANE, q_plane);
5329 glEnable(GL_TEXTURE_GEN_S);
5330 checkGLcall("glEnable(GL_TEXTURE_GEN_S);");
5331 glTexGeni(GL_S, GL_TEXTURE_GEN_MODE, GL_NORMAL_MAP_NV);
5332 checkGLcall("glTexGeni(GL_S, GL_TEXTURE_GEN_MODE, GL_NORMAL_MAP_NV)");
5333 glEnable(GL_TEXTURE_GEN_T);
5334 checkGLcall("glEnable(GL_TEXTURE_GEN_T);");
5335 glTexGeni(GL_T, GL_TEXTURE_GEN_MODE, GL_NORMAL_MAP_NV);
5336 checkGLcall("glTexGeni(GL_T, GL_TEXTURE_GEN_MODE, GL_NORMAL_MAP_NV)");
5337 glEnable(GL_TEXTURE_GEN_R);
5338 checkGLcall("glEnable(GL_TEXTURE_GEN_R);");
5339 glTexGeni(GL_R, GL_TEXTURE_GEN_MODE, GL_NORMAL_MAP_NV);
5340 checkGLcall("glTexGeni(GL_R, GL_TEXTURE_GEN_MODE, GL_NORMAL_MAP_NV)");
5345 case WINED3DTSS_TCI_CAMERASPACEREFLECTIONVECTOR:
5347 if (GL_SUPPORT(NV_TEXGEN_REFLECTION)) {
5348 float s_plane[] = { 1.0, 0.0, 0.0, 0.0 };
5349 float t_plane[] = { 0.0, 1.0, 0.0, 0.0 };
5350 float r_plane[] = { 0.0, 0.0, 1.0, 0.0 };
5351 float q_plane[] = { 0.0, 0.0, 0.0, 1.0 };
5352 TRACE("WINED3DTSS_TCI_CAMERASPACEREFLECTIONVECTOR - Set eye plane\n");
5354 glMatrixMode(GL_MODELVIEW);
5357 glTexGenfv(GL_S, GL_EYE_PLANE, s_plane);
5358 glTexGenfv(GL_T, GL_EYE_PLANE, t_plane);
5359 glTexGenfv(GL_R, GL_EYE_PLANE, r_plane);
5360 glTexGenfv(GL_Q, GL_EYE_PLANE, q_plane);
5363 glEnable(GL_TEXTURE_GEN_S);
5364 checkGLcall("glEnable(GL_TEXTURE_GEN_S);");
5365 glTexGeni(GL_S, GL_TEXTURE_GEN_MODE, GL_REFLECTION_MAP_NV);
5366 checkGLcall("glTexGeni(GL_S, GL_TEXTURE_GEN_MODE, GL_REFLECTION_MAP_NV)");
5367 glEnable(GL_TEXTURE_GEN_T);
5368 checkGLcall("glEnable(GL_TEXTURE_GEN_T);");
5369 glTexGeni(GL_T, GL_TEXTURE_GEN_MODE, GL_REFLECTION_MAP_NV);
5370 checkGLcall("glTexGeni(GL_T, GL_TEXTURE_GEN_MODE, GL_REFLECTION_MAP_NV)");
5371 glEnable(GL_TEXTURE_GEN_R);
5372 checkGLcall("glEnable(GL_TEXTURE_GEN_R);");
5373 glTexGeni(GL_R, GL_TEXTURE_GEN_MODE, GL_REFLECTION_MAP_NV);
5374 checkGLcall("glTexGeni(GL_R, GL_TEXTURE_GEN_MODE, GL_REFLECTION_MAP_NV)");
5379 /* Unhandled types: */
5382 /* ? disable GL_TEXTURE_GEN_n ? */
5383 glDisable(GL_TEXTURE_GEN_S);
5384 glDisable(GL_TEXTURE_GEN_T);
5385 glDisable(GL_TEXTURE_GEN_R);
5386 glDisable(GL_TEXTURE_GEN_Q);
5387 FIXME("Unhandled WINED3DTSS_TEXCOORDINDEX %x\n", Value);
5394 case WINED3DTSS_TEXTURETRANSFORMFLAGS :
5395 set_texture_matrix((float *)&This->stateBlock->transforms[WINED3DTS_TEXTURE0 + Stage].u.m[0][0], Value, (This->stateBlock->textureState[Stage][WINED3DTSS_TEXCOORDINDEX] & 0xFFFF0000) != WINED3DTSS_TCI_PASSTHRU);
5398 case WINED3DTSS_BUMPENVMAT00 :
5399 case WINED3DTSS_BUMPENVMAT01 :
5400 TRACE("BUMPENVMAT0%u Stage=%d, Type=%d, Value =%d\n", Type - WINED3DTSS_BUMPENVMAT00, Stage, Type, Value);
5402 case WINED3DTSS_BUMPENVMAT10 :
5403 case WINED3DTSS_BUMPENVMAT11 :
5404 TRACE("BUMPENVMAT1%u Stage=%d, Type=%d, Value =%d\n", Type - WINED3DTSS_BUMPENVMAT10, Stage, Type, Value);
5407 case WINED3DTSS_BUMPENVLSCALE :
5408 TRACE("BUMPENVLSCALE Stage=%d, Type=%d, Value =%d\n", Stage, Type, Value);
5411 case WINED3DTSS_BUMPENVLOFFSET :
5412 TRACE("BUMPENVLOFFSET Stage=%d, Type=%d, Value =%d\n", Stage, Type, Value);
5415 case WINED3DTSS_RESULTARG :
5416 TRACE("RESULTARG Still a stub, Stage=%d, Type=%d, Value =%d\n", Stage, Type, Value);
5420 /* Put back later: FIXME("(%p) : stub, Stage=%d, Type=%d, Value =%d\n", This, Stage, Type, Value); */
5421 TRACE("Still a stub, Stage=%d, Type=%d, Value =%d\n", Stage, Type, Value);
5430 * Get / Set Texture Stage States
5431 * TODO: Verify against dx9 definitions
5433 static HRESULT WINAPI IWineD3DDeviceImpl_SetTextureStageState(IWineD3DDevice *iface, DWORD Stage, WINED3DTEXTURESTAGESTATETYPE Type, DWORD Value) {
5434 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5436 /* FIXME: Handle 3d textures? What if TSS value set before set texture? Need to reapply all values? */
5438 TRACE("(%p) : Stage=%d, Type=%s(%d), Value=%d\n", This, Stage, debug_d3dtexturestate(Type), Type, Value);
5440 /* Reject invalid texture units */
5441 if (Stage >= GL_LIMITS(texture_stages)) {
5442 TRACE("Attempt to access invalid texture rejected\n");
5443 return WINED3DERR_INVALIDCALL;
5446 This->updateStateBlock->changed.textureState[Stage][Type] = TRUE;
5447 This->updateStateBlock->set.textureState[Stage][Type] = TRUE;
5448 This->updateStateBlock->textureState[Stage][Type] = Value;
5453 static HRESULT WINAPI IWineD3DDeviceImpl_GetTextureStageState(IWineD3DDevice *iface, DWORD Stage, WINED3DTEXTURESTAGESTATETYPE Type, DWORD* pValue) {
5454 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5455 TRACE("(%p) : requesting Stage %d, Type %d getting %d\n", This, Stage, Type, This->updateStateBlock->textureState[Stage][Type]);
5456 *pValue = This->updateStateBlock->textureState[Stage][Type];
5463 static HRESULT WINAPI IWineD3DDeviceImpl_SetTexture(IWineD3DDevice *iface, DWORD Stage, IWineD3DBaseTexture* pTexture) {
5465 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5466 IWineD3DBaseTexture *oldTexture;
5468 oldTexture = This->updateStateBlock->textures[Stage];
5469 TRACE("(%p) : Stage(%d), Texture (%p)\n", This, Stage, pTexture);
5471 #if 0 /* TODO: check so vertex textures */
5472 if (Stage >= D3DVERTEXTEXTURESAMPLER && Stage <= D3DVERTEXTEXTURESAMPLER3){
5473 This->updateStateBlock->vertexTextures[Stage - D3DVERTEXTEXTURESAMPLER] = pTexture;
5478 /* Reject invalid texture units */
5479 if (Stage >= GL_LIMITS(sampler_stages) || Stage < 0) {
5480 WARN("Attempt to access invalid texture rejected\n");
5481 return WINED3DERR_INVALIDCALL;
5484 if(pTexture != NULL) {
5485 /* SetTexture isn't allowed on textures in WINED3DPOOL_SCRATCH;
5487 if(((IWineD3DTextureImpl*)pTexture)->resource.pool == WINED3DPOOL_SCRATCH) {
5488 WARN("(%p) Attempt to set scratch texture rejected\n", pTexture);
5489 return WINED3DERR_INVALIDCALL;
5493 oldTexture = This->updateStateBlock->textures[Stage];
5494 TRACE("GL_LIMITS %d\n",GL_LIMITS(sampler_stages));
5495 TRACE("(%p) : oldtexture(%p)\n", This,oldTexture);
5497 This->updateStateBlock->set.textures[Stage] = TRUE;
5498 This->updateStateBlock->changed.textures[Stage] = TRUE;
5499 TRACE("(%p) : setting new texture to %p\n", This, pTexture);
5500 This->updateStateBlock->textures[Stage] = pTexture;
5502 /* Handle recording of state blocks */
5503 if (This->isRecordingState) {
5504 TRACE("Recording... not performing anything\n");
5508 /** NOTE: MSDN says that setTexture increases the reference count,
5509 * and the the application nust set the texture back to null (or have a leaky application),
5510 * This means we should pass the refcount up to the parent
5511 *******************************/
5512 if (NULL != This->updateStateBlock->textures[Stage]) {
5513 IWineD3DBaseTexture_AddRef(This->updateStateBlock->textures[Stage]);
5516 if (NULL != oldTexture) {
5517 IWineD3DBaseTexture_Release(oldTexture);
5520 /* Reset color keying */
5521 if(Stage == 0 && This->stateBlock->renderState[WINED3DRS_COLORKEYENABLE]) {
5522 BOOL enable_ckey = FALSE;
5525 IWineD3DSurfaceImpl *surf = (IWineD3DSurfaceImpl *) ((IWineD3DTextureImpl *)pTexture)->surfaces[0];
5526 if(surf->CKeyFlags & DDSD_CKSRCBLT) enable_ckey = TRUE;
5530 glAlphaFunc(GL_NOTEQUAL, 0.0);
5531 checkGLcall("glAlphaFunc");
5538 static HRESULT WINAPI IWineD3DDeviceImpl_GetTexture(IWineD3DDevice *iface, DWORD Stage, IWineD3DBaseTexture** ppTexture) {
5539 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5540 TRACE("(%p) : (%d /* Stage */,%p /* ppTexture */)\n", This, Stage, ppTexture);
5542 /* Reject invalid texture units */
5543 if (Stage >= GL_LIMITS(sampler_stages)) {
5544 TRACE("Attempt to access invalid texture rejected\n");
5545 return WINED3DERR_INVALIDCALL;
5547 *ppTexture=This->stateBlock->textures[Stage];
5549 IWineD3DBaseTexture_AddRef(*ppTexture);
5557 static HRESULT WINAPI IWineD3DDeviceImpl_GetBackBuffer(IWineD3DDevice *iface, UINT iSwapChain, UINT BackBuffer, WINED3DBACKBUFFER_TYPE Type,
5558 IWineD3DSurface **ppBackBuffer) {
5559 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5560 IWineD3DSwapChain *swapChain;
5563 TRACE("(%p) : BackBuf %d Type %d SwapChain %d returning %p\n", This, BackBuffer, Type, iSwapChain, *ppBackBuffer);
5565 hr = IWineD3DDeviceImpl_GetSwapChain(iface, iSwapChain, &swapChain);
5566 if (hr == WINED3D_OK) {
5567 hr = IWineD3DSwapChain_GetBackBuffer(swapChain, BackBuffer, Type, ppBackBuffer);
5568 IWineD3DSwapChain_Release(swapChain);
5570 *ppBackBuffer = NULL;
5575 static HRESULT WINAPI IWineD3DDeviceImpl_GetDeviceCaps(IWineD3DDevice *iface, WINED3DCAPS* pCaps) {
5576 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5577 WARN("(%p) : stub, calling idirect3d for now\n", This);
5578 return IWineD3D_GetDeviceCaps(This->wineD3D, This->adapterNo, This->devType, pCaps);
5581 static HRESULT WINAPI IWineD3DDeviceImpl_GetDisplayMode(IWineD3DDevice *iface, UINT iSwapChain, WINED3DDISPLAYMODE* pMode) {
5582 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5583 IWineD3DSwapChain *swapChain;
5586 if(iSwapChain > 0) {
5587 hr = IWineD3DDeviceImpl_GetSwapChain(iface, iSwapChain, (IWineD3DSwapChain **)&swapChain);
5588 if (hr == WINED3D_OK) {
5589 hr = IWineD3DSwapChain_GetDisplayMode(swapChain, pMode);
5590 IWineD3DSwapChain_Release(swapChain);
5592 FIXME("(%p) Error getting display mode\n", This);
5595 /* Don't read the real display mode,
5596 but return the stored mode instead. X11 can't change the color
5597 depth, and some apps are pretty angry if they SetDisplayMode from
5598 24 to 16 bpp and find out that GetDisplayMode still returns 24 bpp
5600 Also don't relay to the swapchain because with ddraw it's possible
5601 that there isn't a swapchain at all */
5602 pMode->Width = This->ddraw_width;
5603 pMode->Height = This->ddraw_height;
5604 pMode->Format = This->ddraw_format;
5605 pMode->RefreshRate = 0;
5612 static HRESULT WINAPI IWineD3DDeviceImpl_SetHWND(IWineD3DDevice *iface, HWND hWnd) {
5613 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5614 TRACE("(%p)->(%p)\n", This, hWnd);
5616 This->ddraw_window = hWnd;
5620 static HRESULT WINAPI IWineD3DDeviceImpl_GetHWND(IWineD3DDevice *iface, HWND *hWnd) {
5621 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5622 TRACE("(%p)->(%p)\n", This, hWnd);
5624 *hWnd = This->ddraw_window;
5629 * Stateblock related functions
5632 static HRESULT WINAPI IWineD3DDeviceImpl_BeginStateBlock(IWineD3DDevice *iface) {
5633 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5634 IWineD3DStateBlockImpl *object;
5635 HRESULT temp_result;
5637 TRACE("(%p)\n", This);
5639 if (This->isRecordingState) {
5640 return WINED3DERR_INVALIDCALL;
5643 object = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(IWineD3DStateBlockImpl));
5644 if (NULL == object ) {
5645 FIXME("(%p)Error allocating memory for stateblock\n", This);
5646 return E_OUTOFMEMORY;
5648 TRACE("(%p) created object %p\n", This, object);
5649 object->wineD3DDevice= This;
5650 /** FIXME: object->parent = parent; **/
5651 object->parent = NULL;
5652 object->blockType = WINED3DSBT_ALL;
5654 object->lpVtbl = &IWineD3DStateBlock_Vtbl;
5656 temp_result = allocate_shader_constants(object);
5657 if (WINED3D_OK != temp_result)
5660 IWineD3DStateBlock_Release((IWineD3DStateBlock*)This->updateStateBlock);
5661 This->updateStateBlock = object;
5662 This->isRecordingState = TRUE;
5664 TRACE("(%p) recording stateblock %p\n",This , object);
5668 static HRESULT WINAPI IWineD3DDeviceImpl_EndStateBlock(IWineD3DDevice *iface, IWineD3DStateBlock** ppStateBlock) {
5669 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5671 if (!This->isRecordingState) {
5672 FIXME("(%p) not recording! returning error\n", This);
5673 *ppStateBlock = NULL;
5674 return WINED3DERR_INVALIDCALL;
5677 *ppStateBlock = (IWineD3DStateBlock*)This->updateStateBlock;
5678 This->isRecordingState = FALSE;
5679 This->updateStateBlock = This->stateBlock;
5680 IWineD3DStateBlock_AddRef((IWineD3DStateBlock*)This->updateStateBlock);
5681 /* IWineD3DStateBlock_AddRef(*ppStateBlock); don't need to do this, since we should really just release UpdateStateBlock first */
5682 TRACE("(%p) returning token (ptr to stateblock) of %p\n", This, *ppStateBlock);
5687 * Scene related functions
5689 static HRESULT WINAPI IWineD3DDeviceImpl_BeginScene(IWineD3DDevice *iface) {
5690 /* At the moment we have no need for any functionality at the beginning
5692 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5693 TRACE("(%p) : stub\n", This);
5697 static HRESULT WINAPI IWineD3DDeviceImpl_EndScene(IWineD3DDevice *iface) {
5698 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5699 TRACE("(%p)\n", This);
5701 /* We only have to do this if we need to read the, swapbuffers performs a flush for us */
5703 checkGLcall("glFlush");
5705 TRACE("End Scene\n");
5706 /* If we're using FBOs this isn't needed */
5707 if (wined3d_settings.offscreen_rendering_mode != ORM_FBO && This->renderTarget != NULL) {
5709 /* If the container of the rendertarget is a texture then we need to save the data from the pbuffer */
5710 IUnknown *targetContainer = NULL;
5711 if (WINED3D_OK == IWineD3DSurface_GetContainer(This->renderTarget, &IID_IWineD3DBaseTexture, (void **)&targetContainer)
5712 || WINED3D_OK == IWineD3DSurface_GetContainer(This->renderTarget, &IID_IWineD3DDevice, (void **)&targetContainer)) {
5713 TRACE("(%p) : Texture rendertarget %p\n", This ,This->renderTarget);
5714 /** always dirtify for now. we must find a better way to see that surface have been modified
5715 (Modifications should will only occur via draw-primitive, but we do need better locking
5716 switching to render-to-texture should remove the overhead though.
5718 IWineD3DSurface_SetPBufferState(This->renderTarget, TRUE /* inPBuffer */, FALSE /* inTexture */);
5719 IWineD3DSurface_AddDirtyRect(This->renderTarget, NULL);
5720 IWineD3DSurface_PreLoad(This->renderTarget);
5721 IWineD3DSurface_SetPBufferState(This->renderTarget, FALSE /* inPBuffer */, FALSE /* inTexture */);
5722 IUnknown_Release(targetContainer);
5725 This->sceneEnded = TRUE;
5730 static HRESULT WINAPI IWineD3DDeviceImpl_Present(IWineD3DDevice *iface,
5731 CONST RECT* pSourceRect, CONST RECT* pDestRect,
5732 HWND hDestWindowOverride, CONST RGNDATA* pDirtyRegion) {
5733 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5734 IWineD3DSwapChain *swapChain = NULL;
5736 int swapchains = IWineD3DDeviceImpl_GetNumberOfSwapChains(iface);
5738 TRACE("(%p) Presenting the frame\n", This);
5740 for(i = 0 ; i < swapchains ; i ++) {
5742 IWineD3DDeviceImpl_GetSwapChain(iface, i , (IWineD3DSwapChain **)&swapChain);
5743 TRACE("presentinng chain %d, %p\n", i, swapChain);
5744 IWineD3DSwapChain_Present(swapChain, pSourceRect, pDestRect, hDestWindowOverride, pDirtyRegion, 0);
5745 IWineD3DSwapChain_Release(swapChain);
5751 static HRESULT WINAPI IWineD3DDeviceImpl_Clear(IWineD3DDevice *iface, DWORD Count, CONST WINED3DRECT* pRects,
5752 DWORD Flags, WINED3DCOLOR Color, float Z, DWORD Stencil) {
5753 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5755 /* TODO: From MSDN This method fails if you specify the WINED3DCLEAR_ZBUFFER or WINED3DCLEAR_STENCIL flags when the
5756 render target does not have an attached depth buffer. Similarly, if you specify the WINED3DCLEAR_STENCIL flag
5757 when the depth-buffer format does not contain stencil buffer information, this method fails. */
5758 GLbitfield glMask = 0;
5759 GLboolean old_ztest;
5760 GLfloat old_z_clear_value;
5761 GLint old_stencil_clear_value;
5762 GLfloat old_color_clear_value[4];
5764 CONST WINED3DRECT* curRect;
5766 TRACE("(%p) Count (%d), pRects (%p), Flags (%x), Z (%f), Stencil (%d)\n", This,
5767 Count, pRects, Flags, Z, Stencil);
5771 glEnable(GL_SCISSOR_TEST);
5772 checkGLcall("glEnable GL_SCISSOR_TEST");
5774 if (Count > 0 && pRects) {
5780 /* Only set the values up once, as they are not changing */
5781 if (Flags & WINED3DCLEAR_STENCIL) {
5782 glGetIntegerv(GL_STENCIL_CLEAR_VALUE, &old_stencil_clear_value);
5783 glClearStencil(Stencil);
5784 checkGLcall("glClearStencil");
5785 glMask = glMask | GL_STENCIL_BUFFER_BIT;
5786 glStencilMask(0xFFFFFFFF);
5789 if (Flags & WINED3DCLEAR_ZBUFFER) {
5790 glGetBooleanv(GL_DEPTH_WRITEMASK, &old_ztest);
5791 glDepthMask(GL_TRUE);
5792 glGetFloatv(GL_DEPTH_CLEAR_VALUE, &old_z_clear_value);
5794 checkGLcall("glClearDepth");
5795 glMask = glMask | GL_DEPTH_BUFFER_BIT;
5798 if (Flags & WINED3DCLEAR_TARGET) {
5799 TRACE("Clearing screen with glClear to color %x\n", Color);
5800 glGetFloatv(GL_COLOR_CLEAR_VALUE, old_color_clear_value);
5801 glClearColor(D3DCOLOR_R(Color),
5805 checkGLcall("glClearColor");
5807 /* Clear ALL colors! */
5808 glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
5809 glMask = glMask | GL_COLOR_BUFFER_BIT;
5812 /* Now process each rect in turn */
5813 for (i = 0; i < Count || i == 0; i++) {
5816 /* Note gl uses lower left, width/height */
5817 TRACE("(%p) %p Rect=(%d,%d)->(%d,%d) glRect=(%d,%d), len=%d, hei=%d\n", This, curRect,
5818 curRect->x1, curRect->y1, curRect->x2, curRect->y2,
5819 curRect->x1, (((IWineD3DSurfaceImpl *)This->renderTarget)->currentDesc.Height - curRect->y2),
5820 curRect->x2 - curRect->x1, curRect->y2 - curRect->y1);
5821 glScissor(curRect->x1, (((IWineD3DSurfaceImpl *)This->renderTarget)->currentDesc.Height - curRect->y2),
5822 curRect->x2 - curRect->x1, curRect->y2 - curRect->y1);
5823 checkGLcall("glScissor");
5825 glScissor(This->stateBlock->viewport.X,
5826 (((IWineD3DSurfaceImpl *)This->renderTarget)->currentDesc.Height -
5827 (This->stateBlock->viewport.Y + This->stateBlock->viewport.Height)),
5828 This->stateBlock->viewport.Width,
5829 This->stateBlock->viewport.Height);
5830 checkGLcall("glScissor");
5833 /* Clear the selected rectangle (or full screen) */
5835 checkGLcall("glClear");
5837 /* Step to the next rectangle */
5838 if (curRect) curRect = curRect + sizeof(WINED3DRECT);
5841 /* Restore the old values (why..?) */
5842 if (Flags & WINED3DCLEAR_STENCIL) {
5843 glClearStencil(old_stencil_clear_value);
5844 glStencilMask(This->stateBlock->renderState[WINED3DRS_STENCILWRITEMASK]);
5846 if (Flags & WINED3DCLEAR_ZBUFFER) {
5847 glDepthMask(old_ztest);
5848 glClearDepth(old_z_clear_value);
5850 if (Flags & WINED3DCLEAR_TARGET) {
5851 glClearColor(old_color_clear_value[0],
5852 old_color_clear_value[1],
5853 old_color_clear_value[2],
5854 old_color_clear_value[3]);
5855 glColorMask(This->stateBlock->renderState[WINED3DRS_COLORWRITEENABLE] & WINED3DCOLORWRITEENABLE_RED ? GL_TRUE : GL_FALSE,
5856 This->stateBlock->renderState[WINED3DRS_COLORWRITEENABLE] & WINED3DCOLORWRITEENABLE_GREEN ? GL_TRUE : GL_FALSE,
5857 This->stateBlock->renderState[WINED3DRS_COLORWRITEENABLE] & WINED3DCOLORWRITEENABLE_BLUE ? GL_TRUE : GL_FALSE,
5858 This->stateBlock->renderState[WINED3DRS_COLORWRITEENABLE] & WINED3DCOLORWRITEENABLE_ALPHA ? GL_TRUE : GL_FALSE);
5861 glDisable(GL_SCISSOR_TEST);
5862 checkGLcall("glDisable");
5871 static HRESULT WINAPI IWineD3DDeviceImpl_DrawPrimitive(IWineD3DDevice *iface, WINED3DPRIMITIVETYPE PrimitiveType, UINT StartVertex,
5872 UINT PrimitiveCount) {
5874 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5875 This->stateBlock->streamIsUP = FALSE;
5877 TRACE("(%p) : Type=(%d,%s), Start=%d, Count=%d\n", This, PrimitiveType,
5878 debug_d3dprimitivetype(PrimitiveType),
5879 StartVertex, PrimitiveCount);
5880 drawPrimitive(iface, PrimitiveType, PrimitiveCount, StartVertex, 0/* NumVertices */, -1 /* indxStart */,
5881 0 /* indxSize */, NULL /* indxData */, 0 /* minIndex */, NULL);
5887 /* TODO: baseVIndex needs to be provided from This->stateBlock->baseVertexIndex when called from d3d8 */
5888 static HRESULT WINAPI IWineD3DDeviceImpl_DrawIndexedPrimitive(IWineD3DDevice *iface,
5889 WINED3DPRIMITIVETYPE PrimitiveType,
5890 INT baseVIndex, UINT minIndex,
5891 UINT NumVertices, UINT startIndex, UINT primCount) {
5893 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5895 IWineD3DIndexBuffer *pIB;
5896 WINED3DINDEXBUFFER_DESC IdxBufDsc;
5898 pIB = This->stateBlock->pIndexData;
5899 This->stateBlock->streamIsUP = FALSE;
5901 TRACE("(%p) : Type=(%d,%s), min=%d, CountV=%d, startIdx=%d, baseVidx=%d, countP=%d\n", This,
5902 PrimitiveType, debug_d3dprimitivetype(PrimitiveType),
5903 minIndex, NumVertices, startIndex, baseVIndex, primCount);
5905 IWineD3DIndexBuffer_GetDesc(pIB, &IdxBufDsc);
5906 if (IdxBufDsc.Format == WINED3DFMT_INDEX16) {
5912 drawPrimitive(iface, PrimitiveType, primCount, baseVIndex, NumVertices, startIndex,
5913 idxStride, ((IWineD3DIndexBufferImpl *) pIB)->resource.allocatedMemory, minIndex, NULL);
5918 static HRESULT WINAPI IWineD3DDeviceImpl_DrawPrimitiveUP(IWineD3DDevice *iface, WINED3DPRIMITIVETYPE PrimitiveType,
5919 UINT PrimitiveCount, CONST void* pVertexStreamZeroData,
5920 UINT VertexStreamZeroStride) {
5921 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5923 TRACE("(%p) : Type=(%d,%s), pCount=%d, pVtxData=%p, Stride=%d\n", This, PrimitiveType,
5924 debug_d3dprimitivetype(PrimitiveType),
5925 PrimitiveCount, pVertexStreamZeroData, VertexStreamZeroStride);
5927 /* release the stream source */
5928 if (This->stateBlock->streamSource[0] != NULL) {
5929 IWineD3DVertexBuffer_Release(This->stateBlock->streamSource[0]);
5932 /* Note in the following, it's not this type, but that's the purpose of streamIsUP */
5933 This->stateBlock->streamSource[0] = (IWineD3DVertexBuffer *)pVertexStreamZeroData;
5934 This->stateBlock->streamStride[0] = VertexStreamZeroStride;
5935 This->stateBlock->streamIsUP = TRUE;
5937 drawPrimitive(iface, PrimitiveType, PrimitiveCount, 0 /* start vertex */, 0 /* NumVertices */,
5938 0 /* indxStart*/, 0 /* indxSize*/, NULL /* indxData */, 0 /* indxMin */, NULL);
5940 /* MSDN specifies stream zero settings must be set to NULL */
5941 This->stateBlock->streamStride[0] = 0;
5942 This->stateBlock->streamSource[0] = NULL;
5944 /*stream zero settings set to null at end, as per the msdn */
5948 static HRESULT WINAPI IWineD3DDeviceImpl_DrawIndexedPrimitiveUP(IWineD3DDevice *iface, WINED3DPRIMITIVETYPE PrimitiveType,
5949 UINT MinVertexIndex, UINT NumVertices,
5950 UINT PrimitiveCount, CONST void* pIndexData,
5951 WINED3DFORMAT IndexDataFormat,CONST void* pVertexStreamZeroData,
5952 UINT VertexStreamZeroStride) {
5954 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5956 TRACE("(%p) : Type=(%d,%s), MinVtxIdx=%d, NumVIdx=%d, PCount=%d, pidxdata=%p, IdxFmt=%d, pVtxdata=%p, stride=%d\n",
5957 This, PrimitiveType, debug_d3dprimitivetype(PrimitiveType),
5958 MinVertexIndex, NumVertices, PrimitiveCount, pIndexData,
5959 IndexDataFormat, pVertexStreamZeroData, VertexStreamZeroStride);
5961 if (IndexDataFormat == WINED3DFMT_INDEX16) {
5967 /* release the stream and index data */
5968 if (This->stateBlock->streamSource[0] != NULL) {
5969 IWineD3DVertexBuffer_Release(This->stateBlock->streamSource[0]);
5971 if (This->stateBlock->pIndexData) {
5972 IWineD3DIndexBuffer_Release(This->stateBlock->pIndexData);
5975 /* Note in the following, it's not this type, but that's the purpose of streamIsUP */
5976 This->stateBlock->streamSource[0] = (IWineD3DVertexBuffer *)pVertexStreamZeroData;
5977 This->stateBlock->streamIsUP = TRUE;
5978 This->stateBlock->streamStride[0] = VertexStreamZeroStride;
5980 drawPrimitive(iface, PrimitiveType, PrimitiveCount, 0 /* vertexStart */, NumVertices, 0 /* indxStart */, idxStride, pIndexData, MinVertexIndex, NULL);
5982 /* MSDN specifies stream zero settings and index buffer must be set to NULL */
5983 This->stateBlock->streamSource[0] = NULL;
5984 This->stateBlock->streamStride[0] = 0;
5985 This->stateBlock->pIndexData = NULL;
5990 static HRESULT WINAPI IWineD3DDeviceImpl_DrawPrimitiveStrided (IWineD3DDevice *iface, WINED3DPRIMITIVETYPE PrimitiveType, UINT PrimitiveCount, WineDirect3DVertexStridedData *DrawPrimStrideData) {
5992 drawPrimitive(iface, PrimitiveType, PrimitiveCount, 0, 0, 0, 0, NULL, 0, DrawPrimStrideData);
5995 /* Yet another way to update a texture, some apps use this to load default textures instead of using surface/texture lock/unlock */
5996 static HRESULT WINAPI IWineD3DDeviceImpl_UpdateTexture (IWineD3DDevice *iface, IWineD3DBaseTexture *pSourceTexture, IWineD3DBaseTexture *pDestinationTexture){
5997 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5998 HRESULT hr = WINED3D_OK;
5999 WINED3DRESOURCETYPE sourceType;
6000 WINED3DRESOURCETYPE destinationType;
6003 /* TODO: think about moving the code into IWineD3DBaseTexture */
6005 TRACE("(%p) Source %p Destination %p\n", This, pSourceTexture, pDestinationTexture);
6007 /* verify that the source and destination textures aren't NULL */
6008 if (NULL == pSourceTexture || NULL == pDestinationTexture) {
6009 WARN("(%p) : source (%p) and destination (%p) textures must not be NULL, returning WINED3DERR_INVALIDCALL\n",
6010 This, pSourceTexture, pDestinationTexture);
6011 hr = WINED3DERR_INVALIDCALL;
6014 if (pSourceTexture == pDestinationTexture) {
6015 WARN("(%p) : source (%p) and destination (%p) textures must be different, returning WINED3DERR_INVALIDCALL\n",
6016 This, pSourceTexture, pDestinationTexture);
6017 hr = WINED3DERR_INVALIDCALL;
6019 /* Verify that the source and destination textures are the same type */
6020 sourceType = IWineD3DBaseTexture_GetType(pSourceTexture);
6021 destinationType = IWineD3DBaseTexture_GetType(pDestinationTexture);
6023 if (sourceType != destinationType) {
6024 WARN("(%p) Sorce and destination types must match, returning WINED3DERR_INVALIDCALL\n",
6026 hr = WINED3DERR_INVALIDCALL;
6029 /* check that both textures have the identical numbers of levels */
6030 if (IWineD3DBaseTexture_GetLevelCount(pDestinationTexture) != IWineD3DBaseTexture_GetLevelCount(pSourceTexture)) {
6031 WARN("(%p) : source (%p) and destination (%p) textures must have identicle numbers of levels, returning WINED3DERR_INVALIDCALL\n", This, pSourceTexture, pDestinationTexture);
6032 hr = WINED3DERR_INVALIDCALL;
6035 if (WINED3D_OK == hr) {
6037 /* Make sure that the destination texture is loaded */
6038 IWineD3DBaseTexture_PreLoad(pDestinationTexture);
6040 /* Update every surface level of the texture */
6041 levels = IWineD3DBaseTexture_GetLevelCount(pDestinationTexture);
6043 switch (sourceType) {
6044 case WINED3DRTYPE_TEXTURE:
6046 IWineD3DSurface *srcSurface;
6047 IWineD3DSurface *destSurface;
6049 for (i = 0 ; i < levels ; ++i) {
6050 IWineD3DTexture_GetSurfaceLevel((IWineD3DTexture *)pSourceTexture, i, &srcSurface);
6051 IWineD3DTexture_GetSurfaceLevel((IWineD3DTexture *)pDestinationTexture, i, &destSurface);
6052 hr = IWineD3DDevice_UpdateSurface(iface, srcSurface, NULL, destSurface, NULL);
6053 IWineD3DSurface_Release(srcSurface);
6054 IWineD3DSurface_Release(destSurface);
6055 if (WINED3D_OK != hr) {
6056 WARN("(%p) : Call to update surface failed\n", This);
6062 case WINED3DRTYPE_CUBETEXTURE:
6064 IWineD3DSurface *srcSurface;
6065 IWineD3DSurface *destSurface;
6066 WINED3DCUBEMAP_FACES faceType;
6068 for (i = 0 ; i < levels ; ++i) {
6069 /* Update each cube face */
6070 for (faceType = WINED3DCUBEMAP_FACE_POSITIVE_X; faceType <= WINED3DCUBEMAP_FACE_NEGATIVE_Z; ++faceType){
6071 hr = IWineD3DCubeTexture_GetCubeMapSurface((IWineD3DCubeTexture *)pSourceTexture, faceType, i, &srcSurface);
6072 if (WINED3D_OK != hr) {
6073 FIXME("(%p) : Failed to get src cube surface facetype %d, level %d\n", This, faceType, i);
6075 TRACE("Got srcSurface %p\n", srcSurface);
6077 hr = IWineD3DCubeTexture_GetCubeMapSurface((IWineD3DCubeTexture *)pDestinationTexture, faceType, i, &destSurface);
6078 if (WINED3D_OK != hr) {
6079 FIXME("(%p) : Failed to get src cube surface facetype %d, level %d\n", This, faceType, i);
6081 TRACE("Got desrSurface %p\n", destSurface);
6083 hr = IWineD3DDevice_UpdateSurface(iface, srcSurface, NULL, destSurface, NULL);
6084 IWineD3DSurface_Release(srcSurface);
6085 IWineD3DSurface_Release(destSurface);
6086 if (WINED3D_OK != hr) {
6087 WARN("(%p) : Call to update surface failed\n", This);
6094 #if 0 /* TODO: Add support for volume textures */
6095 case WINED3DRTYPE_VOLUMETEXTURE:
6097 IWineD3DVolume srcVolume = NULL;
6098 IWineD3DSurface destVolume = NULL;
6100 for (i = 0 ; i < levels ; ++i) {
6101 IWineD3DVolumeTexture_GetVolume((IWineD3DVolumeTexture *)pSourceTexture, i, &srcVolume);
6102 IWineD3DVolumeTexture_GetVolume((IWineD3DVolumeTexture *)pDestinationTexture, i, &destVolume);
6103 hr = IWineD3DFoo_UpdateVolume(iface, srcVolume, NULL, destVolume, NULL);
6104 IWineD3DVolume_Release(srcSurface);
6105 IWineD3DVolume_Release(destSurface);
6106 if (WINED3D_OK != hr) {
6107 WARN("(%p) : Call to update volume failed\n", This);
6115 FIXME("(%p) : Unsupported source and destination type\n", This);
6116 hr = WINED3DERR_INVALIDCALL;
6123 static HRESULT WINAPI IWineD3DDeviceImpl_StretchRect(IWineD3DDevice *iface, IWineD3DSurface *pSourceSurface,
6124 CONST RECT* pSourceRect, IWineD3DSurface *pDestinationSurface,
6125 CONST RECT* pDestRect, WINED3DTEXTUREFILTERTYPE Filter) {
6126 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
6128 TRACE("(%p) : stub\n", This);
6131 static HRESULT WINAPI IWineD3DDeviceImpl_GetRenderTargetData(IWineD3DDevice *iface, IWineD3DSurface *pRenderTarget, IWineD3DSurface *pSurface) {
6132 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
6133 /** TODO: remove remove casts to IWineD3DSurfaceImpl *
6134 * NOTE It may be best to move the code into surface to occomplish this
6135 ****************************************/
6137 WINED3DSURFACE_DESC surfaceDesc;
6138 unsigned int surfaceWidth, surfaceHeight;
6139 glDescriptor *targetGlDescription = NULL;
6140 glDescriptor *surfaceGlDescription = NULL;
6141 IWineD3DSwapChainImpl *container = NULL;
6143 IWineD3DSurface_GetGlDesc(pRenderTarget, &targetGlDescription);
6144 IWineD3DSurface_GetGlDesc(pSurface, &surfaceGlDescription);
6145 memset(&surfaceDesc, 0, sizeof(surfaceDesc));
6147 surfaceDesc.Width = &surfaceWidth;
6148 surfaceDesc.Height = &surfaceHeight;
6149 IWineD3DSurface_GetDesc(pSurface, &surfaceDesc);
6150 /* check to see if it's the backbuffer or the frontbuffer being requested (to make sure the data is up to date)*/
6152 /* Ok, I may need to setup some kind of active swapchain reference on the device */
6153 IWineD3DSurface_GetContainer(pRenderTarget, &IID_IWineD3DSwapChain, (void **)&container);
6155 /* TODO: opengl Context switching for swapchains etc... */
6156 if (NULL != container || pRenderTarget == This->renderTarget || pRenderTarget == This->depthStencilBuffer) {
6157 if (NULL != container && (pRenderTarget == container->backBuffer[0])) {
6158 glReadBuffer(GL_BACK);
6159 vcheckGLcall("glReadBuffer(GL_BACK)");
6160 } else if ((NULL != container && (pRenderTarget == container->frontBuffer)) || (pRenderTarget == This->renderTarget)) {
6161 glReadBuffer(GL_FRONT);
6162 vcheckGLcall("glReadBuffer(GL_FRONT)");
6163 } else if (pRenderTarget == This->depthStencilBuffer) {
6164 FIXME("Reading of depthstencil not yet supported\n");
6171 surfaceGlDescription->glFormat,
6172 surfaceGlDescription->glType,
6173 (void *)IWineD3DSurface_GetData(pSurface));
6174 vcheckGLcall("glReadPixels(...)");
6175 if(NULL != container ){
6176 IWineD3DSwapChain_Release((IWineD3DSwapChain*) container);
6179 IWineD3DBaseTexture *container;
6180 GLenum textureDimensions = GL_TEXTURE_2D;
6182 if (WINED3D_OK == IWineD3DSurface_GetContainer(pSurface, &IID_IWineD3DBaseTexture, (void **)&container)) {
6183 textureDimensions = IWineD3DBaseTexture_GetTextureDimensions(container);
6184 IWineD3DBaseTexture_Release(container);
6186 /* TODO: 2D -> Cube surface coppies etc.. */
6187 if (surfaceGlDescription->target != textureDimensions) {
6188 FIXME("(%p) : Texture dimension mismatch\n", This);
6190 glEnable(textureDimensions);
6191 vcheckGLcall("glEnable(GL_TEXTURE_...)");
6192 /* FIXME: this isn't correct, it need to add a dirty rect if nothing else... */
6193 glBindTexture(targetGlDescription->target, targetGlDescription->textureName);
6194 vcheckGLcall("glBindTexture");
6195 glGetTexImage(surfaceGlDescription->target,
6196 surfaceGlDescription->level,
6197 surfaceGlDescription->glFormat,
6198 surfaceGlDescription->glType,
6199 (void *)IWineD3DSurface_GetData(pSurface));
6200 glDisable(textureDimensions);
6201 vcheckGLcall("glDisable(GL_TEXTURE_...)");
6208 static HRESULT WINAPI IWineD3DDeviceImpl_GetFrontBufferData(IWineD3DDevice *iface,UINT iSwapChain, IWineD3DSurface *pDestSurface) {
6209 IWineD3DSwapChain *swapChain;
6211 hr = IWineD3DDeviceImpl_GetSwapChain(iface, iSwapChain, (IWineD3DSwapChain **)&swapChain);
6212 if(hr == WINED3D_OK) {
6213 hr = IWineD3DSwapChain_GetFrontBufferData(swapChain, pDestSurface);
6214 IWineD3DSwapChain_Release(swapChain);
6219 static HRESULT WINAPI IWineD3DDeviceImpl_ValidateDevice(IWineD3DDevice *iface, DWORD* pNumPasses) {
6220 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
6221 /* return a sensible default */
6223 /* TODO: If the window is minimized then validate device should return something other than WINED3D_OK */
6224 FIXME("(%p) : stub\n", This);
6228 static HRESULT WINAPI IWineD3DDeviceImpl_SetPaletteEntries(IWineD3DDevice *iface, UINT PaletteNumber, CONST PALETTEENTRY* pEntries) {
6229 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
6231 TRACE("(%p) : PaletteNumber %u\n", This, PaletteNumber);
6232 if ( PaletteNumber < 0 || PaletteNumber >= MAX_PALETTES) {
6233 WARN("(%p) : (%u) Out of range 0-%u, returning Invalid Call\n", This, PaletteNumber, MAX_PALETTES);
6234 return WINED3DERR_INVALIDCALL;
6236 for (j = 0; j < 256; ++j) {
6237 This->palettes[PaletteNumber][j].peRed = pEntries[j].peRed;
6238 This->palettes[PaletteNumber][j].peGreen = pEntries[j].peGreen;
6239 This->palettes[PaletteNumber][j].peBlue = pEntries[j].peBlue;
6240 This->palettes[PaletteNumber][j].peFlags = pEntries[j].peFlags;
6242 TRACE("(%p) : returning\n", This);
6246 static HRESULT WINAPI IWineD3DDeviceImpl_GetPaletteEntries(IWineD3DDevice *iface, UINT PaletteNumber, PALETTEENTRY* pEntries) {
6247 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
6249 TRACE("(%p) : PaletteNumber %u\n", This, PaletteNumber);
6250 if ( PaletteNumber < 0 || PaletteNumber >= MAX_PALETTES) {
6251 WARN("(%p) : (%u) Out of range 0-%u, returning Invalid Call\n", This, PaletteNumber, MAX_PALETTES);
6252 return WINED3DERR_INVALIDCALL;
6254 for (j = 0; j < 256; ++j) {
6255 pEntries[j].peRed = This->palettes[PaletteNumber][j].peRed;
6256 pEntries[j].peGreen = This->palettes[PaletteNumber][j].peGreen;
6257 pEntries[j].peBlue = This->palettes[PaletteNumber][j].peBlue;
6258 pEntries[j].peFlags = This->palettes[PaletteNumber][j].peFlags;
6260 TRACE("(%p) : returning\n", This);
6264 static HRESULT WINAPI IWineD3DDeviceImpl_SetCurrentTexturePalette(IWineD3DDevice *iface, UINT PaletteNumber) {
6265 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
6266 TRACE("(%p) : PaletteNumber %u\n", This, PaletteNumber);
6267 if ( PaletteNumber < 0 || PaletteNumber >= MAX_PALETTES) {
6268 WARN("(%p) : (%u) Out of range 0-%u, returning Invalid Call\n", This, PaletteNumber, MAX_PALETTES);
6269 return WINED3DERR_INVALIDCALL;
6271 /*TODO: stateblocks */
6272 This->currentPalette = PaletteNumber;
6273 TRACE("(%p) : returning\n", This);
6277 static HRESULT WINAPI IWineD3DDeviceImpl_GetCurrentTexturePalette(IWineD3DDevice *iface, UINT* PaletteNumber) {
6278 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
6279 if (PaletteNumber == NULL) {
6280 WARN("(%p) : returning Invalid Call\n", This);
6281 return WINED3DERR_INVALIDCALL;
6283 /*TODO: stateblocks */
6284 *PaletteNumber = This->currentPalette;
6285 TRACE("(%p) : returning %u\n", This, *PaletteNumber);
6289 static HRESULT WINAPI IWineD3DDeviceImpl_SetSoftwareVertexProcessing(IWineD3DDevice *iface, BOOL bSoftware) {
6290 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
6291 static BOOL showFixmes = TRUE;
6293 FIXME("(%p) : stub\n", This);
6297 This->softwareVertexProcessing = bSoftware;
6302 static BOOL WINAPI IWineD3DDeviceImpl_GetSoftwareVertexProcessing(IWineD3DDevice *iface) {
6303 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
6304 static BOOL showFixmes = TRUE;
6306 FIXME("(%p) : stub\n", This);
6309 return This->softwareVertexProcessing;
6313 static HRESULT WINAPI IWineD3DDeviceImpl_GetRasterStatus(IWineD3DDevice *iface, UINT iSwapChain, WINED3DRASTER_STATUS* pRasterStatus) {
6314 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
6315 IWineD3DSwapChain *swapChain;
6318 TRACE("(%p) : SwapChain %d returning %p\n", This, iSwapChain, pRasterStatus);
6320 hr = IWineD3DDeviceImpl_GetSwapChain(iface, iSwapChain, (IWineD3DSwapChain **)&swapChain);
6321 if(hr == WINED3D_OK){
6322 hr = IWineD3DSwapChain_GetRasterStatus(swapChain, pRasterStatus);
6323 IWineD3DSwapChain_Release(swapChain);
6325 FIXME("(%p) IWineD3DSwapChain_GetRasterStatus returned in error\n", This);
6331 static HRESULT WINAPI IWineD3DDeviceImpl_SetNPatchMode(IWineD3DDevice *iface, float nSegments) {
6332 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
6333 static BOOL showfixmes = TRUE;
6334 if(nSegments != 0.0f) {
6336 FIXME("(%p) : stub nSegments(%f)\n", This, nSegments);
6343 static float WINAPI IWineD3DDeviceImpl_GetNPatchMode(IWineD3DDevice *iface) {
6344 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
6345 static BOOL showfixmes = TRUE;
6347 FIXME("(%p) : stub returning(%f)\n", This, 0.0f);
6353 static HRESULT WINAPI IWineD3DDeviceImpl_UpdateSurface(IWineD3DDevice *iface, IWineD3DSurface *pSourceSurface, CONST RECT* pSourceRect, IWineD3DSurface *pDestinationSurface, CONST POINT* pDestPoint) {
6354 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *) iface;
6355 /** TODO: remove casts to IWineD3DSurfaceImpl
6356 * NOTE: move code to surface to accomplish this
6357 ****************************************/
6358 IWineD3DSurfaceImpl *pSrcSurface = (IWineD3DSurfaceImpl *)pSourceSurface;
6359 int srcWidth, srcHeight;
6360 unsigned int srcSurfaceWidth, srcSurfaceHeight, destSurfaceWidth, destSurfaceHeight;
6361 WINED3DFORMAT destFormat, srcFormat;
6363 int destLeft, destTop;
6364 WINED3DPOOL srcPool, destPool;
6366 int rowoffset = 0; /* how many bytes to add onto the end of a row to wraparound to the beginning of the next */
6367 glDescriptor *glDescription = NULL;
6368 GLenum textureDimensions = GL_TEXTURE_2D;
6369 IWineD3DBaseTexture *baseTexture;
6371 WINED3DSURFACE_DESC winedesc;
6373 TRACE("(%p) : Source (%p) Rect (%p) Destination (%p) Point(%p)\n", This, pSourceSurface, pSourceRect, pDestinationSurface, pDestPoint);
6374 memset(&winedesc, 0, sizeof(winedesc));
6375 winedesc.Width = &srcSurfaceWidth;
6376 winedesc.Height = &srcSurfaceHeight;
6377 winedesc.Pool = &srcPool;
6378 winedesc.Format = &srcFormat;
6380 IWineD3DSurface_GetDesc(pSourceSurface, &winedesc);
6382 winedesc.Width = &destSurfaceWidth;
6383 winedesc.Height = &destSurfaceHeight;
6384 winedesc.Pool = &destPool;
6385 winedesc.Format = &destFormat;
6386 winedesc.Size = &destSize;
6388 IWineD3DSurface_GetDesc(pDestinationSurface, &winedesc);
6390 if(srcPool != WINED3DPOOL_SYSTEMMEM || destPool != WINED3DPOOL_DEFAULT){
6391 WARN("source %p must be SYSTEMMEM and dest %p must be DEFAULT, returning WINED3DERR_INVALIDCALL\n", pSourceSurface, pDestinationSurface);
6392 return WINED3DERR_INVALIDCALL;
6395 if (destFormat == WINED3DFMT_UNKNOWN) {
6396 TRACE("(%p) : Converting destination surface from WINED3DFMT_UNKNOWN to the source format\n", This);
6397 IWineD3DSurface_SetFormat(pDestinationSurface, srcFormat);
6399 /* Get the update surface description */
6400 IWineD3DSurface_GetDesc(pDestinationSurface, &winedesc);
6403 /* Make sure the surface is loaded and up to date */
6404 IWineD3DSurface_PreLoad(pDestinationSurface);
6406 IWineD3DSurface_GetGlDesc(pDestinationSurface, &glDescription);
6410 /* this needs to be done in lines if the sourceRect != the sourceWidth */
6411 srcWidth = pSourceRect ? pSourceRect->right - pSourceRect->left : srcSurfaceWidth;
6412 srcHeight = pSourceRect ? pSourceRect->top - pSourceRect->bottom : srcSurfaceHeight;
6413 destLeft = pDestPoint ? pDestPoint->x : 0;
6414 destTop = pDestPoint ? pDestPoint->y : 0;
6417 /* This function doesn't support compressed textures
6418 the pitch is just bytesPerPixel * width */
6419 if(srcWidth != srcSurfaceWidth || (pSourceRect != NULL && pSourceRect->left != 0) ){
6420 rowoffset = (srcSurfaceWidth - srcWidth) * pSrcSurface->bytesPerPixel;
6421 offset += pSourceRect->left * pSrcSurface->bytesPerPixel;
6422 /* TODO: do we ever get 3bpp?, would a shift and an add be quicker than a mul (well maybe a cycle or two) */
6424 /* TODO DXT formats */
6426 if(pSourceRect != NULL && pSourceRect->top != 0){
6427 offset += pSourceRect->top * srcWidth * pSrcSurface->bytesPerPixel;
6429 TRACE("(%p) glTexSubImage2D, Level %d, left %d, top %d, width %d, height %d , ftm %d, type %d, memory %p\n"
6431 ,glDescription->level
6436 ,glDescription->glFormat
6437 ,glDescription->glType
6438 ,IWineD3DSurface_GetData(pSourceSurface)
6442 if (IWineD3DSurface_GetData(pSourceSurface) == NULL) {
6444 /* need to lock the surface to get the data */
6445 FIXME("Surfaces has no allocated memory, but should be an in memory only surface\n");
6448 /* TODO: Cube and volume support */
6450 /* not a whole row so we have to do it a line at a time */
6453 /* hopefully using pointer addtion will be quicker than using a point + j * rowoffset */
6454 const unsigned char* data =((const unsigned char *)IWineD3DSurface_GetData(pSourceSurface)) + offset;
6456 for(j = destTop ; j < (srcHeight + destTop) ; j++){
6458 glTexSubImage2D(glDescription->target
6459 ,glDescription->level
6464 ,glDescription->glFormat
6465 ,glDescription->glType
6466 ,data /* could be quicker using */
6471 } else { /* Full width, so just write out the whole texture */
6473 if (WINED3DFMT_DXT1 == destFormat ||
6474 WINED3DFMT_DXT2 == destFormat ||
6475 WINED3DFMT_DXT3 == destFormat ||
6476 WINED3DFMT_DXT4 == destFormat ||
6477 WINED3DFMT_DXT5 == destFormat) {
6478 if (GL_SUPPORT(EXT_TEXTURE_COMPRESSION_S3TC)) {
6479 if (destSurfaceHeight != srcHeight || destSurfaceWidth != srcWidth) {
6480 /* FIXME: The easy way to do this is to lock the destination, and copy the bits across */
6481 FIXME("Updating part of a compressed texture is not supported at the moment\n");
6482 } if (destFormat != srcFormat) {
6483 FIXME("Updating mixed format compressed texture is not curretly support\n");
6485 GL_EXTCALL(glCompressedTexImage2DARB)(glDescription->target,
6486 glDescription->level,
6487 glDescription->glFormatInternal,
6492 IWineD3DSurface_GetData(pSourceSurface));
6495 FIXME("Attempting to update a DXT compressed texture without hardware support\n");
6500 if (NP2_REPACK == wined3d_settings.nonpower2_mode) {
6502 /* some applications cannot handle odd pitches returned by soft non-power2, so we have
6503 to repack the data from pow2Width/Height to expected Width,Height, this makes the
6504 data returned by GetData non-power2 width/height with hardware non-power2
6505 pow2Width/height are set to surface width height, repacking isn't needed so it
6506 doesn't matter which function gets called. */
6507 glTexSubImage2D(glDescription->target
6508 ,glDescription->level
6513 ,glDescription->glFormat
6514 ,glDescription->glType
6515 ,IWineD3DSurface_GetData(pSourceSurface)
6519 /* not repacked, the data returned by IWineD3DSurface_GetData is pow2Width x pow2Height */
6520 glTexSubImage2D(glDescription->target
6521 ,glDescription->level
6524 ,((IWineD3DSurfaceImpl *)pSourceSurface)->pow2Width
6525 ,((IWineD3DSurfaceImpl *)pSourceSurface)->pow2Height
6526 ,glDescription->glFormat
6527 ,glDescription->glType
6528 ,IWineD3DSurface_GetData(pSourceSurface)
6534 checkGLcall("glTexSubImage2D");
6535 ((IWineD3DSurfaceImpl *)pDestinationSurface)->Flags |= SFLAG_GLDIRTY;
6537 /* I only need to look up baseTexture here, so it may be a good idea to hava a GL_TARGET ->
6538 * GL_DIMENSIONS lookup, or maybe store the dimensions on the surface (but that's making the
6539 * surface bigger than it needs to be hmm.. */
6540 if (WINED3D_OK == IWineD3DSurface_GetContainer(pDestinationSurface, &IID_IWineD3DBaseTexture, (void **)&baseTexture)) {
6541 textureDimensions = IWineD3DBaseTexture_GetTextureDimensions(baseTexture);
6542 IWineD3DBaseTexture_Release(baseTexture);
6545 glDisable(textureDimensions); /* This needs to be managed better.... */
6551 /* Implementation details at http://developer.nvidia.com/attach/6494
6553 http://oss.sgi.com/projects/ogl-sample/registry/NV/evaluators.txt
6554 hmm.. no longer supported use
6555 OpenGL evaluators or tessellate surfaces within your application.
6558 /* http://msdn.microsoft.com/library/default.asp?url=/library/en-us/directx9_c/directx/graphics/reference/d3d/interfaces/idirect3ddevice9/DrawRectPatch.asp */
6559 static HRESULT WINAPI IWineD3DDeviceImpl_DrawRectPatch(IWineD3DDevice *iface, UINT Handle, CONST float* pNumSegs, CONST WINED3DRECTPATCH_INFO* pRectPatchInfo) {
6560 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
6561 TRACE("(%p) Handle(%d) noSegs(%p) rectpatch(%p)\n", This, Handle, pNumSegs, pRectPatchInfo);
6562 FIXME("(%p) : Stub\n", This);
6567 /* http://msdn.microsoft.com/library/default.asp?url=/library/en-us/directx9_c/directx/graphics/reference/d3d/interfaces/idirect3ddevice9/DrawTriPatch.asp */
6568 static HRESULT WINAPI IWineD3DDeviceImpl_DrawTriPatch(IWineD3DDevice *iface, UINT Handle, CONST float* pNumSegs, CONST WINED3DTRIPATCH_INFO* pTriPatchInfo) {
6569 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
6570 TRACE("(%p) Handle(%d) noSegs(%p) tripatch(%p)\n", This, Handle, pNumSegs, pTriPatchInfo);
6571 FIXME("(%p) : Stub\n", This);
6575 static HRESULT WINAPI IWineD3DDeviceImpl_DeletePatch(IWineD3DDevice *iface, UINT Handle) {
6576 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
6577 TRACE("(%p) Handle(%d)\n", This, Handle);
6578 FIXME("(%p) : Stub\n", This);
6582 static HRESULT WINAPI IWineD3DDeviceImpl_ColorFill(IWineD3DDevice *iface, IWineD3DSurface *pSurface, CONST WINED3DRECT* pRect, WINED3DCOLOR color) {
6583 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *) iface;
6584 IWineD3DSurfaceImpl *surface = (IWineD3DSurfaceImpl *) pSurface;
6586 TRACE("(%p) Colour fill Surface: %p rect: %p color: %d\n", This, pSurface, pRect, color);
6588 if (surface->resource.pool != WINED3DPOOL_DEFAULT && surface->resource.pool != WINED3DPOOL_SYSTEMMEM) {
6589 FIXME("call to colorfill with non WINED3DPOOL_DEFAULT or WINED3DPOOL_SYSTEMMEM surface\n");
6590 return WINED3DERR_INVALIDCALL;
6593 /* Just forward this to the DirectDraw blitting engine */
6594 memset(&BltFx, 0, sizeof(BltFx));
6595 BltFx.dwSize = sizeof(BltFx);
6596 BltFx.u5.dwFillColor = color;
6597 return IWineD3DSurface_Blt(pSurface, (RECT *) pRect, NULL, NULL, DDBLT_COLORFILL, &BltFx);
6600 /* rendertarget and deptth stencil functions */
6601 static HRESULT WINAPI IWineD3DDeviceImpl_GetRenderTarget(IWineD3DDevice* iface,DWORD RenderTargetIndex, IWineD3DSurface **ppRenderTarget) {
6602 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
6604 /* FIXME: Implelent RenderTargetIndex >0 */
6605 if(RenderTargetIndex > 0)
6606 FIXME("(%p) : RenderTargetIndex %d >0 not currently supported\n", This, RenderTargetIndex);
6608 *ppRenderTarget = This->renderTarget;
6609 TRACE("(%p) : RenderTarget %d Index returning %p\n", This, RenderTargetIndex, *ppRenderTarget);
6610 /* Note inc ref on returned surface */
6611 if(*ppRenderTarget != NULL)
6612 IWineD3DSurface_AddRef(*ppRenderTarget);
6616 static HRESULT WINAPI IWineD3DDeviceImpl_SetFrontBackBuffers(IWineD3DDevice *iface, IWineD3DSurface *Front, IWineD3DSurface *Back) {
6617 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
6618 IWineD3DSurfaceImpl *FrontImpl = (IWineD3DSurfaceImpl *) Front;
6619 IWineD3DSurfaceImpl *BackImpl = (IWineD3DSurfaceImpl *) Back;
6620 IWineD3DSwapChainImpl *Swapchain;
6623 TRACE("(%p)->(%p,%p)\n", This, FrontImpl, BackImpl);
6625 hr = IWineD3DDevice_GetSwapChain(iface, 0, (IWineD3DSwapChain **) &Swapchain);
6626 if(hr != WINED3D_OK) {
6627 ERR("Can't get the swapchain\n");
6631 /* Make sure to release the swapchain */
6632 IWineD3DSwapChain_Release((IWineD3DSwapChain *) Swapchain);
6634 if(FrontImpl && !(FrontImpl->resource.usage & WINED3DUSAGE_RENDERTARGET) ) {
6635 ERR("Trying to set a front buffer which doesn't have WINED3DUSAGE_RENDERTARGET usage\n");
6636 return WINED3DERR_INVALIDCALL;
6638 else if(BackImpl && !(BackImpl->resource.usage & WINED3DUSAGE_RENDERTARGET)) {
6639 ERR("Trying to set a back buffer which doesn't have WINED3DUSAGE_RENDERTARGET usage\n");
6640 return WINED3DERR_INVALIDCALL;
6643 if(Swapchain->frontBuffer != Front) {
6644 TRACE("Changing the front buffer from %p to %p\n", Swapchain->frontBuffer, Front);
6646 if(Swapchain->frontBuffer)
6647 IWineD3DSurface_SetContainer(Swapchain->frontBuffer, NULL);
6648 Swapchain->frontBuffer = Front;
6650 if(Swapchain->frontBuffer) {
6651 IWineD3DSurface_SetContainer(Swapchain->frontBuffer, (IWineD3DBase *) Swapchain);
6655 if(Back && !Swapchain->backBuffer) {
6656 /* We need memory for the back buffer array - only one back buffer this way */
6657 Swapchain->backBuffer = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(IWineD3DSurface *));
6658 if(!Swapchain->backBuffer) {
6659 ERR("Out of memory\n");
6660 return E_OUTOFMEMORY;
6664 if(Swapchain->backBuffer[0] != Back) {
6665 TRACE("Changing the back buffer from %p to %p\n", Swapchain->backBuffer, Back);
6667 if(!Swapchain->backBuffer[0]) {
6668 /* GL was told to draw to the front buffer at creation,
6671 glDrawBuffer(GL_BACK);
6672 checkGLcall("glDrawBuffer(GL_BACK)");
6673 /* Set the backbuffer count to 1 because other code uses it to fing the back buffers */
6674 Swapchain->presentParms.BackBufferCount = 1;
6676 /* That makes problems - disable for now */
6677 /* glDrawBuffer(GL_FRONT); */
6678 checkGLcall("glDrawBuffer(GL_FRONT)");
6679 /* We have lost our back buffer, set this to 0 to avoid confusing other code */
6680 Swapchain->presentParms.BackBufferCount = 0;
6684 if(Swapchain->backBuffer[0])
6685 IWineD3DSurface_SetContainer(Swapchain->backBuffer[0], NULL);
6686 Swapchain->backBuffer[0] = Back;
6688 if(Swapchain->backBuffer[0]) {
6689 IWineD3DSurface_SetContainer(Swapchain->backBuffer[0], (IWineD3DBase *) Swapchain);
6691 HeapFree(GetProcessHeap(), 0, Swapchain->backBuffer);
6699 static HRESULT WINAPI IWineD3DDeviceImpl_GetDepthStencilSurface(IWineD3DDevice* iface, IWineD3DSurface **ppZStencilSurface) {
6700 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
6701 *ppZStencilSurface = This->depthStencilBuffer;
6702 TRACE("(%p) : zStencilSurface returning %p\n", This, *ppZStencilSurface);
6704 if(*ppZStencilSurface != NULL) {
6705 /* Note inc ref on returned surface */
6706 IWineD3DSurface_AddRef(*ppZStencilSurface);
6711 static void bind_fbo(IWineD3DDevice *iface) {
6712 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
6715 GL_EXTCALL(glGenFramebuffersEXT(1, &This->fbo));
6716 checkGLcall("glGenFramebuffersEXT()");
6718 GL_EXTCALL(glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, This->fbo));
6719 checkGLcall("glBindFramebuffer()");
6722 /* TODO: Handle stencil attachments */
6723 static void set_depth_stencil_fbo(IWineD3DDevice *iface, IWineD3DSurface *depth_stencil) {
6724 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
6725 IWineD3DSurfaceImpl *depth_stencil_impl = (IWineD3DSurfaceImpl *)depth_stencil;
6727 This->depth_copy_state = WINED3D_DCS_NO_COPY;
6731 if (depth_stencil_impl) {
6732 GLenum texttarget, target;
6734 IWineD3DSurface_PreLoad(depth_stencil);
6735 texttarget = depth_stencil_impl->glDescription.target;
6736 target = texttarget == GL_TEXTURE_2D ? GL_TEXTURE_2D : GL_TEXTURE_CUBE_MAP_ARB;
6738 glBindTexture(target, depth_stencil_impl->glDescription.textureName);
6739 glTexParameteri(target, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
6740 glTexParameteri(target, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
6741 glTexParameteri(target, GL_DEPTH_TEXTURE_MODE_ARB, GL_LUMINANCE);
6742 glBindTexture(target, 0);
6744 GL_EXTCALL(glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_DEPTH_ATTACHMENT_EXT, texttarget, depth_stencil_impl->glDescription.textureName, 0));
6745 checkGLcall("glFramebufferTexture2DEXT()");
6747 GL_EXTCALL(glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_DEPTH_ATTACHMENT_EXT, GL_TEXTURE_2D, 0, 0));
6748 checkGLcall("glFramebufferTexture2DEXT()");
6751 if (!This->render_offscreen) {
6752 GL_EXTCALL(glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0));
6753 checkGLcall("glBindFramebuffer()");
6757 static void set_render_target_fbo(IWineD3DDevice *iface, IWineD3DSurface *render_target) {
6758 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
6759 IWineD3DSurfaceImpl *rtimpl = (IWineD3DSurfaceImpl *)render_target;
6761 if (This->render_offscreen) {
6762 GLenum texttarget, target;
6766 IWineD3DSurface_PreLoad(render_target);
6767 texttarget = rtimpl->glDescription.target;
6768 target = texttarget == GL_TEXTURE_2D ? GL_TEXTURE_2D : GL_TEXTURE_CUBE_MAP_ARB;
6770 glBindTexture(target, rtimpl->glDescription.textureName);
6771 glTexParameteri(target, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
6772 glTexParameteri(target, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
6773 glBindTexture(target, 0);
6775 GL_EXTCALL(glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT, texttarget, rtimpl->glDescription.textureName, 0));
6776 checkGLcall("glFramebufferTexture2DEXT()");
6778 GL_EXTCALL(glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0));
6779 checkGLcall("glBindFramebuffer()");
6783 /* internal static helper functions */
6784 static HRESULT WINAPI IWineD3DDeviceImpl_ActiveRender(IWineD3DDevice* iface,
6785 IWineD3DSurface *RenderSurface);
6787 static HRESULT WINAPI IWineD3DDeviceImpl_SetRenderTarget(IWineD3DDevice *iface, DWORD RenderTargetIndex, IWineD3DSurface *pRenderTarget) {
6788 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
6789 HRESULT hr = WINED3D_OK;
6790 WINED3DVIEWPORT viewport;
6792 TRACE("(%p) Swapping rendertarget\n",This);
6793 if (RenderTargetIndex > 0) {
6794 FIXME("(%p) Render targets other than the first are not supported\n",This);
6795 RenderTargetIndex = 0;
6798 /* MSDN says that null disables the render target
6799 but a device must always be associated with a render target
6800 nope MSDN says that we return invalid call to a null rendertarget with an index of 0
6802 see http://msdn.microsoft.com/library/default.asp?url=/library/en-us/directx9_c/directx/graphics/programmingguide/AdvancedTopics/PixelPipe/MultipleRenderTarget.asp
6805 if (RenderTargetIndex == 0 && pRenderTarget == NULL) {
6806 FIXME("Trying to set render target 0 to NULL\n");
6807 return WINED3DERR_INVALIDCALL;
6809 /* TODO: replace Impl* usage with interface usage */
6810 if (!((IWineD3DSurfaceImpl *)pRenderTarget)->resource.usage & WINED3DUSAGE_RENDERTARGET) {
6811 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);
6812 return WINED3DERR_INVALIDCALL;
6814 /** TODO: check that the depth stencil format matches the render target, this is only done in debug
6815 * builds, but I think wine counts as a 'debug' build for now.
6816 ******************************/
6817 /* If we are trying to set what we already have, don't bother */
6818 if (pRenderTarget == This->renderTarget) {
6819 TRACE("Trying to do a NOP SetRenderTarget operation\n");
6821 /* Otherwise, set the render target up */
6823 if (!This->sceneEnded) {
6824 IWineD3DDevice_EndScene(iface);
6826 TRACE("clearing renderer\n");
6827 /* IWineD3DDeviceImpl_CleanRender(iface); */
6828 /* OpenGL doesn't support 'sharing' of the stencilBuffer so we may incure an extra memory overhead
6829 depending on the renter target implementation being used.
6830 A shared context implementation will share all buffers between all rendertargets (including swapchains),
6831 implementations that use separate pbuffers for different swapchains or rendertargets will have to duplicate the
6832 stencil buffer and incure an extra memory overhead */
6833 hr = IWineD3DDeviceImpl_ActiveRender(iface, pRenderTarget);
6834 if (wined3d_settings.offscreen_rendering_mode == ORM_FBO) {
6835 set_render_target_fbo(iface, pRenderTarget);
6839 if (SUCCEEDED(hr)) {
6840 /* Finally, reset the viewport as the MSDN states. */
6841 /* TODO: Replace impl usage */
6842 viewport.Height = ((IWineD3DSurfaceImpl *)This->renderTarget)->currentDesc.Height;
6843 viewport.Width = ((IWineD3DSurfaceImpl *)This->renderTarget)->currentDesc.Width;
6846 viewport.MaxZ = 1.0f;
6847 viewport.MinZ = 0.0f;
6848 IWineD3DDeviceImpl_SetViewport(iface, &viewport);
6850 FIXME("Unknown error setting the render target\n");
6852 This->sceneEnded = FALSE;
6856 static HRESULT WINAPI IWineD3DDeviceImpl_SetDepthStencilSurface(IWineD3DDevice *iface, IWineD3DSurface *pNewZStencil) {
6857 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
6858 HRESULT hr = WINED3D_OK;
6859 IWineD3DSurface *tmp;
6861 TRACE("(%p) Swapping z-buffer\n",This);
6863 if (pNewZStencil == This->stencilBufferTarget) {
6864 TRACE("Trying to do a NOP SetRenderTarget operation\n");
6866 /** OpenGL doesn't support 'sharing' of the stencilBuffer so we may incure an extra memory overhead
6867 * depending on the renter target implementation being used.
6868 * A shared context implementation will share all buffers between all rendertargets (including swapchains),
6869 * implementations that use separate pbuffers for different swapchains or rendertargets will have to duplicate the
6870 * stencil buffer and incure an extra memory overhead
6871 ******************************************************/
6874 tmp = This->stencilBufferTarget;
6875 This->stencilBufferTarget = pNewZStencil;
6876 /* should we be calling the parent or the wined3d surface? */
6877 if (NULL != This->stencilBufferTarget) IWineD3DSurface_AddRef(This->stencilBufferTarget);
6878 if (NULL != tmp) IWineD3DSurface_Release(tmp);
6880 /** TODO: glEnable/glDisable on depth/stencil depending on
6881 * pNewZStencil is NULL and the depth/stencil is enabled in d3d
6882 **********************************************************/
6883 if (wined3d_settings.offscreen_rendering_mode == ORM_FBO) {
6884 set_depth_stencil_fbo(iface, pNewZStencil);
6892 #ifdef GL_VERSION_1_3
6893 /* Internal functions not in DirectX */
6894 /** TODO: move this off to the opengl context manager
6895 *(the swapchain doesn't need to know anything about offscreen rendering!)
6896 ****************************************************/
6898 static HRESULT WINAPI IWineD3DDeviceImpl_CleanRender(IWineD3DDevice* iface, IWineD3DSwapChainImpl *swapchain)
6900 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
6902 TRACE("(%p), %p\n", This, swapchain);
6904 if (swapchain->win != swapchain->drawable) {
6905 /* Set everything back the way it ws */
6906 swapchain->render_ctx = swapchain->glCtx;
6907 swapchain->drawable = swapchain->win;
6912 /* TODO: move this off into a context manager so that GLX_ATI_render_texture and other types of surface can be used. */
6913 static HRESULT WINAPI IWineD3DDeviceImpl_FindGLContext(IWineD3DDevice *iface, IWineD3DSurface *pSurface, glContext **context) {
6914 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
6917 unsigned int height;
6918 WINED3DFORMAT format;
6919 WINED3DSURFACE_DESC surfaceDesc;
6920 memset(&surfaceDesc, 0, sizeof(surfaceDesc));
6921 surfaceDesc.Width = &width;
6922 surfaceDesc.Height = &height;
6923 surfaceDesc.Format = &format;
6924 IWineD3DSurface_GetDesc(pSurface, &surfaceDesc);
6926 /* I need a get width/height function (and should do something with the format) */
6927 for (i = 0; i < CONTEXT_CACHE; ++i) {
6928 /** NOTE: the contextCache[i].pSurface == pSurface check ceates onepbuffer per surface
6929 ATI cards don't destroy pbuffers, but as soon as resource releasing callbacks are inplace
6930 the pSurface can be set to 0 allowing it to be reused from cache **/
6931 if (This->contextCache[i].Width == width && This->contextCache[i].Height == height
6932 && (!pbuffer_per_surface || This->contextCache[i].pSurface == pSurface || This->contextCache[i].pSurface == NULL)) {
6933 *context = &This->contextCache[i];
6936 if (This->contextCache[i].Width == 0) {
6937 This->contextCache[i].pSurface = pSurface;
6938 This->contextCache[i].Width = width;
6939 This->contextCache[i].Height = height;
6940 *context = &This->contextCache[i];
6944 if (i == CONTEXT_CACHE) {
6945 int minUsage = 0x7FFFFFFF; /* MAX_INT */
6946 glContext *dropContext = 0;
6947 for (i = 0; i < CONTEXT_CACHE; i++) {
6948 if (This->contextCache[i].usedcount < minUsage) {
6949 dropContext = &This->contextCache[i];
6950 minUsage = This->contextCache[i].usedcount;
6953 /* clean up the context (this doesn't work for ATI at the moment */
6955 glXDestroyContext(swapchain->display, dropContext->context);
6956 glXDestroyPbuffer(swapchain->display, dropContext->drawable);
6959 dropContext->Width = 0;
6960 dropContext->pSurface = pSurface;
6961 *context = dropContext;
6963 if (++This->contextCache[i].usedcount == 0x7FFFFFFF /* MAX_INT */ - 1 ) {
6964 for (i = 0; i < CONTEXT_CACHE; i++) {
6965 This->contextCache[i].usedcount = max(0, This->contextCache[i].usedcount - (0x7FFFFFFF /* MAX_INT */ >> 1));
6969 if (*context != NULL)
6972 return E_OUTOFMEMORY;
6976 /* Reapply the device stateblock */
6977 static void device_reapply_stateblock(IWineD3DDeviceImpl* This) {
6980 IWineD3DStateBlockImpl *oldUpdateStateBlock;
6982 /* Disable recording */
6983 oldUpdateStateBlock = This->updateStateBlock;
6984 oldRecording= This->isRecordingState;
6985 This->isRecordingState = FALSE;
6986 This->updateStateBlock = This->stateBlock;
6988 /* Reapply the state block */
6989 IWineD3DStateBlock_Apply((IWineD3DStateBlock *)This->stateBlock);
6991 /* Restore recording */
6992 This->isRecordingState = oldRecording;
6993 This->updateStateBlock = oldUpdateStateBlock;
6996 /* Set offscreen rendering. When rendering offscreen the surface will be
6997 * rendered upside down to compensate for the fact that D3D texture coordinates
6998 * are flipped compared to GL texture coordinates. The cullmode is affected by
6999 * this, so it must be updated. To update the cullmode stateblock recording has
7000 * to be temporarily disabled. The new state management code will hopefully
7001 * make this unnecessary */
7002 static void device_render_to_texture(IWineD3DDeviceImpl* This, BOOL isTexture) {
7006 IWineD3DStateBlockImpl *oldUpdateStateBlock;
7008 /* Nothing to update, return. */
7009 if (This->render_offscreen == isTexture) return;
7011 /* Disable recording */
7012 oldUpdateStateBlock = This->updateStateBlock;
7013 oldRecording= This->isRecordingState;
7014 This->isRecordingState = FALSE;
7015 This->updateStateBlock = This->stateBlock;
7017 This->render_offscreen = isTexture;
7018 if (This->depth_copy_state != WINED3D_DCS_NO_COPY) {
7019 This->depth_copy_state = WINED3D_DCS_COPY;
7021 This->last_was_rhw = FALSE;
7022 This->proj_valid = FALSE;
7023 IWineD3DDevice_GetRenderState((IWineD3DDevice*) This, WINED3DRS_CULLMODE, &cullMode);
7024 IWineD3DDevice_SetRenderState((IWineD3DDevice*) This, WINED3DRS_CULLMODE, cullMode);
7026 /* Restore recording */
7027 This->isRecordingState = oldRecording;
7028 This->updateStateBlock = oldUpdateStateBlock;
7031 /* Returns an array of compatible FBconfig(s).
7032 * The array must be freed with XFree. Requires ENTER_GL() */
7034 static GLXFBConfig* device_find_fbconfigs(
7035 IWineD3DDeviceImpl* This,
7036 IWineD3DSwapChainImpl* implicitSwapchainImpl,
7037 IWineD3DSurface* RenderSurface) {
7039 GLXFBConfig* cfgs = NULL;
7044 IWineD3DSurface *StencilSurface = This->stencilBufferTarget;
7045 WINED3DFORMAT BackBufferFormat = ((IWineD3DSurfaceImpl *) RenderSurface)->resource.format;
7046 WINED3DFORMAT StencilBufferFormat = (NULL != StencilSurface) ? ((IWineD3DSurfaceImpl *) StencilSurface)->resource.format : 0;
7049 if StencilSurface == NULL && zBufferTarget != NULL then switch the zbuffer off,
7050 it StencilSurface != NULL && zBufferTarget == NULL switch it on
7053 #define PUSH1(att) attribs[nAttribs++] = (att);
7054 #define PUSH2(att,value) attribs[nAttribs++] = (att); attribs[nAttribs++] = (value);
7056 /* PUSH2(GLX_BIND_TO_TEXTURE_RGBA_ATI, True); examples of this are few and far between (but I've got a nice working one!)*/
7058 PUSH2(GLX_DRAWABLE_TYPE, GLX_PBUFFER_BIT);
7059 PUSH2(GLX_X_RENDERABLE, TRUE);
7060 PUSH2(GLX_DOUBLEBUFFER, TRUE);
7061 TRACE("calling makeglcfg\n");
7062 D3DFmtMakeGlCfg(BackBufferFormat, StencilBufferFormat, attribs, &nAttribs, FALSE /* alternate */);
7064 TRACE("calling chooseFGConfig\n");
7065 cfgs = glXChooseFBConfig(implicitSwapchainImpl->display,
7066 DefaultScreen(implicitSwapchainImpl->display),
7069 /* OK we didn't find the exact config, so use any reasonable match */
7070 /* TODO: fill in the 'requested' and 'current' depths, and make sure that's
7072 static BOOL show_message = TRUE;
7074 ERR("Failed to find exact match, finding alternative but you may "
7075 "suffer performance issues, try changing xfree's depth to match the requested depth\n");
7076 show_message = FALSE;
7079 PUSH2(GLX_DRAWABLE_TYPE, GLX_PBUFFER_BIT | GLX_WINDOW_BIT);
7080 /* PUSH2(GLX_X_RENDERABLE, TRUE); */
7081 PUSH2(GLX_RENDER_TYPE, GLX_RGBA_BIT);
7082 PUSH2(GLX_DOUBLEBUFFER, FALSE);
7083 TRACE("calling makeglcfg\n");
7084 D3DFmtMakeGlCfg(BackBufferFormat, StencilBufferFormat, attribs, &nAttribs, TRUE /* alternate */);
7086 cfgs = glXChooseFBConfig(implicitSwapchainImpl->display,
7087 DefaultScreen(implicitSwapchainImpl->display),
7092 ERR("Could not get a valid FBConfig for (%u,%s)/(%u,%s)\n",
7093 BackBufferFormat, debug_d3dformat(BackBufferFormat),
7094 StencilBufferFormat, debug_d3dformat(StencilBufferFormat));
7098 for (i = 0; i < nCfgs; ++i) {
7099 TRACE("for (%u,%s)/(%u,%s) found config[%d]@%p\n", BackBufferFormat,
7100 debug_d3dformat(BackBufferFormat), StencilBufferFormat,
7101 debug_d3dformat(StencilBufferFormat), i, cfgs[i]);
7103 if (NULL != This->renderTarget) {
7105 vcheckGLcall("glFlush");
7106 /** This is only useful if the old render target was a swapchain,
7107 * we need to supercede this with a function that displays
7108 * the current buffer on the screen. This is easy to do in glx1.3 but
7109 * we need to do copy-write pixels in glx 1.2.
7110 ************************************************/
7111 glXSwapBuffers(implicitSwapChainImpl->display,
7112 implicitSwapChainImpl->drawable);
7113 printf("Hit Enter to get next frame ...\n");
7124 /** FIXME: This is currently used called whenever SetRenderTarget or SetStencilBuffer are called
7125 * the functionality needs splitting up so that we don't do more than we should do.
7126 * this only seems to impact performance a little.
7127 ******************************/
7128 static HRESULT WINAPI IWineD3DDeviceImpl_ActiveRender(IWineD3DDevice* iface,
7129 IWineD3DSurface *RenderSurface) {
7132 * Currently only active for GLX >= 1.3
7133 * for others versions we'll have to use GLXPixmaps
7135 * normally we must test GLX_VERSION_1_3 but nvidia headers are not correct
7136 * as they implement GLX 1.3 but only define GLX_VERSION_1_2
7137 * so only check OpenGL version
7138 * ..........................
7139 * I don't believe that it is a problem with NVidia headers,
7140 * XFree only supports GLX1.2, nVidia (and ATI to some extent) provide 1.3 functions
7141 * in GLX 1.2, there is no mention of the correct way to tell if the extensions are provided.
7143 * Your application will report GLX version 1.2 on glXQueryVersion.
7144 * However, it is safe to call the GLX 1.3 functions as described below.
7146 #if defined(GL_VERSION_1_3)
7148 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
7149 GLXFBConfig* cfgs = NULL;
7150 IWineD3DSwapChain *currentSwapchain;
7151 IWineD3DSwapChainImpl *currentSwapchainImpl;
7152 IWineD3DSwapChain *implicitSwapchain;
7153 IWineD3DSwapChainImpl *implicitSwapchainImpl;
7154 IWineD3DSwapChain *renderSurfaceSwapchain;
7155 IWineD3DSwapChainImpl *renderSurfaceSwapchainImpl;
7157 /* Obtain a reference to the device implicit swapchain,
7158 * the swapchain of the current render target,
7159 * and the swapchain of the new render target.
7160 * Fallback to device implicit swapchain if the current render target doesn't have one */
7161 IWineD3DDevice_GetSwapChain(iface, 0, &implicitSwapchain);
7162 IWineD3DSurface_GetContainer(RenderSurface, &IID_IWineD3DSwapChain, (void**) &renderSurfaceSwapchain);
7163 IWineD3DSurface_GetContainer(This->renderTarget, &IID_IWineD3DSwapChain, (void **)¤tSwapchain);
7164 if (currentSwapchain == NULL)
7165 IWineD3DDevice_GetSwapChain(iface, 0, ¤tSwapchain);
7167 currentSwapchainImpl = (IWineD3DSwapChainImpl*) currentSwapchain;
7168 implicitSwapchainImpl = (IWineD3DSwapChainImpl*) implicitSwapchain;
7169 renderSurfaceSwapchainImpl = (IWineD3DSwapChainImpl*) renderSurfaceSwapchain;
7174 * TODO: remove the use of IWineD3DSwapChainImpl, a context manager will help since it will replace the
7175 * renderTarget = swapchain->backBuffer[i] bit and anything to do with *glContexts
7176 **********************************************************************/
7177 if (renderSurfaceSwapchain != NULL) {
7179 /* We also need to make sure that the lights &co are also in the context of the swapchains */
7180 /* FIXME: If the render target gets sent to the frontBuffer, should we be presenting it raw? */
7181 TRACE("making swapchain active\n");
7182 if (RenderSurface != This->renderTarget) {
7183 BOOL backbuf = FALSE;
7186 for(i = 0; i < renderSurfaceSwapchainImpl->presentParms.BackBufferCount; i++) {
7187 if(RenderSurface == renderSurfaceSwapchainImpl->backBuffer[i]) {
7195 /* This could be flagged so that some operations work directly with the front buffer */
7196 FIXME("Attempting to set the renderTarget to the frontBuffer\n");
7198 if (glXMakeCurrent(renderSurfaceSwapchainImpl->display,
7199 renderSurfaceSwapchainImpl->win,
7200 renderSurfaceSwapchainImpl->glCtx) == False) {
7202 TRACE("Error in setting current context: context %p drawable %ld !\n",
7203 implicitSwapchainImpl->glCtx, implicitSwapchainImpl->win);
7205 checkGLcall("glXMakeContextCurrent");
7207 /* Clean up the old context */
7208 IWineD3DDeviceImpl_CleanRender(iface, currentSwapchainImpl);
7210 /* Reapply the stateblock, and set the device not to render to texture */
7211 device_reapply_stateblock(This);
7212 device_render_to_texture(This, FALSE);
7215 /* Offscreen rendering: PBuffers (currently disabled).
7216 * Also note that this path is never reached if FBOs are supported */
7217 } else if (wined3d_settings.offscreen_rendering_mode == ORM_PBUFFER &&
7218 (cfgs = device_find_fbconfigs(This, implicitSwapchainImpl, RenderSurface)) != NULL) {
7220 /** ********************************************************************
7221 * This is a quickly hacked out implementation of offscreen textures.
7222 * It will work in most cases but there may be problems if the client
7223 * modifies the texture directly, or expects the contents of the rendertarget
7226 * There are some real speed vs compatibility issues here:
7227 * we should really use a new context for every texture, but that eats ram.
7228 * we should also be restoring the texture to the pbuffer but that eats CPU
7229 * we can also 'reuse' the current pbuffer if the size is larger than the requested buffer,
7230 * but if this means reusing the display backbuffer then we need to make sure that
7231 * states are correctly preserved.
7232 * In many cases I would expect that we can 'skip' some functions, such as preserving states,
7233 * and gain a good performance increase at the cost of compatibility.
7234 * I would suggest that, when this is the case, a user configurable flag be made
7235 * available, allowing the user to choose the best emulated experience for them.
7236 *********************************************************************/
7238 XVisualInfo *visinfo;
7239 glContext *newContext;
7241 /* Here were using a shared context model */
7242 if (WINED3D_OK != IWineD3DDeviceImpl_FindGLContext(iface, RenderSurface, &newContext)) {
7243 FIXME("(%p) : Failed to find a context for surface %p\n", iface, RenderSurface);
7246 /* If the context doesn't exist then create a new one */
7247 /* TODO: This should really be part of findGlContext */
7248 if (NULL == newContext->context) {
7253 TRACE("making new buffer\n");
7254 attribs[nAttribs++] = GLX_PBUFFER_WIDTH;
7255 attribs[nAttribs++] = newContext->Width;
7256 attribs[nAttribs++] = GLX_PBUFFER_HEIGHT;
7257 attribs[nAttribs++] = newContext->Height;
7258 attribs[nAttribs++] = None;
7260 newContext->drawable = glXCreatePbuffer(implicitSwapchainImpl->display, cfgs[0], attribs);
7262 /** ****************************************
7263 *GLX1.3 isn't supported by XFree 'yet' until that point ATI emulates pBuffers
7265 * In future releases, we may provide the calls glXCreateNewContext,
7266 * glXQueryDrawable and glXMakeContextCurrent.
7267 * so until then we have to use glXGetVisualFromFBConfig &co..
7268 ********************************************/
7270 visinfo = glXGetVisualFromFBConfig(implicitSwapchainImpl->display, cfgs[0]);
7272 ERR("Error: couldn't get an RGBA, double-buffered visual\n");
7274 newContext->context = glXCreateContext(
7275 implicitSwapchainImpl->display, visinfo,
7276 implicitSwapchainImpl->glCtx, GL_TRUE);
7281 if (NULL == newContext || NULL == newContext->context) {
7282 ERR("(%p) : Failed to find a context for surface %p\n", iface, RenderSurface);
7284 /* Debug logging, (this function leaks), change to a TRACE when the leak is plugged */
7285 if (glXMakeCurrent(implicitSwapchainImpl->display,
7286 newContext->drawable, newContext->context) == False) {
7288 TRACE("Error in setting current context: context %p drawable %ld\n",
7289 newContext->context, newContext->drawable);
7291 checkGLcall("glXMakeContextCurrent");
7293 /* Clean up the old context */
7294 IWineD3DDeviceImpl_CleanRender(iface, currentSwapchainImpl);
7296 /* Reapply stateblock, and set device to render to a texture */
7297 device_reapply_stateblock(This);
7298 device_render_to_texture(This, TRUE);
7300 /* Set the current context of the swapchain to the new context */
7301 implicitSwapchainImpl->drawable = newContext->drawable;
7302 implicitSwapchainImpl->render_ctx = newContext->context;
7305 /* Same context, but update render_offscreen and cull mode */
7306 device_render_to_texture(This, TRUE);
7309 /* Replace the render target */
7310 if (This->renderTarget != RenderSurface) {
7311 IWineD3DSurface_Release(This->renderTarget);
7312 This->renderTarget = RenderSurface;
7313 IWineD3DSurface_AddRef(RenderSurface);
7316 if (cfgs != NULL) XFree(cfgs);
7317 if (implicitSwapchain != NULL) IWineD3DSwapChain_Release(implicitSwapchain);
7318 if (currentSwapchain != NULL) IWineD3DSwapChain_Release(currentSwapchain);
7319 if (renderSurfaceSwapchain != NULL) IWineD3DSwapChain_Release(renderSurfaceSwapchain);
7325 static HRESULT WINAPI IWineD3DDeviceImpl_SetCursorProperties(IWineD3DDevice* iface, UINT XHotSpot,
7326 UINT YHotSpot, IWineD3DSurface *pCursorBitmap) {
7327 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *) iface;
7328 /* TODO: the use of Impl is deprecated. */
7329 IWineD3DSurfaceImpl * pSur = (IWineD3DSurfaceImpl *) pCursorBitmap;
7331 TRACE("(%p) : Spot Pos(%u,%u)\n", This, XHotSpot, YHotSpot);
7333 /* some basic validation checks */
7334 if(This->cursorTexture) {
7336 glDeleteTextures(1, &This->cursorTexture);
7338 This->cursorTexture = 0;
7342 /* MSDN: Cursor must be A8R8G8B8 */
7343 if (WINED3DFMT_A8R8G8B8 != pSur->resource.format) {
7344 ERR("(%p) : surface(%p) has an invalid format\n", This, pCursorBitmap);
7345 return WINED3DERR_INVALIDCALL;
7348 /* MSDN: Cursor must be smaller than the display mode */
7349 if(pSur->currentDesc.Width > This->ddraw_width ||
7350 pSur->currentDesc.Height > This->ddraw_height) {
7351 ERR("(%p) : Surface(%p) is %dx%d pixels, but screen res is %dx%d\n", This, pSur, pSur->currentDesc.Width, pSur->currentDesc.Height, This->ddraw_width, This->ddraw_height);
7352 return WINED3DERR_INVALIDCALL;
7355 /* TODO: MSDN: Cursor sizes must be a power of 2 */
7356 /* This is to tell our texture code to load a SCRATCH surface. This allows us to use out
7357 * Texture and Blitting code to draw the cursor
7359 pSur->Flags |= SFLAG_FORCELOAD;
7360 IWineD3DSurface_PreLoad(pCursorBitmap);
7361 pSur->Flags &= ~SFLAG_FORCELOAD;
7362 /* Do not store the surface's pointer because the application may release
7363 * it after setting the cursor image. Windows doesn't addref the set surface, so we can't
7364 * do this either without creating circular refcount dependencies. Copy out the gl texture instead.
7366 This->cursorTexture = pSur->glDescription.textureName;
7367 This->cursorWidth = pSur->currentDesc.Width;
7368 This->cursorHeight = pSur->currentDesc.Height;
7369 pSur->glDescription.textureName = 0; /* Prevent the texture from being changed or deleted */
7372 This->xHotSpot = XHotSpot;
7373 This->yHotSpot = YHotSpot;
7377 static void WINAPI IWineD3DDeviceImpl_SetCursorPosition(IWineD3DDevice* iface, int XScreenSpace, int YScreenSpace, DWORD Flags) {
7378 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *) iface;
7379 TRACE("(%p) : SetPos to (%u,%u)\n", This, XScreenSpace, YScreenSpace);
7381 This->xScreenSpace = XScreenSpace;
7382 This->yScreenSpace = YScreenSpace;
7388 static BOOL WINAPI IWineD3DDeviceImpl_ShowCursor(IWineD3DDevice* iface, BOOL bShow) {
7389 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *) iface;
7390 BOOL oldVisible = This->bCursorVisible;
7391 TRACE("(%p) : visible(%d)\n", This, bShow);
7393 if(This->cursorTexture)
7394 This->bCursorVisible = bShow;
7399 static HRESULT WINAPI IWineD3DDeviceImpl_TestCooperativeLevel(IWineD3DDevice* iface) {
7400 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *) iface;
7401 TRACE("(%p) : state (%u)\n", This, This->state);
7402 /* TODO: Implement wrapping of the WndProc so that mimimize and maxamise can be monitored and the states adjusted. */
7403 switch (This->state) {
7406 case WINED3DERR_DEVICELOST:
7408 ResourceList *resourceList = This->resources;
7409 while (NULL != resourceList) {
7410 if (((IWineD3DResourceImpl *)resourceList->resource)->resource.pool == WINED3DPOOL_DEFAULT /* TODO: IWineD3DResource_GetPool(resourceList->resource)*/)
7411 return WINED3DERR_DEVICENOTRESET;
7412 resourceList = resourceList->next;
7414 return WINED3DERR_DEVICELOST;
7416 case WINED3DERR_DRIVERINTERNALERROR:
7417 return WINED3DERR_DRIVERINTERNALERROR;
7421 return WINED3DERR_DRIVERINTERNALERROR;
7425 static HRESULT WINAPI IWineD3DDeviceImpl_EvictManagedResources(IWineD3DDevice* iface) {
7426 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *) iface;
7427 /** FIXME: Resource tracking needs to be done,
7428 * The closes we can do to this is set the priorities of all managed textures low
7429 * and then reset them.
7430 ***********************************************************/
7431 FIXME("(%p) : stub\n", This);
7435 void updateSurfaceDesc(IWineD3DSurfaceImpl *surface, WINED3DPRESENT_PARAMETERS* pPresentationParameters) {
7436 /* Reallocate proper memory for the front and back buffer and adjust their sizes */
7437 if(surface->Flags & SFLAG_DIBSECTION) {
7438 /* Release the DC */
7439 SelectObject(surface->hDC, surface->dib.holdbitmap);
7440 DeleteDC(surface->hDC);
7441 /* Release the DIB section */
7442 DeleteObject(surface->dib.DIBsection);
7443 surface->dib.bitmap_data = NULL;
7444 surface->resource.allocatedMemory = NULL;
7445 surface->Flags &= ~SFLAG_DIBSECTION;
7447 surface->currentDesc.Width = *pPresentationParameters->BackBufferWidth;
7448 surface->currentDesc.Height = *pPresentationParameters->BackBufferHeight;
7449 if (wined3d_settings.nonpower2_mode == NP2_NATIVE) {
7450 surface->pow2Width = *pPresentationParameters->BackBufferWidth;
7451 surface->pow2Height = *pPresentationParameters->BackBufferHeight;
7453 surface->pow2Width = surface->pow2Height = 1;
7454 while (surface->pow2Width < *pPresentationParameters->BackBufferWidth) surface->pow2Width <<= 1;
7455 while (surface->pow2Height < *pPresentationParameters->BackBufferHeight) surface->pow2Height <<= 1;
7457 if(surface->glDescription.textureName) {
7459 glDeleteTextures(1, &surface->glDescription.textureName);
7461 surface->glDescription.textureName = 0;
7463 if(surface->pow2Width != *pPresentationParameters->BackBufferWidth ||
7464 surface->pow2Height != *pPresentationParameters->BackBufferHeight) {
7465 surface->Flags |= SFLAG_NONPOW2;
7467 surface->Flags &= ~SFLAG_NONPOW2;
7469 HeapFree(GetProcessHeap(), 0, surface->resource.allocatedMemory);
7470 surface->resource.size = IWineD3DSurface_GetPitch((IWineD3DSurface *) surface) * surface->pow2Width;
7473 static HRESULT WINAPI IWineD3DDeviceImpl_Reset(IWineD3DDevice* iface, WINED3DPRESENT_PARAMETERS* pPresentationParameters) {
7474 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *) iface;
7475 IWineD3DSwapChainImpl *swapchain;
7477 BOOL DisplayModeChanged = FALSE;
7478 WINED3DDISPLAYMODE mode;
7479 TRACE("(%p)\n", This);
7481 hr = IWineD3DDevice_GetSwapChain(iface, 0, (IWineD3DSwapChain **) &swapchain);
7483 ERR("Failed to get the first implicit swapchain\n");
7487 /* Is it necessary to recreate the gl context? Actually every setting can be changed
7488 * on an existing gl context, so there's no real need for recreation.
7490 * TODO: Figure out how Reset influences resources in D3DPOOL_DEFAULT, D3DPOOL_SYSTEMMEMORY and D3DPOOL_MANAGED
7492 * TODO: Figure out what happens to explicit swapchains, or if we have more than one implicit swapchain
7494 TRACE("New params:\n");
7495 TRACE("BackBufferWidth = %d\n", *pPresentationParameters->BackBufferWidth);
7496 TRACE("BackBufferHeight = %d\n", *pPresentationParameters->BackBufferHeight);
7497 TRACE("BackBufferFormat = %s\n", debug_d3dformat(*pPresentationParameters->BackBufferFormat));
7498 TRACE("BackBufferCount = %d\n", *pPresentationParameters->BackBufferCount);
7499 TRACE("MultiSampleType = %d\n", *pPresentationParameters->MultiSampleType);
7500 TRACE("MultiSampleQuality = %d\n", *pPresentationParameters->MultiSampleQuality);
7501 TRACE("SwapEffect = %d\n", *pPresentationParameters->SwapEffect);
7502 TRACE("hDeviceWindow = %p\n", *pPresentationParameters->hDeviceWindow);
7503 TRACE("Windowed = %s\n", *pPresentationParameters->Windowed ? "true" : "false");
7504 TRACE("EnableAutoDepthStencil = %s\n", *pPresentationParameters->EnableAutoDepthStencil ? "true" : "false");
7505 TRACE("Flags = %08x\n", *pPresentationParameters->Flags);
7506 TRACE("FullScreen_RefreshRateInHz = %d\n", *pPresentationParameters->FullScreen_RefreshRateInHz);
7507 TRACE("PresentationInterval = %d\n", *pPresentationParameters->PresentationInterval);
7509 /* No special treatment of these parameters. Just store them */
7510 swapchain->presentParms.SwapEffect = *pPresentationParameters->SwapEffect;
7511 swapchain->presentParms.Flags = *pPresentationParameters->Flags;
7512 swapchain->presentParms.PresentationInterval = *pPresentationParameters->PresentationInterval;
7513 swapchain->presentParms.FullScreen_RefreshRateInHz = *pPresentationParameters->FullScreen_RefreshRateInHz;
7515 /* What to do about these? */
7516 if(*pPresentationParameters->BackBufferCount != 0 &&
7517 *pPresentationParameters->BackBufferCount != swapchain->presentParms.BackBufferCount) {
7518 ERR("Cannot change the back buffer count yet\n");
7520 if(*pPresentationParameters->BackBufferFormat != WINED3DFMT_UNKNOWN &&
7521 *pPresentationParameters->BackBufferFormat != swapchain->presentParms.BackBufferFormat) {
7522 ERR("Cannot change the back buffer format yet\n");
7524 if(*pPresentationParameters->hDeviceWindow != NULL &&
7525 *pPresentationParameters->hDeviceWindow != swapchain->presentParms.hDeviceWindow) {
7526 ERR("Cannot change the device window yet\n");
7528 if(*pPresentationParameters->EnableAutoDepthStencil != swapchain->presentParms.EnableAutoDepthStencil) {
7529 ERR("What do do about a changed auto depth stencil parameter?\n");
7532 if(*pPresentationParameters->Windowed) {
7533 mode.Width = swapchain->orig_width;
7534 mode.Height = swapchain->orig_height;
7535 mode.RefreshRate = 0;
7536 mode.Format = swapchain->presentParms.BackBufferFormat;
7538 mode.Width = *pPresentationParameters->BackBufferWidth;
7539 mode.Height = *pPresentationParameters->BackBufferHeight;
7540 mode.RefreshRate = *pPresentationParameters->FullScreen_RefreshRateInHz;
7541 mode.Format = swapchain->presentParms.BackBufferFormat;
7544 /* Should Width == 800 && Height == 0 set 800x600? */
7545 if(*pPresentationParameters->BackBufferWidth != 0 && *pPresentationParameters->BackBufferHeight != 0 &&
7546 (*pPresentationParameters->BackBufferWidth != swapchain->presentParms.BackBufferWidth ||
7547 *pPresentationParameters->BackBufferHeight != swapchain->presentParms.BackBufferHeight))
7554 vp.Width = *pPresentationParameters->BackBufferWidth;
7555 vp.Height = *pPresentationParameters->BackBufferHeight;
7559 if(!*pPresentationParameters->Windowed) {
7560 DisplayModeChanged = TRUE;
7562 swapchain->presentParms.BackBufferWidth = *pPresentationParameters->BackBufferWidth;
7563 swapchain->presentParms.BackBufferHeight = *pPresentationParameters->BackBufferHeight;
7565 updateSurfaceDesc((IWineD3DSurfaceImpl *)swapchain->frontBuffer, pPresentationParameters);
7566 for(i = 0; i < swapchain->presentParms.BackBufferCount; i++) {
7567 updateSurfaceDesc((IWineD3DSurfaceImpl *)swapchain->backBuffer[i], pPresentationParameters);
7570 /* Now set the new viewport */
7571 IWineD3DDevice_SetViewport(iface, &vp);
7574 if((*pPresentationParameters->Windowed && !swapchain->presentParms.Windowed) ||
7575 (swapchain->presentParms.Windowed && !*pPresentationParameters->Windowed) ||
7576 DisplayModeChanged) {
7577 IWineD3DDevice_SetDisplayMode(iface, 0, &mode);
7580 IWineD3DSwapChain_Release((IWineD3DSwapChain *) swapchain);
7584 static HRESULT WINAPI IWineD3DDeviceImpl_SetDialogBoxMode(IWineD3DDevice *iface, BOOL bEnableDialogs) {
7585 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
7586 /** FIXME: always true at the moment **/
7587 if(!bEnableDialogs) {
7588 FIXME("(%p) Dialogs cannot be disabled yet\n", This);
7594 static HRESULT WINAPI IWineD3DDeviceImpl_GetCreationParameters(IWineD3DDevice *iface, WINED3DDEVICE_CREATION_PARAMETERS *pParameters) {
7595 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *) iface;
7596 TRACE("(%p) : pParameters %p\n", This, pParameters);
7598 *pParameters = This->createParms;
7602 static void WINAPI IWineD3DDeviceImpl_SetGammaRamp(IWineD3DDevice * iface, UINT iSwapChain, DWORD Flags, CONST WINED3DGAMMARAMP* pRamp) {
7603 IWineD3DSwapChain *swapchain;
7604 HRESULT hrc = WINED3D_OK;
7606 TRACE("Relaying to swapchain\n");
7608 if ((hrc = IWineD3DDeviceImpl_GetSwapChain(iface, iSwapChain, &swapchain)) == WINED3D_OK) {
7609 IWineD3DSwapChain_SetGammaRamp(swapchain, Flags, (WINED3DGAMMARAMP *)pRamp);
7610 IWineD3DSwapChain_Release(swapchain);
7615 static void WINAPI IWineD3DDeviceImpl_GetGammaRamp(IWineD3DDevice *iface, UINT iSwapChain, WINED3DGAMMARAMP* pRamp) {
7616 IWineD3DSwapChain *swapchain;
7617 HRESULT hrc = WINED3D_OK;
7619 TRACE("Relaying to swapchain\n");
7621 if ((hrc = IWineD3DDeviceImpl_GetSwapChain(iface, iSwapChain, &swapchain)) == WINED3D_OK) {
7622 hrc =IWineD3DSwapChain_GetGammaRamp(swapchain, pRamp);
7623 IWineD3DSwapChain_Release(swapchain);
7629 /** ********************************************************
7630 * Notification functions
7631 ** ********************************************************/
7632 /** This function must be called in the release of a resource when ref == 0,
7633 * the contents of resource must still be correct,
7634 * any handels to other resource held by the caller must be closed
7635 * (e.g. a texture should release all held surfaces because telling the device that it's been released.)
7636 *****************************************************/
7637 static void WINAPI IWineD3DDeviceImpl_AddResource(IWineD3DDevice *iface, IWineD3DResource *resource){
7638 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
7639 ResourceList* resourceList;
7641 TRACE("(%p) : resource %p\n", This, resource);
7643 EnterCriticalSection(&resourceStoreCriticalSection);
7645 /* add a new texture to the frot of the linked list */
7646 resourceList = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(ResourceList));
7647 resourceList->resource = resource;
7649 /* Get the old head */
7650 resourceList->next = This->resources;
7652 This->resources = resourceList;
7653 TRACE("Added resource %p with element %p pointing to %p\n", resource, resourceList, resourceList->next);
7656 LeaveCriticalSection(&resourceStoreCriticalSection);
7661 static void WINAPI IWineD3DDeviceImpl_RemoveResource(IWineD3DDevice *iface, IWineD3DResource *resource){
7662 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
7663 ResourceList* resourceList = NULL;
7664 ResourceList* previousResourceList = NULL;
7666 TRACE("(%p) : resource %p\n", This, resource);
7669 EnterCriticalSection(&resourceStoreCriticalSection);
7671 resourceList = This->resources;
7673 while (resourceList != NULL) {
7674 if(resourceList->resource == resource) break;
7675 previousResourceList = resourceList;
7676 resourceList = resourceList->next;
7679 if (resourceList == NULL) {
7680 FIXME("Attempted to remove resource %p that hasn't been stored\n", resource);
7682 LeaveCriticalSection(&resourceStoreCriticalSection);
7686 TRACE("Found resource %p with element %p pointing to %p (previous %p)\n", resourceList->resource, resourceList, resourceList->next, previousResourceList);
7688 /* make sure we don't leave a hole in the list */
7689 if (previousResourceList != NULL) {
7690 previousResourceList->next = resourceList->next;
7692 This->resources = resourceList->next;
7696 LeaveCriticalSection(&resourceStoreCriticalSection);
7702 static void WINAPI IWineD3DDeviceImpl_ResourceReleased(IWineD3DDevice *iface, IWineD3DResource *resource){
7703 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *) iface;
7706 TRACE("(%p) : resource %p\n", This, resource);
7707 switch(IWineD3DResource_GetType(resource)){
7708 case WINED3DRTYPE_SURFACE:
7709 /* TODO: check front and back buffers, rendertargets etc.. possibly swapchains? */
7711 case WINED3DRTYPE_TEXTURE:
7712 case WINED3DRTYPE_CUBETEXTURE:
7713 case WINED3DRTYPE_VOLUMETEXTURE:
7714 for (counter = 0; counter < GL_LIMITS(sampler_stages); counter++) {
7715 if (This->stateBlock != NULL && This->stateBlock->textures[counter] == (IWineD3DBaseTexture *)resource) {
7716 WARN("Texture being released is still by a stateblock, Stage = %u Texture = %p\n", counter, resource);
7717 This->stateBlock->textures[counter] = NULL;
7719 if (This->updateStateBlock != This->stateBlock ){
7720 if (This->updateStateBlock->textures[counter] == (IWineD3DBaseTexture *)resource) {
7721 WARN("Texture being released is still by a stateblock, Stage = %u Texture = %p\n", counter, resource);
7722 This->updateStateBlock->textures[counter] = NULL;
7727 case WINED3DRTYPE_VOLUME:
7728 /* TODO: nothing really? */
7730 case WINED3DRTYPE_VERTEXBUFFER:
7731 /* MSDN: When an application no longer holds a references to this interface, the interface will automatically be freed. */
7734 TRACE("Cleaning up stream pointers\n");
7736 for(streamNumber = 0; streamNumber < MAX_STREAMS; streamNumber ++){
7737 /* FINDOUT: should a warn be generated if were recording and updateStateBlock->streamSource is lost?
7738 FINDOUT: should changes.streamSource[StreamNumber] be set ?
7740 if (This->updateStateBlock != NULL ) { /* ==NULL when device is being destroyed */
7741 if ((IWineD3DResource *)This->updateStateBlock->streamSource[streamNumber] == resource) {
7742 FIXME("Vertex buffer released while bound to a state block, stream %d\n", streamNumber);
7743 This->updateStateBlock->streamSource[streamNumber] = 0;
7744 /* Set changed flag? */
7747 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) */
7748 if ((IWineD3DResource *)This->stateBlock->streamSource[streamNumber] == resource) {
7749 TRACE("Vertex buffer released while bound to a state block, stream %d\n", streamNumber);
7750 This->stateBlock->streamSource[streamNumber] = 0;
7753 #if 0 /* TODO: Manage internal tracking properly so that 'this shouldn't happen' */
7754 else { /* This shouldn't happen */
7755 FIXME("Calling application has released the device before relasing all the resources bound to the device\n");
7762 case WINED3DRTYPE_INDEXBUFFER:
7763 /* MSDN: When an application no longer holds a references to this interface, the interface will automatically be freed.*/
7764 if (This->updateStateBlock != NULL ) { /* ==NULL when device is being destroyed */
7765 if (This->updateStateBlock->pIndexData == (IWineD3DIndexBuffer *)resource) {
7766 This->updateStateBlock->pIndexData = NULL;
7769 if (This->stateBlock != NULL ) { /* ==NULL when device is being destroyed */
7770 if (This->stateBlock->pIndexData == (IWineD3DIndexBuffer *)resource) {
7771 This->stateBlock->pIndexData = NULL;
7777 FIXME("(%p) unknown resource type %p %u\n", This, resource, IWineD3DResource_GetType(resource));
7782 /* Remove the resoruce from the resourceStore */
7783 IWineD3DDeviceImpl_RemoveResource(iface, resource);
7785 TRACE("Resource released\n");
7789 /**********************************************************
7790 * IWineD3DDevice VTbl follows
7791 **********************************************************/
7793 const IWineD3DDeviceVtbl IWineD3DDevice_Vtbl =
7795 /*** IUnknown methods ***/
7796 IWineD3DDeviceImpl_QueryInterface,
7797 IWineD3DDeviceImpl_AddRef,
7798 IWineD3DDeviceImpl_Release,
7799 /*** IWineD3DDevice methods ***/
7800 IWineD3DDeviceImpl_GetParent,
7801 /*** Creation methods**/
7802 IWineD3DDeviceImpl_CreateVertexBuffer,
7803 IWineD3DDeviceImpl_CreateIndexBuffer,
7804 IWineD3DDeviceImpl_CreateStateBlock,
7805 IWineD3DDeviceImpl_CreateSurface,
7806 IWineD3DDeviceImpl_CreateTexture,
7807 IWineD3DDeviceImpl_CreateVolumeTexture,
7808 IWineD3DDeviceImpl_CreateVolume,
7809 IWineD3DDeviceImpl_CreateCubeTexture,
7810 IWineD3DDeviceImpl_CreateQuery,
7811 IWineD3DDeviceImpl_CreateAdditionalSwapChain,
7812 IWineD3DDeviceImpl_CreateVertexDeclaration,
7813 IWineD3DDeviceImpl_CreateVertexShader,
7814 IWineD3DDeviceImpl_CreatePixelShader,
7815 IWineD3DDeviceImpl_CreatePalette,
7816 /*** Odd functions **/
7817 IWineD3DDeviceImpl_Init3D,
7818 IWineD3DDeviceImpl_Uninit3D,
7819 IWineD3DDeviceImpl_SetFullscreen,
7820 IWineD3DDeviceImpl_EnumDisplayModes,
7821 IWineD3DDeviceImpl_EvictManagedResources,
7822 IWineD3DDeviceImpl_GetAvailableTextureMem,
7823 IWineD3DDeviceImpl_GetBackBuffer,
7824 IWineD3DDeviceImpl_GetCreationParameters,
7825 IWineD3DDeviceImpl_GetDeviceCaps,
7826 IWineD3DDeviceImpl_GetDirect3D,
7827 IWineD3DDeviceImpl_GetDisplayMode,
7828 IWineD3DDeviceImpl_SetDisplayMode,
7829 IWineD3DDeviceImpl_GetHWND,
7830 IWineD3DDeviceImpl_SetHWND,
7831 IWineD3DDeviceImpl_GetNumberOfSwapChains,
7832 IWineD3DDeviceImpl_GetRasterStatus,
7833 IWineD3DDeviceImpl_GetSwapChain,
7834 IWineD3DDeviceImpl_Reset,
7835 IWineD3DDeviceImpl_SetDialogBoxMode,
7836 IWineD3DDeviceImpl_SetCursorProperties,
7837 IWineD3DDeviceImpl_SetCursorPosition,
7838 IWineD3DDeviceImpl_ShowCursor,
7839 IWineD3DDeviceImpl_TestCooperativeLevel,
7840 /*** Getters and setters **/
7841 IWineD3DDeviceImpl_SetClipPlane,
7842 IWineD3DDeviceImpl_GetClipPlane,
7843 IWineD3DDeviceImpl_SetClipStatus,
7844 IWineD3DDeviceImpl_GetClipStatus,
7845 IWineD3DDeviceImpl_SetCurrentTexturePalette,
7846 IWineD3DDeviceImpl_GetCurrentTexturePalette,
7847 IWineD3DDeviceImpl_SetDepthStencilSurface,
7848 IWineD3DDeviceImpl_GetDepthStencilSurface,
7849 IWineD3DDeviceImpl_SetFVF,
7850 IWineD3DDeviceImpl_GetFVF,
7851 IWineD3DDeviceImpl_SetGammaRamp,
7852 IWineD3DDeviceImpl_GetGammaRamp,
7853 IWineD3DDeviceImpl_SetIndices,
7854 IWineD3DDeviceImpl_GetIndices,
7855 IWineD3DDeviceImpl_SetLight,
7856 IWineD3DDeviceImpl_GetLight,
7857 IWineD3DDeviceImpl_SetLightEnable,
7858 IWineD3DDeviceImpl_GetLightEnable,
7859 IWineD3DDeviceImpl_SetMaterial,
7860 IWineD3DDeviceImpl_GetMaterial,
7861 IWineD3DDeviceImpl_SetNPatchMode,
7862 IWineD3DDeviceImpl_GetNPatchMode,
7863 IWineD3DDeviceImpl_SetPaletteEntries,
7864 IWineD3DDeviceImpl_GetPaletteEntries,
7865 IWineD3DDeviceImpl_SetPixelShader,
7866 IWineD3DDeviceImpl_GetPixelShader,
7867 IWineD3DDeviceImpl_SetPixelShaderConstantB,
7868 IWineD3DDeviceImpl_GetPixelShaderConstantB,
7869 IWineD3DDeviceImpl_SetPixelShaderConstantI,
7870 IWineD3DDeviceImpl_GetPixelShaderConstantI,
7871 IWineD3DDeviceImpl_SetPixelShaderConstantF,
7872 IWineD3DDeviceImpl_GetPixelShaderConstantF,
7873 IWineD3DDeviceImpl_SetRenderState,
7874 IWineD3DDeviceImpl_GetRenderState,
7875 IWineD3DDeviceImpl_SetRenderTarget,
7876 IWineD3DDeviceImpl_GetRenderTarget,
7877 IWineD3DDeviceImpl_SetFrontBackBuffers,
7878 IWineD3DDeviceImpl_SetSamplerState,
7879 IWineD3DDeviceImpl_GetSamplerState,
7880 IWineD3DDeviceImpl_SetScissorRect,
7881 IWineD3DDeviceImpl_GetScissorRect,
7882 IWineD3DDeviceImpl_SetSoftwareVertexProcessing,
7883 IWineD3DDeviceImpl_GetSoftwareVertexProcessing,
7884 IWineD3DDeviceImpl_SetStreamSource,
7885 IWineD3DDeviceImpl_GetStreamSource,
7886 IWineD3DDeviceImpl_SetStreamSourceFreq,
7887 IWineD3DDeviceImpl_GetStreamSourceFreq,
7888 IWineD3DDeviceImpl_SetTexture,
7889 IWineD3DDeviceImpl_GetTexture,
7890 IWineD3DDeviceImpl_SetTextureStageState,
7891 IWineD3DDeviceImpl_GetTextureStageState,
7892 IWineD3DDeviceImpl_SetTransform,
7893 IWineD3DDeviceImpl_GetTransform,
7894 IWineD3DDeviceImpl_SetVertexDeclaration,
7895 IWineD3DDeviceImpl_GetVertexDeclaration,
7896 IWineD3DDeviceImpl_SetVertexShader,
7897 IWineD3DDeviceImpl_GetVertexShader,
7898 IWineD3DDeviceImpl_SetVertexShaderConstantB,
7899 IWineD3DDeviceImpl_GetVertexShaderConstantB,
7900 IWineD3DDeviceImpl_SetVertexShaderConstantI,
7901 IWineD3DDeviceImpl_GetVertexShaderConstantI,
7902 IWineD3DDeviceImpl_SetVertexShaderConstantF,
7903 IWineD3DDeviceImpl_GetVertexShaderConstantF,
7904 IWineD3DDeviceImpl_SetViewport,
7905 IWineD3DDeviceImpl_GetViewport,
7906 IWineD3DDeviceImpl_MultiplyTransform,
7907 IWineD3DDeviceImpl_ValidateDevice,
7908 IWineD3DDeviceImpl_ProcessVertices,
7909 /*** State block ***/
7910 IWineD3DDeviceImpl_BeginStateBlock,
7911 IWineD3DDeviceImpl_EndStateBlock,
7912 /*** Scene management ***/
7913 IWineD3DDeviceImpl_BeginScene,
7914 IWineD3DDeviceImpl_EndScene,
7915 IWineD3DDeviceImpl_Present,
7916 IWineD3DDeviceImpl_Clear,
7918 IWineD3DDeviceImpl_DrawPrimitive,
7919 IWineD3DDeviceImpl_DrawIndexedPrimitive,
7920 IWineD3DDeviceImpl_DrawPrimitiveUP,
7921 IWineD3DDeviceImpl_DrawIndexedPrimitiveUP,
7922 IWineD3DDeviceImpl_DrawPrimitiveStrided,
7923 IWineD3DDeviceImpl_DrawRectPatch,
7924 IWineD3DDeviceImpl_DrawTriPatch,
7925 IWineD3DDeviceImpl_DeletePatch,
7926 IWineD3DDeviceImpl_ColorFill,
7927 IWineD3DDeviceImpl_UpdateTexture,
7928 IWineD3DDeviceImpl_UpdateSurface,
7929 IWineD3DDeviceImpl_StretchRect,
7930 IWineD3DDeviceImpl_GetRenderTargetData,
7931 IWineD3DDeviceImpl_GetFrontBufferData,
7932 /*** Internal use IWineD3DDevice methods ***/
7933 IWineD3DDeviceImpl_SetupTextureStates,
7934 /*** object tracking ***/
7935 IWineD3DDeviceImpl_ResourceReleased
7939 const DWORD SavedPixelStates_R[NUM_SAVEDPIXELSTATES_R] = {
7940 WINED3DRS_ALPHABLENDENABLE ,
7941 WINED3DRS_ALPHAFUNC ,
7942 WINED3DRS_ALPHAREF ,
7943 WINED3DRS_ALPHATESTENABLE ,
7945 WINED3DRS_COLORWRITEENABLE ,
7946 WINED3DRS_DESTBLEND ,
7947 WINED3DRS_DITHERENABLE ,
7948 WINED3DRS_FILLMODE ,
7949 WINED3DRS_FOGDENSITY ,
7951 WINED3DRS_FOGSTART ,
7952 WINED3DRS_LASTPIXEL ,
7953 WINED3DRS_SHADEMODE ,
7954 WINED3DRS_SRCBLEND ,
7955 WINED3DRS_STENCILENABLE ,
7956 WINED3DRS_STENCILFAIL ,
7957 WINED3DRS_STENCILFUNC ,
7958 WINED3DRS_STENCILMASK ,
7959 WINED3DRS_STENCILPASS ,
7960 WINED3DRS_STENCILREF ,
7961 WINED3DRS_STENCILWRITEMASK ,
7962 WINED3DRS_STENCILZFAIL ,
7963 WINED3DRS_TEXTUREFACTOR ,
7974 WINED3DRS_ZWRITEENABLE
7977 const DWORD SavedPixelStates_T[NUM_SAVEDPIXELSTATES_T] = {
7978 WINED3DTSS_ADDRESSW ,
7979 WINED3DTSS_ALPHAARG0 ,
7980 WINED3DTSS_ALPHAARG1 ,
7981 WINED3DTSS_ALPHAARG2 ,
7982 WINED3DTSS_ALPHAOP ,
7983 WINED3DTSS_BUMPENVLOFFSET ,
7984 WINED3DTSS_BUMPENVLSCALE ,
7985 WINED3DTSS_BUMPENVMAT00 ,
7986 WINED3DTSS_BUMPENVMAT01 ,
7987 WINED3DTSS_BUMPENVMAT10 ,
7988 WINED3DTSS_BUMPENVMAT11 ,
7989 WINED3DTSS_COLORARG0 ,
7990 WINED3DTSS_COLORARG1 ,
7991 WINED3DTSS_COLORARG2 ,
7992 WINED3DTSS_COLOROP ,
7993 WINED3DTSS_RESULTARG ,
7994 WINED3DTSS_TEXCOORDINDEX ,
7995 WINED3DTSS_TEXTURETRANSFORMFLAGS
7998 const DWORD SavedPixelStates_S[NUM_SAVEDPIXELSTATES_S] = {
7999 WINED3DSAMP_ADDRESSU ,
8000 WINED3DSAMP_ADDRESSV ,
8001 WINED3DSAMP_ADDRESSW ,
8002 WINED3DSAMP_BORDERCOLOR ,
8003 WINED3DSAMP_MAGFILTER ,
8004 WINED3DSAMP_MINFILTER ,
8005 WINED3DSAMP_MIPFILTER ,
8006 WINED3DSAMP_MIPMAPLODBIAS ,
8007 WINED3DSAMP_MAXMIPLEVEL ,
8008 WINED3DSAMP_MAXANISOTROPY ,
8009 WINED3DSAMP_SRGBTEXTURE ,
8010 WINED3DSAMP_ELEMENTINDEX
8013 const DWORD SavedVertexStates_R[NUM_SAVEDVERTEXSTATES_R] = {
8015 WINED3DRS_AMBIENTMATERIALSOURCE ,
8016 WINED3DRS_CLIPPING ,
8017 WINED3DRS_CLIPPLANEENABLE ,
8018 WINED3DRS_COLORVERTEX ,
8019 WINED3DRS_DIFFUSEMATERIALSOURCE ,
8020 WINED3DRS_EMISSIVEMATERIALSOURCE ,
8021 WINED3DRS_FOGDENSITY ,
8023 WINED3DRS_FOGSTART ,
8024 WINED3DRS_FOGTABLEMODE ,
8025 WINED3DRS_FOGVERTEXMODE ,
8026 WINED3DRS_INDEXEDVERTEXBLENDENABLE ,
8027 WINED3DRS_LIGHTING ,
8028 WINED3DRS_LOCALVIEWER ,
8029 WINED3DRS_MULTISAMPLEANTIALIAS ,
8030 WINED3DRS_MULTISAMPLEMASK ,
8031 WINED3DRS_NORMALIZENORMALS ,
8032 WINED3DRS_PATCHEDGESTYLE ,
8033 WINED3DRS_POINTSCALE_A ,
8034 WINED3DRS_POINTSCALE_B ,
8035 WINED3DRS_POINTSCALE_C ,
8036 WINED3DRS_POINTSCALEENABLE ,
8037 WINED3DRS_POINTSIZE ,
8038 WINED3DRS_POINTSIZE_MAX ,
8039 WINED3DRS_POINTSIZE_MIN ,
8040 WINED3DRS_POINTSPRITEENABLE ,
8041 WINED3DRS_RANGEFOGENABLE ,
8042 WINED3DRS_SPECULARMATERIALSOURCE ,
8043 WINED3DRS_TWEENFACTOR ,
8044 WINED3DRS_VERTEXBLEND
8047 const DWORD SavedVertexStates_T[NUM_SAVEDVERTEXSTATES_T] = {
8048 WINED3DTSS_TEXCOORDINDEX ,
8049 WINED3DTSS_TEXTURETRANSFORMFLAGS
8052 const DWORD SavedVertexStates_S[NUM_SAVEDVERTEXSTATES_S] = {
8053 WINED3DSAMP_DMAPOFFSET