2 * IWineD3DDevice implementation
4 * Copyright 2002 Lionel Ulmer
5 * Copyright 2002-2005 Jason Edmeades
6 * Copyright 2003-2004 Raphael Junqueira
7 * Copyright 2004 Christian Costa
8 * Copyright 2005 Oliver Stieber
9 * Copyright 2006 Stefan Dösinger for CodeWeavers
10 * Copyright 2006 Henri Verbeet
12 * This library is free software; you can redistribute it and/or
13 * modify it under the terms of the GNU Lesser General Public
14 * License as published by the Free Software Foundation; either
15 * version 2.1 of the License, or (at your option) any later version.
17 * This library is distributed in the hope that it will be useful,
18 * but WITHOUT ANY WARRANTY; without even the implied warranty of
19 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
20 * Lesser General Public License for more details.
22 * You should have received a copy of the GNU Lesser General Public
23 * License along with this library; if not, write to the Free Software
24 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
32 #include "wined3d_private.h"
34 WINE_DEFAULT_DEBUG_CHANNEL(d3d);
35 WINE_DECLARE_DEBUG_CHANNEL(d3d_shader);
36 #define GLINFO_LOCATION ((IWineD3DImpl *)(This->wineD3D))->gl_info
38 /* Define the default light parameters as specified by MSDN */
39 const WINED3DLIGHT WINED3D_default_light = {
41 D3DLIGHT_DIRECTIONAL, /* Type */
42 { 1.0, 1.0, 1.0, 0.0 }, /* Diffuse r,g,b,a */
43 { 0.0, 0.0, 0.0, 0.0 }, /* Specular r,g,b,a */
44 { 0.0, 0.0, 0.0, 0.0 }, /* Ambient r,g,b,a, */
45 { 0.0, 0.0, 0.0 }, /* Position x,y,z */
46 { 0.0, 0.0, 1.0 }, /* Direction x,y,z */
49 0.0, 0.0, 0.0, /* Attenuation 0,1,2 */
54 /* x11drv GDI escapes */
55 #define X11DRV_ESCAPE 6789
56 enum x11drv_escape_codes
58 X11DRV_GET_DISPLAY, /* get X11 display for a DC */
59 X11DRV_GET_DRAWABLE, /* get current drawable for a DC */
60 X11DRV_GET_FONT, /* get current X font for a DC */
63 /* retrieve the X display to use on a given DC */
64 inline static Display *get_display( HDC hdc )
67 enum x11drv_escape_codes escape = X11DRV_GET_DISPLAY;
69 if (!ExtEscape( hdc, X11DRV_ESCAPE, sizeof(escape), (LPCSTR)&escape,
70 sizeof(display), (LPSTR)&display )) display = NULL;
74 /* TODO: setup some flags in the regestry to enable, disable pbuffer support */
75 /* enable pbuffer support for offscreen textures */
76 BOOL pbuffer_support = FALSE;
77 /* allocate one pbuffer per surface */
78 BOOL pbuffer_per_surface = FALSE;
80 /* static function declarations */
81 static void WINAPI IWineD3DDeviceImpl_AddResource(IWineD3DDevice *iface, IWineD3DResource *resource);
83 static void WINAPI IWineD3DDeviceImpl_ApplyTextureUnitState(IWineD3DDevice *iface, DWORD Stage, WINED3DTEXTURESTAGESTATETYPE Type);
86 #define D3DMEMCHECK(object, ppResult) if(NULL == object) { *ppResult = NULL; WARN("Out of memory\n"); return WINED3DERR_OUTOFVIDEOMEMORY;}
88 #define D3DCREATEOBJECTINSTANCE(object, type) { \
89 object=HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(IWineD3D##type##Impl)); \
90 D3DMEMCHECK(object, pp##type); \
91 object->lpVtbl = &IWineD3D##type##_Vtbl; \
92 object->wineD3DDevice = This; \
93 object->parent = parent; \
95 *pp##type = (IWineD3D##type *) object; \
98 #define D3DCREATESHADEROBJECTINSTANCE(object, type) { \
99 object=HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(IWineD3D##type##Impl)); \
100 D3DMEMCHECK(object, pp##type); \
101 object->lpVtbl = &IWineD3D##type##_Vtbl; \
102 object->parent = parent; \
104 object->baseShader.device = (IWineD3DDevice*) This; \
105 *pp##type = (IWineD3D##type *) object; \
108 #define D3DCREATERESOURCEOBJECTINSTANCE(object, type, d3dtype, _size){ \
109 object=HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(IWineD3D##type##Impl)); \
110 D3DMEMCHECK(object, pp##type); \
111 object->lpVtbl = &IWineD3D##type##_Vtbl; \
112 object->resource.wineD3DDevice = This; \
113 object->resource.parent = parent; \
114 object->resource.resourceType = d3dtype; \
115 object->resource.ref = 1; \
116 object->resource.pool = Pool; \
117 object->resource.format = Format; \
118 object->resource.usage = Usage; \
119 object->resource.size = _size; \
120 /* Check that we have enough video ram left */ \
121 if (Pool == WINED3DPOOL_DEFAULT) { \
122 if (IWineD3DDevice_GetAvailableTextureMem(iface) <= _size) { \
123 WARN("Out of 'bogus' video memory\n"); \
124 HeapFree(GetProcessHeap(), 0, object); \
126 return WINED3DERR_OUTOFVIDEOMEMORY; \
128 globalChangeGlRam(_size); \
130 object->resource.allocatedMemory = (0 == _size ? NULL : Pool == WINED3DPOOL_DEFAULT ? NULL : HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, _size)); \
131 if (object->resource.allocatedMemory == NULL && _size != 0 && Pool != WINED3DPOOL_DEFAULT) { \
132 FIXME("Out of memory!\n"); \
133 HeapFree(GetProcessHeap(), 0, object); \
135 return WINED3DERR_OUTOFVIDEOMEMORY; \
137 *pp##type = (IWineD3D##type *) object; \
138 IWineD3DDeviceImpl_AddResource(iface, (IWineD3DResource *)object) ;\
139 TRACE("(%p) : Created resource %p\n", This, object); \
142 #define D3DINITIALIZEBASETEXTURE(_basetexture) { \
143 _basetexture.levels = Levels; \
144 _basetexture.filterType = (Usage & WINED3DUSAGE_AUTOGENMIPMAP) ? WINED3DTEXF_LINEAR : WINED3DTEXF_NONE; \
145 _basetexture.LOD = 0; \
146 _basetexture.dirty = TRUE; \
149 /**********************************************************
150 * Global variable / Constants follow
151 **********************************************************/
152 const float identity[16] = {1,0,0,0, 0,1,0,0, 0,0,1,0, 0,0,0,1}; /* When needed for comparisons */
154 /**********************************************************
155 * Utility functions follow
156 **********************************************************/
157 /* Convert the D3DLIGHT properties into equivalent gl lights */
158 static void setup_light(IWineD3DDevice *iface, LONG Index, PLIGHTINFOEL *lightInfo) {
161 float colRGBA[] = {0.0, 0.0, 0.0, 0.0};
162 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
164 /* Light settings are affected by the model view in OpenGL, the View transform in direct3d*/
165 glMatrixMode(GL_MODELVIEW);
167 glLoadMatrixf((float *)&This->stateBlock->transforms[WINED3DTS_VIEW].u.m[0][0]);
170 colRGBA[0] = lightInfo->OriginalParms.Diffuse.r;
171 colRGBA[1] = lightInfo->OriginalParms.Diffuse.g;
172 colRGBA[2] = lightInfo->OriginalParms.Diffuse.b;
173 colRGBA[3] = lightInfo->OriginalParms.Diffuse.a;
174 glLightfv(GL_LIGHT0+Index, GL_DIFFUSE, colRGBA);
175 checkGLcall("glLightfv");
178 colRGBA[0] = lightInfo->OriginalParms.Specular.r;
179 colRGBA[1] = lightInfo->OriginalParms.Specular.g;
180 colRGBA[2] = lightInfo->OriginalParms.Specular.b;
181 colRGBA[3] = lightInfo->OriginalParms.Specular.a;
182 glLightfv(GL_LIGHT0+Index, GL_SPECULAR, colRGBA);
183 checkGLcall("glLightfv");
186 colRGBA[0] = lightInfo->OriginalParms.Ambient.r;
187 colRGBA[1] = lightInfo->OriginalParms.Ambient.g;
188 colRGBA[2] = lightInfo->OriginalParms.Ambient.b;
189 colRGBA[3] = lightInfo->OriginalParms.Ambient.a;
190 glLightfv(GL_LIGHT0+Index, GL_AMBIENT, colRGBA);
191 checkGLcall("glLightfv");
193 /* Attenuation - Are these right? guessing... */
194 glLightf(GL_LIGHT0+Index, GL_CONSTANT_ATTENUATION, lightInfo->OriginalParms.Attenuation0);
195 checkGLcall("glLightf");
196 glLightf(GL_LIGHT0+Index, GL_LINEAR_ATTENUATION, lightInfo->OriginalParms.Attenuation1);
197 checkGLcall("glLightf");
199 if ((lightInfo->OriginalParms.Range *lightInfo->OriginalParms.Range) >= FLT_MIN) {
200 quad_att = 1.4/(lightInfo->OriginalParms.Range *lightInfo->OriginalParms.Range);
202 quad_att = 0; /* 0 or MAX? (0 seems to be ok) */
205 if (quad_att < lightInfo->OriginalParms.Attenuation2) quad_att = lightInfo->OriginalParms.Attenuation2;
206 glLightf(GL_LIGHT0+Index, GL_QUADRATIC_ATTENUATION, quad_att);
207 checkGLcall("glLightf");
209 switch (lightInfo->OriginalParms.Type) {
212 glLightfv(GL_LIGHT0+Index, GL_POSITION, &lightInfo->lightPosn[0]);
213 checkGLcall("glLightfv");
214 glLightf(GL_LIGHT0 + Index, GL_SPOT_CUTOFF, lightInfo->cutoff);
215 checkGLcall("glLightf");
221 glLightfv(GL_LIGHT0+Index, GL_POSITION, &lightInfo->lightPosn[0]);
222 checkGLcall("glLightfv");
224 glLightfv(GL_LIGHT0+Index, GL_SPOT_DIRECTION, &lightInfo->lightDirn[0]);
225 checkGLcall("glLightfv");
226 glLightf(GL_LIGHT0 + Index, GL_SPOT_EXPONENT, lightInfo->exponent);
227 checkGLcall("glLightf");
228 glLightf(GL_LIGHT0 + Index, GL_SPOT_CUTOFF, lightInfo->cutoff);
229 checkGLcall("glLightf");
233 case D3DLIGHT_DIRECTIONAL:
235 glLightfv(GL_LIGHT0+Index, GL_POSITION, &lightInfo->lightPosn[0]); /* Note gl uses w position of 0 for direction! */
236 checkGLcall("glLightfv");
237 glLightf(GL_LIGHT0+Index, GL_SPOT_CUTOFF, lightInfo->cutoff);
238 checkGLcall("glLightf");
239 glLightf(GL_LIGHT0+Index, GL_SPOT_EXPONENT, 0.0f);
240 checkGLcall("glLightf");
244 FIXME("Unrecognized light type %d\n", lightInfo->OriginalParms.Type);
247 /* Restore the modelview matrix */
251 /**********************************************************
252 * GLSL helper functions follow
253 **********************************************************/
255 /** Attach a GLSL pixel or vertex shader object to the shader program */
256 static void attach_glsl_shader(IWineD3DDevice *iface, IWineD3DBaseShader* shader) {
258 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
259 GLhandleARB shaderObj = ((IWineD3DBaseShaderImpl*)shader)->baseShader.prgId;
260 if (This->stateBlock->glsl_program && shaderObj != 0) {
261 TRACE_(d3d_shader)("Attaching GLSL shader object %u to program %u\n", shaderObj, This->stateBlock->glsl_program->programId);
262 GL_EXTCALL(glAttachObjectARB(This->stateBlock->glsl_program->programId, shaderObj));
263 checkGLcall("glAttachObjectARB");
267 /** Sets the GLSL program ID for the given pixel and vertex shader combination.
268 * It sets the programId on the current StateBlock (because it should be called
269 * inside of the DrawPrimitive() part of the render loop).
271 * If a program for the given combination does not exist, create one, and store
272 * the program in the list. If it creates a program, it will link the given
275 * We keep the shader programs around on a list because linking
276 * shader objects together is an expensive operation. It's much
277 * faster to loop through a list of pre-compiled & linked programs
278 * each time that the application sets a new pixel or vertex shader
279 * than it is to re-link them together at that time.
281 * The list will be deleted in IWineD3DDevice::Release().
283 void set_glsl_shader_program(IWineD3DDevice *iface) {
285 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
286 IWineD3DPixelShader *pshader = This->stateBlock->pixelShader;
287 IWineD3DVertexShader *vshader = This->stateBlock->vertexShader;
288 struct glsl_shader_prog_link *curLink = NULL;
289 struct glsl_shader_prog_link *newLink = NULL;
290 struct list *ptr = NULL;
291 GLhandleARB programId = 0;
295 ptr = list_head( &This->glsl_shader_progs );
297 /* At least one program exists - see if it matches our ps/vs combination */
298 curLink = LIST_ENTRY( ptr, struct glsl_shader_prog_link, entry );
299 if (vshader == curLink->vertexShader && pshader == curLink->pixelShader) {
300 /* Existing Program found, use it */
301 TRACE_(d3d_shader)("Found existing program (%u) for this vertex/pixel shader combination\n",
303 This->stateBlock->glsl_program = curLink;
306 /* This isn't the entry we need - try the next one */
307 ptr = list_next( &This->glsl_shader_progs, ptr );
310 /* If we get to this point, then no matching program exists, so we create one */
311 programId = GL_EXTCALL(glCreateProgramObjectARB());
312 TRACE_(d3d_shader)("Created new GLSL shader program %u\n", programId);
314 /* Allocate a new link for the list of programs */
315 newLink = HeapAlloc(GetProcessHeap(), 0, sizeof(struct glsl_shader_prog_link));
316 newLink->programId = programId;
317 This->stateBlock->glsl_program = newLink;
319 /* Attach GLSL vshader */
320 if (NULL != vshader && wined3d_settings.vs_selected_mode == SHADER_GLSL) {
322 int max_attribs = 16; /* TODO: Will this always be the case? It is at the moment... */
325 TRACE("Attaching vertex shader to GLSL program\n");
326 attach_glsl_shader(iface, (IWineD3DBaseShader*)vshader);
328 /* Bind vertex attributes to a corresponding index number to match
329 * the same index numbers as ARB_vertex_programs (makes loading
330 * vertex attributes simpler). With this method, we can use the
331 * exact same code to load the attributes later for both ARB and
334 * We have to do this here because we need to know the Program ID
335 * in order to make the bindings work, and it has to be done prior
336 * to linking the GLSL program. */
337 for (i = 0; i < max_attribs; ++i) {
338 snprintf(tmp_name, sizeof(tmp_name), "attrib%i", i);
339 GL_EXTCALL(glBindAttribLocationARB(programId, i, tmp_name));
341 checkGLcall("glBindAttribLocationARB");
342 newLink->vertexShader = vshader;
345 /* Attach GLSL pshader */
346 if (NULL != pshader && wined3d_settings.ps_selected_mode == SHADER_GLSL) {
347 TRACE("Attaching pixel shader to GLSL program\n");
348 attach_glsl_shader(iface, (IWineD3DBaseShader*)pshader);
349 newLink->pixelShader = pshader;
352 /* Link the program */
353 TRACE_(d3d_shader)("Linking GLSL shader program %u\n", programId);
354 GL_EXTCALL(glLinkProgramARB(programId));
355 print_glsl_info_log(&GLINFO_LOCATION, programId);
356 list_add_head( &This->glsl_shader_progs, &newLink->entry);
358 newLink->vuniformF_locations = HeapAlloc(GetProcessHeap(), 0, sizeof(GLhandleARB) * GL_LIMITS(vshader_constantsF));
359 for (i = 0; i < GL_LIMITS(vshader_constantsF); ++i) {
360 snprintf(glsl_name, sizeof(glsl_name), "VC[%i]", i);
361 newLink->vuniformF_locations[i] = GL_EXTCALL(glGetUniformLocationARB(programId, glsl_name));
363 newLink->puniformF_locations = HeapAlloc(GetProcessHeap(), 0, sizeof(GLhandleARB) * GL_LIMITS(pshader_constantsF));
364 for (i = 0; i < GL_LIMITS(pshader_constantsF); ++i) {
365 snprintf(glsl_name, sizeof(glsl_name), "PC[%i]", i);
366 newLink->puniformF_locations[i] = GL_EXTCALL(glGetUniformLocationARB(programId, glsl_name));
372 /** Detach the GLSL pixel or vertex shader object from the shader program */
373 static void detach_glsl_shader(IWineD3DDevice *iface, GLhandleARB shaderObj, GLhandleARB programId) {
375 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
377 if (shaderObj != 0 && programId != 0) {
378 TRACE_(d3d_shader)("Detaching GLSL shader object %u from program %u\n", shaderObj, programId);
379 GL_EXTCALL(glDetachObjectARB(programId, shaderObj));
380 checkGLcall("glDetachObjectARB");
384 /** Delete a GLSL shader program */
385 static void delete_glsl_shader_program(IWineD3DDevice *iface, GLhandleARB obj) {
387 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
390 TRACE_(d3d_shader)("Deleting GLSL shader program %u\n", obj);
391 GL_EXTCALL(glDeleteObjectARB(obj));
392 checkGLcall("glDeleteObjectARB");
396 /** Delete the list of linked programs this shader is associated with.
397 * Also at this point, check to see if there are any objects left attached
398 * to each GLSL program. If not, delete the GLSL program object.
399 * This will be run when a device is released. */
400 static void delete_glsl_shader_list(IWineD3DDevice* iface) {
402 struct list *ptr = NULL;
403 struct glsl_shader_prog_link *curLink = NULL;
404 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
408 GLhandleARB objList[2]; /* There should never be more than 2 objects attached
409 (one pixel shader and one vertex shader at most) */
411 ptr = list_head( &This->glsl_shader_progs );
413 /* First, get the current item,
414 * save the link to the next pointer,
415 * detach and delete shader objects,
416 * then de-allocate the list item's memory */
417 curLink = LIST_ENTRY( ptr, struct glsl_shader_prog_link, entry );
418 ptr = list_next( &This->glsl_shader_progs, ptr );
420 /* See if this object is still attached to the program - it may have been detached already */
421 GL_EXTCALL(glGetAttachedObjectsARB(curLink->programId, 2, &numAttached, objList));
422 TRACE_(d3d_shader)("%i GLSL objects are currently attached to program %u\n", numAttached, curLink->programId);
423 for (i = 0; i < numAttached; i++) {
424 detach_glsl_shader(iface, objList[i], curLink->programId);
427 delete_glsl_shader_program(iface, curLink->programId);
429 /* Free the uniform locations */
430 HeapFree(GetProcessHeap(), 0, curLink->vuniformF_locations);
431 HeapFree(GetProcessHeap(), 0, curLink->puniformF_locations);
433 /* Free the memory for this list item */
434 HeapFree(GetProcessHeap(), 0, curLink);
439 /* Apply the current values to the specified texture stage */
440 static void WINAPI IWineD3DDeviceImpl_SetupTextureStates(IWineD3DDevice *iface, DWORD Sampler, DWORD texture_idx, DWORD Flags) {
441 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
449 /* In addition, IDirect3DDevice9::SetSamplerState will now be used for filtering, tiling,
450 clamping, MIPLOD, etc. This will work for up to 16 samplers.
453 if (Sampler >= GL_LIMITS(sampler_stages)) {
454 FIXME("Trying to set the state of more samplers %ld than are supported %d by this openGL implementation\n", Sampler, GL_LIMITS(sampler_stages));
457 VTRACE(("Activating appropriate texture state %ld\n", Sampler));
458 if (GL_SUPPORT(ARB_MULTITEXTURE)) {
460 GL_EXTCALL(glActiveTextureARB(GL_TEXTURE0_ARB + texture_idx));
461 checkGLcall("glActiveTextureARB");
463 /* Could we use bindTexture and then apply the states instead of GLACTIVETEXTURE */
464 } else if (Sampler > 0) {
465 FIXME("Program using multiple concurrent textures which this opengl implementation doesn't support\n");
469 /* TODO: change this to a lookup table
470 LOOKUP_TEXTURE_STATES lists all texture states that should be applied.
471 LOOKUP_CONTEXT_SATES list all context applicable states that can be applied
472 etc.... it's a lot cleaner, quicker and possibly easier to maintain than running a switch and setting a skip flag...
473 especially when there are a number of groups of states. */
475 TRACE("-----------------------> Updating the texture at Sampler %ld to have new texture state information\n", Sampler);
477 /* 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 */
478 #define APPLY_STATE(_state) IWineD3DDeviceImpl_ApplyTextureUnitState(iface, Sampler, _state)
479 /* these are the only two supported states that need to be applied */
480 APPLY_STATE(WINED3DTSS_TEXCOORDINDEX);
481 APPLY_STATE(WINED3DTSS_TEXTURETRANSFORMFLAGS);
482 #if 0 /* not supported at the moment */
483 APPLY_STATE(WINED3DTSS_BUMPENVMAT00);
484 APPLY_STATE(WINED3DTSS_BUMPENVMAT01);
485 APPLY_STATE(WINED3DTSS_BUMPENVMAT10);
486 APPLY_STATE(WINED3DTSS_BUMPENVMAT11);
487 APPLY_STATE(WINED3DTSS_BUMPENVLSCALE);
488 APPLY_STATE(WINED3DTSS_BUMPENVLOFFSET);
489 APPLY_STATE(WINED3DTSS_RESULTARG);
490 APPLY_STATE(WINED3DTSS_CONSTANT);
492 /* a quick sanity check in case someone forgot to update this function */
493 if (WINED3D_HIGHEST_TEXTURE_STATE > WINED3DTSS_CONSTANT) {
494 FIXME("(%p) : There are more texture states than expected, update device.c to match\n", This);
498 /* apply any sampler states that always need applying */
499 if (GL_SUPPORT(EXT_TEXTURE_LOD_BIAS)) {
500 tmpvalue.d = This->stateBlock->samplerState[Sampler][WINED3DSAMP_MIPMAPLODBIAS];
501 glTexEnvf(GL_TEXTURE_FILTER_CONTROL_EXT,
502 GL_TEXTURE_LOD_BIAS_EXT,
504 checkGLcall("glTexEnvi GL_TEXTURE_LOD_BIAS_EXT ...");
507 D3DCOLORTOGLFLOAT4(This->stateBlock->renderState[WINED3DRS_TEXTUREFACTOR], col);
508 glTexEnvfv(GL_TEXTURE_ENV, GL_TEXTURE_ENV_COLOR, &col[0]);
509 checkGLcall("glTexEnvfv(GL_TEXTURE_ENV, GL_TEXTURE_ENV_COLOR, color);");
511 /* TODO: NV_POINT_SPRITE */
512 if (GL_SUPPORT(ARB_POINT_SPRITE)) {
513 if (This->stateBlock->renderState[WINED3DRS_POINTSPRITEENABLE]) {
514 /* Doesn't work with GL_POINT_SMOOTH on on my ATI 9600, but then ATI drivers are buggered! */
515 glDisable(GL_POINT_SMOOTH);
517 /* Centre the texture on the vertex */
518 VTRACE(("glTexEnvf( GL_POINT_SPRITE_ARB, GL_COORD_REPLACE_ARB, GL_TRUE)\n"));
519 glTexEnvf( GL_POINT_SPRITE_ARB, GL_COORD_REPLACE_ARB, GL_TRUE);
521 VTRACE(("glTexEnvf( GL_POINT_SPRITE_ARB, GL_COORD_REPLACE_ARB, GL_TRUE)\n"));
522 glTexEnvf( GL_POINT_SPRITE_ARB, GL_COORD_REPLACE_ARB, GL_TRUE);
523 checkGLcall("glTexEnvf(...)");
524 VTRACE(("glEnable( GL_POINT_SPRITE_ARB )\n"));
525 glEnable( GL_POINT_SPRITE_ARB );
526 checkGLcall("glEnable(...)");
528 VTRACE(("glDisable( GL_POINT_SPRITE_ARB )\n"));
529 glDisable( GL_POINT_SPRITE_ARB );
530 checkGLcall("glEnable(...)");
534 TRACE("-----------------------> Updated the texture at Sampler %ld to have new texture state information\n", Sampler);
537 /**********************************************************
538 * IUnknown parts follows
539 **********************************************************/
541 static HRESULT WINAPI IWineD3DDeviceImpl_QueryInterface(IWineD3DDevice *iface,REFIID riid,LPVOID *ppobj)
543 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
545 TRACE("(%p)->(%s,%p)\n",This,debugstr_guid(riid),ppobj);
546 if (IsEqualGUID(riid, &IID_IUnknown)
547 || IsEqualGUID(riid, &IID_IWineD3DBase)
548 || IsEqualGUID(riid, &IID_IWineD3DDevice)) {
549 IUnknown_AddRef(iface);
554 return E_NOINTERFACE;
557 static ULONG WINAPI IWineD3DDeviceImpl_AddRef(IWineD3DDevice *iface) {
558 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
559 ULONG refCount = InterlockedIncrement(&This->ref);
561 TRACE("(%p) : AddRef increasing from %ld\n", This, refCount - 1);
565 static ULONG WINAPI IWineD3DDeviceImpl_Release(IWineD3DDevice *iface) {
566 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
567 ULONG refCount = InterlockedDecrement(&This->ref);
569 TRACE("(%p) : Releasing from %ld\n", This, refCount + 1);
572 /* TODO: Clean up all the surfaces and textures! */
573 /* NOTE: You must release the parent if the object was created via a callback
574 ** ***************************/
576 /* Delete any GLSL shader programs that may exist */
577 if (wined3d_settings.vs_selected_mode == SHADER_GLSL ||
578 wined3d_settings.ps_selected_mode == SHADER_GLSL)
579 delete_glsl_shader_list(iface);
581 /* Release the update stateblock */
582 if(IWineD3DStateBlock_Release((IWineD3DStateBlock *)This->updateStateBlock) > 0){
583 if(This->updateStateBlock != This->stateBlock)
584 FIXME("(%p) Something's still holding the Update stateblock\n",This);
586 This->updateStateBlock = NULL;
587 { /* because were not doing proper internal refcounts releasing the primary state block
588 causes recursion with the extra checks in ResourceReleased, to avoid this we have
589 to set this->stateBlock = NULL; first */
590 IWineD3DStateBlock *stateBlock = (IWineD3DStateBlock *)This->stateBlock;
591 This->stateBlock = NULL;
593 /* Release the stateblock */
594 if(IWineD3DStateBlock_Release(stateBlock) > 0){
595 FIXME("(%p) Something's still holding the Update stateblock\n",This);
599 if (This->resources != NULL ) {
600 FIXME("(%p) Device released with resources still bound, acceptable but unexpected\n", This);
601 dumpResources(This->resources);
605 IWineD3D_Release(This->wineD3D);
606 This->wineD3D = NULL;
607 HeapFree(GetProcessHeap(), 0, This);
608 TRACE("Freed device %p\n", This);
614 /**********************************************************
615 * IWineD3DDevice implementation follows
616 **********************************************************/
617 static HRESULT WINAPI IWineD3DDeviceImpl_GetParent(IWineD3DDevice *iface, IUnknown **pParent) {
618 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
619 *pParent = This->parent;
620 IUnknown_AddRef(This->parent);
624 static void CreateVBO(IWineD3DVertexBufferImpl *object) {
625 IWineD3DDeviceImpl *This = object->resource.wineD3DDevice; /* Needed for GL_EXTCALL */
626 GLenum error, glUsage;
627 DWORD vboUsage = object->resource.usage;
628 if(object->Flags & VBFLAG_VBOCREATEFAIL) {
629 WARN("Creating a vbo failed once, not trying again\n");
633 TRACE("Creating an OpenGL vertex buffer object for IWineD3DVertexBuffer %p Usage(%s)\n", object, debug_d3dusage(vboUsage));
636 /* Make sure that the gl error is cleared. Do not use checkGLcall
637 * here because checkGLcall just prints a fixme and continues. However,
638 * if an error during VBO creation occurs we can fall back to non-vbo operation
639 * with full functionality(but performance loss)
641 while(glGetError() != GL_NO_ERROR);
643 /* Basically the FVF parameter passed to CreateVertexBuffer is no good
644 * It is the FVF set with IWineD3DDevice::SetFVF or the Vertex Declaration set with
645 * IWineD3DDevice::SetVertexDeclaration that decides how the vertices in the buffer
646 * look like. This means that on each DrawPrimitive call the vertex buffer has to be verified
647 * to check if the rhw and color values are in the correct format.
650 GL_EXTCALL(glGenBuffersARB(1, &object->vbo));
651 error = glGetError();
652 if(object->vbo == 0 || error != GL_NO_ERROR) {
653 WARN("Failed to create a VBO with error %d\n", error);
657 GL_EXTCALL(glBindBufferARB(GL_ARRAY_BUFFER_ARB, object->vbo));
658 error = glGetError();
659 if(error != GL_NO_ERROR) {
660 WARN("Failed to bind the VBO, error %d\n", error);
664 /* Transformed vertices are horribly inflexible. If the app specifies an
665 * vertex buffer with transformed vertices in default pool without DYNAMIC
666 * usage assume DYNAMIC usage and print a warning. The app will have to update
667 * the vertices regularily for them to be useful
669 if(((object->fvf & D3DFVF_POSITION_MASK) == D3DFVF_XYZRHW) &&
670 !(vboUsage & WINED3DUSAGE_DYNAMIC)) {
671 WARN("Application creates a vertex buffer holding transformed vertices which doesn't specify dynamic usage\n");
672 vboUsage |= WINED3DUSAGE_DYNAMIC;
675 /* Don't use static, because dx apps tend to update the buffer
676 * quite often even if they specify 0 usage
678 switch(vboUsage & (D3DUSAGE_WRITEONLY | D3DUSAGE_DYNAMIC) ) {
679 case D3DUSAGE_WRITEONLY | D3DUSAGE_DYNAMIC:
680 TRACE("Gl usage = GL_STREAM_DRAW\n");
681 glUsage = GL_STREAM_DRAW_ARB;
683 case D3DUSAGE_WRITEONLY:
684 TRACE("Gl usage = GL_DYNAMIC_DRAW\n");
685 glUsage = GL_DYNAMIC_DRAW_ARB;
687 case D3DUSAGE_DYNAMIC:
688 TRACE("Gl usage = GL_STREAM_COPY\n");
689 glUsage = GL_STREAM_COPY_ARB;
692 TRACE("Gl usage = GL_DYNAMIC_COPY\n");
693 glUsage = GL_DYNAMIC_COPY_ARB;
697 /* Reserve memory for the buffer. The amount of data won't change
698 * so we are safe with calling glBufferData once with a NULL ptr and
699 * calling glBufferSubData on updates
701 GL_EXTCALL(glBufferDataARB(GL_ARRAY_BUFFER_ARB, object->resource.size, NULL, glUsage));
702 error = glGetError();
703 if(error != GL_NO_ERROR) {
704 WARN("glBufferDataARB failed with error %d\n", error);
712 /* Clean up all vbo init, but continue because we can work without a vbo :-) */
713 FIXME("Failed to create a vertex buffer object. Continuing, but performance issues can occur\n");
714 if(object->vbo) GL_EXTCALL(glDeleteBuffersARB(1, &object->vbo));
716 object->Flags |= VBFLAG_VBOCREATEFAIL;
721 static HRESULT WINAPI IWineD3DDeviceImpl_CreateVertexBuffer(IWineD3DDevice *iface, UINT Size, DWORD Usage,
722 DWORD FVF, WINED3DPOOL Pool, IWineD3DVertexBuffer** ppVertexBuffer, HANDLE *sharedHandle,
724 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
725 IWineD3DVertexBufferImpl *object;
726 WINED3DFORMAT Format = WINED3DFMT_VERTEXDATA; /* Dummy format for now */
727 int dxVersion = ( (IWineD3DImpl *) This->wineD3D)->dxVersion;
729 D3DCREATERESOURCEOBJECTINSTANCE(object, VertexBuffer, WINED3DRTYPE_VERTEXBUFFER, Size)
731 TRACE("(%p) : Size=%d, Usage=%ld, FVF=%lx, Pool=%d - Memory@%p, Iface@%p\n", This, Size, Usage, FVF, Pool, object->resource.allocatedMemory, object);
732 *ppVertexBuffer = (IWineD3DVertexBuffer *)object;
734 if(Size == 0) return WINED3DERR_INVALIDCALL;
736 if (Pool == WINED3DPOOL_DEFAULT ) { /* Allocate some system memory for now */
737 object->resource.allocatedMemory = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, object->resource.size);
741 /* Observations show that drawStridedSlow is faster on dynamic VBs than converting +
742 * drawStridedFast (half-life 2).
744 * Basically converting the vertices in the buffer is quite expensive, and observations
745 * show that drawStridedSlow is faster than converting + uploading + drawStridedFast.
746 * Therefore do not create a VBO for WINED3DUSAGE_DYNAMIC buffers.
748 * Direct3D7 has another problem: Its vertexbuffer api doesn't offer a way to specify
749 * the range of vertices being locked, so each lock will require the whole buffer to be transformed.
750 * Moreover geometry data in dx7 is quite simple, so drawStridedSlow isn't a big hit. A plus
751 * is that the vertex buffers fvf can be trusted in dx7. So only create non-converted vbos for
753 * There is a IDirect3DVertexBuffer7::Optimize call after which the buffer can't be locked any
754 * more. In this call we can convert dx7 buffers too.
756 conv = ((FVF & D3DFVF_POSITION_MASK) == D3DFVF_XYZRHW ) || (FVF & (D3DFVF_DIFFUSE | D3DFVF_SPECULAR));
757 if( GL_SUPPORT(ARB_VERTEX_BUFFER_OBJECT) && Pool != WINED3DPOOL_SYSTEMMEM && !(Usage & WINED3DUSAGE_DYNAMIC) &&
758 (dxVersion > 7 || !conv) ) {
761 /* DX7 buffers can be locked directly into the VBO (no conversion, see above */
762 if(dxVersion == 7 && object->vbo) {
763 HeapFree(GetProcessHeap(), 0, object->resource.allocatedMemory);
764 object->resource.allocatedMemory = NULL;
771 static HRESULT WINAPI IWineD3DDeviceImpl_CreateIndexBuffer(IWineD3DDevice *iface, UINT Length, DWORD Usage,
772 WINED3DFORMAT Format, WINED3DPOOL Pool, IWineD3DIndexBuffer** ppIndexBuffer,
773 HANDLE *sharedHandle, IUnknown *parent) {
774 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
775 IWineD3DIndexBufferImpl *object;
776 TRACE("(%p) Creating index buffer\n", This);
778 /* Allocate the storage for the device */
779 D3DCREATERESOURCEOBJECTINSTANCE(object,IndexBuffer,WINED3DRTYPE_INDEXBUFFER, Length)
782 if (Pool == WINED3DPOOL_DEFAULT ) { /* Allocate some system memory for now */
783 object->resource.allocatedMemory = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,object->resource.size);
786 TRACE("(%p) : Len=%d, Use=%lx, Format=(%u,%s), Pool=%d - Memory@%p, Iface@%p\n", This, Length, Usage, Format,
787 debug_d3dformat(Format), Pool, object, object->resource.allocatedMemory);
788 *ppIndexBuffer = (IWineD3DIndexBuffer *) object;
793 static HRESULT WINAPI IWineD3DDeviceImpl_CreateStateBlock(IWineD3DDevice* iface, WINED3DSTATEBLOCKTYPE Type, IWineD3DStateBlock** ppStateBlock, IUnknown *parent) {
795 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
796 IWineD3DStateBlockImpl *object;
800 D3DCREATEOBJECTINSTANCE(object, StateBlock)
801 object->blockType = Type;
803 /* Special case - Used during initialization to produce a placeholder stateblock
804 so other functions called can update a state block */
805 if (Type == WINED3DSBT_INIT) {
806 /* Don't bother increasing the reference count otherwise a device will never
807 be freed due to circular dependencies */
811 temp_result = allocate_shader_constants(object);
812 if (WINED3D_OK != temp_result)
815 /* Otherwise, might as well set the whole state block to the appropriate values */
816 if (This->stateBlock != NULL)
817 stateblock_copy((IWineD3DStateBlock*) object, (IWineD3DStateBlock*) This->stateBlock);
819 memset(object->streamFreq, 1, sizeof(object->streamFreq));
821 /* Reset the ref and type after kludging it */
822 object->wineD3DDevice = This;
824 object->blockType = Type;
826 TRACE("Updating changed flags appropriate for type %d\n", Type);
828 if (Type == WINED3DSBT_ALL) {
830 TRACE("ALL => Pretend everything has changed\n");
831 stateblock_savedstates_set((IWineD3DStateBlock*) object, &object->changed, TRUE);
833 } else if (Type == WINED3DSBT_PIXELSTATE) {
835 TRACE("PIXELSTATE => Pretend all pixel shates have changed\n");
836 stateblock_savedstates_set((IWineD3DStateBlock*) object, &object->changed, FALSE);
838 object->changed.pixelShader = TRUE;
840 /* Pixel Shader Constants */
841 for (i = 0; i < GL_LIMITS(pshader_constantsF); ++i)
842 object->changed.pixelShaderConstantsF[i] = TRUE;
843 for (i = 0; i < MAX_CONST_B; ++i)
844 object->changed.pixelShaderConstantsB[i] = TRUE;
845 for (i = 0; i < MAX_CONST_I; ++i)
846 object->changed.pixelShaderConstantsI[i] = TRUE;
848 for (i = 0; i < NUM_SAVEDPIXELSTATES_R; i++) {
849 object->changed.renderState[SavedPixelStates_R[i]] = TRUE;
851 for (j = 0; j < GL_LIMITS(texture_stages); j++) {
852 for (i = 0; i < NUM_SAVEDPIXELSTATES_T; i++) {
853 object->changed.textureState[j][SavedPixelStates_T[i]] = TRUE;
856 for (j = 0 ; j < 16; j++) {
857 for (i =0; i < NUM_SAVEDPIXELSTATES_S;i++) {
859 object->changed.samplerState[j][SavedPixelStates_S[i]] = TRUE;
863 } else if (Type == WINED3DSBT_VERTEXSTATE) {
865 TRACE("VERTEXSTATE => Pretend all vertex shates have changed\n");
866 stateblock_savedstates_set((IWineD3DStateBlock*) object, &object->changed, FALSE);
868 object->changed.vertexShader = TRUE;
870 /* Vertex Shader Constants */
871 for (i = 0; i < GL_LIMITS(vshader_constantsF); ++i)
872 object->changed.vertexShaderConstantsF[i] = TRUE;
873 for (i = 0; i < MAX_CONST_B; ++i)
874 object->changed.vertexShaderConstantsB[i] = TRUE;
875 for (i = 0; i < MAX_CONST_I; ++i)
876 object->changed.vertexShaderConstantsI[i] = TRUE;
878 for (i = 0; i < NUM_SAVEDVERTEXSTATES_R; i++) {
879 object->changed.renderState[SavedVertexStates_R[i]] = TRUE;
881 for (j = 0; j < GL_LIMITS(texture_stages); j++) {
882 for (i = 0; i < NUM_SAVEDVERTEXSTATES_T; i++) {
883 object->changed.textureState[j][SavedVertexStates_T[i]] = TRUE;
886 for (j = 0 ; j < 16; j++){
887 for (i =0; i < NUM_SAVEDVERTEXSTATES_S;i++) {
888 object->changed.samplerState[j][SavedVertexStates_S[i]] = TRUE;
892 /* Duplicate light chain */
894 PLIGHTINFOEL *src = NULL;
895 PLIGHTINFOEL *dst = NULL;
896 PLIGHTINFOEL *newEl = NULL;
897 src = This->stateBlock->lights;
898 object->lights = NULL;
902 newEl = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(PLIGHTINFOEL));
903 if (newEl == NULL) return WINED3DERR_OUTOFVIDEOMEMORY;
904 memcpy(newEl, src, sizeof(PLIGHTINFOEL));
906 newEl->changed = TRUE;
907 newEl->enabledChanged = TRUE;
909 object->lights = newEl;
920 FIXME("Unrecognized state block type %d\n", Type);
923 TRACE("(%p) returning token (ptr to stateblock) of %p\n", This, object);
928 /* ************************************
930 [in] Render targets are not lockable unless the application specifies TRUE for Lockable. Note that lockable render targets reduce performance on some graphics hardware.
933 [in] Set this flag to TRUE to enable z-buffer discarding, and FALSE otherwise.
935 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.
937 ******************************** */
939 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) {
940 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
941 IWineD3DSurfaceImpl *object; /*NOTE: impl ref allowed since this is a create function */
942 unsigned int pow2Width, pow2Height;
943 unsigned int Size = 1;
944 const PixelFormatDesc *tableEntry = getFormatDescEntry(Format);
945 TRACE("(%p) Create surface\n",This);
947 /** FIXME: Check ranges on the inputs are valid
950 * [in] Quality level. The valid range is between zero and one less than the level
951 * returned by pQualityLevels used by IDirect3D9::CheckDeviceMultiSampleType.
952 * Passing a larger value returns the error WINED3DERR_INVALIDCALL. The MultisampleQuality
953 * values of paired render targets, depth stencil surfaces, and the MultiSample type
955 *******************************/
960 * [in] Set this flag to TRUE to enable z-buffer discarding, and FALSE otherwise.
962 * If this flag is set, the contents of the depth stencil buffer will be
963 * invalid after calling either IDirect3DDevice9::Present or * IDirect3DDevice9::SetDepthStencilSurface
964 * with a different depth surface.
966 *This flag has the same behavior as the constant, D3DPRESENTFLAG_DISCARD_DEPTHSTENCIL, in D3DPRESENTFLAG.
967 ***************************/
969 if(MultisampleQuality < 0) {
970 FIXME("Invalid multisample level %ld\n", MultisampleQuality);
971 return WINED3DERR_INVALIDCALL; /* TODO: Check that this is the case! */
974 if(MultisampleQuality > 0) {
975 FIXME("MultisampleQuality set to %ld, substituting 0\n", MultisampleQuality);
976 MultisampleQuality=0;
979 /** FIXME: Check that the format is supported
981 *******************************/
983 /* Non-power2 support */
984 if (wined3d_settings.nonpower2_mode == NP2_NATIVE) {
988 /* Find the nearest pow2 match */
989 pow2Width = pow2Height = 1;
990 while (pow2Width < Width) pow2Width <<= 1;
991 while (pow2Height < Height) pow2Height <<= 1;
994 if (pow2Width > Width || pow2Height > Height) {
995 /** TODO: add support for non power two compressed textures (OpenGL 2 provices support for * non-power-two textures gratis) **/
996 if (Format == WINED3DFMT_DXT1 || Format == WINED3DFMT_DXT2 || Format == WINED3DFMT_DXT3
997 || Format == WINED3DFMT_DXT4 || Format == WINED3DFMT_DXT5) {
998 FIXME("(%p) Compressed non-power-two textures are not supported w(%d) h(%d)\n",
999 This, Width, Height);
1000 return WINED3DERR_NOTAVAILABLE;
1004 /** DXTn mipmaps use the same number of 'levels' down to eg. 8x1, but since
1005 * it is based around 4x4 pixel blocks it requires padding, so allocate enough
1007 *********************************/
1008 if (WINED3DFMT_UNKNOWN == Format) {
1010 } else if (Format == WINED3DFMT_DXT1) {
1011 /* DXT1 is half byte per pixel */
1012 Size = ((max(pow2Width,4) * tableEntry->bpp) * max(pow2Height,4)) >> 1;
1014 } else if (Format == WINED3DFMT_DXT2 || Format == WINED3DFMT_DXT3 ||
1015 Format == WINED3DFMT_DXT4 || Format == WINED3DFMT_DXT5) {
1016 Size = ((max(pow2Width,4) * tableEntry->bpp) * max(pow2Height,4));
1018 /* The pitch is a multiple of 4 bytes */
1019 Size = ((pow2Width * tableEntry->bpp) + 3) & ~3;
1023 /** Create and initialise the surface resource **/
1024 D3DCREATERESOURCEOBJECTINSTANCE(object,Surface,WINED3DRTYPE_SURFACE, Size)
1025 /* "Standalone" surface */
1026 IWineD3DSurface_SetContainer((IWineD3DSurface *)object, NULL);
1028 object->currentDesc.Width = Width;
1029 object->currentDesc.Height = Height;
1030 object->currentDesc.MultiSampleType = MultiSample;
1031 object->currentDesc.MultiSampleQuality = MultisampleQuality;
1033 /* Setup some glformat defaults */
1034 object->glDescription.glFormat = tableEntry->glFormat;
1035 object->glDescription.glFormatInternal = tableEntry->glInternal;
1036 object->glDescription.glType = tableEntry->glType;
1038 object->glDescription.textureName = 0;
1039 object->glDescription.level = Level;
1040 object->glDescription.target = GL_TEXTURE_2D;
1043 object->pow2Width = pow2Width;
1044 object->pow2Height = pow2Height;
1047 object->Flags = 0; /* We start without flags set */
1048 object->Flags |= (pow2Width != Width || pow2Height != Height) ? SFLAG_NONPOW2 : 0;
1049 object->Flags |= Discard ? SFLAG_DISCARD : 0;
1050 object->Flags |= (WINED3DFMT_D16_LOCKABLE == Format) ? SFLAG_LOCKABLE : 0;
1051 object->Flags |= Lockable ? SFLAG_LOCKABLE : 0;
1054 if (WINED3DFMT_UNKNOWN != Format) {
1055 object->bytesPerPixel = tableEntry->bpp;
1056 object->pow2Size = (pow2Width * object->bytesPerPixel) * pow2Height;
1058 object->bytesPerPixel = 0;
1059 object->pow2Size = 0;
1062 /** TODO: change this into a texture transform matrix so that it's processed in hardware **/
1064 TRACE("Pool %d %d %d %d",Pool, WINED3DPOOL_DEFAULT, WINED3DPOOL_MANAGED, WINED3DPOOL_SYSTEMMEM);
1066 /** Quick lockable sanity check TODO: remove this after surfaces, usage and locablility have been debugged properly
1067 * this function is too deap to need to care about things like this.
1068 * Levels need to be checked too, and possibly Type wince they all affect what can be done.
1069 * ****************************************/
1071 case WINED3DPOOL_SCRATCH:
1073 FIXME("Create suface called with a pool of SCRATCH and a Lockable of FALSE \
1074 which are mutually exclusive, setting lockable to true\n");
1077 case WINED3DPOOL_SYSTEMMEM:
1078 if(!Lockable) FIXME("Create surface called with a pool of SYSTEMMEM and a Lockable of FALSE, \
1079 this is acceptable but unexpected (I can't know how the surface can be usable!)\n");
1080 case WINED3DPOOL_MANAGED:
1081 if(Usage == WINED3DUSAGE_DYNAMIC) FIXME("Create surface called with a pool of MANAGED and a \
1082 Usage of DYNAMIC which are mutually exclusive, not doing \
1083 anything just telling you.\n");
1085 case WINED3DPOOL_DEFAULT: /*TODO: Create offscreen plain can cause this check to fail..., find out if it should */
1086 if(!(Usage & WINED3DUSAGE_DYNAMIC) && !(Usage & WINED3DUSAGE_RENDERTARGET)
1087 && !(Usage && WINED3DUSAGE_DEPTHSTENCIL ) && Lockable)
1088 WARN("Creating a surface with a POOL of DEFAULT with Lockable true, that doesn't specify DYNAMIC usage.\n");
1091 FIXME("(%p) Unknown pool %d\n", This, Pool);
1095 if (Usage & WINED3DUSAGE_RENDERTARGET && Pool != WINED3DPOOL_DEFAULT) {
1096 FIXME("Trying to create a render target that isn't in the default pool\n");
1099 /* mark the texture as dirty so that it get's loaded first time around*/
1100 IWineD3DSurface_AddDirtyRect(*ppSurface, NULL);
1101 TRACE("(%p) : w(%d) h(%d) fmt(%d,%s) lockable(%d) surf@%p, surfmem@%p, %d bytes\n",
1102 This, Width, Height, Format, debug_d3dformat(Format),
1103 (WINED3DFMT_D16_LOCKABLE == Format), *ppSurface, object->resource.allocatedMemory, object->resource.size);
1105 /* Store the DirectDraw primary surface. This is the first rendertarget surface created */
1106 if( (Usage & WINED3DUSAGE_RENDERTARGET) && (!This->ddraw_primary) )
1107 This->ddraw_primary = (IWineD3DSurface *) object;
1109 /* Look at the implementation and set the correct Vtable */
1111 case SURFACE_OPENGL:
1112 /* Nothing to do, it's set already */
1116 object->lpVtbl = &IWineGDISurface_Vtbl;
1120 /* To be sure to catch this */
1121 ERR("Unknown requested surface implementation %d!\n", Impl);
1122 IWineD3DSurface_Release((IWineD3DSurface *) object);
1123 return WINED3DERR_INVALIDCALL;
1126 /* Call the private setup routine */
1127 return IWineD3DSurface_PrivateSetup( (IWineD3DSurface *) object );
1131 static HRESULT WINAPI IWineD3DDeviceImpl_CreateTexture(IWineD3DDevice *iface, UINT Width, UINT Height, UINT Levels,
1132 DWORD Usage, WINED3DFORMAT Format, WINED3DPOOL Pool,
1133 IWineD3DTexture** ppTexture, HANDLE* pSharedHandle, IUnknown *parent,
1134 D3DCB_CREATESURFACEFN D3DCB_CreateSurface) {
1136 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
1137 IWineD3DTextureImpl *object;
1142 unsigned int pow2Width;
1143 unsigned int pow2Height;
1146 TRACE("(%p) : Width %d, Height %d, Levels %d, Usage %#lx\n", This, Width, Height, Levels, Usage);
1147 TRACE("Format %#x (%s), Pool %#x, ppTexture %p, pSharedHandle %p, parent %p\n",
1148 Format, debug_d3dformat(Format), Pool, ppTexture, pSharedHandle, parent);
1150 /* TODO: It should only be possible to create textures for formats
1151 that are reported as supported */
1152 if (WINED3DFMT_UNKNOWN >= Format) {
1153 WARN("(%p) : Texture cannot be created with a format of D3DFMT_UNKNOWN\n", This);
1154 return WINED3DERR_INVALIDCALL;
1157 D3DCREATERESOURCEOBJECTINSTANCE(object, Texture, WINED3DRTYPE_TEXTURE, 0);
1158 D3DINITIALIZEBASETEXTURE(object->baseTexture);
1159 object->width = Width;
1160 object->height = Height;
1162 /** Non-power2 support **/
1163 if (wined3d_settings.nonpower2_mode == NP2_NATIVE) {
1165 pow2Height = Height;
1167 /* Find the nearest pow2 match */
1168 pow2Width = pow2Height = 1;
1169 while (pow2Width < Width) pow2Width <<= 1;
1170 while (pow2Height < Height) pow2Height <<= 1;
1173 /** FIXME: add support for real non-power-two if it's provided by the video card **/
1174 /* Precalculated scaling for 'faked' non power of two texture coords */
1175 object->pow2scalingFactorX = (((float)Width) / ((float)pow2Width));
1176 object->pow2scalingFactorY = (((float)Height) / ((float)pow2Height));
1177 TRACE(" xf(%f) yf(%f)\n", object->pow2scalingFactorX, object->pow2scalingFactorY);
1179 /* Calculate levels for mip mapping */
1181 TRACE("calculating levels %d\n", object->baseTexture.levels);
1182 object->baseTexture.levels++;
1185 while (tmpW > 1 || tmpH > 1) {
1186 tmpW = max(1, tmpW >> 1);
1187 tmpH = max(1, tmpH >> 1);
1188 object->baseTexture.levels++;
1190 TRACE("Calculated levels = %d\n", object->baseTexture.levels);
1193 /* Generate all the surfaces */
1196 for (i = 0; i < object->baseTexture.levels; i++)
1198 /* use the callback to create the texture surface */
1199 hr = D3DCB_CreateSurface(This->parent, tmpW, tmpH, Format, Usage, Pool, i, &object->surfaces[i],NULL);
1200 if (hr!= WINED3D_OK || ( (IWineD3DSurfaceImpl *) object->surfaces[i])->Flags & SFLAG_OVERSIZE) {
1201 FIXME("Failed to create surface %p\n", object);
1203 object->surfaces[i] = NULL;
1204 IWineD3DTexture_Release((IWineD3DTexture *)object);
1210 IWineD3DSurface_SetContainer(object->surfaces[i], (IWineD3DBase *)object);
1211 TRACE("Created surface level %d @ %p\n", i, object->surfaces[i]);
1212 /* calculate the next mipmap level */
1213 tmpW = max(1, tmpW >> 1);
1214 tmpH = max(1, tmpH >> 1);
1217 TRACE("(%p) : Created texture %p\n", This, object);
1221 static HRESULT WINAPI IWineD3DDeviceImpl_CreateVolumeTexture(IWineD3DDevice *iface,
1222 UINT Width, UINT Height, UINT Depth,
1223 UINT Levels, DWORD Usage,
1224 WINED3DFORMAT Format, WINED3DPOOL Pool,
1225 IWineD3DVolumeTexture **ppVolumeTexture,
1226 HANDLE *pSharedHandle, IUnknown *parent,
1227 D3DCB_CREATEVOLUMEFN D3DCB_CreateVolume) {
1229 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
1230 IWineD3DVolumeTextureImpl *object;
1236 /* TODO: It should only be possible to create textures for formats
1237 that are reported as supported */
1238 if (WINED3DFMT_UNKNOWN >= Format) {
1239 WARN("(%p) : Texture cannot be created with a format of D3DFMT_UNKNOWN\n", This);
1240 return WINED3DERR_INVALIDCALL;
1243 D3DCREATERESOURCEOBJECTINSTANCE(object, VolumeTexture, WINED3DRTYPE_VOLUMETEXTURE, 0);
1244 D3DINITIALIZEBASETEXTURE(object->baseTexture);
1246 TRACE("(%p) : W(%d) H(%d) D(%d), Lvl(%d) Usage(%ld), Fmt(%u,%s), Pool(%s)\n", This, Width, Height,
1247 Depth, Levels, Usage, Format, debug_d3dformat(Format), debug_d3dpool(Pool));
1249 object->width = Width;
1250 object->height = Height;
1251 object->depth = Depth;
1253 /* Calculate levels for mip mapping */
1255 object->baseTexture.levels++;
1259 while (tmpW > 1 || tmpH > 1 || tmpD > 1) {
1260 tmpW = max(1, tmpW >> 1);
1261 tmpH = max(1, tmpH >> 1);
1262 tmpD = max(1, tmpD >> 1);
1263 object->baseTexture.levels++;
1265 TRACE("Calculated levels = %d\n", object->baseTexture.levels);
1268 /* Generate all the surfaces */
1273 for (i = 0; i < object->baseTexture.levels; i++)
1275 /* Create the volume */
1276 D3DCB_CreateVolume(This->parent, Width, Height, Depth, Format, Pool, Usage,
1277 (IWineD3DVolume **)&object->volumes[i], pSharedHandle);
1279 /* Set it's container to this object */
1280 IWineD3DVolume_SetContainer(object->volumes[i], (IWineD3DBase *)object);
1282 /* calcualte the next mipmap level */
1283 tmpW = max(1, tmpW >> 1);
1284 tmpH = max(1, tmpH >> 1);
1285 tmpD = max(1, tmpD >> 1);
1288 *ppVolumeTexture = (IWineD3DVolumeTexture *) object;
1289 TRACE("(%p) : Created volume texture %p\n", This, object);
1293 static HRESULT WINAPI IWineD3DDeviceImpl_CreateVolume(IWineD3DDevice *iface,
1294 UINT Width, UINT Height, UINT Depth,
1296 WINED3DFORMAT Format, WINED3DPOOL Pool,
1297 IWineD3DVolume** ppVolume,
1298 HANDLE* pSharedHandle, IUnknown *parent) {
1300 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
1301 IWineD3DVolumeImpl *object; /** NOTE: impl ref allowed since this is a create function **/
1302 const PixelFormatDesc *formatDesc = getFormatDescEntry(Format);
1304 D3DCREATERESOURCEOBJECTINSTANCE(object, Volume, WINED3DRTYPE_VOLUME, ((Width * formatDesc->bpp) * Height * Depth))
1306 TRACE("(%p) : W(%d) H(%d) D(%d), Usage(%ld), Fmt(%u,%s), Pool(%s)\n", This, Width, Height,
1307 Depth, Usage, Format, debug_d3dformat(Format), debug_d3dpool(Pool));
1309 object->currentDesc.Width = Width;
1310 object->currentDesc.Height = Height;
1311 object->currentDesc.Depth = Depth;
1312 object->bytesPerPixel = formatDesc->bpp;
1314 /** Note: Volume textures cannot be dxtn, hence no need to check here **/
1315 object->lockable = TRUE;
1316 object->locked = FALSE;
1317 memset(&object->lockedBox, 0, sizeof(WINED3DBOX));
1318 object->dirty = TRUE;
1320 return IWineD3DVolume_AddDirtyBox((IWineD3DVolume *) object, NULL);
1323 static HRESULT WINAPI IWineD3DDeviceImpl_CreateCubeTexture(IWineD3DDevice *iface, UINT EdgeLength,
1324 UINT Levels, DWORD Usage,
1325 WINED3DFORMAT Format, WINED3DPOOL Pool,
1326 IWineD3DCubeTexture **ppCubeTexture,
1327 HANDLE *pSharedHandle, IUnknown *parent,
1328 D3DCB_CREATESURFACEFN D3DCB_CreateSurface) {
1330 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
1331 IWineD3DCubeTextureImpl *object; /** NOTE: impl ref allowed since this is a create function **/
1335 unsigned int pow2EdgeLength = EdgeLength;
1337 /* TODO: It should only be possible to create textures for formats
1338 that are reported as supported */
1339 if (WINED3DFMT_UNKNOWN >= Format) {
1340 WARN("(%p) : Texture cannot be created with a format of D3DFMT_UNKNOWN\n", This);
1341 return WINED3DERR_INVALIDCALL;
1344 D3DCREATERESOURCEOBJECTINSTANCE(object, CubeTexture, WINED3DRTYPE_CUBETEXTURE, 0);
1345 D3DINITIALIZEBASETEXTURE(object->baseTexture);
1347 TRACE("(%p) Create Cube Texture\n", This);
1349 /** Non-power2 support **/
1351 /* Find the nearest pow2 match */
1353 while (pow2EdgeLength < EdgeLength) pow2EdgeLength <<= 1;
1355 object->edgeLength = EdgeLength;
1356 /* TODO: support for native non-power 2 */
1357 /* Precalculated scaling for 'faked' non power of two texture coords */
1358 object->pow2scalingFactor = ((float)EdgeLength) / ((float)pow2EdgeLength);
1360 /* Calculate levels for mip mapping */
1362 object->baseTexture.levels++;
1365 tmpW = max(1, tmpW >> 1);
1366 object->baseTexture.levels++;
1368 TRACE("Calculated levels = %d\n", object->baseTexture.levels);
1371 /* Generate all the surfaces */
1373 for (i = 0; i < object->baseTexture.levels; i++) {
1375 /* Create the 6 faces */
1376 for (j = 0; j < 6; j++) {
1378 hr=D3DCB_CreateSurface(This->parent, tmpW, tmpW, Format, Usage, Pool,
1379 i /* Level */, &object->surfaces[j][i],pSharedHandle);
1381 if(hr!= WINED3D_OK) {
1385 for (l = 0; l < j; l++) {
1386 IWineD3DSurface_Release(object->surfaces[j][i]);
1388 for (k = 0; k < i; k++) {
1389 for (l = 0; l < 6; l++) {
1390 IWineD3DSurface_Release(object->surfaces[l][j]);
1394 FIXME("(%p) Failed to create surface\n",object);
1395 HeapFree(GetProcessHeap(),0,object);
1396 *ppCubeTexture = NULL;
1399 IWineD3DSurface_SetContainer(object->surfaces[j][i], (IWineD3DBase *)object);
1400 TRACE("Created surface level %d @ %p,\n", i, object->surfaces[j][i]);
1402 tmpW = max(1, tmpW >> 1);
1405 TRACE("(%p) : Created Cube Texture %p\n", This, object);
1406 *ppCubeTexture = (IWineD3DCubeTexture *) object;
1410 static HRESULT WINAPI IWineD3DDeviceImpl_CreateQuery(IWineD3DDevice *iface, WINED3DQUERYTYPE Type, IWineD3DQuery **ppQuery, IUnknown* parent) {
1411 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
1412 IWineD3DQueryImpl *object; /*NOTE: impl ref allowed since this is a create function */
1414 if (NULL == ppQuery) {
1415 /* Just a check to see if we support this type of query */
1416 HRESULT hr = WINED3DERR_NOTAVAILABLE;
1418 case WINED3DQUERYTYPE_OCCLUSION:
1419 TRACE("(%p) occlusion query\n", This);
1420 if (GL_SUPPORT(ARB_OCCLUSION_QUERY))
1423 WARN("Unsupported in local OpenGL implementation: ARB_OCCLUSION_QUERY/NV_OCCLUSION_QUERY\n");
1425 case WINED3DQUERYTYPE_VCACHE:
1426 case WINED3DQUERYTYPE_RESOURCEMANAGER:
1427 case WINED3DQUERYTYPE_VERTEXSTATS:
1428 case WINED3DQUERYTYPE_EVENT:
1429 case WINED3DQUERYTYPE_TIMESTAMP:
1430 case WINED3DQUERYTYPE_TIMESTAMPDISJOINT:
1431 case WINED3DQUERYTYPE_TIMESTAMPFREQ:
1432 case WINED3DQUERYTYPE_PIPELINETIMINGS:
1433 case WINED3DQUERYTYPE_INTERFACETIMINGS:
1434 case WINED3DQUERYTYPE_VERTEXTIMINGS:
1435 case WINED3DQUERYTYPE_PIXELTIMINGS:
1436 case WINED3DQUERYTYPE_BANDWIDTHTIMINGS:
1437 case WINED3DQUERYTYPE_CACHEUTILIZATION:
1439 FIXME("(%p) Unhandled query type %d\n", This, Type);
1444 D3DCREATEOBJECTINSTANCE(object, Query)
1445 object->type = Type;
1446 /* allocated the 'extended' data based on the type of query requested */
1448 case D3DQUERYTYPE_OCCLUSION:
1449 if(GL_SUPPORT(ARB_OCCLUSION_QUERY)) {
1450 TRACE("(%p) Allocating data for an occlusion query\n", This);
1451 object->extendedData = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(WineQueryOcclusionData));
1452 GL_EXTCALL(glGenQueriesARB(1, &((WineQueryOcclusionData *)(object->extendedData))->queryId));
1455 case D3DQUERYTYPE_VCACHE:
1456 case D3DQUERYTYPE_RESOURCEMANAGER:
1457 case D3DQUERYTYPE_VERTEXSTATS:
1458 case D3DQUERYTYPE_EVENT:
1459 case D3DQUERYTYPE_TIMESTAMP:
1460 case D3DQUERYTYPE_TIMESTAMPDISJOINT:
1461 case D3DQUERYTYPE_TIMESTAMPFREQ:
1462 case D3DQUERYTYPE_PIPELINETIMINGS:
1463 case D3DQUERYTYPE_INTERFACETIMINGS:
1464 case D3DQUERYTYPE_VERTEXTIMINGS:
1465 case D3DQUERYTYPE_PIXELTIMINGS:
1466 case D3DQUERYTYPE_BANDWIDTHTIMINGS:
1467 case D3DQUERYTYPE_CACHEUTILIZATION:
1469 object->extendedData = 0;
1470 FIXME("(%p) Unhandled query type %d\n",This , Type);
1472 TRACE("(%p) : Created Query %p\n", This, object);
1476 /* example at http://www.fairyengine.com/articles/dxmultiviews.htm */
1477 static HRESULT WINAPI IWineD3DDeviceImpl_CreateAdditionalSwapChain(IWineD3DDevice* iface, WINED3DPRESENT_PARAMETERS* pPresentationParameters, IWineD3DSwapChain** ppSwapChain,
1479 D3DCB_CREATERENDERTARGETFN D3DCB_CreateRenderTarget,
1480 D3DCB_CREATEDEPTHSTENCILSURFACEFN D3DCB_CreateDepthStencil) {
1481 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
1484 IWineD3DSwapChainImpl *object; /** NOTE: impl ref allowed since this is a create function **/
1486 XVisualInfo template;
1487 GLXContext oldContext;
1488 Drawable oldDrawable;
1489 HRESULT hr = WINED3D_OK;
1491 TRACE("(%p) : Created Aditional Swap Chain\n", This);
1493 /** FIXME: Test under windows to find out what the life cycle of a swap chain is,
1494 * does a device hold a reference to a swap chain giving them a lifetime of the device
1495 * or does the swap chain notify the device of its destruction.
1496 *******************************/
1498 /* Check the params */
1499 if(*pPresentationParameters->BackBufferCount > D3DPRESENT_BACK_BUFFER_MAX) {
1500 ERR("App requested %d back buffers, this is not supported for now\n", *pPresentationParameters->BackBufferCount);
1501 return WINED3DERR_INVALIDCALL;
1502 } else if (*pPresentationParameters->BackBufferCount > 1) {
1503 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");
1506 D3DCREATEOBJECTINSTANCE(object, SwapChain)
1508 /*********************
1509 * Lookup the window Handle and the relating X window handle
1510 ********************/
1512 /* Setup hwnd we are using, plus which display this equates to */
1513 object->win_handle = *(pPresentationParameters->hDeviceWindow);
1514 if (!object->win_handle) {
1515 object->win_handle = This->createParms.hFocusWindow;
1518 object->win_handle = GetAncestor(object->win_handle, GA_ROOT);
1519 if ( !( object->win = (Window)GetPropA(object->win_handle, "__wine_x11_whole_window") ) ) {
1520 ERR("Can't get drawable (window), HWND:%p doesn't have the property __wine_x11_whole_window\n", object->win_handle);
1521 return WINED3DERR_NOTAVAILABLE;
1523 hDc = GetDC(object->win_handle);
1524 object->display = get_display(hDc);
1525 ReleaseDC(object->win_handle, hDc);
1526 TRACE("Using a display of %p %p\n", object->display, hDc);
1528 if (NULL == object->display || NULL == hDc) {
1529 WARN("Failed to get a display and HDc for Window %p\n", object->win_handle);
1530 return WINED3DERR_NOTAVAILABLE;
1533 if (object->win == 0) {
1534 WARN("Failed to get a valid XVisuial ID for the window %p\n", object->win_handle);
1535 return WINED3DERR_NOTAVAILABLE;
1538 * Create an opengl context for the display visual
1539 * NOTE: the visual is chosen as the window is created and the glcontext cannot
1540 * use different properties after that point in time. FIXME: How to handle when requested format
1541 * doesn't match actual visual? Cannot choose one here - code removed as it ONLY works if the one
1542 * it chooses is identical to the one already being used!
1543 **********************************/
1545 /** FIXME: Handle stencil appropriately via EnableAutoDepthStencil / AutoDepthStencilFormat **/
1548 /* Create a new context for this swapchain */
1549 template.visualid = (VisualID)GetPropA(GetDesktopWindow(), "__wine_x11_visual_id");
1550 /* TODO: change this to find a similar visual, but one with a stencil/zbuffer buffer that matches the request
1551 (or the best possible if none is requested) */
1552 TRACE("Found x visual ID : %ld\n", template.visualid);
1554 object->visInfo = XGetVisualInfo(object->display, VisualIDMask, &template, &num);
1555 if (NULL == object->visInfo) {
1556 ERR("cannot really get XVisual\n");
1558 return WINED3DERR_NOTAVAILABLE;
1561 /* Write out some debug info about the visual/s */
1562 TRACE("Using x visual ID : %ld\n", template.visualid);
1563 TRACE(" visual info: %p\n", object->visInfo);
1564 TRACE(" num items : %d\n", num);
1565 for (n = 0;n < num; n++) {
1566 TRACE("=====item=====: %d\n", n + 1);
1567 TRACE(" visualid : %ld\n", object->visInfo[n].visualid);
1568 TRACE(" screen : %d\n", object->visInfo[n].screen);
1569 TRACE(" depth : %u\n", object->visInfo[n].depth);
1570 TRACE(" class : %d\n", object->visInfo[n].class);
1571 TRACE(" red_mask : %ld\n", object->visInfo[n].red_mask);
1572 TRACE(" green_mask : %ld\n", object->visInfo[n].green_mask);
1573 TRACE(" blue_mask : %ld\n", object->visInfo[n].blue_mask);
1574 TRACE(" colormap_size : %d\n", object->visInfo[n].colormap_size);
1575 TRACE(" bits_per_rgb : %d\n", object->visInfo[n].bits_per_rgb);
1576 /* log some extra glx info */
1577 glXGetConfig(object->display, object->visInfo, GLX_AUX_BUFFERS, &value);
1578 TRACE(" gl_aux_buffers : %d\n", value);
1579 glXGetConfig(object->display, object->visInfo, GLX_BUFFER_SIZE ,&value);
1580 TRACE(" gl_buffer_size : %d\n", value);
1581 glXGetConfig(object->display, object->visInfo, GLX_RED_SIZE, &value);
1582 TRACE(" gl_red_size : %d\n", value);
1583 glXGetConfig(object->display, object->visInfo, GLX_GREEN_SIZE, &value);
1584 TRACE(" gl_green_size : %d\n", value);
1585 glXGetConfig(object->display, object->visInfo, GLX_BLUE_SIZE, &value);
1586 TRACE(" gl_blue_size : %d\n", value);
1587 glXGetConfig(object->display, object->visInfo, GLX_ALPHA_SIZE, &value);
1588 TRACE(" gl_alpha_size : %d\n", value);
1589 glXGetConfig(object->display, object->visInfo, GLX_DEPTH_SIZE ,&value);
1590 TRACE(" gl_depth_size : %d\n", value);
1591 glXGetConfig(object->display, object->visInfo, GLX_STENCIL_SIZE, &value);
1592 TRACE(" gl_stencil_size : %d\n", value);
1594 /* Now choose a simila visual ID*/
1596 #ifdef USE_CONTEXT_MANAGER
1598 /** TODO: use a context mamager **/
1602 IWineD3DSwapChain *implSwapChain;
1603 if (WINED3D_OK != IWineD3DDevice_GetSwapChain(iface, 0, &implSwapChain)) {
1604 /* The first time around we create the context that is shared with all other swapchains and render targets */
1605 object->glCtx = glXCreateContext(object->display, object->visInfo, NULL, GL_TRUE);
1606 TRACE("Creating implicit context for vis %p, hwnd %p\n", object->display, object->visInfo);
1609 TRACE("Creating context for vis %p, hwnd %p\n", object->display, object->visInfo);
1610 /* TODO: don't use Impl structures outside of create functions! (a context manager will replace the ->glCtx) */
1611 /* and create a new context with the implicit swapchains context as the shared context */
1612 object->glCtx = glXCreateContext(object->display, object->visInfo, ((IWineD3DSwapChainImpl *)implSwapChain)->glCtx, GL_TRUE);
1613 IWineD3DSwapChain_Release(implSwapChain);
1618 XFree(object->visInfo);
1619 object->visInfo = NULL;
1623 if (!object->glCtx) {
1624 ERR("Failed to create GLX context\n");
1625 return WINED3DERR_NOTAVAILABLE;
1627 TRACE("Context created (HWND=%p, glContext=%p, Window=%ld, VisInfo=%p)\n",
1628 object->win_handle, object->glCtx, object->win, object->visInfo);
1631 /*********************
1632 * Windowed / Fullscreen
1633 *******************/
1636 * TODO: MSDN says that we are only allowed one fullscreen swapchain per device,
1637 * so we should really check to see if there is a fullscreen swapchain already
1638 * I think Windows and X have different ideas about fullscreen, does a single head count as full screen?
1639 **************************************/
1641 if (!*(pPresentationParameters->Windowed)) {
1647 /* Get info on the current display setup */
1648 hdc = CreateDCA("DISPLAY", NULL, NULL, NULL);
1649 bpp = GetDeviceCaps(hdc, BITSPIXEL);
1652 /* Change the display settings */
1653 memset(&devmode, 0, sizeof(DEVMODEW));
1654 devmode.dmFields = DM_BITSPERPEL | DM_PELSWIDTH | DM_PELSHEIGHT;
1655 devmode.dmBitsPerPel = (bpp >= 24) ? 32 : bpp; /* Stupid XVidMode cannot change bpp */
1656 devmode.dmPelsWidth = *(pPresentationParameters->BackBufferWidth);
1657 devmode.dmPelsHeight = *(pPresentationParameters->BackBufferHeight);
1658 MultiByteToWideChar(CP_ACP, 0, "Gamers CG", -1, devmode.dmDeviceName, CCHDEVICENAME);
1659 ChangeDisplaySettingsExW(devmode.dmDeviceName, &devmode, object->win_handle, CDS_FULLSCREEN, NULL);
1661 /* Make popup window */
1662 SetWindowLongA(object->win_handle, GWL_STYLE, WS_POPUP);
1663 SetWindowPos(object->win_handle, HWND_TOP, 0, 0,
1664 *(pPresentationParameters->BackBufferWidth),
1665 *(pPresentationParameters->BackBufferHeight), SWP_SHOWWINDOW | SWP_FRAMECHANGED);
1667 /* For GetDisplayMode */
1668 This->ddraw_width = devmode.dmPelsWidth;
1669 This->ddraw_height = devmode.dmPelsHeight;
1670 This->ddraw_format = *(pPresentationParameters->BackBufferFormat);
1674 /** MSDN: If Windowed is TRUE and either of the BackBufferWidth/Height values is zero,
1675 * then the corresponding dimension of the client area of the hDeviceWindow
1676 * (or the focus window, if hDeviceWindow is NULL) is taken.
1677 **********************/
1679 if (*(pPresentationParameters->Windowed) &&
1680 ((*(pPresentationParameters->BackBufferWidth) == 0) ||
1681 (*(pPresentationParameters->BackBufferHeight) == 0))) {
1684 GetClientRect(object->win_handle, &Rect);
1686 if (*(pPresentationParameters->BackBufferWidth) == 0) {
1687 *(pPresentationParameters->BackBufferWidth) = Rect.right;
1688 TRACE("Updating width to %d\n", *(pPresentationParameters->BackBufferWidth));
1690 if (*(pPresentationParameters->BackBufferHeight) == 0) {
1691 *(pPresentationParameters->BackBufferHeight) = Rect.bottom;
1692 TRACE("Updating height to %d\n", *(pPresentationParameters->BackBufferHeight));
1696 /*********************
1697 * finish off parameter initialization
1698 *******************/
1700 /* Put the correct figures in the presentation parameters */
1701 TRACE("Coppying accross presentaion paraneters\n");
1702 object->presentParms.BackBufferWidth = *(pPresentationParameters->BackBufferWidth);
1703 object->presentParms.BackBufferHeight = *(pPresentationParameters->BackBufferHeight);
1704 object->presentParms.BackBufferFormat = *(pPresentationParameters->BackBufferFormat);
1705 object->presentParms.BackBufferCount = *(pPresentationParameters->BackBufferCount);
1706 object->presentParms.MultiSampleType = *(pPresentationParameters->MultiSampleType);
1707 object->presentParms.MultiSampleQuality = NULL == pPresentationParameters->MultiSampleQuality ? 0 : *(pPresentationParameters->MultiSampleQuality);
1708 object->presentParms.SwapEffect = *(pPresentationParameters->SwapEffect);
1709 object->presentParms.hDeviceWindow = *(pPresentationParameters->hDeviceWindow);
1710 object->presentParms.Windowed = *(pPresentationParameters->Windowed);
1711 object->presentParms.EnableAutoDepthStencil = *(pPresentationParameters->EnableAutoDepthStencil);
1712 object->presentParms.AutoDepthStencilFormat = *(pPresentationParameters->AutoDepthStencilFormat);
1713 object->presentParms.Flags = *(pPresentationParameters->Flags);
1714 object->presentParms.FullScreen_RefreshRateInHz = *(pPresentationParameters->FullScreen_RefreshRateInHz);
1715 object->presentParms.PresentationInterval = *(pPresentationParameters->PresentationInterval);
1718 /*********************
1719 * Create the back, front and stencil buffers
1720 *******************/
1722 TRACE("calling rendertarget CB\n");
1723 hr = D3DCB_CreateRenderTarget((IUnknown *) This->parent,
1724 object->presentParms.BackBufferWidth,
1725 object->presentParms.BackBufferHeight,
1726 object->presentParms.BackBufferFormat,
1727 object->presentParms.MultiSampleType,
1728 object->presentParms.MultiSampleQuality,
1729 TRUE /* Lockable */,
1730 &object->frontBuffer,
1731 NULL /* pShared (always null)*/);
1732 if (object->frontBuffer != NULL)
1733 IWineD3DSurface_SetContainer(object->frontBuffer, (IWineD3DBase *)object);
1735 if(object->presentParms.BackBufferCount > 0) {
1738 object->backBuffer = HeapAlloc(GetProcessHeap(), 0, sizeof(IWineD3DSurface *) * object->presentParms.BackBufferCount);
1739 if(!object->backBuffer) {
1740 ERR("Out of memory\n");
1742 if (object->frontBuffer) {
1743 IUnknown *bufferParent;
1744 IWineD3DSurface_GetParent(object->frontBuffer, &bufferParent);
1745 IUnknown_Release(bufferParent); /* once for the get parent */
1746 if (IUnknown_Release(bufferParent) > 0) {
1747 FIXME("(%p) Something's still holding the front buffer\n",This);
1750 HeapFree(GetProcessHeap(), 0, object);
1751 return E_OUTOFMEMORY;
1754 for(i = 0; i < object->presentParms.BackBufferCount; i++) {
1755 TRACE("calling rendertarget CB\n");
1756 hr = D3DCB_CreateRenderTarget((IUnknown *) This->parent,
1757 object->presentParms.BackBufferWidth,
1758 object->presentParms.BackBufferHeight,
1759 object->presentParms.BackBufferFormat,
1760 object->presentParms.MultiSampleType,
1761 object->presentParms.MultiSampleQuality,
1762 TRUE /* Lockable */,
1763 &object->backBuffer[i],
1764 NULL /* pShared (always null)*/);
1765 if(hr == WINED3D_OK && object->backBuffer[i]) {
1766 IWineD3DSurface_SetContainer(object->backBuffer[i], (IWineD3DBase *)object);
1772 object->backBuffer = NULL;
1775 if (object->backBuffer != NULL) {
1777 glDrawBuffer(GL_BACK);
1778 checkGLcall("glDrawBuffer(GL_BACK)");
1781 /* Single buffering - draw to front buffer */
1783 glDrawBuffer(GL_FRONT);
1784 checkGLcall("glDrawBuffer(GL_FRONT)");
1788 /* Under directX swapchains share the depth stencil, so only create one depth-stencil */
1789 if (*(pPresentationParameters->EnableAutoDepthStencil) && hr == WINED3D_OK) {
1790 TRACE("Creating depth stencil buffer\n");
1791 if (This->depthStencilBuffer == NULL ) {
1792 hr = D3DCB_CreateDepthStencil((IUnknown *) This->parent,
1793 object->presentParms.BackBufferWidth,
1794 object->presentParms.BackBufferHeight,
1795 object->presentParms.AutoDepthStencilFormat,
1796 object->presentParms.MultiSampleType,
1797 object->presentParms.MultiSampleQuality,
1798 FALSE /* FIXME: Discard */,
1799 &This->depthStencilBuffer,
1800 NULL /* pShared (always null)*/ );
1801 if (This->depthStencilBuffer != NULL)
1802 IWineD3DSurface_SetContainer(This->depthStencilBuffer, 0);
1805 /** TODO: A check on width, height and multisample types
1806 *(since the zbuffer must be at least as large as the render target and have the same multisample parameters)
1807 ****************************/
1808 object->wantsDepthStencilBuffer = TRUE;
1810 object->wantsDepthStencilBuffer = FALSE;
1813 TRACE("FrontBuf @ %p, BackBuf @ %p, DepthStencil %d\n",object->frontBuffer, object->backBuffer ? object->backBuffer[0] : NULL, object->wantsDepthStencilBuffer);
1816 /*********************
1817 * init the default renderTarget management
1818 *******************/
1819 object->drawable = object->win;
1820 object->render_ctx = object->glCtx;
1822 if (hr == WINED3D_OK) {
1823 /*********************
1824 * Setup some defaults and clear down the buffers
1825 *******************/
1827 /** save current context and drawable **/
1828 oldContext = glXGetCurrentContext();
1829 oldDrawable = glXGetCurrentDrawable();
1831 TRACE("Activating context (display %p context %p drawable %ld)!\n", object->display, object->glCtx, object->win);
1832 if (glXMakeCurrent(object->display, object->win, object->glCtx) == False) {
1833 ERR("Error in setting current context (display %p context %p drawable %ld)!\n", object->display, object->glCtx, object->win);
1835 checkGLcall("glXMakeCurrent");
1837 TRACE("Setting up the screen\n");
1838 /* Clear the screen */
1839 glClearColor(1.0, 0.0, 0.0, 0.0);
1840 checkGLcall("glClearColor");
1843 glClearStencil(0xffff);
1845 checkGLcall("glClear");
1847 glColor3f(1.0, 1.0, 1.0);
1848 checkGLcall("glColor3f");
1850 glEnable(GL_LIGHTING);
1851 checkGLcall("glEnable");
1853 glLightModeli(GL_LIGHT_MODEL_LOCAL_VIEWER, GL_TRUE);
1854 checkGLcall("glLightModeli(GL_LIGHT_MODEL_LOCAL_VIEWER, GL_TRUE);");
1856 glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE_EXT);
1857 checkGLcall("glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE_EXT);");
1859 glLightModeli(GL_LIGHT_MODEL_COLOR_CONTROL, GL_SEPARATE_SPECULAR_COLOR);
1860 checkGLcall("glLightModeli(GL_LIGHT_MODEL_COLOR_CONTROL, GL_SEPARATE_SPECULAR_COLOR);");
1862 /* switch back to the original context (if there was one)*/
1863 if (This->swapchains) {
1864 /** TODO: restore the context and drawable **/
1865 glXMakeCurrent(object->display, oldDrawable, oldContext);
1868 /* Set the surface alignment. This never changes, so we are safe to set it once per context*/
1869 glPixelStorei(GL_PACK_ALIGNMENT, 4);
1870 checkGLcall("glPixelStorei(GL_PACK_ALIGNMENT, 4);");
1871 glPixelStorei(GL_UNPACK_ALIGNMENT, 4);
1872 checkGLcall("glPixelStorei(GL_UNPACK_ALIGNMENT, 4);");
1876 TRACE("Set swapchain to %p\n", object);
1877 } else { /* something went wrong so clean up */
1878 IUnknown* bufferParent;
1879 if (object->frontBuffer) {
1881 IWineD3DSurface_GetParent(object->frontBuffer, &bufferParent);
1882 IUnknown_Release(bufferParent); /* once for the get parent */
1883 if (IUnknown_Release(bufferParent) > 0) {
1884 FIXME("(%p) Something's still holding the front buffer\n",This);
1887 if (object->backBuffer) {
1889 for(i = 0; i < object->presentParms.BackBufferCount; i++) {
1890 if(object->backBuffer[i]) {
1891 IWineD3DSurface_GetParent(object->backBuffer[i], &bufferParent);
1892 IUnknown_Release(bufferParent); /* once for the get parent */
1893 if (IUnknown_Release(bufferParent) > 0) {
1894 FIXME("(%p) Something's still holding the back buffer\n",This);
1898 HeapFree(GetProcessHeap(), 0, object->backBuffer);
1899 object->backBuffer = NULL;
1901 /* NOTE: don't clean up the depthstencil buffer because it belongs to the device */
1902 /* Clean up the context */
1903 /* check that we are the current context first (we shouldn't be though!) */
1904 if (object->glCtx != 0) {
1905 if(glXGetCurrentContext() == object->glCtx) {
1906 glXMakeCurrent(object->display, None, NULL);
1908 glXDestroyContext(object->display, object->glCtx);
1910 HeapFree(GetProcessHeap(), 0, object);
1917 /** NOTE: These are ahead of the other getters and setters to save using a forward declaration **/
1918 static UINT WINAPI IWineD3DDeviceImpl_GetNumberOfSwapChains(IWineD3DDevice *iface) {
1919 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
1920 TRACE("(%p)\n", This);
1922 return This->NumberOfSwapChains;
1925 static HRESULT WINAPI IWineD3DDeviceImpl_GetSwapChain(IWineD3DDevice *iface, UINT iSwapChain, IWineD3DSwapChain **pSwapChain) {
1926 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
1927 TRACE("(%p) : swapchain %d\n", This, iSwapChain);
1929 if(iSwapChain < This->NumberOfSwapChains) {
1930 *pSwapChain = This->swapchains[iSwapChain];
1931 IWineD3DSwapChain_AddRef(*pSwapChain);
1932 TRACE("(%p) returning %p\n", This, *pSwapChain);
1935 TRACE("Swapchain out of range\n");
1937 return WINED3DERR_INVALIDCALL;
1942 * Vertex Declaration
1944 static HRESULT WINAPI IWineD3DDeviceImpl_CreateVertexDeclaration(IWineD3DDevice* iface, CONST VOID* pDeclaration, IWineD3DVertexDeclaration** ppVertexDeclaration, IUnknown *parent) {
1945 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
1946 IWineD3DVertexDeclarationImpl *object = NULL;
1947 HRESULT hr = WINED3D_OK;
1948 TRACE("(%p) : directXVersion=%u, pFunction=%p, ppDecl=%p\n", This, ((IWineD3DImpl *)This->wineD3D)->dxVersion, pDeclaration, ppVertexDeclaration);
1949 D3DCREATEOBJECTINSTANCE(object, VertexDeclaration)
1952 hr = IWineD3DVertexDeclaration_SetDeclaration((IWineD3DVertexDeclaration *)object, (void *)pDeclaration);
1957 /* http://msdn.microsoft.com/archive/default.asp?url=/archive/en-us/directx9_c/directx/graphics/programmingguide/programmable/vertexshaders/vscreate.asp */
1958 static HRESULT WINAPI IWineD3DDeviceImpl_CreateVertexShader(IWineD3DDevice *iface, CONST DWORD *pDeclaration, CONST DWORD *pFunction, IWineD3DVertexShader **ppVertexShader, IUnknown *parent) {
1959 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
1960 IWineD3DVertexShaderImpl *object; /* NOTE: impl usage is ok, this is a create */
1961 HRESULT hr = WINED3D_OK;
1962 D3DCREATESHADEROBJECTINSTANCE(object, VertexShader)
1963 object->baseShader.shader_ins = IWineD3DVertexShaderImpl_shader_ins;
1965 TRACE("(%p) : Created Vertex shader %p\n", This, *ppVertexShader);
1967 /* If a vertex declaration has been passed, save it to the vertex shader, this affects d3d8 only. */
1968 /* Further it needs to be set before calling SetFunction as SetFunction needs the declaration. */
1969 if (pDeclaration != NULL) {
1970 IWineD3DVertexDeclaration *vertexDeclaration;
1971 hr = IWineD3DDevice_CreateVertexDeclaration(iface, pDeclaration, &vertexDeclaration ,NULL);
1972 if (WINED3D_OK == hr) {
1973 TRACE("(%p) : Setting vertex declaration to %p\n", This, vertexDeclaration);
1974 object->vertexDeclaration = vertexDeclaration;
1976 FIXME("(%p) : Failed to set the declaration, returning WINED3DERR_INVALIDCALL\n", iface);
1977 IWineD3DVertexShader_Release(*ppVertexShader);
1978 return WINED3DERR_INVALIDCALL;
1982 hr = IWineD3DVertexShader_SetFunction(*ppVertexShader, pFunction);
1984 if (WINED3D_OK != hr) {
1985 FIXME("(%p) : Failed to set the function, returning WINED3DERR_INVALIDCALL\n", iface);
1986 IWineD3DVertexShader_Release(*ppVertexShader);
1987 return WINED3DERR_INVALIDCALL;
1990 #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. */
1991 if(Usage == WINED3DUSAGE_SOFTWAREVERTEXPROCESSING) {
2002 static HRESULT WINAPI IWineD3DDeviceImpl_CreatePixelShader(IWineD3DDevice *iface, CONST DWORD *pFunction, IWineD3DPixelShader **ppPixelShader, IUnknown *parent) {
2003 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2004 IWineD3DPixelShaderImpl *object; /* NOTE: impl allowed, this is a create */
2005 HRESULT hr = WINED3D_OK;
2007 D3DCREATESHADEROBJECTINSTANCE(object, PixelShader)
2008 object->baseShader.shader_ins = IWineD3DPixelShaderImpl_shader_ins;
2009 hr = IWineD3DPixelShader_SetFunction(*ppPixelShader, pFunction);
2010 if (WINED3D_OK == hr) {
2011 TRACE("(%p) : Created Pixel shader %p\n", This, *ppPixelShader);
2013 WARN("(%p) : Failed to create pixel shader\n", This);
2019 static HRESULT WINAPI IWineD3DDeviceImpl_CreatePalette(IWineD3DDevice *iface, DWORD Flags, PALETTEENTRY *PalEnt, IWineD3DPalette **Palette, IUnknown *Parent) {
2020 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *) iface;
2021 IWineD3DPaletteImpl *object;
2023 TRACE("(%p)->(%lx, %p, %p, %p)\n", This, Flags, PalEnt, Palette, Parent);
2025 /* Create the new object */
2026 object = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(IWineD3DPaletteImpl));
2028 ERR("Out of memory when allocating memory for a IWineD3DPalette implementation\n");
2029 return E_OUTOFMEMORY;
2032 object->lpVtbl = &IWineD3DPalette_Vtbl;
2034 object->Flags = Flags;
2035 object->parent = Parent;
2036 object->wineD3DDevice = This;
2037 object->palNumEntries = IWineD3DPaletteImpl_Size(Flags);
2039 object->hpal = CreatePalette((const LOGPALETTE*)&(object->palVersion));
2042 HeapFree( GetProcessHeap(), 0, object);
2043 return E_OUTOFMEMORY;
2046 hr = IWineD3DPalette_SetEntries((IWineD3DPalette *) object, 0, 0, IWineD3DPaletteImpl_Size(Flags), PalEnt);
2048 IWineD3DPalette_Release((IWineD3DPalette *) object);
2052 *Palette = (IWineD3DPalette *) object;
2057 static HRESULT WINAPI IWineD3DDeviceImpl_Init3D(IWineD3DDevice *iface, WINED3DPRESENT_PARAMETERS* pPresentationParameters, D3DCB_CREATEADDITIONALSWAPCHAIN D3DCB_CreateAdditionalSwapChain) {
2058 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *) iface;
2059 IWineD3DSwapChainImpl *swapchain;
2061 TRACE("(%p)->(%p,%p)\n", This, pPresentationParameters, D3DCB_CreateAdditionalSwapChain);
2062 if(This->d3d_initialized) return WINED3DERR_INVALIDCALL;
2064 /* TODO: Test if OpenGL is compiled in and loaded */
2066 /* Setup the implicit swapchain */
2067 TRACE("Creating implicit swapchain\n");
2068 if (D3D_OK != D3DCB_CreateAdditionalSwapChain((IUnknown *) This->parent, pPresentationParameters, (IWineD3DSwapChain **)&swapchain) || swapchain == NULL) {
2069 WARN("Failed to create implicit swapchain\n");
2070 return WINED3DERR_INVALIDCALL;
2073 This->NumberOfSwapChains = 1;
2074 This->swapchains = HeapAlloc(GetProcessHeap(), 0, This->NumberOfSwapChains * sizeof(IWineD3DSwapChain *));
2075 if(!This->swapchains) {
2076 ERR("Out of memory!\n");
2077 IWineD3DSwapChain_Release( (IWineD3DSwapChain *) swapchain);
2078 return E_OUTOFMEMORY;
2080 This->swapchains[0] = (IWineD3DSwapChain *) swapchain;
2082 if(swapchain->backBuffer && swapchain->backBuffer[0]) {
2083 TRACE("Setting rendertarget to %p\n", swapchain->backBuffer);
2084 This->renderTarget = swapchain->backBuffer[0];
2087 TRACE("Setting rendertarget to %p\n", swapchain->frontBuffer);
2088 This->renderTarget = swapchain->frontBuffer;
2090 IWineD3DSurface_AddRef(This->renderTarget);
2091 /* Depth Stencil support */
2092 This->stencilBufferTarget = This->depthStencilBuffer;
2093 if (NULL != This->stencilBufferTarget) {
2094 IWineD3DSurface_AddRef(This->stencilBufferTarget);
2097 /* Set up some starting GL setup */
2100 * Initialize openGL extension related variables
2101 * with Default values
2104 ((IWineD3DImpl *) This->wineD3D)->isGLInfoValid = IWineD3DImpl_FillGLCaps( This->wineD3D, swapchain->display);
2105 /* Setup all the devices defaults */
2106 IWineD3DStateBlock_InitStartupStateBlock((IWineD3DStateBlock *)This->stateBlock);
2108 IWineD3DImpl_CheckGraphicsMemory();
2112 /* Initialize our list of GLSL programs */
2113 list_init(&This->glsl_shader_progs);
2115 { /* Set a default viewport */
2119 vp.Width = *(pPresentationParameters->BackBufferWidth);
2120 vp.Height = *(pPresentationParameters->BackBufferHeight);
2123 IWineD3DDevice_SetViewport((IWineD3DDevice *)This, &vp);
2126 /* Initialize the current view state */
2127 This->modelview_valid = 1;
2128 This->proj_valid = 0;
2129 This->view_ident = 1;
2130 This->last_was_rhw = 0;
2131 glGetIntegerv(GL_MAX_LIGHTS, &This->maxConcurrentLights);
2132 TRACE("(%p) All defaults now set up, leaving Init3D with %p\n", This, This);
2134 /* Clear the screen */
2135 IWineD3DDevice_Clear((IWineD3DDevice *) This, 0, NULL, D3DCLEAR_STENCIL|D3DCLEAR_ZBUFFER|D3DCLEAR_TARGET, 0x00, 1.0, 0);
2137 This->d3d_initialized = TRUE;
2141 static HRESULT WINAPI IWineD3DDeviceImpl_Uninit3D(IWineD3DDevice *iface) {
2142 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *) iface;
2144 IUnknown* stencilBufferParent;
2145 IUnknown* swapChainParent;
2147 TRACE("(%p)\n", This);
2149 if(!This->d3d_initialized) return WINED3DERR_INVALIDCALL;
2151 /* Delete the mouse cursor texture */
2152 if(This->cursorTexture) {
2154 glDeleteTextures(1, &This->cursorTexture);
2156 This->cursorTexture = 0;
2159 for(sampler = 0; sampler < GL_LIMITS(sampler_stages); ++sampler) {
2160 IWineD3DDevice_SetTexture(iface, sampler, NULL);
2163 /* Release the buffers (with sanity checks)*/
2164 TRACE("Releasing the depth stencil buffer at %p\n", This->stencilBufferTarget);
2165 if(This->stencilBufferTarget != NULL && (IWineD3DSurface_Release(This->stencilBufferTarget) >0)){
2166 if(This->depthStencilBuffer != This->stencilBufferTarget)
2167 FIXME("(%p) Something's still holding the depthStencilBuffer\n",This);
2169 This->stencilBufferTarget = NULL;
2171 TRACE("Releasing the render target at %p\n", This->renderTarget);
2172 if(IWineD3DSurface_Release(This->renderTarget) >0){
2173 /* This check is a bit silly, itshould be in swapchain_release FIXME("(%p) Something's still holding the renderTarget\n",This); */
2175 TRACE("Setting rendertarget to NULL\n");
2176 This->renderTarget = NULL;
2178 if (This->depthStencilBuffer) {
2179 IWineD3DSurface_GetParent(This->depthStencilBuffer, &stencilBufferParent);
2180 IUnknown_Release(stencilBufferParent); /* once for the get parent */
2181 if(IUnknown_Release(stencilBufferParent) >0){ /* the second time for when it was created */
2182 FIXME("(%p) Something's still holding the depthStencilBuffer\n",This);
2184 This->depthStencilBuffer = NULL;
2187 for(i=0; i < This->NumberOfSwapChains; i++) {
2188 TRACE("Releasing the implicit swapchain %d\n", i);
2189 /* Swapchain 0 is special because it's created in startup with a hanging parent, so we have to release its parent now */
2190 IWineD3DSwapChain_GetParent(This->swapchains[i], &swapChainParent);
2191 IUnknown_Release(swapChainParent); /* once for the get parent */
2192 if (IUnknown_Release(swapChainParent) > 0) { /* the second time for when it was created */
2193 FIXME("(%p) Something's still holding the implicit swapchain\n", This);
2197 HeapFree(GetProcessHeap(), 0, This->swapchains);
2198 This->swapchains = NULL;
2199 This->NumberOfSwapChains = 0;
2201 This->d3d_initialized = FALSE;
2205 static void WINAPI IWineD3DDeviceImpl_SetFullscreen(IWineD3DDevice *iface, BOOL fullscreen) {
2206 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *) iface;
2207 TRACE("(%p) Setting DDraw fullscreen mode to %s\n", This, fullscreen ? "true" : "false");
2209 /* DirectDraw apps can change between fullscreen and windowed mode after device creation with
2210 * IDirectDraw7::SetCooperativeLevel. The GDI surface implementation needs to know this.
2211 * DDraw doesn't necessarilly have a swapchain, so we have to store the fullscreen flag
2214 This->ddraw_fullscreen = fullscreen;
2217 static HRESULT WINAPI IWineD3DDeviceImpl_EnumDisplayModes(IWineD3DDevice *iface, DWORD Flags, UINT Width, UINT Height, WINED3DFORMAT pixelformat, LPVOID context, D3DCB_ENUMDISPLAYMODESCALLBACK callback) {
2218 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2222 const PixelFormatDesc *formatDesc = getFormatDescEntry(pixelformat);
2224 TRACE("(%p)->(%lx,%d,%d,%d,%p,%p)\n", This, Flags, Width, Height, pixelformat, context, callback);
2226 for (i = 0; EnumDisplaySettingsExW(NULL, i, &DevModeW, 0); i++) {
2227 /* Ignore some modes if a description was passed */
2228 if ( (Width > 0) && (Width != DevModeW.dmPelsWidth)) continue;
2229 if ( (Height > 0) && (Height != DevModeW.dmPelsHeight)) continue;
2230 if ( (pixelformat != WINED3DFMT_UNKNOWN) && ( formatDesc->bpp != DevModeW.dmBitsPerPel) ) continue;
2232 TRACE("Enumerating %ldx%ld@%s\n", DevModeW.dmPelsWidth, DevModeW.dmPelsHeight, debug_d3dformat(pixelformat_for_depth(DevModeW.dmBitsPerPel)));
2234 if (callback((IUnknown *) This, (UINT) DevModeW.dmPelsWidth, (UINT) DevModeW.dmPelsHeight, pixelformat_for_depth(DevModeW.dmBitsPerPel), 60.0, context) == DDENUMRET_CANCEL)
2241 static HRESULT WINAPI IWineD3DDeviceImpl_SetDisplayMode(IWineD3DDevice *iface, UINT iSwapChain, WINED3DDISPLAYMODE* pMode) {
2243 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2245 const PixelFormatDesc *formatDesc = getFormatDescEntry(pMode->Format);
2247 TRACE("(%p)->(%d,%p) Mode=%dx%dx@%d, %s\n", This, iSwapChain, pMode, pMode->Width, pMode->Height, pMode->RefreshRate, debug_d3dformat(pMode->Format));
2249 /* Resize the screen even without a window:
2250 * The app could have unset it with SetCooperativeLevel, but not called
2251 * RestoreDisplayMode first. Then the release will call RestoreDisplayMode,
2252 * but we don't have any hwnd
2255 devmode.dmFields = DM_BITSPERPEL | DM_PELSWIDTH | DM_PELSHEIGHT;
2256 devmode.dmBitsPerPel = formatDesc->bpp * 8;
2257 if(devmode.dmBitsPerPel == 24) devmode.dmBitsPerPel = 32;
2258 devmode.dmPelsWidth = pMode->Width;
2259 devmode.dmPelsHeight = pMode->Height;
2261 devmode.dmDisplayFrequency = pMode->RefreshRate;
2262 if (pMode->RefreshRate != 0) {
2263 devmode.dmFields |= DM_DISPLAYFREQUENCY;
2266 /* Only change the mode if necessary */
2267 if( (This->ddraw_width == pMode->Width) &&
2268 (This->ddraw_height == pMode->Height) &&
2269 (This->ddraw_format == pMode->Format) &&
2270 (pMode->RefreshRate == 0) ) {
2274 ret = ChangeDisplaySettingsExW(NULL, &devmode, NULL, CDS_FULLSCREEN, NULL);
2275 if (ret != DISP_CHANGE_SUCCESSFUL) {
2276 if(devmode.dmDisplayFrequency != 0) {
2277 WARN("ChangeDisplaySettingsExW failed, trying without the refresh rate\n");
2278 devmode.dmFields &= ~DM_DISPLAYFREQUENCY;
2279 devmode.dmDisplayFrequency = 0;
2280 ret = ChangeDisplaySettingsExW(NULL, &devmode, NULL, CDS_FULLSCREEN, NULL) != DISP_CHANGE_SUCCESSFUL;
2282 if(ret != DISP_CHANGE_SUCCESSFUL) {
2283 return DDERR_INVALIDMODE;
2287 /* Store the new values */
2288 This->ddraw_width = pMode->Width;
2289 This->ddraw_height = pMode->Height;
2290 This->ddraw_format = pMode->Format;
2292 /* Only do this with a window of course */
2293 if(This->ddraw_window)
2294 MoveWindow(This->ddraw_window, 0, 0, pMode->Width, pMode->Height, TRUE);
2299 static HRESULT WINAPI IWineD3DDeviceImpl_GetDirect3D(IWineD3DDevice *iface, IWineD3D **ppD3D) {
2300 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2301 *ppD3D= This->wineD3D;
2302 TRACE("(%p) : wineD3D returning %p\n", This, *ppD3D);
2303 IWineD3D_AddRef(*ppD3D);
2307 static UINT WINAPI IWineD3DDeviceImpl_GetAvailableTextureMem(IWineD3DDevice *iface) {
2308 /** NOTE: There's a probably a hack-around for this one by putting as many pbuffers, VBO's (or whatever)
2309 * Into the video ram as possible and seeing how many fit
2310 * you can also get the correct initial value from nvidia and ATI's driver via X
2311 * texture memory is video memory + AGP memory
2312 *******************/
2313 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2314 static BOOL showfixmes = TRUE;
2316 FIXME("(%p) : stub, simulating %dMB for now, returning %dMB left\n", This,
2317 (wined3d_settings.emulated_textureram/(1024*1024)),
2318 ((wined3d_settings.emulated_textureram - wineD3DGlobalStatistics->glsurfaceram) / (1024*1024)));
2321 TRACE("(%p) : simulating %dMB, returning %dMB left\n", This,
2322 (wined3d_settings.emulated_textureram/(1024*1024)),
2323 ((wined3d_settings.emulated_textureram - wineD3DGlobalStatistics->glsurfaceram) / (1024*1024)));
2324 /* return simulated texture memory left */
2325 return (wined3d_settings.emulated_textureram - wineD3DGlobalStatistics->glsurfaceram);
2333 static HRESULT WINAPI IWineD3DDeviceImpl_SetFVF(IWineD3DDevice *iface, DWORD fvf) {
2334 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2335 HRESULT hr = WINED3D_OK;
2337 /* Update the current state block */
2338 This->updateStateBlock->fvf = fvf;
2339 This->updateStateBlock->changed.fvf = TRUE;
2340 This->updateStateBlock->set.fvf = TRUE;
2342 TRACE("(%p) : FVF Shader FVF set to %lx\n", This, fvf);
2347 static HRESULT WINAPI IWineD3DDeviceImpl_GetFVF(IWineD3DDevice *iface, DWORD *pfvf) {
2348 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2349 TRACE("(%p) : GetFVF returning %lx\n", This, This->stateBlock->fvf);
2350 *pfvf = This->stateBlock->fvf;
2355 * Get / Set Stream Source
2357 static HRESULT WINAPI IWineD3DDeviceImpl_SetStreamSource(IWineD3DDevice *iface, UINT StreamNumber,IWineD3DVertexBuffer* pStreamData, UINT OffsetInBytes, UINT Stride) {
2358 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2359 IWineD3DVertexBuffer *oldSrc;
2361 /**TODO: instance and index data, see
2362 http://msdn.microsoft.com/library/default.asp?url=/library/en-us/directx9_c/directx/graphics/programmingguide/advancedtopics/DrawingMultipleInstances.asp
2364 http://msdn.microsoft.com/library/default.asp?url=/library/en-us/directx9_c/directx/graphics/reference/d3d/interfaces/idirect3ddevice9/SetStreamSourceFreq.asp
2367 /* D3d9 only, but shouldn't hurt d3d8 */
2370 streamFlags = StreamNumber &(D3DSTREAMSOURCE_INDEXEDDATA | D3DSTREAMSOURCE_INSTANCEDATA);
2372 if (streamFlags & D3DSTREAMSOURCE_INDEXEDDATA) {
2373 FIXME("stream index data not supported\n");
2375 if (streamFlags & D3DSTREAMSOURCE_INDEXEDDATA) {
2376 FIXME("stream instance data not supported\n");
2380 StreamNumber&= ~(D3DSTREAMSOURCE_INDEXEDDATA | D3DSTREAMSOURCE_INSTANCEDATA);
2382 if (StreamNumber >= MAX_STREAMS) {
2383 WARN("Stream out of range %d\n", StreamNumber);
2384 return WINED3DERR_INVALIDCALL;
2387 oldSrc = This->stateBlock->streamSource[StreamNumber];
2388 TRACE("(%p) : StreamNo: %d, OldStream (%p), NewStream (%p), NewStride %d\n", This, StreamNumber, oldSrc, pStreamData, Stride);
2390 This->updateStateBlock->changed.streamSource[StreamNumber] = TRUE;
2391 This->updateStateBlock->set.streamSource[StreamNumber] = TRUE;
2392 This->updateStateBlock->streamStride[StreamNumber] = Stride;
2393 This->updateStateBlock->streamSource[StreamNumber] = pStreamData;
2394 This->updateStateBlock->streamOffset[StreamNumber] = OffsetInBytes;
2395 This->updateStateBlock->streamFlags[StreamNumber] = streamFlags;
2397 /* Handle recording of state blocks */
2398 if (This->isRecordingState) {
2399 TRACE("Recording... not performing anything\n");
2403 /* Same stream object: no action */
2404 if (oldSrc == pStreamData)
2407 /* Need to do a getParent and pass the reffs up */
2408 /* MSDN says ..... When an application no longer holds a references to this interface, the interface will automatically be freed.
2409 which suggests that we shouldn't be ref counting? and do need a _release on the stream source to reset the stream source
2410 so for now, just count internally */
2411 if (pStreamData != NULL) {
2412 IWineD3DVertexBufferImpl *vbImpl = (IWineD3DVertexBufferImpl *) pStreamData;
2413 if( (vbImpl->Flags & VBFLAG_STREAM) && vbImpl->stream != StreamNumber) {
2414 WARN("Assigning a Vertex Buffer to stream %d which is already assigned to stream %d\n", StreamNumber, vbImpl->stream);
2416 vbImpl->stream = StreamNumber;
2417 vbImpl->Flags |= VBFLAG_STREAM;
2418 IWineD3DVertexBuffer_AddRef(pStreamData);
2420 if (oldSrc != NULL) {
2421 ((IWineD3DVertexBufferImpl *) oldSrc)->Flags &= ~VBFLAG_STREAM;
2422 IWineD3DVertexBuffer_Release(oldSrc);
2428 static HRESULT WINAPI IWineD3DDeviceImpl_GetStreamSource(IWineD3DDevice *iface, UINT StreamNumber,IWineD3DVertexBuffer** pStream, UINT *pOffset, UINT* pStride) {
2429 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2432 TRACE("(%p) : StreamNo: %d, Stream (%p), Stride %d\n", This, StreamNumber,
2433 This->stateBlock->streamSource[StreamNumber], This->stateBlock->streamStride[StreamNumber]);
2436 streamFlags = StreamNumber &(D3DSTREAMSOURCE_INDEXEDDATA | D3DSTREAMSOURCE_INSTANCEDATA);
2438 if (streamFlags & D3DSTREAMSOURCE_INDEXEDDATA) {
2439 FIXME("stream index data not supported\n");
2441 if (streamFlags & D3DSTREAMSOURCE_INDEXEDDATA) {
2442 FIXME("stream instance data not supported\n");
2446 StreamNumber&= ~(D3DSTREAMSOURCE_INDEXEDDATA | D3DSTREAMSOURCE_INSTANCEDATA);
2448 if (StreamNumber >= MAX_STREAMS) {
2449 WARN("Stream out of range %d\n", StreamNumber);
2450 return WINED3DERR_INVALIDCALL;
2452 *pStream = This->stateBlock->streamSource[StreamNumber];
2453 *pStride = This->stateBlock->streamStride[StreamNumber];
2455 *pOffset = This->stateBlock->streamOffset[StreamNumber];
2458 if (*pStream == NULL) {
2459 FIXME("Attempting to get an empty stream %d, returning WINED3DERR_INVALIDCALL\n", StreamNumber);
2460 return WINED3DERR_INVALIDCALL;
2463 IWineD3DVertexBuffer_AddRef(*pStream); /* We have created a new reference to the VB */
2467 /*Should be quite easy, just an extension of vertexdata
2469 http://msdn.microsoft.com/archive/default.asp?url=/archive/en-us/directx9_c_Summer_04/directx/graphics/programmingguide/advancedtopics/DrawingMultipleInstances.asp
2471 The divider is a bit odd though
2473 VertexOffset = StartVertex / Divider * StreamStride +
2474 VertexIndex / Divider * StreamStride + StreamOffset
2477 static HRESULT WINAPI IWineD3DDeviceImpl_SetStreamSourceFreq(IWineD3DDevice *iface, UINT StreamNumber, UINT Divider) {
2478 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2480 TRACE("(%p) StreamNumber(%d), Divider(%d)\n", This, StreamNumber, Divider);
2481 This->updateStateBlock->streamFlags[StreamNumber] = Divider & (D3DSTREAMSOURCE_INSTANCEDATA | D3DSTREAMSOURCE_INDEXEDDATA );
2483 This->updateStateBlock->changed.streamFreq[StreamNumber] = TRUE;
2484 This->updateStateBlock->set.streamFreq[StreamNumber] = TRUE;
2485 This->updateStateBlock->streamFreq[StreamNumber] = Divider & 0x7FFFFF;
2487 if (This->updateStateBlock->streamFlags[StreamNumber] || This->updateStateBlock->streamFreq[StreamNumber] != 1) {
2488 FIXME("Stream indexing not fully supported\n");
2494 static HRESULT WINAPI IWineD3DDeviceImpl_GetStreamSourceFreq(IWineD3DDevice *iface, UINT StreamNumber, UINT* Divider) {
2495 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2497 TRACE("(%p) StreamNumber(%d), Divider(%p)\n", This, StreamNumber, Divider);
2498 *Divider = This->updateStateBlock->streamFreq[StreamNumber] | This->updateStateBlock->streamFlags[StreamNumber];
2500 TRACE("(%p) : returning %d\n", This, *Divider);
2506 * Get / Set & Multiply Transform
2508 static HRESULT WINAPI IWineD3DDeviceImpl_SetTransform(IWineD3DDevice *iface, D3DTRANSFORMSTATETYPE d3dts, CONST D3DMATRIX* lpmatrix) {
2509 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2511 /* Most of this routine, comments included copied from ddraw tree initially: */
2512 TRACE("(%p) : Transform State=%s\n", This, debug_d3dtstype(d3dts));
2514 /* Handle recording of state blocks */
2515 if (This->isRecordingState) {
2516 TRACE("Recording... not performing anything\n");
2517 This->updateStateBlock->changed.transform[d3dts] = TRUE;
2518 This->updateStateBlock->set.transform[d3dts] = TRUE;
2519 memcpy(&This->updateStateBlock->transforms[d3dts], lpmatrix, sizeof(D3DMATRIX));
2524 * If the new matrix is the same as the current one,
2525 * we cut off any further processing. this seems to be a reasonable
2526 * optimization because as was noticed, some apps (warcraft3 for example)
2527 * tend towards setting the same matrix repeatedly for some reason.
2529 * From here on we assume that the new matrix is different, wherever it matters.
2531 if (!memcmp(&This->stateBlock->transforms[d3dts].u.m[0][0], lpmatrix, sizeof(D3DMATRIX))) {
2532 TRACE("The app is setting the same matrix over again\n");
2535 conv_mat(lpmatrix, &This->stateBlock->transforms[d3dts].u.m[0][0]);
2539 ScreenCoord = ProjectionMat * ViewMat * WorldMat * ObjectCoord
2540 where ViewMat = Camera space, WorldMat = world space.
2542 In OpenGL, camera and world space is combined into GL_MODELVIEW
2543 matrix. The Projection matrix stay projection matrix.
2546 /* Capture the times we can just ignore the change for now */
2547 if (d3dts == WINED3DTS_WORLDMATRIX(0)) {
2548 This->modelview_valid = FALSE;
2551 } else if (d3dts == WINED3DTS_PROJECTION) {
2552 This->proj_valid = FALSE;
2555 } else if (d3dts >= WINED3DTS_WORLDMATRIX(1) && d3dts <= WINED3DTS_WORLDMATRIX(255)) {
2556 /* Indexed Vertex Blending Matrices 256 -> 511 */
2557 /* Use arb_vertex_blend or NV_VERTEX_WEIGHTING? */
2558 FIXME("WINED3DTS_WORLDMATRIX(1..255) not handled\n");
2562 /* Now we really are going to have to change a matrix */
2565 if (d3dts >= WINED3DTS_TEXTURE0 && d3dts <= WINED3DTS_TEXTURE7) { /* handle texture matrices */
2566 /* This is now set with the texture unit states, it may be a good idea to flag the change though! */
2567 } else if (d3dts == WINED3DTS_VIEW) { /* handle the VIEW matrice */
2570 /* If we are changing the View matrix, reset the light and clipping planes to the new view
2571 * NOTE: We have to reset the positions even if the light/plane is not currently
2572 * enabled, since the call to enable it will not reset the position.
2573 * NOTE2: Apparently texture transforms do NOT need reapplying
2576 PLIGHTINFOEL *lightChain = NULL;
2577 This->modelview_valid = FALSE;
2578 This->view_ident = !memcmp(lpmatrix, identity, 16 * sizeof(float));
2580 glMatrixMode(GL_MODELVIEW);
2581 checkGLcall("glMatrixMode(GL_MODELVIEW)");
2583 glLoadMatrixf((float *)lpmatrix);
2584 checkGLcall("glLoadMatrixf(...)");
2587 lightChain = This->stateBlock->lights;
2588 while (lightChain && lightChain->glIndex != -1) {
2589 glLightfv(GL_LIGHT0 + lightChain->glIndex, GL_POSITION, lightChain->lightPosn);
2590 checkGLcall("glLightfv posn");
2591 glLightfv(GL_LIGHT0 + lightChain->glIndex, GL_SPOT_DIRECTION, lightChain->lightDirn);
2592 checkGLcall("glLightfv dirn");
2593 lightChain = lightChain->next;
2596 /* Reset Clipping Planes if clipping is enabled */
2597 for (k = 0; k < GL_LIMITS(clipplanes); k++) {
2598 glClipPlane(GL_CLIP_PLANE0 + k, This->stateBlock->clipplane[k]);
2599 checkGLcall("glClipPlane");
2603 } else { /* What was requested!?? */
2604 WARN("invalid matrix specified: %i\n", d3dts);
2607 /* Release lock, all done */
2612 static HRESULT WINAPI IWineD3DDeviceImpl_GetTransform(IWineD3DDevice *iface, D3DTRANSFORMSTATETYPE State, D3DMATRIX* pMatrix) {
2613 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2614 TRACE("(%p) : for Transform State %s\n", This, debug_d3dtstype(State));
2615 memcpy(pMatrix, &This->stateBlock->transforms[State], sizeof(D3DMATRIX));
2619 static HRESULT WINAPI IWineD3DDeviceImpl_MultiplyTransform(IWineD3DDevice *iface, D3DTRANSFORMSTATETYPE State, CONST D3DMATRIX* pMatrix) {
2620 D3DMATRIX *mat = NULL;
2623 /* Note: Using 'updateStateBlock' rather than 'stateblock' in the code
2624 * below means it will be recorded in a state block change, but it
2625 * works regardless where it is recorded.
2626 * If this is found to be wrong, change to StateBlock.
2628 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2629 TRACE("(%p) : For state %s\n", This, debug_d3dtstype(State));
2631 if (State < HIGHEST_TRANSFORMSTATE)
2633 mat = &This->updateStateBlock->transforms[State];
2635 FIXME("Unhandled transform state!!\n");
2638 multiply_matrix(&temp, mat, (D3DMATRIX *) pMatrix);
2640 /* Apply change via set transform - will reapply to eg. lights this way */
2641 return IWineD3DDeviceImpl_SetTransform(iface, State, &temp);
2646 * WARNING: This code relies on the fact that D3DLIGHT8 == D3DLIGHT9
2648 /* Note lights are real special cases. Although the device caps state only eg. 8 are supported,
2649 you can reference any indexes you want as long as that number max are enabled at any
2650 one point in time! Therefore since the indexes can be anything, we need a linked list of them.
2651 However, this causes stateblock problems. When capturing the state block, I duplicate the list,
2652 but when recording, just build a chain pretty much of commands to be replayed. */
2654 static HRESULT WINAPI IWineD3DDeviceImpl_SetLight(IWineD3DDevice *iface, DWORD Index, CONST WINED3DLIGHT* pLight) {
2656 PLIGHTINFOEL *object, *temp;
2658 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2659 TRACE("(%p) : Idx(%ld), pLight(%p)\n", This, Index, pLight);
2661 /* If recording state block, just add to end of lights chain */
2662 if (This->isRecordingState) {
2663 object = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(PLIGHTINFOEL));
2664 if (NULL == object) {
2665 return WINED3DERR_OUTOFVIDEOMEMORY;
2667 memcpy(&object->OriginalParms, pLight, sizeof(D3DLIGHT9));
2668 object->OriginalIndex = Index;
2669 object->glIndex = -1;
2670 object->changed = TRUE;
2672 /* Add to the END of the chain of lights changes to be replayed */
2673 if (This->updateStateBlock->lights == NULL) {
2674 This->updateStateBlock->lights = object;
2676 temp = This->updateStateBlock->lights;
2677 while (temp->next != NULL) temp=temp->next;
2678 temp->next = object;
2680 TRACE("Recording... not performing anything more\n");
2684 /* Ok, not recording any longer so do real work */
2685 object = This->stateBlock->lights;
2686 while (object != NULL && object->OriginalIndex != Index) object = object->next;
2688 /* If we didn't find it in the list of lights, time to add it */
2689 if (object == NULL) {
2690 PLIGHTINFOEL *insertAt,*prevPos;
2692 object = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(PLIGHTINFOEL));
2693 if (NULL == object) {
2694 return WINED3DERR_OUTOFVIDEOMEMORY;
2696 object->OriginalIndex = Index;
2697 object->glIndex = -1;
2699 /* Add it to the front of list with the idea that lights will be changed as needed
2700 BUT after any lights currently assigned GL indexes */
2701 insertAt = This->stateBlock->lights;
2703 while (insertAt != NULL && insertAt->glIndex != -1) {
2705 insertAt = insertAt->next;
2708 if (insertAt == NULL && prevPos == NULL) { /* Start of list */
2709 This->stateBlock->lights = object;
2710 } else if (insertAt == NULL) { /* End of list */
2711 prevPos->next = object;
2712 object->prev = prevPos;
2713 } else { /* Middle of chain */
2714 if (prevPos == NULL) {
2715 This->stateBlock->lights = object;
2717 prevPos->next = object;
2719 object->prev = prevPos;
2720 object->next = insertAt;
2721 insertAt->prev = object;
2725 /* Initialize the object */
2726 TRACE("Light %ld setting to type %d, Diffuse(%f,%f,%f,%f), Specular(%f,%f,%f,%f), Ambient(%f,%f,%f,%f)\n", Index, pLight->Type,
2727 pLight->Diffuse.r, pLight->Diffuse.g, pLight->Diffuse.b, pLight->Diffuse.a,
2728 pLight->Specular.r, pLight->Specular.g, pLight->Specular.b, pLight->Specular.a,
2729 pLight->Ambient.r, pLight->Ambient.g, pLight->Ambient.b, pLight->Ambient.a);
2730 TRACE("... Pos(%f,%f,%f), Dirn(%f,%f,%f)\n", pLight->Position.x, pLight->Position.y, pLight->Position.z,
2731 pLight->Direction.x, pLight->Direction.y, pLight->Direction.z);
2732 TRACE("... Range(%f), Falloff(%f), Theta(%f), Phi(%f)\n", pLight->Range, pLight->Falloff, pLight->Theta, pLight->Phi);
2734 /* Save away the information */
2735 memcpy(&object->OriginalParms, pLight, sizeof(D3DLIGHT9));
2737 switch (pLight->Type) {
2738 case D3DLIGHT_POINT:
2740 object->lightPosn[0] = pLight->Position.x;
2741 object->lightPosn[1] = pLight->Position.y;
2742 object->lightPosn[2] = pLight->Position.z;
2743 object->lightPosn[3] = 1.0f;
2744 object->cutoff = 180.0f;
2748 case D3DLIGHT_DIRECTIONAL:
2750 object->lightPosn[0] = -pLight->Direction.x;
2751 object->lightPosn[1] = -pLight->Direction.y;
2752 object->lightPosn[2] = -pLight->Direction.z;
2753 object->lightPosn[3] = 0.0;
2754 object->exponent = 0.0f;
2755 object->cutoff = 180.0f;
2760 object->lightPosn[0] = pLight->Position.x;
2761 object->lightPosn[1] = pLight->Position.y;
2762 object->lightPosn[2] = pLight->Position.z;
2763 object->lightPosn[3] = 1.0;
2766 object->lightDirn[0] = pLight->Direction.x;
2767 object->lightDirn[1] = pLight->Direction.y;
2768 object->lightDirn[2] = pLight->Direction.z;
2769 object->lightDirn[3] = 1.0;
2772 * opengl-ish and d3d-ish spot lights use too different models for the
2773 * light "intensity" as a function of the angle towards the main light direction,
2774 * so we only can approximate very roughly.
2775 * however spot lights are rather rarely used in games (if ever used at all).
2776 * furthermore if still used, probably nobody pays attention to such details.
2778 if (pLight->Falloff == 0) {
2781 rho = pLight->Theta + (pLight->Phi - pLight->Theta)/(2*pLight->Falloff);
2783 if (rho < 0.0001) rho = 0.0001f;
2784 object->exponent = -0.3/log(cos(rho/2));
2785 if (object->exponent > 128.0) {
2786 object->exponent = 128.0;
2788 object->cutoff = pLight->Phi*90/M_PI;
2794 FIXME("Unrecognized light type %d\n", pLight->Type);
2797 /* Update the live definitions if the light is currently assigned a glIndex */
2798 if (object->glIndex != -1) {
2799 setup_light(iface, object->glIndex, object);
2804 static HRESULT WINAPI IWineD3DDeviceImpl_GetLight(IWineD3DDevice *iface, DWORD Index, WINED3DLIGHT* pLight) {
2805 PLIGHTINFOEL *lightInfo = NULL;
2806 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2807 TRACE("(%p) : Idx(%ld), pLight(%p)\n", This, Index, pLight);
2809 /* Locate the light in the live lights */
2810 lightInfo = This->stateBlock->lights;
2811 while (lightInfo != NULL && lightInfo->OriginalIndex != Index) lightInfo = lightInfo->next;
2813 if (lightInfo == NULL) {
2814 TRACE("Light information requested but light not defined\n");
2815 return WINED3DERR_INVALIDCALL;
2818 memcpy(pLight, &lightInfo->OriginalParms, sizeof(D3DLIGHT9));
2823 * Get / Set Light Enable
2824 * (Note for consistency, renamed d3dx function by adding the 'set' prefix)
2826 static HRESULT WINAPI IWineD3DDeviceImpl_SetLightEnable(IWineD3DDevice *iface, DWORD Index, BOOL Enable) {
2827 PLIGHTINFOEL *lightInfo = NULL;
2828 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2829 TRACE("(%p) : Idx(%ld), enable? %d\n", This, Index, Enable);
2831 /* Tests show true = 128...not clear why */
2833 Enable = Enable? 128: 0;
2835 /* If recording state block, just add to end of lights chain with changedEnable set to true */
2836 if (This->isRecordingState) {
2837 lightInfo = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(PLIGHTINFOEL));
2838 if (NULL == lightInfo) {
2839 return WINED3DERR_OUTOFVIDEOMEMORY;
2841 lightInfo->OriginalIndex = Index;
2842 lightInfo->glIndex = -1;
2843 lightInfo->enabledChanged = TRUE;
2844 lightInfo->lightEnabled = Enable;
2846 /* Add to the END of the chain of lights changes to be replayed */
2847 if (This->updateStateBlock->lights == NULL) {
2848 This->updateStateBlock->lights = lightInfo;
2850 PLIGHTINFOEL *temp = This->updateStateBlock->lights;
2851 while (temp->next != NULL) temp=temp->next;
2852 temp->next = lightInfo;
2854 TRACE("Recording... not performing anything more\n");
2858 /* Not recording... So, locate the light in the live lights */
2859 lightInfo = This->stateBlock->lights;
2860 while (lightInfo != NULL && lightInfo->OriginalIndex != Index) lightInfo = lightInfo->next;
2862 /* Special case - enabling an undefined light creates one with a strict set of parms! */
2863 if (lightInfo == NULL) {
2865 TRACE("Light enabled requested but light not defined, so defining one!\n");
2866 IWineD3DDeviceImpl_SetLight(iface, Index, &WINED3D_default_light);
2868 /* Search for it again! Should be fairly quick as near head of list */
2869 lightInfo = This->stateBlock->lights;
2870 while (lightInfo != NULL && lightInfo->OriginalIndex != Index) lightInfo = lightInfo->next;
2871 if (lightInfo == NULL) {
2872 FIXME("Adding default lights has failed dismally\n");
2873 return WINED3DERR_INVALIDCALL;
2877 /* OK, we now have a light... */
2880 /* If we are disabling it, check it was enabled, and
2881 still only do something if it has assigned a glIndex (which it should have!) */
2882 if ((lightInfo->lightEnabled) && (lightInfo->glIndex != -1)) {
2883 TRACE("Disabling light set up at gl idx %ld\n", lightInfo->glIndex);
2885 glDisable(GL_LIGHT0 + lightInfo->glIndex);
2886 checkGLcall("glDisable GL_LIGHT0+Index");
2889 TRACE("Nothing to do as light was not enabled\n");
2891 lightInfo->lightEnabled = Enable;
2894 /* We are enabling it. If it is enabled, it's really simple */
2895 if (lightInfo->lightEnabled) {
2897 TRACE("Nothing to do as light was enabled\n");
2899 /* If it already has a glIndex, it's still simple */
2900 } else if (lightInfo->glIndex != -1) {
2901 TRACE("Reusing light as already set up at gl idx %ld\n", lightInfo->glIndex);
2902 lightInfo->lightEnabled = Enable;
2904 glEnable(GL_LIGHT0 + lightInfo->glIndex);
2905 checkGLcall("glEnable GL_LIGHT0+Index already setup");
2908 /* Otherwise got to find space - lights are ordered gl indexes first */
2910 PLIGHTINFOEL *bsf = NULL;
2911 PLIGHTINFOEL *pos = This->stateBlock->lights;
2912 PLIGHTINFOEL *prev = NULL;
2916 /* Try to minimize changes as much as possible */
2917 while (pos != NULL && pos->glIndex != -1 && Index < This->maxConcurrentLights) {
2919 /* Try to remember which index can be replaced if necessary */
2920 if (bsf==NULL && !pos->lightEnabled) {
2921 /* Found a light we can replace, save as best replacement */
2925 /* Step to next space */
2931 /* If we have too many active lights, fail the call */
2932 if ((Index == This->maxConcurrentLights) && (bsf == NULL)) {
2933 FIXME("Program requests too many concurrent lights\n");
2934 return WINED3DERR_INVALIDCALL;
2936 /* If we have allocated all lights, but not all are enabled,
2937 reuse one which is not enabled */
2938 } else if (Index == This->maxConcurrentLights) {
2939 /* use bsf - Simply swap the new light and the BSF one */
2940 PLIGHTINFOEL *bsfNext = bsf->next;
2941 PLIGHTINFOEL *bsfPrev = bsf->prev;
2944 if (lightInfo->next != NULL) lightInfo->next->prev = bsf;
2945 if (bsf->prev != NULL) {
2946 bsf->prev->next = lightInfo;
2948 This->stateBlock->lights = lightInfo;
2951 /* If not side by side, lots of chains to update */
2952 if (bsf->next != lightInfo) {
2953 lightInfo->prev->next = bsf;
2954 bsf->next->prev = lightInfo;
2955 bsf->next = lightInfo->next;
2956 bsf->prev = lightInfo->prev;
2957 lightInfo->next = bsfNext;
2958 lightInfo->prev = bsfPrev;
2962 bsf->prev = lightInfo;
2963 bsf->next = lightInfo->next;
2964 lightInfo->next = bsf;
2965 lightInfo->prev = bsfPrev;
2970 glIndex = bsf->glIndex;
2972 lightInfo->glIndex = glIndex;
2973 lightInfo->lightEnabled = Enable;
2975 /* Finally set up the light in gl itself */
2976 TRACE("Replacing light which was set up at gl idx %ld\n", lightInfo->glIndex);
2978 setup_light(iface, glIndex, lightInfo);
2979 glEnable(GL_LIGHT0 + glIndex);
2980 checkGLcall("glEnable GL_LIGHT0 new setup");
2983 /* If we reached the end of the allocated lights, with space in the
2984 gl lights, setup a new light */
2985 } else if (pos->glIndex == -1) {
2987 /* We reached the end of the allocated gl lights, so already
2988 know the index of the next one! */
2990 lightInfo->glIndex = glIndex;
2991 lightInfo->lightEnabled = Enable;
2993 /* In an ideal world, it's already in the right place */
2994 if (lightInfo->prev == NULL || lightInfo->prev->glIndex!=-1) {
2995 /* No need to move it */
2997 /* Remove this light from the list */
2998 lightInfo->prev->next = lightInfo->next;
2999 if (lightInfo->next != NULL) {
3000 lightInfo->next->prev = lightInfo->prev;
3003 /* Add in at appropriate place (inbetween prev and pos) */
3004 lightInfo->prev = prev;
3005 lightInfo->next = pos;
3007 This->stateBlock->lights = lightInfo;
3009 prev->next = lightInfo;
3012 pos->prev = lightInfo;
3016 /* Finally set up the light in gl itself */
3017 TRACE("Defining new light at gl idx %ld\n", lightInfo->glIndex);
3019 setup_light(iface, glIndex, lightInfo);
3020 glEnable(GL_LIGHT0 + glIndex);
3021 checkGLcall("glEnable GL_LIGHT0 new setup");
3030 static HRESULT WINAPI IWineD3DDeviceImpl_GetLightEnable(IWineD3DDevice *iface, DWORD Index,BOOL* pEnable) {
3032 PLIGHTINFOEL *lightInfo = NULL;
3033 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3034 TRACE("(%p) : for idx(%ld)\n", This, Index);
3036 /* Locate the light in the live lights */
3037 lightInfo = This->stateBlock->lights;
3038 while (lightInfo != NULL && lightInfo->OriginalIndex != Index) lightInfo = lightInfo->next;
3040 if (lightInfo == NULL) {
3041 TRACE("Light enabled state requested but light not defined\n");
3042 return WINED3DERR_INVALIDCALL;
3044 *pEnable = lightInfo->lightEnabled;
3049 * Get / Set Clip Planes
3051 static HRESULT WINAPI IWineD3DDeviceImpl_SetClipPlane(IWineD3DDevice *iface, DWORD Index, CONST float *pPlane) {
3052 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3053 TRACE("(%p) : for idx %ld, %p\n", This, Index, pPlane);
3055 /* Validate Index */
3056 if (Index >= GL_LIMITS(clipplanes)) {
3057 TRACE("Application has requested clipplane this device doesn't support\n");
3058 return WINED3DERR_INVALIDCALL;
3061 This->updateStateBlock->changed.clipplane[Index] = TRUE;
3062 This->updateStateBlock->set.clipplane[Index] = TRUE;
3063 This->updateStateBlock->clipplane[Index][0] = pPlane[0];
3064 This->updateStateBlock->clipplane[Index][1] = pPlane[1];
3065 This->updateStateBlock->clipplane[Index][2] = pPlane[2];
3066 This->updateStateBlock->clipplane[Index][3] = pPlane[3];
3068 /* Handle recording of state blocks */
3069 if (This->isRecordingState) {
3070 TRACE("Recording... not performing anything\n");
3078 /* Clip Plane settings are affected by the model view in OpenGL, the View transform in direct3d */
3079 glMatrixMode(GL_MODELVIEW);
3081 glLoadMatrixf((float *) &This->stateBlock->transforms[WINED3DTS_VIEW].u.m[0][0]);
3083 TRACE("Clipplane [%f,%f,%f,%f]\n",
3084 This->updateStateBlock->clipplane[Index][0],
3085 This->updateStateBlock->clipplane[Index][1],
3086 This->updateStateBlock->clipplane[Index][2],
3087 This->updateStateBlock->clipplane[Index][3]);
3088 glClipPlane(GL_CLIP_PLANE0 + Index, This->updateStateBlock->clipplane[Index]);
3089 checkGLcall("glClipPlane");
3097 static HRESULT WINAPI IWineD3DDeviceImpl_GetClipPlane(IWineD3DDevice *iface, DWORD Index, float *pPlane) {
3098 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3099 TRACE("(%p) : for idx %ld\n", This, Index);
3101 /* Validate Index */
3102 if (Index >= GL_LIMITS(clipplanes)) {
3103 TRACE("Application has requested clipplane this device doesn't support\n");
3104 return WINED3DERR_INVALIDCALL;
3107 pPlane[0] = This->stateBlock->clipplane[Index][0];
3108 pPlane[1] = This->stateBlock->clipplane[Index][1];
3109 pPlane[2] = This->stateBlock->clipplane[Index][2];
3110 pPlane[3] = This->stateBlock->clipplane[Index][3];
3115 * Get / Set Clip Plane Status
3116 * WARNING: This code relies on the fact that D3DCLIPSTATUS8 == D3DCLIPSTATUS9
3118 static HRESULT WINAPI IWineD3DDeviceImpl_SetClipStatus(IWineD3DDevice *iface, CONST WINED3DCLIPSTATUS* pClipStatus) {
3119 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3120 FIXME("(%p) : stub\n", This);
3121 if (NULL == pClipStatus) {
3122 return WINED3DERR_INVALIDCALL;
3124 This->updateStateBlock->clip_status.ClipUnion = pClipStatus->ClipUnion;
3125 This->updateStateBlock->clip_status.ClipIntersection = pClipStatus->ClipIntersection;
3129 static HRESULT WINAPI IWineD3DDeviceImpl_GetClipStatus(IWineD3DDevice *iface, WINED3DCLIPSTATUS* pClipStatus) {
3130 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3131 FIXME("(%p) : stub\n", This);
3132 if (NULL == pClipStatus) {
3133 return WINED3DERR_INVALIDCALL;
3135 pClipStatus->ClipUnion = This->updateStateBlock->clip_status.ClipUnion;
3136 pClipStatus->ClipIntersection = This->updateStateBlock->clip_status.ClipIntersection;
3141 * Get / Set Material
3142 * WARNING: This code relies on the fact that D3DMATERIAL8 == D3DMATERIAL9
3144 static HRESULT WINAPI IWineD3DDeviceImpl_SetMaterial(IWineD3DDevice *iface, CONST WINED3DMATERIAL* pMaterial) {
3145 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3147 This->updateStateBlock->changed.material = TRUE;
3148 This->updateStateBlock->set.material = TRUE;
3149 memcpy(&This->updateStateBlock->material, pMaterial, sizeof(WINED3DMATERIAL));
3151 /* Handle recording of state blocks */
3152 if (This->isRecordingState) {
3153 TRACE("Recording... not performing anything\n");
3158 TRACE("(%p) : Diffuse (%f,%f,%f,%f)\n", This, pMaterial->Diffuse.r, pMaterial->Diffuse.g,
3159 pMaterial->Diffuse.b, pMaterial->Diffuse.a);
3160 TRACE("(%p) : Ambient (%f,%f,%f,%f)\n", This, pMaterial->Ambient.r, pMaterial->Ambient.g,
3161 pMaterial->Ambient.b, pMaterial->Ambient.a);
3162 TRACE("(%p) : Specular (%f,%f,%f,%f)\n", This, pMaterial->Specular.r, pMaterial->Specular.g,
3163 pMaterial->Specular.b, pMaterial->Specular.a);
3164 TRACE("(%p) : Emissive (%f,%f,%f,%f)\n", This, pMaterial->Emissive.r, pMaterial->Emissive.g,
3165 pMaterial->Emissive.b, pMaterial->Emissive.a);
3166 TRACE("(%p) : Power (%f)\n", This, pMaterial->Power);
3168 glMaterialfv(GL_FRONT_AND_BACK, GL_AMBIENT, (float*) &This->updateStateBlock->material.Ambient);
3169 checkGLcall("glMaterialfv(GL_AMBIENT)");
3170 glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, (float*) &This->updateStateBlock->material.Diffuse);
3171 checkGLcall("glMaterialfv(GL_DIFFUSE)");
3173 /* Only change material color if specular is enabled, otherwise it is set to black */
3174 if (This->stateBlock->renderState[WINED3DRS_SPECULARENABLE]) {
3175 glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, (float*) &This->updateStateBlock->material.Specular);
3176 checkGLcall("glMaterialfv(GL_SPECULAR");
3178 float black[4] = {0.0f, 0.0f, 0.0f, 0.0f};
3179 glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, &black[0]);
3180 checkGLcall("glMaterialfv(GL_SPECULAR");
3182 glMaterialfv(GL_FRONT_AND_BACK, GL_EMISSION, (float*) &This->updateStateBlock->material.Emissive);
3183 checkGLcall("glMaterialfv(GL_EMISSION)");
3184 glMaterialf(GL_FRONT_AND_BACK, GL_SHININESS, This->updateStateBlock->material.Power);
3185 checkGLcall("glMaterialf(GL_SHININESS");
3191 static HRESULT WINAPI IWineD3DDeviceImpl_GetMaterial(IWineD3DDevice *iface, WINED3DMATERIAL* pMaterial) {
3192 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3193 memcpy(pMaterial, &This->updateStateBlock->material, sizeof (WINED3DMATERIAL));
3194 TRACE("(%p) : Diffuse (%f,%f,%f,%f)\n", This, pMaterial->Diffuse.r, pMaterial->Diffuse.g,
3195 pMaterial->Diffuse.b, pMaterial->Diffuse.a);
3196 TRACE("(%p) : Ambient (%f,%f,%f,%f)\n", This, pMaterial->Ambient.r, pMaterial->Ambient.g,
3197 pMaterial->Ambient.b, pMaterial->Ambient.a);
3198 TRACE("(%p) : Specular (%f,%f,%f,%f)\n", This, pMaterial->Specular.r, pMaterial->Specular.g,
3199 pMaterial->Specular.b, pMaterial->Specular.a);
3200 TRACE("(%p) : Emissive (%f,%f,%f,%f)\n", This, pMaterial->Emissive.r, pMaterial->Emissive.g,
3201 pMaterial->Emissive.b, pMaterial->Emissive.a);
3202 TRACE("(%p) : Power (%f)\n", This, pMaterial->Power);
3210 static HRESULT WINAPI IWineD3DDeviceImpl_SetIndices(IWineD3DDevice *iface, IWineD3DIndexBuffer* pIndexData,
3211 UINT BaseVertexIndex) {
3212 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3213 IWineD3DIndexBuffer *oldIdxs;
3215 TRACE("(%p) : Setting to %p, base %d\n", This, pIndexData, BaseVertexIndex);
3216 oldIdxs = This->updateStateBlock->pIndexData;
3218 This->updateStateBlock->changed.indices = TRUE;
3219 This->updateStateBlock->set.indices = TRUE;
3220 This->updateStateBlock->pIndexData = pIndexData;
3221 This->updateStateBlock->baseVertexIndex = BaseVertexIndex;
3223 /* Handle recording of state blocks */
3224 if (This->isRecordingState) {
3225 TRACE("Recording... not performing anything\n");
3229 if (NULL != pIndexData) {
3230 IWineD3DIndexBuffer_AddRef(pIndexData);
3232 if (NULL != oldIdxs) {
3233 IWineD3DIndexBuffer_Release(oldIdxs);
3238 static HRESULT WINAPI IWineD3DDeviceImpl_GetIndices(IWineD3DDevice *iface, IWineD3DIndexBuffer** ppIndexData, UINT* pBaseVertexIndex) {
3239 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3241 *ppIndexData = This->stateBlock->pIndexData;
3243 /* up ref count on ppindexdata */
3245 IWineD3DIndexBuffer_AddRef(*ppIndexData);
3246 *pBaseVertexIndex = This->stateBlock->baseVertexIndex;
3247 TRACE("(%p) index data set to %p + %u\n", This, ppIndexData, This->stateBlock->baseVertexIndex);
3249 TRACE("(%p) No index data set\n", This);
3251 TRACE("Returning %p %d\n", *ppIndexData, *pBaseVertexIndex);
3257 * Get / Set Viewports
3259 static HRESULT WINAPI IWineD3DDeviceImpl_SetViewport(IWineD3DDevice *iface, CONST WINED3DVIEWPORT* pViewport) {
3260 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3262 TRACE("(%p)\n", This);
3263 This->updateStateBlock->changed.viewport = TRUE;
3264 This->updateStateBlock->set.viewport = TRUE;
3265 memcpy(&This->updateStateBlock->viewport, pViewport, sizeof(WINED3DVIEWPORT));
3267 /* Handle recording of state blocks */
3268 if (This->isRecordingState) {
3269 TRACE("Recording... not performing anything\n");
3272 This->viewport_changed = TRUE;
3276 TRACE("(%p) : x=%ld, y=%ld, wid=%ld, hei=%ld, minz=%f, maxz=%f\n", This,
3277 pViewport->X, pViewport->Y, pViewport->Width, pViewport->Height, pViewport->MinZ, pViewport->MaxZ);
3279 glDepthRange(pViewport->MinZ, pViewport->MaxZ);
3280 checkGLcall("glDepthRange");
3281 /* Note: GL requires lower left, DirectX supplies upper left */
3282 /* TODO: replace usage of renderTarget with context management */
3283 glViewport(pViewport->X,
3284 (((IWineD3DSurfaceImpl *)This->renderTarget)->currentDesc.Height - (pViewport->Y + pViewport->Height)),
3285 pViewport->Width, pViewport->Height);
3287 checkGLcall("glViewport");
3295 static HRESULT WINAPI IWineD3DDeviceImpl_GetViewport(IWineD3DDevice *iface, WINED3DVIEWPORT* pViewport) {
3296 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3297 TRACE("(%p)\n", This);
3298 memcpy(pViewport, &This->stateBlock->viewport, sizeof(WINED3DVIEWPORT));
3302 static void renderstate_stencil_twosided(
3303 IWineD3DDeviceImpl *This,
3310 GLint stencilPass ) {
3311 #if 0 /* Don't use OpenGL 2.0 calls for now */
3312 if(GL_EXTCALL(glStencilFuncSeparate) && GL_EXTCALL(glStencilOpSeparate)) {
3313 GL_EXTCALL(glStencilFuncSeparate(face, func, ref, mask));
3314 checkGLcall("glStencilFuncSeparate(...)");
3315 GL_EXTCALL(glStencilOpSeparate(face, stencilFail, depthFail, stencilPass));
3316 checkGLcall("glStencilOpSeparate(...)");
3320 if(GL_SUPPORT(EXT_STENCIL_TWO_SIDE)) {
3321 glEnable(GL_STENCIL_TEST_TWO_SIDE_EXT);
3322 checkGLcall("glEnable(GL_STENCIL_TEST_TWO_SIDE_EXT)");
3323 GL_EXTCALL(glActiveStencilFaceEXT(face));
3324 checkGLcall("glActiveStencilFaceEXT(...)");
3325 glStencilFunc(func, ref, mask);
3326 checkGLcall("glStencilFunc(...)");
3327 glStencilOp(stencilFail, depthFail, stencilPass);
3328 checkGLcall("glStencilOp(...)");
3329 } else if(GL_SUPPORT(ATI_SEPARATE_STENCIL)) {
3330 GL_EXTCALL(glStencilFuncSeparateATI(face, func, ref, mask));
3331 checkGLcall("glStencilFuncSeparateATI(...)");
3332 GL_EXTCALL(glStencilOpSeparateATI(face, stencilFail, depthFail, stencilPass));
3333 checkGLcall("glStencilOpSeparateATI(...)");
3335 ERR("Separate (two sided) stencil not supported on this version of opengl. Caps weren't honored?\n");
3339 static void renderstate_stencil(IWineD3DDeviceImpl *This, D3DRENDERSTATETYPE State, DWORD Value) {
3340 DWORD onesided_enable = FALSE;
3341 DWORD twosided_enable = FALSE;
3342 GLint func = GL_ALWAYS;
3343 GLint func_ccw = GL_ALWAYS;
3346 GLint stencilFail = GL_KEEP;
3347 GLint depthFail = GL_KEEP;
3348 GLint stencilPass = GL_KEEP;
3349 GLint stencilFail_ccw = GL_KEEP;
3350 GLint depthFail_ccw = GL_KEEP;
3351 GLint stencilPass_ccw = GL_KEEP;
3353 if( This->stateBlock->set.renderState[WINED3DRS_STENCILENABLE] )
3354 onesided_enable = This->stateBlock->renderState[WINED3DRS_STENCILENABLE];
3355 if( This->stateBlock->set.renderState[WINED3DRS_TWOSIDEDSTENCILMODE] )
3356 twosided_enable = This->stateBlock->renderState[WINED3DRS_TWOSIDEDSTENCILMODE];
3357 if( This->stateBlock->set.renderState[WINED3DRS_STENCILFUNC] )
3358 if( !( func = CompareFunc(This->stateBlock->renderState[WINED3DRS_STENCILFUNC]) ) )
3360 if( This->stateBlock->set.renderState[WINED3DRS_CCW_STENCILFUNC] )
3361 if( !( func_ccw = CompareFunc(This->stateBlock->renderState[WINED3DRS_CCW_STENCILFUNC]) ) )
3363 if( This->stateBlock->set.renderState[WINED3DRS_STENCILREF] )
3364 ref = This->stateBlock->renderState[WINED3DRS_STENCILREF];
3365 if( This->stateBlock->set.renderState[WINED3DRS_STENCILMASK] )
3366 mask = This->stateBlock->renderState[WINED3DRS_STENCILMASK];
3367 if( This->stateBlock->set.renderState[WINED3DRS_STENCILFAIL] )
3368 stencilFail = StencilOp(This->stateBlock->renderState[WINED3DRS_STENCILFAIL]);
3369 if( This->stateBlock->set.renderState[WINED3DRS_STENCILZFAIL] )
3370 depthFail = StencilOp(This->stateBlock->renderState[WINED3DRS_STENCILZFAIL]);
3371 if( This->stateBlock->set.renderState[WINED3DRS_STENCILPASS] )
3372 stencilPass = StencilOp(This->stateBlock->renderState[WINED3DRS_STENCILPASS]);
3373 if( This->stateBlock->set.renderState[WINED3DRS_CCW_STENCILFAIL] )
3374 stencilFail_ccw = StencilOp(This->stateBlock->renderState[WINED3DRS_CCW_STENCILFAIL]);
3375 if( This->stateBlock->set.renderState[WINED3DRS_CCW_STENCILZFAIL] )
3376 depthFail_ccw = StencilOp(This->stateBlock->renderState[WINED3DRS_CCW_STENCILZFAIL]);
3377 if( This->stateBlock->set.renderState[WINED3DRS_CCW_STENCILPASS] )
3378 stencilPass_ccw = StencilOp(This->stateBlock->renderState[WINED3DRS_CCW_STENCILPASS]);
3380 TRACE("(onesided %ld, twosided %ld, ref %x, mask %x, \
3381 GL_FRONT: func: %x, fail %x, zfail %x, zpass %x \
3382 GL_BACK: func: %x, fail %x, zfail %x, zpass %x )\n",
3383 onesided_enable, twosided_enable, ref, mask,
3384 func, stencilFail, depthFail, stencilPass,
3385 func_ccw, stencilFail_ccw, depthFail_ccw, stencilPass_ccw);
3387 if (twosided_enable) {
3388 renderstate_stencil_twosided(This, GL_FRONT, func, ref, mask, stencilFail, depthFail, stencilPass);
3389 renderstate_stencil_twosided(This, GL_BACK, func_ccw, ref, mask, stencilFail_ccw, depthFail_ccw, stencilPass_ccw);
3391 if (onesided_enable) {
3392 glEnable(GL_STENCIL_TEST);
3393 checkGLcall("glEnable GL_STENCIL_TEST");
3394 glStencilFunc(func, ref, mask);
3395 checkGLcall("glStencilFunc(...)");
3396 glStencilOp(stencilFail, depthFail, stencilPass);
3397 checkGLcall("glStencilOp(...)");
3399 glDisable(GL_STENCIL_TEST);
3400 checkGLcall("glDisable GL_STENCIL_TEST");
3406 * Get / Set Render States
3407 * TODO: Verify against dx9 definitions
3409 static HRESULT WINAPI IWineD3DDeviceImpl_SetRenderState(IWineD3DDevice *iface, D3DRENDERSTATETYPE State, DWORD Value) {
3411 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3412 DWORD OldValue = This->stateBlock->renderState[State];
3414 /* Simple way of referring to either a DWORD or a 4 byte float */
3420 TRACE("(%p)->state = %s(%d), value = %ld\n", This, debug_d3drenderstate(State), State, Value);
3421 This->updateStateBlock->changed.renderState[State] = TRUE;
3422 This->updateStateBlock->set.renderState[State] = TRUE;
3423 This->updateStateBlock->renderState[State] = Value;
3425 /* Handle recording of state blocks */
3426 if (This->isRecordingState) {
3427 TRACE("Recording... not performing anything\n");
3434 case WINED3DRS_FILLMODE :
3435 switch ((D3DFILLMODE) Value) {
3436 case D3DFILL_POINT : glPolygonMode(GL_FRONT_AND_BACK, GL_POINT); break;
3437 case D3DFILL_WIREFRAME : glPolygonMode(GL_FRONT_AND_BACK, GL_LINE); break;
3438 case D3DFILL_SOLID : glPolygonMode(GL_FRONT_AND_BACK, GL_FILL); break;
3440 FIXME("Unrecognized WINED3DRS_FILLMODE value %ld\n", Value);
3442 checkGLcall("glPolygonMode (fillmode)");
3445 case WINED3DRS_LIGHTING :
3447 glEnable(GL_LIGHTING);
3448 checkGLcall("glEnable GL_LIGHTING");
3450 glDisable(GL_LIGHTING);
3451 checkGLcall("glDisable GL_LIGHTING");
3455 case WINED3DRS_ZENABLE :
3456 switch ((D3DZBUFFERTYPE) Value) {
3458 glDisable(GL_DEPTH_TEST);
3459 checkGLcall("glDisable GL_DEPTH_TEST");
3462 glEnable(GL_DEPTH_TEST);
3463 checkGLcall("glEnable GL_DEPTH_TEST");
3466 glEnable(GL_DEPTH_TEST);
3467 checkGLcall("glEnable GL_DEPTH_TEST");
3468 FIXME("W buffer is not well handled\n");
3471 FIXME("Unrecognized D3DZBUFFERTYPE value %ld\n", Value);
3475 case WINED3DRS_CULLMODE :
3477 /* If we are culling "back faces with clockwise vertices" then
3478 set front faces to be counter clockwise and enable culling
3480 switch ((D3DCULL) Value) {
3482 glDisable(GL_CULL_FACE);
3483 checkGLcall("glDisable GL_CULL_FACE");
3486 glEnable(GL_CULL_FACE);
3487 checkGLcall("glEnable GL_CULL_FACE");
3488 if (This->renderUpsideDown) {
3490 checkGLcall("glFrontFace GL_CW");
3492 glFrontFace(GL_CCW);
3493 checkGLcall("glFrontFace GL_CCW");
3495 glCullFace(GL_BACK);
3498 glEnable(GL_CULL_FACE);
3499 checkGLcall("glEnable GL_CULL_FACE");
3500 if (This->renderUpsideDown) {
3501 glFrontFace(GL_CCW);
3502 checkGLcall("glFrontFace GL_CCW");
3505 checkGLcall("glFrontFace GL_CW");
3507 glCullFace(GL_BACK);
3510 FIXME("Unrecognized/Unhandled D3DCULL value %ld\n", Value);
3514 case WINED3DRS_SHADEMODE :
3515 switch ((D3DSHADEMODE) Value) {
3517 glShadeModel(GL_FLAT);
3518 checkGLcall("glShadeModel");
3520 case D3DSHADE_GOURAUD:
3521 glShadeModel(GL_SMOOTH);
3522 checkGLcall("glShadeModel");
3524 case D3DSHADE_PHONG:
3525 FIXME("D3DSHADE_PHONG isn't supported\n");
3528 FIXME("Unrecognized/Unhandled D3DSHADEMODE value %ld\n", Value);
3532 case WINED3DRS_DITHERENABLE :
3534 glEnable(GL_DITHER);
3535 checkGLcall("glEnable GL_DITHER");
3537 glDisable(GL_DITHER);
3538 checkGLcall("glDisable GL_DITHER");
3542 case WINED3DRS_ZWRITEENABLE :
3545 checkGLcall("glDepthMask");
3548 checkGLcall("glDepthMask");
3552 case WINED3DRS_ZFUNC :
3554 int glParm = CompareFunc(Value);
3557 glDepthFunc(glParm);
3558 checkGLcall("glDepthFunc");
3563 case WINED3DRS_AMBIENT :
3566 D3DCOLORTOGLFLOAT4(Value, col);
3567 TRACE("Setting ambient to (%f,%f,%f,%f)\n", col[0], col[1], col[2], col[3]);
3568 glLightModelfv(GL_LIGHT_MODEL_AMBIENT, col);
3569 checkGLcall("glLightModel for MODEL_AMBIENT");
3574 case WINED3DRS_ALPHABLENDENABLE :
3577 checkGLcall("glEnable GL_BLEND");
3579 glDisable(GL_BLEND);
3580 checkGLcall("glDisable GL_BLEND");
3584 case WINED3DRS_SRCBLEND :
3585 case WINED3DRS_DESTBLEND :
3587 int newVal = GL_ZERO;
3589 case D3DBLEND_ZERO : newVal = GL_ZERO; break;
3590 case D3DBLEND_ONE : newVal = GL_ONE; break;
3591 case D3DBLEND_SRCCOLOR : newVal = GL_SRC_COLOR; break;
3592 case D3DBLEND_INVSRCCOLOR : newVal = GL_ONE_MINUS_SRC_COLOR; break;
3593 case D3DBLEND_SRCALPHA : newVal = GL_SRC_ALPHA; break;
3594 case D3DBLEND_INVSRCALPHA : newVal = GL_ONE_MINUS_SRC_ALPHA; break;
3595 case D3DBLEND_DESTALPHA : newVal = GL_DST_ALPHA; break;
3596 case D3DBLEND_INVDESTALPHA : newVal = GL_ONE_MINUS_DST_ALPHA; break;
3597 case D3DBLEND_DESTCOLOR : newVal = GL_DST_COLOR; break;
3598 case D3DBLEND_INVDESTCOLOR : newVal = GL_ONE_MINUS_DST_COLOR; break;
3599 case D3DBLEND_SRCALPHASAT : newVal = GL_SRC_ALPHA_SATURATE; break;
3601 case D3DBLEND_BOTHSRCALPHA : newVal = GL_SRC_ALPHA;
3602 This->srcBlend = newVal;
3603 This->dstBlend = newVal;
3606 case D3DBLEND_BOTHINVSRCALPHA : newVal = GL_ONE_MINUS_SRC_ALPHA;
3607 This->srcBlend = newVal;
3608 This->dstBlend = newVal;
3610 case D3DBLEND_BLENDFACTOR : newVal = GL_CONSTANT_COLOR; break;
3611 case D3DBLEND_INVBLENDFACTOR : newVal = GL_ONE_MINUS_CONSTANT_COLOR; break;
3613 FIXME("Unrecognized src/dest blend value %ld (%d)\n", Value, State);
3616 if (State == WINED3DRS_SRCBLEND) This->srcBlend = newVal;
3617 if (State == WINED3DRS_DESTBLEND) This->dstBlend = newVal;
3618 TRACE("glBlendFunc src=%x, dst=%x\n", This->srcBlend, This->dstBlend);
3619 glBlendFunc(This->srcBlend, This->dstBlend);
3621 checkGLcall("glBlendFunc");
3625 case WINED3DRS_ALPHATESTENABLE :
3626 case WINED3DRS_ALPHAFUNC :
3627 case WINED3DRS_ALPHAREF :
3628 case WINED3DRS_COLORKEYENABLE :
3632 BOOL enable_ckey = FALSE;
3634 IWineD3DSurfaceImpl *surf;
3636 /* Find out if the texture on the first stage has a ckey set */
3637 if(This->stateBlock->textures[0]) {
3638 surf = (IWineD3DSurfaceImpl *) ((IWineD3DTextureImpl *)This->stateBlock->textures[0])->surfaces[0];
3639 if(surf->CKeyFlags & DDSD_CKSRCBLT) enable_ckey = TRUE;
3642 if (This->stateBlock->renderState[WINED3DRS_ALPHATESTENABLE] ||
3643 (This->stateBlock->renderState[WINED3DRS_COLORKEYENABLE] && enable_ckey)) {
3644 glEnable(GL_ALPHA_TEST);
3645 checkGLcall("glEnable GL_ALPHA_TEST");
3647 glDisable(GL_ALPHA_TEST);
3648 checkGLcall("glDisable GL_ALPHA_TEST");
3649 /* Alpha test is disabled, don't bother setting the params - it will happen on the next
3655 if(This->stateBlock->renderState[WINED3DRS_COLORKEYENABLE] && enable_ckey) {
3656 glParm = GL_NOTEQUAL;
3659 ref = ((float) This->stateBlock->renderState[WINED3DRS_ALPHAREF]) / 255.0f;
3660 glParm = CompareFunc(This->stateBlock->renderState[WINED3DRS_ALPHAFUNC]);
3663 This->alphafunc = glParm;
3664 glAlphaFunc(glParm, ref);
3665 checkGLcall("glAlphaFunc");
3670 case WINED3DRS_CLIPPLANEENABLE :
3671 case WINED3DRS_CLIPPING :
3673 /* Ensure we only do the changed clip planes */
3674 DWORD enable = 0xFFFFFFFF;
3675 DWORD disable = 0x00000000;
3677 /* If enabling / disabling all */
3678 if (State == WINED3DRS_CLIPPING) {
3680 enable = This->stateBlock->renderState[WINED3DRS_CLIPPLANEENABLE];
3683 disable = This->stateBlock->renderState[WINED3DRS_CLIPPLANEENABLE];
3687 enable = Value & ~OldValue;
3688 disable = ~Value & OldValue;
3691 if (enable & D3DCLIPPLANE0) { glEnable(GL_CLIP_PLANE0); checkGLcall("glEnable(clip plane 0)"); }
3692 if (enable & D3DCLIPPLANE1) { glEnable(GL_CLIP_PLANE1); checkGLcall("glEnable(clip plane 1)"); }
3693 if (enable & D3DCLIPPLANE2) { glEnable(GL_CLIP_PLANE2); checkGLcall("glEnable(clip plane 2)"); }
3694 if (enable & D3DCLIPPLANE3) { glEnable(GL_CLIP_PLANE3); checkGLcall("glEnable(clip plane 3)"); }
3695 if (enable & D3DCLIPPLANE4) { glEnable(GL_CLIP_PLANE4); checkGLcall("glEnable(clip plane 4)"); }
3696 if (enable & D3DCLIPPLANE5) { glEnable(GL_CLIP_PLANE5); checkGLcall("glEnable(clip plane 5)"); }
3698 if (disable & D3DCLIPPLANE0) { glDisable(GL_CLIP_PLANE0); checkGLcall("glDisable(clip plane 0)"); }
3699 if (disable & D3DCLIPPLANE1) { glDisable(GL_CLIP_PLANE1); checkGLcall("glDisable(clip plane 1)"); }
3700 if (disable & D3DCLIPPLANE2) { glDisable(GL_CLIP_PLANE2); checkGLcall("glDisable(clip plane 2)"); }
3701 if (disable & D3DCLIPPLANE3) { glDisable(GL_CLIP_PLANE3); checkGLcall("glDisable(clip plane 3)"); }
3702 if (disable & D3DCLIPPLANE4) { glDisable(GL_CLIP_PLANE4); checkGLcall("glDisable(clip plane 4)"); }
3703 if (disable & D3DCLIPPLANE5) { glDisable(GL_CLIP_PLANE5); checkGLcall("glDisable(clip plane 5)"); }
3705 /** update clipping status */
3707 This->stateBlock->clip_status.ClipUnion = 0;
3708 This->stateBlock->clip_status.ClipIntersection = 0xFFFFFFFF;
3710 This->stateBlock->clip_status.ClipUnion = 0;
3711 This->stateBlock->clip_status.ClipIntersection = 0;
3716 case WINED3DRS_BLENDOP :
3718 int glParm = GL_FUNC_ADD;
3720 switch ((D3DBLENDOP) Value) {
3721 case D3DBLENDOP_ADD : glParm = GL_FUNC_ADD; break;
3722 case D3DBLENDOP_SUBTRACT : glParm = GL_FUNC_SUBTRACT; break;
3723 case D3DBLENDOP_REVSUBTRACT : glParm = GL_FUNC_REVERSE_SUBTRACT; break;
3724 case D3DBLENDOP_MIN : glParm = GL_MIN; break;
3725 case D3DBLENDOP_MAX : glParm = GL_MAX; break;
3727 FIXME("Unrecognized/Unhandled D3DBLENDOP value %ld\n", Value);
3730 if(GL_SUPPORT(EXT_BLEND_MINMAX)) {
3731 TRACE("glBlendEquation(%x)\n", glParm);
3732 GL_EXTCALL(glBlendEquation(glParm));
3733 checkGLcall("glBlendEquation");
3735 WARN("Unsupported in local OpenGL implementation: glBlendEquation\n");
3740 case WINED3DRS_TEXTUREFACTOR :
3744 /* Note the texture color applies to all textures whereas
3745 GL_TEXTURE_ENV_COLOR applies to active only */
3747 D3DCOLORTOGLFLOAT4(Value, col);
3749 if (!GL_SUPPORT(NV_REGISTER_COMBINERS)) {
3750 /* And now the default texture color as well */
3751 for (i = 0; i < GL_LIMITS(texture_stages); i++) {
3752 /* Note the D3DRS value applies to all textures, but GL has one
3753 per texture, so apply it now ready to be used! */
3754 if (GL_SUPPORT(ARB_MULTITEXTURE)) {
3755 GL_EXTCALL(glActiveTextureARB(GL_TEXTURE0_ARB + i));
3756 checkGLcall("glActiveTextureARB");
3758 FIXME("Program using multiple concurrent textures which this opengl implementation doesn't support\n");
3761 glTexEnvfv(GL_TEXTURE_ENV, GL_TEXTURE_ENV_COLOR, &col[0]);
3762 checkGLcall("glTexEnvfv(GL_TEXTURE_ENV, GL_TEXTURE_ENV_COLOR, color);");
3768 case WINED3DRS_SPECULARENABLE :
3770 /* Originally this used glLightModeli(GL_LIGHT_MODEL_COLOR_CONTROL,GL_SEPARATE_SPECULAR_COLOR)
3771 and (GL_LIGHT_MODEL_COLOR_CONTROL,GL_SINGLE_COLOR) to swap between enabled/disabled
3772 specular color. This is wrong:
3773 Separate specular color means the specular colour is maintained separately, whereas
3774 single color means it is merged in. However in both cases they are being used to
3776 To disable specular color, set it explicitly to black and turn off GL_COLOR_SUM_EXT
3777 NOTE: If not supported don't give FIXMEs the impact is really minimal and very few people are
3781 * If register combiners are enabled, enabling / disabling GL_COLOR_SUM has no effect.
3782 * Instead, we need to setup the FinalCombiner properly.
3784 * The default setup for the FinalCombiner is:
3786 * <variable> <input> <mapping> <usage>
3787 * GL_VARIABLE_A_NV GL_FOG, GL_UNSIGNED_IDENTITY_NV GL_ALPHA
3788 * GL_VARIABLE_B_NV GL_SPARE0_PLUS_SECONDARY_COLOR_NV GL_UNSIGNED_IDENTITY_NV GL_RGB
3789 * GL_VARIABLE_C_NV GL_FOG GL_UNSIGNED_IDENTITY_NV GL_RGB
3790 * GL_VARIABLE_D_NV GL_ZERO GL_UNSIGNED_IDENTITY_NV GL_RGB
3791 * GL_VARIABLE_E_NV GL_ZERO GL_UNSIGNED_IDENTITY_NV GL_RGB
3792 * GL_VARIABLE_F_NV GL_ZERO GL_UNSIGNED_IDENTITY_NV GL_RGB
3793 * GL_VARIABLE_G_NV GL_SPARE0_NV GL_UNSIGNED_IDENTITY_NV GL_ALPHA
3795 * That's pretty much fine as it is, except for variable B, which needs to take
3796 * either GL_SPARE0_PLUS_SECONDARY_COLOR_NV or GL_SPARE0_NV, depending on
3797 * whether WINED3DRS_SPECULARENABLE is enabled or not.
3801 glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, (float*) &This->updateStateBlock->material.Specular);
3802 checkGLcall("glMaterialfv");
3803 if (GL_SUPPORT(EXT_SECONDARY_COLOR)) {
3804 glEnable(GL_COLOR_SUM_EXT);
3806 TRACE("Specular colors cannot be enabled in this version of opengl\n");
3808 checkGLcall("glEnable(GL_COLOR_SUM)");
3810 if (GL_SUPPORT(NV_REGISTER_COMBINERS)) {
3811 GL_EXTCALL(glFinalCombinerInputNV(GL_VARIABLE_B_NV, GL_SPARE0_PLUS_SECONDARY_COLOR_NV, GL_UNSIGNED_IDENTITY_NV, GL_RGB));
3812 checkGLcall("glFinalCombinerInputNV()");
3815 float black[4] = {0.0f, 0.0f, 0.0f, 0.0f};
3817 /* for the case of enabled lighting: */
3818 glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, &black[0]);
3819 checkGLcall("glMaterialfv");
3821 /* for the case of disabled lighting: */
3822 if (GL_SUPPORT(EXT_SECONDARY_COLOR)) {
3823 glDisable(GL_COLOR_SUM_EXT);
3825 TRACE("Specular colors cannot be disabled in this version of opengl\n");
3827 checkGLcall("glDisable(GL_COLOR_SUM)");
3829 if (GL_SUPPORT(NV_REGISTER_COMBINERS)) {
3830 GL_EXTCALL(glFinalCombinerInputNV(GL_VARIABLE_B_NV, GL_SPARE0_NV, GL_UNSIGNED_IDENTITY_NV, GL_RGB));
3831 checkGLcall("glFinalCombinerInputNV()");
3837 case WINED3DRS_STENCILENABLE :
3838 case WINED3DRS_TWOSIDEDSTENCILMODE :
3839 case WINED3DRS_STENCILFUNC :
3840 case WINED3DRS_CCW_STENCILFUNC :
3841 case WINED3DRS_STENCILREF :
3842 case WINED3DRS_STENCILMASK :
3843 case WINED3DRS_STENCILFAIL :
3844 case WINED3DRS_STENCILZFAIL :
3845 case WINED3DRS_STENCILPASS :
3846 case WINED3DRS_CCW_STENCILFAIL :
3847 case WINED3DRS_CCW_STENCILZFAIL :
3848 case WINED3DRS_CCW_STENCILPASS :
3849 renderstate_stencil(This, State, Value);
3851 case WINED3DRS_STENCILWRITEMASK :
3853 glStencilMask(Value);
3854 TRACE("glStencilMask(%lu)\n", Value);
3855 checkGLcall("glStencilMask");
3859 case WINED3DRS_FOGENABLE :
3863 checkGLcall("glEnable GL_FOG");
3866 checkGLcall("glDisable GL_FOG");
3871 case WINED3DRS_RANGEFOGENABLE :
3874 TRACE("Enabled RANGEFOG\n");
3876 TRACE("Disabled RANGEFOG\n");
3881 case WINED3DRS_FOGCOLOR :
3884 D3DCOLORTOGLFLOAT4(Value, col);
3885 /* Set the default alpha blend color */
3886 glFogfv(GL_FOG_COLOR, &col[0]);
3887 checkGLcall("glFog GL_FOG_COLOR");
3891 case WINED3DRS_FOGTABLEMODE :
3892 case WINED3DRS_FOGVERTEXMODE :
3894 /* 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." */
3895 if(This->stateBlock->renderState[WINED3DRS_FOGTABLEMODE] == D3DFOG_NONE) {
3896 glHint(GL_FOG_HINT, GL_FASTEST);
3897 checkGLcall("glHint(GL_FOG_HINT, GL_FASTEST)");
3898 switch (This->stateBlock->renderState[WINED3DRS_FOGVERTEXMODE]) {
3899 /* Processed vertices have their fog factor stored in the specular value. Fall too the none case.
3900 * If we are drawing untransformed vertices atm, d3ddevice_set_ortho will update the fog
3903 if(!This->last_was_rhw) {
3904 glFogi(GL_FOG_MODE, GL_EXP);
3905 checkGLcall("glFogi(GL_FOG_MODE, GL_EXP");
3906 if(GL_SUPPORT(EXT_FOG_COORD)) {
3907 glFogi(GL_FOG_COORDINATE_SOURCE_EXT, GL_FRAGMENT_DEPTH_EXT);
3908 checkGLcall("glFogi(GL_FOG_COORDINATE_SOURCE_EXT, GL_FRAGMENT_DEPTH_EXT");
3909 IWineD3DDevice_SetRenderState(iface, WINED3DRS_FOGSTART, This->stateBlock->renderState[WINED3DRS_FOGSTART]);
3910 IWineD3DDevice_SetRenderState(iface, WINED3DRS_FOGEND, This->stateBlock->renderState[WINED3DRS_FOGEND]);
3916 if(!This->last_was_rhw) {
3917 glFogi(GL_FOG_MODE, GL_EXP2);
3918 checkGLcall("glFogi(GL_FOG_MODE, GL_EXP2");
3919 if(GL_SUPPORT(EXT_FOG_COORD)) {
3920 glFogi(GL_FOG_COORDINATE_SOURCE_EXT, GL_FRAGMENT_DEPTH_EXT);
3921 checkGLcall("glFogi(GL_FOG_COORDINATE_SOURCE_EXT, GL_FRAGMENT_DEPTH_EXT");
3922 IWineD3DDevice_SetRenderState(iface, WINED3DRS_FOGSTART, This->stateBlock->renderState[WINED3DRS_FOGSTART]);
3923 IWineD3DDevice_SetRenderState(iface, WINED3DRS_FOGEND, This->stateBlock->renderState[WINED3DRS_FOGEND]);
3928 case D3DFOG_LINEAR: {
3929 if(!This->last_was_rhw) {
3930 glFogi(GL_FOG_MODE, GL_LINEAR);
3931 checkGLcall("glFogi(GL_FOG_MODE, GL_LINEAR");
3932 if(GL_SUPPORT(EXT_FOG_COORD)) {
3933 glFogi(GL_FOG_COORDINATE_SOURCE_EXT, GL_FRAGMENT_DEPTH_EXT);
3934 checkGLcall("glFogi(GL_FOG_COORDINATE_SOURCE_EXT, GL_FRAGMENT_DEPTH_EXT");
3935 IWineD3DDevice_SetRenderState(iface, WINED3DRS_FOGSTART, This->stateBlock->renderState[WINED3DRS_FOGSTART]);
3936 IWineD3DDevice_SetRenderState(iface, WINED3DRS_FOGEND, This->stateBlock->renderState[WINED3DRS_FOGEND]);
3942 /* Both are none? According to msdn the alpha channel of the specular
3943 * color contains a fog factor. Set it in drawStridedSlow.
3944 * Same happens with Vertexfog on transformed vertices
3946 if(GL_SUPPORT(EXT_FOG_COORD)) {
3947 glFogi(GL_FOG_COORDINATE_SOURCE_EXT, GL_FOG_COORDINATE_EXT);
3948 checkGLcall("glFogi(GL_FOG_COORDINATE_SOURCE_EXT, GL_FOG_COORDINATE_EXT)\n");
3949 glFogi(GL_FOG_MODE, GL_LINEAR);
3950 checkGLcall("glFogi(GL_FOG_MODE, GL_LINEAR)");
3951 glFogf(GL_FOG_START, (float) 0xff);
3952 checkGLcall("glFogfv GL_FOG_START");
3953 glFogf(GL_FOG_END, 0.0);
3954 checkGLcall("glFogfv GL_FOG_END");
3956 /* Disable GL fog, handle this in software in drawStridedSlow */
3958 checkGLcall("glDisable(GL_FOG)");
3962 default: FIXME("Unexpected WINED3DRS_FOGVERTEXMODE %ld\n", This->stateBlock->renderState[WINED3DRS_FOGVERTEXMODE]);
3965 glHint(GL_FOG_HINT, GL_NICEST);
3966 checkGLcall("glHint(GL_FOG_HINT, GL_NICEST)");
3967 switch (This->stateBlock->renderState[WINED3DRS_FOGTABLEMODE]) {
3968 case D3DFOG_EXP: glFogi(GL_FOG_MODE, GL_EXP);
3969 checkGLcall("glFogi(GL_FOG_MODE, GL_EXP");
3970 if(GL_SUPPORT(EXT_FOG_COORD)) {
3971 glFogi(GL_FOG_COORDINATE_SOURCE_EXT, GL_FRAGMENT_DEPTH_EXT);
3972 checkGLcall("glFogi(GL_FOG_COORDINATE_SOURCE_EXT, GL_FRAGMENT_DEPTH_EXT");
3973 IWineD3DDevice_SetRenderState(iface, WINED3DRS_FOGSTART, This->stateBlock->renderState[WINED3DRS_FOGSTART]);
3974 IWineD3DDevice_SetRenderState(iface, WINED3DRS_FOGEND, This->stateBlock->renderState[WINED3DRS_FOGEND]);
3977 case D3DFOG_EXP2: glFogi(GL_FOG_MODE, GL_EXP2);
3978 checkGLcall("glFogi(GL_FOG_MODE, GL_EXP2");
3979 if(GL_SUPPORT(EXT_FOG_COORD)) {
3980 glFogi(GL_FOG_COORDINATE_SOURCE_EXT, GL_FRAGMENT_DEPTH_EXT);
3981 checkGLcall("glFogi(GL_FOG_COORDINATE_SOURCE_EXT, GL_FRAGMENT_DEPTH_EXT");
3982 IWineD3DDevice_SetRenderState(iface, WINED3DRS_FOGSTART, This->stateBlock->renderState[WINED3DRS_FOGSTART]);
3983 IWineD3DDevice_SetRenderState(iface, WINED3DRS_FOGEND, This->stateBlock->renderState[WINED3DRS_FOGEND]);
3986 case D3DFOG_LINEAR: glFogi(GL_FOG_MODE, GL_LINEAR);
3987 checkGLcall("glFogi(GL_FOG_MODE, GL_LINEAR");
3988 if(GL_SUPPORT(EXT_FOG_COORD)) {
3989 glFogi(GL_FOG_COORDINATE_SOURCE_EXT, GL_FRAGMENT_DEPTH_EXT);
3990 checkGLcall("glFogi(GL_FOG_COORDINATE_SOURCE_EXT, GL_FRAGMENT_DEPTH_EXT");
3991 IWineD3DDevice_SetRenderState(iface, WINED3DRS_FOGSTART, This->stateBlock->renderState[WINED3DRS_FOGSTART]);
3992 IWineD3DDevice_SetRenderState(iface, WINED3DRS_FOGEND, This->stateBlock->renderState[WINED3DRS_FOGEND]);
3995 case D3DFOG_NONE: /* Won't happen */
3996 default: FIXME("Unexpected WINED3DRS_FOGTABLEMODE %ld\n", This->stateBlock->renderState[WINED3DRS_FOGTABLEMODE]);
3999 if (GL_SUPPORT(NV_FOG_DISTANCE)) {
4000 glFogi(GL_FOG_DISTANCE_MODE_NV, GL_EYE_PLANE_ABSOLUTE_NV);
4005 case WINED3DRS_FOGSTART :
4008 glFogfv(GL_FOG_START, &tmpvalue.f);
4009 checkGLcall("glFogf(GL_FOG_START, (float) Value)");
4010 TRACE("Fog Start == %f\n", tmpvalue.f);
4014 case WINED3DRS_FOGEND :
4017 glFogfv(GL_FOG_END, &tmpvalue.f);
4018 checkGLcall("glFogf(GL_FOG_END, (float) Value)");
4019 TRACE("Fog End == %f\n", tmpvalue.f);
4023 case WINED3DRS_FOGDENSITY :
4026 glFogfv(GL_FOG_DENSITY, &tmpvalue.f);
4027 checkGLcall("glFogf(GL_FOG_DENSITY, (float) Value)");
4031 case WINED3DRS_VERTEXBLEND :
4033 This->updateStateBlock->vertex_blend = (D3DVERTEXBLENDFLAGS) Value;
4034 TRACE("Vertex Blending state to %ld\n", Value);
4038 case WINED3DRS_TWEENFACTOR :
4041 This->updateStateBlock->tween_factor = tmpvalue.f;
4042 TRACE("Vertex Blending Tween Factor to %f\n", This->updateStateBlock->tween_factor);
4046 case WINED3DRS_INDEXEDVERTEXBLENDENABLE :
4048 TRACE("Indexed Vertex Blend Enable to %ul\n", (BOOL) Value);
4052 case WINED3DRS_COLORVERTEX :
4053 case WINED3DRS_DIFFUSEMATERIALSOURCE :
4054 case WINED3DRS_SPECULARMATERIALSOURCE :
4055 case WINED3DRS_AMBIENTMATERIALSOURCE :
4056 case WINED3DRS_EMISSIVEMATERIALSOURCE :
4058 GLenum Parm = GL_AMBIENT_AND_DIFFUSE;
4060 if (This->stateBlock->renderState[WINED3DRS_COLORVERTEX]) {
4061 TRACE("diff %ld, amb %ld, emis %ld, spec %ld\n",
4062 This->stateBlock->renderState[WINED3DRS_DIFFUSEMATERIALSOURCE],
4063 This->stateBlock->renderState[WINED3DRS_AMBIENTMATERIALSOURCE],
4064 This->stateBlock->renderState[WINED3DRS_EMISSIVEMATERIALSOURCE],
4065 This->stateBlock->renderState[WINED3DRS_SPECULARMATERIALSOURCE]);
4067 if (This->stateBlock->renderState[WINED3DRS_DIFFUSEMATERIALSOURCE] == D3DMCS_COLOR1) {
4068 if (This->stateBlock->renderState[WINED3DRS_AMBIENTMATERIALSOURCE] == D3DMCS_COLOR1) {
4069 Parm = GL_AMBIENT_AND_DIFFUSE;
4073 } else if (This->stateBlock->renderState[WINED3DRS_AMBIENTMATERIALSOURCE] == D3DMCS_COLOR1) {
4075 } else if (This->stateBlock->renderState[WINED3DRS_EMISSIVEMATERIALSOURCE] == D3DMCS_COLOR1) {
4077 } else if (This->stateBlock->renderState[WINED3DRS_SPECULARMATERIALSOURCE] == D3DMCS_COLOR1) {
4084 if (This->tracking_color != DISABLED_TRACKING) This->tracking_color = NEEDS_DISABLE;
4086 This->tracking_color = NEEDS_TRACKING;
4087 This->tracking_parm = Parm;
4091 if (This->tracking_color != DISABLED_TRACKING) This->tracking_color = NEEDS_DISABLE;
4096 case WINED3DRS_LINEPATTERN :
4102 tmppattern.d = Value;
4104 TRACE("Line pattern: repeat %d bits %x\n", tmppattern.lp.wRepeatFactor, tmppattern.lp.wLinePattern);
4106 if (tmppattern.lp.wRepeatFactor) {
4107 glLineStipple(tmppattern.lp.wRepeatFactor, tmppattern.lp.wLinePattern);
4108 checkGLcall("glLineStipple(repeat, linepattern)");
4109 glEnable(GL_LINE_STIPPLE);
4110 checkGLcall("glEnable(GL_LINE_STIPPLE);");
4112 glDisable(GL_LINE_STIPPLE);
4113 checkGLcall("glDisable(GL_LINE_STIPPLE);");
4118 case WINED3DRS_ZBIAS : /* D3D8 only */
4122 TRACE("ZBias value %f\n", tmpvalue.f);
4123 glPolygonOffset(0, -tmpvalue.f);
4124 checkGLcall("glPolygonOffset(0, -Value)");
4125 glEnable(GL_POLYGON_OFFSET_FILL);
4126 checkGLcall("glEnable(GL_POLYGON_OFFSET_FILL);");
4127 glEnable(GL_POLYGON_OFFSET_LINE);
4128 checkGLcall("glEnable(GL_POLYGON_OFFSET_LINE);");
4129 glEnable(GL_POLYGON_OFFSET_POINT);
4130 checkGLcall("glEnable(GL_POLYGON_OFFSET_POINT);");
4132 glDisable(GL_POLYGON_OFFSET_FILL);
4133 checkGLcall("glDisable(GL_POLYGON_OFFSET_FILL);");
4134 glDisable(GL_POLYGON_OFFSET_LINE);
4135 checkGLcall("glDisable(GL_POLYGON_OFFSET_LINE);");
4136 glDisable(GL_POLYGON_OFFSET_POINT);
4137 checkGLcall("glDisable(GL_POLYGON_OFFSET_POINT);");
4142 case WINED3DRS_NORMALIZENORMALS :
4144 glEnable(GL_NORMALIZE);
4145 checkGLcall("glEnable(GL_NORMALIZE);");
4147 glDisable(GL_NORMALIZE);
4148 checkGLcall("glDisable(GL_NORMALIZE);");
4152 case WINED3DRS_POINTSIZE :
4153 /* FIXME: check that pointSize isn't outside glGetFloatv( GL_POINT_SIZE_MAX_ARB, &maxSize ); or -ve */
4155 TRACE("Set point size to %f\n", tmpvalue.f);
4156 glPointSize(tmpvalue.f);
4157 checkGLcall("glPointSize(...);");
4160 case WINED3DRS_POINTSIZE_MIN :
4161 if (GL_SUPPORT(EXT_POINT_PARAMETERS)) {
4163 GL_EXTCALL(glPointParameterfEXT)(GL_POINT_SIZE_MIN_EXT, tmpvalue.f);
4164 checkGLcall("glPointParameterfEXT(...);");
4166 FIXME("WINED3DRS_POINTSIZE_MIN not supported on this opengl\n");
4170 case WINED3DRS_POINTSIZE_MAX :
4171 if (GL_SUPPORT(EXT_POINT_PARAMETERS)) {
4173 GL_EXTCALL(glPointParameterfEXT)(GL_POINT_SIZE_MAX_EXT, tmpvalue.f);
4174 checkGLcall("glPointParameterfEXT(...);");
4176 FIXME("WINED3DRS_POINTSIZE_MAX not supported on this opengl\n");
4180 case WINED3DRS_POINTSCALE_A :
4181 case WINED3DRS_POINTSCALE_B :
4182 case WINED3DRS_POINTSCALE_C :
4183 case WINED3DRS_POINTSCALEENABLE :
4186 * POINTSCALEENABLE controls how point size value is treated. If set to
4187 * true, the point size is scaled with respect to height of viewport.
4188 * When set to false point size is in pixels.
4190 * http://msdn.microsoft.com/library/en-us/directx9_c/point_sprites.asp
4193 /* Default values */
4194 GLfloat att[3] = {1.0f, 0.0f, 0.0f};
4197 * Minimum valid point size for OpenGL is 1.0f. For Direct3D it is 0.0f.
4198 * This means that OpenGL will clamp really small point sizes to 1.0f.
4199 * To correct for this we need to multiply by the scale factor when sizes
4200 * are less than 1.0f. scale_factor = 1.0f / point_size.
4202 GLfloat pointSize = *((float*)&This->stateBlock->renderState[WINED3DRS_POINTSIZE]);
4203 if(pointSize > 0.0f) {
4204 GLfloat scaleFactor;
4206 if(pointSize < 1.0f) {
4207 scaleFactor = pointSize * pointSize;
4212 if(This->stateBlock->renderState[WINED3DRS_POINTSCALEENABLE]) {
4213 att[0] = *((float*)&This->stateBlock->renderState[WINED3DRS_POINTSCALE_A]) /
4214 (This->stateBlock->viewport.Height * This->stateBlock->viewport.Height * scaleFactor);
4215 att[1] = *((float*)&This->stateBlock->renderState[WINED3DRS_POINTSCALE_B]) /
4216 (This->stateBlock->viewport.Height * This->stateBlock->viewport.Height * scaleFactor);
4217 att[2] = *((float*)&This->stateBlock->renderState[WINED3DRS_POINTSCALE_C]) /
4218 (This->stateBlock->viewport.Height * This->stateBlock->viewport.Height * scaleFactor);
4222 if(GL_SUPPORT(ARB_POINT_PARAMETERS)) {
4223 GL_EXTCALL(glPointParameterfvARB)(GL_POINT_DISTANCE_ATTENUATION_ARB, att);
4224 checkGLcall("glPointParameterfvARB(GL_DISTANCE_ATTENUATION_ARB, ...");
4226 else if(GL_SUPPORT(EXT_POINT_PARAMETERS)) {
4227 GL_EXTCALL(glPointParameterfvEXT)(GL_DISTANCE_ATTENUATION_EXT, att);
4228 checkGLcall("glPointParameterfvEXT(GL_DISTANCE_ATTENUATION_EXT, ...");
4230 TRACE("POINT_PARAMETERS not supported in this version of opengl\n");
4234 case WINED3DRS_COLORWRITEENABLE :
4236 TRACE("Color mask: r(%d) g(%d) b(%d) a(%d)\n",
4237 Value & D3DCOLORWRITEENABLE_RED ? 1 : 0,
4238 Value & D3DCOLORWRITEENABLE_GREEN ? 1 : 0,
4239 Value & D3DCOLORWRITEENABLE_BLUE ? 1 : 0,
4240 Value & D3DCOLORWRITEENABLE_ALPHA ? 1 : 0);
4241 glColorMask(Value & D3DCOLORWRITEENABLE_RED ? GL_TRUE : GL_FALSE,
4242 Value & D3DCOLORWRITEENABLE_GREEN ? GL_TRUE : GL_FALSE,
4243 Value & D3DCOLORWRITEENABLE_BLUE ? GL_TRUE : GL_FALSE,
4244 Value & D3DCOLORWRITEENABLE_ALPHA ? GL_TRUE : GL_FALSE);
4245 checkGLcall("glColorMask(...)");
4249 case WINED3DRS_LOCALVIEWER :
4251 GLint state = (Value) ? 1 : 0;
4252 TRACE("Local Viewer Enable to %ul\n", (BOOL) Value);
4253 glLightModeli(GL_LIGHT_MODEL_LOCAL_VIEWER, state);
4257 case WINED3DRS_LASTPIXEL :
4260 TRACE("Last Pixel Drawing Enabled\n");
4262 FIXME("Last Pixel Drawing Disabled, not handled yet\n");
4267 case WINED3DRS_SOFTWAREVERTEXPROCESSING :
4270 TRACE("Software Processing Enabled\n");
4272 TRACE("Software Processing Disabled\n");
4277 /** not supported */
4278 case WINED3DRS_ZVISIBLE :
4281 return WINED3DERR_INVALIDCALL;
4283 case WINED3DRS_POINTSPRITEENABLE :
4285 /* TODO: NV_POINT_SPRITE */
4286 if (!GL_SUPPORT(ARB_POINT_SPRITE)) {
4287 TRACE("Point sprites not supported\n");
4292 * Point sprites are always enabled. Value controls texture coordinate
4293 * replacement mode. Must be set true for point sprites to use
4296 glEnable(GL_POINT_SPRITE_ARB);
4297 checkGLcall("glEnable(GL_POINT_SPRITE_ARB)");
4300 glTexEnvf(GL_POINT_SPRITE_ARB, GL_COORD_REPLACE_ARB, TRUE);
4301 checkGLcall("glTexEnvf(GL_POINT_SPRITE, GL_COORD_REPLACE, TRUE)");
4303 glTexEnvf(GL_POINT_SPRITE_ARB, GL_COORD_REPLACE_ARB, FALSE);
4304 checkGLcall("glTexEnvf(GL_POINT_SPRITE, GL_COORD_REPLACE, FALSE)");
4308 case WINED3DRS_EDGEANTIALIAS :
4311 glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
4313 checkGLcall("glEnable(GL_BLEND)");
4314 glEnable(GL_LINE_SMOOTH);
4315 checkGLcall("glEnable(GL_LINE_SMOOTH)");
4317 if(!This->stateBlock->renderState[WINED3DRS_ALPHABLENDENABLE]) {
4318 glDisable(GL_BLEND);
4319 checkGLcall("glDisable(GL_BLEND)");
4321 glDisable(GL_LINE_SMOOTH);
4322 checkGLcall("glDisable(GL_LINE_SMOOTH)");
4326 case WINED3DRS_WRAP0 :
4327 case WINED3DRS_WRAP1 :
4328 case WINED3DRS_WRAP2 :
4329 case WINED3DRS_WRAP3 :
4330 case WINED3DRS_WRAP4 :
4331 case WINED3DRS_WRAP5 :
4332 case WINED3DRS_WRAP6 :
4333 case WINED3DRS_WRAP7 :
4334 case WINED3DRS_WRAP8 :
4335 case WINED3DRS_WRAP9 :
4336 case WINED3DRS_WRAP10 :
4337 case WINED3DRS_WRAP11 :
4338 case WINED3DRS_WRAP12 :
4339 case WINED3DRS_WRAP13 :
4340 case WINED3DRS_WRAP14 :
4341 case WINED3DRS_WRAP15 :
4343 http://www.cosc.brocku.ca/Offerings/3P98/course/lectures/texture/
4344 http://msdn.microsoft.com/archive/default.asp?url=/archive/en-us/directx9_c/directx/graphics/programmingguide/FixedFunction/Textures/texturewrapping.asp
4345 http://www.gamedev.net/reference/programming/features/rendererdll3/page2.asp
4346 Descussion that ways to turn on WRAPing to solve an opengl conversion problem.
4347 http://www.flipcode.org/cgi-bin/fcmsg.cgi?thread_show=10248
4349 so far as I can tell, wrapping and texture-coordinate generate go hand in hand,
4353 ERR("(%p)->(%s,%ld) Texture wraping not yet supported\n",This, debug_d3drenderstate(State), Value);
4358 case WINED3DRS_MULTISAMPLEANTIALIAS :
4360 if( GL_SUPPORT(ARB_MULTISAMPLE) ) {
4362 glEnable(GL_MULTISAMPLE_ARB);
4363 checkGLcall("glEnable(GL_MULTISAMPLE_ARB)");
4365 glDisable(GL_MULTISAMPLE_ARB);
4366 checkGLcall("glDisable(GL_MULTISAMPLE_ARB)");
4370 ERR("Multisample antialiasing not supported by gl\n");
4376 case WINED3DRS_SCISSORTESTENABLE :
4379 glEnable(GL_SCISSOR_TEST);
4380 checkGLcall("glEnable(GL_SCISSOR_TEST)");
4382 glDisable(GL_SCISSOR_TEST);
4383 checkGLcall("glDisable(GL_SCISSOR_TEST)");
4387 case WINED3DRS_SLOPESCALEDEPTHBIAS :
4391 glEnable(GL_POLYGON_OFFSET_FILL);
4392 checkGLcall("glEnable(GL_POLYGON_OFFSET_FILL)");
4393 glPolygonOffset(tmpvalue.f, *((float*)&This->stateBlock->renderState[WINED3DRS_DEPTHBIAS]));
4394 checkGLcall("glPolygonOffset(...)");
4396 glDisable(GL_POLYGON_OFFSET_FILL);
4397 checkGLcall("glDisable(GL_POLYGON_OFFSET_FILL)");
4401 case WINED3DRS_ANTIALIASEDLINEENABLE :
4404 glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
4406 checkGLcall("glEnable(GL_BLEND)");
4407 glEnable(GL_LINE_SMOOTH);
4408 checkGLcall("glEnable(GL_LINE_SMOOTH)");
4410 glDisable(GL_BLEND);
4411 checkGLcall("glDisable(GL_BLEND)");
4412 glDisable(GL_LINE_SMOOTH);
4413 checkGLcall("glDisable(GL_LINE_SMOOTH)");
4417 case WINED3DRS_DEPTHBIAS :
4421 glEnable(GL_POLYGON_OFFSET_FILL);
4422 checkGLcall("glEnable(GL_POLYGON_OFFSET_FILL)");
4423 glPolygonOffset(*((float*)&This->stateBlock->renderState[WINED3DRS_SLOPESCALEDEPTHBIAS]), tmpvalue.f);
4424 checkGLcall("glPolygonOffset(...)");
4426 glDisable(GL_POLYGON_OFFSET_FILL);
4427 checkGLcall("glDisable(GL_POLYGON_OFFSET_FILL)");
4432 case WINED3DRS_TEXTUREPERSPECTIVE :
4435 glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST);
4437 glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_FASTEST);
4441 case WINED3DRS_STIPPLEDALPHA :
4444 ERR(" Stippled Alpha not supported yet.\n");
4447 case WINED3DRS_ANTIALIAS :
4450 ERR(" Antialias not supported yet.\n");
4454 case WINED3DRS_MULTISAMPLEMASK :
4456 if(0xFFFFFFFF != Value)
4457 ERR("(%p)->(%s,%ld) not yet implemented\n", This, debug_d3drenderstate(State), Value);
4461 case WINED3DRS_PATCHEDGESTYLE :
4463 if(D3DPATCHEDGE_DISCRETE != Value)
4464 ERR("(%p)->(%s,%ld) not yet implemented\n", This, debug_d3drenderstate(State), Value);
4468 case WINED3DRS_PATCHSEGMENTS :
4470 /* available in d3d8 but in d3d9 it was replaced by IDirect3DDevice9::SetNPatchMode */
4472 if(tmpvalue.d != Value)
4473 ERR("(%p)->(%s,%ld) not yet implemented\n", This, debug_d3drenderstate(State), Value);
4477 case WINED3DRS_DEBUGMONITORTOKEN :
4479 /* Only useful for "debug builds". */
4480 if(0xbaadcafe != Value) {
4481 /* MSDN says the default is D3DDMT_ENABLE but our tests confirm 0xbaadcafe is the default. */
4482 /* MSDN says anything other than D3DDMT_ENABLE or DISABLE does not change the state,
4483 * but our tests disagree.
4484 * We do not claim to implement a debugging lib, so do not write an ERR
4486 WARN("(%p)->(%s,%ld) not yet implemented\n", This, debug_d3drenderstate(State), Value);
4491 case WINED3DRS_POSITIONDEGREE :
4493 if(D3DDEGREE_CUBIC != Value)
4494 ERR("(%p)->(%s,%ld) not yet implemented\n", This, debug_d3drenderstate(State), Value);
4498 case WINED3DRS_NORMALDEGREE :
4500 if(D3DDEGREE_LINEAR != Value)
4501 ERR("(%p)->(%s,%ld) not yet implemented\n", This, debug_d3drenderstate(State), Value);
4505 case WINED3DRS_MINTESSELLATIONLEVEL :
4506 case WINED3DRS_MAXTESSELLATIONLEVEL :
4507 case WINED3DRS_ADAPTIVETESS_X :
4508 case WINED3DRS_ADAPTIVETESS_Y :
4509 case WINED3DRS_ADAPTIVETESS_Z :
4510 case WINED3DRS_ADAPTIVETESS_W :
4512 if(This->stateBlock->renderState[WINED3DRS_ENABLEADAPTIVETESSELLATION])
4513 FIXME("(%p)->(%s,%ld) not yet implemented\n", This, debug_d3drenderstate(State), Value);
4515 TRACE("(%p)->(%s,%ld): recording state but WINED3DRS_ENABLEADAPTIVETESSELLATION is not enabled\n", This, debug_d3drenderstate(State), Value);
4519 case WINED3DRS_ENABLEADAPTIVETESSELLATION:
4522 ERR("(%p)->(%s,%ld) not yet implemented\n", This, debug_d3drenderstate(State), Value);
4526 case WINED3DRS_COLORWRITEENABLE1 :
4527 case WINED3DRS_COLORWRITEENABLE2 :
4528 case WINED3DRS_COLORWRITEENABLE3 :
4530 /* depends on WINED3DRS_COLORWRITEENABLE. */
4531 if(0x0000000F != Value)
4532 ERR("(%p)->(%s,%ld) not yet implemented. Missing of cap D3DPMISCCAPS_INDEPENDENTWRITEMASKS wasn't honored?\n", This, debug_d3drenderstate(State), Value);
4536 case WINED3DRS_BLENDFACTOR :
4540 TRACE("Setting BlendFactor to %ld\n", Value);
4542 D3DCOLORTOGLFLOAT4(Value, col);
4543 if (0xFFFFFFFF != Value) {
4545 checkGLcall("glEnable(GL_BLEND)");
4548 glDisable(GL_BLEND);
4549 checkGLcall("glDisable(GL_BLEND)");
4551 glBlendColor (col[0],col[1],col[2],col[3]);
4555 case WINED3DRS_SRGBWRITEENABLE :
4558 ERR("(%p)->(%s,%ld) not yet implemented\n", This, debug_d3drenderstate(State), Value);
4562 case WINED3DRS_SEPARATEALPHABLENDENABLE :
4565 ERR("(%p)->(%s,%ld) not yet implemented. Missing of cap D3DPMISCCAPS_SEPARATEALPHABLEND wasn't honored?\n", This, debug_d3drenderstate(State), Value);
4569 case WINED3DRS_SRCBLENDALPHA :
4570 case WINED3DRS_DESTBLENDALPHA :
4571 case WINED3DRS_BLENDOPALPHA :
4573 if(This->stateBlock->renderState[WINED3DRS_SEPARATEALPHABLENDENABLE])
4574 FIXME("(%p)->(%s,%ld) not yet implemented\n", This, debug_d3drenderstate(State), Value);
4576 TRACE("(%p)->(%s,%ld): recording state but WINED3DRS_SEPARATEALPHABLENDENABLE is not enabled\n", This, debug_d3drenderstate(State), Value);
4581 FIXME("(%p)->(%s,%ld) unknown state\n", This, debug_d3drenderstate(State), Value);
4589 static HRESULT WINAPI IWineD3DDeviceImpl_GetRenderState(IWineD3DDevice *iface, D3DRENDERSTATETYPE State, DWORD *pValue) {
4590 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4591 TRACE("(%p) for State %d = %ld\n", This, State, This->stateBlock->renderState[State]);
4592 *pValue = This->stateBlock->renderState[State];
4597 * Get / Set Sampler States
4598 * TODO: Verify against dx9 definitions
4601 static HRESULT WINAPI IWineD3DDeviceImpl_SetSamplerState(IWineD3DDevice *iface, DWORD Sampler, WINED3DSAMPLERSTATETYPE Type, DWORD Value) {
4602 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4604 * SetSampler is designed to allow for more than the standard up to 8 textures
4605 * and Geforce has stopped supporting more than 6 standard textures in openGL.
4606 * So I have to use ARB for Gforce. (maybe if the sampler > 4 then use ARB?)
4608 * http://developer.nvidia.com/object/General_FAQ.html#t6
4610 * There are two new settings for GForce
4612 * GL_MAX_TEXTURE_IMAGE_UNITS_ARB
4613 * and the texture one:
4614 * GL_MAX_TEXTURE_COORDS_ARB.
4615 * Ok GForce say it's ok to use glTexParameter/glGetTexParameter(...).
4617 /** NOTE: States are appled in IWineD3DBaseTextre ApplyStateChanges and IWineD3DDevice SetupTextureStates**/
4618 if(Sampler > GL_LIMITS(sampler_stages) || Sampler < 0 || Type > WINED3D_HIGHEST_SAMPLER_STATE || Type < 0) {
4619 FIXME("sampler %ld type %s(%u) is out of range [max_samplers=%d, highest_state=%d]\n",
4620 Sampler, debug_d3dsamplerstate(Type), Type, GL_LIMITS(sampler_stages), WINED3D_HIGHEST_SAMPLER_STATE);
4621 return WINED3DERR_INVALIDCALL;
4624 TRACE("(%p) : Sampler=%ld, Type=%s(%d), Value=%ld\n", This, Sampler,
4625 debug_d3dsamplerstate(Type), Type, Value);
4626 This->updateStateBlock->samplerState[Sampler][Type] = Value;
4627 This->updateStateBlock->set.samplerState[Sampler][Type] = Value;
4628 This->updateStateBlock->changed.samplerState[Sampler][Type] = Value;
4630 /* Handle recording of state blocks */
4631 if (This->isRecordingState) {
4632 TRACE("Recording... not performing anything\n");
4639 static HRESULT WINAPI IWineD3DDeviceImpl_GetSamplerState(IWineD3DDevice *iface, DWORD Sampler, WINED3DSAMPLERSTATETYPE Type, DWORD* Value) {
4640 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4641 /** TODO: check that sampler is in range **/
4642 *Value = This->updateStateBlock->samplerState[Sampler][Type];
4643 TRACE("(%p) : Sampler %ld Type %u Returning %ld\n", This, Sampler, Type, *Value);
4648 static HRESULT WINAPI IWineD3DDeviceImpl_SetScissorRect(IWineD3DDevice *iface, CONST RECT* pRect) {
4649 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4652 /** FIXME: Windows uses a top,left origin openGL uses a bottom Right? **/
4653 TRACE("(%p)Setting new Scissor Rect to %ld:%ld-%ld:%ld\n", This, pRect->left, pRect->top, pRect->right, pRect->bottom);
4654 glScissor(pRect->left, pRect->top, pRect->right - pRect->left, pRect->bottom - pRect->top);
4660 static HRESULT WINAPI IWineD3DDeviceImpl_GetScissorRect(IWineD3DDevice *iface, RECT* pRect) {
4661 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4662 GLint scissorBox[4];
4665 /** FIXME: Windows uses a top,left origin openGL uses a bottom Right? **/
4666 glGetIntegerv(GL_SCISSOR_BOX, scissorBox);
4667 pRect->left = scissorBox[0];
4668 pRect->top = scissorBox[1];
4669 pRect->right = scissorBox[0] + scissorBox[2];
4670 pRect->bottom = scissorBox[1] + scissorBox[3];
4671 TRACE("(%p)Returning a Scissor Rect of %ld:%ld-%ld:%ld\n", This, pRect->left, pRect->top, pRect->right, pRect->bottom);
4676 static HRESULT WINAPI IWineD3DDeviceImpl_SetVertexDeclaration(IWineD3DDevice* iface, IWineD3DVertexDeclaration* pDecl) {
4677 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *) iface;
4678 IWineD3DVertexDeclaration *oldDecl = This->updateStateBlock->vertexDecl;
4680 TRACE("(%p) : pDecl=%p\n", This, pDecl);
4682 This->updateStateBlock->vertexDecl = pDecl;
4683 This->updateStateBlock->changed.vertexDecl = TRUE;
4684 This->updateStateBlock->set.vertexDecl = TRUE;
4686 if (This->isRecordingState) {
4687 TRACE("Recording... not performing anything\n");
4690 if (NULL != pDecl) {
4691 IWineD3DVertexDeclaration_AddRef(pDecl);
4693 if (NULL != oldDecl) {
4694 IWineD3DVertexDeclaration_Release(oldDecl);
4699 static HRESULT WINAPI IWineD3DDeviceImpl_GetVertexDeclaration(IWineD3DDevice* iface, IWineD3DVertexDeclaration** ppDecl) {
4700 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4702 TRACE("(%p) : ppDecl=%p\n", This, ppDecl);
4704 *ppDecl = This->stateBlock->vertexDecl;
4705 if (NULL != *ppDecl) IWineD3DVertexDeclaration_AddRef(*ppDecl);
4709 static HRESULT WINAPI IWineD3DDeviceImpl_SetVertexShader(IWineD3DDevice *iface, IWineD3DVertexShader* pShader) {
4710 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4711 IWineD3DVertexShader* oldShader = This->updateStateBlock->vertexShader;
4713 This->updateStateBlock->vertexShader = pShader;
4714 This->updateStateBlock->changed.vertexShader = TRUE;
4715 This->updateStateBlock->set.vertexShader = TRUE;
4717 if (This->isRecordingState) {
4718 TRACE("Recording... not performing anything\n");
4721 if (NULL != pShader) {
4722 IWineD3DVertexShader_AddRef(pShader);
4724 if (NULL != oldShader) {
4725 IWineD3DVertexShader_Release(oldShader);
4728 TRACE("(%p) : setting pShader(%p)\n", This, pShader);
4730 * TODO: merge HAL shaders context switching from prototype
4735 static HRESULT WINAPI IWineD3DDeviceImpl_GetVertexShader(IWineD3DDevice *iface, IWineD3DVertexShader** ppShader) {
4736 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4738 if (NULL == ppShader) {
4739 return WINED3DERR_INVALIDCALL;
4741 *ppShader = This->stateBlock->vertexShader;
4742 if( NULL != *ppShader)
4743 IWineD3DVertexShader_AddRef(*ppShader);
4745 TRACE("(%p) : returning %p\n", This, *ppShader);
4749 static HRESULT WINAPI IWineD3DDeviceImpl_SetVertexShaderConstantB(
4750 IWineD3DDevice *iface,
4752 CONST BOOL *srcData,
4755 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4756 int i, cnt = min(count, MAX_CONST_B - start);
4758 TRACE("(iface %p, srcData %p, start %d, count %d)\n",
4759 iface, srcData, start, count);
4761 if (srcData == NULL || cnt < 0)
4762 return WINED3DERR_INVALIDCALL;
4764 memcpy(&This->updateStateBlock->vertexShaderConstantB[start], srcData, cnt * sizeof(BOOL));
4765 for (i = 0; i < cnt; i++)
4766 TRACE("Set BOOL constant %u to %s\n", start + i, srcData[i]? "true":"false");
4768 for (i = start; i < cnt + start; ++i) {
4769 This->updateStateBlock->changed.vertexShaderConstantsB[i] = TRUE;
4770 This->updateStateBlock->set.vertexShaderConstantsB[i] = TRUE;
4776 static HRESULT WINAPI IWineD3DDeviceImpl_GetVertexShaderConstantB(
4777 IWineD3DDevice *iface,
4782 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4783 int cnt = min(count, MAX_CONST_B - start);
4785 TRACE("(iface %p, dstData %p, start %d, count %d)\n",
4786 iface, dstData, start, count);
4788 if (dstData == NULL || cnt < 0)
4789 return WINED3DERR_INVALIDCALL;
4791 memcpy(dstData, &This->stateBlock->vertexShaderConstantB[start], cnt * sizeof(BOOL));
4795 static HRESULT WINAPI IWineD3DDeviceImpl_SetVertexShaderConstantI(
4796 IWineD3DDevice *iface,
4801 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4802 int i, cnt = min(count, MAX_CONST_I - start);
4804 TRACE("(iface %p, srcData %p, start %d, count %d)\n",
4805 iface, srcData, start, count);
4807 if (srcData == NULL || cnt < 0)
4808 return WINED3DERR_INVALIDCALL;
4810 memcpy(&This->updateStateBlock->vertexShaderConstantI[start * 4], srcData, cnt * sizeof(int) * 4);
4811 for (i = 0; i < cnt; i++)
4812 TRACE("Set INT constant %u to { %d, %d, %d, %d }\n", start + i,
4813 srcData[i*4], srcData[i*4+1], srcData[i*4+2], srcData[i*4+3]);
4815 for (i = start; i < cnt + start; ++i) {
4816 This->updateStateBlock->changed.vertexShaderConstantsI[i] = TRUE;
4817 This->updateStateBlock->set.vertexShaderConstantsI[i] = TRUE;
4823 static HRESULT WINAPI IWineD3DDeviceImpl_GetVertexShaderConstantI(
4824 IWineD3DDevice *iface,
4829 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4830 int cnt = min(count, MAX_CONST_I - start);
4832 TRACE("(iface %p, dstData %p, start %d, count %d)\n",
4833 iface, dstData, start, count);
4835 if (dstData == NULL || ((signed int) MAX_CONST_I - (signed int) start) <= (signed int) 0)
4836 return WINED3DERR_INVALIDCALL;
4838 memcpy(dstData, &This->stateBlock->vertexShaderConstantI[start * 4], cnt * sizeof(int) * 4);
4842 static HRESULT WINAPI IWineD3DDeviceImpl_SetVertexShaderConstantF(
4843 IWineD3DDevice *iface,
4845 CONST float *srcData,
4848 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4849 int i, cnt = min(count, GL_LIMITS(vshader_constantsF) - start);
4851 TRACE("(iface %p, srcData %p, start %d, count %d)\n",
4852 iface, srcData, start, count);
4854 if (srcData == NULL || ((signed int) GL_LIMITS(vshader_constantsF) - (signed int) start) <= (signed int) 0)
4855 return WINED3DERR_INVALIDCALL;
4857 memcpy(&This->updateStateBlock->vertexShaderConstantF[start * 4], srcData, cnt * sizeof(float) * 4);
4858 for (i = 0; i < cnt; i++)
4859 TRACE("Set FLOAT constant %u to { %f, %f, %f, %f }\n", start + i,
4860 srcData[i*4], srcData[i*4+1], srcData[i*4+2], srcData[i*4+3]);
4862 for (i = start; i < cnt + start; ++i) {
4863 if (!This->updateStateBlock->set.vertexShaderConstantsF[i]) {
4864 constant_entry *ptr = HeapAlloc(GetProcessHeap(), 0, sizeof(constant_entry));
4866 list_add_head(&This->updateStateBlock->set_vconstantsF, &ptr->entry);
4867 This->updateStateBlock->set.vertexShaderConstantsF[i] = TRUE;
4869 This->updateStateBlock->changed.vertexShaderConstantsF[i] = TRUE;
4875 static HRESULT WINAPI IWineD3DDeviceImpl_GetVertexShaderConstantF(
4876 IWineD3DDevice *iface,
4881 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4882 int cnt = min(count, GL_LIMITS(vshader_constantsF) - start);
4884 TRACE("(iface %p, dstData %p, start %d, count %d)\n",
4885 iface, dstData, start, count);
4887 if (dstData == NULL || cnt < 0)
4888 return WINED3DERR_INVALIDCALL;
4890 memcpy(dstData, &This->stateBlock->vertexShaderConstantF[start * 4], cnt * sizeof(float) * 4);
4894 static HRESULT WINAPI IWineD3DDeviceImpl_SetPixelShader(IWineD3DDevice *iface, IWineD3DPixelShader *pShader) {
4895 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4896 IWineD3DPixelShader *oldShader = This->updateStateBlock->pixelShader;
4897 This->updateStateBlock->pixelShader = pShader;
4898 This->updateStateBlock->changed.pixelShader = TRUE;
4899 This->updateStateBlock->set.pixelShader = TRUE;
4901 /* Handle recording of state blocks */
4902 if (This->isRecordingState) {
4903 TRACE("Recording... not performing anything\n");
4906 if (NULL != pShader) {
4907 IWineD3DPixelShader_AddRef(pShader);
4909 if (NULL != oldShader) {
4910 IWineD3DPixelShader_Release(oldShader);
4913 TRACE("(%p) : setting pShader(%p)\n", This, pShader);
4915 * TODO: merge HAL shaders context switching from prototype
4920 static HRESULT WINAPI IWineD3DDeviceImpl_GetPixelShader(IWineD3DDevice *iface, IWineD3DPixelShader **ppShader) {
4921 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4923 if (NULL == ppShader) {
4924 WARN("(%p) : PShader is NULL, returning INVALIDCALL\n", This);
4925 return WINED3DERR_INVALIDCALL;
4928 *ppShader = This->stateBlock->pixelShader;
4929 if (NULL != *ppShader) {
4930 IWineD3DPixelShader_AddRef(*ppShader);
4932 TRACE("(%p) : returning %p\n", This, *ppShader);
4936 static HRESULT WINAPI IWineD3DDeviceImpl_SetPixelShaderConstantB(
4937 IWineD3DDevice *iface,
4939 CONST BOOL *srcData,
4942 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4943 int i, cnt = min(count, MAX_CONST_B - start);
4945 TRACE("(iface %p, srcData %p, start %d, count %d)\n",
4946 iface, srcData, start, count);
4948 if (srcData == NULL || cnt < 0)
4949 return WINED3DERR_INVALIDCALL;
4951 memcpy(&This->updateStateBlock->pixelShaderConstantB[start], srcData, cnt * sizeof(BOOL));
4952 for (i = 0; i < cnt; i++)
4953 TRACE("Set BOOL constant %u to %s\n", start + i, srcData[i]? "true":"false");
4955 for (i = start; i < cnt + start; ++i) {
4956 This->updateStateBlock->changed.pixelShaderConstantsB[i] = TRUE;
4957 This->updateStateBlock->set.pixelShaderConstantsB[i] = TRUE;
4963 static HRESULT WINAPI IWineD3DDeviceImpl_GetPixelShaderConstantB(
4964 IWineD3DDevice *iface,
4969 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4970 int cnt = min(count, MAX_CONST_B - start);
4972 TRACE("(iface %p, dstData %p, start %d, count %d)\n",
4973 iface, dstData, start, count);
4975 if (dstData == NULL || cnt < 0)
4976 return WINED3DERR_INVALIDCALL;
4978 memcpy(dstData, &This->stateBlock->pixelShaderConstantB[start], cnt * sizeof(BOOL));
4982 static HRESULT WINAPI IWineD3DDeviceImpl_SetPixelShaderConstantI(
4983 IWineD3DDevice *iface,
4988 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4989 int i, cnt = min(count, MAX_CONST_I - start);
4991 TRACE("(iface %p, srcData %p, start %d, count %d)\n",
4992 iface, srcData, start, count);
4994 if (srcData == NULL || cnt < 0)
4995 return WINED3DERR_INVALIDCALL;
4997 memcpy(&This->updateStateBlock->pixelShaderConstantI[start * 4], srcData, cnt * sizeof(int) * 4);
4998 for (i = 0; i < cnt; i++)
4999 TRACE("Set INT constant %u to { %d, %d, %d, %d }\n", start + i,
5000 srcData[i*4], srcData[i*4+1], srcData[i*4+2], srcData[i*4+3]);
5002 for (i = start; i < cnt + start; ++i) {
5003 This->updateStateBlock->changed.pixelShaderConstantsI[i] = TRUE;
5004 This->updateStateBlock->set.pixelShaderConstantsI[i] = TRUE;
5010 static HRESULT WINAPI IWineD3DDeviceImpl_GetPixelShaderConstantI(
5011 IWineD3DDevice *iface,
5016 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5017 int cnt = min(count, MAX_CONST_I - start);
5019 TRACE("(iface %p, dstData %p, start %d, count %d)\n",
5020 iface, dstData, start, count);
5022 if (dstData == NULL || cnt < 0)
5023 return WINED3DERR_INVALIDCALL;
5025 memcpy(dstData, &This->stateBlock->pixelShaderConstantI[start * 4], cnt * sizeof(int) * 4);
5029 static HRESULT WINAPI IWineD3DDeviceImpl_SetPixelShaderConstantF(
5030 IWineD3DDevice *iface,
5032 CONST float *srcData,
5035 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5036 int i, cnt = min(count, GL_LIMITS(pshader_constantsF) - start);
5038 TRACE("(iface %p, srcData %p, start %d, count %d)\n",
5039 iface, srcData, start, count);
5041 if (srcData == NULL || cnt < 0)
5042 return WINED3DERR_INVALIDCALL;
5044 memcpy(&This->updateStateBlock->pixelShaderConstantF[start * 4], srcData, cnt * sizeof(float) * 4);
5045 for (i = 0; i < cnt; i++)
5046 TRACE("Set FLOAT constant %u to { %f, %f, %f, %f }\n", start + i,
5047 srcData[i*4], srcData[i*4+1], srcData[i*4+2], srcData[i*4+3]);
5049 for (i = start; i < cnt + start; ++i) {
5050 if (!This->updateStateBlock->set.pixelShaderConstantsF[i]) {
5051 constant_entry *ptr = HeapAlloc(GetProcessHeap(), 0, sizeof(constant_entry));
5053 list_add_head(&This->updateStateBlock->set_pconstantsF, &ptr->entry);
5054 This->updateStateBlock->set.pixelShaderConstantsF[i] = TRUE;
5056 This->updateStateBlock->changed.pixelShaderConstantsF[i] = TRUE;
5062 static HRESULT WINAPI IWineD3DDeviceImpl_GetPixelShaderConstantF(
5063 IWineD3DDevice *iface,
5068 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5069 int cnt = min(count, GL_LIMITS(pshader_constantsF) - start);
5071 TRACE("(iface %p, dstData %p, start %d, count %d)\n",
5072 iface, dstData, start, count);
5074 if (dstData == NULL || cnt < 0)
5075 return WINED3DERR_INVALIDCALL;
5077 memcpy(dstData, &This->stateBlock->pixelShaderConstantF[start * 4], cnt * sizeof(float) * 4);
5081 #define copy_and_next(dest, src, size) memcpy(dest, src, size); dest += (size)
5083 process_vertices_strided(IWineD3DDeviceImpl *This, DWORD dwDestIndex, DWORD dwCount, WineDirect3DVertexStridedData *lpStrideData, DWORD SrcFVF, IWineD3DVertexBufferImpl *dest, DWORD dwFlags) {
5084 char *dest_ptr, *dest_conv = NULL;
5086 DWORD DestFVF = dest->fvf;
5088 D3DMATRIX mat, proj_mat, view_mat, world_mat;
5092 if (SrcFVF & D3DFVF_NORMAL) {
5093 WARN(" lighting state not saved yet... Some strange stuff may happen !\n");
5096 if ( (SrcFVF & D3DFVF_POSITION_MASK) != D3DFVF_XYZ) {
5097 ERR("Source has no position mask\n");
5098 return WINED3DERR_INVALIDCALL;
5101 /* We might access VBOs from this code, so hold the lock */
5104 if (dest->resource.allocatedMemory == NULL) {
5105 /* This may happen if we do direct locking into a vbo. Unlikely,
5106 * but theoretically possible(ddraw processvertices test)
5108 dest->resource.allocatedMemory = HeapAlloc(GetProcessHeap(), 0, dest->resource.size);
5109 if(!dest->resource.allocatedMemory) {
5111 ERR("Out of memory\n");
5112 return E_OUTOFMEMORY;
5116 GL_EXTCALL(glBindBufferARB(GL_ARRAY_BUFFER_ARB, dest->vbo));
5117 checkGLcall("glBindBufferARB");
5118 src = GL_EXTCALL(glMapBufferARB(GL_ARRAY_BUFFER_ARB, GL_READ_ONLY_ARB));
5120 memcpy(dest->resource.allocatedMemory, src, dest->resource.size);
5122 GL_EXTCALL(glUnmapBufferARB(GL_ARRAY_BUFFER_ARB));
5123 checkGLcall("glUnmapBufferARB");
5127 /* Get a pointer into the destination vbo(create one if none exists) and
5128 * write correct opengl data into it. It's cheap and allows us to run drawStridedFast
5130 if(!dest->vbo && GL_SUPPORT(ARB_VERTEX_BUFFER_OBJECT)) {
5135 GL_EXTCALL(glBindBufferARB(GL_ARRAY_BUFFER_ARB, dest->vbo));
5136 dest_conv = GL_EXTCALL(glMapBufferARB(GL_ARRAY_BUFFER_ARB, GL_WRITE_ONLY_ARB));
5138 ERR("glMapBuffer failed\n");
5139 /* Continue without storing converted vertices */
5144 * a) D3DRS_CLIPPING is enabled
5145 * b) WINED3DVOP_CLIP is passed
5147 if(This->stateBlock->renderState[WINED3DRS_CLIPPING]) {
5148 static BOOL warned = FALSE;
5150 * The clipping code is not quite correct. Some things need
5151 * to be checked against IDirect3DDevice3 (!), d3d8 and d3d9,
5152 * so disable clipping for now.
5153 * (The graphics in Half-Life are broken, and my processvertices
5154 * test crashes with IDirect3DDevice3)
5160 FIXME("Clipping is broken and disabled for now\n");
5162 } else doClip = FALSE;
5163 dest_ptr = ((char *) dest->resource.allocatedMemory) + dwDestIndex * get_flexible_vertex_size(DestFVF);
5165 dest_conv = ((char *) dest_conv) + dwDestIndex * get_flexible_vertex_size(DestFVF);
5168 IWineD3DDevice_GetTransform( (IWineD3DDevice *) This,
5171 IWineD3DDevice_GetTransform( (IWineD3DDevice *) This,
5172 WINED3DTS_PROJECTION,
5174 IWineD3DDevice_GetTransform( (IWineD3DDevice *) This,
5175 WINED3DTS_WORLDMATRIX(0),
5178 TRACE("View mat:\n");
5179 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); \
5180 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); \
5181 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); \
5182 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); \
5184 TRACE("Proj mat:\n");
5185 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); \
5186 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); \
5187 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); \
5188 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); \
5190 TRACE("World mat:\n");
5191 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); \
5192 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); \
5193 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); \
5194 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); \
5196 /* Get the viewport */
5197 IWineD3DDevice_GetViewport( (IWineD3DDevice *) This, &vp);
5198 TRACE("Viewport: X=%ld, Y=%ld, Width=%ld, Height=%ld, MinZ=%f, MaxZ=%f\n",
5199 vp.X, vp.Y, vp.Width, vp.Height, vp.MinZ, vp.MaxZ);
5201 multiply_matrix(&mat,&view_mat,&world_mat);
5202 multiply_matrix(&mat,&proj_mat,&mat);
5204 numTextures = (DestFVF & D3DFVF_TEXCOUNT_MASK) >> D3DFVF_TEXCOUNT_SHIFT;
5206 for (i = 0; i < dwCount; i+= 1) {
5207 unsigned int tex_index;
5209 if ( ((DestFVF & D3DFVF_POSITION_MASK) == D3DFVF_XYZ ) ||
5210 ((DestFVF & D3DFVF_POSITION_MASK) == D3DFVF_XYZRHW ) ) {
5211 /* The position first */
5213 (float *) (((char *) lpStrideData->u.s.position.lpData) + i * lpStrideData->u.s.position.dwStride);
5215 TRACE("In: ( %06.2f %06.2f %06.2f )\n", p[0], p[1], p[2]);
5217 /* Multiplication with world, view and projection matrix */
5218 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);
5219 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);
5220 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);
5221 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);
5223 TRACE("x=%f y=%f z=%f rhw=%f\n", x, y, z, rhw);
5225 /* WARNING: The following things are taken from d3d7 and were not yet checked
5226 * against d3d8 or d3d9!
5229 /* Clipping conditions: From
5230 * http://msdn.microsoft.com/archive/default.asp?url=/archive/en-us/directx9_c/directx/graphics/programmingguide/fixedfunction/viewportsclipping/clippingvolumes.asp
5232 * A vertex is clipped if it does not match the following requirements
5236 * 0 < rhw ( Not in d3d7, but tested in d3d7)
5238 * If clipping is on is determined by the D3DVOP_CLIP flag in D3D7, and
5239 * by the D3DRS_CLIPPING in D3D9(according to the msdn, not checked)
5244 ( (-rhw -eps < x) && (-rhw -eps < y) && ( -eps < z) &&
5245 (x <= rhw + eps) && (y <= rhw + eps ) && (z <= rhw + eps) &&
5248 /* "Normal" viewport transformation (not clipped)
5249 * 1) The values are divided by rhw
5250 * 2) The y axis is negative, so multiply it with -1
5251 * 3) Screen coordinates go from -(Width/2) to +(Width/2) and
5252 * -(Height/2) to +(Height/2). The z range is MinZ to MaxZ
5253 * 4) Multiply x with Width/2 and add Width/2
5254 * 5) The same for the height
5255 * 6) Add the viewpoint X and Y to the 2D coordinates and
5256 * The minimum Z value to z
5257 * 7) rhw = 1 / rhw Reciprocal of Homogeneous W....
5259 * Well, basically it's simply a linear transformation into viewport
5271 z *= vp.MaxZ - vp.MinZ;
5273 x += vp.Width / 2 + vp.X;
5274 y += vp.Height / 2 + vp.Y;
5279 /* That vertex got clipped
5280 * Contrary to OpenGL it is not dropped completely, it just
5281 * undergoes a different calculation.
5283 TRACE("Vertex got clipped\n");
5290 /* Msdn mentions that Direct3D9 keeps a list of clipped vertices
5291 * outside of the main vertex buffer memory. That needs some more
5296 TRACE("Writing (%f %f %f) %f\n", x, y, z, rhw);
5299 ( (float *) dest_ptr)[0] = x;
5300 ( (float *) dest_ptr)[1] = y;
5301 ( (float *) dest_ptr)[2] = z;
5302 ( (float *) dest_ptr)[3] = rhw; /* SIC, see ddraw test! */
5304 dest_ptr += 3 * sizeof(float);
5306 if((DestFVF & D3DFVF_POSITION_MASK) == D3DFVF_XYZRHW) {
5307 dest_ptr += sizeof(float);
5312 ( (float *) dest_conv)[0] = x * w;
5313 ( (float *) dest_conv)[1] = y * w;
5314 ( (float *) dest_conv)[2] = z * w;
5315 ( (float *) dest_conv)[3] = w;
5317 dest_conv += 3 * sizeof(float);
5319 if((DestFVF & D3DFVF_POSITION_MASK) == D3DFVF_XYZRHW) {
5320 dest_conv += sizeof(float);
5324 if (DestFVF & D3DFVF_PSIZE) {
5325 dest_ptr += sizeof(DWORD);
5326 if(dest_conv) dest_conv += sizeof(DWORD);
5328 if (DestFVF & D3DFVF_NORMAL) {
5330 (float *) (((float *) lpStrideData->u.s.normal.lpData) + i * lpStrideData->u.s.normal.dwStride);
5331 /* AFAIK this should go into the lighting information */
5332 FIXME("Didn't expect the destination to have a normal\n");
5333 copy_and_next(dest_ptr, normal, 3 * sizeof(float));
5335 copy_and_next(dest_conv, normal, 3 * sizeof(float));
5339 if (DestFVF & D3DFVF_DIFFUSE) {
5341 (DWORD *) (((char *) lpStrideData->u.s.diffuse.lpData) + i * lpStrideData->u.s.diffuse.dwStride);
5343 static BOOL warned = FALSE;
5346 ERR("No diffuse color in source, but destination has one\n");
5350 *( (DWORD *) dest_ptr) = 0xffffffff;
5351 dest_ptr += sizeof(DWORD);
5354 *( (DWORD *) dest_conv) = 0xffffffff;
5355 dest_conv += sizeof(DWORD);
5359 copy_and_next(dest_ptr, color_d, sizeof(DWORD));
5361 *( (DWORD *) dest_conv) = (*color_d & 0xff00ff00) ; /* Alpha + green */
5362 *( (DWORD *) dest_conv) |= (*color_d & 0x00ff0000) >> 16; /* Red */
5363 *( (DWORD *) dest_conv) |= (*color_d & 0xff0000ff) << 16; /* Blue */
5364 dest_conv += sizeof(DWORD);
5369 if (DestFVF & D3DFVF_SPECULAR) {
5370 /* What's the color value in the feedback buffer? */
5372 (DWORD *) (((char *) lpStrideData->u.s.specular.lpData) + i * lpStrideData->u.s.specular.dwStride);
5374 static BOOL warned = FALSE;
5377 ERR("No specular color in source, but destination has one\n");
5381 *( (DWORD *) dest_ptr) = 0xFF000000;
5382 dest_ptr += sizeof(DWORD);
5385 *( (DWORD *) dest_conv) = 0xFF000000;
5386 dest_conv += sizeof(DWORD);
5390 copy_and_next(dest_ptr, color_s, sizeof(DWORD));
5392 *( (DWORD *) dest_conv) = (*color_s & 0xff00ff00) ; /* Alpha + green */
5393 *( (DWORD *) dest_conv) |= (*color_s & 0x00ff0000) >> 16; /* Red */
5394 *( (DWORD *) dest_conv) |= (*color_s & 0xff0000ff) << 16; /* Blue */
5395 dest_conv += sizeof(DWORD);
5400 for (tex_index = 0; tex_index < numTextures; tex_index++) {
5402 (float *) (((char *) lpStrideData->u.s.texCoords[tex_index].lpData) +
5403 i * lpStrideData->u.s.texCoords[tex_index].dwStride);
5405 ERR("No source texture, but destination requests one\n");
5406 dest_ptr+=GET_TEXCOORD_SIZE_FROM_FVF(DestFVF, tex_index) * sizeof(float);
5407 if(dest_conv) dest_conv += GET_TEXCOORD_SIZE_FROM_FVF(DestFVF, tex_index) * sizeof(float);
5410 copy_and_next(dest_ptr, tex_coord, GET_TEXCOORD_SIZE_FROM_FVF(DestFVF, tex_index) * sizeof(float));
5412 copy_and_next(dest_conv, tex_coord, GET_TEXCOORD_SIZE_FROM_FVF(DestFVF, tex_index) * sizeof(float));
5419 GL_EXTCALL(glUnmapBufferARB(GL_ARRAY_BUFFER_ARB));
5420 checkGLcall("glUnmapBufferARB(GL_ARRAY_BUFFER_ARB)");
5427 #undef copy_and_next
5429 static HRESULT WINAPI IWineD3DDeviceImpl_ProcessVertices(IWineD3DDevice *iface, UINT SrcStartIndex, UINT DestIndex, UINT VertexCount, IWineD3DVertexBuffer* pDestBuffer, IWineD3DVertexBuffer* pVertexDecl, DWORD Flags) {
5430 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5431 IWineD3DVertexBufferImpl *SrcImpl = (IWineD3DVertexBufferImpl *) pVertexDecl;
5432 WineDirect3DVertexStridedData strided;
5433 TRACE("(%p)->(%d,%d,%d,%p,%p,%ld\n", This, SrcStartIndex, DestIndex, VertexCount, pDestBuffer, pVertexDecl, Flags);
5436 WARN("NULL source vertex buffer\n");
5437 return WINED3DERR_INVALIDCALL;
5439 /* We don't need the source vbo because this buffer is only used as
5440 * a source for ProcessVertices. Avoid wasting resources by converting the
5441 * buffer and loading the VBO
5444 TRACE("Releaseing the source vbo, it won't be needed\n");
5446 if(!SrcImpl->resource.allocatedMemory) {
5447 /* Rescue the data from the buffer */
5449 SrcImpl->resource.allocatedMemory = HeapAlloc(GetProcessHeap(), 0, SrcImpl->resource.size);
5450 if(!SrcImpl->resource.allocatedMemory) {
5451 ERR("Out of memory\n");
5452 return E_OUTOFMEMORY;
5456 GL_EXTCALL(glBindBufferARB(GL_ARRAY_BUFFER_ARB, SrcImpl->vbo));
5457 checkGLcall("glBindBufferARB");
5459 src = GL_EXTCALL(glMapBufferARB(GL_ARRAY_BUFFER_ARB, GL_READ_ONLY_ARB));
5461 memcpy(SrcImpl->resource.allocatedMemory, src, SrcImpl->resource.size);
5464 GL_EXTCALL(glUnmapBufferARB(GL_ARRAY_BUFFER_ARB));
5465 checkGLcall("glUnmapBufferARB");
5470 GL_EXTCALL(glBindBufferARB(GL_ARRAY_BUFFER_ARB, 0));
5471 checkGLcall("glBindBufferARB");
5472 GL_EXTCALL(glDeleteBuffersARB(1, &SrcImpl->vbo));
5473 checkGLcall("glDeleteBuffersARB");
5479 memset(&strided, 0, sizeof(strided));
5480 primitiveConvertFVFtoOffset(SrcImpl->fvf, get_flexible_vertex_size(SrcImpl->fvf), SrcImpl->resource.allocatedMemory + get_flexible_vertex_size(SrcImpl->fvf) * SrcStartIndex, &strided, 0);
5482 return process_vertices_strided(This, DestIndex, VertexCount, &strided, SrcImpl->fvf, (IWineD3DVertexBufferImpl *) pDestBuffer, Flags);
5486 * Apply / Get / Set Texture Stage States
5487 * TODO: Verify against dx9 definitions
5490 /* 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 */
5491 static void WINAPI IWineD3DDeviceImpl_ApplyTextureUnitState(IWineD3DDevice *iface, DWORD Stage, WINED3DTEXTURESTAGESTATETYPE Type) {
5492 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5493 DWORD Value = This->updateStateBlock->textureState[Stage][Type];
5494 /* FIXME: Handle 3d textures? What if TSS value set before set texture? Need to reapply all values? */
5496 TRACE("(%p) : Stage=%ld, Type=%s(%d), Value=%ld\n", This, Stage, debug_d3dtexturestate(Type), Type, Value);
5498 /* Check that the stage is within limits */
5499 if (Stage >= GL_LIMITS(texture_stages) || Stage < 0) {
5500 TRACE("Attempt to access invalid texture rejected\n");
5507 case WINED3DTSS_ALPHAOP :
5508 case WINED3DTSS_COLOROP :
5509 /* nothing to do as moved to drawprim for now */
5511 case WINED3DTSS_ADDRESSW :
5512 #if 0 /* I'm not sure what D3D does about ADDRESSW appearing twice */
5513 if (Value < minLookup[WINELOOKUP_WARPPARAM] || Value > maxLookup[WINELOOKUP_WARPPARAM]) {
5514 FIXME("Unrecognized or unsupported D3DTADDRESS_* value %ld, state %d\n", Value, Type);
5517 GLint wrapParm = stateLookup[WINELOOKUP_WARPPARAM][Value - minLookup[WINELOOKUP_WARPPARAM]];
5518 TRACE("Setting WRAP_R to %d for %x\n", wrapParm, This->stateBlock->textureDimensions[Stage]);
5519 glTexParameteri(This->stateBlock->textureDimensions[Stage], GL_TEXTURE_WRAP_R, wrapParm);
5520 checkGLcall("glTexParameteri(..., GL_TEXTURE_WRAP_R, wrapParm)");
5523 case WINED3DTSS_TEXCOORDINDEX :
5525 /* Values 0-7 are indexes into the FVF tex coords - See comments in DrawPrimitive */
5527 /* FIXME: From MSDN: The WINED3DTSS_TCI_* flags are mutually exclusive. If you include
5528 one flag, you can still specify an index value, which the system uses to
5529 determine the texture wrapping mode.
5530 eg. SetTextureStageState( 0, D3DTSS_TEXCOORDINDEX, D3DTSS_TCI_CAMERASPACEPOSITION | 1 );
5531 means use the vertex position (camera-space) as the input texture coordinates
5532 for this texture stage, and the wrap mode set in the WINED3DRS_WRAP1 render
5533 state. We do not (yet) support the D3DRENDERSTATE_WRAPx values, nor tie them up
5534 to the TEXCOORDINDEX value */
5537 * Be careful the value of the mask 0xF0000 come from d3d8types.h infos
5539 switch (Value & 0xFFFF0000) {
5540 case D3DTSS_TCI_PASSTHRU:
5541 /*Use the specified texture coordinates contained within the vertex format. This value resolves to zero.*/
5542 glDisable(GL_TEXTURE_GEN_S);
5543 glDisable(GL_TEXTURE_GEN_T);
5544 glDisable(GL_TEXTURE_GEN_R);
5545 glDisable(GL_TEXTURE_GEN_Q);
5546 checkGLcall("glDisable(GL_TEXTURE_GEN_S,T,R,Q)");
5549 case D3DTSS_TCI_CAMERASPACEPOSITION:
5550 /* CameraSpacePosition means use the vertex position, transformed to camera space,
5551 as the input texture coordinates for this stage's texture transformation. This
5552 equates roughly to EYE_LINEAR */
5554 float s_plane[] = { 1.0, 0.0, 0.0, 0.0 };
5555 float t_plane[] = { 0.0, 1.0, 0.0, 0.0 };
5556 float r_plane[] = { 0.0, 0.0, 1.0, 0.0 };
5557 float q_plane[] = { 0.0, 0.0, 0.0, 1.0 };
5558 TRACE("WINED3DTSS_TCI_CAMERASPACEPOSITION - Set eye plane\n");
5560 glMatrixMode(GL_MODELVIEW);
5563 glTexGenfv(GL_S, GL_EYE_PLANE, s_plane);
5564 glTexGenfv(GL_T, GL_EYE_PLANE, t_plane);
5565 glTexGenfv(GL_R, GL_EYE_PLANE, r_plane);
5566 glTexGenfv(GL_Q, GL_EYE_PLANE, q_plane);
5569 TRACE("WINED3DTSS_TCI_CAMERASPACEPOSITION - Set GL_TEXTURE_GEN_x and GL_x, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR\n");
5570 glEnable(GL_TEXTURE_GEN_S);
5571 checkGLcall("glEnable(GL_TEXTURE_GEN_S);");
5572 glTexGeni(GL_S, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR);
5573 checkGLcall("glTexGeni(GL_S, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR)");
5574 glEnable(GL_TEXTURE_GEN_T);
5575 checkGLcall("glEnable(GL_TEXTURE_GEN_T);");
5576 glTexGeni(GL_T, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR);
5577 checkGLcall("glTexGeni(GL_T, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR)");
5578 glEnable(GL_TEXTURE_GEN_R);
5579 checkGLcall("glEnable(GL_TEXTURE_GEN_R);");
5580 glTexGeni(GL_R, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR);
5581 checkGLcall("glTexGeni(GL_R, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR)");
5585 case D3DTSS_TCI_CAMERASPACENORMAL:
5587 if (GL_SUPPORT(NV_TEXGEN_REFLECTION)) {
5588 float s_plane[] = { 1.0, 0.0, 0.0, 0.0 };
5589 float t_plane[] = { 0.0, 1.0, 0.0, 0.0 };
5590 float r_plane[] = { 0.0, 0.0, 1.0, 0.0 };
5591 float q_plane[] = { 0.0, 0.0, 0.0, 1.0 };
5592 TRACE("WINED3DTSS_TCI_CAMERASPACENORMAL - Set eye plane\n");
5594 glMatrixMode(GL_MODELVIEW);
5597 glTexGenfv(GL_S, GL_EYE_PLANE, s_plane);
5598 glTexGenfv(GL_T, GL_EYE_PLANE, t_plane);
5599 glTexGenfv(GL_R, GL_EYE_PLANE, r_plane);
5600 glTexGenfv(GL_Q, GL_EYE_PLANE, q_plane);
5603 glEnable(GL_TEXTURE_GEN_S);
5604 checkGLcall("glEnable(GL_TEXTURE_GEN_S);");
5605 glTexGeni(GL_S, GL_TEXTURE_GEN_MODE, GL_NORMAL_MAP_NV);
5606 checkGLcall("glTexGeni(GL_S, GL_TEXTURE_GEN_MODE, GL_NORMAL_MAP_NV)");
5607 glEnable(GL_TEXTURE_GEN_T);
5608 checkGLcall("glEnable(GL_TEXTURE_GEN_T);");
5609 glTexGeni(GL_T, GL_TEXTURE_GEN_MODE, GL_NORMAL_MAP_NV);
5610 checkGLcall("glTexGeni(GL_T, GL_TEXTURE_GEN_MODE, GL_NORMAL_MAP_NV)");
5611 glEnable(GL_TEXTURE_GEN_R);
5612 checkGLcall("glEnable(GL_TEXTURE_GEN_R);");
5613 glTexGeni(GL_R, GL_TEXTURE_GEN_MODE, GL_NORMAL_MAP_NV);
5614 checkGLcall("glTexGeni(GL_R, GL_TEXTURE_GEN_MODE, GL_NORMAL_MAP_NV)");
5619 case D3DTSS_TCI_CAMERASPACEREFLECTIONVECTOR:
5621 if (GL_SUPPORT(NV_TEXGEN_REFLECTION)) {
5622 float s_plane[] = { 1.0, 0.0, 0.0, 0.0 };
5623 float t_plane[] = { 0.0, 1.0, 0.0, 0.0 };
5624 float r_plane[] = { 0.0, 0.0, 1.0, 0.0 };
5625 float q_plane[] = { 0.0, 0.0, 0.0, 1.0 };
5626 TRACE("WINED3DTSS_TCI_CAMERASPACEREFLECTIONVECTOR - Set eye plane\n");
5628 glMatrixMode(GL_MODELVIEW);
5631 glTexGenfv(GL_S, GL_EYE_PLANE, s_plane);
5632 glTexGenfv(GL_T, GL_EYE_PLANE, t_plane);
5633 glTexGenfv(GL_R, GL_EYE_PLANE, r_plane);
5634 glTexGenfv(GL_Q, GL_EYE_PLANE, q_plane);
5637 glEnable(GL_TEXTURE_GEN_S);
5638 checkGLcall("glEnable(GL_TEXTURE_GEN_S);");
5639 glTexGeni(GL_S, GL_TEXTURE_GEN_MODE, GL_REFLECTION_MAP_NV);
5640 checkGLcall("glTexGeni(GL_S, GL_TEXTURE_GEN_MODE, GL_REFLECTION_MAP_NV)");
5641 glEnable(GL_TEXTURE_GEN_T);
5642 checkGLcall("glEnable(GL_TEXTURE_GEN_T);");
5643 glTexGeni(GL_T, GL_TEXTURE_GEN_MODE, GL_REFLECTION_MAP_NV);
5644 checkGLcall("glTexGeni(GL_T, GL_TEXTURE_GEN_MODE, GL_REFLECTION_MAP_NV)");
5645 glEnable(GL_TEXTURE_GEN_R);
5646 checkGLcall("glEnable(GL_TEXTURE_GEN_R);");
5647 glTexGeni(GL_R, GL_TEXTURE_GEN_MODE, GL_REFLECTION_MAP_NV);
5648 checkGLcall("glTexGeni(GL_R, GL_TEXTURE_GEN_MODE, GL_REFLECTION_MAP_NV)");
5653 /* Unhandled types: */
5656 /* ? disable GL_TEXTURE_GEN_n ? */
5657 glDisable(GL_TEXTURE_GEN_S);
5658 glDisable(GL_TEXTURE_GEN_T);
5659 glDisable(GL_TEXTURE_GEN_R);
5660 glDisable(GL_TEXTURE_GEN_Q);
5661 FIXME("Unhandled WINED3DTSS_TEXCOORDINDEX %lx\n", Value);
5668 case WINED3DTSS_TEXTURETRANSFORMFLAGS :
5669 set_texture_matrix((float *)&This->stateBlock->transforms[WINED3DTS_TEXTURE0 + Stage].u.m[0][0], Value, (This->stateBlock->textureState[Stage][WINED3DTSS_TEXCOORDINDEX] & 0xFFFF0000) != D3DTSS_TCI_PASSTHRU);
5672 case WINED3DTSS_BUMPENVMAT00 :
5673 case WINED3DTSS_BUMPENVMAT01 :
5674 TRACE("BUMPENVMAT0%u Stage=%ld, Type=%d, Value =%ld\n", Type - WINED3DTSS_BUMPENVMAT00, Stage, Type, Value);
5676 case WINED3DTSS_BUMPENVMAT10 :
5677 case WINED3DTSS_BUMPENVMAT11 :
5678 TRACE("BUMPENVMAT1%u Stage=%ld, Type=%d, Value =%ld\n", Type - WINED3DTSS_BUMPENVMAT10, Stage, Type, Value);
5681 case WINED3DTSS_BUMPENVLSCALE :
5682 TRACE("BUMPENVLSCALE Stage=%ld, Type=%d, Value =%ld\n", Stage, Type, Value);
5685 case WINED3DTSS_BUMPENVLOFFSET :
5686 TRACE("BUMPENVLOFFSET Stage=%ld, Type=%d, Value =%ld\n", Stage, Type, Value);
5689 case WINED3DTSS_RESULTARG :
5690 TRACE("RESULTARG Still a stub, Stage=%ld, Type=%d, Value =%ld\n", Stage, Type, Value);
5694 /* Put back later: FIXME("(%p) : stub, Stage=%ld, Type=%d, Value =%ld\n", This, Stage, Type, Value); */
5695 TRACE("Still a stub, Stage=%ld, Type=%d, Value =%ld\n", Stage, Type, Value);
5704 * Get / Set Texture Stage States
5705 * TODO: Verify against dx9 definitions
5707 static HRESULT WINAPI IWineD3DDeviceImpl_SetTextureStageState(IWineD3DDevice *iface, DWORD Stage, WINED3DTEXTURESTAGESTATETYPE Type, DWORD Value) {
5708 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5710 /* FIXME: Handle 3d textures? What if TSS value set before set texture? Need to reapply all values? */
5712 TRACE("(%p) : Stage=%ld, Type=%s(%d), Value=%ld\n", This, Stage, debug_d3dtexturestate(Type), Type, Value);
5714 /* Reject invalid texture units */
5715 if (Stage >= GL_LIMITS(texture_stages)) {
5716 TRACE("Attempt to access invalid texture rejected\n");
5717 return WINED3DERR_INVALIDCALL;
5720 This->updateStateBlock->changed.textureState[Stage][Type] = TRUE;
5721 This->updateStateBlock->set.textureState[Stage][Type] = TRUE;
5722 This->updateStateBlock->textureState[Stage][Type] = Value;
5727 static HRESULT WINAPI IWineD3DDeviceImpl_GetTextureStageState(IWineD3DDevice *iface, DWORD Stage, WINED3DTEXTURESTAGESTATETYPE Type, DWORD* pValue) {
5728 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5729 TRACE("(%p) : requesting Stage %ld, Type %d getting %ld\n", This, Stage, Type, This->updateStateBlock->textureState[Stage][Type]);
5730 *pValue = This->updateStateBlock->textureState[Stage][Type];
5737 static HRESULT WINAPI IWineD3DDeviceImpl_SetTexture(IWineD3DDevice *iface, DWORD Stage, IWineD3DBaseTexture* pTexture) {
5739 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5740 IWineD3DBaseTexture *oldTexture;
5742 oldTexture = This->updateStateBlock->textures[Stage];
5743 TRACE("(%p) : Stage(%ld), Texture (%p)\n", This, Stage, pTexture);
5745 #if 0 /* TODO: check so vertex textures */
5746 if (Stage >= D3DVERTEXTEXTURESAMPLER && Stage <= D3DVERTEXTEXTURESAMPLER3){
5747 This->updateStateBlock->vertexTextures[Stage - D3DVERTEXTEXTURESAMPLER] = pTexture;
5752 /* Reject invalid texture units */
5753 if (Stage >= GL_LIMITS(sampler_stages) || Stage < 0) {
5754 WARN("Attempt to access invalid texture rejected\n");
5755 return WINED3DERR_INVALIDCALL;
5758 if(pTexture != NULL) {
5759 /* SetTexture isn't allowed on textures in WINED3DPOOL_SCRATCH;
5761 if(((IWineD3DTextureImpl*)pTexture)->resource.pool == WINED3DPOOL_SCRATCH) {
5762 WARN("(%p) Attempt to set scratch texture rejected\n", pTexture);
5763 return WINED3DERR_INVALIDCALL;
5767 oldTexture = This->updateStateBlock->textures[Stage];
5768 TRACE("GL_LIMITS %d\n",GL_LIMITS(sampler_stages));
5769 TRACE("(%p) : oldtexture(%p)\n", This,oldTexture);
5771 This->updateStateBlock->set.textures[Stage] = TRUE;
5772 This->updateStateBlock->changed.textures[Stage] = TRUE;
5773 TRACE("(%p) : setting new texture to %p\n", This, pTexture);
5774 This->updateStateBlock->textures[Stage] = pTexture;
5776 /* Handle recording of state blocks */
5777 if (This->isRecordingState) {
5778 TRACE("Recording... not performing anything\n");
5782 /** NOTE: MSDN says that setTexture increases the reference count,
5783 * and the the application nust set the texture back to null (or have a leaky application),
5784 * This means we should pass the refcount up to the parent
5785 *******************************/
5786 if (NULL != This->updateStateBlock->textures[Stage]) {
5787 IWineD3DBaseTexture_AddRef(This->updateStateBlock->textures[Stage]);
5790 if (NULL != oldTexture) {
5791 IWineD3DBaseTexture_Release(oldTexture);
5794 /* Reset color keying */
5795 if(Stage == 0 && This->stateBlock->renderState[WINED3DRS_COLORKEYENABLE]) {
5796 BOOL enable_ckey = FALSE;
5799 IWineD3DSurfaceImpl *surf = (IWineD3DSurfaceImpl *) ((IWineD3DTextureImpl *)pTexture)->surfaces[0];
5800 if(surf->CKeyFlags & DDSD_CKSRCBLT) enable_ckey = TRUE;
5804 glAlphaFunc(GL_NOTEQUAL, 0.0);
5805 checkGLcall("glAlphaFunc");
5812 static HRESULT WINAPI IWineD3DDeviceImpl_GetTexture(IWineD3DDevice *iface, DWORD Stage, IWineD3DBaseTexture** ppTexture) {
5813 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5814 TRACE("(%p) : (%ld /* Stage */,%p /* ppTexture */)\n", This, Stage, ppTexture);
5816 /* Reject invalid texture units */
5817 if (Stage >= GL_LIMITS(sampler_stages)) {
5818 TRACE("Attempt to access invalid texture rejected\n");
5819 return WINED3DERR_INVALIDCALL;
5821 *ppTexture=This->updateStateBlock->textures[Stage];
5823 IWineD3DBaseTexture_AddRef(*ppTexture);
5825 return WINED3DERR_INVALIDCALL;
5832 static HRESULT WINAPI IWineD3DDeviceImpl_GetBackBuffer(IWineD3DDevice *iface, UINT iSwapChain, UINT BackBuffer, WINED3DBACKBUFFER_TYPE Type,
5833 IWineD3DSurface **ppBackBuffer) {
5834 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5835 IWineD3DSwapChain *swapChain;
5838 TRACE("(%p) : BackBuf %d Type %d SwapChain %d returning %p\n", This, BackBuffer, Type, iSwapChain, *ppBackBuffer);
5840 hr = IWineD3DDeviceImpl_GetSwapChain(iface, iSwapChain, &swapChain);
5841 if (hr == WINED3D_OK) {
5842 hr = IWineD3DSwapChain_GetBackBuffer(swapChain, BackBuffer, Type, ppBackBuffer);
5843 IWineD3DSwapChain_Release(swapChain);
5845 *ppBackBuffer = NULL;
5850 static HRESULT WINAPI IWineD3DDeviceImpl_GetDeviceCaps(IWineD3DDevice *iface, WINED3DCAPS* pCaps) {
5851 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5852 WARN("(%p) : stub, calling idirect3d for now\n", This);
5853 return IWineD3D_GetDeviceCaps(This->wineD3D, This->adapterNo, This->devType, pCaps);
5856 static HRESULT WINAPI IWineD3DDeviceImpl_GetDisplayMode(IWineD3DDevice *iface, UINT iSwapChain, WINED3DDISPLAYMODE* pMode) {
5857 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5858 IWineD3DSwapChain *swapChain;
5861 if(iSwapChain > 0) {
5862 hr = IWineD3DDeviceImpl_GetSwapChain(iface, iSwapChain, (IWineD3DSwapChain **)&swapChain);
5863 if (hr == WINED3D_OK) {
5864 hr = IWineD3DSwapChain_GetDisplayMode(swapChain, pMode);
5865 IWineD3DSwapChain_Release(swapChain);
5867 FIXME("(%p) Error getting display mode\n", This);
5870 /* Don't read the real display mode,
5871 but return the stored mode instead. X11 can't change the color
5872 depth, and some apps are pretty angry if they SetDisplayMode from
5873 24 to 16 bpp and find out that GetDisplayMode still returns 24 bpp
5875 Also don't relay to the swapchain because with ddraw it's possible
5876 that there isn't a swapchain at all */
5877 pMode->Width = This->ddraw_width;
5878 pMode->Height = This->ddraw_height;
5879 pMode->Format = This->ddraw_format;
5880 pMode->RefreshRate = 0;
5887 static HRESULT WINAPI IWineD3DDeviceImpl_SetHWND(IWineD3DDevice *iface, HWND hWnd) {
5888 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5889 TRACE("(%p)->(%p)\n", This, hWnd);
5891 This->ddraw_window = hWnd;
5895 static HRESULT WINAPI IWineD3DDeviceImpl_GetHWND(IWineD3DDevice *iface, HWND *hWnd) {
5896 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5897 TRACE("(%p)->(%p)\n", This, hWnd);
5899 *hWnd = This->ddraw_window;
5904 * Stateblock related functions
5907 static HRESULT WINAPI IWineD3DDeviceImpl_BeginStateBlock(IWineD3DDevice *iface) {
5908 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5909 IWineD3DStateBlockImpl *object;
5910 HRESULT temp_result;
5912 TRACE("(%p)", This);
5914 if (This->isRecordingState) {
5915 return WINED3DERR_INVALIDCALL;
5918 object = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(IWineD3DStateBlockImpl));
5919 if (NULL == object ) {
5920 FIXME("(%p)Error allocating memory for stateblock\n", This);
5921 return E_OUTOFMEMORY;
5923 TRACE("(%p) created object %p\n", This, object);
5924 object->wineD3DDevice= This;
5925 /** FIXME: object->parent = parent; **/
5926 object->parent = NULL;
5927 object->blockType = WINED3DSBT_ALL;
5929 object->lpVtbl = &IWineD3DStateBlock_Vtbl;
5931 temp_result = allocate_shader_constants(object);
5932 if (WINED3D_OK != temp_result)
5935 IWineD3DStateBlock_Release((IWineD3DStateBlock*)This->updateStateBlock);
5936 This->updateStateBlock = object;
5937 This->isRecordingState = TRUE;
5939 TRACE("(%p) recording stateblock %p\n",This , object);
5943 static HRESULT WINAPI IWineD3DDeviceImpl_EndStateBlock(IWineD3DDevice *iface, IWineD3DStateBlock** ppStateBlock) {
5944 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5946 if (!This->isRecordingState) {
5947 FIXME("(%p) not recording! returning error\n", This);
5948 *ppStateBlock = NULL;
5949 return WINED3DERR_INVALIDCALL;
5952 *ppStateBlock = (IWineD3DStateBlock*)This->updateStateBlock;
5953 This->isRecordingState = FALSE;
5954 This->updateStateBlock = This->stateBlock;
5955 IWineD3DStateBlock_AddRef((IWineD3DStateBlock*)This->updateStateBlock);
5956 /* IWineD3DStateBlock_AddRef(*ppStateBlock); don't need to do this, since we should really just release UpdateStateBlock first */
5957 TRACE("(%p) returning token (ptr to stateblock) of %p\n", This, *ppStateBlock);
5962 * Scene related functions
5964 static HRESULT WINAPI IWineD3DDeviceImpl_BeginScene(IWineD3DDevice *iface) {
5965 /* At the moment we have no need for any functionality at the beginning
5967 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5968 TRACE("(%p) : stub\n", This);
5972 static HRESULT WINAPI IWineD3DDeviceImpl_EndScene(IWineD3DDevice *iface) {
5973 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5974 TRACE("(%p)\n", This);
5976 /* We only have to do this if we need to read the, swapbuffers performs a flush for us */
5978 checkGLcall("glFlush");
5980 TRACE("End Scene\n");
5981 if(This->renderTarget != NULL) {
5983 /* If the container of the rendertarget is a texture then we need to save the data from the pbuffer */
5984 IUnknown *targetContainer = NULL;
5985 if (WINED3D_OK == IWineD3DSurface_GetContainer(This->renderTarget, &IID_IWineD3DBaseTexture, (void **)&targetContainer)
5986 || WINED3D_OK == IWineD3DSurface_GetContainer(This->renderTarget, &IID_IWineD3DDevice, (void **)&targetContainer)) {
5987 TRACE("(%p) : Texture rendertarget %p\n", This ,This->renderTarget);
5988 /** always dirtify for now. we must find a better way to see that surface have been modified
5989 (Modifications should will only occur via draw-primitive, but we do need better locking
5990 switching to render-to-texture should remove the overhead though.
5992 IWineD3DSurface_SetPBufferState(This->renderTarget, TRUE /* inPBuffer */, FALSE /* inTexture */);
5993 IWineD3DSurface_AddDirtyRect(This->renderTarget, NULL);
5994 IWineD3DSurface_PreLoad(This->renderTarget);
5995 IWineD3DSurface_SetPBufferState(This->renderTarget, FALSE /* inPBuffer */, FALSE /* inTexture */);
5996 IUnknown_Release(targetContainer);
5999 This->sceneEnded = TRUE;
6004 static HRESULT WINAPI IWineD3DDeviceImpl_Present(IWineD3DDevice *iface,
6005 CONST RECT* pSourceRect, CONST RECT* pDestRect,
6006 HWND hDestWindowOverride, CONST RGNDATA* pDirtyRegion) {
6007 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
6008 IWineD3DSwapChain *swapChain = NULL;
6010 int swapchains = IWineD3DDeviceImpl_GetNumberOfSwapChains(iface);
6012 TRACE("(%p) Presenting the frame\n", This);
6014 for(i = 0 ; i < swapchains ; i ++) {
6016 IWineD3DDeviceImpl_GetSwapChain(iface, i , (IWineD3DSwapChain **)&swapChain);
6017 TRACE("presentinng chain %d, %p\n", i, swapChain);
6018 IWineD3DSwapChain_Present(swapChain, pSourceRect, pDestRect, hDestWindowOverride, pDirtyRegion, 0);
6019 IWineD3DSwapChain_Release(swapChain);
6025 static HRESULT WINAPI IWineD3DDeviceImpl_Clear(IWineD3DDevice *iface, DWORD Count, CONST D3DRECT* pRects,
6026 DWORD Flags, D3DCOLOR Color, float Z, DWORD Stencil) {
6027 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
6029 /* TODO: From MSDN This method fails if you specify the D3DCLEAR_ZBUFFER or D3DCLEAR_STENCIL flags when the
6030 render target does not have an attached depth buffer. Similarly, if you specify the D3DCLEAR_STENCIL flag
6031 when the depth-buffer format does not contain stencil buffer information, this method fails. */
6032 GLbitfield glMask = 0;
6033 GLboolean old_ztest;
6034 GLfloat old_z_clear_value;
6035 GLint old_stencil_clear_value;
6036 GLfloat old_color_clear_value[4];
6038 CONST D3DRECT* curRect;
6040 TRACE("(%p) Count (%ld), pRects (%p), Flags (%lx), Z (%f), Stencil (%ld)\n", This,
6041 Count, pRects, Flags, Z, Stencil);
6045 glEnable(GL_SCISSOR_TEST);
6046 checkGLcall("glEnable GL_SCISSOR_TEST");
6048 if (Count > 0 && pRects) {
6054 /* Only set the values up once, as they are not changing */
6055 if (Flags & D3DCLEAR_STENCIL) {
6056 glGetIntegerv(GL_STENCIL_CLEAR_VALUE, &old_stencil_clear_value);
6057 glClearStencil(Stencil);
6058 checkGLcall("glClearStencil");
6059 glMask = glMask | GL_STENCIL_BUFFER_BIT;
6060 glStencilMask(0xFFFFFFFF);
6063 if (Flags & D3DCLEAR_ZBUFFER) {
6064 glGetBooleanv(GL_DEPTH_WRITEMASK, &old_ztest);
6065 glDepthMask(GL_TRUE);
6066 glGetFloatv(GL_DEPTH_CLEAR_VALUE, &old_z_clear_value);
6068 checkGLcall("glClearDepth");
6069 glMask = glMask | GL_DEPTH_BUFFER_BIT;
6072 if (Flags & D3DCLEAR_TARGET) {
6073 TRACE("Clearing screen with glClear to color %lx\n", Color);
6074 glGetFloatv(GL_COLOR_CLEAR_VALUE, old_color_clear_value);
6075 glClearColor(D3DCOLOR_R(Color),
6079 checkGLcall("glClearColor");
6081 /* Clear ALL colors! */
6082 glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
6083 glMask = glMask | GL_COLOR_BUFFER_BIT;
6086 /* Now process each rect in turn */
6087 for (i = 0; i < Count || i == 0; i++) {
6090 /* Note gl uses lower left, width/height */
6091 TRACE("(%p) %p Rect=(%ld,%ld)->(%ld,%ld) glRect=(%ld,%ld), len=%ld, hei=%ld\n", This, curRect,
6092 curRect->x1, curRect->y1, curRect->x2, curRect->y2,
6093 curRect->x1, (((IWineD3DSurfaceImpl *)This->renderTarget)->currentDesc.Height - curRect->y2),
6094 curRect->x2 - curRect->x1, curRect->y2 - curRect->y1);
6095 glScissor(curRect->x1, (((IWineD3DSurfaceImpl *)This->renderTarget)->currentDesc.Height - curRect->y2),
6096 curRect->x2 - curRect->x1, curRect->y2 - curRect->y1);
6097 checkGLcall("glScissor");
6099 glScissor(This->stateBlock->viewport.X,
6100 (((IWineD3DSurfaceImpl *)This->renderTarget)->currentDesc.Height -
6101 (This->stateBlock->viewport.Y + This->stateBlock->viewport.Height)),
6102 This->stateBlock->viewport.Width,
6103 This->stateBlock->viewport.Height);
6104 checkGLcall("glScissor");
6107 /* Clear the selected rectangle (or full screen) */
6109 checkGLcall("glClear");
6111 /* Step to the next rectangle */
6112 if (curRect) curRect = curRect + sizeof(D3DRECT);
6115 /* Restore the old values (why..?) */
6116 if (Flags & D3DCLEAR_STENCIL) {
6117 glClearStencil(old_stencil_clear_value);
6118 glStencilMask(This->stateBlock->renderState[WINED3DRS_STENCILWRITEMASK]);
6120 if (Flags & D3DCLEAR_ZBUFFER) {
6121 glDepthMask(old_ztest);
6122 glClearDepth(old_z_clear_value);
6124 if (Flags & D3DCLEAR_TARGET) {
6125 glClearColor(old_color_clear_value[0],
6126 old_color_clear_value[1],
6127 old_color_clear_value[2],
6128 old_color_clear_value[3]);
6129 glColorMask(This->stateBlock->renderState[WINED3DRS_COLORWRITEENABLE] & D3DCOLORWRITEENABLE_RED ? GL_TRUE : GL_FALSE,
6130 This->stateBlock->renderState[WINED3DRS_COLORWRITEENABLE] & D3DCOLORWRITEENABLE_GREEN ? GL_TRUE : GL_FALSE,
6131 This->stateBlock->renderState[WINED3DRS_COLORWRITEENABLE] & D3DCOLORWRITEENABLE_BLUE ? GL_TRUE : GL_FALSE,
6132 This->stateBlock->renderState[WINED3DRS_COLORWRITEENABLE] & D3DCOLORWRITEENABLE_ALPHA ? GL_TRUE : GL_FALSE);
6135 glDisable(GL_SCISSOR_TEST);
6136 checkGLcall("glDisable");
6145 static HRESULT WINAPI IWineD3DDeviceImpl_DrawPrimitive(IWineD3DDevice *iface, D3DPRIMITIVETYPE PrimitiveType, UINT StartVertex,
6146 UINT PrimitiveCount) {
6148 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
6149 This->stateBlock->streamIsUP = FALSE;
6151 TRACE("(%p) : Type=(%d,%s), Start=%d, Count=%d\n", This, PrimitiveType,
6152 debug_d3dprimitivetype(PrimitiveType),
6153 StartVertex, PrimitiveCount);
6154 drawPrimitive(iface, PrimitiveType, PrimitiveCount, StartVertex, 0/* NumVertices */, -1 /* indxStart */,
6155 0 /* indxSize */, NULL /* indxData */, 0 /* minIndex */, NULL);
6161 /* TODO: baseVIndex needs to be provided from This->stateBlock->baseVertexIndex when called from d3d8 */
6162 static HRESULT WINAPI IWineD3DDeviceImpl_DrawIndexedPrimitive(IWineD3DDevice *iface,
6163 D3DPRIMITIVETYPE PrimitiveType,
6164 INT baseVIndex, UINT minIndex,
6165 UINT NumVertices, UINT startIndex, UINT primCount) {
6167 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
6169 IWineD3DIndexBuffer *pIB;
6170 WINED3DINDEXBUFFER_DESC IdxBufDsc;
6172 pIB = This->stateBlock->pIndexData;
6173 This->stateBlock->streamIsUP = FALSE;
6175 TRACE("(%p) : Type=(%d,%s), min=%d, CountV=%d, startIdx=%d, baseVidx=%d, countP=%d\n", This,
6176 PrimitiveType, debug_d3dprimitivetype(PrimitiveType),
6177 minIndex, NumVertices, startIndex, baseVIndex, primCount);
6179 IWineD3DIndexBuffer_GetDesc(pIB, &IdxBufDsc);
6180 if (IdxBufDsc.Format == WINED3DFMT_INDEX16) {
6186 drawPrimitive(iface, PrimitiveType, primCount, baseVIndex, NumVertices, startIndex,
6187 idxStride, ((IWineD3DIndexBufferImpl *) pIB)->resource.allocatedMemory, minIndex, NULL);
6192 static HRESULT WINAPI IWineD3DDeviceImpl_DrawPrimitiveUP(IWineD3DDevice *iface, D3DPRIMITIVETYPE PrimitiveType,
6193 UINT PrimitiveCount, CONST void* pVertexStreamZeroData,
6194 UINT VertexStreamZeroStride) {
6195 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
6197 TRACE("(%p) : Type=(%d,%s), pCount=%d, pVtxData=%p, Stride=%d\n", This, PrimitiveType,
6198 debug_d3dprimitivetype(PrimitiveType),
6199 PrimitiveCount, pVertexStreamZeroData, VertexStreamZeroStride);
6201 /* release the stream source */
6202 if (This->stateBlock->streamSource[0] != NULL) {
6203 IWineD3DVertexBuffer_Release(This->stateBlock->streamSource[0]);
6206 /* Note in the following, it's not this type, but that's the purpose of streamIsUP */
6207 This->stateBlock->streamSource[0] = (IWineD3DVertexBuffer *)pVertexStreamZeroData;
6208 This->stateBlock->streamStride[0] = VertexStreamZeroStride;
6209 This->stateBlock->streamIsUP = TRUE;
6211 drawPrimitive(iface, PrimitiveType, PrimitiveCount, 0 /* start vertex */, 0 /* NumVertices */,
6212 0 /* indxStart*/, 0 /* indxSize*/, NULL /* indxData */, 0 /* indxMin */, NULL);
6214 /* MSDN specifies stream zero settings must be set to NULL */
6215 This->stateBlock->streamStride[0] = 0;
6216 This->stateBlock->streamSource[0] = NULL;
6218 /*stream zero settings set to null at end, as per the msdn */
6222 static HRESULT WINAPI IWineD3DDeviceImpl_DrawIndexedPrimitiveUP(IWineD3DDevice *iface, D3DPRIMITIVETYPE PrimitiveType,
6223 UINT MinVertexIndex, UINT NumVertices,
6224 UINT PrimitiveCount, CONST void* pIndexData,
6225 WINED3DFORMAT IndexDataFormat,CONST void* pVertexStreamZeroData,
6226 UINT VertexStreamZeroStride) {
6228 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
6230 TRACE("(%p) : Type=(%d,%s), MinVtxIdx=%d, NumVIdx=%d, PCount=%d, pidxdata=%p, IdxFmt=%d, pVtxdata=%p, stride=%d\n",
6231 This, PrimitiveType, debug_d3dprimitivetype(PrimitiveType),
6232 MinVertexIndex, NumVertices, PrimitiveCount, pIndexData,
6233 IndexDataFormat, pVertexStreamZeroData, VertexStreamZeroStride);
6235 if (IndexDataFormat == WINED3DFMT_INDEX16) {
6241 /* release the stream and index data */
6242 if (This->stateBlock->streamSource[0] != NULL) {
6243 IWineD3DVertexBuffer_Release(This->stateBlock->streamSource[0]);
6245 if (This->stateBlock->pIndexData) {
6246 IWineD3DIndexBuffer_Release(This->stateBlock->pIndexData);
6249 /* Note in the following, it's not this type, but that's the purpose of streamIsUP */
6250 This->stateBlock->streamSource[0] = (IWineD3DVertexBuffer *)pVertexStreamZeroData;
6251 This->stateBlock->streamIsUP = TRUE;
6252 This->stateBlock->streamStride[0] = VertexStreamZeroStride;
6254 drawPrimitive(iface, PrimitiveType, PrimitiveCount, 0 /* vertexStart */, NumVertices, 0 /* indxStart */, idxStride, pIndexData, MinVertexIndex, NULL);
6256 /* MSDN specifies stream zero settings and index buffer must be set to NULL */
6257 This->stateBlock->streamSource[0] = NULL;
6258 This->stateBlock->streamStride[0] = 0;
6259 This->stateBlock->pIndexData = NULL;
6264 static HRESULT WINAPI IWineD3DDeviceImpl_DrawPrimitiveStrided (IWineD3DDevice *iface, D3DPRIMITIVETYPE PrimitiveType, UINT PrimitiveCount, WineDirect3DVertexStridedData *DrawPrimStrideData) {
6266 drawPrimitive(iface, PrimitiveType, PrimitiveCount, 0, 0, 0, 0, NULL, 0, DrawPrimStrideData);
6269 /* Yet another way to update a texture, some apps use this to load default textures instead of using surface/texture lock/unlock */
6270 static HRESULT WINAPI IWineD3DDeviceImpl_UpdateTexture (IWineD3DDevice *iface, IWineD3DBaseTexture *pSourceTexture, IWineD3DBaseTexture *pDestinationTexture){
6271 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
6272 HRESULT hr = WINED3D_OK;
6273 WINED3DRESOURCETYPE sourceType;
6274 WINED3DRESOURCETYPE destinationType;
6277 /* TODO: think about moving the code into IWineD3DBaseTexture */
6279 TRACE("(%p) Source %p Destination %p\n", This, pSourceTexture, pDestinationTexture);
6281 /* verify that the source and destination textures aren't NULL */
6282 if (NULL == pSourceTexture || NULL == pDestinationTexture) {
6283 WARN("(%p) : source (%p) and destination (%p) textures must not be NULL, returning WINED3DERR_INVALIDCALL\n",
6284 This, pSourceTexture, pDestinationTexture);
6285 hr = WINED3DERR_INVALIDCALL;
6288 if (pSourceTexture == pDestinationTexture) {
6289 WARN("(%p) : source (%p) and destination (%p) textures must be different, returning WINED3DERR_INVALIDCALL\n",
6290 This, pSourceTexture, pDestinationTexture);
6291 hr = WINED3DERR_INVALIDCALL;
6293 /* Verify that the source and destination textures are the same type */
6294 sourceType = IWineD3DBaseTexture_GetType(pSourceTexture);
6295 destinationType = IWineD3DBaseTexture_GetType(pDestinationTexture);
6297 if (sourceType != destinationType) {
6298 WARN("(%p) Sorce and destination types must match, returning WINED3DERR_INVALIDCALL\n",
6300 hr = WINED3DERR_INVALIDCALL;
6303 /* check that both textures have the identical numbers of levels */
6304 if (IWineD3DBaseTexture_GetLevelCount(pDestinationTexture) != IWineD3DBaseTexture_GetLevelCount(pSourceTexture)) {
6305 WARN("(%p) : source (%p) and destination (%p) textures must have identicle numbers of levels, returning WINED3DERR_INVALIDCALL\n", This, pSourceTexture, pDestinationTexture);
6306 hr = WINED3DERR_INVALIDCALL;
6309 if (WINED3D_OK == hr) {
6311 /* Make sure that the destination texture is loaded */
6312 IWineD3DBaseTexture_PreLoad(pDestinationTexture);
6314 /* Update every surface level of the texture */
6315 levels = IWineD3DBaseTexture_GetLevelCount(pDestinationTexture);
6317 switch (sourceType) {
6318 case WINED3DRTYPE_TEXTURE:
6320 IWineD3DSurface *srcSurface;
6321 IWineD3DSurface *destSurface;
6323 for (i = 0 ; i < levels ; ++i) {
6324 IWineD3DTexture_GetSurfaceLevel((IWineD3DTexture *)pSourceTexture, i, &srcSurface);
6325 IWineD3DTexture_GetSurfaceLevel((IWineD3DTexture *)pDestinationTexture, i, &destSurface);
6326 hr = IWineD3DDevice_UpdateSurface(iface, srcSurface, NULL, destSurface, NULL);
6327 IWineD3DSurface_Release(srcSurface);
6328 IWineD3DSurface_Release(destSurface);
6329 if (WINED3D_OK != hr) {
6330 WARN("(%p) : Call to update surface failed\n", This);
6336 case WINED3DRTYPE_CUBETEXTURE:
6338 IWineD3DSurface *srcSurface;
6339 IWineD3DSurface *destSurface;
6340 WINED3DCUBEMAP_FACES faceType;
6342 for (i = 0 ; i < levels ; ++i) {
6343 /* Update each cube face */
6344 for (faceType = D3DCUBEMAP_FACE_POSITIVE_X; faceType <= D3DCUBEMAP_FACE_NEGATIVE_Z; ++faceType){
6345 hr = IWineD3DCubeTexture_GetCubeMapSurface((IWineD3DCubeTexture *)pSourceTexture, faceType, i, &srcSurface);
6346 if (WINED3D_OK != hr) {
6347 FIXME("(%p) : Failed to get src cube surface facetype %d, level %d\n", This, faceType, i);
6349 TRACE("Got srcSurface %p\n", srcSurface);
6351 hr = IWineD3DCubeTexture_GetCubeMapSurface((IWineD3DCubeTexture *)pDestinationTexture, faceType, i, &destSurface);
6352 if (WINED3D_OK != hr) {
6353 FIXME("(%p) : Failed to get src cube surface facetype %d, level %d\n", This, faceType, i);
6355 TRACE("Got desrSurface %p\n", destSurface);
6357 hr = IWineD3DDevice_UpdateSurface(iface, srcSurface, NULL, destSurface, NULL);
6358 IWineD3DSurface_Release(srcSurface);
6359 IWineD3DSurface_Release(destSurface);
6360 if (WINED3D_OK != hr) {
6361 WARN("(%p) : Call to update surface failed\n", This);
6368 #if 0 /* TODO: Add support for volume textures */
6369 case WINED3DRTYPE_VOLUMETEXTURE:
6371 IWineD3DVolume srcVolume = NULL;
6372 IWineD3DSurface destVolume = NULL;
6374 for (i = 0 ; i < levels ; ++i) {
6375 IWineD3DVolumeTexture_GetVolume((IWineD3DVolumeTexture *)pSourceTexture, i, &srcVolume);
6376 IWineD3DVolumeTexture_GetVolume((IWineD3DVolumeTexture *)pDestinationTexture, i, &destVolume);
6377 hr = IWineD3DFoo_UpdateVolume(iface, srcVolume, NULL, destVolume, NULL);
6378 IWineD3DVolume_Release(srcSurface);
6379 IWineD3DVolume_Release(destSurface);
6380 if (WINED3D_OK != hr) {
6381 WARN("(%p) : Call to update volume failed\n", This);
6389 FIXME("(%p) : Unsupported source and destination type\n", This);
6390 hr = WINED3DERR_INVALIDCALL;
6397 static HRESULT WINAPI IWineD3DDeviceImpl_StretchRect(IWineD3DDevice *iface, IWineD3DSurface *pSourceSurface,
6398 CONST RECT* pSourceRect, IWineD3DSurface *pDestinationSurface,
6399 CONST RECT* pDestRect, WINED3DTEXTUREFILTERTYPE Filter) {
6400 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
6402 TRACE("(%p) : stub\n", This);
6405 static HRESULT WINAPI IWineD3DDeviceImpl_GetRenderTargetData(IWineD3DDevice *iface, IWineD3DSurface *pRenderTarget, IWineD3DSurface *pSurface) {
6406 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
6407 /** TODO: remove remove casts to IWineD3DSurfaceImpl *
6408 * NOTE It may be best to move the code into surface to occomplish this
6409 ****************************************/
6411 WINED3DSURFACE_DESC surfaceDesc;
6412 unsigned int surfaceWidth, surfaceHeight;
6413 glDescriptor *targetGlDescription = NULL;
6414 glDescriptor *surfaceGlDescription = NULL;
6415 IWineD3DSwapChainImpl *container = NULL;
6417 IWineD3DSurface_GetGlDesc(pRenderTarget, &targetGlDescription);
6418 IWineD3DSurface_GetGlDesc(pSurface, &surfaceGlDescription);
6419 memset(&surfaceDesc, 0, sizeof(surfaceDesc));
6421 surfaceDesc.Width = &surfaceWidth;
6422 surfaceDesc.Height = &surfaceHeight;
6423 IWineD3DSurface_GetDesc(pSurface, &surfaceDesc);
6424 /* check to see if it's the backbuffer or the frontbuffer being requested (to make sure the data is up to date)*/
6426 /* Ok, I may need to setup some kind of active swapchain reference on the device */
6427 IWineD3DSurface_GetContainer(pRenderTarget, &IID_IWineD3DSwapChain, (void **)&container);
6429 /* TODO: opengl Context switching for swapchains etc... */
6430 if (NULL != container || pRenderTarget == This->renderTarget || pRenderTarget == This->depthStencilBuffer) {
6431 if (NULL != container && (pRenderTarget == container->backBuffer[0])) {
6432 glReadBuffer(GL_BACK);
6433 vcheckGLcall("glReadBuffer(GL_BACK)");
6434 } else if ((NULL != container && (pRenderTarget == container->frontBuffer)) || (pRenderTarget == This->renderTarget)) {
6435 glReadBuffer(GL_FRONT);
6436 vcheckGLcall("glReadBuffer(GL_FRONT)");
6437 } else if (pRenderTarget == This->depthStencilBuffer) {
6438 FIXME("Reading of depthstencil not yet supported\n");
6441 glReadPixels(surfaceGlDescription->target,
6442 surfaceGlDescription->level,
6445 surfaceGlDescription->glFormat,
6446 surfaceGlDescription->glType,
6447 (void *)IWineD3DSurface_GetData(pSurface));
6448 vcheckGLcall("glReadPixels(...)");
6449 if(NULL != container ){
6450 IWineD3DSwapChain_Release((IWineD3DSwapChain*) container);
6453 IWineD3DBaseTexture *container;
6454 GLenum textureDimensions = GL_TEXTURE_2D;
6456 if (WINED3D_OK == IWineD3DSurface_GetContainer(pSurface, &IID_IWineD3DBaseTexture, (void **)&container)) {
6457 textureDimensions = IWineD3DBaseTexture_GetTextureDimensions(container);
6458 IWineD3DBaseTexture_Release(container);
6460 /* TODO: 2D -> Cube surface coppies etc.. */
6461 if (surfaceGlDescription->target != textureDimensions) {
6462 FIXME("(%p) : Texture dimension mismatch\n", This);
6464 glEnable(textureDimensions);
6465 vcheckGLcall("glEnable(GL_TEXTURE_...)");
6466 /* FIXME: this isn't correct, it need to add a dirty rect if nothing else... */
6467 glBindTexture(targetGlDescription->target, targetGlDescription->textureName);
6468 vcheckGLcall("glBindTexture");
6469 glGetTexImage(surfaceGlDescription->target,
6470 surfaceGlDescription->level,
6471 surfaceGlDescription->glFormat,
6472 surfaceGlDescription->glType,
6473 (void *)IWineD3DSurface_GetData(pSurface));
6474 glDisable(textureDimensions);
6475 vcheckGLcall("glDisable(GL_TEXTURE_...)");
6482 static HRESULT WINAPI IWineD3DDeviceImpl_GetFrontBufferData(IWineD3DDevice *iface,UINT iSwapChain, IWineD3DSurface *pDestSurface) {
6483 IWineD3DSwapChain *swapChain;
6485 hr = IWineD3DDeviceImpl_GetSwapChain(iface, iSwapChain, (IWineD3DSwapChain **)&swapChain);
6486 if(hr == WINED3D_OK) {
6487 hr = IWineD3DSwapChain_GetFrontBufferData(swapChain, pDestSurface);
6488 IWineD3DSwapChain_Release(swapChain);
6493 static HRESULT WINAPI IWineD3DDeviceImpl_ValidateDevice(IWineD3DDevice *iface, DWORD* pNumPasses) {
6494 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
6495 /* return a sensible default */
6497 /* TODO: If the window is minimized then validate device should return something other than WINED3D_OK */
6498 FIXME("(%p) : stub\n", This);
6502 static HRESULT WINAPI IWineD3DDeviceImpl_SetPaletteEntries(IWineD3DDevice *iface, UINT PaletteNumber, CONST PALETTEENTRY* pEntries) {
6503 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
6505 TRACE("(%p) : PaletteNumber %u\n", This, PaletteNumber);
6506 if ( PaletteNumber < 0 || PaletteNumber >= MAX_PALETTES) {
6507 WARN("(%p) : (%u) Out of range 0-%u, returning Invalid Call\n", This, PaletteNumber, MAX_PALETTES);
6508 return WINED3DERR_INVALIDCALL;
6510 for (j = 0; j < 256; ++j) {
6511 This->palettes[PaletteNumber][j].peRed = pEntries[j].peRed;
6512 This->palettes[PaletteNumber][j].peGreen = pEntries[j].peGreen;
6513 This->palettes[PaletteNumber][j].peBlue = pEntries[j].peBlue;
6514 This->palettes[PaletteNumber][j].peFlags = pEntries[j].peFlags;
6516 TRACE("(%p) : returning\n", This);
6520 static HRESULT WINAPI IWineD3DDeviceImpl_GetPaletteEntries(IWineD3DDevice *iface, UINT PaletteNumber, PALETTEENTRY* pEntries) {
6521 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
6523 TRACE("(%p) : PaletteNumber %u\n", This, PaletteNumber);
6524 if ( PaletteNumber < 0 || PaletteNumber >= MAX_PALETTES) {
6525 WARN("(%p) : (%u) Out of range 0-%u, returning Invalid Call\n", This, PaletteNumber, MAX_PALETTES);
6526 return WINED3DERR_INVALIDCALL;
6528 for (j = 0; j < 256; ++j) {
6529 pEntries[j].peRed = This->palettes[PaletteNumber][j].peRed;
6530 pEntries[j].peGreen = This->palettes[PaletteNumber][j].peGreen;
6531 pEntries[j].peBlue = This->palettes[PaletteNumber][j].peBlue;
6532 pEntries[j].peFlags = This->palettes[PaletteNumber][j].peFlags;
6534 TRACE("(%p) : returning\n", This);
6538 static HRESULT WINAPI IWineD3DDeviceImpl_SetCurrentTexturePalette(IWineD3DDevice *iface, UINT PaletteNumber) {
6539 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
6540 TRACE("(%p) : PaletteNumber %u\n", This, PaletteNumber);
6541 if ( PaletteNumber < 0 || PaletteNumber >= MAX_PALETTES) {
6542 WARN("(%p) : (%u) Out of range 0-%u, returning Invalid Call\n", This, PaletteNumber, MAX_PALETTES);
6543 return WINED3DERR_INVALIDCALL;
6545 /*TODO: stateblocks */
6546 This->currentPalette = PaletteNumber;
6547 TRACE("(%p) : returning\n", This);
6551 static HRESULT WINAPI IWineD3DDeviceImpl_GetCurrentTexturePalette(IWineD3DDevice *iface, UINT* PaletteNumber) {
6552 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
6553 if (PaletteNumber == NULL) {
6554 WARN("(%p) : returning Invalid Call\n", This);
6555 return WINED3DERR_INVALIDCALL;
6557 /*TODO: stateblocks */
6558 *PaletteNumber = This->currentPalette;
6559 TRACE("(%p) : returning %u\n", This, *PaletteNumber);
6563 static HRESULT WINAPI IWineD3DDeviceImpl_SetSoftwareVertexProcessing(IWineD3DDevice *iface, BOOL bSoftware) {
6564 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
6565 static BOOL showFixmes = TRUE;
6567 FIXME("(%p) : stub\n", This);
6571 This->softwareVertexProcessing = bSoftware;
6576 static BOOL WINAPI IWineD3DDeviceImpl_GetSoftwareVertexProcessing(IWineD3DDevice *iface) {
6577 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
6578 static BOOL showFixmes = TRUE;
6580 FIXME("(%p) : stub\n", This);
6583 return This->softwareVertexProcessing;
6587 static HRESULT WINAPI IWineD3DDeviceImpl_GetRasterStatus(IWineD3DDevice *iface, UINT iSwapChain, WINED3DRASTER_STATUS* pRasterStatus) {
6588 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
6589 IWineD3DSwapChain *swapChain;
6592 TRACE("(%p) : SwapChain %d returning %p\n", This, iSwapChain, pRasterStatus);
6594 hr = IWineD3DDeviceImpl_GetSwapChain(iface, iSwapChain, (IWineD3DSwapChain **)&swapChain);
6595 if(hr == WINED3D_OK){
6596 hr = IWineD3DSwapChain_GetRasterStatus(swapChain, pRasterStatus);
6597 IWineD3DSwapChain_Release(swapChain);
6599 FIXME("(%p) IWineD3DSwapChain_GetRasterStatus returned in error\n", This);
6605 static HRESULT WINAPI IWineD3DDeviceImpl_SetNPatchMode(IWineD3DDevice *iface, float nSegments) {
6606 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
6607 static BOOL showfixmes = TRUE;
6608 if(nSegments != 0.0f) {
6610 FIXME("(%p) : stub nSegments(%f)\n", This, nSegments);
6617 static float WINAPI IWineD3DDeviceImpl_GetNPatchMode(IWineD3DDevice *iface) {
6618 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
6619 static BOOL showfixmes = TRUE;
6621 FIXME("(%p) : stub returning(%f)\n", This, 0.0f);
6627 static HRESULT WINAPI IWineD3DDeviceImpl_UpdateSurface(IWineD3DDevice *iface, IWineD3DSurface *pSourceSurface, CONST RECT* pSourceRect, IWineD3DSurface *pDestinationSurface, CONST POINT* pDestPoint) {
6628 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *) iface;
6629 /** TODO: remove casts to IWineD3DSurfaceImpl
6630 * NOTE: move code to surface to accomplish this
6631 ****************************************/
6632 IWineD3DSurfaceImpl *pSrcSurface = (IWineD3DSurfaceImpl *)pSourceSurface;
6633 int srcWidth, srcHeight;
6634 unsigned int srcSurfaceWidth, srcSurfaceHeight, destSurfaceWidth, destSurfaceHeight;
6635 WINED3DFORMAT destFormat, srcFormat;
6637 int destLeft, destTop;
6638 WINED3DPOOL srcPool, destPool;
6640 int rowoffset = 0; /* how many bytes to add onto the end of a row to wraparound to the beginning of the next */
6641 glDescriptor *glDescription = NULL;
6642 GLenum textureDimensions = GL_TEXTURE_2D;
6643 IWineD3DBaseTexture *baseTexture;
6645 WINED3DSURFACE_DESC winedesc;
6647 TRACE("(%p) : Source (%p) Rect (%p) Destination (%p) Point(%p)\n", This, pSourceSurface, pSourceRect, pDestinationSurface, pDestPoint);
6648 memset(&winedesc, 0, sizeof(winedesc));
6649 winedesc.Width = &srcSurfaceWidth;
6650 winedesc.Height = &srcSurfaceHeight;
6651 winedesc.Pool = &srcPool;
6652 winedesc.Format = &srcFormat;
6654 IWineD3DSurface_GetDesc(pSourceSurface, &winedesc);
6656 winedesc.Width = &destSurfaceWidth;
6657 winedesc.Height = &destSurfaceHeight;
6658 winedesc.Pool = &destPool;
6659 winedesc.Format = &destFormat;
6660 winedesc.Size = &destSize;
6662 IWineD3DSurface_GetDesc(pDestinationSurface, &winedesc);
6664 if(srcPool != WINED3DPOOL_SYSTEMMEM || destPool != WINED3DPOOL_DEFAULT){
6665 WARN("source %p must be SYSTEMMEM and dest %p must be DEFAULT, returning WINED3DERR_INVALIDCALL\n", pSourceSurface, pDestinationSurface);
6666 return WINED3DERR_INVALIDCALL;
6669 if (destFormat == WINED3DFMT_UNKNOWN) {
6670 TRACE("(%p) : Converting destination surface from WINED3DFMT_UNKNOWN to the source format\n", This);
6671 IWineD3DSurface_SetFormat(pDestinationSurface, srcFormat);
6673 /* Get the update surface description */
6674 IWineD3DSurface_GetDesc(pDestinationSurface, &winedesc);
6677 /* Make sure the surface is loaded and up to date */
6678 IWineD3DSurface_PreLoad(pDestinationSurface);
6680 IWineD3DSurface_GetGlDesc(pDestinationSurface, &glDescription);
6684 /* this needs to be done in lines if the sourceRect != the sourceWidth */
6685 srcWidth = pSourceRect ? pSourceRect->right - pSourceRect->left : srcSurfaceWidth;
6686 srcHeight = pSourceRect ? pSourceRect->top - pSourceRect->bottom : srcSurfaceHeight;
6687 destLeft = pDestPoint ? pDestPoint->x : 0;
6688 destTop = pDestPoint ? pDestPoint->y : 0;
6691 /* This function doesn't support compressed textures
6692 the pitch is just bytesPerPixel * width */
6693 if(srcWidth != srcSurfaceWidth || (pSourceRect != NULL && pSourceRect->left != 0) ){
6694 rowoffset = (srcSurfaceWidth - srcWidth) * pSrcSurface->bytesPerPixel;
6695 offset += pSourceRect->left * pSrcSurface->bytesPerPixel;
6696 /* TODO: do we ever get 3bpp?, would a shift and an add be quicker than a mul (well maybe a cycle or two) */
6698 /* TODO DXT formats */
6700 if(pSourceRect != NULL && pSourceRect->top != 0){
6701 offset += pSourceRect->top * srcWidth * pSrcSurface->bytesPerPixel;
6703 TRACE("(%p) glTexSubImage2D, Level %d, left %d, top %d, width %d, height %d , ftm %d, type %d, memory %p\n"
6705 ,glDescription->level
6710 ,glDescription->glFormat
6711 ,glDescription->glType
6712 ,IWineD3DSurface_GetData(pSourceSurface)
6716 if (IWineD3DSurface_GetData(pSourceSurface) == NULL) {
6718 /* need to lock the surface to get the data */
6719 FIXME("Surfaces has no allocated memory, but should be an in memory only surface\n");
6722 /* TODO: Cube and volume support */
6724 /* not a whole row so we have to do it a line at a time */
6727 /* hopefully using pointer addtion will be quicker than using a point + j * rowoffset */
6728 unsigned char* data =((unsigned char *)IWineD3DSurface_GetData(pSourceSurface)) + offset;
6730 for(j = destTop ; j < (srcHeight + destTop) ; j++){
6732 glTexSubImage2D(glDescription->target
6733 ,glDescription->level
6738 ,glDescription->glFormat
6739 ,glDescription->glType
6740 ,data /* could be quicker using */
6745 } else { /* Full width, so just write out the whole texture */
6747 if (WINED3DFMT_DXT1 == destFormat ||
6748 WINED3DFMT_DXT2 == destFormat ||
6749 WINED3DFMT_DXT3 == destFormat ||
6750 WINED3DFMT_DXT4 == destFormat ||
6751 WINED3DFMT_DXT5 == destFormat) {
6752 if (GL_SUPPORT(EXT_TEXTURE_COMPRESSION_S3TC)) {
6753 if (destSurfaceHeight != srcHeight || destSurfaceWidth != srcWidth) {
6754 /* FIXME: The easy way to do this is lock the destination, and copy the bits accross */
6755 FIXME("Updating part of a compressed texture is not supported at the moment\n");
6756 } if (destFormat != srcFormat) {
6757 FIXME("Updating mixed format compressed texture is not curretly support\n");
6759 GL_EXTCALL(glCompressedTexImage2DARB)(glDescription->target,
6760 glDescription->level,
6761 glDescription->glFormatInternal,
6766 IWineD3DSurface_GetData(pSourceSurface));
6769 FIXME("Attempting to update a DXT compressed texture without hardware support\n");
6774 if (NP2_REPACK == wined3d_settings.nonpower2_mode) {
6776 /* some applications cannot handle odd pitches returned by soft non-power2, so we have
6777 to repack the data from pow2Width/Height to expected Width,Height, this makes the
6778 data returned by GetData non-power2 width/height with hardware non-power2
6779 pow2Width/height are set to surface width height, repacking isn't needed so it
6780 doesn't matter which function gets called. */
6781 glTexSubImage2D(glDescription->target
6782 ,glDescription->level
6787 ,glDescription->glFormat
6788 ,glDescription->glType
6789 ,IWineD3DSurface_GetData(pSourceSurface)
6793 /* not repacked, the data returned by IWineD3DSurface_GetData is pow2Width x pow2Height */
6794 glTexSubImage2D(glDescription->target
6795 ,glDescription->level
6798 ,((IWineD3DSurfaceImpl *)pSourceSurface)->pow2Width
6799 ,((IWineD3DSurfaceImpl *)pSourceSurface)->pow2Height
6800 ,glDescription->glFormat
6801 ,glDescription->glType
6802 ,IWineD3DSurface_GetData(pSourceSurface)
6808 checkGLcall("glTexSubImage2D");
6809 ((IWineD3DSurfaceImpl *)pDestinationSurface)->Flags |= SFLAG_GLDIRTY;
6811 /* I only need to look up baseTexture here, so it may be a good idea to hava a GL_TARGET ->
6812 * GL_DIMENSIONS lookup, or maybe store the dimensions on the surface (but that's making the
6813 * surface bigger than it needs to be hmm.. */
6814 if (WINED3D_OK == IWineD3DSurface_GetContainer(pDestinationSurface, &IID_IWineD3DBaseTexture, (void **)&baseTexture)) {
6815 textureDimensions = IWineD3DBaseTexture_GetTextureDimensions(baseTexture);
6816 IWineD3DBaseTexture_Release(baseTexture);
6819 glDisable(textureDimensions); /* This needs to be managed better.... */
6825 /* Used by DirectX 8 */
6826 static HRESULT WINAPI IWineD3DDeviceImpl_CopyRects(IWineD3DDevice *iface,
6827 IWineD3DSurface* pSourceSurface, CONST RECT* pSourceRectsArray, UINT cRects,
6828 IWineD3DSurface* pDestinationSurface, CONST POINT* pDestPointsArray) {
6830 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
6831 HRESULT hr = WINED3D_OK;
6832 WINED3DFORMAT srcFormat, destFormat;
6833 UINT srcWidth, destWidth;
6834 UINT srcHeight, destHeight;
6836 WINED3DSURFACE_DESC winedesc;
6838 TRACE("(%p) pSrcSur=%p, pSourceRects=%p, cRects=%d, pDstSur=%p, pDestPtsArr=%p\n", This,
6839 pSourceSurface, pSourceRectsArray, cRects, pDestinationSurface, pDestPointsArray);
6842 /* Check that the source texture is in WINED3DPOOL_SYSTEMMEM and the destination texture is in WINED3DPOOL_DEFAULT */
6843 memset(&winedesc, 0, sizeof(winedesc));
6845 winedesc.Format = &srcFormat;
6846 winedesc.Width = &srcWidth;
6847 winedesc.Height = &srcHeight;
6848 winedesc.Size = &srcSize;
6849 IWineD3DSurface_GetDesc(pSourceSurface, &winedesc);
6851 winedesc.Format = &destFormat;
6852 winedesc.Width = &destWidth;
6853 winedesc.Height = &destHeight;
6854 winedesc.Size = NULL;
6855 IWineD3DSurface_GetDesc(pDestinationSurface, &winedesc);
6857 /* Check that the source and destination formats match */
6858 if (srcFormat != destFormat && WINED3DFMT_UNKNOWN != destFormat) {
6859 WARN("(%p) source %p format must match the dest %p format, returning WINED3DERR_INVALIDCALL\n", This, pSourceSurface, pDestinationSurface);
6860 return WINED3DERR_INVALIDCALL;
6861 } else if (WINED3DFMT_UNKNOWN == destFormat) {
6862 TRACE("(%p) : Converting destination surface from WINED3DFMT_UNKNOWN to the source format\n", This);
6863 IWineD3DSurface_SetFormat(pDestinationSurface, srcFormat);
6864 destFormat = srcFormat;
6867 /* Quick if complete copy ... */
6868 if (cRects == 0 && pSourceRectsArray == NULL && pDestPointsArray == NULL) {
6870 if (srcWidth == destWidth && srcHeight == destHeight) {
6871 WINED3DLOCKED_RECT lrSrc;
6872 WINED3DLOCKED_RECT lrDst;
6873 IWineD3DSurface_LockRect(pSourceSurface, &lrSrc, NULL, WINED3DLOCK_READONLY);
6874 IWineD3DSurface_LockRect(pDestinationSurface, &lrDst, NULL, 0L);
6875 TRACE("Locked src and dst, Direct copy as surfaces are equal, w=%d, h=%d\n", srcWidth, srcHeight);
6877 memcpy(lrDst.pBits, lrSrc.pBits, srcSize);
6879 IWineD3DSurface_UnlockRect(pSourceSurface);
6880 IWineD3DSurface_UnlockRect(pDestinationSurface);
6881 TRACE("Unlocked src and dst\n");
6885 FIXME("Wanted to copy all surfaces but size not compatible, returning WINED3DERR_INVALIDCALL\n");
6886 hr = WINED3DERR_INVALIDCALL;
6891 if (NULL != pSourceRectsArray && NULL != pDestPointsArray) {
6893 int bytesPerPixel = ((IWineD3DSurfaceImpl *) pSourceSurface)->bytesPerPixel;
6896 /* Copy rect by rect */
6897 for (i = 0; i < cRects; ++i) {
6898 CONST RECT* r = &pSourceRectsArray[i];
6899 CONST POINT* p = &pDestPointsArray[i];
6902 WINED3DLOCKED_RECT lrSrc;
6903 WINED3DLOCKED_RECT lrDst;
6906 TRACE("Copying rect %d (%ld,%ld),(%ld,%ld) -> (%ld,%ld)\n", i, r->left, r->top, r->right, r->bottom, p->x, p->y);
6907 if (srcFormat == WINED3DFMT_DXT1) {
6908 copyperline = ((r->right - r->left) * bytesPerPixel) / 2; /* DXT1 is half byte per pixel */
6910 copyperline = ((r->right - r->left) * bytesPerPixel);
6913 IWineD3DSurface_LockRect(pSourceSurface, &lrSrc, r, WINED3DLOCK_READONLY);
6914 dest_rect.left = p->x;
6915 dest_rect.top = p->y;
6916 dest_rect.right = p->x + (r->right - r->left);
6917 dest_rect.bottom= p->y + (r->bottom - r->top);
6918 IWineD3DSurface_LockRect(pDestinationSurface, &lrDst, &dest_rect, 0L);
6919 TRACE("Locked src and dst\n");
6921 /* Find where to start */
6922 for (j = 0; j < (r->bottom - r->top - 1); ++j) {
6923 memcpy((char*) lrDst.pBits + (j * lrDst.Pitch), (char*) lrSrc.pBits + (j * lrSrc.Pitch), copyperline);
6925 IWineD3DSurface_UnlockRect(pSourceSurface);
6926 IWineD3DSurface_UnlockRect(pDestinationSurface);
6927 TRACE("Unlocked src and dst\n");
6931 int bytesPerPixel = ((IWineD3DSurfaceImpl *) pSourceSurface)->bytesPerPixel;
6934 WINED3DLOCKED_RECT lrSrc;
6935 WINED3DLOCKED_RECT lrDst;
6938 for(i=0; i < cRects; i++) {
6939 CONST RECT* r = &pSourceRectsArray[i];
6941 TRACE("Copying rect %d (%ld,%ld),(%ld,%ld) -> (0, 0)\n", i, r->left, r->top, r->right, r->bottom);
6942 if (srcFormat == WINED3DFMT_DXT1) {
6943 copyperline = ((r->right - r->left) * bytesPerPixel) / 2; /* DXT1 is half byte per pixel */
6945 copyperline = ((r->right - r->left) * bytesPerPixel);
6947 IWineD3DSurface_LockRect(pSourceSurface, &lrSrc, r, WINED3DLOCK_READONLY);
6950 dest_rect.right = r->right - r->left;
6951 dest_rect.bottom= r->bottom - r->top;
6952 IWineD3DSurface_LockRect(pDestinationSurface, &lrDst, &dest_rect, 0L);
6953 TRACE("Locked src and dst\n");
6954 /* Find where to start */
6955 for (j = 0; j < (r->bottom - r->top - 1); ++j) {
6956 memcpy((char*) lrDst.pBits + (j * lrDst.Pitch), (char*) lrSrc.pBits + (j * lrSrc.Pitch), copyperline);
6958 IWineD3DSurface_UnlockRect(pSourceSurface);
6959 IWineD3DSurface_UnlockRect(pDestinationSurface);
6960 TRACE("Unlocked src and dst\n");
6968 /* Implementation details at http://developer.nvidia.com/attach/6494
6970 http://oss.sgi.com/projects/ogl-sample/registry/NV/evaluators.txt
6971 hmm.. no longer supported use
6972 OpenGL evaluators or tessellate surfaces within your application.
6975 /* http://msdn.microsoft.com/library/default.asp?url=/library/en-us/directx9_c/directx/graphics/reference/d3d/interfaces/idirect3ddevice9/DrawRectPatch.asp */
6976 static HRESULT WINAPI IWineD3DDeviceImpl_DrawRectPatch(IWineD3DDevice *iface, UINT Handle, CONST float* pNumSegs, CONST WINED3DRECTPATCH_INFO* pRectPatchInfo) {
6977 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
6978 TRACE("(%p) Handle(%d) noSegs(%p) rectpatch(%p)\n", This, Handle, pNumSegs, pRectPatchInfo);
6979 FIXME("(%p) : Stub\n", This);
6984 /* http://msdn.microsoft.com/library/default.asp?url=/library/en-us/directx9_c/directx/graphics/reference/d3d/interfaces/idirect3ddevice9/DrawTriPatch.asp */
6985 static HRESULT WINAPI IWineD3DDeviceImpl_DrawTriPatch(IWineD3DDevice *iface, UINT Handle, CONST float* pNumSegs, CONST WINED3DTRIPATCH_INFO* pTriPatchInfo) {
6986 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
6987 TRACE("(%p) Handle(%d) noSegs(%p) tripatch(%p)\n", This, Handle, pNumSegs, pTriPatchInfo);
6988 FIXME("(%p) : Stub\n", This);
6992 static HRESULT WINAPI IWineD3DDeviceImpl_DeletePatch(IWineD3DDevice *iface, UINT Handle) {
6993 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
6994 TRACE("(%p) Handle(%d)\n", This, Handle);
6995 FIXME("(%p) : Stub\n", This);
6999 static HRESULT WINAPI IWineD3DDeviceImpl_ColorFill(IWineD3DDevice *iface, IWineD3DSurface *pSurface, CONST D3DRECT* pRect, D3DCOLOR color) {
7000 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *) iface;
7001 IWineD3DSurfaceImpl *surface = (IWineD3DSurfaceImpl *) pSurface;
7003 TRACE("(%p) Colour fill Surface: %p rect: %p color: %ld\n", This, pSurface, pRect, color);
7005 if (surface->resource.pool != WINED3DPOOL_DEFAULT && surface->resource.pool != WINED3DPOOL_SYSTEMMEM) {
7006 FIXME("call to colorfill with non WINED3DPOOL_DEFAULT or WINED3DPOOL_SYSTEMMEM surface\n");
7007 return WINED3DERR_INVALIDCALL;
7010 /* Just forward this to the DirectDraw blitting engine */
7011 memset(&BltFx, 0, sizeof(BltFx));
7012 BltFx.dwSize = sizeof(BltFx);
7013 BltFx.u5.dwFillColor = color;
7014 return IWineD3DSurface_Blt(pSurface, (RECT *) pRect, NULL, NULL, DDBLT_COLORFILL, &BltFx);
7017 /* rendertarget and deptth stencil functions */
7018 static HRESULT WINAPI IWineD3DDeviceImpl_GetRenderTarget(IWineD3DDevice* iface,DWORD RenderTargetIndex, IWineD3DSurface **ppRenderTarget) {
7019 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
7021 /* FIXME: Implelent RenderTargetIndex >0 */
7022 if(RenderTargetIndex > 0)
7023 FIXME("(%p) : RenderTargetIndex %ld >0 not currently supported\n", This, RenderTargetIndex);
7025 *ppRenderTarget = This->renderTarget;
7026 TRACE("(%p) : RenderTarget %ld Index returning %p\n", This, RenderTargetIndex, *ppRenderTarget);
7027 /* Note inc ref on returned surface */
7028 if(*ppRenderTarget != NULL)
7029 IWineD3DSurface_AddRef(*ppRenderTarget);
7033 static HRESULT WINAPI IWineD3DDeviceImpl_SetFrontBackBuffers(IWineD3DDevice *iface, IWineD3DSurface *Front, IWineD3DSurface *Back) {
7034 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
7035 IWineD3DSurfaceImpl *FrontImpl = (IWineD3DSurfaceImpl *) Front;
7036 IWineD3DSurfaceImpl *BackImpl = (IWineD3DSurfaceImpl *) Back;
7037 IWineD3DSwapChainImpl *Swapchain;
7040 TRACE("(%p)->(%p,%p)\n", This, FrontImpl, BackImpl);
7042 hr = IWineD3DDevice_GetSwapChain(iface, 0, (IWineD3DSwapChain **) &Swapchain);
7043 if(hr != WINED3D_OK) {
7044 ERR("Can't get the swapchain\n");
7048 /* Make sure to release the swapchain */
7049 IWineD3DSwapChain_Release((IWineD3DSwapChain *) Swapchain);
7051 if(FrontImpl && !(FrontImpl->resource.usage & WINED3DUSAGE_RENDERTARGET) ) {
7052 ERR("Trying to set a front buffer which doesn't have WINED3DUSAGE_RENDERTARGET usage\n");
7053 return WINED3DERR_INVALIDCALL;
7055 else if(BackImpl && !(BackImpl->resource.usage & WINED3DUSAGE_RENDERTARGET)) {
7056 ERR("Trying to set a back buffer which doesn't have WINED3DUSAGE_RENDERTARGET usage\n");
7057 return WINED3DERR_INVALIDCALL;
7060 if(Swapchain->frontBuffer != Front) {
7061 TRACE("Changing the front buffer from %p to %p\n", Swapchain->frontBuffer, Front);
7063 if(Swapchain->frontBuffer)
7064 IWineD3DSurface_SetContainer(Swapchain->frontBuffer, NULL);
7065 Swapchain->frontBuffer = Front;
7067 if(Swapchain->frontBuffer) {
7068 IWineD3DSurface_SetContainer(Swapchain->frontBuffer, (IWineD3DBase *) Swapchain);
7072 if(Back && !Swapchain->backBuffer) {
7073 /* We need memory for the back buffer array - only one back buffer this way */
7074 Swapchain->backBuffer = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(IWineD3DSurface *));
7075 if(!Swapchain->backBuffer) {
7076 ERR("Out of memory\n");
7077 return E_OUTOFMEMORY;
7081 if(Swapchain->backBuffer[0] != Back) {
7082 TRACE("Changing the back buffer from %p to %p\n", Swapchain->backBuffer, Back);
7084 if(!Swapchain->backBuffer[0]) {
7085 /* GL was told to draw to the front buffer at creation,
7088 glDrawBuffer(GL_BACK);
7089 checkGLcall("glDrawBuffer(GL_BACK)");
7090 /* Set the backbuffer count to 1 because other code uses it to fing the back buffers */
7091 Swapchain->presentParms.BackBufferCount = 1;
7093 /* That makes problems - disable for now */
7094 /* glDrawBuffer(GL_FRONT); */
7095 checkGLcall("glDrawBuffer(GL_FRONT)");
7096 /* We have lost our back buffer, set this to 0 to avoid confusing other code */
7097 Swapchain->presentParms.BackBufferCount = 0;
7101 if(Swapchain->backBuffer[0])
7102 IWineD3DSurface_SetContainer(Swapchain->backBuffer[0], NULL);
7103 Swapchain->backBuffer[0] = Back;
7105 if(Swapchain->backBuffer[0]) {
7106 IWineD3DSurface_SetContainer(Swapchain->backBuffer[0], (IWineD3DBase *) Swapchain);
7108 HeapFree(GetProcessHeap(), 0, Swapchain->backBuffer);
7116 static HRESULT WINAPI IWineD3DDeviceImpl_GetDepthStencilSurface(IWineD3DDevice* iface, IWineD3DSurface **ppZStencilSurface) {
7117 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
7118 *ppZStencilSurface = This->depthStencilBuffer;
7119 TRACE("(%p) : zStencilSurface returning %p\n", This, *ppZStencilSurface);
7121 if(*ppZStencilSurface != NULL) {
7122 /* Note inc ref on returned surface */
7123 IWineD3DSurface_AddRef(*ppZStencilSurface);
7128 /* internal static helper functions */
7129 static HRESULT WINAPI IWineD3DDeviceImpl_ActiveRender(IWineD3DDevice* iface,
7130 IWineD3DSurface *RenderSurface);
7132 static HRESULT WINAPI IWineD3DDeviceImpl_SetRenderTarget(IWineD3DDevice *iface, DWORD RenderTargetIndex, IWineD3DSurface *pRenderTarget) {
7133 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
7134 HRESULT hr = WINED3D_OK;
7135 WINED3DVIEWPORT viewport;
7137 TRACE("(%p) Swapping rendertarget\n",This);
7138 if (RenderTargetIndex > 0) {
7139 FIXME("(%p) Render targets other than the first are not supported\n",This);
7140 RenderTargetIndex = 0;
7143 /* MSDN says that null disables the render target
7144 but a device must always be associated with a render target
7145 nope MSDN says that we return invalid call to a null rendertarget with an index of 0
7147 see http://msdn.microsoft.com/library/default.asp?url=/library/en-us/directx9_c/directx/graphics/programmingguide/AdvancedTopics/PixelPipe/MultipleRenderTarget.asp
7150 if (RenderTargetIndex == 0 && pRenderTarget == NULL) {
7151 FIXME("Trying to set render target 0 to NULL\n");
7152 return WINED3DERR_INVALIDCALL;
7154 /* TODO: replace Impl* usage with interface usage */
7155 if (!((IWineD3DSurfaceImpl *)pRenderTarget)->resource.usage & WINED3DUSAGE_RENDERTARGET) {
7156 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);
7157 return WINED3DERR_INVALIDCALL;
7159 /** TODO: check that the depth stencil format matches the render target, this is only done in debug
7160 * builds, but I think wine counts as a 'debug' build for now.
7161 ******************************/
7162 /* If we are trying to set what we already have, don't bother */
7163 if (pRenderTarget == This->renderTarget) {
7164 TRACE("Trying to do a NOP SetRenderTarget operation\n");
7166 /* Otherwise, set the render target up */
7168 if (!This->sceneEnded) {
7169 IWineD3DDevice_EndScene(iface);
7171 TRACE("clearing renderer\n");
7172 /* IWineD3DDeviceImpl_CleanRender(iface); */
7173 /* OpenGL doesn't support 'sharing' of the stencilBuffer so we may incure an extra memory overhead
7174 depending on the renter target implementation being used.
7175 A shared context implementation will share all buffers between all rendertargets (including swapchains),
7176 implementations that use separate pbuffers for different swapchains or rendertargets will have to duplicate the
7177 stencil buffer and incure an extra memory overhead */
7178 hr = IWineD3DDeviceImpl_ActiveRender(iface, pRenderTarget);
7181 if (SUCCEEDED(hr)) {
7182 /* Finally, reset the viewport as the MSDN states. */
7183 /* TODO: Replace impl usage */
7184 viewport.Height = ((IWineD3DSurfaceImpl *)This->renderTarget)->currentDesc.Height;
7185 viewport.Width = ((IWineD3DSurfaceImpl *)This->renderTarget)->currentDesc.Width;
7188 viewport.MaxZ = 1.0f;
7189 viewport.MinZ = 0.0f;
7190 IWineD3DDeviceImpl_SetViewport(iface, &viewport);
7192 FIXME("Unknown error setting the render target\n");
7194 This->sceneEnded = FALSE;
7198 static HRESULT WINAPI IWineD3DDeviceImpl_SetDepthStencilSurface(IWineD3DDevice *iface, IWineD3DSurface *pNewZStencil) {
7199 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
7200 HRESULT hr = WINED3D_OK;
7201 IWineD3DSurface *tmp;
7203 TRACE("(%p) Swapping z-buffer\n",This);
7205 if (pNewZStencil == This->stencilBufferTarget) {
7206 TRACE("Trying to do a NOP SetRenderTarget operation\n");
7208 /** OpenGL doesn't support 'sharing' of the stencilBuffer so we may incure an extra memory overhead
7209 * depending on the renter target implementation being used.
7210 * A shared context implementation will share all buffers between all rendertargets (including swapchains),
7211 * implementations that use separate pbuffers for different swapchains or rendertargets will have to duplicate the
7212 * stencil buffer and incure an extra memory overhead
7213 ******************************************************/
7216 tmp = This->stencilBufferTarget;
7217 This->stencilBufferTarget = pNewZStencil;
7218 /* should we be calling the parent or the wined3d surface? */
7219 if (NULL != This->stencilBufferTarget) IWineD3DSurface_AddRef(This->stencilBufferTarget);
7220 if (NULL != tmp) IWineD3DSurface_Release(tmp);
7222 /** TODO: glEnable/glDisable on depth/stencil depending on
7223 * pNewZStencil is NULL and the depth/stencil is enabled in d3d
7224 **********************************************************/
7231 #ifdef GL_VERSION_1_3
7232 /* Internal functions not in DirectX */
7233 /** TODO: move this off to the opengl context manager
7234 *(the swapchain doesn't need to know anything about offscreen rendering!)
7235 ****************************************************/
7237 static HRESULT WINAPI IWineD3DDeviceImpl_CleanRender(IWineD3DDevice* iface, IWineD3DSwapChainImpl *swapchain)
7239 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
7241 TRACE("(%p), %p\n", This, swapchain);
7243 if (swapchain->win != swapchain->drawable) {
7244 /* Set everything back the way it ws */
7245 swapchain->render_ctx = swapchain->glCtx;
7246 swapchain->drawable = swapchain->win;
7251 /* TODO: move this off into a context manager so that GLX_ATI_render_texture and other types of surface can be used. */
7252 static HRESULT WINAPI IWineD3DDeviceImpl_FindGLContext(IWineD3DDevice *iface, IWineD3DSurface *pSurface, glContext **context) {
7253 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
7256 unsigned int height;
7257 WINED3DFORMAT format;
7258 WINED3DSURFACE_DESC surfaceDesc;
7259 memset(&surfaceDesc, 0, sizeof(surfaceDesc));
7260 surfaceDesc.Width = &width;
7261 surfaceDesc.Height = &height;
7262 surfaceDesc.Format = &format;
7263 IWineD3DSurface_GetDesc(pSurface, &surfaceDesc);
7265 /* I need a get width/height function (and should do something with the format) */
7266 for (i = 0; i < CONTEXT_CACHE; ++i) {
7267 /** NOTE: the contextCache[i].pSurface == pSurface check ceates onepbuffer per surface
7268 ATI cards don't destroy pbuffers, but as soon as resource releasing callbacks are inplace
7269 the pSurface can be set to 0 allowing it to be reused from cache **/
7270 if (This->contextCache[i].Width == width && This->contextCache[i].Height == height
7271 && (!pbuffer_per_surface || This->contextCache[i].pSurface == pSurface || This->contextCache[i].pSurface == NULL)) {
7272 *context = &This->contextCache[i];
7275 if (This->contextCache[i].Width == 0) {
7276 This->contextCache[i].pSurface = pSurface;
7277 This->contextCache[i].Width = width;
7278 This->contextCache[i].Height = height;
7279 *context = &This->contextCache[i];
7283 if (i == CONTEXT_CACHE) {
7284 int minUsage = 0x7FFFFFFF; /* MAX_INT */
7285 glContext *dropContext = 0;
7286 for (i = 0; i < CONTEXT_CACHE; i++) {
7287 if (This->contextCache[i].usedcount < minUsage) {
7288 dropContext = &This->contextCache[i];
7289 minUsage = This->contextCache[i].usedcount;
7292 /* clean up the context (this doesn't work for ATI at the moment */
7294 glXDestroyContext(swapchain->display, dropContext->context);
7295 glXDestroyPbuffer(swapchain->display, dropContext->drawable);
7298 dropContext->Width = 0;
7299 dropContext->pSurface = pSurface;
7300 *context = dropContext;
7302 if (++This->contextCache[i].usedcount == 0x7FFFFFFF /* MAX_INT */ - 1 ) {
7303 for (i = 0; i < CONTEXT_CACHE; i++) {
7304 This->contextCache[i].usedcount = max(0, This->contextCache[i].usedcount - (0x7FFFFFFF /* MAX_INT */ >> 1));
7308 if (*context != NULL)
7311 return E_OUTOFMEMORY;
7315 /* Reapply the device stateblock */
7316 static void device_reapply_stateblock(IWineD3DDeviceImpl* This) {
7319 IWineD3DStateBlockImpl *oldUpdateStateBlock;
7321 /* Disable recording */
7322 oldUpdateStateBlock = This->updateStateBlock;
7323 oldRecording= This->isRecordingState;
7324 This->isRecordingState = FALSE;
7325 This->updateStateBlock = This->stateBlock;
7327 /* Reapply the state block */
7328 IWineD3DStateBlock_Apply((IWineD3DStateBlock *)This->stateBlock);
7330 /* Restore recording */
7331 This->isRecordingState = oldRecording;
7332 This->updateStateBlock = oldUpdateStateBlock;
7335 /* Set the device to render to a texture, or not.
7336 * This involves changing renderUpsideDown */
7338 static void device_render_to_texture(IWineD3DDeviceImpl* This, BOOL isTexture) {
7342 IWineD3DStateBlockImpl *oldUpdateStateBlock;
7344 /* Disable recording */
7345 oldUpdateStateBlock = This->updateStateBlock;
7346 oldRecording= This->isRecordingState;
7347 This->isRecordingState = FALSE;
7348 This->updateStateBlock = This->stateBlock;
7350 /* Set upside-down rendering, and update the cull mode */
7351 /* The surface must be rendered upside down to cancel the flip produced by glCopyTexImage */
7352 This->renderUpsideDown = isTexture;
7353 This->last_was_rhw = FALSE;
7354 This->proj_valid = FALSE;
7355 IWineD3DDevice_GetRenderState((IWineD3DDevice*) This, WINED3DRS_CULLMODE, &cullMode);
7356 IWineD3DDevice_SetRenderState((IWineD3DDevice*) This, WINED3DRS_CULLMODE, cullMode);
7358 /* Restore recording */
7359 This->isRecordingState = oldRecording;
7360 This->updateStateBlock = oldUpdateStateBlock;
7363 /* Returns an array of compatible FBconfig(s).
7364 * The array must be freed with XFree. Requires ENTER_GL() */
7366 static GLXFBConfig* device_find_fbconfigs(
7367 IWineD3DDeviceImpl* This,
7368 IWineD3DSwapChainImpl* implicitSwapchainImpl,
7369 IWineD3DSurface* RenderSurface) {
7371 GLXFBConfig* cfgs = NULL;
7376 IWineD3DSurface *StencilSurface = This->stencilBufferTarget;
7377 D3DFORMAT BackBufferFormat = ((IWineD3DSurfaceImpl *) RenderSurface)->resource.format;
7378 D3DFORMAT StencilBufferFormat = (NULL != StencilSurface) ? ((IWineD3DSurfaceImpl *) StencilSurface)->resource.format : 0;
7381 if StencilSurface == NULL && zBufferTarget != NULL then switch the zbuffer off,
7382 it StencilSurface != NULL && zBufferTarget == NULL switch it on
7385 #define PUSH1(att) attribs[nAttribs++] = (att);
7386 #define PUSH2(att,value) attribs[nAttribs++] = (att); attribs[nAttribs++] = (value);
7388 /* PUSH2(GLX_BIND_TO_TEXTURE_RGBA_ATI, True); examples of this are few and far between (but I've got a nice working one!)*/
7390 PUSH2(GLX_DRAWABLE_TYPE, GLX_PBUFFER_BIT);
7391 PUSH2(GLX_X_RENDERABLE, TRUE);
7392 PUSH2(GLX_DOUBLEBUFFER, TRUE);
7393 TRACE("calling makeglcfg\n");
7394 D3DFmtMakeGlCfg(BackBufferFormat, StencilBufferFormat, attribs, &nAttribs, FALSE /* alternate */);
7396 TRACE("calling chooseFGConfig\n");
7397 cfgs = glXChooseFBConfig(implicitSwapchainImpl->display,
7398 DefaultScreen(implicitSwapchainImpl->display),
7401 /* OK we didn't find the exact config, so use any reasonable match */
7402 /* TODO: fill in the 'requested' and 'current' depths, and make sure that's
7404 static BOOL show_message = TRUE;
7406 ERR("Failed to find exact match, finding alternative but you may "
7407 "suffer performance issues, try changing xfree's depth to match the requested depth\n");
7408 show_message = FALSE;
7411 PUSH2(GLX_DRAWABLE_TYPE, GLX_PBUFFER_BIT | GLX_WINDOW_BIT);
7412 /* PUSH2(GLX_X_RENDERABLE, TRUE); */
7413 PUSH2(GLX_RENDER_TYPE, GLX_RGBA_BIT);
7414 PUSH2(GLX_DOUBLEBUFFER, FALSE);
7415 TRACE("calling makeglcfg\n");
7416 D3DFmtMakeGlCfg(BackBufferFormat, StencilBufferFormat, attribs, &nAttribs, TRUE /* alternate */);
7418 cfgs = glXChooseFBConfig(implicitSwapchainImpl->display,
7419 DefaultScreen(implicitSwapchainImpl->display),
7424 ERR("Could not get a valid FBConfig for (%u,%s)/(%u,%s)\n",
7425 BackBufferFormat, debug_d3dformat(BackBufferFormat),
7426 StencilBufferFormat, debug_d3dformat(StencilBufferFormat));
7430 for (i = 0; i < nCfgs; ++i) {
7431 TRACE("for (%u,%s)/(%u,%s) found config[%d]@%p\n", BackBufferFormat,
7432 debug_d3dformat(BackBufferFormat), StencilBufferFormat,
7433 debug_d3dformat(StencilBufferFormat), i, cfgs[i]);
7435 if (NULL != This->renderTarget) {
7437 vcheckGLcall("glFlush");
7438 /** This is only useful if the old render target was a swapchain,
7439 * we need to supercede this with a function that displays
7440 * the current buffer on the screen. This is easy to do in glx1.3 but
7441 * we need to do copy-write pixels in glx 1.2.
7442 ************************************************/
7443 glXSwapBuffers(implicitSwapChainImpl->display,
7444 implicitSwapChainImpl->drawable);
7445 printf("Hit Enter to get next frame ...\n");
7456 /** FIXME: This is currently used called whenever SetRenderTarget or SetStencilBuffer are called
7457 * the functionality needs splitting up so that we don't do more than we should do.
7458 * this only seems to impact performance a little.
7459 ******************************/
7460 static HRESULT WINAPI IWineD3DDeviceImpl_ActiveRender(IWineD3DDevice* iface,
7461 IWineD3DSurface *RenderSurface) {
7464 * Currently only active for GLX >= 1.3
7465 * for others versions we'll have to use GLXPixmaps
7467 * normally we must test GLX_VERSION_1_3 but nvidia headers are not correct
7468 * as they implement GLX 1.3 but only define GLX_VERSION_1_2
7469 * so only check OpenGL version
7470 * ..........................
7471 * I don't believe that it is a problem with NVidia headers,
7472 * XFree only supports GLX1.2, nVidia (and ATI to some extent) provide 1.3 functions
7473 * in GLX 1.2, there is no mention of the correct way to tell if the extensions are provided.
7475 * Your application will report GLX version 1.2 on glXQueryVersion.
7476 * However, it is safe to call the GLX 1.3 functions as described below.
7478 #if defined(GL_VERSION_1_3)
7480 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
7481 GLXFBConfig* cfgs = NULL;
7482 IWineD3DSwapChain *currentSwapchain;
7483 IWineD3DSwapChainImpl *currentSwapchainImpl;
7484 IWineD3DSwapChain *implicitSwapchain;
7485 IWineD3DSwapChainImpl *implicitSwapchainImpl;
7486 IWineD3DSwapChain *renderSurfaceSwapchain;
7487 IWineD3DSwapChainImpl *renderSurfaceSwapchainImpl;
7489 /* Obtain a reference to the device implicit swapchain,
7490 * the swapchain of the current render target,
7491 * and the swapchain of the new render target.
7492 * Fallback to device implicit swapchain if the current render target doesn't have one */
7493 IWineD3DDevice_GetSwapChain(iface, 0, &implicitSwapchain);
7494 IWineD3DSurface_GetContainer(RenderSurface, &IID_IWineD3DSwapChain, (void**) &renderSurfaceSwapchain);
7495 IWineD3DSurface_GetContainer(This->renderTarget, &IID_IWineD3DSwapChain, (void **)¤tSwapchain);
7496 if (currentSwapchain == NULL)
7497 IWineD3DDevice_GetSwapChain(iface, 0, ¤tSwapchain);
7499 currentSwapchainImpl = (IWineD3DSwapChainImpl*) currentSwapchain;
7500 implicitSwapchainImpl = (IWineD3DSwapChainImpl*) implicitSwapchain;
7501 renderSurfaceSwapchainImpl = (IWineD3DSwapChainImpl*) renderSurfaceSwapchain;
7506 * TODO: remove the use of IWineD3DSwapChainImpl, a context manager will help since it will replace the
7507 * renderTarget = swapchain->backBuffer[i] bit and anything to do with *glContexts
7508 **********************************************************************/
7509 if (renderSurfaceSwapchain != NULL) {
7511 /* We also need to make sure that the lights &co are also in the context of the swapchains */
7512 /* FIXME: If the render target gets sent to the frontBuffer should be be presenting it raw? */
7513 TRACE("making swapchain active\n");
7514 if (RenderSurface != This->renderTarget) {
7515 BOOL backbuf = FALSE;
7518 for(i = 0; i < renderSurfaceSwapchainImpl->presentParms.BackBufferCount; i++) {
7519 if(RenderSurface == renderSurfaceSwapchainImpl->backBuffer[i]) {
7527 /* This could be flagged so that some operations work directly with the front buffer */
7528 FIXME("Attempting to set the renderTarget to the frontBuffer\n");
7530 if (glXMakeCurrent(renderSurfaceSwapchainImpl->display,
7531 renderSurfaceSwapchainImpl->win,
7532 renderSurfaceSwapchainImpl->glCtx) == False) {
7534 TRACE("Error in setting current context: context %p drawable %ld !\n",
7535 implicitSwapchainImpl->glCtx, implicitSwapchainImpl->win);
7537 checkGLcall("glXMakeContextCurrent");
7539 /* Clean up the old context */
7540 IWineD3DDeviceImpl_CleanRender(iface, currentSwapchainImpl);
7542 /* Reapply the stateblock, and set the device not to render to texture */
7543 device_reapply_stateblock(This);
7544 device_render_to_texture(This, FALSE);
7547 /* Offscreen rendering: PBuffers (currently disabled).
7548 * Also note that this path is never reached if FBOs are supported */
7549 } else if (pbuffer_support &&
7550 (cfgs = device_find_fbconfigs(This, implicitSwapchainImpl, RenderSurface)) != NULL) {
7552 /** ********************************************************************
7553 * This is a quickly hacked out implementation of offscreen textures.
7554 * It will work in most cases but there may be problems if the client
7555 * modifies the texture directly, or expects the contents of the rendertarget
7558 * There are some real speed vs compatibility issues here:
7559 * we should really use a new context for every texture, but that eats ram.
7560 * we should also be restoring the texture to the pbuffer but that eats CPU
7561 * we can also 'reuse' the current pbuffer if the size is larger than the requested buffer,
7562 * but if this means reusing the display backbuffer then we need to make sure that
7563 * states are correctly preserved.
7564 * In many cases I would expect that we can 'skip' some functions, such as preserving states,
7565 * and gain a good performance increase at the cost of compatibility.
7566 * I would suggest that, when this is the case, a user configurable flag be made
7567 * available, allowing the user to choose the best emulated experience for them.
7568 *********************************************************************/
7570 XVisualInfo *visinfo;
7571 glContext *newContext;
7573 /* Here were using a shared context model */
7574 if (WINED3D_OK != IWineD3DDeviceImpl_FindGLContext(iface, RenderSurface, &newContext)) {
7575 FIXME("(%p) : Failed to find a context for surface %p\n", iface, RenderSurface);
7578 /* If the context doesn't exist then create a new one */
7579 /* TODO: This should really be part of findGlContext */
7580 if (NULL == newContext->context) {
7585 TRACE("making new buffer\n");
7586 attribs[nAttribs++] = GLX_PBUFFER_WIDTH;
7587 attribs[nAttribs++] = newContext->Width;
7588 attribs[nAttribs++] = GLX_PBUFFER_HEIGHT;
7589 attribs[nAttribs++] = newContext->Height;
7590 attribs[nAttribs++] = None;
7592 newContext->drawable = glXCreatePbuffer(implicitSwapchainImpl->display, cfgs[0], attribs);
7594 /** ****************************************
7595 *GLX1.3 isn't supported by XFree 'yet' until that point ATI emulates pBuffers
7597 * In future releases, we may provide the calls glXCreateNewContext,
7598 * glXQueryDrawable and glXMakeContextCurrent.
7599 * so until then we have to use glXGetVisualFromFBConfig &co..
7600 ********************************************/
7602 visinfo = glXGetVisualFromFBConfig(implicitSwapchainImpl->display, cfgs[0]);
7604 ERR("Error: couldn't get an RGBA, double-buffered visual\n");
7606 newContext->context = glXCreateContext(
7607 implicitSwapchainImpl->display, visinfo,
7608 implicitSwapchainImpl->glCtx, GL_TRUE);
7613 if (NULL == newContext || NULL == newContext->context) {
7614 ERR("(%p) : Failed to find a context for surface %p\n", iface, RenderSurface);
7616 /* Debug logging, (this function leaks), change to a TRACE when the leak is plugged */
7617 if (glXMakeCurrent(implicitSwapchainImpl->display,
7618 newContext->drawable, newContext->context) == False) {
7620 TRACE("Error in setting current context: context %p drawable %ld\n",
7621 newContext->context, newContext->drawable);
7623 checkGLcall("glXMakeContextCurrent");
7625 /* Clean up the old context */
7626 IWineD3DDeviceImpl_CleanRender(iface, currentSwapchainImpl);
7628 /* Reapply stateblock, and set device to render to a texture */
7629 device_reapply_stateblock(This);
7630 device_render_to_texture(This, TRUE);
7632 /* Set the current context of the swapchain to the new context */
7633 implicitSwapchainImpl->drawable = newContext->drawable;
7634 implicitSwapchainImpl->render_ctx = newContext->context;
7637 /* Same context, but update renderUpsideDown and cull mode */
7638 device_render_to_texture(This, TRUE);
7641 /* Replace the render target */
7642 if (This->renderTarget != RenderSurface) {
7643 IWineD3DSurface_Release(This->renderTarget);
7644 This->renderTarget = RenderSurface;
7645 IWineD3DSurface_AddRef(RenderSurface);
7648 if (cfgs != NULL) XFree(cfgs);
7649 if (implicitSwapchain != NULL) IWineD3DSwapChain_Release(implicitSwapchain);
7650 if (currentSwapchain != NULL) IWineD3DSwapChain_Release(currentSwapchain);
7651 if (renderSurfaceSwapchain != NULL) IWineD3DSwapChain_Release(renderSurfaceSwapchain);
7657 static HRESULT WINAPI IWineD3DDeviceImpl_SetCursorProperties(IWineD3DDevice* iface, UINT XHotSpot,
7658 UINT YHotSpot, IWineD3DSurface *pCursorBitmap) {
7659 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *) iface;
7660 /* TODO: the use of Impl is deprecated. */
7661 IWineD3DSurfaceImpl * pSur = (IWineD3DSurfaceImpl *) pCursorBitmap;
7663 TRACE("(%p) : Spot Pos(%u,%u)\n", This, XHotSpot, YHotSpot);
7665 /* some basic validation checks */
7666 if(This->cursorTexture) {
7668 glDeleteTextures(1, &This->cursorTexture);
7670 This->cursorTexture = 0;
7674 /* MSDN: Cursor must be A8R8G8B8 */
7675 if (WINED3DFMT_A8R8G8B8 != pSur->resource.format) {
7676 ERR("(%p) : surface(%p) has an invalid format\n", This, pCursorBitmap);
7677 return WINED3DERR_INVALIDCALL;
7680 /* MSDN: Cursor must be smaller than the display mode */
7681 if(pSur->currentDesc.Width > This->ddraw_width ||
7682 pSur->currentDesc.Height > This->ddraw_height) {
7683 ERR("(%p) : Surface(%p) is %dx%d pixels, but screen res is %ldx%ld\n", This, pSur, pSur->currentDesc.Width, pSur->currentDesc.Height, This->ddraw_width, This->ddraw_height);
7684 return WINED3DERR_INVALIDCALL;
7687 /* TODO: MSDN: Cursor sizes must be a power of 2 */
7688 /* This is to tell our texture code to load a SCRATCH surface. This allows us to use out
7689 * Texture and Blitting code to draw the cursor
7691 pSur->Flags |= SFLAG_FORCELOAD;
7692 IWineD3DSurface_PreLoad(pCursorBitmap);
7693 pSur->Flags &= ~SFLAG_FORCELOAD;
7694 /* Do not store the surface's pointer because the application may release
7695 * it after setting the cursor image. Windows doesn't addref the set surface, so we can't
7696 * do this either without creating circular refcount dependencies. Copy out the gl texture instead.
7698 This->cursorTexture = pSur->glDescription.textureName;
7699 This->cursorWidth = pSur->currentDesc.Width;
7700 This->cursorHeight = pSur->currentDesc.Height;
7701 pSur->glDescription.textureName = 0; /* Prevent the texture from being changed or deleted */
7704 This->xHotSpot = XHotSpot;
7705 This->yHotSpot = YHotSpot;
7709 static void WINAPI IWineD3DDeviceImpl_SetCursorPosition(IWineD3DDevice* iface, int XScreenSpace, int YScreenSpace, DWORD Flags) {
7710 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *) iface;
7711 TRACE("(%p) : SetPos to (%u,%u)\n", This, XScreenSpace, YScreenSpace);
7713 This->xScreenSpace = XScreenSpace;
7714 This->yScreenSpace = YScreenSpace;
7720 static BOOL WINAPI IWineD3DDeviceImpl_ShowCursor(IWineD3DDevice* iface, BOOL bShow) {
7721 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *) iface;
7722 BOOL oldVisible = This->bCursorVisible;
7723 TRACE("(%p) : visible(%d)\n", This, bShow);
7725 if(This->cursorTexture)
7726 This->bCursorVisible = bShow;
7731 static HRESULT WINAPI IWineD3DDeviceImpl_TestCooperativeLevel(IWineD3DDevice* iface) {
7732 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *) iface;
7733 TRACE("(%p) : state (%lu)\n", This, This->state);
7734 /* TODO: Implement wrapping of the WndProc so that mimimize and maxamise can be monitored and the states adjusted. */
7735 switch (This->state) {
7738 case WINED3DERR_DEVICELOST:
7740 ResourceList *resourceList = This->resources;
7741 while (NULL != resourceList) {
7742 if (((IWineD3DResourceImpl *)resourceList->resource)->resource.pool == WINED3DPOOL_DEFAULT /* TODO: IWineD3DResource_GetPool(resourceList->resource)*/)
7743 return WINED3DERR_DEVICENOTRESET;
7744 resourceList = resourceList->next;
7746 return WINED3DERR_DEVICELOST;
7748 case WINED3DERR_DRIVERINTERNALERROR:
7749 return WINED3DERR_DRIVERINTERNALERROR;
7753 return WINED3DERR_DRIVERINTERNALERROR;
7757 static HRESULT WINAPI IWineD3DDeviceImpl_EvictManagedResources(IWineD3DDevice* iface) {
7758 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *) iface;
7759 /** FIXME: Resource tracking needs to be done,
7760 * The closes we can do to this is set the priorities of all managed textures low
7761 * and then reset them.
7762 ***********************************************************/
7763 FIXME("(%p) : stub\n", This);
7767 static HRESULT WINAPI IWineD3DDeviceImpl_Reset(IWineD3DDevice* iface, WINED3DPRESENT_PARAMETERS* pPresentationParameters) {
7768 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *) iface;
7769 /** FIXME: Resource trascking needs to be done.
7770 * in effect this pulls all non only default
7771 * textures out of video memory and deletes all glTextures (glDeleteTextures)
7772 * and should clear down the context and set it up according to pPresentationParameters
7773 ***********************************************************/
7774 FIXME("(%p) : stub\n", This);
7778 static HRESULT WINAPI IWineD3DDeviceImpl_SetDialogBoxMode(IWineD3DDevice *iface, BOOL bEnableDialogs) {
7779 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
7780 /** FIXME: always true at the moment **/
7781 if(!bEnableDialogs) {
7782 FIXME("(%p) Dialogs cannot be disabled yet\n", This);
7788 static HRESULT WINAPI IWineD3DDeviceImpl_GetCreationParameters(IWineD3DDevice *iface, WINED3DDEVICE_CREATION_PARAMETERS *pParameters) {
7789 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *) iface;
7790 TRACE("(%p) : pParameters %p\n", This, pParameters);
7792 *pParameters = This->createParms;
7796 static void WINAPI IWineD3DDeviceImpl_SetGammaRamp(IWineD3DDevice * iface, UINT iSwapChain, DWORD Flags, CONST WINED3DGAMMARAMP* pRamp) {
7797 IWineD3DSwapChain *swapchain;
7798 HRESULT hrc = WINED3D_OK;
7800 TRACE("Relaying to swapchain\n");
7802 if ((hrc = IWineD3DDeviceImpl_GetSwapChain(iface, iSwapChain, &swapchain)) == WINED3D_OK) {
7803 IWineD3DSwapChain_SetGammaRamp(swapchain, Flags, (WINED3DGAMMARAMP *)pRamp);
7804 IWineD3DSwapChain_Release(swapchain);
7809 static void WINAPI IWineD3DDeviceImpl_GetGammaRamp(IWineD3DDevice *iface, UINT iSwapChain, WINED3DGAMMARAMP* pRamp) {
7810 IWineD3DSwapChain *swapchain;
7811 HRESULT hrc = WINED3D_OK;
7813 TRACE("Relaying to swapchain\n");
7815 if ((hrc = IWineD3DDeviceImpl_GetSwapChain(iface, iSwapChain, &swapchain)) == WINED3D_OK) {
7816 hrc =IWineD3DSwapChain_GetGammaRamp(swapchain, pRamp);
7817 IWineD3DSwapChain_Release(swapchain);
7823 /** ********************************************************
7824 * Notification functions
7825 ** ********************************************************/
7826 /** This function must be called in the release of a resource when ref == 0,
7827 * the contents of resource must still be correct,
7828 * any handels to other resource held by the caller must be closed
7829 * (e.g. a texture should release all held surfaces because telling the device that it's been released.)
7830 *****************************************************/
7831 static void WINAPI IWineD3DDeviceImpl_AddResource(IWineD3DDevice *iface, IWineD3DResource *resource){
7832 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
7833 ResourceList* resourceList;
7835 TRACE("(%p) : resource %p\n", This, resource);
7837 EnterCriticalSection(&resourceStoreCriticalSection);
7839 /* add a new texture to the frot of the linked list */
7840 resourceList = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(ResourceList));
7841 resourceList->resource = resource;
7843 /* Get the old head */
7844 resourceList->next = This->resources;
7846 This->resources = resourceList;
7847 TRACE("Added resource %p with element %p pointing to %p\n", resource, resourceList, resourceList->next);
7850 LeaveCriticalSection(&resourceStoreCriticalSection);
7855 static void WINAPI IWineD3DDeviceImpl_RemoveResource(IWineD3DDevice *iface, IWineD3DResource *resource){
7856 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
7857 ResourceList* resourceList = NULL;
7858 ResourceList* previousResourceList = NULL;
7860 TRACE("(%p) : resource %p\n", This, resource);
7863 EnterCriticalSection(&resourceStoreCriticalSection);
7865 resourceList = This->resources;
7867 while (resourceList != NULL) {
7868 if(resourceList->resource == resource) break;
7869 previousResourceList = resourceList;
7870 resourceList = resourceList->next;
7873 if (resourceList == NULL) {
7874 FIXME("Attempted to remove resource %p that hasn't been stored\n", resource);
7876 LeaveCriticalSection(&resourceStoreCriticalSection);
7880 TRACE("Found resource %p with element %p pointing to %p (previous %p)\n", resourceList->resource, resourceList, resourceList->next, previousResourceList);
7882 /* make sure we don't leave a hole in the list */
7883 if (previousResourceList != NULL) {
7884 previousResourceList->next = resourceList->next;
7886 This->resources = resourceList->next;
7890 LeaveCriticalSection(&resourceStoreCriticalSection);
7896 static void WINAPI IWineD3DDeviceImpl_ResourceReleased(IWineD3DDevice *iface, IWineD3DResource *resource){
7897 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *) iface;
7900 TRACE("(%p) : resource %p\n", This, resource);
7901 switch(IWineD3DResource_GetType(resource)){
7902 case WINED3DRTYPE_SURFACE:
7903 /* TODO: check front and back buffers, rendertargets etc.. possibly swapchains? */
7905 case WINED3DRTYPE_TEXTURE:
7906 case WINED3DRTYPE_CUBETEXTURE:
7907 case WINED3DRTYPE_VOLUMETEXTURE:
7908 for (counter = 0; counter < GL_LIMITS(sampler_stages); counter++) {
7909 if (This->stateBlock != NULL && This->stateBlock->textures[counter] == (IWineD3DBaseTexture *)resource) {
7910 WARN("Texture being released is still by a stateblock, Stage = %u Texture = %p\n", counter, resource);
7911 This->stateBlock->textures[counter] = NULL;
7913 if (This->updateStateBlock != This->stateBlock ){
7914 if (This->updateStateBlock->textures[counter] == (IWineD3DBaseTexture *)resource) {
7915 WARN("Texture being released is still by a stateblock, Stage = %u Texture = %p\n", counter, resource);
7916 This->updateStateBlock->textures[counter] = NULL;
7921 case WINED3DRTYPE_VOLUME:
7922 /* TODO: nothing really? */
7924 case WINED3DRTYPE_VERTEXBUFFER:
7925 /* MSDN: When an application no longer holds a references to this interface, the interface will automatically be freed. */
7928 TRACE("Cleaning up stream pointers\n");
7930 for(streamNumber = 0; streamNumber < MAX_STREAMS; streamNumber ++){
7931 /* FINDOUT: should a warn be generated if were recording and updateStateBlock->streamSource is lost?
7932 FINDOUT: should changes.streamSource[StreamNumber] be set ?
7934 if (This->updateStateBlock != NULL ) { /* ==NULL when device is being destroyed */
7935 if ((IWineD3DResource *)This->updateStateBlock->streamSource[streamNumber] == resource) {
7936 FIXME("Vertex buffer released while bound to a state block, stream %d\n", streamNumber);
7937 This->updateStateBlock->streamSource[streamNumber] = 0;
7938 /* Set changed flag? */
7941 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) */
7942 if ((IWineD3DResource *)This->stateBlock->streamSource[streamNumber] == resource) {
7943 TRACE("Vertex buffer released while bound to a state block, stream %d\n", streamNumber);
7944 This->stateBlock->streamSource[streamNumber] = 0;
7947 #if 0 /* TODO: Manage internal tracking properly so that 'this shouldn't happen' */
7948 else { /* This shouldn't happen */
7949 FIXME("Calling application has released the device before relasing all the resources bound to the device\n");
7956 case WINED3DRTYPE_INDEXBUFFER:
7957 /* MSDN: When an application no longer holds a references to this interface, the interface will automatically be freed.*/
7958 if (This->updateStateBlock != NULL ) { /* ==NULL when device is being destroyed */
7959 if (This->updateStateBlock->pIndexData == (IWineD3DIndexBuffer *)resource) {
7960 This->updateStateBlock->pIndexData = NULL;
7963 if (This->stateBlock != NULL ) { /* ==NULL when device is being destroyed */
7964 if (This->stateBlock->pIndexData == (IWineD3DIndexBuffer *)resource) {
7965 This->stateBlock->pIndexData = NULL;
7971 FIXME("(%p) unknown resource type %p %u\n", This, resource, IWineD3DResource_GetType(resource));
7976 /* Remove the resoruce from the resourceStore */
7977 IWineD3DDeviceImpl_RemoveResource(iface, resource);
7979 TRACE("Resource released\n");
7983 /**********************************************************
7984 * IWineD3DDevice VTbl follows
7985 **********************************************************/
7987 const IWineD3DDeviceVtbl IWineD3DDevice_Vtbl =
7989 /*** IUnknown methods ***/
7990 IWineD3DDeviceImpl_QueryInterface,
7991 IWineD3DDeviceImpl_AddRef,
7992 IWineD3DDeviceImpl_Release,
7993 /*** IWineD3DDevice methods ***/
7994 IWineD3DDeviceImpl_GetParent,
7995 /*** Creation methods**/
7996 IWineD3DDeviceImpl_CreateVertexBuffer,
7997 IWineD3DDeviceImpl_CreateIndexBuffer,
7998 IWineD3DDeviceImpl_CreateStateBlock,
7999 IWineD3DDeviceImpl_CreateSurface,
8000 IWineD3DDeviceImpl_CreateTexture,
8001 IWineD3DDeviceImpl_CreateVolumeTexture,
8002 IWineD3DDeviceImpl_CreateVolume,
8003 IWineD3DDeviceImpl_CreateCubeTexture,
8004 IWineD3DDeviceImpl_CreateQuery,
8005 IWineD3DDeviceImpl_CreateAdditionalSwapChain,
8006 IWineD3DDeviceImpl_CreateVertexDeclaration,
8007 IWineD3DDeviceImpl_CreateVertexShader,
8008 IWineD3DDeviceImpl_CreatePixelShader,
8009 IWineD3DDeviceImpl_CreatePalette,
8010 /*** Odd functions **/
8011 IWineD3DDeviceImpl_Init3D,
8012 IWineD3DDeviceImpl_Uninit3D,
8013 IWineD3DDeviceImpl_SetFullscreen,
8014 IWineD3DDeviceImpl_EnumDisplayModes,
8015 IWineD3DDeviceImpl_EvictManagedResources,
8016 IWineD3DDeviceImpl_GetAvailableTextureMem,
8017 IWineD3DDeviceImpl_GetBackBuffer,
8018 IWineD3DDeviceImpl_GetCreationParameters,
8019 IWineD3DDeviceImpl_GetDeviceCaps,
8020 IWineD3DDeviceImpl_GetDirect3D,
8021 IWineD3DDeviceImpl_GetDisplayMode,
8022 IWineD3DDeviceImpl_SetDisplayMode,
8023 IWineD3DDeviceImpl_GetHWND,
8024 IWineD3DDeviceImpl_SetHWND,
8025 IWineD3DDeviceImpl_GetNumberOfSwapChains,
8026 IWineD3DDeviceImpl_GetRasterStatus,
8027 IWineD3DDeviceImpl_GetSwapChain,
8028 IWineD3DDeviceImpl_Reset,
8029 IWineD3DDeviceImpl_SetDialogBoxMode,
8030 IWineD3DDeviceImpl_SetCursorProperties,
8031 IWineD3DDeviceImpl_SetCursorPosition,
8032 IWineD3DDeviceImpl_ShowCursor,
8033 IWineD3DDeviceImpl_TestCooperativeLevel,
8034 /*** Getters and setters **/
8035 IWineD3DDeviceImpl_SetClipPlane,
8036 IWineD3DDeviceImpl_GetClipPlane,
8037 IWineD3DDeviceImpl_SetClipStatus,
8038 IWineD3DDeviceImpl_GetClipStatus,
8039 IWineD3DDeviceImpl_SetCurrentTexturePalette,
8040 IWineD3DDeviceImpl_GetCurrentTexturePalette,
8041 IWineD3DDeviceImpl_SetDepthStencilSurface,
8042 IWineD3DDeviceImpl_GetDepthStencilSurface,
8043 IWineD3DDeviceImpl_SetFVF,
8044 IWineD3DDeviceImpl_GetFVF,
8045 IWineD3DDeviceImpl_SetGammaRamp,
8046 IWineD3DDeviceImpl_GetGammaRamp,
8047 IWineD3DDeviceImpl_SetIndices,
8048 IWineD3DDeviceImpl_GetIndices,
8049 IWineD3DDeviceImpl_SetLight,
8050 IWineD3DDeviceImpl_GetLight,
8051 IWineD3DDeviceImpl_SetLightEnable,
8052 IWineD3DDeviceImpl_GetLightEnable,
8053 IWineD3DDeviceImpl_SetMaterial,
8054 IWineD3DDeviceImpl_GetMaterial,
8055 IWineD3DDeviceImpl_SetNPatchMode,
8056 IWineD3DDeviceImpl_GetNPatchMode,
8057 IWineD3DDeviceImpl_SetPaletteEntries,
8058 IWineD3DDeviceImpl_GetPaletteEntries,
8059 IWineD3DDeviceImpl_SetPixelShader,
8060 IWineD3DDeviceImpl_GetPixelShader,
8061 IWineD3DDeviceImpl_SetPixelShaderConstantB,
8062 IWineD3DDeviceImpl_GetPixelShaderConstantB,
8063 IWineD3DDeviceImpl_SetPixelShaderConstantI,
8064 IWineD3DDeviceImpl_GetPixelShaderConstantI,
8065 IWineD3DDeviceImpl_SetPixelShaderConstantF,
8066 IWineD3DDeviceImpl_GetPixelShaderConstantF,
8067 IWineD3DDeviceImpl_SetRenderState,
8068 IWineD3DDeviceImpl_GetRenderState,
8069 IWineD3DDeviceImpl_SetRenderTarget,
8070 IWineD3DDeviceImpl_GetRenderTarget,
8071 IWineD3DDeviceImpl_SetFrontBackBuffers,
8072 IWineD3DDeviceImpl_SetSamplerState,
8073 IWineD3DDeviceImpl_GetSamplerState,
8074 IWineD3DDeviceImpl_SetScissorRect,
8075 IWineD3DDeviceImpl_GetScissorRect,
8076 IWineD3DDeviceImpl_SetSoftwareVertexProcessing,
8077 IWineD3DDeviceImpl_GetSoftwareVertexProcessing,
8078 IWineD3DDeviceImpl_SetStreamSource,
8079 IWineD3DDeviceImpl_GetStreamSource,
8080 IWineD3DDeviceImpl_SetStreamSourceFreq,
8081 IWineD3DDeviceImpl_GetStreamSourceFreq,
8082 IWineD3DDeviceImpl_SetTexture,
8083 IWineD3DDeviceImpl_GetTexture,
8084 IWineD3DDeviceImpl_SetTextureStageState,
8085 IWineD3DDeviceImpl_GetTextureStageState,
8086 IWineD3DDeviceImpl_SetTransform,
8087 IWineD3DDeviceImpl_GetTransform,
8088 IWineD3DDeviceImpl_SetVertexDeclaration,
8089 IWineD3DDeviceImpl_GetVertexDeclaration,
8090 IWineD3DDeviceImpl_SetVertexShader,
8091 IWineD3DDeviceImpl_GetVertexShader,
8092 IWineD3DDeviceImpl_SetVertexShaderConstantB,
8093 IWineD3DDeviceImpl_GetVertexShaderConstantB,
8094 IWineD3DDeviceImpl_SetVertexShaderConstantI,
8095 IWineD3DDeviceImpl_GetVertexShaderConstantI,
8096 IWineD3DDeviceImpl_SetVertexShaderConstantF,
8097 IWineD3DDeviceImpl_GetVertexShaderConstantF,
8098 IWineD3DDeviceImpl_SetViewport,
8099 IWineD3DDeviceImpl_GetViewport,
8100 IWineD3DDeviceImpl_MultiplyTransform,
8101 IWineD3DDeviceImpl_ValidateDevice,
8102 IWineD3DDeviceImpl_ProcessVertices,
8103 /*** State block ***/
8104 IWineD3DDeviceImpl_BeginStateBlock,
8105 IWineD3DDeviceImpl_EndStateBlock,
8106 /*** Scene management ***/
8107 IWineD3DDeviceImpl_BeginScene,
8108 IWineD3DDeviceImpl_EndScene,
8109 IWineD3DDeviceImpl_Present,
8110 IWineD3DDeviceImpl_Clear,
8112 IWineD3DDeviceImpl_DrawPrimitive,
8113 IWineD3DDeviceImpl_DrawIndexedPrimitive,
8114 IWineD3DDeviceImpl_DrawPrimitiveUP,
8115 IWineD3DDeviceImpl_DrawIndexedPrimitiveUP,
8116 IWineD3DDeviceImpl_DrawPrimitiveStrided,
8117 IWineD3DDeviceImpl_DrawRectPatch,
8118 IWineD3DDeviceImpl_DrawTriPatch,
8119 IWineD3DDeviceImpl_DeletePatch,
8120 IWineD3DDeviceImpl_ColorFill,
8121 IWineD3DDeviceImpl_UpdateTexture,
8122 IWineD3DDeviceImpl_UpdateSurface,
8123 IWineD3DDeviceImpl_CopyRects,
8124 IWineD3DDeviceImpl_StretchRect,
8125 IWineD3DDeviceImpl_GetRenderTargetData,
8126 IWineD3DDeviceImpl_GetFrontBufferData,
8127 /*** Internal use IWineD3DDevice methods ***/
8128 IWineD3DDeviceImpl_SetupTextureStates,
8129 /*** object tracking ***/
8130 IWineD3DDeviceImpl_ResourceReleased
8134 const DWORD SavedPixelStates_R[NUM_SAVEDPIXELSTATES_R] = {
8135 WINED3DRS_ALPHABLENDENABLE ,
8136 WINED3DRS_ALPHAFUNC ,
8137 WINED3DRS_ALPHAREF ,
8138 WINED3DRS_ALPHATESTENABLE ,
8140 WINED3DRS_COLORWRITEENABLE ,
8141 WINED3DRS_DESTBLEND ,
8142 WINED3DRS_DITHERENABLE ,
8143 WINED3DRS_FILLMODE ,
8144 WINED3DRS_FOGDENSITY ,
8146 WINED3DRS_FOGSTART ,
8147 WINED3DRS_LASTPIXEL ,
8148 WINED3DRS_SHADEMODE ,
8149 WINED3DRS_SRCBLEND ,
8150 WINED3DRS_STENCILENABLE ,
8151 WINED3DRS_STENCILFAIL ,
8152 WINED3DRS_STENCILFUNC ,
8153 WINED3DRS_STENCILMASK ,
8154 WINED3DRS_STENCILPASS ,
8155 WINED3DRS_STENCILREF ,
8156 WINED3DRS_STENCILWRITEMASK ,
8157 WINED3DRS_STENCILZFAIL ,
8158 WINED3DRS_TEXTUREFACTOR ,
8169 WINED3DRS_ZWRITEENABLE
8172 const DWORD SavedPixelStates_T[NUM_SAVEDPIXELSTATES_T] = {
8173 WINED3DTSS_ADDRESSW ,
8174 WINED3DTSS_ALPHAARG0 ,
8175 WINED3DTSS_ALPHAARG1 ,
8176 WINED3DTSS_ALPHAARG2 ,
8177 WINED3DTSS_ALPHAOP ,
8178 WINED3DTSS_BUMPENVLOFFSET ,
8179 WINED3DTSS_BUMPENVLSCALE ,
8180 WINED3DTSS_BUMPENVMAT00 ,
8181 WINED3DTSS_BUMPENVMAT01 ,
8182 WINED3DTSS_BUMPENVMAT10 ,
8183 WINED3DTSS_BUMPENVMAT11 ,
8184 WINED3DTSS_COLORARG0 ,
8185 WINED3DTSS_COLORARG1 ,
8186 WINED3DTSS_COLORARG2 ,
8187 WINED3DTSS_COLOROP ,
8188 WINED3DTSS_RESULTARG ,
8189 WINED3DTSS_TEXCOORDINDEX ,
8190 WINED3DTSS_TEXTURETRANSFORMFLAGS
8193 const DWORD SavedPixelStates_S[NUM_SAVEDPIXELSTATES_S] = {
8194 WINED3DSAMP_ADDRESSU ,
8195 WINED3DSAMP_ADDRESSV ,
8196 WINED3DSAMP_ADDRESSW ,
8197 WINED3DSAMP_BORDERCOLOR ,
8198 WINED3DSAMP_MAGFILTER ,
8199 WINED3DSAMP_MINFILTER ,
8200 WINED3DSAMP_MIPFILTER ,
8201 WINED3DSAMP_MIPMAPLODBIAS ,
8202 WINED3DSAMP_MAXMIPLEVEL ,
8203 WINED3DSAMP_MAXANISOTROPY ,
8204 WINED3DSAMP_SRGBTEXTURE ,
8205 WINED3DSAMP_ELEMENTINDEX
8208 const DWORD SavedVertexStates_R[NUM_SAVEDVERTEXSTATES_R] = {
8210 WINED3DRS_AMBIENTMATERIALSOURCE ,
8211 WINED3DRS_CLIPPING ,
8212 WINED3DRS_CLIPPLANEENABLE ,
8213 WINED3DRS_COLORVERTEX ,
8214 WINED3DRS_DIFFUSEMATERIALSOURCE ,
8215 WINED3DRS_EMISSIVEMATERIALSOURCE ,
8216 WINED3DRS_FOGDENSITY ,
8218 WINED3DRS_FOGSTART ,
8219 WINED3DRS_FOGTABLEMODE ,
8220 WINED3DRS_FOGVERTEXMODE ,
8221 WINED3DRS_INDEXEDVERTEXBLENDENABLE ,
8222 WINED3DRS_LIGHTING ,
8223 WINED3DRS_LOCALVIEWER ,
8224 WINED3DRS_MULTISAMPLEANTIALIAS ,
8225 WINED3DRS_MULTISAMPLEMASK ,
8226 WINED3DRS_NORMALIZENORMALS ,
8227 WINED3DRS_PATCHEDGESTYLE ,
8228 WINED3DRS_POINTSCALE_A ,
8229 WINED3DRS_POINTSCALE_B ,
8230 WINED3DRS_POINTSCALE_C ,
8231 WINED3DRS_POINTSCALEENABLE ,
8232 WINED3DRS_POINTSIZE ,
8233 WINED3DRS_POINTSIZE_MAX ,
8234 WINED3DRS_POINTSIZE_MIN ,
8235 WINED3DRS_POINTSPRITEENABLE ,
8236 WINED3DRS_RANGEFOGENABLE ,
8237 WINED3DRS_SPECULARMATERIALSOURCE ,
8238 WINED3DRS_TWEENFACTOR ,
8239 WINED3DRS_VERTEXBLEND
8242 const DWORD SavedVertexStates_T[NUM_SAVEDVERTEXSTATES_T] = {
8243 WINED3DTSS_TEXCOORDINDEX ,
8244 WINED3DTSS_TEXTURETRANSFORMFLAGS
8247 const DWORD SavedVertexStates_S[NUM_SAVEDVERTEXSTATES_S] = {
8248 WINED3DSAMP_DMAPOFFSET