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 && This->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 && This->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 %d than are supported %d by this openGL implementation\n", Sampler, GL_LIMITS(sampler_stages));
457 VTRACE(("Activating appropriate texture state %d\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 %d 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 %d 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 %d\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 %d\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 (This->vs_selected_mode == SHADER_GLSL ||
578 This->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=%d, FVF=%x, 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=%x, 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 %d\n", MultisampleQuality);
971 return WINED3DERR_INVALIDCALL; /* TODO: Check that this is the case! */
974 if(MultisampleQuality > 0) {
975 FIXME("MultisampleQuality set to %d, 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) + SURFACE_ALIGNMENT - 1) & ~(SURFACE_ALIGNMENT - 1);
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) + SURFACE_ALIGNMENT - 1) & ~(SURFACE_ALIGNMENT - 1);
1057 object->pow2Size *= pow2Height;
1059 object->bytesPerPixel = 0;
1060 object->pow2Size = 0;
1063 /** TODO: change this into a texture transform matrix so that it's processed in hardware **/
1065 TRACE("Pool %d %d %d %d\n",Pool, WINED3DPOOL_DEFAULT, WINED3DPOOL_MANAGED, WINED3DPOOL_SYSTEMMEM);
1067 /** Quick lockable sanity check TODO: remove this after surfaces, usage and locablility have been debugged properly
1068 * this function is too deap to need to care about things like this.
1069 * Levels need to be checked too, and possibly Type wince they all affect what can be done.
1070 * ****************************************/
1072 case WINED3DPOOL_SCRATCH:
1074 FIXME("Create suface called with a pool of SCRATCH and a Lockable of FALSE \
1075 which are mutually exclusive, setting lockable to true\n");
1078 case WINED3DPOOL_SYSTEMMEM:
1079 if(!Lockable) FIXME("Create surface called with a pool of SYSTEMMEM and a Lockable of FALSE, \
1080 this is acceptable but unexpected (I can't know how the surface can be usable!)\n");
1081 case WINED3DPOOL_MANAGED:
1082 if(Usage == WINED3DUSAGE_DYNAMIC) FIXME("Create surface called with a pool of MANAGED and a \
1083 Usage of DYNAMIC which are mutually exclusive, not doing \
1084 anything just telling you.\n");
1086 case WINED3DPOOL_DEFAULT: /*TODO: Create offscreen plain can cause this check to fail..., find out if it should */
1087 if(!(Usage & WINED3DUSAGE_DYNAMIC) && !(Usage & WINED3DUSAGE_RENDERTARGET)
1088 && !(Usage && WINED3DUSAGE_DEPTHSTENCIL ) && Lockable)
1089 WARN("Creating a surface with a POOL of DEFAULT with Lockable true, that doesn't specify DYNAMIC usage.\n");
1092 FIXME("(%p) Unknown pool %d\n", This, Pool);
1096 if (Usage & WINED3DUSAGE_RENDERTARGET && Pool != WINED3DPOOL_DEFAULT) {
1097 FIXME("Trying to create a render target that isn't in the default pool\n");
1100 /* mark the texture as dirty so that it get's loaded first time around*/
1101 IWineD3DSurface_AddDirtyRect(*ppSurface, NULL);
1102 TRACE("(%p) : w(%d) h(%d) fmt(%d,%s) lockable(%d) surf@%p, surfmem@%p, %d bytes\n",
1103 This, Width, Height, Format, debug_d3dformat(Format),
1104 (WINED3DFMT_D16_LOCKABLE == Format), *ppSurface, object->resource.allocatedMemory, object->resource.size);
1106 /* Store the DirectDraw primary surface. This is the first rendertarget surface created */
1107 if( (Usage & WINED3DUSAGE_RENDERTARGET) && (!This->ddraw_primary) )
1108 This->ddraw_primary = (IWineD3DSurface *) object;
1110 /* Look at the implementation and set the correct Vtable */
1112 case SURFACE_OPENGL:
1113 /* Nothing to do, it's set already */
1117 object->lpVtbl = &IWineGDISurface_Vtbl;
1121 /* To be sure to catch this */
1122 ERR("Unknown requested surface implementation %d!\n", Impl);
1123 IWineD3DSurface_Release((IWineD3DSurface *) object);
1124 return WINED3DERR_INVALIDCALL;
1127 /* Call the private setup routine */
1128 return IWineD3DSurface_PrivateSetup( (IWineD3DSurface *) object );
1132 static HRESULT WINAPI IWineD3DDeviceImpl_CreateTexture(IWineD3DDevice *iface, UINT Width, UINT Height, UINT Levels,
1133 DWORD Usage, WINED3DFORMAT Format, WINED3DPOOL Pool,
1134 IWineD3DTexture** ppTexture, HANDLE* pSharedHandle, IUnknown *parent,
1135 D3DCB_CREATESURFACEFN D3DCB_CreateSurface) {
1137 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
1138 IWineD3DTextureImpl *object;
1143 unsigned int pow2Width;
1144 unsigned int pow2Height;
1147 TRACE("(%p) : Width %d, Height %d, Levels %d, Usage %#x\n", This, Width, Height, Levels, Usage);
1148 TRACE("Format %#x (%s), Pool %#x, ppTexture %p, pSharedHandle %p, parent %p\n",
1149 Format, debug_d3dformat(Format), Pool, ppTexture, pSharedHandle, parent);
1151 /* TODO: It should only be possible to create textures for formats
1152 that are reported as supported */
1153 if (WINED3DFMT_UNKNOWN >= Format) {
1154 WARN("(%p) : Texture cannot be created with a format of D3DFMT_UNKNOWN\n", This);
1155 return WINED3DERR_INVALIDCALL;
1158 D3DCREATERESOURCEOBJECTINSTANCE(object, Texture, WINED3DRTYPE_TEXTURE, 0);
1159 D3DINITIALIZEBASETEXTURE(object->baseTexture);
1160 object->width = Width;
1161 object->height = Height;
1163 /** Non-power2 support **/
1164 if (wined3d_settings.nonpower2_mode == NP2_NATIVE) {
1166 pow2Height = Height;
1168 /* Find the nearest pow2 match */
1169 pow2Width = pow2Height = 1;
1170 while (pow2Width < Width) pow2Width <<= 1;
1171 while (pow2Height < Height) pow2Height <<= 1;
1174 /** FIXME: add support for real non-power-two if it's provided by the video card **/
1175 /* Precalculated scaling for 'faked' non power of two texture coords */
1176 object->pow2scalingFactorX = (((float)Width) / ((float)pow2Width));
1177 object->pow2scalingFactorY = (((float)Height) / ((float)pow2Height));
1178 TRACE(" xf(%f) yf(%f)\n", object->pow2scalingFactorX, object->pow2scalingFactorY);
1180 /* Calculate levels for mip mapping */
1182 TRACE("calculating levels %d\n", object->baseTexture.levels);
1183 object->baseTexture.levels++;
1186 while (tmpW > 1 || tmpH > 1) {
1187 tmpW = max(1, tmpW >> 1);
1188 tmpH = max(1, tmpH >> 1);
1189 object->baseTexture.levels++;
1191 TRACE("Calculated levels = %d\n", object->baseTexture.levels);
1194 /* Generate all the surfaces */
1197 for (i = 0; i < object->baseTexture.levels; i++)
1199 /* use the callback to create the texture surface */
1200 hr = D3DCB_CreateSurface(This->parent, tmpW, tmpH, Format, Usage, Pool, i, &object->surfaces[i],NULL);
1201 if (hr!= WINED3D_OK || ( (IWineD3DSurfaceImpl *) object->surfaces[i])->Flags & SFLAG_OVERSIZE) {
1202 FIXME("Failed to create surface %p\n", object);
1204 object->surfaces[i] = NULL;
1205 IWineD3DTexture_Release((IWineD3DTexture *)object);
1211 IWineD3DSurface_SetContainer(object->surfaces[i], (IWineD3DBase *)object);
1212 TRACE("Created surface level %d @ %p\n", i, object->surfaces[i]);
1213 /* calculate the next mipmap level */
1214 tmpW = max(1, tmpW >> 1);
1215 tmpH = max(1, tmpH >> 1);
1218 TRACE("(%p) : Created texture %p\n", This, object);
1222 static HRESULT WINAPI IWineD3DDeviceImpl_CreateVolumeTexture(IWineD3DDevice *iface,
1223 UINT Width, UINT Height, UINT Depth,
1224 UINT Levels, DWORD Usage,
1225 WINED3DFORMAT Format, WINED3DPOOL Pool,
1226 IWineD3DVolumeTexture **ppVolumeTexture,
1227 HANDLE *pSharedHandle, IUnknown *parent,
1228 D3DCB_CREATEVOLUMEFN D3DCB_CreateVolume) {
1230 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
1231 IWineD3DVolumeTextureImpl *object;
1237 /* TODO: It should only be possible to create textures for formats
1238 that are reported as supported */
1239 if (WINED3DFMT_UNKNOWN >= Format) {
1240 WARN("(%p) : Texture cannot be created with a format of D3DFMT_UNKNOWN\n", This);
1241 return WINED3DERR_INVALIDCALL;
1244 D3DCREATERESOURCEOBJECTINSTANCE(object, VolumeTexture, WINED3DRTYPE_VOLUMETEXTURE, 0);
1245 D3DINITIALIZEBASETEXTURE(object->baseTexture);
1247 TRACE("(%p) : W(%d) H(%d) D(%d), Lvl(%d) Usage(%d), Fmt(%u,%s), Pool(%s)\n", This, Width, Height,
1248 Depth, Levels, Usage, Format, debug_d3dformat(Format), debug_d3dpool(Pool));
1250 object->width = Width;
1251 object->height = Height;
1252 object->depth = Depth;
1254 /* Calculate levels for mip mapping */
1256 object->baseTexture.levels++;
1260 while (tmpW > 1 || tmpH > 1 || tmpD > 1) {
1261 tmpW = max(1, tmpW >> 1);
1262 tmpH = max(1, tmpH >> 1);
1263 tmpD = max(1, tmpD >> 1);
1264 object->baseTexture.levels++;
1266 TRACE("Calculated levels = %d\n", object->baseTexture.levels);
1269 /* Generate all the surfaces */
1274 for (i = 0; i < object->baseTexture.levels; i++)
1276 /* Create the volume */
1277 D3DCB_CreateVolume(This->parent, Width, Height, Depth, Format, Pool, Usage,
1278 (IWineD3DVolume **)&object->volumes[i], pSharedHandle);
1280 /* Set it's container to this object */
1281 IWineD3DVolume_SetContainer(object->volumes[i], (IWineD3DBase *)object);
1283 /* calcualte the next mipmap level */
1284 tmpW = max(1, tmpW >> 1);
1285 tmpH = max(1, tmpH >> 1);
1286 tmpD = max(1, tmpD >> 1);
1289 *ppVolumeTexture = (IWineD3DVolumeTexture *) object;
1290 TRACE("(%p) : Created volume texture %p\n", This, object);
1294 static HRESULT WINAPI IWineD3DDeviceImpl_CreateVolume(IWineD3DDevice *iface,
1295 UINT Width, UINT Height, UINT Depth,
1297 WINED3DFORMAT Format, WINED3DPOOL Pool,
1298 IWineD3DVolume** ppVolume,
1299 HANDLE* pSharedHandle, IUnknown *parent) {
1301 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
1302 IWineD3DVolumeImpl *object; /** NOTE: impl ref allowed since this is a create function **/
1303 const PixelFormatDesc *formatDesc = getFormatDescEntry(Format);
1305 D3DCREATERESOURCEOBJECTINSTANCE(object, Volume, WINED3DRTYPE_VOLUME, ((Width * formatDesc->bpp) * Height * Depth))
1307 TRACE("(%p) : W(%d) H(%d) D(%d), Usage(%d), Fmt(%u,%s), Pool(%s)\n", This, Width, Height,
1308 Depth, Usage, Format, debug_d3dformat(Format), debug_d3dpool(Pool));
1310 object->currentDesc.Width = Width;
1311 object->currentDesc.Height = Height;
1312 object->currentDesc.Depth = Depth;
1313 object->bytesPerPixel = formatDesc->bpp;
1315 /** Note: Volume textures cannot be dxtn, hence no need to check here **/
1316 object->lockable = TRUE;
1317 object->locked = FALSE;
1318 memset(&object->lockedBox, 0, sizeof(WINED3DBOX));
1319 object->dirty = TRUE;
1321 return IWineD3DVolume_AddDirtyBox((IWineD3DVolume *) object, NULL);
1324 static HRESULT WINAPI IWineD3DDeviceImpl_CreateCubeTexture(IWineD3DDevice *iface, UINT EdgeLength,
1325 UINT Levels, DWORD Usage,
1326 WINED3DFORMAT Format, WINED3DPOOL Pool,
1327 IWineD3DCubeTexture **ppCubeTexture,
1328 HANDLE *pSharedHandle, IUnknown *parent,
1329 D3DCB_CREATESURFACEFN D3DCB_CreateSurface) {
1331 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
1332 IWineD3DCubeTextureImpl *object; /** NOTE: impl ref allowed since this is a create function **/
1336 unsigned int pow2EdgeLength = EdgeLength;
1338 /* TODO: It should only be possible to create textures for formats
1339 that are reported as supported */
1340 if (WINED3DFMT_UNKNOWN >= Format) {
1341 WARN("(%p) : Texture cannot be created with a format of D3DFMT_UNKNOWN\n", This);
1342 return WINED3DERR_INVALIDCALL;
1345 D3DCREATERESOURCEOBJECTINSTANCE(object, CubeTexture, WINED3DRTYPE_CUBETEXTURE, 0);
1346 D3DINITIALIZEBASETEXTURE(object->baseTexture);
1348 TRACE("(%p) Create Cube Texture\n", This);
1350 /** Non-power2 support **/
1352 /* Find the nearest pow2 match */
1354 while (pow2EdgeLength < EdgeLength) pow2EdgeLength <<= 1;
1356 object->edgeLength = EdgeLength;
1357 /* TODO: support for native non-power 2 */
1358 /* Precalculated scaling for 'faked' non power of two texture coords */
1359 object->pow2scalingFactor = ((float)EdgeLength) / ((float)pow2EdgeLength);
1361 /* Calculate levels for mip mapping */
1363 object->baseTexture.levels++;
1366 tmpW = max(1, tmpW >> 1);
1367 object->baseTexture.levels++;
1369 TRACE("Calculated levels = %d\n", object->baseTexture.levels);
1372 /* Generate all the surfaces */
1374 for (i = 0; i < object->baseTexture.levels; i++) {
1376 /* Create the 6 faces */
1377 for (j = 0; j < 6; j++) {
1379 hr=D3DCB_CreateSurface(This->parent, tmpW, tmpW, Format, Usage, Pool,
1380 i /* Level */, &object->surfaces[j][i],pSharedHandle);
1382 if(hr!= WINED3D_OK) {
1386 for (l = 0; l < j; l++) {
1387 IWineD3DSurface_Release(object->surfaces[j][i]);
1389 for (k = 0; k < i; k++) {
1390 for (l = 0; l < 6; l++) {
1391 IWineD3DSurface_Release(object->surfaces[l][j]);
1395 FIXME("(%p) Failed to create surface\n",object);
1396 HeapFree(GetProcessHeap(),0,object);
1397 *ppCubeTexture = NULL;
1400 IWineD3DSurface_SetContainer(object->surfaces[j][i], (IWineD3DBase *)object);
1401 TRACE("Created surface level %d @ %p,\n", i, object->surfaces[j][i]);
1403 tmpW = max(1, tmpW >> 1);
1406 TRACE("(%p) : Created Cube Texture %p\n", This, object);
1407 *ppCubeTexture = (IWineD3DCubeTexture *) object;
1411 static HRESULT WINAPI IWineD3DDeviceImpl_CreateQuery(IWineD3DDevice *iface, WINED3DQUERYTYPE Type, IWineD3DQuery **ppQuery, IUnknown* parent) {
1412 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
1413 IWineD3DQueryImpl *object; /*NOTE: impl ref allowed since this is a create function */
1415 if (NULL == ppQuery) {
1416 /* Just a check to see if we support this type of query */
1417 HRESULT hr = WINED3DERR_NOTAVAILABLE;
1419 case WINED3DQUERYTYPE_OCCLUSION:
1420 TRACE("(%p) occlusion query\n", This);
1421 if (GL_SUPPORT(ARB_OCCLUSION_QUERY))
1424 WARN("Unsupported in local OpenGL implementation: ARB_OCCLUSION_QUERY/NV_OCCLUSION_QUERY\n");
1426 case WINED3DQUERYTYPE_VCACHE:
1427 case WINED3DQUERYTYPE_RESOURCEMANAGER:
1428 case WINED3DQUERYTYPE_VERTEXSTATS:
1429 case WINED3DQUERYTYPE_EVENT:
1430 case WINED3DQUERYTYPE_TIMESTAMP:
1431 case WINED3DQUERYTYPE_TIMESTAMPDISJOINT:
1432 case WINED3DQUERYTYPE_TIMESTAMPFREQ:
1433 case WINED3DQUERYTYPE_PIPELINETIMINGS:
1434 case WINED3DQUERYTYPE_INTERFACETIMINGS:
1435 case WINED3DQUERYTYPE_VERTEXTIMINGS:
1436 case WINED3DQUERYTYPE_PIXELTIMINGS:
1437 case WINED3DQUERYTYPE_BANDWIDTHTIMINGS:
1438 case WINED3DQUERYTYPE_CACHEUTILIZATION:
1440 FIXME("(%p) Unhandled query type %d\n", This, Type);
1445 D3DCREATEOBJECTINSTANCE(object, Query)
1446 object->type = Type;
1447 /* allocated the 'extended' data based on the type of query requested */
1449 case D3DQUERYTYPE_OCCLUSION:
1450 if(GL_SUPPORT(ARB_OCCLUSION_QUERY)) {
1451 TRACE("(%p) Allocating data for an occlusion query\n", This);
1452 object->extendedData = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(WineQueryOcclusionData));
1453 GL_EXTCALL(glGenQueriesARB(1, &((WineQueryOcclusionData *)(object->extendedData))->queryId));
1456 case D3DQUERYTYPE_VCACHE:
1457 case D3DQUERYTYPE_RESOURCEMANAGER:
1458 case D3DQUERYTYPE_VERTEXSTATS:
1459 case D3DQUERYTYPE_EVENT:
1460 case D3DQUERYTYPE_TIMESTAMP:
1461 case D3DQUERYTYPE_TIMESTAMPDISJOINT:
1462 case D3DQUERYTYPE_TIMESTAMPFREQ:
1463 case D3DQUERYTYPE_PIPELINETIMINGS:
1464 case D3DQUERYTYPE_INTERFACETIMINGS:
1465 case D3DQUERYTYPE_VERTEXTIMINGS:
1466 case D3DQUERYTYPE_PIXELTIMINGS:
1467 case D3DQUERYTYPE_BANDWIDTHTIMINGS:
1468 case D3DQUERYTYPE_CACHEUTILIZATION:
1470 object->extendedData = 0;
1471 FIXME("(%p) Unhandled query type %d\n",This , Type);
1473 TRACE("(%p) : Created Query %p\n", This, object);
1477 /* example at http://www.fairyengine.com/articles/dxmultiviews.htm */
1478 static HRESULT WINAPI IWineD3DDeviceImpl_CreateAdditionalSwapChain(IWineD3DDevice* iface, WINED3DPRESENT_PARAMETERS* pPresentationParameters, IWineD3DSwapChain** ppSwapChain,
1480 D3DCB_CREATERENDERTARGETFN D3DCB_CreateRenderTarget,
1481 D3DCB_CREATEDEPTHSTENCILSURFACEFN D3DCB_CreateDepthStencil) {
1482 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
1485 IWineD3DSwapChainImpl *object; /** NOTE: impl ref allowed since this is a create function **/
1487 XVisualInfo template;
1488 GLXContext oldContext;
1489 Drawable oldDrawable;
1490 HRESULT hr = WINED3D_OK;
1492 TRACE("(%p) : Created Aditional Swap Chain\n", This);
1494 /** FIXME: Test under windows to find out what the life cycle of a swap chain is,
1495 * does a device hold a reference to a swap chain giving them a lifetime of the device
1496 * or does the swap chain notify the device of its destruction.
1497 *******************************/
1499 /* Check the params */
1500 if(*pPresentationParameters->BackBufferCount > D3DPRESENT_BACK_BUFFER_MAX) {
1501 ERR("App requested %d back buffers, this is not supported for now\n", *pPresentationParameters->BackBufferCount);
1502 return WINED3DERR_INVALIDCALL;
1503 } else if (*pPresentationParameters->BackBufferCount > 1) {
1504 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");
1507 D3DCREATEOBJECTINSTANCE(object, SwapChain)
1509 /*********************
1510 * Lookup the window Handle and the relating X window handle
1511 ********************/
1513 /* Setup hwnd we are using, plus which display this equates to */
1514 object->win_handle = *(pPresentationParameters->hDeviceWindow);
1515 if (!object->win_handle) {
1516 object->win_handle = This->createParms.hFocusWindow;
1519 object->win_handle = GetAncestor(object->win_handle, GA_ROOT);
1520 if ( !( object->win = (Window)GetPropA(object->win_handle, "__wine_x11_whole_window") ) ) {
1521 ERR("Can't get drawable (window), HWND:%p doesn't have the property __wine_x11_whole_window\n", object->win_handle);
1522 return WINED3DERR_NOTAVAILABLE;
1524 hDc = GetDC(object->win_handle);
1525 object->display = get_display(hDc);
1526 ReleaseDC(object->win_handle, hDc);
1527 TRACE("Using a display of %p %p\n", object->display, hDc);
1529 if (NULL == object->display || NULL == hDc) {
1530 WARN("Failed to get a display and HDc for Window %p\n", object->win_handle);
1531 return WINED3DERR_NOTAVAILABLE;
1534 if (object->win == 0) {
1535 WARN("Failed to get a valid XVisuial ID for the window %p\n", object->win_handle);
1536 return WINED3DERR_NOTAVAILABLE;
1539 * Create an opengl context for the display visual
1540 * NOTE: the visual is chosen as the window is created and the glcontext cannot
1541 * use different properties after that point in time. FIXME: How to handle when requested format
1542 * doesn't match actual visual? Cannot choose one here - code removed as it ONLY works if the one
1543 * it chooses is identical to the one already being used!
1544 **********************************/
1546 /** FIXME: Handle stencil appropriately via EnableAutoDepthStencil / AutoDepthStencilFormat **/
1549 /* Create a new context for this swapchain */
1550 template.visualid = (VisualID)GetPropA(GetDesktopWindow(), "__wine_x11_visual_id");
1551 /* TODO: change this to find a similar visual, but one with a stencil/zbuffer buffer that matches the request
1552 (or the best possible if none is requested) */
1553 TRACE("Found x visual ID : %ld\n", template.visualid);
1555 object->visInfo = XGetVisualInfo(object->display, VisualIDMask, &template, &num);
1556 if (NULL == object->visInfo) {
1557 ERR("cannot really get XVisual\n");
1559 return WINED3DERR_NOTAVAILABLE;
1562 /* Write out some debug info about the visual/s */
1563 TRACE("Using x visual ID : %ld\n", template.visualid);
1564 TRACE(" visual info: %p\n", object->visInfo);
1565 TRACE(" num items : %d\n", num);
1566 for (n = 0;n < num; n++) {
1567 TRACE("=====item=====: %d\n", n + 1);
1568 TRACE(" visualid : %ld\n", object->visInfo[n].visualid);
1569 TRACE(" screen : %d\n", object->visInfo[n].screen);
1570 TRACE(" depth : %u\n", object->visInfo[n].depth);
1571 TRACE(" class : %d\n", object->visInfo[n].class);
1572 TRACE(" red_mask : %ld\n", object->visInfo[n].red_mask);
1573 TRACE(" green_mask : %ld\n", object->visInfo[n].green_mask);
1574 TRACE(" blue_mask : %ld\n", object->visInfo[n].blue_mask);
1575 TRACE(" colormap_size : %d\n", object->visInfo[n].colormap_size);
1576 TRACE(" bits_per_rgb : %d\n", object->visInfo[n].bits_per_rgb);
1577 /* log some extra glx info */
1578 glXGetConfig(object->display, object->visInfo, GLX_AUX_BUFFERS, &value);
1579 TRACE(" gl_aux_buffers : %d\n", value);
1580 glXGetConfig(object->display, object->visInfo, GLX_BUFFER_SIZE ,&value);
1581 TRACE(" gl_buffer_size : %d\n", value);
1582 glXGetConfig(object->display, object->visInfo, GLX_RED_SIZE, &value);
1583 TRACE(" gl_red_size : %d\n", value);
1584 glXGetConfig(object->display, object->visInfo, GLX_GREEN_SIZE, &value);
1585 TRACE(" gl_green_size : %d\n", value);
1586 glXGetConfig(object->display, object->visInfo, GLX_BLUE_SIZE, &value);
1587 TRACE(" gl_blue_size : %d\n", value);
1588 glXGetConfig(object->display, object->visInfo, GLX_ALPHA_SIZE, &value);
1589 TRACE(" gl_alpha_size : %d\n", value);
1590 glXGetConfig(object->display, object->visInfo, GLX_DEPTH_SIZE ,&value);
1591 TRACE(" gl_depth_size : %d\n", value);
1592 glXGetConfig(object->display, object->visInfo, GLX_STENCIL_SIZE, &value);
1593 TRACE(" gl_stencil_size : %d\n", value);
1595 /* Now choose a simila visual ID*/
1597 #ifdef USE_CONTEXT_MANAGER
1599 /** TODO: use a context mamager **/
1603 IWineD3DSwapChain *implSwapChain;
1604 if (WINED3D_OK != IWineD3DDevice_GetSwapChain(iface, 0, &implSwapChain)) {
1605 /* The first time around we create the context that is shared with all other swapchains and render targets */
1606 object->glCtx = glXCreateContext(object->display, object->visInfo, NULL, GL_TRUE);
1607 TRACE("Creating implicit context for vis %p, hwnd %p\n", object->display, object->visInfo);
1610 TRACE("Creating context for vis %p, hwnd %p\n", object->display, object->visInfo);
1611 /* TODO: don't use Impl structures outside of create functions! (a context manager will replace the ->glCtx) */
1612 /* and create a new context with the implicit swapchains context as the shared context */
1613 object->glCtx = glXCreateContext(object->display, object->visInfo, ((IWineD3DSwapChainImpl *)implSwapChain)->glCtx, GL_TRUE);
1614 IWineD3DSwapChain_Release(implSwapChain);
1619 XFree(object->visInfo);
1620 object->visInfo = NULL;
1624 if (!object->glCtx) {
1625 ERR("Failed to create GLX context\n");
1626 return WINED3DERR_NOTAVAILABLE;
1628 TRACE("Context created (HWND=%p, glContext=%p, Window=%ld, VisInfo=%p)\n",
1629 object->win_handle, object->glCtx, object->win, object->visInfo);
1632 /*********************
1633 * Windowed / Fullscreen
1634 *******************/
1637 * TODO: MSDN says that we are only allowed one fullscreen swapchain per device,
1638 * so we should really check to see if there is a fullscreen swapchain already
1639 * I think Windows and X have different ideas about fullscreen, does a single head count as full screen?
1640 **************************************/
1642 if (!*(pPresentationParameters->Windowed)) {
1648 /* Get info on the current display setup */
1649 hdc = CreateDCA("DISPLAY", NULL, NULL, NULL);
1650 bpp = GetDeviceCaps(hdc, BITSPIXEL);
1653 /* Change the display settings */
1654 memset(&devmode, 0, sizeof(DEVMODEW));
1655 devmode.dmFields = DM_BITSPERPEL | DM_PELSWIDTH | DM_PELSHEIGHT;
1656 devmode.dmBitsPerPel = (bpp >= 24) ? 32 : bpp; /* Stupid XVidMode cannot change bpp */
1657 devmode.dmPelsWidth = *(pPresentationParameters->BackBufferWidth);
1658 devmode.dmPelsHeight = *(pPresentationParameters->BackBufferHeight);
1659 MultiByteToWideChar(CP_ACP, 0, "Gamers CG", -1, devmode.dmDeviceName, CCHDEVICENAME);
1660 ChangeDisplaySettingsExW(devmode.dmDeviceName, &devmode, object->win_handle, CDS_FULLSCREEN, NULL);
1662 /* Make popup window */
1663 SetWindowLongA(object->win_handle, GWL_STYLE, WS_POPUP);
1664 SetWindowPos(object->win_handle, HWND_TOP, 0, 0,
1665 *(pPresentationParameters->BackBufferWidth),
1666 *(pPresentationParameters->BackBufferHeight), SWP_SHOWWINDOW | SWP_FRAMECHANGED);
1668 /* For GetDisplayMode */
1669 This->ddraw_width = devmode.dmPelsWidth;
1670 This->ddraw_height = devmode.dmPelsHeight;
1671 This->ddraw_format = *(pPresentationParameters->BackBufferFormat);
1675 /** MSDN: If Windowed is TRUE and either of the BackBufferWidth/Height values is zero,
1676 * then the corresponding dimension of the client area of the hDeviceWindow
1677 * (or the focus window, if hDeviceWindow is NULL) is taken.
1678 **********************/
1680 if (*(pPresentationParameters->Windowed) &&
1681 ((*(pPresentationParameters->BackBufferWidth) == 0) ||
1682 (*(pPresentationParameters->BackBufferHeight) == 0))) {
1685 GetClientRect(object->win_handle, &Rect);
1687 if (*(pPresentationParameters->BackBufferWidth) == 0) {
1688 *(pPresentationParameters->BackBufferWidth) = Rect.right;
1689 TRACE("Updating width to %d\n", *(pPresentationParameters->BackBufferWidth));
1691 if (*(pPresentationParameters->BackBufferHeight) == 0) {
1692 *(pPresentationParameters->BackBufferHeight) = Rect.bottom;
1693 TRACE("Updating height to %d\n", *(pPresentationParameters->BackBufferHeight));
1697 /*********************
1698 * finish off parameter initialization
1699 *******************/
1701 /* Put the correct figures in the presentation parameters */
1702 TRACE("Coppying accross presentaion paraneters\n");
1703 object->presentParms.BackBufferWidth = *(pPresentationParameters->BackBufferWidth);
1704 object->presentParms.BackBufferHeight = *(pPresentationParameters->BackBufferHeight);
1705 object->presentParms.BackBufferFormat = *(pPresentationParameters->BackBufferFormat);
1706 object->presentParms.BackBufferCount = *(pPresentationParameters->BackBufferCount);
1707 object->presentParms.MultiSampleType = *(pPresentationParameters->MultiSampleType);
1708 object->presentParms.MultiSampleQuality = NULL == pPresentationParameters->MultiSampleQuality ? 0 : *(pPresentationParameters->MultiSampleQuality);
1709 object->presentParms.SwapEffect = *(pPresentationParameters->SwapEffect);
1710 object->presentParms.hDeviceWindow = *(pPresentationParameters->hDeviceWindow);
1711 object->presentParms.Windowed = *(pPresentationParameters->Windowed);
1712 object->presentParms.EnableAutoDepthStencil = *(pPresentationParameters->EnableAutoDepthStencil);
1713 object->presentParms.AutoDepthStencilFormat = *(pPresentationParameters->AutoDepthStencilFormat);
1714 object->presentParms.Flags = *(pPresentationParameters->Flags);
1715 object->presentParms.FullScreen_RefreshRateInHz = *(pPresentationParameters->FullScreen_RefreshRateInHz);
1716 object->presentParms.PresentationInterval = *(pPresentationParameters->PresentationInterval);
1719 /*********************
1720 * Create the back, front and stencil buffers
1721 *******************/
1723 TRACE("calling rendertarget CB\n");
1724 hr = D3DCB_CreateRenderTarget((IUnknown *) This->parent,
1725 object->presentParms.BackBufferWidth,
1726 object->presentParms.BackBufferHeight,
1727 object->presentParms.BackBufferFormat,
1728 object->presentParms.MultiSampleType,
1729 object->presentParms.MultiSampleQuality,
1730 TRUE /* Lockable */,
1731 &object->frontBuffer,
1732 NULL /* pShared (always null)*/);
1733 if (object->frontBuffer != NULL)
1734 IWineD3DSurface_SetContainer(object->frontBuffer, (IWineD3DBase *)object);
1736 if(object->presentParms.BackBufferCount > 0) {
1739 object->backBuffer = HeapAlloc(GetProcessHeap(), 0, sizeof(IWineD3DSurface *) * object->presentParms.BackBufferCount);
1740 if(!object->backBuffer) {
1741 ERR("Out of memory\n");
1743 if (object->frontBuffer) {
1744 IUnknown *bufferParent;
1745 IWineD3DSurface_GetParent(object->frontBuffer, &bufferParent);
1746 IUnknown_Release(bufferParent); /* once for the get parent */
1747 if (IUnknown_Release(bufferParent) > 0) {
1748 FIXME("(%p) Something's still holding the front buffer\n",This);
1751 HeapFree(GetProcessHeap(), 0, object);
1752 return E_OUTOFMEMORY;
1755 for(i = 0; i < object->presentParms.BackBufferCount; i++) {
1756 TRACE("calling rendertarget CB\n");
1757 hr = D3DCB_CreateRenderTarget((IUnknown *) This->parent,
1758 object->presentParms.BackBufferWidth,
1759 object->presentParms.BackBufferHeight,
1760 object->presentParms.BackBufferFormat,
1761 object->presentParms.MultiSampleType,
1762 object->presentParms.MultiSampleQuality,
1763 TRUE /* Lockable */,
1764 &object->backBuffer[i],
1765 NULL /* pShared (always null)*/);
1766 if(hr == WINED3D_OK && object->backBuffer[i]) {
1767 IWineD3DSurface_SetContainer(object->backBuffer[i], (IWineD3DBase *)object);
1773 object->backBuffer = NULL;
1776 if (object->backBuffer != NULL) {
1778 glDrawBuffer(GL_BACK);
1779 checkGLcall("glDrawBuffer(GL_BACK)");
1782 /* Single buffering - draw to front buffer */
1784 glDrawBuffer(GL_FRONT);
1785 checkGLcall("glDrawBuffer(GL_FRONT)");
1789 /* Under directX swapchains share the depth stencil, so only create one depth-stencil */
1790 if (*(pPresentationParameters->EnableAutoDepthStencil) && hr == WINED3D_OK) {
1791 TRACE("Creating depth stencil buffer\n");
1792 if (This->depthStencilBuffer == NULL ) {
1793 hr = D3DCB_CreateDepthStencil((IUnknown *) This->parent,
1794 object->presentParms.BackBufferWidth,
1795 object->presentParms.BackBufferHeight,
1796 object->presentParms.AutoDepthStencilFormat,
1797 object->presentParms.MultiSampleType,
1798 object->presentParms.MultiSampleQuality,
1799 FALSE /* FIXME: Discard */,
1800 &This->depthStencilBuffer,
1801 NULL /* pShared (always null)*/ );
1802 if (This->depthStencilBuffer != NULL)
1803 IWineD3DSurface_SetContainer(This->depthStencilBuffer, 0);
1806 /** TODO: A check on width, height and multisample types
1807 *(since the zbuffer must be at least as large as the render target and have the same multisample parameters)
1808 ****************************/
1809 object->wantsDepthStencilBuffer = TRUE;
1811 object->wantsDepthStencilBuffer = FALSE;
1814 TRACE("FrontBuf @ %p, BackBuf @ %p, DepthStencil %d\n",object->frontBuffer, object->backBuffer ? object->backBuffer[0] : NULL, object->wantsDepthStencilBuffer);
1817 /*********************
1818 * init the default renderTarget management
1819 *******************/
1820 object->drawable = object->win;
1821 object->render_ctx = object->glCtx;
1823 if (hr == WINED3D_OK) {
1824 /*********************
1825 * Setup some defaults and clear down the buffers
1826 *******************/
1828 /** save current context and drawable **/
1829 oldContext = glXGetCurrentContext();
1830 oldDrawable = glXGetCurrentDrawable();
1832 TRACE("Activating context (display %p context %p drawable %ld)!\n", object->display, object->glCtx, object->win);
1833 if (glXMakeCurrent(object->display, object->win, object->glCtx) == False) {
1834 ERR("Error in setting current context (display %p context %p drawable %ld)!\n", object->display, object->glCtx, object->win);
1836 checkGLcall("glXMakeCurrent");
1838 TRACE("Setting up the screen\n");
1839 /* Clear the screen */
1840 glClearColor(1.0, 0.0, 0.0, 0.0);
1841 checkGLcall("glClearColor");
1844 glClearStencil(0xffff);
1846 checkGLcall("glClear");
1848 glColor3f(1.0, 1.0, 1.0);
1849 checkGLcall("glColor3f");
1851 glEnable(GL_LIGHTING);
1852 checkGLcall("glEnable");
1854 glLightModeli(GL_LIGHT_MODEL_LOCAL_VIEWER, GL_TRUE);
1855 checkGLcall("glLightModeli(GL_LIGHT_MODEL_LOCAL_VIEWER, GL_TRUE);");
1857 glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE_EXT);
1858 checkGLcall("glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE_EXT);");
1860 glLightModeli(GL_LIGHT_MODEL_COLOR_CONTROL, GL_SEPARATE_SPECULAR_COLOR);
1861 checkGLcall("glLightModeli(GL_LIGHT_MODEL_COLOR_CONTROL, GL_SEPARATE_SPECULAR_COLOR);");
1863 /* switch back to the original context (if there was one)*/
1864 if (This->swapchains) {
1865 /** TODO: restore the context and drawable **/
1866 glXMakeCurrent(object->display, oldDrawable, oldContext);
1869 /* Set the surface alignment. This never changes, so we are safe to set it once per context*/
1870 glPixelStorei(GL_PACK_ALIGNMENT, SURFACE_ALIGNMENT);
1871 checkGLcall("glPixelStorei(GL_PACK_ALIGNMENT, SURFACE_ALIGNMENT);");
1872 glPixelStorei(GL_UNPACK_ALIGNMENT, SURFACE_ALIGNMENT);
1873 checkGLcall("glPixelStorei(GL_UNPACK_ALIGNMENT, SURFACE_ALIGNMENT);");
1877 TRACE("Set swapchain to %p\n", object);
1878 } else { /* something went wrong so clean up */
1879 IUnknown* bufferParent;
1880 if (object->frontBuffer) {
1882 IWineD3DSurface_GetParent(object->frontBuffer, &bufferParent);
1883 IUnknown_Release(bufferParent); /* once for the get parent */
1884 if (IUnknown_Release(bufferParent) > 0) {
1885 FIXME("(%p) Something's still holding the front buffer\n",This);
1888 if (object->backBuffer) {
1890 for(i = 0; i < object->presentParms.BackBufferCount; i++) {
1891 if(object->backBuffer[i]) {
1892 IWineD3DSurface_GetParent(object->backBuffer[i], &bufferParent);
1893 IUnknown_Release(bufferParent); /* once for the get parent */
1894 if (IUnknown_Release(bufferParent) > 0) {
1895 FIXME("(%p) Something's still holding the back buffer\n",This);
1899 HeapFree(GetProcessHeap(), 0, object->backBuffer);
1900 object->backBuffer = NULL;
1902 /* NOTE: don't clean up the depthstencil buffer because it belongs to the device */
1903 /* Clean up the context */
1904 /* check that we are the current context first (we shouldn't be though!) */
1905 if (object->glCtx != 0) {
1906 if(glXGetCurrentContext() == object->glCtx) {
1907 glXMakeCurrent(object->display, None, NULL);
1909 glXDestroyContext(object->display, object->glCtx);
1911 HeapFree(GetProcessHeap(), 0, object);
1918 /** NOTE: These are ahead of the other getters and setters to save using a forward declaration **/
1919 static UINT WINAPI IWineD3DDeviceImpl_GetNumberOfSwapChains(IWineD3DDevice *iface) {
1920 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
1921 TRACE("(%p)\n", This);
1923 return This->NumberOfSwapChains;
1926 static HRESULT WINAPI IWineD3DDeviceImpl_GetSwapChain(IWineD3DDevice *iface, UINT iSwapChain, IWineD3DSwapChain **pSwapChain) {
1927 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
1928 TRACE("(%p) : swapchain %d\n", This, iSwapChain);
1930 if(iSwapChain < This->NumberOfSwapChains) {
1931 *pSwapChain = This->swapchains[iSwapChain];
1932 IWineD3DSwapChain_AddRef(*pSwapChain);
1933 TRACE("(%p) returning %p\n", This, *pSwapChain);
1936 TRACE("Swapchain out of range\n");
1938 return WINED3DERR_INVALIDCALL;
1943 * Vertex Declaration
1945 static HRESULT WINAPI IWineD3DDeviceImpl_CreateVertexDeclaration(IWineD3DDevice* iface, CONST VOID* pDeclaration, IWineD3DVertexDeclaration** ppVertexDeclaration, IUnknown *parent) {
1946 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
1947 IWineD3DVertexDeclarationImpl *object = NULL;
1948 HRESULT hr = WINED3D_OK;
1949 TRACE("(%p) : directXVersion=%u, pFunction=%p, ppDecl=%p\n", This, ((IWineD3DImpl *)This->wineD3D)->dxVersion, pDeclaration, ppVertexDeclaration);
1950 D3DCREATEOBJECTINSTANCE(object, VertexDeclaration)
1953 hr = IWineD3DVertexDeclaration_SetDeclaration((IWineD3DVertexDeclaration *)object, (void *)pDeclaration);
1958 /* http://msdn.microsoft.com/archive/default.asp?url=/archive/en-us/directx9_c/directx/graphics/programmingguide/programmable/vertexshaders/vscreate.asp */
1959 static HRESULT WINAPI IWineD3DDeviceImpl_CreateVertexShader(IWineD3DDevice *iface, CONST DWORD *pDeclaration, CONST DWORD *pFunction, IWineD3DVertexShader **ppVertexShader, IUnknown *parent) {
1960 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
1961 IWineD3DVertexShaderImpl *object; /* NOTE: impl usage is ok, this is a create */
1962 HRESULT hr = WINED3D_OK;
1963 D3DCREATESHADEROBJECTINSTANCE(object, VertexShader)
1964 object->baseShader.shader_ins = IWineD3DVertexShaderImpl_shader_ins;
1966 TRACE("(%p) : Created Vertex shader %p\n", This, *ppVertexShader);
1968 /* If a vertex declaration has been passed, save it to the vertex shader, this affects d3d8 only. */
1969 /* Further it needs to be set before calling SetFunction as SetFunction needs the declaration. */
1970 if (pDeclaration != NULL) {
1971 IWineD3DVertexDeclaration *vertexDeclaration;
1972 hr = IWineD3DDevice_CreateVertexDeclaration(iface, pDeclaration, &vertexDeclaration ,NULL);
1973 if (WINED3D_OK == hr) {
1974 TRACE("(%p) : Setting vertex declaration to %p\n", This, vertexDeclaration);
1975 object->vertexDeclaration = vertexDeclaration;
1977 FIXME("(%p) : Failed to set the declaration, returning WINED3DERR_INVALIDCALL\n", iface);
1978 IWineD3DVertexShader_Release(*ppVertexShader);
1979 return WINED3DERR_INVALIDCALL;
1983 hr = IWineD3DVertexShader_SetFunction(*ppVertexShader, pFunction);
1985 if (WINED3D_OK != hr) {
1986 FIXME("(%p) : Failed to set the function, returning WINED3DERR_INVALIDCALL\n", iface);
1987 IWineD3DVertexShader_Release(*ppVertexShader);
1988 return WINED3DERR_INVALIDCALL;
1991 #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. */
1992 if(Usage == WINED3DUSAGE_SOFTWAREVERTEXPROCESSING) {
2003 static HRESULT WINAPI IWineD3DDeviceImpl_CreatePixelShader(IWineD3DDevice *iface, CONST DWORD *pFunction, IWineD3DPixelShader **ppPixelShader, IUnknown *parent) {
2004 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2005 IWineD3DPixelShaderImpl *object; /* NOTE: impl allowed, this is a create */
2006 HRESULT hr = WINED3D_OK;
2008 D3DCREATESHADEROBJECTINSTANCE(object, PixelShader)
2009 object->baseShader.shader_ins = IWineD3DPixelShaderImpl_shader_ins;
2010 hr = IWineD3DPixelShader_SetFunction(*ppPixelShader, pFunction);
2011 if (WINED3D_OK == hr) {
2012 TRACE("(%p) : Created Pixel shader %p\n", This, *ppPixelShader);
2014 WARN("(%p) : Failed to create pixel shader\n", This);
2020 static HRESULT WINAPI IWineD3DDeviceImpl_CreatePalette(IWineD3DDevice *iface, DWORD Flags, PALETTEENTRY *PalEnt, IWineD3DPalette **Palette, IUnknown *Parent) {
2021 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *) iface;
2022 IWineD3DPaletteImpl *object;
2024 TRACE("(%p)->(%x, %p, %p, %p)\n", This, Flags, PalEnt, Palette, Parent);
2026 /* Create the new object */
2027 object = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(IWineD3DPaletteImpl));
2029 ERR("Out of memory when allocating memory for a IWineD3DPalette implementation\n");
2030 return E_OUTOFMEMORY;
2033 object->lpVtbl = &IWineD3DPalette_Vtbl;
2035 object->Flags = Flags;
2036 object->parent = Parent;
2037 object->wineD3DDevice = This;
2038 object->palNumEntries = IWineD3DPaletteImpl_Size(Flags);
2040 object->hpal = CreatePalette((const LOGPALETTE*)&(object->palVersion));
2043 HeapFree( GetProcessHeap(), 0, object);
2044 return E_OUTOFMEMORY;
2047 hr = IWineD3DPalette_SetEntries((IWineD3DPalette *) object, 0, 0, IWineD3DPaletteImpl_Size(Flags), PalEnt);
2049 IWineD3DPalette_Release((IWineD3DPalette *) object);
2053 *Palette = (IWineD3DPalette *) object;
2058 static HRESULT WINAPI IWineD3DDeviceImpl_Init3D(IWineD3DDevice *iface, WINED3DPRESENT_PARAMETERS* pPresentationParameters, D3DCB_CREATEADDITIONALSWAPCHAIN D3DCB_CreateAdditionalSwapChain) {
2059 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *) iface;
2060 IWineD3DSwapChainImpl *swapchain;
2062 TRACE("(%p)->(%p,%p)\n", This, pPresentationParameters, D3DCB_CreateAdditionalSwapChain);
2063 if(This->d3d_initialized) return WINED3DERR_INVALIDCALL;
2065 /* TODO: Test if OpenGL is compiled in and loaded */
2067 /* Setup the implicit swapchain */
2068 TRACE("Creating implicit swapchain\n");
2069 if (D3D_OK != D3DCB_CreateAdditionalSwapChain((IUnknown *) This->parent, pPresentationParameters, (IWineD3DSwapChain **)&swapchain) || swapchain == NULL) {
2070 WARN("Failed to create implicit swapchain\n");
2071 return WINED3DERR_INVALIDCALL;
2074 This->NumberOfSwapChains = 1;
2075 This->swapchains = HeapAlloc(GetProcessHeap(), 0, This->NumberOfSwapChains * sizeof(IWineD3DSwapChain *));
2076 if(!This->swapchains) {
2077 ERR("Out of memory!\n");
2078 IWineD3DSwapChain_Release( (IWineD3DSwapChain *) swapchain);
2079 return E_OUTOFMEMORY;
2081 This->swapchains[0] = (IWineD3DSwapChain *) swapchain;
2083 if(swapchain->backBuffer && swapchain->backBuffer[0]) {
2084 TRACE("Setting rendertarget to %p\n", swapchain->backBuffer);
2085 This->renderTarget = swapchain->backBuffer[0];
2088 TRACE("Setting rendertarget to %p\n", swapchain->frontBuffer);
2089 This->renderTarget = swapchain->frontBuffer;
2091 IWineD3DSurface_AddRef(This->renderTarget);
2092 /* Depth Stencil support */
2093 This->stencilBufferTarget = This->depthStencilBuffer;
2094 if (NULL != This->stencilBufferTarget) {
2095 IWineD3DSurface_AddRef(This->stencilBufferTarget);
2098 /* Set up some starting GL setup */
2101 * Initialize openGL extension related variables
2102 * with Default values
2105 ((IWineD3DImpl *) This->wineD3D)->isGLInfoValid = IWineD3DImpl_FillGLCaps( This->wineD3D, swapchain->display);
2106 /* Setup all the devices defaults */
2107 IWineD3DStateBlock_InitStartupStateBlock((IWineD3DStateBlock *)This->stateBlock);
2109 IWineD3DImpl_CheckGraphicsMemory();
2113 /* Initialize our list of GLSL programs */
2114 list_init(&This->glsl_shader_progs);
2116 { /* Set a default viewport */
2120 vp.Width = *(pPresentationParameters->BackBufferWidth);
2121 vp.Height = *(pPresentationParameters->BackBufferHeight);
2124 IWineD3DDevice_SetViewport((IWineD3DDevice *)This, &vp);
2127 /* Initialize the current view state */
2128 This->modelview_valid = 1;
2129 This->proj_valid = 0;
2130 This->view_ident = 1;
2131 This->last_was_rhw = 0;
2132 glGetIntegerv(GL_MAX_LIGHTS, &This->maxConcurrentLights);
2133 TRACE("(%p) All defaults now set up, leaving Init3D with %p\n", This, This);
2135 /* Clear the screen */
2136 IWineD3DDevice_Clear((IWineD3DDevice *) This, 0, NULL, D3DCLEAR_STENCIL|D3DCLEAR_ZBUFFER|D3DCLEAR_TARGET, 0x00, 1.0, 0);
2138 This->d3d_initialized = TRUE;
2142 static HRESULT WINAPI IWineD3DDeviceImpl_Uninit3D(IWineD3DDevice *iface) {
2143 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *) iface;
2145 IUnknown* stencilBufferParent;
2146 IUnknown* swapChainParent;
2148 TRACE("(%p)\n", This);
2150 if(!This->d3d_initialized) return WINED3DERR_INVALIDCALL;
2152 /* Delete the mouse cursor texture */
2153 if(This->cursorTexture) {
2155 glDeleteTextures(1, &This->cursorTexture);
2157 This->cursorTexture = 0;
2160 for(sampler = 0; sampler < GL_LIMITS(sampler_stages); ++sampler) {
2161 IWineD3DDevice_SetTexture(iface, sampler, NULL);
2164 /* Release the buffers (with sanity checks)*/
2165 TRACE("Releasing the depth stencil buffer at %p\n", This->stencilBufferTarget);
2166 if(This->stencilBufferTarget != NULL && (IWineD3DSurface_Release(This->stencilBufferTarget) >0)){
2167 if(This->depthStencilBuffer != This->stencilBufferTarget)
2168 FIXME("(%p) Something's still holding the depthStencilBuffer\n",This);
2170 This->stencilBufferTarget = NULL;
2172 TRACE("Releasing the render target at %p\n", This->renderTarget);
2173 if(IWineD3DSurface_Release(This->renderTarget) >0){
2174 /* This check is a bit silly, itshould be in swapchain_release FIXME("(%p) Something's still holding the renderTarget\n",This); */
2176 TRACE("Setting rendertarget to NULL\n");
2177 This->renderTarget = NULL;
2179 if (This->depthStencilBuffer) {
2180 IWineD3DSurface_GetParent(This->depthStencilBuffer, &stencilBufferParent);
2181 IUnknown_Release(stencilBufferParent); /* once for the get parent */
2182 if(IUnknown_Release(stencilBufferParent) >0){ /* the second time for when it was created */
2183 FIXME("(%p) Something's still holding the depthStencilBuffer\n",This);
2185 This->depthStencilBuffer = NULL;
2188 for(i=0; i < This->NumberOfSwapChains; i++) {
2189 TRACE("Releasing the implicit swapchain %d\n", i);
2190 /* Swapchain 0 is special because it's created in startup with a hanging parent, so we have to release its parent now */
2191 IWineD3DSwapChain_GetParent(This->swapchains[i], &swapChainParent);
2192 IUnknown_Release(swapChainParent); /* once for the get parent */
2193 if (IUnknown_Release(swapChainParent) > 0) { /* the second time for when it was created */
2194 FIXME("(%p) Something's still holding the implicit swapchain\n", This);
2198 HeapFree(GetProcessHeap(), 0, This->swapchains);
2199 This->swapchains = NULL;
2200 This->NumberOfSwapChains = 0;
2202 This->d3d_initialized = FALSE;
2206 static void WINAPI IWineD3DDeviceImpl_SetFullscreen(IWineD3DDevice *iface, BOOL fullscreen) {
2207 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *) iface;
2208 TRACE("(%p) Setting DDraw fullscreen mode to %s\n", This, fullscreen ? "true" : "false");
2210 /* DirectDraw apps can change between fullscreen and windowed mode after device creation with
2211 * IDirectDraw7::SetCooperativeLevel. The GDI surface implementation needs to know this.
2212 * DDraw doesn't necessarilly have a swapchain, so we have to store the fullscreen flag
2215 This->ddraw_fullscreen = fullscreen;
2218 static HRESULT WINAPI IWineD3DDeviceImpl_EnumDisplayModes(IWineD3DDevice *iface, DWORD Flags, UINT Width, UINT Height, WINED3DFORMAT pixelformat, LPVOID context, D3DCB_ENUMDISPLAYMODESCALLBACK callback) {
2219 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2223 const PixelFormatDesc *formatDesc = getFormatDescEntry(pixelformat);
2225 TRACE("(%p)->(%x,%d,%d,%d,%p,%p)\n", This, Flags, Width, Height, pixelformat, context, callback);
2227 for (i = 0; EnumDisplaySettingsExW(NULL, i, &DevModeW, 0); i++) {
2228 /* Ignore some modes if a description was passed */
2229 if ( (Width > 0) && (Width != DevModeW.dmPelsWidth)) continue;
2230 if ( (Height > 0) && (Height != DevModeW.dmPelsHeight)) continue;
2231 if ( (pixelformat != WINED3DFMT_UNKNOWN) && ( formatDesc->bpp != DevModeW.dmBitsPerPel) ) continue;
2233 TRACE("Enumerating %dx%d@%s\n", DevModeW.dmPelsWidth, DevModeW.dmPelsHeight, debug_d3dformat(pixelformat_for_depth(DevModeW.dmBitsPerPel)));
2235 if (callback((IUnknown *) This, (UINT) DevModeW.dmPelsWidth, (UINT) DevModeW.dmPelsHeight, pixelformat_for_depth(DevModeW.dmBitsPerPel), 60.0, context) == DDENUMRET_CANCEL)
2242 static HRESULT WINAPI IWineD3DDeviceImpl_SetDisplayMode(IWineD3DDevice *iface, UINT iSwapChain, WINED3DDISPLAYMODE* pMode) {
2244 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2246 const PixelFormatDesc *formatDesc = getFormatDescEntry(pMode->Format);
2248 TRACE("(%p)->(%d,%p) Mode=%dx%dx@%d, %s\n", This, iSwapChain, pMode, pMode->Width, pMode->Height, pMode->RefreshRate, debug_d3dformat(pMode->Format));
2250 /* Resize the screen even without a window:
2251 * The app could have unset it with SetCooperativeLevel, but not called
2252 * RestoreDisplayMode first. Then the release will call RestoreDisplayMode,
2253 * but we don't have any hwnd
2256 devmode.dmFields = DM_BITSPERPEL | DM_PELSWIDTH | DM_PELSHEIGHT;
2257 devmode.dmBitsPerPel = formatDesc->bpp * 8;
2258 if(devmode.dmBitsPerPel == 24) devmode.dmBitsPerPel = 32;
2259 devmode.dmPelsWidth = pMode->Width;
2260 devmode.dmPelsHeight = pMode->Height;
2262 devmode.dmDisplayFrequency = pMode->RefreshRate;
2263 if (pMode->RefreshRate != 0) {
2264 devmode.dmFields |= DM_DISPLAYFREQUENCY;
2267 /* Only change the mode if necessary */
2268 if( (This->ddraw_width == pMode->Width) &&
2269 (This->ddraw_height == pMode->Height) &&
2270 (This->ddraw_format == pMode->Format) &&
2271 (pMode->RefreshRate == 0) ) {
2275 ret = ChangeDisplaySettingsExW(NULL, &devmode, NULL, CDS_FULLSCREEN, NULL);
2276 if (ret != DISP_CHANGE_SUCCESSFUL) {
2277 if(devmode.dmDisplayFrequency != 0) {
2278 WARN("ChangeDisplaySettingsExW failed, trying without the refresh rate\n");
2279 devmode.dmFields &= ~DM_DISPLAYFREQUENCY;
2280 devmode.dmDisplayFrequency = 0;
2281 ret = ChangeDisplaySettingsExW(NULL, &devmode, NULL, CDS_FULLSCREEN, NULL) != DISP_CHANGE_SUCCESSFUL;
2283 if(ret != DISP_CHANGE_SUCCESSFUL) {
2284 return DDERR_INVALIDMODE;
2288 /* Store the new values */
2289 This->ddraw_width = pMode->Width;
2290 This->ddraw_height = pMode->Height;
2291 This->ddraw_format = pMode->Format;
2293 /* Only do this with a window of course */
2294 if(This->ddraw_window)
2295 MoveWindow(This->ddraw_window, 0, 0, pMode->Width, pMode->Height, TRUE);
2300 static HRESULT WINAPI IWineD3DDeviceImpl_GetDirect3D(IWineD3DDevice *iface, IWineD3D **ppD3D) {
2301 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2302 *ppD3D= This->wineD3D;
2303 TRACE("(%p) : wineD3D returning %p\n", This, *ppD3D);
2304 IWineD3D_AddRef(*ppD3D);
2308 static UINT WINAPI IWineD3DDeviceImpl_GetAvailableTextureMem(IWineD3DDevice *iface) {
2309 /** NOTE: There's a probably a hack-around for this one by putting as many pbuffers, VBO's (or whatever)
2310 * Into the video ram as possible and seeing how many fit
2311 * you can also get the correct initial value from nvidia and ATI's driver via X
2312 * texture memory is video memory + AGP memory
2313 *******************/
2314 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2315 static BOOL showfixmes = TRUE;
2317 FIXME("(%p) : stub, simulating %dMB for now, returning %dMB left\n", This,
2318 (wined3d_settings.emulated_textureram/(1024*1024)),
2319 ((wined3d_settings.emulated_textureram - wineD3DGlobalStatistics->glsurfaceram) / (1024*1024)));
2322 TRACE("(%p) : simulating %dMB, returning %dMB left\n", This,
2323 (wined3d_settings.emulated_textureram/(1024*1024)),
2324 ((wined3d_settings.emulated_textureram - wineD3DGlobalStatistics->glsurfaceram) / (1024*1024)));
2325 /* return simulated texture memory left */
2326 return (wined3d_settings.emulated_textureram - wineD3DGlobalStatistics->glsurfaceram);
2334 static HRESULT WINAPI IWineD3DDeviceImpl_SetFVF(IWineD3DDevice *iface, DWORD fvf) {
2335 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2336 HRESULT hr = WINED3D_OK;
2338 /* Update the current state block */
2339 This->updateStateBlock->fvf = fvf;
2340 This->updateStateBlock->changed.fvf = TRUE;
2341 This->updateStateBlock->set.fvf = TRUE;
2343 TRACE("(%p) : FVF Shader FVF set to %x\n", This, fvf);
2348 static HRESULT WINAPI IWineD3DDeviceImpl_GetFVF(IWineD3DDevice *iface, DWORD *pfvf) {
2349 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2350 TRACE("(%p) : GetFVF returning %x\n", This, This->stateBlock->fvf);
2351 *pfvf = This->stateBlock->fvf;
2356 * Get / Set Stream Source
2358 static HRESULT WINAPI IWineD3DDeviceImpl_SetStreamSource(IWineD3DDevice *iface, UINT StreamNumber,IWineD3DVertexBuffer* pStreamData, UINT OffsetInBytes, UINT Stride) {
2359 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2360 IWineD3DVertexBuffer *oldSrc;
2362 /**TODO: instance and index data, see
2363 http://msdn.microsoft.com/library/default.asp?url=/library/en-us/directx9_c/directx/graphics/programmingguide/advancedtopics/DrawingMultipleInstances.asp
2365 http://msdn.microsoft.com/library/default.asp?url=/library/en-us/directx9_c/directx/graphics/reference/d3d/interfaces/idirect3ddevice9/SetStreamSourceFreq.asp
2368 /* D3d9 only, but shouldn't hurt d3d8 */
2371 streamFlags = StreamNumber &(D3DSTREAMSOURCE_INDEXEDDATA | D3DSTREAMSOURCE_INSTANCEDATA);
2373 if (streamFlags & D3DSTREAMSOURCE_INDEXEDDATA) {
2374 FIXME("stream index data not supported\n");
2376 if (streamFlags & D3DSTREAMSOURCE_INDEXEDDATA) {
2377 FIXME("stream instance data not supported\n");
2381 StreamNumber&= ~(D3DSTREAMSOURCE_INDEXEDDATA | D3DSTREAMSOURCE_INSTANCEDATA);
2383 if (StreamNumber >= MAX_STREAMS) {
2384 WARN("Stream out of range %d\n", StreamNumber);
2385 return WINED3DERR_INVALIDCALL;
2388 oldSrc = This->stateBlock->streamSource[StreamNumber];
2389 TRACE("(%p) : StreamNo: %d, OldStream (%p), NewStream (%p), NewStride %d\n", This, StreamNumber, oldSrc, pStreamData, Stride);
2391 This->updateStateBlock->changed.streamSource[StreamNumber] = TRUE;
2392 This->updateStateBlock->set.streamSource[StreamNumber] = TRUE;
2393 This->updateStateBlock->streamStride[StreamNumber] = Stride;
2394 This->updateStateBlock->streamSource[StreamNumber] = pStreamData;
2395 This->updateStateBlock->streamOffset[StreamNumber] = OffsetInBytes;
2396 This->updateStateBlock->streamFlags[StreamNumber] = streamFlags;
2398 /* Handle recording of state blocks */
2399 if (This->isRecordingState) {
2400 TRACE("Recording... not performing anything\n");
2404 /* Same stream object: no action */
2405 if (oldSrc == pStreamData)
2408 /* Need to do a getParent and pass the reffs up */
2409 /* MSDN says ..... When an application no longer holds a references to this interface, the interface will automatically be freed.
2410 which suggests that we shouldn't be ref counting? and do need a _release on the stream source to reset the stream source
2411 so for now, just count internally */
2412 if (pStreamData != NULL) {
2413 IWineD3DVertexBufferImpl *vbImpl = (IWineD3DVertexBufferImpl *) pStreamData;
2414 if( (vbImpl->Flags & VBFLAG_STREAM) && vbImpl->stream != StreamNumber) {
2415 WARN("Assigning a Vertex Buffer to stream %d which is already assigned to stream %d\n", StreamNumber, vbImpl->stream);
2417 vbImpl->stream = StreamNumber;
2418 vbImpl->Flags |= VBFLAG_STREAM;
2419 IWineD3DVertexBuffer_AddRef(pStreamData);
2421 if (oldSrc != NULL) {
2422 ((IWineD3DVertexBufferImpl *) oldSrc)->Flags &= ~VBFLAG_STREAM;
2423 IWineD3DVertexBuffer_Release(oldSrc);
2429 static HRESULT WINAPI IWineD3DDeviceImpl_GetStreamSource(IWineD3DDevice *iface, UINT StreamNumber,IWineD3DVertexBuffer** pStream, UINT *pOffset, UINT* pStride) {
2430 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2433 TRACE("(%p) : StreamNo: %d, Stream (%p), Stride %d\n", This, StreamNumber,
2434 This->stateBlock->streamSource[StreamNumber], This->stateBlock->streamStride[StreamNumber]);
2437 streamFlags = StreamNumber &(D3DSTREAMSOURCE_INDEXEDDATA | D3DSTREAMSOURCE_INSTANCEDATA);
2439 if (streamFlags & D3DSTREAMSOURCE_INDEXEDDATA) {
2440 FIXME("stream index data not supported\n");
2442 if (streamFlags & D3DSTREAMSOURCE_INDEXEDDATA) {
2443 FIXME("stream instance data not supported\n");
2447 StreamNumber&= ~(D3DSTREAMSOURCE_INDEXEDDATA | D3DSTREAMSOURCE_INSTANCEDATA);
2449 if (StreamNumber >= MAX_STREAMS) {
2450 WARN("Stream out of range %d\n", StreamNumber);
2451 return WINED3DERR_INVALIDCALL;
2453 *pStream = This->stateBlock->streamSource[StreamNumber];
2454 *pStride = This->stateBlock->streamStride[StreamNumber];
2456 *pOffset = This->stateBlock->streamOffset[StreamNumber];
2459 if (*pStream == NULL) {
2460 FIXME("Attempting to get an empty stream %d, returning WINED3DERR_INVALIDCALL\n", StreamNumber);
2461 return WINED3DERR_INVALIDCALL;
2464 IWineD3DVertexBuffer_AddRef(*pStream); /* We have created a new reference to the VB */
2468 /*Should be quite easy, just an extension of vertexdata
2470 http://msdn.microsoft.com/archive/default.asp?url=/archive/en-us/directx9_c_Summer_04/directx/graphics/programmingguide/advancedtopics/DrawingMultipleInstances.asp
2472 The divider is a bit odd though
2474 VertexOffset = StartVertex / Divider * StreamStride +
2475 VertexIndex / Divider * StreamStride + StreamOffset
2478 static HRESULT WINAPI IWineD3DDeviceImpl_SetStreamSourceFreq(IWineD3DDevice *iface, UINT StreamNumber, UINT Divider) {
2479 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2481 TRACE("(%p) StreamNumber(%d), Divider(%d)\n", This, StreamNumber, Divider);
2482 This->updateStateBlock->streamFlags[StreamNumber] = Divider & (D3DSTREAMSOURCE_INSTANCEDATA | D3DSTREAMSOURCE_INDEXEDDATA );
2484 This->updateStateBlock->changed.streamFreq[StreamNumber] = TRUE;
2485 This->updateStateBlock->set.streamFreq[StreamNumber] = TRUE;
2486 This->updateStateBlock->streamFreq[StreamNumber] = Divider & 0x7FFFFF;
2488 if (This->updateStateBlock->streamFlags[StreamNumber] || This->updateStateBlock->streamFreq[StreamNumber] != 1) {
2489 FIXME("Stream indexing not fully supported\n");
2495 static HRESULT WINAPI IWineD3DDeviceImpl_GetStreamSourceFreq(IWineD3DDevice *iface, UINT StreamNumber, UINT* Divider) {
2496 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2498 TRACE("(%p) StreamNumber(%d), Divider(%p)\n", This, StreamNumber, Divider);
2499 *Divider = This->updateStateBlock->streamFreq[StreamNumber] | This->updateStateBlock->streamFlags[StreamNumber];
2501 TRACE("(%p) : returning %d\n", This, *Divider);
2507 * Get / Set & Multiply Transform
2509 static HRESULT WINAPI IWineD3DDeviceImpl_SetTransform(IWineD3DDevice *iface, D3DTRANSFORMSTATETYPE d3dts, CONST D3DMATRIX* lpmatrix) {
2510 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2512 /* Most of this routine, comments included copied from ddraw tree initially: */
2513 TRACE("(%p) : Transform State=%s\n", This, debug_d3dtstype(d3dts));
2515 /* Handle recording of state blocks */
2516 if (This->isRecordingState) {
2517 TRACE("Recording... not performing anything\n");
2518 This->updateStateBlock->changed.transform[d3dts] = TRUE;
2519 This->updateStateBlock->set.transform[d3dts] = TRUE;
2520 memcpy(&This->updateStateBlock->transforms[d3dts], lpmatrix, sizeof(D3DMATRIX));
2525 * If the new matrix is the same as the current one,
2526 * we cut off any further processing. this seems to be a reasonable
2527 * optimization because as was noticed, some apps (warcraft3 for example)
2528 * tend towards setting the same matrix repeatedly for some reason.
2530 * From here on we assume that the new matrix is different, wherever it matters.
2532 if (!memcmp(&This->stateBlock->transforms[d3dts].u.m[0][0], lpmatrix, sizeof(D3DMATRIX))) {
2533 TRACE("The app is setting the same matrix over again\n");
2536 conv_mat(lpmatrix, &This->stateBlock->transforms[d3dts].u.m[0][0]);
2540 ScreenCoord = ProjectionMat * ViewMat * WorldMat * ObjectCoord
2541 where ViewMat = Camera space, WorldMat = world space.
2543 In OpenGL, camera and world space is combined into GL_MODELVIEW
2544 matrix. The Projection matrix stay projection matrix.
2547 /* Capture the times we can just ignore the change for now */
2548 if (d3dts == WINED3DTS_WORLDMATRIX(0)) {
2549 This->modelview_valid = FALSE;
2552 } else if (d3dts == WINED3DTS_PROJECTION) {
2553 This->proj_valid = FALSE;
2556 } else if (d3dts >= WINED3DTS_WORLDMATRIX(1) && d3dts <= WINED3DTS_WORLDMATRIX(255)) {
2557 /* Indexed Vertex Blending Matrices 256 -> 511 */
2558 /* Use arb_vertex_blend or NV_VERTEX_WEIGHTING? */
2559 FIXME("WINED3DTS_WORLDMATRIX(1..255) not handled\n");
2563 /* Now we really are going to have to change a matrix */
2566 if (d3dts >= WINED3DTS_TEXTURE0 && d3dts <= WINED3DTS_TEXTURE7) { /* handle texture matrices */
2567 /* This is now set with the texture unit states, it may be a good idea to flag the change though! */
2568 } else if (d3dts == WINED3DTS_VIEW) { /* handle the VIEW matrice */
2571 /* If we are changing the View matrix, reset the light and clipping planes to the new view
2572 * NOTE: We have to reset the positions even if the light/plane is not currently
2573 * enabled, since the call to enable it will not reset the position.
2574 * NOTE2: Apparently texture transforms do NOT need reapplying
2577 PLIGHTINFOEL *lightChain = NULL;
2578 This->modelview_valid = FALSE;
2579 This->view_ident = !memcmp(lpmatrix, identity, 16 * sizeof(float));
2581 glMatrixMode(GL_MODELVIEW);
2582 checkGLcall("glMatrixMode(GL_MODELVIEW)");
2584 glLoadMatrixf((float *)lpmatrix);
2585 checkGLcall("glLoadMatrixf(...)");
2588 lightChain = This->stateBlock->lights;
2589 while (lightChain && lightChain->glIndex != -1) {
2590 glLightfv(GL_LIGHT0 + lightChain->glIndex, GL_POSITION, lightChain->lightPosn);
2591 checkGLcall("glLightfv posn");
2592 glLightfv(GL_LIGHT0 + lightChain->glIndex, GL_SPOT_DIRECTION, lightChain->lightDirn);
2593 checkGLcall("glLightfv dirn");
2594 lightChain = lightChain->next;
2597 /* Reset Clipping Planes if clipping is enabled */
2598 for (k = 0; k < GL_LIMITS(clipplanes); k++) {
2599 glClipPlane(GL_CLIP_PLANE0 + k, This->stateBlock->clipplane[k]);
2600 checkGLcall("glClipPlane");
2604 } else { /* What was requested!?? */
2605 WARN("invalid matrix specified: %i\n", d3dts);
2608 /* Release lock, all done */
2613 static HRESULT WINAPI IWineD3DDeviceImpl_GetTransform(IWineD3DDevice *iface, D3DTRANSFORMSTATETYPE State, D3DMATRIX* pMatrix) {
2614 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2615 TRACE("(%p) : for Transform State %s\n", This, debug_d3dtstype(State));
2616 memcpy(pMatrix, &This->stateBlock->transforms[State], sizeof(D3DMATRIX));
2620 static HRESULT WINAPI IWineD3DDeviceImpl_MultiplyTransform(IWineD3DDevice *iface, D3DTRANSFORMSTATETYPE State, CONST D3DMATRIX* pMatrix) {
2621 D3DMATRIX *mat = NULL;
2624 /* Note: Using 'updateStateBlock' rather than 'stateblock' in the code
2625 * below means it will be recorded in a state block change, but it
2626 * works regardless where it is recorded.
2627 * If this is found to be wrong, change to StateBlock.
2629 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2630 TRACE("(%p) : For state %s\n", This, debug_d3dtstype(State));
2632 if (State < HIGHEST_TRANSFORMSTATE)
2634 mat = &This->updateStateBlock->transforms[State];
2636 FIXME("Unhandled transform state!!\n");
2639 multiply_matrix(&temp, mat, (D3DMATRIX *) pMatrix);
2641 /* Apply change via set transform - will reapply to eg. lights this way */
2642 return IWineD3DDeviceImpl_SetTransform(iface, State, &temp);
2647 * WARNING: This code relies on the fact that D3DLIGHT8 == D3DLIGHT9
2649 /* Note lights are real special cases. Although the device caps state only eg. 8 are supported,
2650 you can reference any indexes you want as long as that number max are enabled at any
2651 one point in time! Therefore since the indexes can be anything, we need a linked list of them.
2652 However, this causes stateblock problems. When capturing the state block, I duplicate the list,
2653 but when recording, just build a chain pretty much of commands to be replayed. */
2655 static HRESULT WINAPI IWineD3DDeviceImpl_SetLight(IWineD3DDevice *iface, DWORD Index, CONST WINED3DLIGHT* pLight) {
2657 PLIGHTINFOEL *object, *temp;
2659 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2660 TRACE("(%p) : Idx(%d), pLight(%p)\n", This, Index, pLight);
2662 /* If recording state block, just add to end of lights chain */
2663 if (This->isRecordingState) {
2664 object = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(PLIGHTINFOEL));
2665 if (NULL == object) {
2666 return WINED3DERR_OUTOFVIDEOMEMORY;
2668 memcpy(&object->OriginalParms, pLight, sizeof(D3DLIGHT9));
2669 object->OriginalIndex = Index;
2670 object->glIndex = -1;
2671 object->changed = TRUE;
2673 /* Add to the END of the chain of lights changes to be replayed */
2674 if (This->updateStateBlock->lights == NULL) {
2675 This->updateStateBlock->lights = object;
2677 temp = This->updateStateBlock->lights;
2678 while (temp->next != NULL) temp=temp->next;
2679 temp->next = object;
2681 TRACE("Recording... not performing anything more\n");
2685 /* Ok, not recording any longer so do real work */
2686 object = This->stateBlock->lights;
2687 while (object != NULL && object->OriginalIndex != Index) object = object->next;
2689 /* If we didn't find it in the list of lights, time to add it */
2690 if (object == NULL) {
2691 PLIGHTINFOEL *insertAt,*prevPos;
2693 object = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(PLIGHTINFOEL));
2694 if (NULL == object) {
2695 return WINED3DERR_OUTOFVIDEOMEMORY;
2697 object->OriginalIndex = Index;
2698 object->glIndex = -1;
2700 /* Add it to the front of list with the idea that lights will be changed as needed
2701 BUT after any lights currently assigned GL indexes */
2702 insertAt = This->stateBlock->lights;
2704 while (insertAt != NULL && insertAt->glIndex != -1) {
2706 insertAt = insertAt->next;
2709 if (insertAt == NULL && prevPos == NULL) { /* Start of list */
2710 This->stateBlock->lights = object;
2711 } else if (insertAt == NULL) { /* End of list */
2712 prevPos->next = object;
2713 object->prev = prevPos;
2714 } else { /* Middle of chain */
2715 if (prevPos == NULL) {
2716 This->stateBlock->lights = object;
2718 prevPos->next = object;
2720 object->prev = prevPos;
2721 object->next = insertAt;
2722 insertAt->prev = object;
2726 /* Initialize the object */
2727 TRACE("Light %d setting to type %d, Diffuse(%f,%f,%f,%f), Specular(%f,%f,%f,%f), Ambient(%f,%f,%f,%f)\n", Index, pLight->Type,
2728 pLight->Diffuse.r, pLight->Diffuse.g, pLight->Diffuse.b, pLight->Diffuse.a,
2729 pLight->Specular.r, pLight->Specular.g, pLight->Specular.b, pLight->Specular.a,
2730 pLight->Ambient.r, pLight->Ambient.g, pLight->Ambient.b, pLight->Ambient.a);
2731 TRACE("... Pos(%f,%f,%f), Dirn(%f,%f,%f)\n", pLight->Position.x, pLight->Position.y, pLight->Position.z,
2732 pLight->Direction.x, pLight->Direction.y, pLight->Direction.z);
2733 TRACE("... Range(%f), Falloff(%f), Theta(%f), Phi(%f)\n", pLight->Range, pLight->Falloff, pLight->Theta, pLight->Phi);
2735 /* Save away the information */
2736 memcpy(&object->OriginalParms, pLight, sizeof(D3DLIGHT9));
2738 switch (pLight->Type) {
2739 case D3DLIGHT_POINT:
2741 object->lightPosn[0] = pLight->Position.x;
2742 object->lightPosn[1] = pLight->Position.y;
2743 object->lightPosn[2] = pLight->Position.z;
2744 object->lightPosn[3] = 1.0f;
2745 object->cutoff = 180.0f;
2749 case D3DLIGHT_DIRECTIONAL:
2751 object->lightPosn[0] = -pLight->Direction.x;
2752 object->lightPosn[1] = -pLight->Direction.y;
2753 object->lightPosn[2] = -pLight->Direction.z;
2754 object->lightPosn[3] = 0.0;
2755 object->exponent = 0.0f;
2756 object->cutoff = 180.0f;
2761 object->lightPosn[0] = pLight->Position.x;
2762 object->lightPosn[1] = pLight->Position.y;
2763 object->lightPosn[2] = pLight->Position.z;
2764 object->lightPosn[3] = 1.0;
2767 object->lightDirn[0] = pLight->Direction.x;
2768 object->lightDirn[1] = pLight->Direction.y;
2769 object->lightDirn[2] = pLight->Direction.z;
2770 object->lightDirn[3] = 1.0;
2773 * opengl-ish and d3d-ish spot lights use too different models for the
2774 * light "intensity" as a function of the angle towards the main light direction,
2775 * so we only can approximate very roughly.
2776 * however spot lights are rather rarely used in games (if ever used at all).
2777 * furthermore if still used, probably nobody pays attention to such details.
2779 if (pLight->Falloff == 0) {
2782 rho = pLight->Theta + (pLight->Phi - pLight->Theta)/(2*pLight->Falloff);
2784 if (rho < 0.0001) rho = 0.0001f;
2785 object->exponent = -0.3/log(cos(rho/2));
2786 if (object->exponent > 128.0) {
2787 object->exponent = 128.0;
2789 object->cutoff = pLight->Phi*90/M_PI;
2795 FIXME("Unrecognized light type %d\n", pLight->Type);
2798 /* Update the live definitions if the light is currently assigned a glIndex */
2799 if (object->glIndex != -1) {
2800 setup_light(iface, object->glIndex, object);
2805 static HRESULT WINAPI IWineD3DDeviceImpl_GetLight(IWineD3DDevice *iface, DWORD Index, WINED3DLIGHT* pLight) {
2806 PLIGHTINFOEL *lightInfo = NULL;
2807 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2808 TRACE("(%p) : Idx(%d), pLight(%p)\n", This, Index, pLight);
2810 /* Locate the light in the live lights */
2811 lightInfo = This->stateBlock->lights;
2812 while (lightInfo != NULL && lightInfo->OriginalIndex != Index) lightInfo = lightInfo->next;
2814 if (lightInfo == NULL) {
2815 TRACE("Light information requested but light not defined\n");
2816 return WINED3DERR_INVALIDCALL;
2819 memcpy(pLight, &lightInfo->OriginalParms, sizeof(D3DLIGHT9));
2824 * Get / Set Light Enable
2825 * (Note for consistency, renamed d3dx function by adding the 'set' prefix)
2827 static HRESULT WINAPI IWineD3DDeviceImpl_SetLightEnable(IWineD3DDevice *iface, DWORD Index, BOOL Enable) {
2828 PLIGHTINFOEL *lightInfo = NULL;
2829 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2830 TRACE("(%p) : Idx(%d), enable? %d\n", This, Index, Enable);
2832 /* Tests show true = 128...not clear why */
2834 Enable = Enable? 128: 0;
2836 /* If recording state block, just add to end of lights chain with changedEnable set to true */
2837 if (This->isRecordingState) {
2838 lightInfo = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(PLIGHTINFOEL));
2839 if (NULL == lightInfo) {
2840 return WINED3DERR_OUTOFVIDEOMEMORY;
2842 lightInfo->OriginalIndex = Index;
2843 lightInfo->glIndex = -1;
2844 lightInfo->enabledChanged = TRUE;
2845 lightInfo->lightEnabled = Enable;
2847 /* Add to the END of the chain of lights changes to be replayed */
2848 if (This->updateStateBlock->lights == NULL) {
2849 This->updateStateBlock->lights = lightInfo;
2851 PLIGHTINFOEL *temp = This->updateStateBlock->lights;
2852 while (temp->next != NULL) temp=temp->next;
2853 temp->next = lightInfo;
2855 TRACE("Recording... not performing anything more\n");
2859 /* Not recording... So, locate the light in the live lights */
2860 lightInfo = This->stateBlock->lights;
2861 while (lightInfo != NULL && lightInfo->OriginalIndex != Index) lightInfo = lightInfo->next;
2863 /* Special case - enabling an undefined light creates one with a strict set of parms! */
2864 if (lightInfo == NULL) {
2866 TRACE("Light enabled requested but light not defined, so defining one!\n");
2867 IWineD3DDeviceImpl_SetLight(iface, Index, &WINED3D_default_light);
2869 /* Search for it again! Should be fairly quick as near head of list */
2870 lightInfo = This->stateBlock->lights;
2871 while (lightInfo != NULL && lightInfo->OriginalIndex != Index) lightInfo = lightInfo->next;
2872 if (lightInfo == NULL) {
2873 FIXME("Adding default lights has failed dismally\n");
2874 return WINED3DERR_INVALIDCALL;
2878 /* OK, we now have a light... */
2881 /* If we are disabling it, check it was enabled, and
2882 still only do something if it has assigned a glIndex (which it should have!) */
2883 if ((lightInfo->lightEnabled) && (lightInfo->glIndex != -1)) {
2884 TRACE("Disabling light set up at gl idx %d\n", lightInfo->glIndex);
2886 glDisable(GL_LIGHT0 + lightInfo->glIndex);
2887 checkGLcall("glDisable GL_LIGHT0+Index");
2890 TRACE("Nothing to do as light was not enabled\n");
2892 lightInfo->lightEnabled = Enable;
2895 /* We are enabling it. If it is enabled, it's really simple */
2896 if (lightInfo->lightEnabled) {
2898 TRACE("Nothing to do as light was enabled\n");
2900 /* If it already has a glIndex, it's still simple */
2901 } else if (lightInfo->glIndex != -1) {
2902 TRACE("Reusing light as already set up at gl idx %d\n", lightInfo->glIndex);
2903 lightInfo->lightEnabled = Enable;
2905 glEnable(GL_LIGHT0 + lightInfo->glIndex);
2906 checkGLcall("glEnable GL_LIGHT0+Index already setup");
2909 /* Otherwise got to find space - lights are ordered gl indexes first */
2911 PLIGHTINFOEL *bsf = NULL;
2912 PLIGHTINFOEL *pos = This->stateBlock->lights;
2913 PLIGHTINFOEL *prev = NULL;
2917 /* Try to minimize changes as much as possible */
2918 while (pos != NULL && pos->glIndex != -1 && Index < This->maxConcurrentLights) {
2920 /* Try to remember which index can be replaced if necessary */
2921 if (bsf==NULL && !pos->lightEnabled) {
2922 /* Found a light we can replace, save as best replacement */
2926 /* Step to next space */
2932 /* If we have too many active lights, fail the call */
2933 if ((Index == This->maxConcurrentLights) && (bsf == NULL)) {
2934 FIXME("Program requests too many concurrent lights\n");
2935 return WINED3DERR_INVALIDCALL;
2937 /* If we have allocated all lights, but not all are enabled,
2938 reuse one which is not enabled */
2939 } else if (Index == This->maxConcurrentLights) {
2940 /* use bsf - Simply swap the new light and the BSF one */
2941 PLIGHTINFOEL *bsfNext = bsf->next;
2942 PLIGHTINFOEL *bsfPrev = bsf->prev;
2945 if (lightInfo->next != NULL) lightInfo->next->prev = bsf;
2946 if (bsf->prev != NULL) {
2947 bsf->prev->next = lightInfo;
2949 This->stateBlock->lights = lightInfo;
2952 /* If not side by side, lots of chains to update */
2953 if (bsf->next != lightInfo) {
2954 lightInfo->prev->next = bsf;
2955 bsf->next->prev = lightInfo;
2956 bsf->next = lightInfo->next;
2957 bsf->prev = lightInfo->prev;
2958 lightInfo->next = bsfNext;
2959 lightInfo->prev = bsfPrev;
2963 bsf->prev = lightInfo;
2964 bsf->next = lightInfo->next;
2965 lightInfo->next = bsf;
2966 lightInfo->prev = bsfPrev;
2971 glIndex = bsf->glIndex;
2973 lightInfo->glIndex = glIndex;
2974 lightInfo->lightEnabled = Enable;
2976 /* Finally set up the light in gl itself */
2977 TRACE("Replacing light which was set up at gl idx %d\n", lightInfo->glIndex);
2979 setup_light(iface, glIndex, lightInfo);
2980 glEnable(GL_LIGHT0 + glIndex);
2981 checkGLcall("glEnable GL_LIGHT0 new setup");
2984 /* If we reached the end of the allocated lights, with space in the
2985 gl lights, setup a new light */
2986 } else if (pos->glIndex == -1) {
2988 /* We reached the end of the allocated gl lights, so already
2989 know the index of the next one! */
2991 lightInfo->glIndex = glIndex;
2992 lightInfo->lightEnabled = Enable;
2994 /* In an ideal world, it's already in the right place */
2995 if (lightInfo->prev == NULL || lightInfo->prev->glIndex!=-1) {
2996 /* No need to move it */
2998 /* Remove this light from the list */
2999 lightInfo->prev->next = lightInfo->next;
3000 if (lightInfo->next != NULL) {
3001 lightInfo->next->prev = lightInfo->prev;
3004 /* Add in at appropriate place (inbetween prev and pos) */
3005 lightInfo->prev = prev;
3006 lightInfo->next = pos;
3008 This->stateBlock->lights = lightInfo;
3010 prev->next = lightInfo;
3013 pos->prev = lightInfo;
3017 /* Finally set up the light in gl itself */
3018 TRACE("Defining new light at gl idx %d\n", lightInfo->glIndex);
3020 setup_light(iface, glIndex, lightInfo);
3021 glEnable(GL_LIGHT0 + glIndex);
3022 checkGLcall("glEnable GL_LIGHT0 new setup");
3031 static HRESULT WINAPI IWineD3DDeviceImpl_GetLightEnable(IWineD3DDevice *iface, DWORD Index,BOOL* pEnable) {
3033 PLIGHTINFOEL *lightInfo = NULL;
3034 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3035 TRACE("(%p) : for idx(%d)\n", This, Index);
3037 /* Locate the light in the live lights */
3038 lightInfo = This->stateBlock->lights;
3039 while (lightInfo != NULL && lightInfo->OriginalIndex != Index) lightInfo = lightInfo->next;
3041 if (lightInfo == NULL) {
3042 TRACE("Light enabled state requested but light not defined\n");
3043 return WINED3DERR_INVALIDCALL;
3045 *pEnable = lightInfo->lightEnabled;
3050 * Get / Set Clip Planes
3052 static HRESULT WINAPI IWineD3DDeviceImpl_SetClipPlane(IWineD3DDevice *iface, DWORD Index, CONST float *pPlane) {
3053 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3054 TRACE("(%p) : for idx %d, %p\n", This, Index, pPlane);
3056 /* Validate Index */
3057 if (Index >= GL_LIMITS(clipplanes)) {
3058 TRACE("Application has requested clipplane this device doesn't support\n");
3059 return WINED3DERR_INVALIDCALL;
3062 This->updateStateBlock->changed.clipplane[Index] = TRUE;
3063 This->updateStateBlock->set.clipplane[Index] = TRUE;
3064 This->updateStateBlock->clipplane[Index][0] = pPlane[0];
3065 This->updateStateBlock->clipplane[Index][1] = pPlane[1];
3066 This->updateStateBlock->clipplane[Index][2] = pPlane[2];
3067 This->updateStateBlock->clipplane[Index][3] = pPlane[3];
3069 /* Handle recording of state blocks */
3070 if (This->isRecordingState) {
3071 TRACE("Recording... not performing anything\n");
3079 /* Clip Plane settings are affected by the model view in OpenGL, the View transform in direct3d */
3080 glMatrixMode(GL_MODELVIEW);
3082 glLoadMatrixf((float *) &This->stateBlock->transforms[WINED3DTS_VIEW].u.m[0][0]);
3084 TRACE("Clipplane [%f,%f,%f,%f]\n",
3085 This->updateStateBlock->clipplane[Index][0],
3086 This->updateStateBlock->clipplane[Index][1],
3087 This->updateStateBlock->clipplane[Index][2],
3088 This->updateStateBlock->clipplane[Index][3]);
3089 glClipPlane(GL_CLIP_PLANE0 + Index, This->updateStateBlock->clipplane[Index]);
3090 checkGLcall("glClipPlane");
3098 static HRESULT WINAPI IWineD3DDeviceImpl_GetClipPlane(IWineD3DDevice *iface, DWORD Index, float *pPlane) {
3099 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3100 TRACE("(%p) : for idx %d\n", This, Index);
3102 /* Validate Index */
3103 if (Index >= GL_LIMITS(clipplanes)) {
3104 TRACE("Application has requested clipplane this device doesn't support\n");
3105 return WINED3DERR_INVALIDCALL;
3108 pPlane[0] = This->stateBlock->clipplane[Index][0];
3109 pPlane[1] = This->stateBlock->clipplane[Index][1];
3110 pPlane[2] = This->stateBlock->clipplane[Index][2];
3111 pPlane[3] = This->stateBlock->clipplane[Index][3];
3116 * Get / Set Clip Plane Status
3117 * WARNING: This code relies on the fact that D3DCLIPSTATUS8 == D3DCLIPSTATUS9
3119 static HRESULT WINAPI IWineD3DDeviceImpl_SetClipStatus(IWineD3DDevice *iface, CONST WINED3DCLIPSTATUS* pClipStatus) {
3120 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3121 FIXME("(%p) : stub\n", This);
3122 if (NULL == pClipStatus) {
3123 return WINED3DERR_INVALIDCALL;
3125 This->updateStateBlock->clip_status.ClipUnion = pClipStatus->ClipUnion;
3126 This->updateStateBlock->clip_status.ClipIntersection = pClipStatus->ClipIntersection;
3130 static HRESULT WINAPI IWineD3DDeviceImpl_GetClipStatus(IWineD3DDevice *iface, WINED3DCLIPSTATUS* pClipStatus) {
3131 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3132 FIXME("(%p) : stub\n", This);
3133 if (NULL == pClipStatus) {
3134 return WINED3DERR_INVALIDCALL;
3136 pClipStatus->ClipUnion = This->updateStateBlock->clip_status.ClipUnion;
3137 pClipStatus->ClipIntersection = This->updateStateBlock->clip_status.ClipIntersection;
3142 * Get / Set Material
3143 * WARNING: This code relies on the fact that D3DMATERIAL8 == D3DMATERIAL9
3145 static HRESULT WINAPI IWineD3DDeviceImpl_SetMaterial(IWineD3DDevice *iface, CONST WINED3DMATERIAL* pMaterial) {
3146 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3148 This->updateStateBlock->changed.material = TRUE;
3149 This->updateStateBlock->set.material = TRUE;
3150 memcpy(&This->updateStateBlock->material, pMaterial, sizeof(WINED3DMATERIAL));
3152 /* Handle recording of state blocks */
3153 if (This->isRecordingState) {
3154 TRACE("Recording... not performing anything\n");
3159 TRACE("(%p) : Diffuse (%f,%f,%f,%f)\n", This, pMaterial->Diffuse.r, pMaterial->Diffuse.g,
3160 pMaterial->Diffuse.b, pMaterial->Diffuse.a);
3161 TRACE("(%p) : Ambient (%f,%f,%f,%f)\n", This, pMaterial->Ambient.r, pMaterial->Ambient.g,
3162 pMaterial->Ambient.b, pMaterial->Ambient.a);
3163 TRACE("(%p) : Specular (%f,%f,%f,%f)\n", This, pMaterial->Specular.r, pMaterial->Specular.g,
3164 pMaterial->Specular.b, pMaterial->Specular.a);
3165 TRACE("(%p) : Emissive (%f,%f,%f,%f)\n", This, pMaterial->Emissive.r, pMaterial->Emissive.g,
3166 pMaterial->Emissive.b, pMaterial->Emissive.a);
3167 TRACE("(%p) : Power (%f)\n", This, pMaterial->Power);
3169 glMaterialfv(GL_FRONT_AND_BACK, GL_AMBIENT, (float*) &This->updateStateBlock->material.Ambient);
3170 checkGLcall("glMaterialfv(GL_AMBIENT)");
3171 glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, (float*) &This->updateStateBlock->material.Diffuse);
3172 checkGLcall("glMaterialfv(GL_DIFFUSE)");
3174 /* Only change material color if specular is enabled, otherwise it is set to black */
3175 if (This->stateBlock->renderState[WINED3DRS_SPECULARENABLE]) {
3176 glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, (float*) &This->updateStateBlock->material.Specular);
3177 checkGLcall("glMaterialfv(GL_SPECULAR");
3179 float black[4] = {0.0f, 0.0f, 0.0f, 0.0f};
3180 glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, &black[0]);
3181 checkGLcall("glMaterialfv(GL_SPECULAR");
3183 glMaterialfv(GL_FRONT_AND_BACK, GL_EMISSION, (float*) &This->updateStateBlock->material.Emissive);
3184 checkGLcall("glMaterialfv(GL_EMISSION)");
3185 glMaterialf(GL_FRONT_AND_BACK, GL_SHININESS, This->updateStateBlock->material.Power);
3186 checkGLcall("glMaterialf(GL_SHININESS");
3192 static HRESULT WINAPI IWineD3DDeviceImpl_GetMaterial(IWineD3DDevice *iface, WINED3DMATERIAL* pMaterial) {
3193 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3194 memcpy(pMaterial, &This->updateStateBlock->material, sizeof (WINED3DMATERIAL));
3195 TRACE("(%p) : Diffuse (%f,%f,%f,%f)\n", This, pMaterial->Diffuse.r, pMaterial->Diffuse.g,
3196 pMaterial->Diffuse.b, pMaterial->Diffuse.a);
3197 TRACE("(%p) : Ambient (%f,%f,%f,%f)\n", This, pMaterial->Ambient.r, pMaterial->Ambient.g,
3198 pMaterial->Ambient.b, pMaterial->Ambient.a);
3199 TRACE("(%p) : Specular (%f,%f,%f,%f)\n", This, pMaterial->Specular.r, pMaterial->Specular.g,
3200 pMaterial->Specular.b, pMaterial->Specular.a);
3201 TRACE("(%p) : Emissive (%f,%f,%f,%f)\n", This, pMaterial->Emissive.r, pMaterial->Emissive.g,
3202 pMaterial->Emissive.b, pMaterial->Emissive.a);
3203 TRACE("(%p) : Power (%f)\n", This, pMaterial->Power);
3211 static HRESULT WINAPI IWineD3DDeviceImpl_SetIndices(IWineD3DDevice *iface, IWineD3DIndexBuffer* pIndexData,
3212 UINT BaseVertexIndex) {
3213 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3214 IWineD3DIndexBuffer *oldIdxs;
3216 TRACE("(%p) : Setting to %p, base %d\n", This, pIndexData, BaseVertexIndex);
3217 oldIdxs = This->updateStateBlock->pIndexData;
3219 This->updateStateBlock->changed.indices = TRUE;
3220 This->updateStateBlock->set.indices = TRUE;
3221 This->updateStateBlock->pIndexData = pIndexData;
3222 This->updateStateBlock->baseVertexIndex = BaseVertexIndex;
3224 /* Handle recording of state blocks */
3225 if (This->isRecordingState) {
3226 TRACE("Recording... not performing anything\n");
3230 if (NULL != pIndexData) {
3231 IWineD3DIndexBuffer_AddRef(pIndexData);
3233 if (NULL != oldIdxs) {
3234 IWineD3DIndexBuffer_Release(oldIdxs);
3239 static HRESULT WINAPI IWineD3DDeviceImpl_GetIndices(IWineD3DDevice *iface, IWineD3DIndexBuffer** ppIndexData, UINT* pBaseVertexIndex) {
3240 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3242 *ppIndexData = This->stateBlock->pIndexData;
3244 /* up ref count on ppindexdata */
3246 IWineD3DIndexBuffer_AddRef(*ppIndexData);
3247 *pBaseVertexIndex = This->stateBlock->baseVertexIndex;
3248 TRACE("(%p) index data set to %p + %u\n", This, ppIndexData, This->stateBlock->baseVertexIndex);
3250 TRACE("(%p) No index data set\n", This);
3252 TRACE("Returning %p %d\n", *ppIndexData, *pBaseVertexIndex);
3258 * Get / Set Viewports
3260 static HRESULT WINAPI IWineD3DDeviceImpl_SetViewport(IWineD3DDevice *iface, CONST WINED3DVIEWPORT* pViewport) {
3261 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3263 TRACE("(%p)\n", This);
3264 This->updateStateBlock->changed.viewport = TRUE;
3265 This->updateStateBlock->set.viewport = TRUE;
3266 memcpy(&This->updateStateBlock->viewport, pViewport, sizeof(WINED3DVIEWPORT));
3268 /* Handle recording of state blocks */
3269 if (This->isRecordingState) {
3270 TRACE("Recording... not performing anything\n");
3273 This->viewport_changed = TRUE;
3277 TRACE("(%p) : x=%d, y=%d, wid=%d, hei=%d, minz=%f, maxz=%f\n", This,
3278 pViewport->X, pViewport->Y, pViewport->Width, pViewport->Height, pViewport->MinZ, pViewport->MaxZ);
3280 glDepthRange(pViewport->MinZ, pViewport->MaxZ);
3281 checkGLcall("glDepthRange");
3282 /* Note: GL requires lower left, DirectX supplies upper left */
3283 /* TODO: replace usage of renderTarget with context management */
3284 glViewport(pViewport->X,
3285 (((IWineD3DSurfaceImpl *)This->renderTarget)->currentDesc.Height - (pViewport->Y + pViewport->Height)),
3286 pViewport->Width, pViewport->Height);
3288 checkGLcall("glViewport");
3296 static HRESULT WINAPI IWineD3DDeviceImpl_GetViewport(IWineD3DDevice *iface, WINED3DVIEWPORT* pViewport) {
3297 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3298 TRACE("(%p)\n", This);
3299 memcpy(pViewport, &This->stateBlock->viewport, sizeof(WINED3DVIEWPORT));
3303 static void renderstate_stencil_twosided(
3304 IWineD3DDeviceImpl *This,
3311 GLint stencilPass ) {
3312 #if 0 /* Don't use OpenGL 2.0 calls for now */
3313 if(GL_EXTCALL(glStencilFuncSeparate) && GL_EXTCALL(glStencilOpSeparate)) {
3314 GL_EXTCALL(glStencilFuncSeparate(face, func, ref, mask));
3315 checkGLcall("glStencilFuncSeparate(...)");
3316 GL_EXTCALL(glStencilOpSeparate(face, stencilFail, depthFail, stencilPass));
3317 checkGLcall("glStencilOpSeparate(...)");
3321 if(GL_SUPPORT(EXT_STENCIL_TWO_SIDE)) {
3322 glEnable(GL_STENCIL_TEST_TWO_SIDE_EXT);
3323 checkGLcall("glEnable(GL_STENCIL_TEST_TWO_SIDE_EXT)");
3324 GL_EXTCALL(glActiveStencilFaceEXT(face));
3325 checkGLcall("glActiveStencilFaceEXT(...)");
3326 glStencilFunc(func, ref, mask);
3327 checkGLcall("glStencilFunc(...)");
3328 glStencilOp(stencilFail, depthFail, stencilPass);
3329 checkGLcall("glStencilOp(...)");
3330 } else if(GL_SUPPORT(ATI_SEPARATE_STENCIL)) {
3331 GL_EXTCALL(glStencilFuncSeparateATI(face, func, ref, mask));
3332 checkGLcall("glStencilFuncSeparateATI(...)");
3333 GL_EXTCALL(glStencilOpSeparateATI(face, stencilFail, depthFail, stencilPass));
3334 checkGLcall("glStencilOpSeparateATI(...)");
3336 ERR("Separate (two sided) stencil not supported on this version of opengl. Caps weren't honored?\n");
3340 static void renderstate_stencil(IWineD3DDeviceImpl *This, D3DRENDERSTATETYPE State, DWORD Value) {
3341 DWORD onesided_enable = FALSE;
3342 DWORD twosided_enable = FALSE;
3343 GLint func = GL_ALWAYS;
3344 GLint func_ccw = GL_ALWAYS;
3347 GLint stencilFail = GL_KEEP;
3348 GLint depthFail = GL_KEEP;
3349 GLint stencilPass = GL_KEEP;
3350 GLint stencilFail_ccw = GL_KEEP;
3351 GLint depthFail_ccw = GL_KEEP;
3352 GLint stencilPass_ccw = GL_KEEP;
3354 if( This->stateBlock->set.renderState[WINED3DRS_STENCILENABLE] )
3355 onesided_enable = This->stateBlock->renderState[WINED3DRS_STENCILENABLE];
3356 if( This->stateBlock->set.renderState[WINED3DRS_TWOSIDEDSTENCILMODE] )
3357 twosided_enable = This->stateBlock->renderState[WINED3DRS_TWOSIDEDSTENCILMODE];
3358 if( This->stateBlock->set.renderState[WINED3DRS_STENCILFUNC] )
3359 if( !( func = CompareFunc(This->stateBlock->renderState[WINED3DRS_STENCILFUNC]) ) )
3361 if( This->stateBlock->set.renderState[WINED3DRS_CCW_STENCILFUNC] )
3362 if( !( func_ccw = CompareFunc(This->stateBlock->renderState[WINED3DRS_CCW_STENCILFUNC]) ) )
3364 if( This->stateBlock->set.renderState[WINED3DRS_STENCILREF] )
3365 ref = This->stateBlock->renderState[WINED3DRS_STENCILREF];
3366 if( This->stateBlock->set.renderState[WINED3DRS_STENCILMASK] )
3367 mask = This->stateBlock->renderState[WINED3DRS_STENCILMASK];
3368 if( This->stateBlock->set.renderState[WINED3DRS_STENCILFAIL] )
3369 stencilFail = StencilOp(This->stateBlock->renderState[WINED3DRS_STENCILFAIL]);
3370 if( This->stateBlock->set.renderState[WINED3DRS_STENCILZFAIL] )
3371 depthFail = StencilOp(This->stateBlock->renderState[WINED3DRS_STENCILZFAIL]);
3372 if( This->stateBlock->set.renderState[WINED3DRS_STENCILPASS] )
3373 stencilPass = StencilOp(This->stateBlock->renderState[WINED3DRS_STENCILPASS]);
3374 if( This->stateBlock->set.renderState[WINED3DRS_CCW_STENCILFAIL] )
3375 stencilFail_ccw = StencilOp(This->stateBlock->renderState[WINED3DRS_CCW_STENCILFAIL]);
3376 if( This->stateBlock->set.renderState[WINED3DRS_CCW_STENCILZFAIL] )
3377 depthFail_ccw = StencilOp(This->stateBlock->renderState[WINED3DRS_CCW_STENCILZFAIL]);
3378 if( This->stateBlock->set.renderState[WINED3DRS_CCW_STENCILPASS] )
3379 stencilPass_ccw = StencilOp(This->stateBlock->renderState[WINED3DRS_CCW_STENCILPASS]);
3381 TRACE("(onesided %d, twosided %d, ref %x, mask %x, \
3382 GL_FRONT: func: %x, fail %x, zfail %x, zpass %x \
3383 GL_BACK: func: %x, fail %x, zfail %x, zpass %x )\n",
3384 onesided_enable, twosided_enable, ref, mask,
3385 func, stencilFail, depthFail, stencilPass,
3386 func_ccw, stencilFail_ccw, depthFail_ccw, stencilPass_ccw);
3388 if (twosided_enable) {
3389 renderstate_stencil_twosided(This, GL_FRONT, func, ref, mask, stencilFail, depthFail, stencilPass);
3390 renderstate_stencil_twosided(This, GL_BACK, func_ccw, ref, mask, stencilFail_ccw, depthFail_ccw, stencilPass_ccw);
3392 if (onesided_enable) {
3393 glEnable(GL_STENCIL_TEST);
3394 checkGLcall("glEnable GL_STENCIL_TEST");
3395 glStencilFunc(func, ref, mask);
3396 checkGLcall("glStencilFunc(...)");
3397 glStencilOp(stencilFail, depthFail, stencilPass);
3398 checkGLcall("glStencilOp(...)");
3400 glDisable(GL_STENCIL_TEST);
3401 checkGLcall("glDisable GL_STENCIL_TEST");
3407 * Get / Set Render States
3408 * TODO: Verify against dx9 definitions
3410 static HRESULT WINAPI IWineD3DDeviceImpl_SetRenderState(IWineD3DDevice *iface, D3DRENDERSTATETYPE State, DWORD Value) {
3412 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3413 DWORD OldValue = This->stateBlock->renderState[State];
3415 /* Simple way of referring to either a DWORD or a 4 byte float */
3421 TRACE("(%p)->state = %s(%d), value = %d\n", This, debug_d3drenderstate(State), State, Value);
3422 This->updateStateBlock->changed.renderState[State] = TRUE;
3423 This->updateStateBlock->set.renderState[State] = TRUE;
3424 This->updateStateBlock->renderState[State] = Value;
3426 /* Handle recording of state blocks */
3427 if (This->isRecordingState) {
3428 TRACE("Recording... not performing anything\n");
3435 case WINED3DRS_FILLMODE :
3436 switch ((D3DFILLMODE) Value) {
3437 case D3DFILL_POINT : glPolygonMode(GL_FRONT_AND_BACK, GL_POINT); break;
3438 case D3DFILL_WIREFRAME : glPolygonMode(GL_FRONT_AND_BACK, GL_LINE); break;
3439 case D3DFILL_SOLID : glPolygonMode(GL_FRONT_AND_BACK, GL_FILL); break;
3441 FIXME("Unrecognized WINED3DRS_FILLMODE value %d\n", Value);
3443 checkGLcall("glPolygonMode (fillmode)");
3446 case WINED3DRS_LIGHTING :
3448 glEnable(GL_LIGHTING);
3449 checkGLcall("glEnable GL_LIGHTING");
3451 glDisable(GL_LIGHTING);
3452 checkGLcall("glDisable GL_LIGHTING");
3456 case WINED3DRS_ZENABLE :
3457 switch ((D3DZBUFFERTYPE) Value) {
3459 glDisable(GL_DEPTH_TEST);
3460 checkGLcall("glDisable GL_DEPTH_TEST");
3463 glEnable(GL_DEPTH_TEST);
3464 checkGLcall("glEnable GL_DEPTH_TEST");
3467 glEnable(GL_DEPTH_TEST);
3468 checkGLcall("glEnable GL_DEPTH_TEST");
3469 FIXME("W buffer is not well handled\n");
3472 FIXME("Unrecognized D3DZBUFFERTYPE value %d\n", Value);
3476 case WINED3DRS_CULLMODE :
3478 /* If we are culling "back faces with clockwise vertices" then
3479 set front faces to be counter clockwise and enable culling
3481 switch ((D3DCULL) Value) {
3483 glDisable(GL_CULL_FACE);
3484 checkGLcall("glDisable GL_CULL_FACE");
3487 glEnable(GL_CULL_FACE);
3488 checkGLcall("glEnable GL_CULL_FACE");
3489 if (This->renderUpsideDown) {
3491 checkGLcall("glFrontFace GL_CW");
3493 glFrontFace(GL_CCW);
3494 checkGLcall("glFrontFace GL_CCW");
3496 glCullFace(GL_BACK);
3499 glEnable(GL_CULL_FACE);
3500 checkGLcall("glEnable GL_CULL_FACE");
3501 if (This->renderUpsideDown) {
3502 glFrontFace(GL_CCW);
3503 checkGLcall("glFrontFace GL_CCW");
3506 checkGLcall("glFrontFace GL_CW");
3508 glCullFace(GL_BACK);
3511 FIXME("Unrecognized/Unhandled D3DCULL value %d\n", Value);
3515 case WINED3DRS_SHADEMODE :
3516 switch ((D3DSHADEMODE) Value) {
3518 glShadeModel(GL_FLAT);
3519 checkGLcall("glShadeModel");
3521 case D3DSHADE_GOURAUD:
3522 glShadeModel(GL_SMOOTH);
3523 checkGLcall("glShadeModel");
3525 case D3DSHADE_PHONG:
3526 FIXME("D3DSHADE_PHONG isn't supported\n");
3529 FIXME("Unrecognized/Unhandled D3DSHADEMODE value %d\n", Value);
3533 case WINED3DRS_DITHERENABLE :
3535 glEnable(GL_DITHER);
3536 checkGLcall("glEnable GL_DITHER");
3538 glDisable(GL_DITHER);
3539 checkGLcall("glDisable GL_DITHER");
3543 case WINED3DRS_ZWRITEENABLE :
3546 checkGLcall("glDepthMask");
3549 checkGLcall("glDepthMask");
3553 case WINED3DRS_ZFUNC :
3555 int glParm = CompareFunc(Value);
3558 glDepthFunc(glParm);
3559 checkGLcall("glDepthFunc");
3564 case WINED3DRS_AMBIENT :
3567 D3DCOLORTOGLFLOAT4(Value, col);
3568 TRACE("Setting ambient to (%f,%f,%f,%f)\n", col[0], col[1], col[2], col[3]);
3569 glLightModelfv(GL_LIGHT_MODEL_AMBIENT, col);
3570 checkGLcall("glLightModel for MODEL_AMBIENT");
3575 case WINED3DRS_ALPHABLENDENABLE :
3578 checkGLcall("glEnable GL_BLEND");
3580 glDisable(GL_BLEND);
3581 checkGLcall("glDisable GL_BLEND");
3585 case WINED3DRS_SRCBLEND :
3586 case WINED3DRS_DESTBLEND :
3588 int newVal = GL_ZERO;
3590 case D3DBLEND_ZERO : newVal = GL_ZERO; break;
3591 case D3DBLEND_ONE : newVal = GL_ONE; break;
3592 case D3DBLEND_SRCCOLOR : newVal = GL_SRC_COLOR; break;
3593 case D3DBLEND_INVSRCCOLOR : newVal = GL_ONE_MINUS_SRC_COLOR; break;
3594 case D3DBLEND_SRCALPHA : newVal = GL_SRC_ALPHA; break;
3595 case D3DBLEND_INVSRCALPHA : newVal = GL_ONE_MINUS_SRC_ALPHA; break;
3596 case D3DBLEND_DESTALPHA : newVal = GL_DST_ALPHA; break;
3597 case D3DBLEND_INVDESTALPHA : newVal = GL_ONE_MINUS_DST_ALPHA; break;
3598 case D3DBLEND_DESTCOLOR : newVal = GL_DST_COLOR; break;
3599 case D3DBLEND_INVDESTCOLOR : newVal = GL_ONE_MINUS_DST_COLOR; break;
3600 case D3DBLEND_SRCALPHASAT : newVal = GL_SRC_ALPHA_SATURATE; break;
3602 case D3DBLEND_BOTHSRCALPHA : newVal = GL_SRC_ALPHA;
3603 This->srcBlend = newVal;
3604 This->dstBlend = newVal;
3607 case D3DBLEND_BOTHINVSRCALPHA : newVal = GL_ONE_MINUS_SRC_ALPHA;
3608 This->srcBlend = newVal;
3609 This->dstBlend = newVal;
3611 case D3DBLEND_BLENDFACTOR : newVal = GL_CONSTANT_COLOR; break;
3612 case D3DBLEND_INVBLENDFACTOR : newVal = GL_ONE_MINUS_CONSTANT_COLOR; break;
3614 FIXME("Unrecognized src/dest blend value %d (%d)\n", Value, State);
3617 if (State == WINED3DRS_SRCBLEND) This->srcBlend = newVal;
3618 if (State == WINED3DRS_DESTBLEND) This->dstBlend = newVal;
3619 TRACE("glBlendFunc src=%x, dst=%x\n", This->srcBlend, This->dstBlend);
3620 glBlendFunc(This->srcBlend, This->dstBlend);
3622 checkGLcall("glBlendFunc");
3626 case WINED3DRS_ALPHATESTENABLE :
3627 case WINED3DRS_ALPHAFUNC :
3628 case WINED3DRS_ALPHAREF :
3629 case WINED3DRS_COLORKEYENABLE :
3633 BOOL enable_ckey = FALSE;
3635 IWineD3DSurfaceImpl *surf;
3637 /* Find out if the texture on the first stage has a ckey set */
3638 if(This->stateBlock->textures[0]) {
3639 surf = (IWineD3DSurfaceImpl *) ((IWineD3DTextureImpl *)This->stateBlock->textures[0])->surfaces[0];
3640 if(surf->CKeyFlags & DDSD_CKSRCBLT) enable_ckey = TRUE;
3643 if (This->stateBlock->renderState[WINED3DRS_ALPHATESTENABLE] ||
3644 (This->stateBlock->renderState[WINED3DRS_COLORKEYENABLE] && enable_ckey)) {
3645 glEnable(GL_ALPHA_TEST);
3646 checkGLcall("glEnable GL_ALPHA_TEST");
3648 glDisable(GL_ALPHA_TEST);
3649 checkGLcall("glDisable GL_ALPHA_TEST");
3650 /* Alpha test is disabled, don't bother setting the params - it will happen on the next
3656 if(This->stateBlock->renderState[WINED3DRS_COLORKEYENABLE] && enable_ckey) {
3657 glParm = GL_NOTEQUAL;
3660 ref = ((float) This->stateBlock->renderState[WINED3DRS_ALPHAREF]) / 255.0f;
3661 glParm = CompareFunc(This->stateBlock->renderState[WINED3DRS_ALPHAFUNC]);
3664 This->alphafunc = glParm;
3665 glAlphaFunc(glParm, ref);
3666 checkGLcall("glAlphaFunc");
3671 case WINED3DRS_CLIPPLANEENABLE :
3672 case WINED3DRS_CLIPPING :
3674 /* Ensure we only do the changed clip planes */
3675 DWORD enable = 0xFFFFFFFF;
3676 DWORD disable = 0x00000000;
3678 /* If enabling / disabling all */
3679 if (State == WINED3DRS_CLIPPING) {
3681 enable = This->stateBlock->renderState[WINED3DRS_CLIPPLANEENABLE];
3684 disable = This->stateBlock->renderState[WINED3DRS_CLIPPLANEENABLE];
3688 enable = Value & ~OldValue;
3689 disable = ~Value & OldValue;
3692 if (enable & D3DCLIPPLANE0) { glEnable(GL_CLIP_PLANE0); checkGLcall("glEnable(clip plane 0)"); }
3693 if (enable & D3DCLIPPLANE1) { glEnable(GL_CLIP_PLANE1); checkGLcall("glEnable(clip plane 1)"); }
3694 if (enable & D3DCLIPPLANE2) { glEnable(GL_CLIP_PLANE2); checkGLcall("glEnable(clip plane 2)"); }
3695 if (enable & D3DCLIPPLANE3) { glEnable(GL_CLIP_PLANE3); checkGLcall("glEnable(clip plane 3)"); }
3696 if (enable & D3DCLIPPLANE4) { glEnable(GL_CLIP_PLANE4); checkGLcall("glEnable(clip plane 4)"); }
3697 if (enable & D3DCLIPPLANE5) { glEnable(GL_CLIP_PLANE5); checkGLcall("glEnable(clip plane 5)"); }
3699 if (disable & D3DCLIPPLANE0) { glDisable(GL_CLIP_PLANE0); checkGLcall("glDisable(clip plane 0)"); }
3700 if (disable & D3DCLIPPLANE1) { glDisable(GL_CLIP_PLANE1); checkGLcall("glDisable(clip plane 1)"); }
3701 if (disable & D3DCLIPPLANE2) { glDisable(GL_CLIP_PLANE2); checkGLcall("glDisable(clip plane 2)"); }
3702 if (disable & D3DCLIPPLANE3) { glDisable(GL_CLIP_PLANE3); checkGLcall("glDisable(clip plane 3)"); }
3703 if (disable & D3DCLIPPLANE4) { glDisable(GL_CLIP_PLANE4); checkGLcall("glDisable(clip plane 4)"); }
3704 if (disable & D3DCLIPPLANE5) { glDisable(GL_CLIP_PLANE5); checkGLcall("glDisable(clip plane 5)"); }
3706 /** update clipping status */
3708 This->stateBlock->clip_status.ClipUnion = 0;
3709 This->stateBlock->clip_status.ClipIntersection = 0xFFFFFFFF;
3711 This->stateBlock->clip_status.ClipUnion = 0;
3712 This->stateBlock->clip_status.ClipIntersection = 0;
3717 case WINED3DRS_BLENDOP :
3719 int glParm = GL_FUNC_ADD;
3721 switch ((D3DBLENDOP) Value) {
3722 case D3DBLENDOP_ADD : glParm = GL_FUNC_ADD; break;
3723 case D3DBLENDOP_SUBTRACT : glParm = GL_FUNC_SUBTRACT; break;
3724 case D3DBLENDOP_REVSUBTRACT : glParm = GL_FUNC_REVERSE_SUBTRACT; break;
3725 case D3DBLENDOP_MIN : glParm = GL_MIN; break;
3726 case D3DBLENDOP_MAX : glParm = GL_MAX; break;
3728 FIXME("Unrecognized/Unhandled D3DBLENDOP value %d\n", Value);
3731 if(GL_SUPPORT(EXT_BLEND_MINMAX)) {
3732 TRACE("glBlendEquation(%x)\n", glParm);
3733 GL_EXTCALL(glBlendEquation(glParm));
3734 checkGLcall("glBlendEquation");
3736 WARN("Unsupported in local OpenGL implementation: glBlendEquation\n");
3741 case WINED3DRS_TEXTUREFACTOR :
3745 /* Note the texture color applies to all textures whereas
3746 GL_TEXTURE_ENV_COLOR applies to active only */
3748 D3DCOLORTOGLFLOAT4(Value, col);
3750 if (!GL_SUPPORT(NV_REGISTER_COMBINERS)) {
3751 /* And now the default texture color as well */
3752 for (i = 0; i < GL_LIMITS(texture_stages); i++) {
3753 /* Note the D3DRS value applies to all textures, but GL has one
3754 per texture, so apply it now ready to be used! */
3755 if (GL_SUPPORT(ARB_MULTITEXTURE)) {
3756 GL_EXTCALL(glActiveTextureARB(GL_TEXTURE0_ARB + i));
3757 checkGLcall("glActiveTextureARB");
3759 FIXME("Program using multiple concurrent textures which this opengl implementation doesn't support\n");
3762 glTexEnvfv(GL_TEXTURE_ENV, GL_TEXTURE_ENV_COLOR, &col[0]);
3763 checkGLcall("glTexEnvfv(GL_TEXTURE_ENV, GL_TEXTURE_ENV_COLOR, color);");
3769 case WINED3DRS_SPECULARENABLE :
3771 /* Originally this used glLightModeli(GL_LIGHT_MODEL_COLOR_CONTROL,GL_SEPARATE_SPECULAR_COLOR)
3772 and (GL_LIGHT_MODEL_COLOR_CONTROL,GL_SINGLE_COLOR) to swap between enabled/disabled
3773 specular color. This is wrong:
3774 Separate specular color means the specular colour is maintained separately, whereas
3775 single color means it is merged in. However in both cases they are being used to
3777 To disable specular color, set it explicitly to black and turn off GL_COLOR_SUM_EXT
3778 NOTE: If not supported don't give FIXMEs the impact is really minimal and very few people are
3782 * If register combiners are enabled, enabling / disabling GL_COLOR_SUM has no effect.
3783 * Instead, we need to setup the FinalCombiner properly.
3785 * The default setup for the FinalCombiner is:
3787 * <variable> <input> <mapping> <usage>
3788 * GL_VARIABLE_A_NV GL_FOG, GL_UNSIGNED_IDENTITY_NV GL_ALPHA
3789 * GL_VARIABLE_B_NV GL_SPARE0_PLUS_SECONDARY_COLOR_NV GL_UNSIGNED_IDENTITY_NV GL_RGB
3790 * GL_VARIABLE_C_NV GL_FOG GL_UNSIGNED_IDENTITY_NV GL_RGB
3791 * GL_VARIABLE_D_NV GL_ZERO GL_UNSIGNED_IDENTITY_NV GL_RGB
3792 * GL_VARIABLE_E_NV GL_ZERO GL_UNSIGNED_IDENTITY_NV GL_RGB
3793 * GL_VARIABLE_F_NV GL_ZERO GL_UNSIGNED_IDENTITY_NV GL_RGB
3794 * GL_VARIABLE_G_NV GL_SPARE0_NV GL_UNSIGNED_IDENTITY_NV GL_ALPHA
3796 * That's pretty much fine as it is, except for variable B, which needs to take
3797 * either GL_SPARE0_PLUS_SECONDARY_COLOR_NV or GL_SPARE0_NV, depending on
3798 * whether WINED3DRS_SPECULARENABLE is enabled or not.
3802 glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, (float*) &This->updateStateBlock->material.Specular);
3803 checkGLcall("glMaterialfv");
3804 if (GL_SUPPORT(EXT_SECONDARY_COLOR)) {
3805 glEnable(GL_COLOR_SUM_EXT);
3807 TRACE("Specular colors cannot be enabled in this version of opengl\n");
3809 checkGLcall("glEnable(GL_COLOR_SUM)");
3811 if (GL_SUPPORT(NV_REGISTER_COMBINERS)) {
3812 GL_EXTCALL(glFinalCombinerInputNV(GL_VARIABLE_B_NV, GL_SPARE0_PLUS_SECONDARY_COLOR_NV, GL_UNSIGNED_IDENTITY_NV, GL_RGB));
3813 checkGLcall("glFinalCombinerInputNV()");
3816 float black[4] = {0.0f, 0.0f, 0.0f, 0.0f};
3818 /* for the case of enabled lighting: */
3819 glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, &black[0]);
3820 checkGLcall("glMaterialfv");
3822 /* for the case of disabled lighting: */
3823 if (GL_SUPPORT(EXT_SECONDARY_COLOR)) {
3824 glDisable(GL_COLOR_SUM_EXT);
3826 TRACE("Specular colors cannot be disabled in this version of opengl\n");
3828 checkGLcall("glDisable(GL_COLOR_SUM)");
3830 if (GL_SUPPORT(NV_REGISTER_COMBINERS)) {
3831 GL_EXTCALL(glFinalCombinerInputNV(GL_VARIABLE_B_NV, GL_SPARE0_NV, GL_UNSIGNED_IDENTITY_NV, GL_RGB));
3832 checkGLcall("glFinalCombinerInputNV()");
3838 case WINED3DRS_STENCILENABLE :
3839 case WINED3DRS_TWOSIDEDSTENCILMODE :
3840 case WINED3DRS_STENCILFUNC :
3841 case WINED3DRS_CCW_STENCILFUNC :
3842 case WINED3DRS_STENCILREF :
3843 case WINED3DRS_STENCILMASK :
3844 case WINED3DRS_STENCILFAIL :
3845 case WINED3DRS_STENCILZFAIL :
3846 case WINED3DRS_STENCILPASS :
3847 case WINED3DRS_CCW_STENCILFAIL :
3848 case WINED3DRS_CCW_STENCILZFAIL :
3849 case WINED3DRS_CCW_STENCILPASS :
3850 renderstate_stencil(This, State, Value);
3852 case WINED3DRS_STENCILWRITEMASK :
3854 glStencilMask(Value);
3855 TRACE("glStencilMask(%u)\n", Value);
3856 checkGLcall("glStencilMask");
3860 case WINED3DRS_FOGENABLE :
3864 checkGLcall("glEnable GL_FOG");
3867 checkGLcall("glDisable GL_FOG");
3872 case WINED3DRS_RANGEFOGENABLE :
3875 TRACE("Enabled RANGEFOG\n");
3877 TRACE("Disabled RANGEFOG\n");
3882 case WINED3DRS_FOGCOLOR :
3885 D3DCOLORTOGLFLOAT4(Value, col);
3886 /* Set the default alpha blend color */
3887 glFogfv(GL_FOG_COLOR, &col[0]);
3888 checkGLcall("glFog GL_FOG_COLOR");
3892 case WINED3DRS_FOGTABLEMODE :
3893 case WINED3DRS_FOGVERTEXMODE :
3895 /* DX 7 sdk: "If both render states(vertex and table fog) are set to valid modes, the system will apply only pixel(=table) fog effects." */
3896 if(This->stateBlock->renderState[WINED3DRS_FOGTABLEMODE] == D3DFOG_NONE) {
3897 glHint(GL_FOG_HINT, GL_FASTEST);
3898 checkGLcall("glHint(GL_FOG_HINT, GL_FASTEST)");
3899 switch (This->stateBlock->renderState[WINED3DRS_FOGVERTEXMODE]) {
3900 /* Processed vertices have their fog factor stored in the specular value. Fall too the none case.
3901 * If we are drawing untransformed vertices atm, d3ddevice_set_ortho will update the fog
3904 if(!This->last_was_rhw) {
3905 glFogi(GL_FOG_MODE, GL_EXP);
3906 checkGLcall("glFogi(GL_FOG_MODE, GL_EXP");
3907 if(GL_SUPPORT(EXT_FOG_COORD)) {
3908 glFogi(GL_FOG_COORDINATE_SOURCE_EXT, GL_FRAGMENT_DEPTH_EXT);
3909 checkGLcall("glFogi(GL_FOG_COORDINATE_SOURCE_EXT, GL_FRAGMENT_DEPTH_EXT");
3910 IWineD3DDevice_SetRenderState(iface, WINED3DRS_FOGSTART, This->stateBlock->renderState[WINED3DRS_FOGSTART]);
3911 IWineD3DDevice_SetRenderState(iface, WINED3DRS_FOGEND, This->stateBlock->renderState[WINED3DRS_FOGEND]);
3917 if(!This->last_was_rhw) {
3918 glFogi(GL_FOG_MODE, GL_EXP2);
3919 checkGLcall("glFogi(GL_FOG_MODE, GL_EXP2");
3920 if(GL_SUPPORT(EXT_FOG_COORD)) {
3921 glFogi(GL_FOG_COORDINATE_SOURCE_EXT, GL_FRAGMENT_DEPTH_EXT);
3922 checkGLcall("glFogi(GL_FOG_COORDINATE_SOURCE_EXT, GL_FRAGMENT_DEPTH_EXT");
3923 IWineD3DDevice_SetRenderState(iface, WINED3DRS_FOGSTART, This->stateBlock->renderState[WINED3DRS_FOGSTART]);
3924 IWineD3DDevice_SetRenderState(iface, WINED3DRS_FOGEND, This->stateBlock->renderState[WINED3DRS_FOGEND]);
3929 case D3DFOG_LINEAR: {
3930 if(!This->last_was_rhw) {
3931 glFogi(GL_FOG_MODE, GL_LINEAR);
3932 checkGLcall("glFogi(GL_FOG_MODE, GL_LINEAR");
3933 if(GL_SUPPORT(EXT_FOG_COORD)) {
3934 glFogi(GL_FOG_COORDINATE_SOURCE_EXT, GL_FRAGMENT_DEPTH_EXT);
3935 checkGLcall("glFogi(GL_FOG_COORDINATE_SOURCE_EXT, GL_FRAGMENT_DEPTH_EXT");
3936 IWineD3DDevice_SetRenderState(iface, WINED3DRS_FOGSTART, This->stateBlock->renderState[WINED3DRS_FOGSTART]);
3937 IWineD3DDevice_SetRenderState(iface, WINED3DRS_FOGEND, This->stateBlock->renderState[WINED3DRS_FOGEND]);
3943 /* Both are none? According to msdn the alpha channel of the specular
3944 * color contains a fog factor. Set it in drawStridedSlow.
3945 * Same happens with Vertexfog on transformed vertices
3947 if(GL_SUPPORT(EXT_FOG_COORD)) {
3948 glFogi(GL_FOG_COORDINATE_SOURCE_EXT, GL_FOG_COORDINATE_EXT);
3949 checkGLcall("glFogi(GL_FOG_COORDINATE_SOURCE_EXT, GL_FOG_COORDINATE_EXT)\n");
3950 glFogi(GL_FOG_MODE, GL_LINEAR);
3951 checkGLcall("glFogi(GL_FOG_MODE, GL_LINEAR)");
3952 glFogf(GL_FOG_START, (float) 0xff);
3953 checkGLcall("glFogfv GL_FOG_START");
3954 glFogf(GL_FOG_END, 0.0);
3955 checkGLcall("glFogfv GL_FOG_END");
3957 /* Disable GL fog, handle this in software in drawStridedSlow */
3959 checkGLcall("glDisable(GL_FOG)");
3963 default: FIXME("Unexpected WINED3DRS_FOGVERTEXMODE %d\n", This->stateBlock->renderState[WINED3DRS_FOGVERTEXMODE]);
3966 glHint(GL_FOG_HINT, GL_NICEST);
3967 checkGLcall("glHint(GL_FOG_HINT, GL_NICEST)");
3968 switch (This->stateBlock->renderState[WINED3DRS_FOGTABLEMODE]) {
3969 case D3DFOG_EXP: glFogi(GL_FOG_MODE, GL_EXP);
3970 checkGLcall("glFogi(GL_FOG_MODE, GL_EXP");
3971 if(GL_SUPPORT(EXT_FOG_COORD)) {
3972 glFogi(GL_FOG_COORDINATE_SOURCE_EXT, GL_FRAGMENT_DEPTH_EXT);
3973 checkGLcall("glFogi(GL_FOG_COORDINATE_SOURCE_EXT, GL_FRAGMENT_DEPTH_EXT");
3974 IWineD3DDevice_SetRenderState(iface, WINED3DRS_FOGSTART, This->stateBlock->renderState[WINED3DRS_FOGSTART]);
3975 IWineD3DDevice_SetRenderState(iface, WINED3DRS_FOGEND, This->stateBlock->renderState[WINED3DRS_FOGEND]);
3978 case D3DFOG_EXP2: glFogi(GL_FOG_MODE, GL_EXP2);
3979 checkGLcall("glFogi(GL_FOG_MODE, GL_EXP2");
3980 if(GL_SUPPORT(EXT_FOG_COORD)) {
3981 glFogi(GL_FOG_COORDINATE_SOURCE_EXT, GL_FRAGMENT_DEPTH_EXT);
3982 checkGLcall("glFogi(GL_FOG_COORDINATE_SOURCE_EXT, GL_FRAGMENT_DEPTH_EXT");
3983 IWineD3DDevice_SetRenderState(iface, WINED3DRS_FOGSTART, This->stateBlock->renderState[WINED3DRS_FOGSTART]);
3984 IWineD3DDevice_SetRenderState(iface, WINED3DRS_FOGEND, This->stateBlock->renderState[WINED3DRS_FOGEND]);
3987 case D3DFOG_LINEAR: glFogi(GL_FOG_MODE, GL_LINEAR);
3988 checkGLcall("glFogi(GL_FOG_MODE, GL_LINEAR");
3989 if(GL_SUPPORT(EXT_FOG_COORD)) {
3990 glFogi(GL_FOG_COORDINATE_SOURCE_EXT, GL_FRAGMENT_DEPTH_EXT);
3991 checkGLcall("glFogi(GL_FOG_COORDINATE_SOURCE_EXT, GL_FRAGMENT_DEPTH_EXT");
3992 IWineD3DDevice_SetRenderState(iface, WINED3DRS_FOGSTART, This->stateBlock->renderState[WINED3DRS_FOGSTART]);
3993 IWineD3DDevice_SetRenderState(iface, WINED3DRS_FOGEND, This->stateBlock->renderState[WINED3DRS_FOGEND]);
3996 case D3DFOG_NONE: /* Won't happen */
3997 default: FIXME("Unexpected WINED3DRS_FOGTABLEMODE %d\n", This->stateBlock->renderState[WINED3DRS_FOGTABLEMODE]);
4000 if (GL_SUPPORT(NV_FOG_DISTANCE)) {
4001 glFogi(GL_FOG_DISTANCE_MODE_NV, GL_EYE_PLANE_ABSOLUTE_NV);
4006 case WINED3DRS_FOGSTART :
4009 glFogfv(GL_FOG_START, &tmpvalue.f);
4010 checkGLcall("glFogf(GL_FOG_START, (float) Value)");
4011 TRACE("Fog Start == %f\n", tmpvalue.f);
4015 case WINED3DRS_FOGEND :
4018 glFogfv(GL_FOG_END, &tmpvalue.f);
4019 checkGLcall("glFogf(GL_FOG_END, (float) Value)");
4020 TRACE("Fog End == %f\n", tmpvalue.f);
4024 case WINED3DRS_FOGDENSITY :
4027 glFogfv(GL_FOG_DENSITY, &tmpvalue.f);
4028 checkGLcall("glFogf(GL_FOG_DENSITY, (float) Value)");
4032 case WINED3DRS_VERTEXBLEND :
4034 This->updateStateBlock->vertex_blend = (D3DVERTEXBLENDFLAGS) Value;
4035 TRACE("Vertex Blending state to %d\n", Value);
4039 case WINED3DRS_TWEENFACTOR :
4042 This->updateStateBlock->tween_factor = tmpvalue.f;
4043 TRACE("Vertex Blending Tween Factor to %f\n", This->updateStateBlock->tween_factor);
4047 case WINED3DRS_INDEXEDVERTEXBLENDENABLE :
4049 TRACE("Indexed Vertex Blend Enable to %u\n", (BOOL) Value);
4053 case WINED3DRS_COLORVERTEX :
4054 case WINED3DRS_DIFFUSEMATERIALSOURCE :
4055 case WINED3DRS_SPECULARMATERIALSOURCE :
4056 case WINED3DRS_AMBIENTMATERIALSOURCE :
4057 case WINED3DRS_EMISSIVEMATERIALSOURCE :
4059 GLenum Parm = GL_AMBIENT_AND_DIFFUSE;
4061 if (This->stateBlock->renderState[WINED3DRS_COLORVERTEX]) {
4062 TRACE("diff %d, amb %d, emis %d, spec %d\n",
4063 This->stateBlock->renderState[WINED3DRS_DIFFUSEMATERIALSOURCE],
4064 This->stateBlock->renderState[WINED3DRS_AMBIENTMATERIALSOURCE],
4065 This->stateBlock->renderState[WINED3DRS_EMISSIVEMATERIALSOURCE],
4066 This->stateBlock->renderState[WINED3DRS_SPECULARMATERIALSOURCE]);
4068 if (This->stateBlock->renderState[WINED3DRS_DIFFUSEMATERIALSOURCE] == D3DMCS_COLOR1) {
4069 if (This->stateBlock->renderState[WINED3DRS_AMBIENTMATERIALSOURCE] == D3DMCS_COLOR1) {
4070 Parm = GL_AMBIENT_AND_DIFFUSE;
4074 } else if (This->stateBlock->renderState[WINED3DRS_AMBIENTMATERIALSOURCE] == D3DMCS_COLOR1) {
4076 } else if (This->stateBlock->renderState[WINED3DRS_EMISSIVEMATERIALSOURCE] == D3DMCS_COLOR1) {
4078 } else if (This->stateBlock->renderState[WINED3DRS_SPECULARMATERIALSOURCE] == D3DMCS_COLOR1) {
4085 if (This->tracking_color != DISABLED_TRACKING) This->tracking_color = NEEDS_DISABLE;
4087 This->tracking_color = NEEDS_TRACKING;
4088 This->tracking_parm = Parm;
4092 if (This->tracking_color != DISABLED_TRACKING) This->tracking_color = NEEDS_DISABLE;
4097 case WINED3DRS_LINEPATTERN :
4103 tmppattern.d = Value;
4105 TRACE("Line pattern: repeat %d bits %x\n", tmppattern.lp.wRepeatFactor, tmppattern.lp.wLinePattern);
4107 if (tmppattern.lp.wRepeatFactor) {
4108 glLineStipple(tmppattern.lp.wRepeatFactor, tmppattern.lp.wLinePattern);
4109 checkGLcall("glLineStipple(repeat, linepattern)");
4110 glEnable(GL_LINE_STIPPLE);
4111 checkGLcall("glEnable(GL_LINE_STIPPLE);");
4113 glDisable(GL_LINE_STIPPLE);
4114 checkGLcall("glDisable(GL_LINE_STIPPLE);");
4119 case WINED3DRS_ZBIAS : /* D3D8 only */
4123 TRACE("ZBias value %f\n", tmpvalue.f);
4124 glPolygonOffset(0, -tmpvalue.f);
4125 checkGLcall("glPolygonOffset(0, -Value)");
4126 glEnable(GL_POLYGON_OFFSET_FILL);
4127 checkGLcall("glEnable(GL_POLYGON_OFFSET_FILL);");
4128 glEnable(GL_POLYGON_OFFSET_LINE);
4129 checkGLcall("glEnable(GL_POLYGON_OFFSET_LINE);");
4130 glEnable(GL_POLYGON_OFFSET_POINT);
4131 checkGLcall("glEnable(GL_POLYGON_OFFSET_POINT);");
4133 glDisable(GL_POLYGON_OFFSET_FILL);
4134 checkGLcall("glDisable(GL_POLYGON_OFFSET_FILL);");
4135 glDisable(GL_POLYGON_OFFSET_LINE);
4136 checkGLcall("glDisable(GL_POLYGON_OFFSET_LINE);");
4137 glDisable(GL_POLYGON_OFFSET_POINT);
4138 checkGLcall("glDisable(GL_POLYGON_OFFSET_POINT);");
4143 case WINED3DRS_NORMALIZENORMALS :
4145 glEnable(GL_NORMALIZE);
4146 checkGLcall("glEnable(GL_NORMALIZE);");
4148 glDisable(GL_NORMALIZE);
4149 checkGLcall("glDisable(GL_NORMALIZE);");
4153 case WINED3DRS_POINTSIZE :
4154 /* FIXME: check that pointSize isn't outside glGetFloatv( GL_POINT_SIZE_MAX_ARB, &maxSize ); or -ve */
4156 TRACE("Set point size to %f\n", tmpvalue.f);
4157 glPointSize(tmpvalue.f);
4158 checkGLcall("glPointSize(...);");
4161 case WINED3DRS_POINTSIZE_MIN :
4162 if (GL_SUPPORT(EXT_POINT_PARAMETERS)) {
4164 GL_EXTCALL(glPointParameterfEXT)(GL_POINT_SIZE_MIN_EXT, tmpvalue.f);
4165 checkGLcall("glPointParameterfEXT(...);");
4167 FIXME("WINED3DRS_POINTSIZE_MIN not supported on this opengl\n");
4171 case WINED3DRS_POINTSIZE_MAX :
4172 if (GL_SUPPORT(EXT_POINT_PARAMETERS)) {
4174 GL_EXTCALL(glPointParameterfEXT)(GL_POINT_SIZE_MAX_EXT, tmpvalue.f);
4175 checkGLcall("glPointParameterfEXT(...);");
4177 FIXME("WINED3DRS_POINTSIZE_MAX not supported on this opengl\n");
4181 case WINED3DRS_POINTSCALE_A :
4182 case WINED3DRS_POINTSCALE_B :
4183 case WINED3DRS_POINTSCALE_C :
4184 case WINED3DRS_POINTSCALEENABLE :
4187 * POINTSCALEENABLE controls how point size value is treated. If set to
4188 * true, the point size is scaled with respect to height of viewport.
4189 * When set to false point size is in pixels.
4191 * http://msdn.microsoft.com/library/en-us/directx9_c/point_sprites.asp
4194 /* Default values */
4195 GLfloat att[3] = {1.0f, 0.0f, 0.0f};
4198 * Minimum valid point size for OpenGL is 1.0f. For Direct3D it is 0.0f.
4199 * This means that OpenGL will clamp really small point sizes to 1.0f.
4200 * To correct for this we need to multiply by the scale factor when sizes
4201 * are less than 1.0f. scale_factor = 1.0f / point_size.
4203 GLfloat pointSize = *((float*)&This->stateBlock->renderState[WINED3DRS_POINTSIZE]);
4204 if(pointSize > 0.0f) {
4205 GLfloat scaleFactor;
4207 if(pointSize < 1.0f) {
4208 scaleFactor = pointSize * pointSize;
4213 if(This->stateBlock->renderState[WINED3DRS_POINTSCALEENABLE]) {
4214 att[0] = *((float*)&This->stateBlock->renderState[WINED3DRS_POINTSCALE_A]) /
4215 (This->stateBlock->viewport.Height * This->stateBlock->viewport.Height * scaleFactor);
4216 att[1] = *((float*)&This->stateBlock->renderState[WINED3DRS_POINTSCALE_B]) /
4217 (This->stateBlock->viewport.Height * This->stateBlock->viewport.Height * scaleFactor);
4218 att[2] = *((float*)&This->stateBlock->renderState[WINED3DRS_POINTSCALE_C]) /
4219 (This->stateBlock->viewport.Height * This->stateBlock->viewport.Height * scaleFactor);
4223 if(GL_SUPPORT(ARB_POINT_PARAMETERS)) {
4224 GL_EXTCALL(glPointParameterfvARB)(GL_POINT_DISTANCE_ATTENUATION_ARB, att);
4225 checkGLcall("glPointParameterfvARB(GL_DISTANCE_ATTENUATION_ARB, ...");
4227 else if(GL_SUPPORT(EXT_POINT_PARAMETERS)) {
4228 GL_EXTCALL(glPointParameterfvEXT)(GL_DISTANCE_ATTENUATION_EXT, att);
4229 checkGLcall("glPointParameterfvEXT(GL_DISTANCE_ATTENUATION_EXT, ...");
4231 TRACE("POINT_PARAMETERS not supported in this version of opengl\n");
4235 case WINED3DRS_COLORWRITEENABLE :
4237 TRACE("Color mask: r(%d) g(%d) b(%d) a(%d)\n",
4238 Value & D3DCOLORWRITEENABLE_RED ? 1 : 0,
4239 Value & D3DCOLORWRITEENABLE_GREEN ? 1 : 0,
4240 Value & D3DCOLORWRITEENABLE_BLUE ? 1 : 0,
4241 Value & D3DCOLORWRITEENABLE_ALPHA ? 1 : 0);
4242 glColorMask(Value & D3DCOLORWRITEENABLE_RED ? GL_TRUE : GL_FALSE,
4243 Value & D3DCOLORWRITEENABLE_GREEN ? GL_TRUE : GL_FALSE,
4244 Value & D3DCOLORWRITEENABLE_BLUE ? GL_TRUE : GL_FALSE,
4245 Value & D3DCOLORWRITEENABLE_ALPHA ? GL_TRUE : GL_FALSE);
4246 checkGLcall("glColorMask(...)");
4250 case WINED3DRS_LOCALVIEWER :
4252 GLint state = (Value) ? 1 : 0;
4253 TRACE("Local Viewer Enable to %ul\n", (BOOL) Value);
4254 glLightModeli(GL_LIGHT_MODEL_LOCAL_VIEWER, state);
4258 case WINED3DRS_LASTPIXEL :
4261 TRACE("Last Pixel Drawing Enabled\n");
4263 FIXME("Last Pixel Drawing Disabled, not handled yet\n");
4268 case WINED3DRS_SOFTWAREVERTEXPROCESSING :
4271 TRACE("Software Processing Enabled\n");
4273 TRACE("Software Processing Disabled\n");
4278 /** not supported */
4279 case WINED3DRS_ZVISIBLE :
4282 return WINED3DERR_INVALIDCALL;
4284 case WINED3DRS_POINTSPRITEENABLE :
4286 /* TODO: NV_POINT_SPRITE */
4287 if (!GL_SUPPORT(ARB_POINT_SPRITE)) {
4288 TRACE("Point sprites not supported\n");
4293 * Point sprites are always enabled. Value controls texture coordinate
4294 * replacement mode. Must be set true for point sprites to use
4297 glEnable(GL_POINT_SPRITE_ARB);
4298 checkGLcall("glEnable(GL_POINT_SPRITE_ARB)");
4301 glTexEnvf(GL_POINT_SPRITE_ARB, GL_COORD_REPLACE_ARB, TRUE);
4302 checkGLcall("glTexEnvf(GL_POINT_SPRITE, GL_COORD_REPLACE, TRUE)");
4304 glTexEnvf(GL_POINT_SPRITE_ARB, GL_COORD_REPLACE_ARB, FALSE);
4305 checkGLcall("glTexEnvf(GL_POINT_SPRITE, GL_COORD_REPLACE, FALSE)");
4309 case WINED3DRS_EDGEANTIALIAS :
4312 glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
4314 checkGLcall("glEnable(GL_BLEND)");
4315 glEnable(GL_LINE_SMOOTH);
4316 checkGLcall("glEnable(GL_LINE_SMOOTH)");
4318 if(!This->stateBlock->renderState[WINED3DRS_ALPHABLENDENABLE]) {
4319 glDisable(GL_BLEND);
4320 checkGLcall("glDisable(GL_BLEND)");
4322 glDisable(GL_LINE_SMOOTH);
4323 checkGLcall("glDisable(GL_LINE_SMOOTH)");
4327 case WINED3DRS_WRAP0 :
4328 case WINED3DRS_WRAP1 :
4329 case WINED3DRS_WRAP2 :
4330 case WINED3DRS_WRAP3 :
4331 case WINED3DRS_WRAP4 :
4332 case WINED3DRS_WRAP5 :
4333 case WINED3DRS_WRAP6 :
4334 case WINED3DRS_WRAP7 :
4335 case WINED3DRS_WRAP8 :
4336 case WINED3DRS_WRAP9 :
4337 case WINED3DRS_WRAP10 :
4338 case WINED3DRS_WRAP11 :
4339 case WINED3DRS_WRAP12 :
4340 case WINED3DRS_WRAP13 :
4341 case WINED3DRS_WRAP14 :
4342 case WINED3DRS_WRAP15 :
4344 http://www.cosc.brocku.ca/Offerings/3P98/course/lectures/texture/
4345 http://msdn.microsoft.com/archive/default.asp?url=/archive/en-us/directx9_c/directx/graphics/programmingguide/FixedFunction/Textures/texturewrapping.asp
4346 http://www.gamedev.net/reference/programming/features/rendererdll3/page2.asp
4347 Descussion that ways to turn on WRAPing to solve an opengl conversion problem.
4348 http://www.flipcode.org/cgi-bin/fcmsg.cgi?thread_show=10248
4350 so far as I can tell, wrapping and texture-coordinate generate go hand in hand,
4354 ERR("(%p)->(%s,%d) Texture wraping not yet supported\n",This, debug_d3drenderstate(State), Value);
4359 case WINED3DRS_MULTISAMPLEANTIALIAS :
4361 if( GL_SUPPORT(ARB_MULTISAMPLE) ) {
4363 glEnable(GL_MULTISAMPLE_ARB);
4364 checkGLcall("glEnable(GL_MULTISAMPLE_ARB)");
4366 glDisable(GL_MULTISAMPLE_ARB);
4367 checkGLcall("glDisable(GL_MULTISAMPLE_ARB)");
4371 ERR("Multisample antialiasing not supported by gl\n");
4377 case WINED3DRS_SCISSORTESTENABLE :
4380 glEnable(GL_SCISSOR_TEST);
4381 checkGLcall("glEnable(GL_SCISSOR_TEST)");
4383 glDisable(GL_SCISSOR_TEST);
4384 checkGLcall("glDisable(GL_SCISSOR_TEST)");
4388 case WINED3DRS_SLOPESCALEDEPTHBIAS :
4392 glEnable(GL_POLYGON_OFFSET_FILL);
4393 checkGLcall("glEnable(GL_POLYGON_OFFSET_FILL)");
4394 glPolygonOffset(tmpvalue.f, *((float*)&This->stateBlock->renderState[WINED3DRS_DEPTHBIAS]));
4395 checkGLcall("glPolygonOffset(...)");
4397 glDisable(GL_POLYGON_OFFSET_FILL);
4398 checkGLcall("glDisable(GL_POLYGON_OFFSET_FILL)");
4402 case WINED3DRS_ANTIALIASEDLINEENABLE :
4405 glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
4407 checkGLcall("glEnable(GL_BLEND)");
4408 glEnable(GL_LINE_SMOOTH);
4409 checkGLcall("glEnable(GL_LINE_SMOOTH)");
4411 glDisable(GL_BLEND);
4412 checkGLcall("glDisable(GL_BLEND)");
4413 glDisable(GL_LINE_SMOOTH);
4414 checkGLcall("glDisable(GL_LINE_SMOOTH)");
4418 case WINED3DRS_DEPTHBIAS :
4422 glEnable(GL_POLYGON_OFFSET_FILL);
4423 checkGLcall("glEnable(GL_POLYGON_OFFSET_FILL)");
4424 glPolygonOffset(*((float*)&This->stateBlock->renderState[WINED3DRS_SLOPESCALEDEPTHBIAS]), tmpvalue.f);
4425 checkGLcall("glPolygonOffset(...)");
4427 glDisable(GL_POLYGON_OFFSET_FILL);
4428 checkGLcall("glDisable(GL_POLYGON_OFFSET_FILL)");
4433 case WINED3DRS_TEXTUREPERSPECTIVE :
4436 glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST);
4438 glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_FASTEST);
4442 case WINED3DRS_STIPPLEDALPHA :
4445 ERR(" Stippled Alpha not supported yet.\n");
4448 case WINED3DRS_ANTIALIAS :
4451 ERR(" Antialias not supported yet.\n");
4455 case WINED3DRS_MULTISAMPLEMASK :
4457 if(0xFFFFFFFF != Value)
4458 ERR("(%p)->(%s,%d) not yet implemented\n", This, debug_d3drenderstate(State), Value);
4462 case WINED3DRS_PATCHEDGESTYLE :
4464 if(D3DPATCHEDGE_DISCRETE != Value)
4465 ERR("(%p)->(%s,%d) not yet implemented\n", This, debug_d3drenderstate(State), Value);
4469 case WINED3DRS_PATCHSEGMENTS :
4471 /* available in d3d8 but in d3d9 it was replaced by IDirect3DDevice9::SetNPatchMode */
4473 if(tmpvalue.d != Value)
4474 ERR("(%p)->(%s,%d) not yet implemented\n", This, debug_d3drenderstate(State), Value);
4478 case WINED3DRS_DEBUGMONITORTOKEN :
4480 /* Only useful for "debug builds". */
4481 if(0xbaadcafe != Value) {
4482 /* MSDN says the default is D3DDMT_ENABLE but our tests confirm 0xbaadcafe is the default. */
4483 /* MSDN says anything other than D3DDMT_ENABLE or DISABLE does not change the state,
4484 * but our tests disagree.
4485 * We do not claim to implement a debugging lib, so do not write an ERR
4487 WARN("(%p)->(%s,%d) not yet implemented\n", This, debug_d3drenderstate(State), Value);
4492 case WINED3DRS_POSITIONDEGREE :
4494 if(D3DDEGREE_CUBIC != Value)
4495 ERR("(%p)->(%s,%d) not yet implemented\n", This, debug_d3drenderstate(State), Value);
4499 case WINED3DRS_NORMALDEGREE :
4501 if(D3DDEGREE_LINEAR != Value)
4502 ERR("(%p)->(%s,%d) not yet implemented\n", This, debug_d3drenderstate(State), Value);
4506 case WINED3DRS_MINTESSELLATIONLEVEL :
4507 case WINED3DRS_MAXTESSELLATIONLEVEL :
4508 case WINED3DRS_ADAPTIVETESS_X :
4509 case WINED3DRS_ADAPTIVETESS_Y :
4510 case WINED3DRS_ADAPTIVETESS_Z :
4511 case WINED3DRS_ADAPTIVETESS_W :
4513 if(This->stateBlock->renderState[WINED3DRS_ENABLEADAPTIVETESSELLATION])
4514 FIXME("(%p)->(%s,%d) not yet implemented\n", This, debug_d3drenderstate(State), Value);
4516 TRACE("(%p)->(%s,%d): recording state but WINED3DRS_ENABLEADAPTIVETESSELLATION is not enabled\n", This, debug_d3drenderstate(State), Value);
4520 case WINED3DRS_ENABLEADAPTIVETESSELLATION:
4523 ERR("(%p)->(%s,%d) not yet implemented\n", This, debug_d3drenderstate(State), Value);
4527 case WINED3DRS_COLORWRITEENABLE1 :
4528 case WINED3DRS_COLORWRITEENABLE2 :
4529 case WINED3DRS_COLORWRITEENABLE3 :
4531 /* depends on WINED3DRS_COLORWRITEENABLE. */
4532 if(0x0000000F != Value)
4533 ERR("(%p)->(%s,%d) not yet implemented. Missing of cap D3DPMISCCAPS_INDEPENDENTWRITEMASKS wasn't honored?\n", This, debug_d3drenderstate(State), Value);
4537 case WINED3DRS_BLENDFACTOR :
4541 TRACE("Setting BlendFactor to %d\n", Value);
4543 D3DCOLORTOGLFLOAT4(Value, col);
4544 if (0xFFFFFFFF != Value) {
4546 checkGLcall("glEnable(GL_BLEND)");
4549 glDisable(GL_BLEND);
4550 checkGLcall("glDisable(GL_BLEND)");
4552 glBlendColor (col[0],col[1],col[2],col[3]);
4556 case WINED3DRS_SRGBWRITEENABLE :
4559 ERR("(%p)->(%s,%d) not yet implemented\n", This, debug_d3drenderstate(State), Value);
4563 case WINED3DRS_SEPARATEALPHABLENDENABLE :
4566 ERR("(%p)->(%s,%d) not yet implemented. Missing of cap D3DPMISCCAPS_SEPARATEALPHABLEND wasn't honored?\n", This, debug_d3drenderstate(State), Value);
4570 case WINED3DRS_SRCBLENDALPHA :
4571 case WINED3DRS_DESTBLENDALPHA :
4572 case WINED3DRS_BLENDOPALPHA :
4574 if(This->stateBlock->renderState[WINED3DRS_SEPARATEALPHABLENDENABLE])
4575 FIXME("(%p)->(%s,%d) not yet implemented\n", This, debug_d3drenderstate(State), Value);
4577 TRACE("(%p)->(%s,%d): recording state but WINED3DRS_SEPARATEALPHABLENDENABLE is not enabled\n", This, debug_d3drenderstate(State), Value);
4582 FIXME("(%p)->(%s,%d) unknown state\n", This, debug_d3drenderstate(State), Value);
4590 static HRESULT WINAPI IWineD3DDeviceImpl_GetRenderState(IWineD3DDevice *iface, D3DRENDERSTATETYPE State, DWORD *pValue) {
4591 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4592 TRACE("(%p) for State %d = %d\n", This, State, This->stateBlock->renderState[State]);
4593 *pValue = This->stateBlock->renderState[State];
4598 * Get / Set Sampler States
4599 * TODO: Verify against dx9 definitions
4602 static HRESULT WINAPI IWineD3DDeviceImpl_SetSamplerState(IWineD3DDevice *iface, DWORD Sampler, WINED3DSAMPLERSTATETYPE Type, DWORD Value) {
4603 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4605 * SetSampler is designed to allow for more than the standard up to 8 textures
4606 * and Geforce has stopped supporting more than 6 standard textures in openGL.
4607 * So I have to use ARB for Gforce. (maybe if the sampler > 4 then use ARB?)
4609 * http://developer.nvidia.com/object/General_FAQ.html#t6
4611 * There are two new settings for GForce
4613 * GL_MAX_TEXTURE_IMAGE_UNITS_ARB
4614 * and the texture one:
4615 * GL_MAX_TEXTURE_COORDS_ARB.
4616 * Ok GForce say it's ok to use glTexParameter/glGetTexParameter(...).
4618 /** NOTE: States are appled in IWineD3DBaseTextre ApplyStateChanges and IWineD3DDevice SetupTextureStates**/
4619 if(Sampler > GL_LIMITS(sampler_stages) || Sampler < 0 || Type > WINED3D_HIGHEST_SAMPLER_STATE || Type < 0) {
4620 FIXME("sampler %d type %s(%u) is out of range [max_samplers=%d, highest_state=%d]\n",
4621 Sampler, debug_d3dsamplerstate(Type), Type, GL_LIMITS(sampler_stages), WINED3D_HIGHEST_SAMPLER_STATE);
4622 return WINED3DERR_INVALIDCALL;
4625 TRACE("(%p) : Sampler=%d, Type=%s(%d), Value=%d\n", This, Sampler,
4626 debug_d3dsamplerstate(Type), Type, Value);
4627 This->updateStateBlock->samplerState[Sampler][Type] = Value;
4628 This->updateStateBlock->set.samplerState[Sampler][Type] = Value;
4629 This->updateStateBlock->changed.samplerState[Sampler][Type] = Value;
4631 /* Handle recording of state blocks */
4632 if (This->isRecordingState) {
4633 TRACE("Recording... not performing anything\n");
4640 static HRESULT WINAPI IWineD3DDeviceImpl_GetSamplerState(IWineD3DDevice *iface, DWORD Sampler, WINED3DSAMPLERSTATETYPE Type, DWORD* Value) {
4641 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4642 /** TODO: check that sampler is in range **/
4643 *Value = This->updateStateBlock->samplerState[Sampler][Type];
4644 TRACE("(%p) : Sampler %d Type %u Returning %d\n", This, Sampler, Type, *Value);
4649 static HRESULT WINAPI IWineD3DDeviceImpl_SetScissorRect(IWineD3DDevice *iface, CONST RECT* pRect) {
4650 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4653 /** FIXME: Windows uses a top,left origin openGL uses a bottom Right? **/
4654 TRACE("(%p)Setting new Scissor Rect to %d:%d-%d:%d\n", This, pRect->left, pRect->top, pRect->right, pRect->bottom);
4655 glScissor(pRect->left, pRect->top, pRect->right - pRect->left, pRect->bottom - pRect->top);
4661 static HRESULT WINAPI IWineD3DDeviceImpl_GetScissorRect(IWineD3DDevice *iface, RECT* pRect) {
4662 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4663 GLint scissorBox[4];
4666 /** FIXME: Windows uses a top,left origin openGL uses a bottom Right? **/
4667 glGetIntegerv(GL_SCISSOR_BOX, scissorBox);
4668 pRect->left = scissorBox[0];
4669 pRect->top = scissorBox[1];
4670 pRect->right = scissorBox[0] + scissorBox[2];
4671 pRect->bottom = scissorBox[1] + scissorBox[3];
4672 TRACE("(%p)Returning a Scissor Rect of %d:%d-%d:%d\n", This, pRect->left, pRect->top, pRect->right, pRect->bottom);
4677 static HRESULT WINAPI IWineD3DDeviceImpl_SetVertexDeclaration(IWineD3DDevice* iface, IWineD3DVertexDeclaration* pDecl) {
4678 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *) iface;
4679 IWineD3DVertexDeclaration *oldDecl = This->updateStateBlock->vertexDecl;
4681 TRACE("(%p) : pDecl=%p\n", This, pDecl);
4683 This->updateStateBlock->vertexDecl = pDecl;
4684 This->updateStateBlock->changed.vertexDecl = TRUE;
4685 This->updateStateBlock->set.vertexDecl = TRUE;
4687 if (This->isRecordingState) {
4688 TRACE("Recording... not performing anything\n");
4691 if (NULL != pDecl) {
4692 IWineD3DVertexDeclaration_AddRef(pDecl);
4694 if (NULL != oldDecl) {
4695 IWineD3DVertexDeclaration_Release(oldDecl);
4700 static HRESULT WINAPI IWineD3DDeviceImpl_GetVertexDeclaration(IWineD3DDevice* iface, IWineD3DVertexDeclaration** ppDecl) {
4701 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4703 TRACE("(%p) : ppDecl=%p\n", This, ppDecl);
4705 *ppDecl = This->stateBlock->vertexDecl;
4706 if (NULL != *ppDecl) IWineD3DVertexDeclaration_AddRef(*ppDecl);
4710 static HRESULT WINAPI IWineD3DDeviceImpl_SetVertexShader(IWineD3DDevice *iface, IWineD3DVertexShader* pShader) {
4711 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4712 IWineD3DVertexShader* oldShader = This->updateStateBlock->vertexShader;
4714 This->updateStateBlock->vertexShader = pShader;
4715 This->updateStateBlock->changed.vertexShader = TRUE;
4716 This->updateStateBlock->set.vertexShader = TRUE;
4718 if (This->isRecordingState) {
4719 TRACE("Recording... not performing anything\n");
4722 if (NULL != pShader) {
4723 IWineD3DVertexShader_AddRef(pShader);
4725 if (NULL != oldShader) {
4726 IWineD3DVertexShader_Release(oldShader);
4729 TRACE("(%p) : setting pShader(%p)\n", This, pShader);
4731 * TODO: merge HAL shaders context switching from prototype
4736 static HRESULT WINAPI IWineD3DDeviceImpl_GetVertexShader(IWineD3DDevice *iface, IWineD3DVertexShader** ppShader) {
4737 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4739 if (NULL == ppShader) {
4740 return WINED3DERR_INVALIDCALL;
4742 *ppShader = This->stateBlock->vertexShader;
4743 if( NULL != *ppShader)
4744 IWineD3DVertexShader_AddRef(*ppShader);
4746 TRACE("(%p) : returning %p\n", This, *ppShader);
4750 static HRESULT WINAPI IWineD3DDeviceImpl_SetVertexShaderConstantB(
4751 IWineD3DDevice *iface,
4753 CONST BOOL *srcData,
4756 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4757 int i, cnt = min(count, MAX_CONST_B - start);
4759 TRACE("(iface %p, srcData %p, start %d, count %d)\n",
4760 iface, srcData, start, count);
4762 if (srcData == NULL || cnt < 0)
4763 return WINED3DERR_INVALIDCALL;
4765 memcpy(&This->updateStateBlock->vertexShaderConstantB[start], srcData, cnt * sizeof(BOOL));
4766 for (i = 0; i < cnt; i++)
4767 TRACE("Set BOOL constant %u to %s\n", start + i, srcData[i]? "true":"false");
4769 for (i = start; i < cnt + start; ++i) {
4770 This->updateStateBlock->changed.vertexShaderConstantsB[i] = TRUE;
4771 This->updateStateBlock->set.vertexShaderConstantsB[i] = TRUE;
4777 static HRESULT WINAPI IWineD3DDeviceImpl_GetVertexShaderConstantB(
4778 IWineD3DDevice *iface,
4783 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4784 int cnt = min(count, MAX_CONST_B - start);
4786 TRACE("(iface %p, dstData %p, start %d, count %d)\n",
4787 iface, dstData, start, count);
4789 if (dstData == NULL || cnt < 0)
4790 return WINED3DERR_INVALIDCALL;
4792 memcpy(dstData, &This->stateBlock->vertexShaderConstantB[start], cnt * sizeof(BOOL));
4796 static HRESULT WINAPI IWineD3DDeviceImpl_SetVertexShaderConstantI(
4797 IWineD3DDevice *iface,
4802 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4803 int i, cnt = min(count, MAX_CONST_I - start);
4805 TRACE("(iface %p, srcData %p, start %d, count %d)\n",
4806 iface, srcData, start, count);
4808 if (srcData == NULL || cnt < 0)
4809 return WINED3DERR_INVALIDCALL;
4811 memcpy(&This->updateStateBlock->vertexShaderConstantI[start * 4], srcData, cnt * sizeof(int) * 4);
4812 for (i = 0; i < cnt; i++)
4813 TRACE("Set INT constant %u to { %d, %d, %d, %d }\n", start + i,
4814 srcData[i*4], srcData[i*4+1], srcData[i*4+2], srcData[i*4+3]);
4816 for (i = start; i < cnt + start; ++i) {
4817 This->updateStateBlock->changed.vertexShaderConstantsI[i] = TRUE;
4818 This->updateStateBlock->set.vertexShaderConstantsI[i] = TRUE;
4824 static HRESULT WINAPI IWineD3DDeviceImpl_GetVertexShaderConstantI(
4825 IWineD3DDevice *iface,
4830 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4831 int cnt = min(count, MAX_CONST_I - start);
4833 TRACE("(iface %p, dstData %p, start %d, count %d)\n",
4834 iface, dstData, start, count);
4836 if (dstData == NULL || ((signed int) MAX_CONST_I - (signed int) start) <= (signed int) 0)
4837 return WINED3DERR_INVALIDCALL;
4839 memcpy(dstData, &This->stateBlock->vertexShaderConstantI[start * 4], cnt * sizeof(int) * 4);
4843 static HRESULT WINAPI IWineD3DDeviceImpl_SetVertexShaderConstantF(
4844 IWineD3DDevice *iface,
4846 CONST float *srcData,
4849 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4850 int i, cnt = min(count, GL_LIMITS(vshader_constantsF) - start);
4852 TRACE("(iface %p, srcData %p, start %d, count %d)\n",
4853 iface, srcData, start, count);
4855 if (srcData == NULL || ((signed int) GL_LIMITS(vshader_constantsF) - (signed int) start) <= (signed int) 0)
4856 return WINED3DERR_INVALIDCALL;
4858 memcpy(&This->updateStateBlock->vertexShaderConstantF[start * 4], srcData, cnt * sizeof(float) * 4);
4859 for (i = 0; i < cnt; i++)
4860 TRACE("Set FLOAT constant %u to { %f, %f, %f, %f }\n", start + i,
4861 srcData[i*4], srcData[i*4+1], srcData[i*4+2], srcData[i*4+3]);
4863 for (i = start; i < cnt + start; ++i) {
4864 if (!This->updateStateBlock->set.vertexShaderConstantsF[i]) {
4865 constant_entry *ptr = HeapAlloc(GetProcessHeap(), 0, sizeof(constant_entry));
4867 list_add_head(&This->updateStateBlock->set_vconstantsF, &ptr->entry);
4868 This->updateStateBlock->set.vertexShaderConstantsF[i] = TRUE;
4870 This->updateStateBlock->changed.vertexShaderConstantsF[i] = TRUE;
4876 static HRESULT WINAPI IWineD3DDeviceImpl_GetVertexShaderConstantF(
4877 IWineD3DDevice *iface,
4882 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4883 int cnt = min(count, GL_LIMITS(vshader_constantsF) - start);
4885 TRACE("(iface %p, dstData %p, start %d, count %d)\n",
4886 iface, dstData, start, count);
4888 if (dstData == NULL || cnt < 0)
4889 return WINED3DERR_INVALIDCALL;
4891 memcpy(dstData, &This->stateBlock->vertexShaderConstantF[start * 4], cnt * sizeof(float) * 4);
4895 static HRESULT WINAPI IWineD3DDeviceImpl_SetPixelShader(IWineD3DDevice *iface, IWineD3DPixelShader *pShader) {
4896 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4897 IWineD3DPixelShader *oldShader = This->updateStateBlock->pixelShader;
4898 This->updateStateBlock->pixelShader = pShader;
4899 This->updateStateBlock->changed.pixelShader = TRUE;
4900 This->updateStateBlock->set.pixelShader = TRUE;
4902 /* Handle recording of state blocks */
4903 if (This->isRecordingState) {
4904 TRACE("Recording... not performing anything\n");
4907 if (NULL != pShader) {
4908 IWineD3DPixelShader_AddRef(pShader);
4910 if (NULL != oldShader) {
4911 IWineD3DPixelShader_Release(oldShader);
4914 TRACE("(%p) : setting pShader(%p)\n", This, pShader);
4916 * TODO: merge HAL shaders context switching from prototype
4921 static HRESULT WINAPI IWineD3DDeviceImpl_GetPixelShader(IWineD3DDevice *iface, IWineD3DPixelShader **ppShader) {
4922 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4924 if (NULL == ppShader) {
4925 WARN("(%p) : PShader is NULL, returning INVALIDCALL\n", This);
4926 return WINED3DERR_INVALIDCALL;
4929 *ppShader = This->stateBlock->pixelShader;
4930 if (NULL != *ppShader) {
4931 IWineD3DPixelShader_AddRef(*ppShader);
4933 TRACE("(%p) : returning %p\n", This, *ppShader);
4937 static HRESULT WINAPI IWineD3DDeviceImpl_SetPixelShaderConstantB(
4938 IWineD3DDevice *iface,
4940 CONST BOOL *srcData,
4943 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4944 int i, cnt = min(count, MAX_CONST_B - start);
4946 TRACE("(iface %p, srcData %p, start %d, count %d)\n",
4947 iface, srcData, start, count);
4949 if (srcData == NULL || cnt < 0)
4950 return WINED3DERR_INVALIDCALL;
4952 memcpy(&This->updateStateBlock->pixelShaderConstantB[start], srcData, cnt * sizeof(BOOL));
4953 for (i = 0; i < cnt; i++)
4954 TRACE("Set BOOL constant %u to %s\n", start + i, srcData[i]? "true":"false");
4956 for (i = start; i < cnt + start; ++i) {
4957 This->updateStateBlock->changed.pixelShaderConstantsB[i] = TRUE;
4958 This->updateStateBlock->set.pixelShaderConstantsB[i] = TRUE;
4964 static HRESULT WINAPI IWineD3DDeviceImpl_GetPixelShaderConstantB(
4965 IWineD3DDevice *iface,
4970 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4971 int cnt = min(count, MAX_CONST_B - start);
4973 TRACE("(iface %p, dstData %p, start %d, count %d)\n",
4974 iface, dstData, start, count);
4976 if (dstData == NULL || cnt < 0)
4977 return WINED3DERR_INVALIDCALL;
4979 memcpy(dstData, &This->stateBlock->pixelShaderConstantB[start], cnt * sizeof(BOOL));
4983 static HRESULT WINAPI IWineD3DDeviceImpl_SetPixelShaderConstantI(
4984 IWineD3DDevice *iface,
4989 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4990 int i, cnt = min(count, MAX_CONST_I - start);
4992 TRACE("(iface %p, srcData %p, start %d, count %d)\n",
4993 iface, srcData, start, count);
4995 if (srcData == NULL || cnt < 0)
4996 return WINED3DERR_INVALIDCALL;
4998 memcpy(&This->updateStateBlock->pixelShaderConstantI[start * 4], srcData, cnt * sizeof(int) * 4);
4999 for (i = 0; i < cnt; i++)
5000 TRACE("Set INT constant %u to { %d, %d, %d, %d }\n", start + i,
5001 srcData[i*4], srcData[i*4+1], srcData[i*4+2], srcData[i*4+3]);
5003 for (i = start; i < cnt + start; ++i) {
5004 This->updateStateBlock->changed.pixelShaderConstantsI[i] = TRUE;
5005 This->updateStateBlock->set.pixelShaderConstantsI[i] = TRUE;
5011 static HRESULT WINAPI IWineD3DDeviceImpl_GetPixelShaderConstantI(
5012 IWineD3DDevice *iface,
5017 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5018 int cnt = min(count, MAX_CONST_I - start);
5020 TRACE("(iface %p, dstData %p, start %d, count %d)\n",
5021 iface, dstData, start, count);
5023 if (dstData == NULL || cnt < 0)
5024 return WINED3DERR_INVALIDCALL;
5026 memcpy(dstData, &This->stateBlock->pixelShaderConstantI[start * 4], cnt * sizeof(int) * 4);
5030 static HRESULT WINAPI IWineD3DDeviceImpl_SetPixelShaderConstantF(
5031 IWineD3DDevice *iface,
5033 CONST float *srcData,
5036 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5037 int i, cnt = min(count, GL_LIMITS(pshader_constantsF) - start);
5039 TRACE("(iface %p, srcData %p, start %d, count %d)\n",
5040 iface, srcData, start, count);
5042 if (srcData == NULL || cnt < 0)
5043 return WINED3DERR_INVALIDCALL;
5045 memcpy(&This->updateStateBlock->pixelShaderConstantF[start * 4], srcData, cnt * sizeof(float) * 4);
5046 for (i = 0; i < cnt; i++)
5047 TRACE("Set FLOAT constant %u to { %f, %f, %f, %f }\n", start + i,
5048 srcData[i*4], srcData[i*4+1], srcData[i*4+2], srcData[i*4+3]);
5050 for (i = start; i < cnt + start; ++i) {
5051 if (!This->updateStateBlock->set.pixelShaderConstantsF[i]) {
5052 constant_entry *ptr = HeapAlloc(GetProcessHeap(), 0, sizeof(constant_entry));
5054 list_add_head(&This->updateStateBlock->set_pconstantsF, &ptr->entry);
5055 This->updateStateBlock->set.pixelShaderConstantsF[i] = TRUE;
5057 This->updateStateBlock->changed.pixelShaderConstantsF[i] = TRUE;
5063 static HRESULT WINAPI IWineD3DDeviceImpl_GetPixelShaderConstantF(
5064 IWineD3DDevice *iface,
5069 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5070 int cnt = min(count, GL_LIMITS(pshader_constantsF) - start);
5072 TRACE("(iface %p, dstData %p, start %d, count %d)\n",
5073 iface, dstData, start, count);
5075 if (dstData == NULL || cnt < 0)
5076 return WINED3DERR_INVALIDCALL;
5078 memcpy(dstData, &This->stateBlock->pixelShaderConstantF[start * 4], cnt * sizeof(float) * 4);
5082 #define copy_and_next(dest, src, size) memcpy(dest, src, size); dest += (size)
5084 process_vertices_strided(IWineD3DDeviceImpl *This, DWORD dwDestIndex, DWORD dwCount, WineDirect3DVertexStridedData *lpStrideData, DWORD SrcFVF, IWineD3DVertexBufferImpl *dest, DWORD dwFlags) {
5085 char *dest_ptr, *dest_conv = NULL;
5087 DWORD DestFVF = dest->fvf;
5089 D3DMATRIX mat, proj_mat, view_mat, world_mat;
5093 if (SrcFVF & D3DFVF_NORMAL) {
5094 WARN(" lighting state not saved yet... Some strange stuff may happen !\n");
5097 if ( (SrcFVF & D3DFVF_POSITION_MASK) != D3DFVF_XYZ) {
5098 ERR("Source has no position mask\n");
5099 return WINED3DERR_INVALIDCALL;
5102 /* We might access VBOs from this code, so hold the lock */
5105 if (dest->resource.allocatedMemory == NULL) {
5106 /* This may happen if we do direct locking into a vbo. Unlikely,
5107 * but theoretically possible(ddraw processvertices test)
5109 dest->resource.allocatedMemory = HeapAlloc(GetProcessHeap(), 0, dest->resource.size);
5110 if(!dest->resource.allocatedMemory) {
5112 ERR("Out of memory\n");
5113 return E_OUTOFMEMORY;
5117 GL_EXTCALL(glBindBufferARB(GL_ARRAY_BUFFER_ARB, dest->vbo));
5118 checkGLcall("glBindBufferARB");
5119 src = GL_EXTCALL(glMapBufferARB(GL_ARRAY_BUFFER_ARB, GL_READ_ONLY_ARB));
5121 memcpy(dest->resource.allocatedMemory, src, dest->resource.size);
5123 GL_EXTCALL(glUnmapBufferARB(GL_ARRAY_BUFFER_ARB));
5124 checkGLcall("glUnmapBufferARB");
5128 /* Get a pointer into the destination vbo(create one if none exists) and
5129 * write correct opengl data into it. It's cheap and allows us to run drawStridedFast
5131 if(!dest->vbo && GL_SUPPORT(ARB_VERTEX_BUFFER_OBJECT)) {
5136 GL_EXTCALL(glBindBufferARB(GL_ARRAY_BUFFER_ARB, dest->vbo));
5137 dest_conv = GL_EXTCALL(glMapBufferARB(GL_ARRAY_BUFFER_ARB, GL_WRITE_ONLY_ARB));
5139 ERR("glMapBuffer failed\n");
5140 /* Continue without storing converted vertices */
5145 * a) D3DRS_CLIPPING is enabled
5146 * b) WINED3DVOP_CLIP is passed
5148 if(This->stateBlock->renderState[WINED3DRS_CLIPPING]) {
5149 static BOOL warned = FALSE;
5151 * The clipping code is not quite correct. Some things need
5152 * to be checked against IDirect3DDevice3 (!), d3d8 and d3d9,
5153 * so disable clipping for now.
5154 * (The graphics in Half-Life are broken, and my processvertices
5155 * test crashes with IDirect3DDevice3)
5161 FIXME("Clipping is broken and disabled for now\n");
5163 } else doClip = FALSE;
5164 dest_ptr = ((char *) dest->resource.allocatedMemory) + dwDestIndex * get_flexible_vertex_size(DestFVF);
5166 dest_conv = ((char *) dest_conv) + dwDestIndex * get_flexible_vertex_size(DestFVF);
5169 IWineD3DDevice_GetTransform( (IWineD3DDevice *) This,
5172 IWineD3DDevice_GetTransform( (IWineD3DDevice *) This,
5173 WINED3DTS_PROJECTION,
5175 IWineD3DDevice_GetTransform( (IWineD3DDevice *) This,
5176 WINED3DTS_WORLDMATRIX(0),
5179 TRACE("View mat:\n");
5180 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); \
5181 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); \
5182 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); \
5183 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); \
5185 TRACE("Proj mat:\n");
5186 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); \
5187 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); \
5188 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); \
5189 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); \
5191 TRACE("World mat:\n");
5192 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); \
5193 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); \
5194 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); \
5195 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); \
5197 /* Get the viewport */
5198 IWineD3DDevice_GetViewport( (IWineD3DDevice *) This, &vp);
5199 TRACE("Viewport: X=%d, Y=%d, Width=%d, Height=%d, MinZ=%f, MaxZ=%f\n",
5200 vp.X, vp.Y, vp.Width, vp.Height, vp.MinZ, vp.MaxZ);
5202 multiply_matrix(&mat,&view_mat,&world_mat);
5203 multiply_matrix(&mat,&proj_mat,&mat);
5205 numTextures = (DestFVF & D3DFVF_TEXCOUNT_MASK) >> D3DFVF_TEXCOUNT_SHIFT;
5207 for (i = 0; i < dwCount; i+= 1) {
5208 unsigned int tex_index;
5210 if ( ((DestFVF & D3DFVF_POSITION_MASK) == D3DFVF_XYZ ) ||
5211 ((DestFVF & D3DFVF_POSITION_MASK) == D3DFVF_XYZRHW ) ) {
5212 /* The position first */
5214 (float *) (((char *) lpStrideData->u.s.position.lpData) + i * lpStrideData->u.s.position.dwStride);
5216 TRACE("In: ( %06.2f %06.2f %06.2f )\n", p[0], p[1], p[2]);
5218 /* Multiplication with world, view and projection matrix */
5219 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);
5220 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);
5221 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);
5222 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);
5224 TRACE("x=%f y=%f z=%f rhw=%f\n", x, y, z, rhw);
5226 /* WARNING: The following things are taken from d3d7 and were not yet checked
5227 * against d3d8 or d3d9!
5230 /* Clipping conditions: From
5231 * http://msdn.microsoft.com/archive/default.asp?url=/archive/en-us/directx9_c/directx/graphics/programmingguide/fixedfunction/viewportsclipping/clippingvolumes.asp
5233 * A vertex is clipped if it does not match the following requirements
5237 * 0 < rhw ( Not in d3d7, but tested in d3d7)
5239 * If clipping is on is determined by the D3DVOP_CLIP flag in D3D7, and
5240 * by the D3DRS_CLIPPING in D3D9(according to the msdn, not checked)
5245 ( (-rhw -eps < x) && (-rhw -eps < y) && ( -eps < z) &&
5246 (x <= rhw + eps) && (y <= rhw + eps ) && (z <= rhw + eps) &&
5249 /* "Normal" viewport transformation (not clipped)
5250 * 1) The values are divided by rhw
5251 * 2) The y axis is negative, so multiply it with -1
5252 * 3) Screen coordinates go from -(Width/2) to +(Width/2) and
5253 * -(Height/2) to +(Height/2). The z range is MinZ to MaxZ
5254 * 4) Multiply x with Width/2 and add Width/2
5255 * 5) The same for the height
5256 * 6) Add the viewpoint X and Y to the 2D coordinates and
5257 * The minimum Z value to z
5258 * 7) rhw = 1 / rhw Reciprocal of Homogeneous W....
5260 * Well, basically it's simply a linear transformation into viewport
5272 z *= vp.MaxZ - vp.MinZ;
5274 x += vp.Width / 2 + vp.X;
5275 y += vp.Height / 2 + vp.Y;
5280 /* That vertex got clipped
5281 * Contrary to OpenGL it is not dropped completely, it just
5282 * undergoes a different calculation.
5284 TRACE("Vertex got clipped\n");
5291 /* Msdn mentions that Direct3D9 keeps a list of clipped vertices
5292 * outside of the main vertex buffer memory. That needs some more
5297 TRACE("Writing (%f %f %f) %f\n", x, y, z, rhw);
5300 ( (float *) dest_ptr)[0] = x;
5301 ( (float *) dest_ptr)[1] = y;
5302 ( (float *) dest_ptr)[2] = z;
5303 ( (float *) dest_ptr)[3] = rhw; /* SIC, see ddraw test! */
5305 dest_ptr += 3 * sizeof(float);
5307 if((DestFVF & D3DFVF_POSITION_MASK) == D3DFVF_XYZRHW) {
5308 dest_ptr += sizeof(float);
5313 ( (float *) dest_conv)[0] = x * w;
5314 ( (float *) dest_conv)[1] = y * w;
5315 ( (float *) dest_conv)[2] = z * w;
5316 ( (float *) dest_conv)[3] = w;
5318 dest_conv += 3 * sizeof(float);
5320 if((DestFVF & D3DFVF_POSITION_MASK) == D3DFVF_XYZRHW) {
5321 dest_conv += sizeof(float);
5325 if (DestFVF & D3DFVF_PSIZE) {
5326 dest_ptr += sizeof(DWORD);
5327 if(dest_conv) dest_conv += sizeof(DWORD);
5329 if (DestFVF & D3DFVF_NORMAL) {
5331 (float *) (((float *) lpStrideData->u.s.normal.lpData) + i * lpStrideData->u.s.normal.dwStride);
5332 /* AFAIK this should go into the lighting information */
5333 FIXME("Didn't expect the destination to have a normal\n");
5334 copy_and_next(dest_ptr, normal, 3 * sizeof(float));
5336 copy_and_next(dest_conv, normal, 3 * sizeof(float));
5340 if (DestFVF & D3DFVF_DIFFUSE) {
5342 (DWORD *) (((char *) lpStrideData->u.s.diffuse.lpData) + i * lpStrideData->u.s.diffuse.dwStride);
5344 static BOOL warned = FALSE;
5347 ERR("No diffuse color in source, but destination has one\n");
5351 *( (DWORD *) dest_ptr) = 0xffffffff;
5352 dest_ptr += sizeof(DWORD);
5355 *( (DWORD *) dest_conv) = 0xffffffff;
5356 dest_conv += sizeof(DWORD);
5360 copy_and_next(dest_ptr, color_d, sizeof(DWORD));
5362 *( (DWORD *) dest_conv) = (*color_d & 0xff00ff00) ; /* Alpha + green */
5363 *( (DWORD *) dest_conv) |= (*color_d & 0x00ff0000) >> 16; /* Red */
5364 *( (DWORD *) dest_conv) |= (*color_d & 0xff0000ff) << 16; /* Blue */
5365 dest_conv += sizeof(DWORD);
5370 if (DestFVF & D3DFVF_SPECULAR) {
5371 /* What's the color value in the feedback buffer? */
5373 (DWORD *) (((char *) lpStrideData->u.s.specular.lpData) + i * lpStrideData->u.s.specular.dwStride);
5375 static BOOL warned = FALSE;
5378 ERR("No specular color in source, but destination has one\n");
5382 *( (DWORD *) dest_ptr) = 0xFF000000;
5383 dest_ptr += sizeof(DWORD);
5386 *( (DWORD *) dest_conv) = 0xFF000000;
5387 dest_conv += sizeof(DWORD);
5391 copy_and_next(dest_ptr, color_s, sizeof(DWORD));
5393 *( (DWORD *) dest_conv) = (*color_s & 0xff00ff00) ; /* Alpha + green */
5394 *( (DWORD *) dest_conv) |= (*color_s & 0x00ff0000) >> 16; /* Red */
5395 *( (DWORD *) dest_conv) |= (*color_s & 0xff0000ff) << 16; /* Blue */
5396 dest_conv += sizeof(DWORD);
5401 for (tex_index = 0; tex_index < numTextures; tex_index++) {
5403 (float *) (((char *) lpStrideData->u.s.texCoords[tex_index].lpData) +
5404 i * lpStrideData->u.s.texCoords[tex_index].dwStride);
5406 ERR("No source texture, but destination requests one\n");
5407 dest_ptr+=GET_TEXCOORD_SIZE_FROM_FVF(DestFVF, tex_index) * sizeof(float);
5408 if(dest_conv) dest_conv += GET_TEXCOORD_SIZE_FROM_FVF(DestFVF, tex_index) * sizeof(float);
5411 copy_and_next(dest_ptr, tex_coord, GET_TEXCOORD_SIZE_FROM_FVF(DestFVF, tex_index) * sizeof(float));
5413 copy_and_next(dest_conv, tex_coord, GET_TEXCOORD_SIZE_FROM_FVF(DestFVF, tex_index) * sizeof(float));
5420 GL_EXTCALL(glUnmapBufferARB(GL_ARRAY_BUFFER_ARB));
5421 checkGLcall("glUnmapBufferARB(GL_ARRAY_BUFFER_ARB)");
5428 #undef copy_and_next
5430 static HRESULT WINAPI IWineD3DDeviceImpl_ProcessVertices(IWineD3DDevice *iface, UINT SrcStartIndex, UINT DestIndex, UINT VertexCount, IWineD3DVertexBuffer* pDestBuffer, IWineD3DVertexBuffer* pVertexDecl, DWORD Flags) {
5431 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5432 IWineD3DVertexBufferImpl *SrcImpl = (IWineD3DVertexBufferImpl *) pVertexDecl;
5433 WineDirect3DVertexStridedData strided;
5434 TRACE("(%p)->(%d,%d,%d,%p,%p,%d\n", This, SrcStartIndex, DestIndex, VertexCount, pDestBuffer, pVertexDecl, Flags);
5437 WARN("NULL source vertex buffer\n");
5438 return WINED3DERR_INVALIDCALL;
5440 /* We don't need the source vbo because this buffer is only used as
5441 * a source for ProcessVertices. Avoid wasting resources by converting the
5442 * buffer and loading the VBO
5445 TRACE("Releaseing the source vbo, it won't be needed\n");
5447 if(!SrcImpl->resource.allocatedMemory) {
5448 /* Rescue the data from the buffer */
5450 SrcImpl->resource.allocatedMemory = HeapAlloc(GetProcessHeap(), 0, SrcImpl->resource.size);
5451 if(!SrcImpl->resource.allocatedMemory) {
5452 ERR("Out of memory\n");
5453 return E_OUTOFMEMORY;
5457 GL_EXTCALL(glBindBufferARB(GL_ARRAY_BUFFER_ARB, SrcImpl->vbo));
5458 checkGLcall("glBindBufferARB");
5460 src = GL_EXTCALL(glMapBufferARB(GL_ARRAY_BUFFER_ARB, GL_READ_ONLY_ARB));
5462 memcpy(SrcImpl->resource.allocatedMemory, src, SrcImpl->resource.size);
5465 GL_EXTCALL(glUnmapBufferARB(GL_ARRAY_BUFFER_ARB));
5466 checkGLcall("glUnmapBufferARB");
5471 GL_EXTCALL(glBindBufferARB(GL_ARRAY_BUFFER_ARB, 0));
5472 checkGLcall("glBindBufferARB");
5473 GL_EXTCALL(glDeleteBuffersARB(1, &SrcImpl->vbo));
5474 checkGLcall("glDeleteBuffersARB");
5480 memset(&strided, 0, sizeof(strided));
5481 primitiveConvertFVFtoOffset(SrcImpl->fvf, get_flexible_vertex_size(SrcImpl->fvf), SrcImpl->resource.allocatedMemory + get_flexible_vertex_size(SrcImpl->fvf) * SrcStartIndex, &strided, 0);
5483 return process_vertices_strided(This, DestIndex, VertexCount, &strided, SrcImpl->fvf, (IWineD3DVertexBufferImpl *) pDestBuffer, Flags);
5487 * Apply / Get / Set Texture Stage States
5488 * TODO: Verify against dx9 definitions
5491 /* 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 */
5492 static void WINAPI IWineD3DDeviceImpl_ApplyTextureUnitState(IWineD3DDevice *iface, DWORD Stage, WINED3DTEXTURESTAGESTATETYPE Type) {
5493 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5494 DWORD Value = This->updateStateBlock->textureState[Stage][Type];
5495 /* FIXME: Handle 3d textures? What if TSS value set before set texture? Need to reapply all values? */
5497 TRACE("(%p) : Stage=%d, Type=%s(%d), Value=%d\n", This, Stage, debug_d3dtexturestate(Type), Type, Value);
5499 /* Check that the stage is within limits */
5500 if (Stage >= GL_LIMITS(texture_stages) || Stage < 0) {
5501 TRACE("Attempt to access invalid texture rejected\n");
5508 case WINED3DTSS_ALPHAOP :
5509 case WINED3DTSS_COLOROP :
5510 /* nothing to do as moved to drawprim for now */
5512 case WINED3DTSS_ADDRESSW :
5513 #if 0 /* I'm not sure what D3D does about ADDRESSW appearing twice */
5514 if (Value < minLookup[WINELOOKUP_WARPPARAM] || Value > maxLookup[WINELOOKUP_WARPPARAM]) {
5515 FIXME("Unrecognized or unsupported D3DTADDRESS_* value %d, state %d\n", Value, Type);
5518 GLint wrapParm = stateLookup[WINELOOKUP_WARPPARAM][Value - minLookup[WINELOOKUP_WARPPARAM]];
5519 TRACE("Setting WRAP_R to %d for %x\n", wrapParm, This->stateBlock->textureDimensions[Stage]);
5520 glTexParameteri(This->stateBlock->textureDimensions[Stage], GL_TEXTURE_WRAP_R, wrapParm);
5521 checkGLcall("glTexParameteri(..., GL_TEXTURE_WRAP_R, wrapParm)");
5524 case WINED3DTSS_TEXCOORDINDEX :
5526 /* Values 0-7 are indexes into the FVF tex coords - See comments in DrawPrimitive */
5528 /* FIXME: From MSDN: The WINED3DTSS_TCI_* flags are mutually exclusive. If you include
5529 one flag, you can still specify an index value, which the system uses to
5530 determine the texture wrapping mode.
5531 eg. SetTextureStageState( 0, D3DTSS_TEXCOORDINDEX, D3DTSS_TCI_CAMERASPACEPOSITION | 1 );
5532 means use the vertex position (camera-space) as the input texture coordinates
5533 for this texture stage, and the wrap mode set in the WINED3DRS_WRAP1 render
5534 state. We do not (yet) support the D3DRENDERSTATE_WRAPx values, nor tie them up
5535 to the TEXCOORDINDEX value */
5538 * Be careful the value of the mask 0xF0000 come from d3d8types.h infos
5540 switch (Value & 0xFFFF0000) {
5541 case D3DTSS_TCI_PASSTHRU:
5542 /*Use the specified texture coordinates contained within the vertex format. This value resolves to zero.*/
5543 glDisable(GL_TEXTURE_GEN_S);
5544 glDisable(GL_TEXTURE_GEN_T);
5545 glDisable(GL_TEXTURE_GEN_R);
5546 glDisable(GL_TEXTURE_GEN_Q);
5547 checkGLcall("glDisable(GL_TEXTURE_GEN_S,T,R,Q)");
5550 case D3DTSS_TCI_CAMERASPACEPOSITION:
5551 /* CameraSpacePosition means use the vertex position, transformed to camera space,
5552 as the input texture coordinates for this stage's texture transformation. This
5553 equates roughly to EYE_LINEAR */
5555 float s_plane[] = { 1.0, 0.0, 0.0, 0.0 };
5556 float t_plane[] = { 0.0, 1.0, 0.0, 0.0 };
5557 float r_plane[] = { 0.0, 0.0, 1.0, 0.0 };
5558 float q_plane[] = { 0.0, 0.0, 0.0, 1.0 };
5559 TRACE("WINED3DTSS_TCI_CAMERASPACEPOSITION - Set eye plane\n");
5561 glMatrixMode(GL_MODELVIEW);
5564 glTexGenfv(GL_S, GL_EYE_PLANE, s_plane);
5565 glTexGenfv(GL_T, GL_EYE_PLANE, t_plane);
5566 glTexGenfv(GL_R, GL_EYE_PLANE, r_plane);
5567 glTexGenfv(GL_Q, GL_EYE_PLANE, q_plane);
5570 TRACE("WINED3DTSS_TCI_CAMERASPACEPOSITION - Set GL_TEXTURE_GEN_x and GL_x, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR\n");
5571 glEnable(GL_TEXTURE_GEN_S);
5572 checkGLcall("glEnable(GL_TEXTURE_GEN_S);");
5573 glTexGeni(GL_S, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR);
5574 checkGLcall("glTexGeni(GL_S, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR)");
5575 glEnable(GL_TEXTURE_GEN_T);
5576 checkGLcall("glEnable(GL_TEXTURE_GEN_T);");
5577 glTexGeni(GL_T, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR);
5578 checkGLcall("glTexGeni(GL_T, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR)");
5579 glEnable(GL_TEXTURE_GEN_R);
5580 checkGLcall("glEnable(GL_TEXTURE_GEN_R);");
5581 glTexGeni(GL_R, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR);
5582 checkGLcall("glTexGeni(GL_R, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR)");
5586 case D3DTSS_TCI_CAMERASPACENORMAL:
5588 if (GL_SUPPORT(NV_TEXGEN_REFLECTION)) {
5589 float s_plane[] = { 1.0, 0.0, 0.0, 0.0 };
5590 float t_plane[] = { 0.0, 1.0, 0.0, 0.0 };
5591 float r_plane[] = { 0.0, 0.0, 1.0, 0.0 };
5592 float q_plane[] = { 0.0, 0.0, 0.0, 1.0 };
5593 TRACE("WINED3DTSS_TCI_CAMERASPACENORMAL - Set eye plane\n");
5595 glMatrixMode(GL_MODELVIEW);
5598 glTexGenfv(GL_S, GL_EYE_PLANE, s_plane);
5599 glTexGenfv(GL_T, GL_EYE_PLANE, t_plane);
5600 glTexGenfv(GL_R, GL_EYE_PLANE, r_plane);
5601 glTexGenfv(GL_Q, GL_EYE_PLANE, q_plane);
5604 glEnable(GL_TEXTURE_GEN_S);
5605 checkGLcall("glEnable(GL_TEXTURE_GEN_S);");
5606 glTexGeni(GL_S, GL_TEXTURE_GEN_MODE, GL_NORMAL_MAP_NV);
5607 checkGLcall("glTexGeni(GL_S, GL_TEXTURE_GEN_MODE, GL_NORMAL_MAP_NV)");
5608 glEnable(GL_TEXTURE_GEN_T);
5609 checkGLcall("glEnable(GL_TEXTURE_GEN_T);");
5610 glTexGeni(GL_T, GL_TEXTURE_GEN_MODE, GL_NORMAL_MAP_NV);
5611 checkGLcall("glTexGeni(GL_T, GL_TEXTURE_GEN_MODE, GL_NORMAL_MAP_NV)");
5612 glEnable(GL_TEXTURE_GEN_R);
5613 checkGLcall("glEnable(GL_TEXTURE_GEN_R);");
5614 glTexGeni(GL_R, GL_TEXTURE_GEN_MODE, GL_NORMAL_MAP_NV);
5615 checkGLcall("glTexGeni(GL_R, GL_TEXTURE_GEN_MODE, GL_NORMAL_MAP_NV)");
5620 case D3DTSS_TCI_CAMERASPACEREFLECTIONVECTOR:
5622 if (GL_SUPPORT(NV_TEXGEN_REFLECTION)) {
5623 float s_plane[] = { 1.0, 0.0, 0.0, 0.0 };
5624 float t_plane[] = { 0.0, 1.0, 0.0, 0.0 };
5625 float r_plane[] = { 0.0, 0.0, 1.0, 0.0 };
5626 float q_plane[] = { 0.0, 0.0, 0.0, 1.0 };
5627 TRACE("WINED3DTSS_TCI_CAMERASPACEREFLECTIONVECTOR - Set eye plane\n");
5629 glMatrixMode(GL_MODELVIEW);
5632 glTexGenfv(GL_S, GL_EYE_PLANE, s_plane);
5633 glTexGenfv(GL_T, GL_EYE_PLANE, t_plane);
5634 glTexGenfv(GL_R, GL_EYE_PLANE, r_plane);
5635 glTexGenfv(GL_Q, GL_EYE_PLANE, q_plane);
5638 glEnable(GL_TEXTURE_GEN_S);
5639 checkGLcall("glEnable(GL_TEXTURE_GEN_S);");
5640 glTexGeni(GL_S, GL_TEXTURE_GEN_MODE, GL_REFLECTION_MAP_NV);
5641 checkGLcall("glTexGeni(GL_S, GL_TEXTURE_GEN_MODE, GL_REFLECTION_MAP_NV)");
5642 glEnable(GL_TEXTURE_GEN_T);
5643 checkGLcall("glEnable(GL_TEXTURE_GEN_T);");
5644 glTexGeni(GL_T, GL_TEXTURE_GEN_MODE, GL_REFLECTION_MAP_NV);
5645 checkGLcall("glTexGeni(GL_T, GL_TEXTURE_GEN_MODE, GL_REFLECTION_MAP_NV)");
5646 glEnable(GL_TEXTURE_GEN_R);
5647 checkGLcall("glEnable(GL_TEXTURE_GEN_R);");
5648 glTexGeni(GL_R, GL_TEXTURE_GEN_MODE, GL_REFLECTION_MAP_NV);
5649 checkGLcall("glTexGeni(GL_R, GL_TEXTURE_GEN_MODE, GL_REFLECTION_MAP_NV)");
5654 /* Unhandled types: */
5657 /* ? disable GL_TEXTURE_GEN_n ? */
5658 glDisable(GL_TEXTURE_GEN_S);
5659 glDisable(GL_TEXTURE_GEN_T);
5660 glDisable(GL_TEXTURE_GEN_R);
5661 glDisable(GL_TEXTURE_GEN_Q);
5662 FIXME("Unhandled WINED3DTSS_TEXCOORDINDEX %x\n", Value);
5669 case WINED3DTSS_TEXTURETRANSFORMFLAGS :
5670 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);
5673 case WINED3DTSS_BUMPENVMAT00 :
5674 case WINED3DTSS_BUMPENVMAT01 :
5675 TRACE("BUMPENVMAT0%u Stage=%d, Type=%d, Value =%d\n", Type - WINED3DTSS_BUMPENVMAT00, Stage, Type, Value);
5677 case WINED3DTSS_BUMPENVMAT10 :
5678 case WINED3DTSS_BUMPENVMAT11 :
5679 TRACE("BUMPENVMAT1%u Stage=%d, Type=%d, Value =%d\n", Type - WINED3DTSS_BUMPENVMAT10, Stage, Type, Value);
5682 case WINED3DTSS_BUMPENVLSCALE :
5683 TRACE("BUMPENVLSCALE Stage=%d, Type=%d, Value =%d\n", Stage, Type, Value);
5686 case WINED3DTSS_BUMPENVLOFFSET :
5687 TRACE("BUMPENVLOFFSET Stage=%d, Type=%d, Value =%d\n", Stage, Type, Value);
5690 case WINED3DTSS_RESULTARG :
5691 TRACE("RESULTARG Still a stub, Stage=%d, Type=%d, Value =%d\n", Stage, Type, Value);
5695 /* Put back later: FIXME("(%p) : stub, Stage=%d, Type=%d, Value =%d\n", This, Stage, Type, Value); */
5696 TRACE("Still a stub, Stage=%d, Type=%d, Value =%d\n", Stage, Type, Value);
5705 * Get / Set Texture Stage States
5706 * TODO: Verify against dx9 definitions
5708 static HRESULT WINAPI IWineD3DDeviceImpl_SetTextureStageState(IWineD3DDevice *iface, DWORD Stage, WINED3DTEXTURESTAGESTATETYPE Type, DWORD Value) {
5709 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5711 /* FIXME: Handle 3d textures? What if TSS value set before set texture? Need to reapply all values? */
5713 TRACE("(%p) : Stage=%d, Type=%s(%d), Value=%d\n", This, Stage, debug_d3dtexturestate(Type), Type, Value);
5715 /* Reject invalid texture units */
5716 if (Stage >= GL_LIMITS(texture_stages)) {
5717 TRACE("Attempt to access invalid texture rejected\n");
5718 return WINED3DERR_INVALIDCALL;
5721 This->updateStateBlock->changed.textureState[Stage][Type] = TRUE;
5722 This->updateStateBlock->set.textureState[Stage][Type] = TRUE;
5723 This->updateStateBlock->textureState[Stage][Type] = Value;
5728 static HRESULT WINAPI IWineD3DDeviceImpl_GetTextureStageState(IWineD3DDevice *iface, DWORD Stage, WINED3DTEXTURESTAGESTATETYPE Type, DWORD* pValue) {
5729 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5730 TRACE("(%p) : requesting Stage %d, Type %d getting %d\n", This, Stage, Type, This->updateStateBlock->textureState[Stage][Type]);
5731 *pValue = This->updateStateBlock->textureState[Stage][Type];
5738 static HRESULT WINAPI IWineD3DDeviceImpl_SetTexture(IWineD3DDevice *iface, DWORD Stage, IWineD3DBaseTexture* pTexture) {
5740 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5741 IWineD3DBaseTexture *oldTexture;
5743 oldTexture = This->updateStateBlock->textures[Stage];
5744 TRACE("(%p) : Stage(%d), Texture (%p)\n", This, Stage, pTexture);
5746 #if 0 /* TODO: check so vertex textures */
5747 if (Stage >= D3DVERTEXTEXTURESAMPLER && Stage <= D3DVERTEXTEXTURESAMPLER3){
5748 This->updateStateBlock->vertexTextures[Stage - D3DVERTEXTEXTURESAMPLER] = pTexture;
5753 /* Reject invalid texture units */
5754 if (Stage >= GL_LIMITS(sampler_stages) || Stage < 0) {
5755 WARN("Attempt to access invalid texture rejected\n");
5756 return WINED3DERR_INVALIDCALL;
5759 if(pTexture != NULL) {
5760 /* SetTexture isn't allowed on textures in WINED3DPOOL_SCRATCH;
5762 if(((IWineD3DTextureImpl*)pTexture)->resource.pool == WINED3DPOOL_SCRATCH) {
5763 WARN("(%p) Attempt to set scratch texture rejected\n", pTexture);
5764 return WINED3DERR_INVALIDCALL;
5768 oldTexture = This->updateStateBlock->textures[Stage];
5769 TRACE("GL_LIMITS %d\n",GL_LIMITS(sampler_stages));
5770 TRACE("(%p) : oldtexture(%p)\n", This,oldTexture);
5772 This->updateStateBlock->set.textures[Stage] = TRUE;
5773 This->updateStateBlock->changed.textures[Stage] = TRUE;
5774 TRACE("(%p) : setting new texture to %p\n", This, pTexture);
5775 This->updateStateBlock->textures[Stage] = pTexture;
5777 /* Handle recording of state blocks */
5778 if (This->isRecordingState) {
5779 TRACE("Recording... not performing anything\n");
5783 /** NOTE: MSDN says that setTexture increases the reference count,
5784 * and the the application nust set the texture back to null (or have a leaky application),
5785 * This means we should pass the refcount up to the parent
5786 *******************************/
5787 if (NULL != This->updateStateBlock->textures[Stage]) {
5788 IWineD3DBaseTexture_AddRef(This->updateStateBlock->textures[Stage]);
5791 if (NULL != oldTexture) {
5792 IWineD3DBaseTexture_Release(oldTexture);
5795 /* Reset color keying */
5796 if(Stage == 0 && This->stateBlock->renderState[WINED3DRS_COLORKEYENABLE]) {
5797 BOOL enable_ckey = FALSE;
5800 IWineD3DSurfaceImpl *surf = (IWineD3DSurfaceImpl *) ((IWineD3DTextureImpl *)pTexture)->surfaces[0];
5801 if(surf->CKeyFlags & DDSD_CKSRCBLT) enable_ckey = TRUE;
5805 glAlphaFunc(GL_NOTEQUAL, 0.0);
5806 checkGLcall("glAlphaFunc");
5813 static HRESULT WINAPI IWineD3DDeviceImpl_GetTexture(IWineD3DDevice *iface, DWORD Stage, IWineD3DBaseTexture** ppTexture) {
5814 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5815 TRACE("(%p) : (%d /* Stage */,%p /* ppTexture */)\n", This, Stage, ppTexture);
5817 /* Reject invalid texture units */
5818 if (Stage >= GL_LIMITS(sampler_stages)) {
5819 TRACE("Attempt to access invalid texture rejected\n");
5820 return WINED3DERR_INVALIDCALL;
5822 *ppTexture=This->updateStateBlock->textures[Stage];
5824 IWineD3DBaseTexture_AddRef(*ppTexture);
5826 return WINED3DERR_INVALIDCALL;
5833 static HRESULT WINAPI IWineD3DDeviceImpl_GetBackBuffer(IWineD3DDevice *iface, UINT iSwapChain, UINT BackBuffer, WINED3DBACKBUFFER_TYPE Type,
5834 IWineD3DSurface **ppBackBuffer) {
5835 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5836 IWineD3DSwapChain *swapChain;
5839 TRACE("(%p) : BackBuf %d Type %d SwapChain %d returning %p\n", This, BackBuffer, Type, iSwapChain, *ppBackBuffer);
5841 hr = IWineD3DDeviceImpl_GetSwapChain(iface, iSwapChain, &swapChain);
5842 if (hr == WINED3D_OK) {
5843 hr = IWineD3DSwapChain_GetBackBuffer(swapChain, BackBuffer, Type, ppBackBuffer);
5844 IWineD3DSwapChain_Release(swapChain);
5846 *ppBackBuffer = NULL;
5851 static HRESULT WINAPI IWineD3DDeviceImpl_GetDeviceCaps(IWineD3DDevice *iface, WINED3DCAPS* pCaps) {
5852 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5853 WARN("(%p) : stub, calling idirect3d for now\n", This);
5854 return IWineD3D_GetDeviceCaps(This->wineD3D, This->adapterNo, This->devType, pCaps);
5857 static HRESULT WINAPI IWineD3DDeviceImpl_GetDisplayMode(IWineD3DDevice *iface, UINT iSwapChain, WINED3DDISPLAYMODE* pMode) {
5858 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5859 IWineD3DSwapChain *swapChain;
5862 if(iSwapChain > 0) {
5863 hr = IWineD3DDeviceImpl_GetSwapChain(iface, iSwapChain, (IWineD3DSwapChain **)&swapChain);
5864 if (hr == WINED3D_OK) {
5865 hr = IWineD3DSwapChain_GetDisplayMode(swapChain, pMode);
5866 IWineD3DSwapChain_Release(swapChain);
5868 FIXME("(%p) Error getting display mode\n", This);
5871 /* Don't read the real display mode,
5872 but return the stored mode instead. X11 can't change the color
5873 depth, and some apps are pretty angry if they SetDisplayMode from
5874 24 to 16 bpp and find out that GetDisplayMode still returns 24 bpp
5876 Also don't relay to the swapchain because with ddraw it's possible
5877 that there isn't a swapchain at all */
5878 pMode->Width = This->ddraw_width;
5879 pMode->Height = This->ddraw_height;
5880 pMode->Format = This->ddraw_format;
5881 pMode->RefreshRate = 0;
5888 static HRESULT WINAPI IWineD3DDeviceImpl_SetHWND(IWineD3DDevice *iface, HWND hWnd) {
5889 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5890 TRACE("(%p)->(%p)\n", This, hWnd);
5892 This->ddraw_window = hWnd;
5896 static HRESULT WINAPI IWineD3DDeviceImpl_GetHWND(IWineD3DDevice *iface, HWND *hWnd) {
5897 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5898 TRACE("(%p)->(%p)\n", This, hWnd);
5900 *hWnd = This->ddraw_window;
5905 * Stateblock related functions
5908 static HRESULT WINAPI IWineD3DDeviceImpl_BeginStateBlock(IWineD3DDevice *iface) {
5909 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5910 IWineD3DStateBlockImpl *object;
5911 HRESULT temp_result;
5913 TRACE("(%p)\n", This);
5915 if (This->isRecordingState) {
5916 return WINED3DERR_INVALIDCALL;
5919 object = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(IWineD3DStateBlockImpl));
5920 if (NULL == object ) {
5921 FIXME("(%p)Error allocating memory for stateblock\n", This);
5922 return E_OUTOFMEMORY;
5924 TRACE("(%p) created object %p\n", This, object);
5925 object->wineD3DDevice= This;
5926 /** FIXME: object->parent = parent; **/
5927 object->parent = NULL;
5928 object->blockType = WINED3DSBT_ALL;
5930 object->lpVtbl = &IWineD3DStateBlock_Vtbl;
5932 temp_result = allocate_shader_constants(object);
5933 if (WINED3D_OK != temp_result)
5936 IWineD3DStateBlock_Release((IWineD3DStateBlock*)This->updateStateBlock);
5937 This->updateStateBlock = object;
5938 This->isRecordingState = TRUE;
5940 TRACE("(%p) recording stateblock %p\n",This , object);
5944 static HRESULT WINAPI IWineD3DDeviceImpl_EndStateBlock(IWineD3DDevice *iface, IWineD3DStateBlock** ppStateBlock) {
5945 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5947 if (!This->isRecordingState) {
5948 FIXME("(%p) not recording! returning error\n", This);
5949 *ppStateBlock = NULL;
5950 return WINED3DERR_INVALIDCALL;
5953 *ppStateBlock = (IWineD3DStateBlock*)This->updateStateBlock;
5954 This->isRecordingState = FALSE;
5955 This->updateStateBlock = This->stateBlock;
5956 IWineD3DStateBlock_AddRef((IWineD3DStateBlock*)This->updateStateBlock);
5957 /* IWineD3DStateBlock_AddRef(*ppStateBlock); don't need to do this, since we should really just release UpdateStateBlock first */
5958 TRACE("(%p) returning token (ptr to stateblock) of %p\n", This, *ppStateBlock);
5963 * Scene related functions
5965 static HRESULT WINAPI IWineD3DDeviceImpl_BeginScene(IWineD3DDevice *iface) {
5966 /* At the moment we have no need for any functionality at the beginning
5968 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5969 TRACE("(%p) : stub\n", This);
5973 static HRESULT WINAPI IWineD3DDeviceImpl_EndScene(IWineD3DDevice *iface) {
5974 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5975 TRACE("(%p)\n", This);
5977 /* We only have to do this if we need to read the, swapbuffers performs a flush for us */
5979 checkGLcall("glFlush");
5981 TRACE("End Scene\n");
5982 if(This->renderTarget != NULL) {
5984 /* If the container of the rendertarget is a texture then we need to save the data from the pbuffer */
5985 IUnknown *targetContainer = NULL;
5986 if (WINED3D_OK == IWineD3DSurface_GetContainer(This->renderTarget, &IID_IWineD3DBaseTexture, (void **)&targetContainer)
5987 || WINED3D_OK == IWineD3DSurface_GetContainer(This->renderTarget, &IID_IWineD3DDevice, (void **)&targetContainer)) {
5988 TRACE("(%p) : Texture rendertarget %p\n", This ,This->renderTarget);
5989 /** always dirtify for now. we must find a better way to see that surface have been modified
5990 (Modifications should will only occur via draw-primitive, but we do need better locking
5991 switching to render-to-texture should remove the overhead though.
5993 IWineD3DSurface_SetPBufferState(This->renderTarget, TRUE /* inPBuffer */, FALSE /* inTexture */);
5994 IWineD3DSurface_AddDirtyRect(This->renderTarget, NULL);
5995 IWineD3DSurface_PreLoad(This->renderTarget);
5996 IWineD3DSurface_SetPBufferState(This->renderTarget, FALSE /* inPBuffer */, FALSE /* inTexture */);
5997 IUnknown_Release(targetContainer);
6000 This->sceneEnded = TRUE;
6005 static HRESULT WINAPI IWineD3DDeviceImpl_Present(IWineD3DDevice *iface,
6006 CONST RECT* pSourceRect, CONST RECT* pDestRect,
6007 HWND hDestWindowOverride, CONST RGNDATA* pDirtyRegion) {
6008 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
6009 IWineD3DSwapChain *swapChain = NULL;
6011 int swapchains = IWineD3DDeviceImpl_GetNumberOfSwapChains(iface);
6013 TRACE("(%p) Presenting the frame\n", This);
6015 for(i = 0 ; i < swapchains ; i ++) {
6017 IWineD3DDeviceImpl_GetSwapChain(iface, i , (IWineD3DSwapChain **)&swapChain);
6018 TRACE("presentinng chain %d, %p\n", i, swapChain);
6019 IWineD3DSwapChain_Present(swapChain, pSourceRect, pDestRect, hDestWindowOverride, pDirtyRegion, 0);
6020 IWineD3DSwapChain_Release(swapChain);
6026 static HRESULT WINAPI IWineD3DDeviceImpl_Clear(IWineD3DDevice *iface, DWORD Count, CONST D3DRECT* pRects,
6027 DWORD Flags, D3DCOLOR Color, float Z, DWORD Stencil) {
6028 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
6030 /* TODO: From MSDN This method fails if you specify the D3DCLEAR_ZBUFFER or D3DCLEAR_STENCIL flags when the
6031 render target does not have an attached depth buffer. Similarly, if you specify the D3DCLEAR_STENCIL flag
6032 when the depth-buffer format does not contain stencil buffer information, this method fails. */
6033 GLbitfield glMask = 0;
6034 GLboolean old_ztest;
6035 GLfloat old_z_clear_value;
6036 GLint old_stencil_clear_value;
6037 GLfloat old_color_clear_value[4];
6039 CONST D3DRECT* curRect;
6041 TRACE("(%p) Count (%d), pRects (%p), Flags (%x), Z (%f), Stencil (%d)\n", This,
6042 Count, pRects, Flags, Z, Stencil);
6046 glEnable(GL_SCISSOR_TEST);
6047 checkGLcall("glEnable GL_SCISSOR_TEST");
6049 if (Count > 0 && pRects) {
6055 /* Only set the values up once, as they are not changing */
6056 if (Flags & D3DCLEAR_STENCIL) {
6057 glGetIntegerv(GL_STENCIL_CLEAR_VALUE, &old_stencil_clear_value);
6058 glClearStencil(Stencil);
6059 checkGLcall("glClearStencil");
6060 glMask = glMask | GL_STENCIL_BUFFER_BIT;
6061 glStencilMask(0xFFFFFFFF);
6064 if (Flags & D3DCLEAR_ZBUFFER) {
6065 glGetBooleanv(GL_DEPTH_WRITEMASK, &old_ztest);
6066 glDepthMask(GL_TRUE);
6067 glGetFloatv(GL_DEPTH_CLEAR_VALUE, &old_z_clear_value);
6069 checkGLcall("glClearDepth");
6070 glMask = glMask | GL_DEPTH_BUFFER_BIT;
6073 if (Flags & D3DCLEAR_TARGET) {
6074 TRACE("Clearing screen with glClear to color %x\n", Color);
6075 glGetFloatv(GL_COLOR_CLEAR_VALUE, old_color_clear_value);
6076 glClearColor(D3DCOLOR_R(Color),
6080 checkGLcall("glClearColor");
6082 /* Clear ALL colors! */
6083 glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
6084 glMask = glMask | GL_COLOR_BUFFER_BIT;
6087 /* Now process each rect in turn */
6088 for (i = 0; i < Count || i == 0; i++) {
6091 /* Note gl uses lower left, width/height */
6092 TRACE("(%p) %p Rect=(%d,%d)->(%d,%d) glRect=(%d,%d), len=%d, hei=%d\n", This, curRect,
6093 curRect->x1, curRect->y1, curRect->x2, curRect->y2,
6094 curRect->x1, (((IWineD3DSurfaceImpl *)This->renderTarget)->currentDesc.Height - curRect->y2),
6095 curRect->x2 - curRect->x1, curRect->y2 - curRect->y1);
6096 glScissor(curRect->x1, (((IWineD3DSurfaceImpl *)This->renderTarget)->currentDesc.Height - curRect->y2),
6097 curRect->x2 - curRect->x1, curRect->y2 - curRect->y1);
6098 checkGLcall("glScissor");
6100 glScissor(This->stateBlock->viewport.X,
6101 (((IWineD3DSurfaceImpl *)This->renderTarget)->currentDesc.Height -
6102 (This->stateBlock->viewport.Y + This->stateBlock->viewport.Height)),
6103 This->stateBlock->viewport.Width,
6104 This->stateBlock->viewport.Height);
6105 checkGLcall("glScissor");
6108 /* Clear the selected rectangle (or full screen) */
6110 checkGLcall("glClear");
6112 /* Step to the next rectangle */
6113 if (curRect) curRect = curRect + sizeof(D3DRECT);
6116 /* Restore the old values (why..?) */
6117 if (Flags & D3DCLEAR_STENCIL) {
6118 glClearStencil(old_stencil_clear_value);
6119 glStencilMask(This->stateBlock->renderState[WINED3DRS_STENCILWRITEMASK]);
6121 if (Flags & D3DCLEAR_ZBUFFER) {
6122 glDepthMask(old_ztest);
6123 glClearDepth(old_z_clear_value);
6125 if (Flags & D3DCLEAR_TARGET) {
6126 glClearColor(old_color_clear_value[0],
6127 old_color_clear_value[1],
6128 old_color_clear_value[2],
6129 old_color_clear_value[3]);
6130 glColorMask(This->stateBlock->renderState[WINED3DRS_COLORWRITEENABLE] & D3DCOLORWRITEENABLE_RED ? GL_TRUE : GL_FALSE,
6131 This->stateBlock->renderState[WINED3DRS_COLORWRITEENABLE] & D3DCOLORWRITEENABLE_GREEN ? GL_TRUE : GL_FALSE,
6132 This->stateBlock->renderState[WINED3DRS_COLORWRITEENABLE] & D3DCOLORWRITEENABLE_BLUE ? GL_TRUE : GL_FALSE,
6133 This->stateBlock->renderState[WINED3DRS_COLORWRITEENABLE] & D3DCOLORWRITEENABLE_ALPHA ? GL_TRUE : GL_FALSE);
6136 glDisable(GL_SCISSOR_TEST);
6137 checkGLcall("glDisable");
6146 static HRESULT WINAPI IWineD3DDeviceImpl_DrawPrimitive(IWineD3DDevice *iface, D3DPRIMITIVETYPE PrimitiveType, UINT StartVertex,
6147 UINT PrimitiveCount) {
6149 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
6150 This->stateBlock->streamIsUP = FALSE;
6152 TRACE("(%p) : Type=(%d,%s), Start=%d, Count=%d\n", This, PrimitiveType,
6153 debug_d3dprimitivetype(PrimitiveType),
6154 StartVertex, PrimitiveCount);
6155 drawPrimitive(iface, PrimitiveType, PrimitiveCount, StartVertex, 0/* NumVertices */, -1 /* indxStart */,
6156 0 /* indxSize */, NULL /* indxData */, 0 /* minIndex */, NULL);
6162 /* TODO: baseVIndex needs to be provided from This->stateBlock->baseVertexIndex when called from d3d8 */
6163 static HRESULT WINAPI IWineD3DDeviceImpl_DrawIndexedPrimitive(IWineD3DDevice *iface,
6164 D3DPRIMITIVETYPE PrimitiveType,
6165 INT baseVIndex, UINT minIndex,
6166 UINT NumVertices, UINT startIndex, UINT primCount) {
6168 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
6170 IWineD3DIndexBuffer *pIB;
6171 WINED3DINDEXBUFFER_DESC IdxBufDsc;
6173 pIB = This->stateBlock->pIndexData;
6174 This->stateBlock->streamIsUP = FALSE;
6176 TRACE("(%p) : Type=(%d,%s), min=%d, CountV=%d, startIdx=%d, baseVidx=%d, countP=%d\n", This,
6177 PrimitiveType, debug_d3dprimitivetype(PrimitiveType),
6178 minIndex, NumVertices, startIndex, baseVIndex, primCount);
6180 IWineD3DIndexBuffer_GetDesc(pIB, &IdxBufDsc);
6181 if (IdxBufDsc.Format == WINED3DFMT_INDEX16) {
6187 drawPrimitive(iface, PrimitiveType, primCount, baseVIndex, NumVertices, startIndex,
6188 idxStride, ((IWineD3DIndexBufferImpl *) pIB)->resource.allocatedMemory, minIndex, NULL);
6193 static HRESULT WINAPI IWineD3DDeviceImpl_DrawPrimitiveUP(IWineD3DDevice *iface, D3DPRIMITIVETYPE PrimitiveType,
6194 UINT PrimitiveCount, CONST void* pVertexStreamZeroData,
6195 UINT VertexStreamZeroStride) {
6196 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
6198 TRACE("(%p) : Type=(%d,%s), pCount=%d, pVtxData=%p, Stride=%d\n", This, PrimitiveType,
6199 debug_d3dprimitivetype(PrimitiveType),
6200 PrimitiveCount, pVertexStreamZeroData, VertexStreamZeroStride);
6202 /* release the stream source */
6203 if (This->stateBlock->streamSource[0] != NULL) {
6204 IWineD3DVertexBuffer_Release(This->stateBlock->streamSource[0]);
6207 /* Note in the following, it's not this type, but that's the purpose of streamIsUP */
6208 This->stateBlock->streamSource[0] = (IWineD3DVertexBuffer *)pVertexStreamZeroData;
6209 This->stateBlock->streamStride[0] = VertexStreamZeroStride;
6210 This->stateBlock->streamIsUP = TRUE;
6212 drawPrimitive(iface, PrimitiveType, PrimitiveCount, 0 /* start vertex */, 0 /* NumVertices */,
6213 0 /* indxStart*/, 0 /* indxSize*/, NULL /* indxData */, 0 /* indxMin */, NULL);
6215 /* MSDN specifies stream zero settings must be set to NULL */
6216 This->stateBlock->streamStride[0] = 0;
6217 This->stateBlock->streamSource[0] = NULL;
6219 /*stream zero settings set to null at end, as per the msdn */
6223 static HRESULT WINAPI IWineD3DDeviceImpl_DrawIndexedPrimitiveUP(IWineD3DDevice *iface, D3DPRIMITIVETYPE PrimitiveType,
6224 UINT MinVertexIndex, UINT NumVertices,
6225 UINT PrimitiveCount, CONST void* pIndexData,
6226 WINED3DFORMAT IndexDataFormat,CONST void* pVertexStreamZeroData,
6227 UINT VertexStreamZeroStride) {
6229 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
6231 TRACE("(%p) : Type=(%d,%s), MinVtxIdx=%d, NumVIdx=%d, PCount=%d, pidxdata=%p, IdxFmt=%d, pVtxdata=%p, stride=%d\n",
6232 This, PrimitiveType, debug_d3dprimitivetype(PrimitiveType),
6233 MinVertexIndex, NumVertices, PrimitiveCount, pIndexData,
6234 IndexDataFormat, pVertexStreamZeroData, VertexStreamZeroStride);
6236 if (IndexDataFormat == WINED3DFMT_INDEX16) {
6242 /* release the stream and index data */
6243 if (This->stateBlock->streamSource[0] != NULL) {
6244 IWineD3DVertexBuffer_Release(This->stateBlock->streamSource[0]);
6246 if (This->stateBlock->pIndexData) {
6247 IWineD3DIndexBuffer_Release(This->stateBlock->pIndexData);
6250 /* Note in the following, it's not this type, but that's the purpose of streamIsUP */
6251 This->stateBlock->streamSource[0] = (IWineD3DVertexBuffer *)pVertexStreamZeroData;
6252 This->stateBlock->streamIsUP = TRUE;
6253 This->stateBlock->streamStride[0] = VertexStreamZeroStride;
6255 drawPrimitive(iface, PrimitiveType, PrimitiveCount, 0 /* vertexStart */, NumVertices, 0 /* indxStart */, idxStride, pIndexData, MinVertexIndex, NULL);
6257 /* MSDN specifies stream zero settings and index buffer must be set to NULL */
6258 This->stateBlock->streamSource[0] = NULL;
6259 This->stateBlock->streamStride[0] = 0;
6260 This->stateBlock->pIndexData = NULL;
6265 static HRESULT WINAPI IWineD3DDeviceImpl_DrawPrimitiveStrided (IWineD3DDevice *iface, D3DPRIMITIVETYPE PrimitiveType, UINT PrimitiveCount, WineDirect3DVertexStridedData *DrawPrimStrideData) {
6267 drawPrimitive(iface, PrimitiveType, PrimitiveCount, 0, 0, 0, 0, NULL, 0, DrawPrimStrideData);
6270 /* Yet another way to update a texture, some apps use this to load default textures instead of using surface/texture lock/unlock */
6271 static HRESULT WINAPI IWineD3DDeviceImpl_UpdateTexture (IWineD3DDevice *iface, IWineD3DBaseTexture *pSourceTexture, IWineD3DBaseTexture *pDestinationTexture){
6272 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
6273 HRESULT hr = WINED3D_OK;
6274 WINED3DRESOURCETYPE sourceType;
6275 WINED3DRESOURCETYPE destinationType;
6278 /* TODO: think about moving the code into IWineD3DBaseTexture */
6280 TRACE("(%p) Source %p Destination %p\n", This, pSourceTexture, pDestinationTexture);
6282 /* verify that the source and destination textures aren't NULL */
6283 if (NULL == pSourceTexture || NULL == pDestinationTexture) {
6284 WARN("(%p) : source (%p) and destination (%p) textures must not be NULL, returning WINED3DERR_INVALIDCALL\n",
6285 This, pSourceTexture, pDestinationTexture);
6286 hr = WINED3DERR_INVALIDCALL;
6289 if (pSourceTexture == pDestinationTexture) {
6290 WARN("(%p) : source (%p) and destination (%p) textures must be different, returning WINED3DERR_INVALIDCALL\n",
6291 This, pSourceTexture, pDestinationTexture);
6292 hr = WINED3DERR_INVALIDCALL;
6294 /* Verify that the source and destination textures are the same type */
6295 sourceType = IWineD3DBaseTexture_GetType(pSourceTexture);
6296 destinationType = IWineD3DBaseTexture_GetType(pDestinationTexture);
6298 if (sourceType != destinationType) {
6299 WARN("(%p) Sorce and destination types must match, returning WINED3DERR_INVALIDCALL\n",
6301 hr = WINED3DERR_INVALIDCALL;
6304 /* check that both textures have the identical numbers of levels */
6305 if (IWineD3DBaseTexture_GetLevelCount(pDestinationTexture) != IWineD3DBaseTexture_GetLevelCount(pSourceTexture)) {
6306 WARN("(%p) : source (%p) and destination (%p) textures must have identicle numbers of levels, returning WINED3DERR_INVALIDCALL\n", This, pSourceTexture, pDestinationTexture);
6307 hr = WINED3DERR_INVALIDCALL;
6310 if (WINED3D_OK == hr) {
6312 /* Make sure that the destination texture is loaded */
6313 IWineD3DBaseTexture_PreLoad(pDestinationTexture);
6315 /* Update every surface level of the texture */
6316 levels = IWineD3DBaseTexture_GetLevelCount(pDestinationTexture);
6318 switch (sourceType) {
6319 case WINED3DRTYPE_TEXTURE:
6321 IWineD3DSurface *srcSurface;
6322 IWineD3DSurface *destSurface;
6324 for (i = 0 ; i < levels ; ++i) {
6325 IWineD3DTexture_GetSurfaceLevel((IWineD3DTexture *)pSourceTexture, i, &srcSurface);
6326 IWineD3DTexture_GetSurfaceLevel((IWineD3DTexture *)pDestinationTexture, i, &destSurface);
6327 hr = IWineD3DDevice_UpdateSurface(iface, srcSurface, NULL, destSurface, NULL);
6328 IWineD3DSurface_Release(srcSurface);
6329 IWineD3DSurface_Release(destSurface);
6330 if (WINED3D_OK != hr) {
6331 WARN("(%p) : Call to update surface failed\n", This);
6337 case WINED3DRTYPE_CUBETEXTURE:
6339 IWineD3DSurface *srcSurface;
6340 IWineD3DSurface *destSurface;
6341 WINED3DCUBEMAP_FACES faceType;
6343 for (i = 0 ; i < levels ; ++i) {
6344 /* Update each cube face */
6345 for (faceType = D3DCUBEMAP_FACE_POSITIVE_X; faceType <= D3DCUBEMAP_FACE_NEGATIVE_Z; ++faceType){
6346 hr = IWineD3DCubeTexture_GetCubeMapSurface((IWineD3DCubeTexture *)pSourceTexture, faceType, i, &srcSurface);
6347 if (WINED3D_OK != hr) {
6348 FIXME("(%p) : Failed to get src cube surface facetype %d, level %d\n", This, faceType, i);
6350 TRACE("Got srcSurface %p\n", srcSurface);
6352 hr = IWineD3DCubeTexture_GetCubeMapSurface((IWineD3DCubeTexture *)pDestinationTexture, faceType, i, &destSurface);
6353 if (WINED3D_OK != hr) {
6354 FIXME("(%p) : Failed to get src cube surface facetype %d, level %d\n", This, faceType, i);
6356 TRACE("Got desrSurface %p\n", destSurface);
6358 hr = IWineD3DDevice_UpdateSurface(iface, srcSurface, NULL, destSurface, NULL);
6359 IWineD3DSurface_Release(srcSurface);
6360 IWineD3DSurface_Release(destSurface);
6361 if (WINED3D_OK != hr) {
6362 WARN("(%p) : Call to update surface failed\n", This);
6369 #if 0 /* TODO: Add support for volume textures */
6370 case WINED3DRTYPE_VOLUMETEXTURE:
6372 IWineD3DVolume srcVolume = NULL;
6373 IWineD3DSurface destVolume = NULL;
6375 for (i = 0 ; i < levels ; ++i) {
6376 IWineD3DVolumeTexture_GetVolume((IWineD3DVolumeTexture *)pSourceTexture, i, &srcVolume);
6377 IWineD3DVolumeTexture_GetVolume((IWineD3DVolumeTexture *)pDestinationTexture, i, &destVolume);
6378 hr = IWineD3DFoo_UpdateVolume(iface, srcVolume, NULL, destVolume, NULL);
6379 IWineD3DVolume_Release(srcSurface);
6380 IWineD3DVolume_Release(destSurface);
6381 if (WINED3D_OK != hr) {
6382 WARN("(%p) : Call to update volume failed\n", This);
6390 FIXME("(%p) : Unsupported source and destination type\n", This);
6391 hr = WINED3DERR_INVALIDCALL;
6398 static HRESULT WINAPI IWineD3DDeviceImpl_StretchRect(IWineD3DDevice *iface, IWineD3DSurface *pSourceSurface,
6399 CONST RECT* pSourceRect, IWineD3DSurface *pDestinationSurface,
6400 CONST RECT* pDestRect, WINED3DTEXTUREFILTERTYPE Filter) {
6401 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
6403 TRACE("(%p) : stub\n", This);
6406 static HRESULT WINAPI IWineD3DDeviceImpl_GetRenderTargetData(IWineD3DDevice *iface, IWineD3DSurface *pRenderTarget, IWineD3DSurface *pSurface) {
6407 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
6408 /** TODO: remove remove casts to IWineD3DSurfaceImpl *
6409 * NOTE It may be best to move the code into surface to occomplish this
6410 ****************************************/
6412 WINED3DSURFACE_DESC surfaceDesc;
6413 unsigned int surfaceWidth, surfaceHeight;
6414 glDescriptor *targetGlDescription = NULL;
6415 glDescriptor *surfaceGlDescription = NULL;
6416 IWineD3DSwapChainImpl *container = NULL;
6418 IWineD3DSurface_GetGlDesc(pRenderTarget, &targetGlDescription);
6419 IWineD3DSurface_GetGlDesc(pSurface, &surfaceGlDescription);
6420 memset(&surfaceDesc, 0, sizeof(surfaceDesc));
6422 surfaceDesc.Width = &surfaceWidth;
6423 surfaceDesc.Height = &surfaceHeight;
6424 IWineD3DSurface_GetDesc(pSurface, &surfaceDesc);
6425 /* check to see if it's the backbuffer or the frontbuffer being requested (to make sure the data is up to date)*/
6427 /* Ok, I may need to setup some kind of active swapchain reference on the device */
6428 IWineD3DSurface_GetContainer(pRenderTarget, &IID_IWineD3DSwapChain, (void **)&container);
6430 /* TODO: opengl Context switching for swapchains etc... */
6431 if (NULL != container || pRenderTarget == This->renderTarget || pRenderTarget == This->depthStencilBuffer) {
6432 if (NULL != container && (pRenderTarget == container->backBuffer[0])) {
6433 glReadBuffer(GL_BACK);
6434 vcheckGLcall("glReadBuffer(GL_BACK)");
6435 } else if ((NULL != container && (pRenderTarget == container->frontBuffer)) || (pRenderTarget == This->renderTarget)) {
6436 glReadBuffer(GL_FRONT);
6437 vcheckGLcall("glReadBuffer(GL_FRONT)");
6438 } else if (pRenderTarget == This->depthStencilBuffer) {
6439 FIXME("Reading of depthstencil not yet supported\n");
6442 glReadPixels(surfaceGlDescription->target,
6443 surfaceGlDescription->level,
6446 surfaceGlDescription->glFormat,
6447 surfaceGlDescription->glType,
6448 (void *)IWineD3DSurface_GetData(pSurface));
6449 vcheckGLcall("glReadPixels(...)");
6450 if(NULL != container ){
6451 IWineD3DSwapChain_Release((IWineD3DSwapChain*) container);
6454 IWineD3DBaseTexture *container;
6455 GLenum textureDimensions = GL_TEXTURE_2D;
6457 if (WINED3D_OK == IWineD3DSurface_GetContainer(pSurface, &IID_IWineD3DBaseTexture, (void **)&container)) {
6458 textureDimensions = IWineD3DBaseTexture_GetTextureDimensions(container);
6459 IWineD3DBaseTexture_Release(container);
6461 /* TODO: 2D -> Cube surface coppies etc.. */
6462 if (surfaceGlDescription->target != textureDimensions) {
6463 FIXME("(%p) : Texture dimension mismatch\n", This);
6465 glEnable(textureDimensions);
6466 vcheckGLcall("glEnable(GL_TEXTURE_...)");
6467 /* FIXME: this isn't correct, it need to add a dirty rect if nothing else... */
6468 glBindTexture(targetGlDescription->target, targetGlDescription->textureName);
6469 vcheckGLcall("glBindTexture");
6470 glGetTexImage(surfaceGlDescription->target,
6471 surfaceGlDescription->level,
6472 surfaceGlDescription->glFormat,
6473 surfaceGlDescription->glType,
6474 (void *)IWineD3DSurface_GetData(pSurface));
6475 glDisable(textureDimensions);
6476 vcheckGLcall("glDisable(GL_TEXTURE_...)");
6483 static HRESULT WINAPI IWineD3DDeviceImpl_GetFrontBufferData(IWineD3DDevice *iface,UINT iSwapChain, IWineD3DSurface *pDestSurface) {
6484 IWineD3DSwapChain *swapChain;
6486 hr = IWineD3DDeviceImpl_GetSwapChain(iface, iSwapChain, (IWineD3DSwapChain **)&swapChain);
6487 if(hr == WINED3D_OK) {
6488 hr = IWineD3DSwapChain_GetFrontBufferData(swapChain, pDestSurface);
6489 IWineD3DSwapChain_Release(swapChain);
6494 static HRESULT WINAPI IWineD3DDeviceImpl_ValidateDevice(IWineD3DDevice *iface, DWORD* pNumPasses) {
6495 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
6496 /* return a sensible default */
6498 /* TODO: If the window is minimized then validate device should return something other than WINED3D_OK */
6499 FIXME("(%p) : stub\n", This);
6503 static HRESULT WINAPI IWineD3DDeviceImpl_SetPaletteEntries(IWineD3DDevice *iface, UINT PaletteNumber, CONST PALETTEENTRY* pEntries) {
6504 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
6506 TRACE("(%p) : PaletteNumber %u\n", This, PaletteNumber);
6507 if ( PaletteNumber < 0 || PaletteNumber >= MAX_PALETTES) {
6508 WARN("(%p) : (%u) Out of range 0-%u, returning Invalid Call\n", This, PaletteNumber, MAX_PALETTES);
6509 return WINED3DERR_INVALIDCALL;
6511 for (j = 0; j < 256; ++j) {
6512 This->palettes[PaletteNumber][j].peRed = pEntries[j].peRed;
6513 This->palettes[PaletteNumber][j].peGreen = pEntries[j].peGreen;
6514 This->palettes[PaletteNumber][j].peBlue = pEntries[j].peBlue;
6515 This->palettes[PaletteNumber][j].peFlags = pEntries[j].peFlags;
6517 TRACE("(%p) : returning\n", This);
6521 static HRESULT WINAPI IWineD3DDeviceImpl_GetPaletteEntries(IWineD3DDevice *iface, UINT PaletteNumber, PALETTEENTRY* pEntries) {
6522 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
6524 TRACE("(%p) : PaletteNumber %u\n", This, PaletteNumber);
6525 if ( PaletteNumber < 0 || PaletteNumber >= MAX_PALETTES) {
6526 WARN("(%p) : (%u) Out of range 0-%u, returning Invalid Call\n", This, PaletteNumber, MAX_PALETTES);
6527 return WINED3DERR_INVALIDCALL;
6529 for (j = 0; j < 256; ++j) {
6530 pEntries[j].peRed = This->palettes[PaletteNumber][j].peRed;
6531 pEntries[j].peGreen = This->palettes[PaletteNumber][j].peGreen;
6532 pEntries[j].peBlue = This->palettes[PaletteNumber][j].peBlue;
6533 pEntries[j].peFlags = This->palettes[PaletteNumber][j].peFlags;
6535 TRACE("(%p) : returning\n", This);
6539 static HRESULT WINAPI IWineD3DDeviceImpl_SetCurrentTexturePalette(IWineD3DDevice *iface, UINT PaletteNumber) {
6540 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
6541 TRACE("(%p) : PaletteNumber %u\n", This, PaletteNumber);
6542 if ( PaletteNumber < 0 || PaletteNumber >= MAX_PALETTES) {
6543 WARN("(%p) : (%u) Out of range 0-%u, returning Invalid Call\n", This, PaletteNumber, MAX_PALETTES);
6544 return WINED3DERR_INVALIDCALL;
6546 /*TODO: stateblocks */
6547 This->currentPalette = PaletteNumber;
6548 TRACE("(%p) : returning\n", This);
6552 static HRESULT WINAPI IWineD3DDeviceImpl_GetCurrentTexturePalette(IWineD3DDevice *iface, UINT* PaletteNumber) {
6553 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
6554 if (PaletteNumber == NULL) {
6555 WARN("(%p) : returning Invalid Call\n", This);
6556 return WINED3DERR_INVALIDCALL;
6558 /*TODO: stateblocks */
6559 *PaletteNumber = This->currentPalette;
6560 TRACE("(%p) : returning %u\n", This, *PaletteNumber);
6564 static HRESULT WINAPI IWineD3DDeviceImpl_SetSoftwareVertexProcessing(IWineD3DDevice *iface, BOOL bSoftware) {
6565 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
6566 static BOOL showFixmes = TRUE;
6568 FIXME("(%p) : stub\n", This);
6572 This->softwareVertexProcessing = bSoftware;
6577 static BOOL WINAPI IWineD3DDeviceImpl_GetSoftwareVertexProcessing(IWineD3DDevice *iface) {
6578 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
6579 static BOOL showFixmes = TRUE;
6581 FIXME("(%p) : stub\n", This);
6584 return This->softwareVertexProcessing;
6588 static HRESULT WINAPI IWineD3DDeviceImpl_GetRasterStatus(IWineD3DDevice *iface, UINT iSwapChain, WINED3DRASTER_STATUS* pRasterStatus) {
6589 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
6590 IWineD3DSwapChain *swapChain;
6593 TRACE("(%p) : SwapChain %d returning %p\n", This, iSwapChain, pRasterStatus);
6595 hr = IWineD3DDeviceImpl_GetSwapChain(iface, iSwapChain, (IWineD3DSwapChain **)&swapChain);
6596 if(hr == WINED3D_OK){
6597 hr = IWineD3DSwapChain_GetRasterStatus(swapChain, pRasterStatus);
6598 IWineD3DSwapChain_Release(swapChain);
6600 FIXME("(%p) IWineD3DSwapChain_GetRasterStatus returned in error\n", This);
6606 static HRESULT WINAPI IWineD3DDeviceImpl_SetNPatchMode(IWineD3DDevice *iface, float nSegments) {
6607 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
6608 static BOOL showfixmes = TRUE;
6609 if(nSegments != 0.0f) {
6611 FIXME("(%p) : stub nSegments(%f)\n", This, nSegments);
6618 static float WINAPI IWineD3DDeviceImpl_GetNPatchMode(IWineD3DDevice *iface) {
6619 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
6620 static BOOL showfixmes = TRUE;
6622 FIXME("(%p) : stub returning(%f)\n", This, 0.0f);
6628 static HRESULT WINAPI IWineD3DDeviceImpl_UpdateSurface(IWineD3DDevice *iface, IWineD3DSurface *pSourceSurface, CONST RECT* pSourceRect, IWineD3DSurface *pDestinationSurface, CONST POINT* pDestPoint) {
6629 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *) iface;
6630 /** TODO: remove casts to IWineD3DSurfaceImpl
6631 * NOTE: move code to surface to accomplish this
6632 ****************************************/
6633 IWineD3DSurfaceImpl *pSrcSurface = (IWineD3DSurfaceImpl *)pSourceSurface;
6634 int srcWidth, srcHeight;
6635 unsigned int srcSurfaceWidth, srcSurfaceHeight, destSurfaceWidth, destSurfaceHeight;
6636 WINED3DFORMAT destFormat, srcFormat;
6638 int destLeft, destTop;
6639 WINED3DPOOL srcPool, destPool;
6641 int rowoffset = 0; /* how many bytes to add onto the end of a row to wraparound to the beginning of the next */
6642 glDescriptor *glDescription = NULL;
6643 GLenum textureDimensions = GL_TEXTURE_2D;
6644 IWineD3DBaseTexture *baseTexture;
6646 WINED3DSURFACE_DESC winedesc;
6648 TRACE("(%p) : Source (%p) Rect (%p) Destination (%p) Point(%p)\n", This, pSourceSurface, pSourceRect, pDestinationSurface, pDestPoint);
6649 memset(&winedesc, 0, sizeof(winedesc));
6650 winedesc.Width = &srcSurfaceWidth;
6651 winedesc.Height = &srcSurfaceHeight;
6652 winedesc.Pool = &srcPool;
6653 winedesc.Format = &srcFormat;
6655 IWineD3DSurface_GetDesc(pSourceSurface, &winedesc);
6657 winedesc.Width = &destSurfaceWidth;
6658 winedesc.Height = &destSurfaceHeight;
6659 winedesc.Pool = &destPool;
6660 winedesc.Format = &destFormat;
6661 winedesc.Size = &destSize;
6663 IWineD3DSurface_GetDesc(pDestinationSurface, &winedesc);
6665 if(srcPool != WINED3DPOOL_SYSTEMMEM || destPool != WINED3DPOOL_DEFAULT){
6666 WARN("source %p must be SYSTEMMEM and dest %p must be DEFAULT, returning WINED3DERR_INVALIDCALL\n", pSourceSurface, pDestinationSurface);
6667 return WINED3DERR_INVALIDCALL;
6670 if (destFormat == WINED3DFMT_UNKNOWN) {
6671 TRACE("(%p) : Converting destination surface from WINED3DFMT_UNKNOWN to the source format\n", This);
6672 IWineD3DSurface_SetFormat(pDestinationSurface, srcFormat);
6674 /* Get the update surface description */
6675 IWineD3DSurface_GetDesc(pDestinationSurface, &winedesc);
6678 /* Make sure the surface is loaded and up to date */
6679 IWineD3DSurface_PreLoad(pDestinationSurface);
6681 IWineD3DSurface_GetGlDesc(pDestinationSurface, &glDescription);
6685 /* this needs to be done in lines if the sourceRect != the sourceWidth */
6686 srcWidth = pSourceRect ? pSourceRect->right - pSourceRect->left : srcSurfaceWidth;
6687 srcHeight = pSourceRect ? pSourceRect->top - pSourceRect->bottom : srcSurfaceHeight;
6688 destLeft = pDestPoint ? pDestPoint->x : 0;
6689 destTop = pDestPoint ? pDestPoint->y : 0;
6692 /* This function doesn't support compressed textures
6693 the pitch is just bytesPerPixel * width */
6694 if(srcWidth != srcSurfaceWidth || (pSourceRect != NULL && pSourceRect->left != 0) ){
6695 rowoffset = (srcSurfaceWidth - srcWidth) * pSrcSurface->bytesPerPixel;
6696 offset += pSourceRect->left * pSrcSurface->bytesPerPixel;
6697 /* TODO: do we ever get 3bpp?, would a shift and an add be quicker than a mul (well maybe a cycle or two) */
6699 /* TODO DXT formats */
6701 if(pSourceRect != NULL && pSourceRect->top != 0){
6702 offset += pSourceRect->top * srcWidth * pSrcSurface->bytesPerPixel;
6704 TRACE("(%p) glTexSubImage2D, Level %d, left %d, top %d, width %d, height %d , ftm %d, type %d, memory %p\n"
6706 ,glDescription->level
6711 ,glDescription->glFormat
6712 ,glDescription->glType
6713 ,IWineD3DSurface_GetData(pSourceSurface)
6717 if (IWineD3DSurface_GetData(pSourceSurface) == NULL) {
6719 /* need to lock the surface to get the data */
6720 FIXME("Surfaces has no allocated memory, but should be an in memory only surface\n");
6723 /* TODO: Cube and volume support */
6725 /* not a whole row so we have to do it a line at a time */
6728 /* hopefully using pointer addtion will be quicker than using a point + j * rowoffset */
6729 unsigned char* data =((unsigned char *)IWineD3DSurface_GetData(pSourceSurface)) + offset;
6731 for(j = destTop ; j < (srcHeight + destTop) ; j++){
6733 glTexSubImage2D(glDescription->target
6734 ,glDescription->level
6739 ,glDescription->glFormat
6740 ,glDescription->glType
6741 ,data /* could be quicker using */
6746 } else { /* Full width, so just write out the whole texture */
6748 if (WINED3DFMT_DXT1 == destFormat ||
6749 WINED3DFMT_DXT2 == destFormat ||
6750 WINED3DFMT_DXT3 == destFormat ||
6751 WINED3DFMT_DXT4 == destFormat ||
6752 WINED3DFMT_DXT5 == destFormat) {
6753 if (GL_SUPPORT(EXT_TEXTURE_COMPRESSION_S3TC)) {
6754 if (destSurfaceHeight != srcHeight || destSurfaceWidth != srcWidth) {
6755 /* FIXME: The easy way to do this is lock the destination, and copy the bits accross */
6756 FIXME("Updating part of a compressed texture is not supported at the moment\n");
6757 } if (destFormat != srcFormat) {
6758 FIXME("Updating mixed format compressed texture is not curretly support\n");
6760 GL_EXTCALL(glCompressedTexImage2DARB)(glDescription->target,
6761 glDescription->level,
6762 glDescription->glFormatInternal,
6767 IWineD3DSurface_GetData(pSourceSurface));
6770 FIXME("Attempting to update a DXT compressed texture without hardware support\n");
6775 if (NP2_REPACK == wined3d_settings.nonpower2_mode) {
6777 /* some applications cannot handle odd pitches returned by soft non-power2, so we have
6778 to repack the data from pow2Width/Height to expected Width,Height, this makes the
6779 data returned by GetData non-power2 width/height with hardware non-power2
6780 pow2Width/height are set to surface width height, repacking isn't needed so it
6781 doesn't matter which function gets called. */
6782 glTexSubImage2D(glDescription->target
6783 ,glDescription->level
6788 ,glDescription->glFormat
6789 ,glDescription->glType
6790 ,IWineD3DSurface_GetData(pSourceSurface)
6794 /* not repacked, the data returned by IWineD3DSurface_GetData is pow2Width x pow2Height */
6795 glTexSubImage2D(glDescription->target
6796 ,glDescription->level
6799 ,((IWineD3DSurfaceImpl *)pSourceSurface)->pow2Width
6800 ,((IWineD3DSurfaceImpl *)pSourceSurface)->pow2Height
6801 ,glDescription->glFormat
6802 ,glDescription->glType
6803 ,IWineD3DSurface_GetData(pSourceSurface)
6809 checkGLcall("glTexSubImage2D");
6810 ((IWineD3DSurfaceImpl *)pDestinationSurface)->Flags |= SFLAG_GLDIRTY;
6812 /* I only need to look up baseTexture here, so it may be a good idea to hava a GL_TARGET ->
6813 * GL_DIMENSIONS lookup, or maybe store the dimensions on the surface (but that's making the
6814 * surface bigger than it needs to be hmm.. */
6815 if (WINED3D_OK == IWineD3DSurface_GetContainer(pDestinationSurface, &IID_IWineD3DBaseTexture, (void **)&baseTexture)) {
6816 textureDimensions = IWineD3DBaseTexture_GetTextureDimensions(baseTexture);
6817 IWineD3DBaseTexture_Release(baseTexture);
6820 glDisable(textureDimensions); /* This needs to be managed better.... */
6826 /* Used by DirectX 8 */
6827 static HRESULT WINAPI IWineD3DDeviceImpl_CopyRects(IWineD3DDevice *iface,
6828 IWineD3DSurface* pSourceSurface, CONST RECT* pSourceRectsArray, UINT cRects,
6829 IWineD3DSurface* pDestinationSurface, CONST POINT* pDestPointsArray) {
6831 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
6832 HRESULT hr = WINED3D_OK;
6833 WINED3DFORMAT srcFormat, destFormat;
6834 UINT srcWidth, destWidth;
6835 UINT srcHeight, destHeight;
6837 WINED3DSURFACE_DESC winedesc;
6839 TRACE("(%p) pSrcSur=%p, pSourceRects=%p, cRects=%d, pDstSur=%p, pDestPtsArr=%p\n", This,
6840 pSourceSurface, pSourceRectsArray, cRects, pDestinationSurface, pDestPointsArray);
6843 /* Check that the source texture is in WINED3DPOOL_SYSTEMMEM and the destination texture is in WINED3DPOOL_DEFAULT */
6844 memset(&winedesc, 0, sizeof(winedesc));
6846 winedesc.Format = &srcFormat;
6847 winedesc.Width = &srcWidth;
6848 winedesc.Height = &srcHeight;
6849 winedesc.Size = &srcSize;
6850 IWineD3DSurface_GetDesc(pSourceSurface, &winedesc);
6852 winedesc.Format = &destFormat;
6853 winedesc.Width = &destWidth;
6854 winedesc.Height = &destHeight;
6855 winedesc.Size = NULL;
6856 IWineD3DSurface_GetDesc(pDestinationSurface, &winedesc);
6858 /* Check that the source and destination formats match */
6859 if (srcFormat != destFormat && WINED3DFMT_UNKNOWN != destFormat) {
6860 WARN("(%p) source %p format must match the dest %p format, returning WINED3DERR_INVALIDCALL\n", This, pSourceSurface, pDestinationSurface);
6861 return WINED3DERR_INVALIDCALL;
6862 } else if (WINED3DFMT_UNKNOWN == destFormat) {
6863 TRACE("(%p) : Converting destination surface from WINED3DFMT_UNKNOWN to the source format\n", This);
6864 IWineD3DSurface_SetFormat(pDestinationSurface, srcFormat);
6865 destFormat = srcFormat;
6868 /* Quick if complete copy ... */
6869 if (cRects == 0 && pSourceRectsArray == NULL && pDestPointsArray == NULL) {
6871 if (srcWidth == destWidth && srcHeight == destHeight) {
6872 WINED3DLOCKED_RECT lrSrc;
6873 WINED3DLOCKED_RECT lrDst;
6874 IWineD3DSurface_LockRect(pSourceSurface, &lrSrc, NULL, WINED3DLOCK_READONLY);
6875 IWineD3DSurface_LockRect(pDestinationSurface, &lrDst, NULL, 0L);
6876 TRACE("Locked src and dst, Direct copy as surfaces are equal, w=%d, h=%d\n", srcWidth, srcHeight);
6878 memcpy(lrDst.pBits, lrSrc.pBits, srcSize);
6880 IWineD3DSurface_UnlockRect(pSourceSurface);
6881 IWineD3DSurface_UnlockRect(pDestinationSurface);
6882 TRACE("Unlocked src and dst\n");
6886 FIXME("Wanted to copy all surfaces but size not compatible, returning WINED3DERR_INVALIDCALL\n");
6887 hr = WINED3DERR_INVALIDCALL;
6892 if (NULL != pSourceRectsArray && NULL != pDestPointsArray) {
6894 int bytesPerPixel = ((IWineD3DSurfaceImpl *) pSourceSurface)->bytesPerPixel;
6897 /* Copy rect by rect */
6898 for (i = 0; i < cRects; ++i) {
6899 CONST RECT* r = &pSourceRectsArray[i];
6900 CONST POINT* p = &pDestPointsArray[i];
6903 WINED3DLOCKED_RECT lrSrc;
6904 WINED3DLOCKED_RECT lrDst;
6907 TRACE("Copying rect %d (%d,%d),(%d,%d) -> (%d,%d)\n", i, r->left, r->top, r->right, r->bottom, p->x, p->y);
6908 if (srcFormat == WINED3DFMT_DXT1) {
6909 copyperline = ((r->right - r->left) * bytesPerPixel) / 2; /* DXT1 is half byte per pixel */
6911 copyperline = ((r->right - r->left) * bytesPerPixel);
6914 IWineD3DSurface_LockRect(pSourceSurface, &lrSrc, r, WINED3DLOCK_READONLY);
6915 dest_rect.left = p->x;
6916 dest_rect.top = p->y;
6917 dest_rect.right = p->x + (r->right - r->left);
6918 dest_rect.bottom= p->y + (r->bottom - r->top);
6919 IWineD3DSurface_LockRect(pDestinationSurface, &lrDst, &dest_rect, 0L);
6920 TRACE("Locked src and dst\n");
6922 /* Find where to start */
6923 for (j = 0; j < (r->bottom - r->top - 1); ++j) {
6924 memcpy((char*) lrDst.pBits + (j * lrDst.Pitch), (char*) lrSrc.pBits + (j * lrSrc.Pitch), copyperline);
6926 IWineD3DSurface_UnlockRect(pSourceSurface);
6927 IWineD3DSurface_UnlockRect(pDestinationSurface);
6928 TRACE("Unlocked src and dst\n");
6932 int bytesPerPixel = ((IWineD3DSurfaceImpl *) pSourceSurface)->bytesPerPixel;
6935 WINED3DLOCKED_RECT lrSrc;
6936 WINED3DLOCKED_RECT lrDst;
6939 for(i=0; i < cRects; i++) {
6940 CONST RECT* r = &pSourceRectsArray[i];
6942 TRACE("Copying rect %d (%d,%d),(%d,%d) -> (0, 0)\n", i, r->left, r->top, r->right, r->bottom);
6943 if (srcFormat == WINED3DFMT_DXT1) {
6944 copyperline = ((r->right - r->left) * bytesPerPixel) / 2; /* DXT1 is half byte per pixel */
6946 copyperline = ((r->right - r->left) * bytesPerPixel);
6948 IWineD3DSurface_LockRect(pSourceSurface, &lrSrc, r, WINED3DLOCK_READONLY);
6951 dest_rect.right = r->right - r->left;
6952 dest_rect.bottom= r->bottom - r->top;
6953 IWineD3DSurface_LockRect(pDestinationSurface, &lrDst, &dest_rect, 0L);
6954 TRACE("Locked src and dst\n");
6955 /* Find where to start */
6956 for (j = 0; j < (r->bottom - r->top - 1); ++j) {
6957 memcpy((char*) lrDst.pBits + (j * lrDst.Pitch), (char*) lrSrc.pBits + (j * lrSrc.Pitch), copyperline);
6959 IWineD3DSurface_UnlockRect(pSourceSurface);
6960 IWineD3DSurface_UnlockRect(pDestinationSurface);
6961 TRACE("Unlocked src and dst\n");
6969 /* Implementation details at http://developer.nvidia.com/attach/6494
6971 http://oss.sgi.com/projects/ogl-sample/registry/NV/evaluators.txt
6972 hmm.. no longer supported use
6973 OpenGL evaluators or tessellate surfaces within your application.
6976 /* http://msdn.microsoft.com/library/default.asp?url=/library/en-us/directx9_c/directx/graphics/reference/d3d/interfaces/idirect3ddevice9/DrawRectPatch.asp */
6977 static HRESULT WINAPI IWineD3DDeviceImpl_DrawRectPatch(IWineD3DDevice *iface, UINT Handle, CONST float* pNumSegs, CONST WINED3DRECTPATCH_INFO* pRectPatchInfo) {
6978 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
6979 TRACE("(%p) Handle(%d) noSegs(%p) rectpatch(%p)\n", This, Handle, pNumSegs, pRectPatchInfo);
6980 FIXME("(%p) : Stub\n", This);
6985 /* http://msdn.microsoft.com/library/default.asp?url=/library/en-us/directx9_c/directx/graphics/reference/d3d/interfaces/idirect3ddevice9/DrawTriPatch.asp */
6986 static HRESULT WINAPI IWineD3DDeviceImpl_DrawTriPatch(IWineD3DDevice *iface, UINT Handle, CONST float* pNumSegs, CONST WINED3DTRIPATCH_INFO* pTriPatchInfo) {
6987 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
6988 TRACE("(%p) Handle(%d) noSegs(%p) tripatch(%p)\n", This, Handle, pNumSegs, pTriPatchInfo);
6989 FIXME("(%p) : Stub\n", This);
6993 static HRESULT WINAPI IWineD3DDeviceImpl_DeletePatch(IWineD3DDevice *iface, UINT Handle) {
6994 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
6995 TRACE("(%p) Handle(%d)\n", This, Handle);
6996 FIXME("(%p) : Stub\n", This);
7000 static HRESULT WINAPI IWineD3DDeviceImpl_ColorFill(IWineD3DDevice *iface, IWineD3DSurface *pSurface, CONST D3DRECT* pRect, D3DCOLOR color) {
7001 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *) iface;
7002 IWineD3DSurfaceImpl *surface = (IWineD3DSurfaceImpl *) pSurface;
7004 TRACE("(%p) Colour fill Surface: %p rect: %p color: %d\n", This, pSurface, pRect, color);
7006 if (surface->resource.pool != WINED3DPOOL_DEFAULT && surface->resource.pool != WINED3DPOOL_SYSTEMMEM) {
7007 FIXME("call to colorfill with non WINED3DPOOL_DEFAULT or WINED3DPOOL_SYSTEMMEM surface\n");
7008 return WINED3DERR_INVALIDCALL;
7011 /* Just forward this to the DirectDraw blitting engine */
7012 memset(&BltFx, 0, sizeof(BltFx));
7013 BltFx.dwSize = sizeof(BltFx);
7014 BltFx.u5.dwFillColor = color;
7015 return IWineD3DSurface_Blt(pSurface, (RECT *) pRect, NULL, NULL, DDBLT_COLORFILL, &BltFx);
7018 /* rendertarget and deptth stencil functions */
7019 static HRESULT WINAPI IWineD3DDeviceImpl_GetRenderTarget(IWineD3DDevice* iface,DWORD RenderTargetIndex, IWineD3DSurface **ppRenderTarget) {
7020 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
7022 /* FIXME: Implelent RenderTargetIndex >0 */
7023 if(RenderTargetIndex > 0)
7024 FIXME("(%p) : RenderTargetIndex %d >0 not currently supported\n", This, RenderTargetIndex);
7026 *ppRenderTarget = This->renderTarget;
7027 TRACE("(%p) : RenderTarget %d Index returning %p\n", This, RenderTargetIndex, *ppRenderTarget);
7028 /* Note inc ref on returned surface */
7029 if(*ppRenderTarget != NULL)
7030 IWineD3DSurface_AddRef(*ppRenderTarget);
7034 static HRESULT WINAPI IWineD3DDeviceImpl_SetFrontBackBuffers(IWineD3DDevice *iface, IWineD3DSurface *Front, IWineD3DSurface *Back) {
7035 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
7036 IWineD3DSurfaceImpl *FrontImpl = (IWineD3DSurfaceImpl *) Front;
7037 IWineD3DSurfaceImpl *BackImpl = (IWineD3DSurfaceImpl *) Back;
7038 IWineD3DSwapChainImpl *Swapchain;
7041 TRACE("(%p)->(%p,%p)\n", This, FrontImpl, BackImpl);
7043 hr = IWineD3DDevice_GetSwapChain(iface, 0, (IWineD3DSwapChain **) &Swapchain);
7044 if(hr != WINED3D_OK) {
7045 ERR("Can't get the swapchain\n");
7049 /* Make sure to release the swapchain */
7050 IWineD3DSwapChain_Release((IWineD3DSwapChain *) Swapchain);
7052 if(FrontImpl && !(FrontImpl->resource.usage & WINED3DUSAGE_RENDERTARGET) ) {
7053 ERR("Trying to set a front buffer which doesn't have WINED3DUSAGE_RENDERTARGET usage\n");
7054 return WINED3DERR_INVALIDCALL;
7056 else if(BackImpl && !(BackImpl->resource.usage & WINED3DUSAGE_RENDERTARGET)) {
7057 ERR("Trying to set a back buffer which doesn't have WINED3DUSAGE_RENDERTARGET usage\n");
7058 return WINED3DERR_INVALIDCALL;
7061 if(Swapchain->frontBuffer != Front) {
7062 TRACE("Changing the front buffer from %p to %p\n", Swapchain->frontBuffer, Front);
7064 if(Swapchain->frontBuffer)
7065 IWineD3DSurface_SetContainer(Swapchain->frontBuffer, NULL);
7066 Swapchain->frontBuffer = Front;
7068 if(Swapchain->frontBuffer) {
7069 IWineD3DSurface_SetContainer(Swapchain->frontBuffer, (IWineD3DBase *) Swapchain);
7073 if(Back && !Swapchain->backBuffer) {
7074 /* We need memory for the back buffer array - only one back buffer this way */
7075 Swapchain->backBuffer = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(IWineD3DSurface *));
7076 if(!Swapchain->backBuffer) {
7077 ERR("Out of memory\n");
7078 return E_OUTOFMEMORY;
7082 if(Swapchain->backBuffer[0] != Back) {
7083 TRACE("Changing the back buffer from %p to %p\n", Swapchain->backBuffer, Back);
7085 if(!Swapchain->backBuffer[0]) {
7086 /* GL was told to draw to the front buffer at creation,
7089 glDrawBuffer(GL_BACK);
7090 checkGLcall("glDrawBuffer(GL_BACK)");
7091 /* Set the backbuffer count to 1 because other code uses it to fing the back buffers */
7092 Swapchain->presentParms.BackBufferCount = 1;
7094 /* That makes problems - disable for now */
7095 /* glDrawBuffer(GL_FRONT); */
7096 checkGLcall("glDrawBuffer(GL_FRONT)");
7097 /* We have lost our back buffer, set this to 0 to avoid confusing other code */
7098 Swapchain->presentParms.BackBufferCount = 0;
7102 if(Swapchain->backBuffer[0])
7103 IWineD3DSurface_SetContainer(Swapchain->backBuffer[0], NULL);
7104 Swapchain->backBuffer[0] = Back;
7106 if(Swapchain->backBuffer[0]) {
7107 IWineD3DSurface_SetContainer(Swapchain->backBuffer[0], (IWineD3DBase *) Swapchain);
7109 HeapFree(GetProcessHeap(), 0, Swapchain->backBuffer);
7117 static HRESULT WINAPI IWineD3DDeviceImpl_GetDepthStencilSurface(IWineD3DDevice* iface, IWineD3DSurface **ppZStencilSurface) {
7118 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
7119 *ppZStencilSurface = This->depthStencilBuffer;
7120 TRACE("(%p) : zStencilSurface returning %p\n", This, *ppZStencilSurface);
7122 if(*ppZStencilSurface != NULL) {
7123 /* Note inc ref on returned surface */
7124 IWineD3DSurface_AddRef(*ppZStencilSurface);
7129 /* internal static helper functions */
7130 static HRESULT WINAPI IWineD3DDeviceImpl_ActiveRender(IWineD3DDevice* iface,
7131 IWineD3DSurface *RenderSurface);
7133 static HRESULT WINAPI IWineD3DDeviceImpl_SetRenderTarget(IWineD3DDevice *iface, DWORD RenderTargetIndex, IWineD3DSurface *pRenderTarget) {
7134 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
7135 HRESULT hr = WINED3D_OK;
7136 WINED3DVIEWPORT viewport;
7138 TRACE("(%p) Swapping rendertarget\n",This);
7139 if (RenderTargetIndex > 0) {
7140 FIXME("(%p) Render targets other than the first are not supported\n",This);
7141 RenderTargetIndex = 0;
7144 /* MSDN says that null disables the render target
7145 but a device must always be associated with a render target
7146 nope MSDN says that we return invalid call to a null rendertarget with an index of 0
7148 see http://msdn.microsoft.com/library/default.asp?url=/library/en-us/directx9_c/directx/graphics/programmingguide/AdvancedTopics/PixelPipe/MultipleRenderTarget.asp
7151 if (RenderTargetIndex == 0 && pRenderTarget == NULL) {
7152 FIXME("Trying to set render target 0 to NULL\n");
7153 return WINED3DERR_INVALIDCALL;
7155 /* TODO: replace Impl* usage with interface usage */
7156 if (!((IWineD3DSurfaceImpl *)pRenderTarget)->resource.usage & WINED3DUSAGE_RENDERTARGET) {
7157 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);
7158 return WINED3DERR_INVALIDCALL;
7160 /** TODO: check that the depth stencil format matches the render target, this is only done in debug
7161 * builds, but I think wine counts as a 'debug' build for now.
7162 ******************************/
7163 /* If we are trying to set what we already have, don't bother */
7164 if (pRenderTarget == This->renderTarget) {
7165 TRACE("Trying to do a NOP SetRenderTarget operation\n");
7167 /* Otherwise, set the render target up */
7169 if (!This->sceneEnded) {
7170 IWineD3DDevice_EndScene(iface);
7172 TRACE("clearing renderer\n");
7173 /* IWineD3DDeviceImpl_CleanRender(iface); */
7174 /* OpenGL doesn't support 'sharing' of the stencilBuffer so we may incure an extra memory overhead
7175 depending on the renter target implementation being used.
7176 A shared context implementation will share all buffers between all rendertargets (including swapchains),
7177 implementations that use separate pbuffers for different swapchains or rendertargets will have to duplicate the
7178 stencil buffer and incure an extra memory overhead */
7179 hr = IWineD3DDeviceImpl_ActiveRender(iface, pRenderTarget);
7182 if (SUCCEEDED(hr)) {
7183 /* Finally, reset the viewport as the MSDN states. */
7184 /* TODO: Replace impl usage */
7185 viewport.Height = ((IWineD3DSurfaceImpl *)This->renderTarget)->currentDesc.Height;
7186 viewport.Width = ((IWineD3DSurfaceImpl *)This->renderTarget)->currentDesc.Width;
7189 viewport.MaxZ = 1.0f;
7190 viewport.MinZ = 0.0f;
7191 IWineD3DDeviceImpl_SetViewport(iface, &viewport);
7193 FIXME("Unknown error setting the render target\n");
7195 This->sceneEnded = FALSE;
7199 static HRESULT WINAPI IWineD3DDeviceImpl_SetDepthStencilSurface(IWineD3DDevice *iface, IWineD3DSurface *pNewZStencil) {
7200 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
7201 HRESULT hr = WINED3D_OK;
7202 IWineD3DSurface *tmp;
7204 TRACE("(%p) Swapping z-buffer\n",This);
7206 if (pNewZStencil == This->stencilBufferTarget) {
7207 TRACE("Trying to do a NOP SetRenderTarget operation\n");
7209 /** OpenGL doesn't support 'sharing' of the stencilBuffer so we may incure an extra memory overhead
7210 * depending on the renter target implementation being used.
7211 * A shared context implementation will share all buffers between all rendertargets (including swapchains),
7212 * implementations that use separate pbuffers for different swapchains or rendertargets will have to duplicate the
7213 * stencil buffer and incure an extra memory overhead
7214 ******************************************************/
7217 tmp = This->stencilBufferTarget;
7218 This->stencilBufferTarget = pNewZStencil;
7219 /* should we be calling the parent or the wined3d surface? */
7220 if (NULL != This->stencilBufferTarget) IWineD3DSurface_AddRef(This->stencilBufferTarget);
7221 if (NULL != tmp) IWineD3DSurface_Release(tmp);
7223 /** TODO: glEnable/glDisable on depth/stencil depending on
7224 * pNewZStencil is NULL and the depth/stencil is enabled in d3d
7225 **********************************************************/
7232 #ifdef GL_VERSION_1_3
7233 /* Internal functions not in DirectX */
7234 /** TODO: move this off to the opengl context manager
7235 *(the swapchain doesn't need to know anything about offscreen rendering!)
7236 ****************************************************/
7238 static HRESULT WINAPI IWineD3DDeviceImpl_CleanRender(IWineD3DDevice* iface, IWineD3DSwapChainImpl *swapchain)
7240 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
7242 TRACE("(%p), %p\n", This, swapchain);
7244 if (swapchain->win != swapchain->drawable) {
7245 /* Set everything back the way it ws */
7246 swapchain->render_ctx = swapchain->glCtx;
7247 swapchain->drawable = swapchain->win;
7252 /* TODO: move this off into a context manager so that GLX_ATI_render_texture and other types of surface can be used. */
7253 static HRESULT WINAPI IWineD3DDeviceImpl_FindGLContext(IWineD3DDevice *iface, IWineD3DSurface *pSurface, glContext **context) {
7254 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
7257 unsigned int height;
7258 WINED3DFORMAT format;
7259 WINED3DSURFACE_DESC surfaceDesc;
7260 memset(&surfaceDesc, 0, sizeof(surfaceDesc));
7261 surfaceDesc.Width = &width;
7262 surfaceDesc.Height = &height;
7263 surfaceDesc.Format = &format;
7264 IWineD3DSurface_GetDesc(pSurface, &surfaceDesc);
7266 /* I need a get width/height function (and should do something with the format) */
7267 for (i = 0; i < CONTEXT_CACHE; ++i) {
7268 /** NOTE: the contextCache[i].pSurface == pSurface check ceates onepbuffer per surface
7269 ATI cards don't destroy pbuffers, but as soon as resource releasing callbacks are inplace
7270 the pSurface can be set to 0 allowing it to be reused from cache **/
7271 if (This->contextCache[i].Width == width && This->contextCache[i].Height == height
7272 && (!pbuffer_per_surface || This->contextCache[i].pSurface == pSurface || This->contextCache[i].pSurface == NULL)) {
7273 *context = &This->contextCache[i];
7276 if (This->contextCache[i].Width == 0) {
7277 This->contextCache[i].pSurface = pSurface;
7278 This->contextCache[i].Width = width;
7279 This->contextCache[i].Height = height;
7280 *context = &This->contextCache[i];
7284 if (i == CONTEXT_CACHE) {
7285 int minUsage = 0x7FFFFFFF; /* MAX_INT */
7286 glContext *dropContext = 0;
7287 for (i = 0; i < CONTEXT_CACHE; i++) {
7288 if (This->contextCache[i].usedcount < minUsage) {
7289 dropContext = &This->contextCache[i];
7290 minUsage = This->contextCache[i].usedcount;
7293 /* clean up the context (this doesn't work for ATI at the moment */
7295 glXDestroyContext(swapchain->display, dropContext->context);
7296 glXDestroyPbuffer(swapchain->display, dropContext->drawable);
7299 dropContext->Width = 0;
7300 dropContext->pSurface = pSurface;
7301 *context = dropContext;
7303 if (++This->contextCache[i].usedcount == 0x7FFFFFFF /* MAX_INT */ - 1 ) {
7304 for (i = 0; i < CONTEXT_CACHE; i++) {
7305 This->contextCache[i].usedcount = max(0, This->contextCache[i].usedcount - (0x7FFFFFFF /* MAX_INT */ >> 1));
7309 if (*context != NULL)
7312 return E_OUTOFMEMORY;
7316 /* Reapply the device stateblock */
7317 static void device_reapply_stateblock(IWineD3DDeviceImpl* This) {
7320 IWineD3DStateBlockImpl *oldUpdateStateBlock;
7322 /* Disable recording */
7323 oldUpdateStateBlock = This->updateStateBlock;
7324 oldRecording= This->isRecordingState;
7325 This->isRecordingState = FALSE;
7326 This->updateStateBlock = This->stateBlock;
7328 /* Reapply the state block */
7329 IWineD3DStateBlock_Apply((IWineD3DStateBlock *)This->stateBlock);
7331 /* Restore recording */
7332 This->isRecordingState = oldRecording;
7333 This->updateStateBlock = oldUpdateStateBlock;
7336 /* Set the device to render to a texture, or not.
7337 * This involves changing renderUpsideDown */
7339 static void device_render_to_texture(IWineD3DDeviceImpl* This, BOOL isTexture) {
7343 IWineD3DStateBlockImpl *oldUpdateStateBlock;
7345 /* Disable recording */
7346 oldUpdateStateBlock = This->updateStateBlock;
7347 oldRecording= This->isRecordingState;
7348 This->isRecordingState = FALSE;
7349 This->updateStateBlock = This->stateBlock;
7351 /* Set upside-down rendering, and update the cull mode */
7352 /* The surface must be rendered upside down to cancel the flip produced by glCopyTexImage */
7353 This->renderUpsideDown = isTexture;
7354 This->last_was_rhw = FALSE;
7355 This->proj_valid = FALSE;
7356 IWineD3DDevice_GetRenderState((IWineD3DDevice*) This, WINED3DRS_CULLMODE, &cullMode);
7357 IWineD3DDevice_SetRenderState((IWineD3DDevice*) This, WINED3DRS_CULLMODE, cullMode);
7359 /* Restore recording */
7360 This->isRecordingState = oldRecording;
7361 This->updateStateBlock = oldUpdateStateBlock;
7364 /* Returns an array of compatible FBconfig(s).
7365 * The array must be freed with XFree. Requires ENTER_GL() */
7367 static GLXFBConfig* device_find_fbconfigs(
7368 IWineD3DDeviceImpl* This,
7369 IWineD3DSwapChainImpl* implicitSwapchainImpl,
7370 IWineD3DSurface* RenderSurface) {
7372 GLXFBConfig* cfgs = NULL;
7377 IWineD3DSurface *StencilSurface = This->stencilBufferTarget;
7378 D3DFORMAT BackBufferFormat = ((IWineD3DSurfaceImpl *) RenderSurface)->resource.format;
7379 D3DFORMAT StencilBufferFormat = (NULL != StencilSurface) ? ((IWineD3DSurfaceImpl *) StencilSurface)->resource.format : 0;
7382 if StencilSurface == NULL && zBufferTarget != NULL then switch the zbuffer off,
7383 it StencilSurface != NULL && zBufferTarget == NULL switch it on
7386 #define PUSH1(att) attribs[nAttribs++] = (att);
7387 #define PUSH2(att,value) attribs[nAttribs++] = (att); attribs[nAttribs++] = (value);
7389 /* PUSH2(GLX_BIND_TO_TEXTURE_RGBA_ATI, True); examples of this are few and far between (but I've got a nice working one!)*/
7391 PUSH2(GLX_DRAWABLE_TYPE, GLX_PBUFFER_BIT);
7392 PUSH2(GLX_X_RENDERABLE, TRUE);
7393 PUSH2(GLX_DOUBLEBUFFER, TRUE);
7394 TRACE("calling makeglcfg\n");
7395 D3DFmtMakeGlCfg(BackBufferFormat, StencilBufferFormat, attribs, &nAttribs, FALSE /* alternate */);
7397 TRACE("calling chooseFGConfig\n");
7398 cfgs = glXChooseFBConfig(implicitSwapchainImpl->display,
7399 DefaultScreen(implicitSwapchainImpl->display),
7402 /* OK we didn't find the exact config, so use any reasonable match */
7403 /* TODO: fill in the 'requested' and 'current' depths, and make sure that's
7405 static BOOL show_message = TRUE;
7407 ERR("Failed to find exact match, finding alternative but you may "
7408 "suffer performance issues, try changing xfree's depth to match the requested depth\n");
7409 show_message = FALSE;
7412 PUSH2(GLX_DRAWABLE_TYPE, GLX_PBUFFER_BIT | GLX_WINDOW_BIT);
7413 /* PUSH2(GLX_X_RENDERABLE, TRUE); */
7414 PUSH2(GLX_RENDER_TYPE, GLX_RGBA_BIT);
7415 PUSH2(GLX_DOUBLEBUFFER, FALSE);
7416 TRACE("calling makeglcfg\n");
7417 D3DFmtMakeGlCfg(BackBufferFormat, StencilBufferFormat, attribs, &nAttribs, TRUE /* alternate */);
7419 cfgs = glXChooseFBConfig(implicitSwapchainImpl->display,
7420 DefaultScreen(implicitSwapchainImpl->display),
7425 ERR("Could not get a valid FBConfig for (%u,%s)/(%u,%s)\n",
7426 BackBufferFormat, debug_d3dformat(BackBufferFormat),
7427 StencilBufferFormat, debug_d3dformat(StencilBufferFormat));
7431 for (i = 0; i < nCfgs; ++i) {
7432 TRACE("for (%u,%s)/(%u,%s) found config[%d]@%p\n", BackBufferFormat,
7433 debug_d3dformat(BackBufferFormat), StencilBufferFormat,
7434 debug_d3dformat(StencilBufferFormat), i, cfgs[i]);
7436 if (NULL != This->renderTarget) {
7438 vcheckGLcall("glFlush");
7439 /** This is only useful if the old render target was a swapchain,
7440 * we need to supercede this with a function that displays
7441 * the current buffer on the screen. This is easy to do in glx1.3 but
7442 * we need to do copy-write pixels in glx 1.2.
7443 ************************************************/
7444 glXSwapBuffers(implicitSwapChainImpl->display,
7445 implicitSwapChainImpl->drawable);
7446 printf("Hit Enter to get next frame ...\n");
7457 /** FIXME: This is currently used called whenever SetRenderTarget or SetStencilBuffer are called
7458 * the functionality needs splitting up so that we don't do more than we should do.
7459 * this only seems to impact performance a little.
7460 ******************************/
7461 static HRESULT WINAPI IWineD3DDeviceImpl_ActiveRender(IWineD3DDevice* iface,
7462 IWineD3DSurface *RenderSurface) {
7465 * Currently only active for GLX >= 1.3
7466 * for others versions we'll have to use GLXPixmaps
7468 * normally we must test GLX_VERSION_1_3 but nvidia headers are not correct
7469 * as they implement GLX 1.3 but only define GLX_VERSION_1_2
7470 * so only check OpenGL version
7471 * ..........................
7472 * I don't believe that it is a problem with NVidia headers,
7473 * XFree only supports GLX1.2, nVidia (and ATI to some extent) provide 1.3 functions
7474 * in GLX 1.2, there is no mention of the correct way to tell if the extensions are provided.
7476 * Your application will report GLX version 1.2 on glXQueryVersion.
7477 * However, it is safe to call the GLX 1.3 functions as described below.
7479 #if defined(GL_VERSION_1_3)
7481 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
7482 GLXFBConfig* cfgs = NULL;
7483 IWineD3DSwapChain *currentSwapchain;
7484 IWineD3DSwapChainImpl *currentSwapchainImpl;
7485 IWineD3DSwapChain *implicitSwapchain;
7486 IWineD3DSwapChainImpl *implicitSwapchainImpl;
7487 IWineD3DSwapChain *renderSurfaceSwapchain;
7488 IWineD3DSwapChainImpl *renderSurfaceSwapchainImpl;
7490 /* Obtain a reference to the device implicit swapchain,
7491 * the swapchain of the current render target,
7492 * and the swapchain of the new render target.
7493 * Fallback to device implicit swapchain if the current render target doesn't have one */
7494 IWineD3DDevice_GetSwapChain(iface, 0, &implicitSwapchain);
7495 IWineD3DSurface_GetContainer(RenderSurface, &IID_IWineD3DSwapChain, (void**) &renderSurfaceSwapchain);
7496 IWineD3DSurface_GetContainer(This->renderTarget, &IID_IWineD3DSwapChain, (void **)¤tSwapchain);
7497 if (currentSwapchain == NULL)
7498 IWineD3DDevice_GetSwapChain(iface, 0, ¤tSwapchain);
7500 currentSwapchainImpl = (IWineD3DSwapChainImpl*) currentSwapchain;
7501 implicitSwapchainImpl = (IWineD3DSwapChainImpl*) implicitSwapchain;
7502 renderSurfaceSwapchainImpl = (IWineD3DSwapChainImpl*) renderSurfaceSwapchain;
7507 * TODO: remove the use of IWineD3DSwapChainImpl, a context manager will help since it will replace the
7508 * renderTarget = swapchain->backBuffer[i] bit and anything to do with *glContexts
7509 **********************************************************************/
7510 if (renderSurfaceSwapchain != NULL) {
7512 /* We also need to make sure that the lights &co are also in the context of the swapchains */
7513 /* FIXME: If the render target gets sent to the frontBuffer should be be presenting it raw? */
7514 TRACE("making swapchain active\n");
7515 if (RenderSurface != This->renderTarget) {
7516 BOOL backbuf = FALSE;
7519 for(i = 0; i < renderSurfaceSwapchainImpl->presentParms.BackBufferCount; i++) {
7520 if(RenderSurface == renderSurfaceSwapchainImpl->backBuffer[i]) {
7528 /* This could be flagged so that some operations work directly with the front buffer */
7529 FIXME("Attempting to set the renderTarget to the frontBuffer\n");
7531 if (glXMakeCurrent(renderSurfaceSwapchainImpl->display,
7532 renderSurfaceSwapchainImpl->win,
7533 renderSurfaceSwapchainImpl->glCtx) == False) {
7535 TRACE("Error in setting current context: context %p drawable %ld !\n",
7536 implicitSwapchainImpl->glCtx, implicitSwapchainImpl->win);
7538 checkGLcall("glXMakeContextCurrent");
7540 /* Clean up the old context */
7541 IWineD3DDeviceImpl_CleanRender(iface, currentSwapchainImpl);
7543 /* Reapply the stateblock, and set the device not to render to texture */
7544 device_reapply_stateblock(This);
7545 device_render_to_texture(This, FALSE);
7548 /* Offscreen rendering: PBuffers (currently disabled).
7549 * Also note that this path is never reached if FBOs are supported */
7550 } else if (pbuffer_support &&
7551 (cfgs = device_find_fbconfigs(This, implicitSwapchainImpl, RenderSurface)) != NULL) {
7553 /** ********************************************************************
7554 * This is a quickly hacked out implementation of offscreen textures.
7555 * It will work in most cases but there may be problems if the client
7556 * modifies the texture directly, or expects the contents of the rendertarget
7559 * There are some real speed vs compatibility issues here:
7560 * we should really use a new context for every texture, but that eats ram.
7561 * we should also be restoring the texture to the pbuffer but that eats CPU
7562 * we can also 'reuse' the current pbuffer if the size is larger than the requested buffer,
7563 * but if this means reusing the display backbuffer then we need to make sure that
7564 * states are correctly preserved.
7565 * In many cases I would expect that we can 'skip' some functions, such as preserving states,
7566 * and gain a good performance increase at the cost of compatibility.
7567 * I would suggest that, when this is the case, a user configurable flag be made
7568 * available, allowing the user to choose the best emulated experience for them.
7569 *********************************************************************/
7571 XVisualInfo *visinfo;
7572 glContext *newContext;
7574 /* Here were using a shared context model */
7575 if (WINED3D_OK != IWineD3DDeviceImpl_FindGLContext(iface, RenderSurface, &newContext)) {
7576 FIXME("(%p) : Failed to find a context for surface %p\n", iface, RenderSurface);
7579 /* If the context doesn't exist then create a new one */
7580 /* TODO: This should really be part of findGlContext */
7581 if (NULL == newContext->context) {
7586 TRACE("making new buffer\n");
7587 attribs[nAttribs++] = GLX_PBUFFER_WIDTH;
7588 attribs[nAttribs++] = newContext->Width;
7589 attribs[nAttribs++] = GLX_PBUFFER_HEIGHT;
7590 attribs[nAttribs++] = newContext->Height;
7591 attribs[nAttribs++] = None;
7593 newContext->drawable = glXCreatePbuffer(implicitSwapchainImpl->display, cfgs[0], attribs);
7595 /** ****************************************
7596 *GLX1.3 isn't supported by XFree 'yet' until that point ATI emulates pBuffers
7598 * In future releases, we may provide the calls glXCreateNewContext,
7599 * glXQueryDrawable and glXMakeContextCurrent.
7600 * so until then we have to use glXGetVisualFromFBConfig &co..
7601 ********************************************/
7603 visinfo = glXGetVisualFromFBConfig(implicitSwapchainImpl->display, cfgs[0]);
7605 ERR("Error: couldn't get an RGBA, double-buffered visual\n");
7607 newContext->context = glXCreateContext(
7608 implicitSwapchainImpl->display, visinfo,
7609 implicitSwapchainImpl->glCtx, GL_TRUE);
7614 if (NULL == newContext || NULL == newContext->context) {
7615 ERR("(%p) : Failed to find a context for surface %p\n", iface, RenderSurface);
7617 /* Debug logging, (this function leaks), change to a TRACE when the leak is plugged */
7618 if (glXMakeCurrent(implicitSwapchainImpl->display,
7619 newContext->drawable, newContext->context) == False) {
7621 TRACE("Error in setting current context: context %p drawable %ld\n",
7622 newContext->context, newContext->drawable);
7624 checkGLcall("glXMakeContextCurrent");
7626 /* Clean up the old context */
7627 IWineD3DDeviceImpl_CleanRender(iface, currentSwapchainImpl);
7629 /* Reapply stateblock, and set device to render to a texture */
7630 device_reapply_stateblock(This);
7631 device_render_to_texture(This, TRUE);
7633 /* Set the current context of the swapchain to the new context */
7634 implicitSwapchainImpl->drawable = newContext->drawable;
7635 implicitSwapchainImpl->render_ctx = newContext->context;
7638 /* Same context, but update renderUpsideDown and cull mode */
7639 device_render_to_texture(This, TRUE);
7642 /* Replace the render target */
7643 if (This->renderTarget != RenderSurface) {
7644 IWineD3DSurface_Release(This->renderTarget);
7645 This->renderTarget = RenderSurface;
7646 IWineD3DSurface_AddRef(RenderSurface);
7649 if (cfgs != NULL) XFree(cfgs);
7650 if (implicitSwapchain != NULL) IWineD3DSwapChain_Release(implicitSwapchain);
7651 if (currentSwapchain != NULL) IWineD3DSwapChain_Release(currentSwapchain);
7652 if (renderSurfaceSwapchain != NULL) IWineD3DSwapChain_Release(renderSurfaceSwapchain);
7658 static HRESULT WINAPI IWineD3DDeviceImpl_SetCursorProperties(IWineD3DDevice* iface, UINT XHotSpot,
7659 UINT YHotSpot, IWineD3DSurface *pCursorBitmap) {
7660 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *) iface;
7661 /* TODO: the use of Impl is deprecated. */
7662 IWineD3DSurfaceImpl * pSur = (IWineD3DSurfaceImpl *) pCursorBitmap;
7664 TRACE("(%p) : Spot Pos(%u,%u)\n", This, XHotSpot, YHotSpot);
7666 /* some basic validation checks */
7667 if(This->cursorTexture) {
7669 glDeleteTextures(1, &This->cursorTexture);
7671 This->cursorTexture = 0;
7675 /* MSDN: Cursor must be A8R8G8B8 */
7676 if (WINED3DFMT_A8R8G8B8 != pSur->resource.format) {
7677 ERR("(%p) : surface(%p) has an invalid format\n", This, pCursorBitmap);
7678 return WINED3DERR_INVALIDCALL;
7681 /* MSDN: Cursor must be smaller than the display mode */
7682 if(pSur->currentDesc.Width > This->ddraw_width ||
7683 pSur->currentDesc.Height > This->ddraw_height) {
7684 ERR("(%p) : Surface(%p) is %dx%d pixels, but screen res is %dx%d\n", This, pSur, pSur->currentDesc.Width, pSur->currentDesc.Height, This->ddraw_width, This->ddraw_height);
7685 return WINED3DERR_INVALIDCALL;
7688 /* TODO: MSDN: Cursor sizes must be a power of 2 */
7689 /* This is to tell our texture code to load a SCRATCH surface. This allows us to use out
7690 * Texture and Blitting code to draw the cursor
7692 pSur->Flags |= SFLAG_FORCELOAD;
7693 IWineD3DSurface_PreLoad(pCursorBitmap);
7694 pSur->Flags &= ~SFLAG_FORCELOAD;
7695 /* Do not store the surface's pointer because the application may release
7696 * it after setting the cursor image. Windows doesn't addref the set surface, so we can't
7697 * do this either without creating circular refcount dependencies. Copy out the gl texture instead.
7699 This->cursorTexture = pSur->glDescription.textureName;
7700 This->cursorWidth = pSur->currentDesc.Width;
7701 This->cursorHeight = pSur->currentDesc.Height;
7702 pSur->glDescription.textureName = 0; /* Prevent the texture from being changed or deleted */
7705 This->xHotSpot = XHotSpot;
7706 This->yHotSpot = YHotSpot;
7710 static void WINAPI IWineD3DDeviceImpl_SetCursorPosition(IWineD3DDevice* iface, int XScreenSpace, int YScreenSpace, DWORD Flags) {
7711 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *) iface;
7712 TRACE("(%p) : SetPos to (%u,%u)\n", This, XScreenSpace, YScreenSpace);
7714 This->xScreenSpace = XScreenSpace;
7715 This->yScreenSpace = YScreenSpace;
7721 static BOOL WINAPI IWineD3DDeviceImpl_ShowCursor(IWineD3DDevice* iface, BOOL bShow) {
7722 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *) iface;
7723 BOOL oldVisible = This->bCursorVisible;
7724 TRACE("(%p) : visible(%d)\n", This, bShow);
7726 if(This->cursorTexture)
7727 This->bCursorVisible = bShow;
7732 static HRESULT WINAPI IWineD3DDeviceImpl_TestCooperativeLevel(IWineD3DDevice* iface) {
7733 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *) iface;
7734 TRACE("(%p) : state (%u)\n", This, This->state);
7735 /* TODO: Implement wrapping of the WndProc so that mimimize and maxamise can be monitored and the states adjusted. */
7736 switch (This->state) {
7739 case WINED3DERR_DEVICELOST:
7741 ResourceList *resourceList = This->resources;
7742 while (NULL != resourceList) {
7743 if (((IWineD3DResourceImpl *)resourceList->resource)->resource.pool == WINED3DPOOL_DEFAULT /* TODO: IWineD3DResource_GetPool(resourceList->resource)*/)
7744 return WINED3DERR_DEVICENOTRESET;
7745 resourceList = resourceList->next;
7747 return WINED3DERR_DEVICELOST;
7749 case WINED3DERR_DRIVERINTERNALERROR:
7750 return WINED3DERR_DRIVERINTERNALERROR;
7754 return WINED3DERR_DRIVERINTERNALERROR;
7758 static HRESULT WINAPI IWineD3DDeviceImpl_EvictManagedResources(IWineD3DDevice* iface) {
7759 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *) iface;
7760 /** FIXME: Resource tracking needs to be done,
7761 * The closes we can do to this is set the priorities of all managed textures low
7762 * and then reset them.
7763 ***********************************************************/
7764 FIXME("(%p) : stub\n", This);
7768 static HRESULT WINAPI IWineD3DDeviceImpl_Reset(IWineD3DDevice* iface, WINED3DPRESENT_PARAMETERS* pPresentationParameters) {
7769 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *) iface;
7770 /** FIXME: Resource trascking needs to be done.
7771 * in effect this pulls all non only default
7772 * textures out of video memory and deletes all glTextures (glDeleteTextures)
7773 * and should clear down the context and set it up according to pPresentationParameters
7774 ***********************************************************/
7775 FIXME("(%p) : stub\n", This);
7779 static HRESULT WINAPI IWineD3DDeviceImpl_SetDialogBoxMode(IWineD3DDevice *iface, BOOL bEnableDialogs) {
7780 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
7781 /** FIXME: always true at the moment **/
7782 if(!bEnableDialogs) {
7783 FIXME("(%p) Dialogs cannot be disabled yet\n", This);
7789 static HRESULT WINAPI IWineD3DDeviceImpl_GetCreationParameters(IWineD3DDevice *iface, WINED3DDEVICE_CREATION_PARAMETERS *pParameters) {
7790 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *) iface;
7791 TRACE("(%p) : pParameters %p\n", This, pParameters);
7793 *pParameters = This->createParms;
7797 static void WINAPI IWineD3DDeviceImpl_SetGammaRamp(IWineD3DDevice * iface, UINT iSwapChain, DWORD Flags, CONST WINED3DGAMMARAMP* pRamp) {
7798 IWineD3DSwapChain *swapchain;
7799 HRESULT hrc = WINED3D_OK;
7801 TRACE("Relaying to swapchain\n");
7803 if ((hrc = IWineD3DDeviceImpl_GetSwapChain(iface, iSwapChain, &swapchain)) == WINED3D_OK) {
7804 IWineD3DSwapChain_SetGammaRamp(swapchain, Flags, (WINED3DGAMMARAMP *)pRamp);
7805 IWineD3DSwapChain_Release(swapchain);
7810 static void WINAPI IWineD3DDeviceImpl_GetGammaRamp(IWineD3DDevice *iface, UINT iSwapChain, WINED3DGAMMARAMP* pRamp) {
7811 IWineD3DSwapChain *swapchain;
7812 HRESULT hrc = WINED3D_OK;
7814 TRACE("Relaying to swapchain\n");
7816 if ((hrc = IWineD3DDeviceImpl_GetSwapChain(iface, iSwapChain, &swapchain)) == WINED3D_OK) {
7817 hrc =IWineD3DSwapChain_GetGammaRamp(swapchain, pRamp);
7818 IWineD3DSwapChain_Release(swapchain);
7824 /** ********************************************************
7825 * Notification functions
7826 ** ********************************************************/
7827 /** This function must be called in the release of a resource when ref == 0,
7828 * the contents of resource must still be correct,
7829 * any handels to other resource held by the caller must be closed
7830 * (e.g. a texture should release all held surfaces because telling the device that it's been released.)
7831 *****************************************************/
7832 static void WINAPI IWineD3DDeviceImpl_AddResource(IWineD3DDevice *iface, IWineD3DResource *resource){
7833 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
7834 ResourceList* resourceList;
7836 TRACE("(%p) : resource %p\n", This, resource);
7838 EnterCriticalSection(&resourceStoreCriticalSection);
7840 /* add a new texture to the frot of the linked list */
7841 resourceList = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(ResourceList));
7842 resourceList->resource = resource;
7844 /* Get the old head */
7845 resourceList->next = This->resources;
7847 This->resources = resourceList;
7848 TRACE("Added resource %p with element %p pointing to %p\n", resource, resourceList, resourceList->next);
7851 LeaveCriticalSection(&resourceStoreCriticalSection);
7856 static void WINAPI IWineD3DDeviceImpl_RemoveResource(IWineD3DDevice *iface, IWineD3DResource *resource){
7857 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
7858 ResourceList* resourceList = NULL;
7859 ResourceList* previousResourceList = NULL;
7861 TRACE("(%p) : resource %p\n", This, resource);
7864 EnterCriticalSection(&resourceStoreCriticalSection);
7866 resourceList = This->resources;
7868 while (resourceList != NULL) {
7869 if(resourceList->resource == resource) break;
7870 previousResourceList = resourceList;
7871 resourceList = resourceList->next;
7874 if (resourceList == NULL) {
7875 FIXME("Attempted to remove resource %p that hasn't been stored\n", resource);
7877 LeaveCriticalSection(&resourceStoreCriticalSection);
7881 TRACE("Found resource %p with element %p pointing to %p (previous %p)\n", resourceList->resource, resourceList, resourceList->next, previousResourceList);
7883 /* make sure we don't leave a hole in the list */
7884 if (previousResourceList != NULL) {
7885 previousResourceList->next = resourceList->next;
7887 This->resources = resourceList->next;
7891 LeaveCriticalSection(&resourceStoreCriticalSection);
7897 static void WINAPI IWineD3DDeviceImpl_ResourceReleased(IWineD3DDevice *iface, IWineD3DResource *resource){
7898 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *) iface;
7901 TRACE("(%p) : resource %p\n", This, resource);
7902 switch(IWineD3DResource_GetType(resource)){
7903 case WINED3DRTYPE_SURFACE:
7904 /* TODO: check front and back buffers, rendertargets etc.. possibly swapchains? */
7906 case WINED3DRTYPE_TEXTURE:
7907 case WINED3DRTYPE_CUBETEXTURE:
7908 case WINED3DRTYPE_VOLUMETEXTURE:
7909 for (counter = 0; counter < GL_LIMITS(sampler_stages); counter++) {
7910 if (This->stateBlock != NULL && This->stateBlock->textures[counter] == (IWineD3DBaseTexture *)resource) {
7911 WARN("Texture being released is still by a stateblock, Stage = %u Texture = %p\n", counter, resource);
7912 This->stateBlock->textures[counter] = NULL;
7914 if (This->updateStateBlock != This->stateBlock ){
7915 if (This->updateStateBlock->textures[counter] == (IWineD3DBaseTexture *)resource) {
7916 WARN("Texture being released is still by a stateblock, Stage = %u Texture = %p\n", counter, resource);
7917 This->updateStateBlock->textures[counter] = NULL;
7922 case WINED3DRTYPE_VOLUME:
7923 /* TODO: nothing really? */
7925 case WINED3DRTYPE_VERTEXBUFFER:
7926 /* MSDN: When an application no longer holds a references to this interface, the interface will automatically be freed. */
7929 TRACE("Cleaning up stream pointers\n");
7931 for(streamNumber = 0; streamNumber < MAX_STREAMS; streamNumber ++){
7932 /* FINDOUT: should a warn be generated if were recording and updateStateBlock->streamSource is lost?
7933 FINDOUT: should changes.streamSource[StreamNumber] be set ?
7935 if (This->updateStateBlock != NULL ) { /* ==NULL when device is being destroyed */
7936 if ((IWineD3DResource *)This->updateStateBlock->streamSource[streamNumber] == resource) {
7937 FIXME("Vertex buffer released while bound to a state block, stream %d\n", streamNumber);
7938 This->updateStateBlock->streamSource[streamNumber] = 0;
7939 /* Set changed flag? */
7942 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) */
7943 if ((IWineD3DResource *)This->stateBlock->streamSource[streamNumber] == resource) {
7944 TRACE("Vertex buffer released while bound to a state block, stream %d\n", streamNumber);
7945 This->stateBlock->streamSource[streamNumber] = 0;
7948 #if 0 /* TODO: Manage internal tracking properly so that 'this shouldn't happen' */
7949 else { /* This shouldn't happen */
7950 FIXME("Calling application has released the device before relasing all the resources bound to the device\n");
7957 case WINED3DRTYPE_INDEXBUFFER:
7958 /* MSDN: When an application no longer holds a references to this interface, the interface will automatically be freed.*/
7959 if (This->updateStateBlock != NULL ) { /* ==NULL when device is being destroyed */
7960 if (This->updateStateBlock->pIndexData == (IWineD3DIndexBuffer *)resource) {
7961 This->updateStateBlock->pIndexData = NULL;
7964 if (This->stateBlock != NULL ) { /* ==NULL when device is being destroyed */
7965 if (This->stateBlock->pIndexData == (IWineD3DIndexBuffer *)resource) {
7966 This->stateBlock->pIndexData = NULL;
7972 FIXME("(%p) unknown resource type %p %u\n", This, resource, IWineD3DResource_GetType(resource));
7977 /* Remove the resoruce from the resourceStore */
7978 IWineD3DDeviceImpl_RemoveResource(iface, resource);
7980 TRACE("Resource released\n");
7984 /**********************************************************
7985 * IWineD3DDevice VTbl follows
7986 **********************************************************/
7988 const IWineD3DDeviceVtbl IWineD3DDevice_Vtbl =
7990 /*** IUnknown methods ***/
7991 IWineD3DDeviceImpl_QueryInterface,
7992 IWineD3DDeviceImpl_AddRef,
7993 IWineD3DDeviceImpl_Release,
7994 /*** IWineD3DDevice methods ***/
7995 IWineD3DDeviceImpl_GetParent,
7996 /*** Creation methods**/
7997 IWineD3DDeviceImpl_CreateVertexBuffer,
7998 IWineD3DDeviceImpl_CreateIndexBuffer,
7999 IWineD3DDeviceImpl_CreateStateBlock,
8000 IWineD3DDeviceImpl_CreateSurface,
8001 IWineD3DDeviceImpl_CreateTexture,
8002 IWineD3DDeviceImpl_CreateVolumeTexture,
8003 IWineD3DDeviceImpl_CreateVolume,
8004 IWineD3DDeviceImpl_CreateCubeTexture,
8005 IWineD3DDeviceImpl_CreateQuery,
8006 IWineD3DDeviceImpl_CreateAdditionalSwapChain,
8007 IWineD3DDeviceImpl_CreateVertexDeclaration,
8008 IWineD3DDeviceImpl_CreateVertexShader,
8009 IWineD3DDeviceImpl_CreatePixelShader,
8010 IWineD3DDeviceImpl_CreatePalette,
8011 /*** Odd functions **/
8012 IWineD3DDeviceImpl_Init3D,
8013 IWineD3DDeviceImpl_Uninit3D,
8014 IWineD3DDeviceImpl_SetFullscreen,
8015 IWineD3DDeviceImpl_EnumDisplayModes,
8016 IWineD3DDeviceImpl_EvictManagedResources,
8017 IWineD3DDeviceImpl_GetAvailableTextureMem,
8018 IWineD3DDeviceImpl_GetBackBuffer,
8019 IWineD3DDeviceImpl_GetCreationParameters,
8020 IWineD3DDeviceImpl_GetDeviceCaps,
8021 IWineD3DDeviceImpl_GetDirect3D,
8022 IWineD3DDeviceImpl_GetDisplayMode,
8023 IWineD3DDeviceImpl_SetDisplayMode,
8024 IWineD3DDeviceImpl_GetHWND,
8025 IWineD3DDeviceImpl_SetHWND,
8026 IWineD3DDeviceImpl_GetNumberOfSwapChains,
8027 IWineD3DDeviceImpl_GetRasterStatus,
8028 IWineD3DDeviceImpl_GetSwapChain,
8029 IWineD3DDeviceImpl_Reset,
8030 IWineD3DDeviceImpl_SetDialogBoxMode,
8031 IWineD3DDeviceImpl_SetCursorProperties,
8032 IWineD3DDeviceImpl_SetCursorPosition,
8033 IWineD3DDeviceImpl_ShowCursor,
8034 IWineD3DDeviceImpl_TestCooperativeLevel,
8035 /*** Getters and setters **/
8036 IWineD3DDeviceImpl_SetClipPlane,
8037 IWineD3DDeviceImpl_GetClipPlane,
8038 IWineD3DDeviceImpl_SetClipStatus,
8039 IWineD3DDeviceImpl_GetClipStatus,
8040 IWineD3DDeviceImpl_SetCurrentTexturePalette,
8041 IWineD3DDeviceImpl_GetCurrentTexturePalette,
8042 IWineD3DDeviceImpl_SetDepthStencilSurface,
8043 IWineD3DDeviceImpl_GetDepthStencilSurface,
8044 IWineD3DDeviceImpl_SetFVF,
8045 IWineD3DDeviceImpl_GetFVF,
8046 IWineD3DDeviceImpl_SetGammaRamp,
8047 IWineD3DDeviceImpl_GetGammaRamp,
8048 IWineD3DDeviceImpl_SetIndices,
8049 IWineD3DDeviceImpl_GetIndices,
8050 IWineD3DDeviceImpl_SetLight,
8051 IWineD3DDeviceImpl_GetLight,
8052 IWineD3DDeviceImpl_SetLightEnable,
8053 IWineD3DDeviceImpl_GetLightEnable,
8054 IWineD3DDeviceImpl_SetMaterial,
8055 IWineD3DDeviceImpl_GetMaterial,
8056 IWineD3DDeviceImpl_SetNPatchMode,
8057 IWineD3DDeviceImpl_GetNPatchMode,
8058 IWineD3DDeviceImpl_SetPaletteEntries,
8059 IWineD3DDeviceImpl_GetPaletteEntries,
8060 IWineD3DDeviceImpl_SetPixelShader,
8061 IWineD3DDeviceImpl_GetPixelShader,
8062 IWineD3DDeviceImpl_SetPixelShaderConstantB,
8063 IWineD3DDeviceImpl_GetPixelShaderConstantB,
8064 IWineD3DDeviceImpl_SetPixelShaderConstantI,
8065 IWineD3DDeviceImpl_GetPixelShaderConstantI,
8066 IWineD3DDeviceImpl_SetPixelShaderConstantF,
8067 IWineD3DDeviceImpl_GetPixelShaderConstantF,
8068 IWineD3DDeviceImpl_SetRenderState,
8069 IWineD3DDeviceImpl_GetRenderState,
8070 IWineD3DDeviceImpl_SetRenderTarget,
8071 IWineD3DDeviceImpl_GetRenderTarget,
8072 IWineD3DDeviceImpl_SetFrontBackBuffers,
8073 IWineD3DDeviceImpl_SetSamplerState,
8074 IWineD3DDeviceImpl_GetSamplerState,
8075 IWineD3DDeviceImpl_SetScissorRect,
8076 IWineD3DDeviceImpl_GetScissorRect,
8077 IWineD3DDeviceImpl_SetSoftwareVertexProcessing,
8078 IWineD3DDeviceImpl_GetSoftwareVertexProcessing,
8079 IWineD3DDeviceImpl_SetStreamSource,
8080 IWineD3DDeviceImpl_GetStreamSource,
8081 IWineD3DDeviceImpl_SetStreamSourceFreq,
8082 IWineD3DDeviceImpl_GetStreamSourceFreq,
8083 IWineD3DDeviceImpl_SetTexture,
8084 IWineD3DDeviceImpl_GetTexture,
8085 IWineD3DDeviceImpl_SetTextureStageState,
8086 IWineD3DDeviceImpl_GetTextureStageState,
8087 IWineD3DDeviceImpl_SetTransform,
8088 IWineD3DDeviceImpl_GetTransform,
8089 IWineD3DDeviceImpl_SetVertexDeclaration,
8090 IWineD3DDeviceImpl_GetVertexDeclaration,
8091 IWineD3DDeviceImpl_SetVertexShader,
8092 IWineD3DDeviceImpl_GetVertexShader,
8093 IWineD3DDeviceImpl_SetVertexShaderConstantB,
8094 IWineD3DDeviceImpl_GetVertexShaderConstantB,
8095 IWineD3DDeviceImpl_SetVertexShaderConstantI,
8096 IWineD3DDeviceImpl_GetVertexShaderConstantI,
8097 IWineD3DDeviceImpl_SetVertexShaderConstantF,
8098 IWineD3DDeviceImpl_GetVertexShaderConstantF,
8099 IWineD3DDeviceImpl_SetViewport,
8100 IWineD3DDeviceImpl_GetViewport,
8101 IWineD3DDeviceImpl_MultiplyTransform,
8102 IWineD3DDeviceImpl_ValidateDevice,
8103 IWineD3DDeviceImpl_ProcessVertices,
8104 /*** State block ***/
8105 IWineD3DDeviceImpl_BeginStateBlock,
8106 IWineD3DDeviceImpl_EndStateBlock,
8107 /*** Scene management ***/
8108 IWineD3DDeviceImpl_BeginScene,
8109 IWineD3DDeviceImpl_EndScene,
8110 IWineD3DDeviceImpl_Present,
8111 IWineD3DDeviceImpl_Clear,
8113 IWineD3DDeviceImpl_DrawPrimitive,
8114 IWineD3DDeviceImpl_DrawIndexedPrimitive,
8115 IWineD3DDeviceImpl_DrawPrimitiveUP,
8116 IWineD3DDeviceImpl_DrawIndexedPrimitiveUP,
8117 IWineD3DDeviceImpl_DrawPrimitiveStrided,
8118 IWineD3DDeviceImpl_DrawRectPatch,
8119 IWineD3DDeviceImpl_DrawTriPatch,
8120 IWineD3DDeviceImpl_DeletePatch,
8121 IWineD3DDeviceImpl_ColorFill,
8122 IWineD3DDeviceImpl_UpdateTexture,
8123 IWineD3DDeviceImpl_UpdateSurface,
8124 IWineD3DDeviceImpl_CopyRects,
8125 IWineD3DDeviceImpl_StretchRect,
8126 IWineD3DDeviceImpl_GetRenderTargetData,
8127 IWineD3DDeviceImpl_GetFrontBufferData,
8128 /*** Internal use IWineD3DDevice methods ***/
8129 IWineD3DDeviceImpl_SetupTextureStates,
8130 /*** object tracking ***/
8131 IWineD3DDeviceImpl_ResourceReleased
8135 const DWORD SavedPixelStates_R[NUM_SAVEDPIXELSTATES_R] = {
8136 WINED3DRS_ALPHABLENDENABLE ,
8137 WINED3DRS_ALPHAFUNC ,
8138 WINED3DRS_ALPHAREF ,
8139 WINED3DRS_ALPHATESTENABLE ,
8141 WINED3DRS_COLORWRITEENABLE ,
8142 WINED3DRS_DESTBLEND ,
8143 WINED3DRS_DITHERENABLE ,
8144 WINED3DRS_FILLMODE ,
8145 WINED3DRS_FOGDENSITY ,
8147 WINED3DRS_FOGSTART ,
8148 WINED3DRS_LASTPIXEL ,
8149 WINED3DRS_SHADEMODE ,
8150 WINED3DRS_SRCBLEND ,
8151 WINED3DRS_STENCILENABLE ,
8152 WINED3DRS_STENCILFAIL ,
8153 WINED3DRS_STENCILFUNC ,
8154 WINED3DRS_STENCILMASK ,
8155 WINED3DRS_STENCILPASS ,
8156 WINED3DRS_STENCILREF ,
8157 WINED3DRS_STENCILWRITEMASK ,
8158 WINED3DRS_STENCILZFAIL ,
8159 WINED3DRS_TEXTUREFACTOR ,
8170 WINED3DRS_ZWRITEENABLE
8173 const DWORD SavedPixelStates_T[NUM_SAVEDPIXELSTATES_T] = {
8174 WINED3DTSS_ADDRESSW ,
8175 WINED3DTSS_ALPHAARG0 ,
8176 WINED3DTSS_ALPHAARG1 ,
8177 WINED3DTSS_ALPHAARG2 ,
8178 WINED3DTSS_ALPHAOP ,
8179 WINED3DTSS_BUMPENVLOFFSET ,
8180 WINED3DTSS_BUMPENVLSCALE ,
8181 WINED3DTSS_BUMPENVMAT00 ,
8182 WINED3DTSS_BUMPENVMAT01 ,
8183 WINED3DTSS_BUMPENVMAT10 ,
8184 WINED3DTSS_BUMPENVMAT11 ,
8185 WINED3DTSS_COLORARG0 ,
8186 WINED3DTSS_COLORARG1 ,
8187 WINED3DTSS_COLORARG2 ,
8188 WINED3DTSS_COLOROP ,
8189 WINED3DTSS_RESULTARG ,
8190 WINED3DTSS_TEXCOORDINDEX ,
8191 WINED3DTSS_TEXTURETRANSFORMFLAGS
8194 const DWORD SavedPixelStates_S[NUM_SAVEDPIXELSTATES_S] = {
8195 WINED3DSAMP_ADDRESSU ,
8196 WINED3DSAMP_ADDRESSV ,
8197 WINED3DSAMP_ADDRESSW ,
8198 WINED3DSAMP_BORDERCOLOR ,
8199 WINED3DSAMP_MAGFILTER ,
8200 WINED3DSAMP_MINFILTER ,
8201 WINED3DSAMP_MIPFILTER ,
8202 WINED3DSAMP_MIPMAPLODBIAS ,
8203 WINED3DSAMP_MAXMIPLEVEL ,
8204 WINED3DSAMP_MAXANISOTROPY ,
8205 WINED3DSAMP_SRGBTEXTURE ,
8206 WINED3DSAMP_ELEMENTINDEX
8209 const DWORD SavedVertexStates_R[NUM_SAVEDVERTEXSTATES_R] = {
8211 WINED3DRS_AMBIENTMATERIALSOURCE ,
8212 WINED3DRS_CLIPPING ,
8213 WINED3DRS_CLIPPLANEENABLE ,
8214 WINED3DRS_COLORVERTEX ,
8215 WINED3DRS_DIFFUSEMATERIALSOURCE ,
8216 WINED3DRS_EMISSIVEMATERIALSOURCE ,
8217 WINED3DRS_FOGDENSITY ,
8219 WINED3DRS_FOGSTART ,
8220 WINED3DRS_FOGTABLEMODE ,
8221 WINED3DRS_FOGVERTEXMODE ,
8222 WINED3DRS_INDEXEDVERTEXBLENDENABLE ,
8223 WINED3DRS_LIGHTING ,
8224 WINED3DRS_LOCALVIEWER ,
8225 WINED3DRS_MULTISAMPLEANTIALIAS ,
8226 WINED3DRS_MULTISAMPLEMASK ,
8227 WINED3DRS_NORMALIZENORMALS ,
8228 WINED3DRS_PATCHEDGESTYLE ,
8229 WINED3DRS_POINTSCALE_A ,
8230 WINED3DRS_POINTSCALE_B ,
8231 WINED3DRS_POINTSCALE_C ,
8232 WINED3DRS_POINTSCALEENABLE ,
8233 WINED3DRS_POINTSIZE ,
8234 WINED3DRS_POINTSIZE_MAX ,
8235 WINED3DRS_POINTSIZE_MIN ,
8236 WINED3DRS_POINTSPRITEENABLE ,
8237 WINED3DRS_RANGEFOGENABLE ,
8238 WINED3DRS_SPECULARMATERIALSOURCE ,
8239 WINED3DRS_TWEENFACTOR ,
8240 WINED3DRS_VERTEXBLEND
8243 const DWORD SavedVertexStates_T[NUM_SAVEDVERTEXSTATES_T] = {
8244 WINED3DTSS_TEXCOORDINDEX ,
8245 WINED3DTSS_TEXTURETRANSFORMFLAGS
8248 const DWORD SavedVertexStates_S[NUM_SAVEDVERTEXSTATES_S] = {
8249 WINED3DSAMP_DMAPOFFSET