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
11 * This library is free software; you can redistribute it and/or
12 * modify it under the terms of the GNU Lesser General Public
13 * License as published by the Free Software Foundation; either
14 * version 2.1 of the License, or (at your option) any later version.
16 * This library is distributed in the hope that it will be useful,
17 * but WITHOUT ANY WARRANTY; without even the implied warranty of
18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
19 * Lesser General Public License for more details.
21 * You should have received a copy of the GNU Lesser General Public
22 * License along with this library; if not, write to the Free Software
23 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
31 #include "wined3d_private.h"
33 WINE_DEFAULT_DEBUG_CHANNEL(d3d);
34 WINE_DECLARE_DEBUG_CHANNEL(d3d_shader);
35 #define GLINFO_LOCATION ((IWineD3DImpl *)(This->wineD3D))->gl_info
37 /* Define the default light parameters as specified by MSDN */
38 const WINED3DLIGHT WINED3D_default_light = {
40 D3DLIGHT_DIRECTIONAL, /* Type */
41 { 1.0, 1.0, 1.0, 0.0 }, /* Diffuse r,g,b,a */
42 { 0.0, 0.0, 0.0, 0.0 }, /* Specular r,g,b,a */
43 { 0.0, 0.0, 0.0, 0.0 }, /* Ambient r,g,b,a, */
44 { 0.0, 0.0, 0.0 }, /* Position x,y,z */
45 { 0.0, 0.0, 1.0 }, /* Direction x,y,z */
48 0.0, 0.0, 0.0, /* Attenuation 0,1,2 */
53 /* x11drv GDI escapes */
54 #define X11DRV_ESCAPE 6789
55 enum x11drv_escape_codes
57 X11DRV_GET_DISPLAY, /* get X11 display for a DC */
58 X11DRV_GET_DRAWABLE, /* get current drawable for a DC */
59 X11DRV_GET_FONT, /* get current X font for a DC */
62 /* retrieve the X display to use on a given DC */
63 inline static Display *get_display( HDC hdc )
66 enum x11drv_escape_codes escape = X11DRV_GET_DISPLAY;
68 if (!ExtEscape( hdc, X11DRV_ESCAPE, sizeof(escape), (LPCSTR)&escape,
69 sizeof(display), (LPSTR)&display )) display = NULL;
73 /* Memory tracking and object counting */
74 static unsigned int emulated_textureram = 64*1024*1024;
76 /* TODO: setup some flags in the regestry to enable, disable pbuffer support */
77 /* enable pbuffer support for offscreen textures */
78 BOOL pbuffer_support = FALSE;
79 /* allocate one pbuffer per surface */
80 BOOL pbuffer_per_surface = FALSE;
82 /* static function declarations */
83 static void WINAPI IWineD3DDeviceImpl_AddResource(IWineD3DDevice *iface, IWineD3DResource *resource);
85 static void WINAPI IWineD3DDeviceImpl_ApplyTextureUnitState(IWineD3DDevice *iface, DWORD Stage, WINED3DTEXTURESTAGESTATETYPE Type);
88 #define D3DMEMCHECK(object, ppResult) if(NULL == object) { *ppResult = NULL; WARN("Out of memory\n"); return WINED3DERR_OUTOFVIDEOMEMORY;}
90 #define D3DCREATEOBJECTINSTANCE(object, type) { \
91 object=HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(IWineD3D##type##Impl)); \
92 D3DMEMCHECK(object, pp##type); \
93 object->lpVtbl = &IWineD3D##type##_Vtbl; \
94 object->wineD3DDevice = This; \
95 object->parent = parent; \
97 *pp##type = (IWineD3D##type *) object; \
100 #define D3DCREATERESOURCEOBJECTINSTANCE(object, type, d3dtype, _size){ \
101 object=HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(IWineD3D##type##Impl)); \
102 D3DMEMCHECK(object, pp##type); \
103 object->lpVtbl = &IWineD3D##type##_Vtbl; \
104 object->resource.wineD3DDevice = This; \
105 object->resource.parent = parent; \
106 object->resource.resourceType = d3dtype; \
107 object->resource.ref = 1; \
108 object->resource.pool = Pool; \
109 object->resource.format = Format; \
110 object->resource.usage = Usage; \
111 object->resource.size = _size; \
112 /* Check that we have enough video ram left */ \
113 if (Pool == WINED3DPOOL_DEFAULT) { \
114 if (IWineD3DDevice_GetAvailableTextureMem(iface) <= _size) { \
115 WARN("Out of 'bogus' video memory\n"); \
116 HeapFree(GetProcessHeap(), 0, object); \
118 return WINED3DERR_OUTOFVIDEOMEMORY; \
120 globalChangeGlRam(_size); \
122 object->resource.allocatedMemory = (0 == _size ? NULL : Pool == WINED3DPOOL_DEFAULT ? NULL : HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, _size)); \
123 if (object->resource.allocatedMemory == NULL && _size != 0 && Pool != WINED3DPOOL_DEFAULT) { \
124 FIXME("Out of memory!\n"); \
125 HeapFree(GetProcessHeap(), 0, object); \
127 return WINED3DERR_OUTOFVIDEOMEMORY; \
129 *pp##type = (IWineD3D##type *) object; \
130 IWineD3DDeviceImpl_AddResource(iface, (IWineD3DResource *)object) ;\
131 TRACE("(%p) : Created resource %p\n", This, object); \
134 #define D3DINITIALIZEBASETEXTURE(_basetexture) { \
135 _basetexture.levels = Levels; \
136 _basetexture.filterType = (Usage & WINED3DUSAGE_AUTOGENMIPMAP) ? WINED3DTEXF_LINEAR : WINED3DTEXF_NONE; \
137 _basetexture.LOD = 0; \
138 _basetexture.dirty = TRUE; \
141 /**********************************************************
142 * Global variable / Constants follow
143 **********************************************************/
144 const float identity[16] = {1,0,0,0, 0,1,0,0, 0,0,1,0, 0,0,0,1}; /* When needed for comparisons */
146 /**********************************************************
147 * Utility functions follow
148 **********************************************************/
149 /* Convert the D3DLIGHT properties into equivalent gl lights */
150 static void setup_light(IWineD3DDevice *iface, LONG Index, PLIGHTINFOEL *lightInfo) {
153 float colRGBA[] = {0.0, 0.0, 0.0, 0.0};
154 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
156 /* Light settings are affected by the model view in OpenGL, the View transform in direct3d*/
157 glMatrixMode(GL_MODELVIEW);
159 glLoadMatrixf((float *)&This->stateBlock->transforms[D3DTS_VIEW].u.m[0][0]);
162 colRGBA[0] = lightInfo->OriginalParms.Diffuse.r;
163 colRGBA[1] = lightInfo->OriginalParms.Diffuse.g;
164 colRGBA[2] = lightInfo->OriginalParms.Diffuse.b;
165 colRGBA[3] = lightInfo->OriginalParms.Diffuse.a;
166 glLightfv(GL_LIGHT0+Index, GL_DIFFUSE, colRGBA);
167 checkGLcall("glLightfv");
170 colRGBA[0] = lightInfo->OriginalParms.Specular.r;
171 colRGBA[1] = lightInfo->OriginalParms.Specular.g;
172 colRGBA[2] = lightInfo->OriginalParms.Specular.b;
173 colRGBA[3] = lightInfo->OriginalParms.Specular.a;
174 glLightfv(GL_LIGHT0+Index, GL_SPECULAR, colRGBA);
175 checkGLcall("glLightfv");
178 colRGBA[0] = lightInfo->OriginalParms.Ambient.r;
179 colRGBA[1] = lightInfo->OriginalParms.Ambient.g;
180 colRGBA[2] = lightInfo->OriginalParms.Ambient.b;
181 colRGBA[3] = lightInfo->OriginalParms.Ambient.a;
182 glLightfv(GL_LIGHT0+Index, GL_AMBIENT, colRGBA);
183 checkGLcall("glLightfv");
185 /* Attenuation - Are these right? guessing... */
186 glLightf(GL_LIGHT0+Index, GL_CONSTANT_ATTENUATION, lightInfo->OriginalParms.Attenuation0);
187 checkGLcall("glLightf");
188 glLightf(GL_LIGHT0+Index, GL_LINEAR_ATTENUATION, lightInfo->OriginalParms.Attenuation1);
189 checkGLcall("glLightf");
191 if ((lightInfo->OriginalParms.Range *lightInfo->OriginalParms.Range) >= FLT_MIN) {
192 quad_att = 1.4/(lightInfo->OriginalParms.Range *lightInfo->OriginalParms.Range);
194 quad_att = 0; /* 0 or MAX? (0 seems to be ok) */
197 if (quad_att < lightInfo->OriginalParms.Attenuation2) quad_att = lightInfo->OriginalParms.Attenuation2;
198 glLightf(GL_LIGHT0+Index, GL_QUADRATIC_ATTENUATION, quad_att);
199 checkGLcall("glLightf");
201 switch (lightInfo->OriginalParms.Type) {
204 glLightfv(GL_LIGHT0+Index, GL_POSITION, &lightInfo->lightPosn[0]);
205 checkGLcall("glLightfv");
206 glLightf(GL_LIGHT0 + Index, GL_SPOT_CUTOFF, lightInfo->cutoff);
207 checkGLcall("glLightf");
213 glLightfv(GL_LIGHT0+Index, GL_POSITION, &lightInfo->lightPosn[0]);
214 checkGLcall("glLightfv");
216 glLightfv(GL_LIGHT0+Index, GL_SPOT_DIRECTION, &lightInfo->lightDirn[0]);
217 checkGLcall("glLightfv");
218 glLightf(GL_LIGHT0 + Index, GL_SPOT_EXPONENT, lightInfo->exponent);
219 checkGLcall("glLightf");
220 glLightf(GL_LIGHT0 + Index, GL_SPOT_CUTOFF, lightInfo->cutoff);
221 checkGLcall("glLightf");
225 case D3DLIGHT_DIRECTIONAL:
227 glLightfv(GL_LIGHT0+Index, GL_POSITION, &lightInfo->lightPosn[0]); /* Note gl uses w position of 0 for direction! */
228 checkGLcall("glLightfv");
229 glLightf(GL_LIGHT0+Index, GL_SPOT_CUTOFF, lightInfo->cutoff);
230 checkGLcall("glLightf");
231 glLightf(GL_LIGHT0+Index, GL_SPOT_EXPONENT, 0.0f);
232 checkGLcall("glLightf");
236 FIXME("Unrecognized light type %d\n", lightInfo->OriginalParms.Type);
239 /* Restore the modelview matrix */
243 /**********************************************************
244 * GLSL helper functions follow
245 **********************************************************/
247 /** Attach a GLSL pixel or vertex shader object to the shader program */
248 static void attach_glsl_shader(IWineD3DDevice *iface, IWineD3DBaseShader* shader) {
250 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
251 GLhandleARB shaderObj = ((IWineD3DBaseShaderImpl*)shader)->baseShader.prgId;
252 if (This->stateBlock->shaderPrgId != 0 && shaderObj != 0) {
253 TRACE_(d3d_shader)("Attaching GLSL shader object %u to program %u\n", shaderObj, This->stateBlock->shaderPrgId);
254 GL_EXTCALL(glAttachObjectARB(This->stateBlock->shaderPrgId, shaderObj));
255 checkGLcall("glAttachObjectARB");
259 /** Sets the GLSL program ID for the given pixel and vertex shader combination.
260 * It sets the programId on the current StateBlock (because it should be called
261 * inside of the DrawPrimitive() part of the render loop).
263 * If a program for the given combination does not exist, create one, and store
264 * the program in the list. If it creates a program, it will link the given
267 * We keep the shader programs around on a list because linking
268 * shader objects together is an expensive operation. It's much
269 * faster to loop through a list of pre-compiled & linked programs
270 * each time that the application sets a new pixel or vertex shader
271 * than it is to re-link them together at that time.
273 * The list will be deleted in IWineD3DDevice::Release().
275 void set_glsl_shader_program(IWineD3DDevice *iface) {
277 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
278 IWineD3DPixelShader *pshader = This->stateBlock->pixelShader;
279 IWineD3DVertexShader *vshader = This->stateBlock->vertexShader;
280 struct glsl_shader_prog_link *curLink = NULL;
281 struct glsl_shader_prog_link *newLink = NULL;
282 struct list *ptr = NULL;
283 GLhandleARB programId = 0;
285 if (NULL == vshader && NULL == pshader) {
286 /* No pixel or vertex shader specified */
287 This->stateBlock->shaderPrgId = 0;
291 ptr = list_head( &This->glsl_shader_progs );
293 /* At least one program exists - see if it matches our ps/vs combination */
294 curLink = LIST_ENTRY( ptr, struct glsl_shader_prog_link, entry );
295 if (vshader == curLink->vertexShader && pshader == curLink->pixelShader) {
296 /* Existing Program found, use it */
297 TRACE_(d3d_shader)("Found existing program (%u) for this vertex/pixel shader combination\n",
299 This->stateBlock->shaderPrgId = curLink->programId;
302 /* This isn't the entry we need - try the next one */
303 ptr = list_next( &This->glsl_shader_progs, ptr );
306 /* If we get to this point, then no matching program exists, so we create one */
307 programId = GL_EXTCALL(glCreateProgramObjectARB());
308 TRACE_(d3d_shader)("Created new GLSL shader program %u\n", programId);
309 This->stateBlock->shaderPrgId = programId;
311 if (NULL != vshader) {
313 int max_attribs = 16; /* TODO: Will this always be the case? It is at the moment... */
316 attach_glsl_shader(iface, (IWineD3DBaseShader*)vshader);
318 /* Bind vertex attributes to a corresponding index number to match
319 * the same index numbers as ARB_vertex_programs (makes loading
320 * vertex attributes simpler). With this method, we can use the
321 * exact same code to load the attributes later for both ARB and
324 * We have to do this here because we need to know the Program ID
325 * in order to make the bindings work, and it has to be done prior
326 * to linking the GLSL program. */
327 for (i = 0; i < max_attribs; ++i) {
328 snprintf(tmp_name, sizeof(tmp_name), "attrib%i", i);
329 GL_EXTCALL(glBindAttribLocationARB(programId, i, tmp_name));
331 checkGLcall("glBindAttribLocationARB");
334 if (NULL != pshader) {
335 attach_glsl_shader(iface, (IWineD3DBaseShader*)pshader);
338 /* Link the program */
339 TRACE_(d3d_shader)("Linking GLSL shader program %u\n", programId);
340 GL_EXTCALL(glLinkProgramARB(programId));
341 print_glsl_info_log(&GLINFO_LOCATION, programId);
343 /* Now, we add a list item to associate this program with the vertex and
344 * pixel shaders that it is attached to.
346 * These list items will be deleted when the device is released.
348 newLink = HeapAlloc(GetProcessHeap(), 0, sizeof(struct glsl_shader_prog_link));
349 newLink->programId = programId;
350 newLink->pixelShader = pshader;
351 newLink->vertexShader = vshader;
352 list_add_head( &This->glsl_shader_progs, &newLink->entry);
357 /** Detach the GLSL pixel or vertex shader object from the shader program */
358 static void detach_glsl_shader(IWineD3DDevice *iface, GLhandleARB shaderObj, GLhandleARB programId) {
360 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
362 if (shaderObj != 0 && programId != 0) {
363 TRACE_(d3d_shader)("Detaching GLSL shader object %u from program %u\n", shaderObj, programId);
364 GL_EXTCALL(glDetachObjectARB(programId, shaderObj));
365 checkGLcall("glDetachObjectARB");
369 /** Delete a GLSL shader program */
370 static void delete_glsl_shader_program(IWineD3DDevice *iface, GLhandleARB obj) {
372 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
375 TRACE_(d3d_shader)("Deleting GLSL shader program %u\n", obj);
376 GL_EXTCALL(glDeleteObjectARB(obj));
377 checkGLcall("glDeleteObjectARB");
381 /** Delete the list of linked programs this shader is associated with.
382 * Also at this point, check to see if there are any objects left attached
383 * to each GLSL program. If not, delete the GLSL program object.
384 * This will be run when a device is released. */
385 static void delete_glsl_shader_list(IWineD3DDevice* iface) {
387 struct list *ptr = NULL;
388 struct glsl_shader_prog_link *curLink = NULL;
389 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
393 GLhandleARB objList[2]; /* There should never be more than 2 objects attached
394 (one pixel shader and one vertex shader at most) */
396 ptr = list_head( &This->glsl_shader_progs );
398 /* First, get the current item,
399 * save the link to the next pointer,
400 * detach and delete shader objects,
401 * then de-allocate the list item's memory */
402 curLink = LIST_ENTRY( ptr, struct glsl_shader_prog_link, entry );
403 ptr = list_next( &This->glsl_shader_progs, ptr );
405 /* See if this object is still attached to the program - it may have been detached already */
406 GL_EXTCALL(glGetAttachedObjectsARB(curLink->programId, 2, &numAttached, objList));
407 TRACE_(d3d_shader)("%i GLSL objects are currently attached to program %u\n", numAttached, curLink->programId);
408 for (i = 0; i < numAttached; i++) {
409 detach_glsl_shader(iface, objList[i], curLink->programId);
412 delete_glsl_shader_program(iface, curLink->programId);
414 /* Free the memory for this list item */
415 HeapFree(GetProcessHeap(), 0, curLink);
420 /* Apply the current values to the specified texture stage */
421 void WINAPI IWineD3DDeviceImpl_SetupTextureStates(IWineD3DDevice *iface, DWORD Sampler, DWORD Flags) {
422 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
430 /* In addition, IDirect3DDevice9::SetSamplerState will now be used for filtering, tiling,
431 clamping, MIPLOD, etc. This will work for up to 16 samplers.
434 if (Sampler >= GL_LIMITS(samplers)) {
435 FIXME("Trying to set the state of more samplers %ld than are supported %d by this openGL implementation\n", Sampler, GL_LIMITS(samplers));
438 VTRACE(("Activating appropriate texture state %ld\n", Sampler));
439 if (GL_SUPPORT(ARB_MULTITEXTURE)) {
441 GL_EXTCALL(glActiveTextureARB(GL_TEXTURE0_ARB + Sampler));
442 checkGLcall("glActiveTextureARB");
444 /* Could we use bindTexture and then apply the states instead of GLACTIVETEXTURE */
445 } else if (Sampler > 0) {
446 FIXME("Program using multiple concurrent textures which this opengl implementation doesn't support\n");
450 /* TODO: change this to a lookup table
451 LOOKUP_TEXTURE_STATES lists all texture states that should be applied.
452 LOOKUP_CONTEXT_SATES list all context applicable states that can be applied
453 etc.... it's a lot cleaner, quicker and possibly easier to maintain than running a switch and setting a skip flag...
454 especially when there are a number of groups of states. */
456 TRACE("-----------------------> Updating the texture at Sampler %ld to have new texture state information\n", Sampler);
458 /* 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 */
459 #define APPLY_STATE(_state) IWineD3DDeviceImpl_ApplyTextureUnitState(iface, Sampler, _state)
460 /* these are the only two supported states that need to be applied */
461 APPLY_STATE(WINED3DTSS_TEXCOORDINDEX);
462 APPLY_STATE(WINED3DTSS_TEXTURETRANSFORMFLAGS);
463 #if 0 /* not supported at the moment */
464 APPLY_STATE(WINED3DTSS_BUMPENVMAT00);
465 APPLY_STATE(WINED3DTSS_BUMPENVMAT01);
466 APPLY_STATE(WINED3DTSS_BUMPENVMAT10);
467 APPLY_STATE(WINED3DTSS_BUMPENVMAT11);
468 APPLY_STATE(WINED3DTSS_BUMPENVLSCALE);
469 APPLY_STATE(WINED3DTSS_BUMPENVLOFFSET);
470 APPLY_STATE(WINED3DTSS_RESULTARG);
471 APPLY_STATE(WINED3DTSS_CONSTANT);
473 /* a quick sanity check in case someone forgot to update this function */
474 if (WINED3D_HIGHEST_TEXTURE_STATE > WINED3DTSS_CONSTANT) {
475 FIXME("(%p) : There are more texture states than expected, update device.c to match\n", This);
479 /* apply any sampler states that always need applying */
480 if (GL_SUPPORT(EXT_TEXTURE_LOD_BIAS)) {
481 tmpvalue.d = This->stateBlock->samplerState[Sampler][WINED3DSAMP_MIPMAPLODBIAS];
482 glTexEnvf(GL_TEXTURE_FILTER_CONTROL_EXT,
483 GL_TEXTURE_LOD_BIAS_EXT,
485 checkGLcall("glTexEnvi GL_TEXTURE_LOD_BIAS_EXT ...");
488 /* Note the D3DRS value applies to all textures, but GL has one
489 * per texture, so apply it now ready to be used!
491 D3DCOLORTOGLFLOAT4(This->stateBlock->renderState[WINED3DRS_TEXTUREFACTOR], col);
492 /* Set the default alpha blend color */
493 if (GL_SUPPORT(ARB_IMAGING)) {
494 GL_EXTCALL(glBlendColor(col[0], col[1], col[2], col[3]));
495 checkGLcall("glBlendColor");
497 WARN("Unsupported in local OpenGL implementation: glBlendColor\n");
500 D3DCOLORTOGLFLOAT4(This->stateBlock->renderState[WINED3DRS_TEXTUREFACTOR], col);
501 glTexEnvfv(GL_TEXTURE_ENV, GL_TEXTURE_ENV_COLOR, &col[0]);
502 checkGLcall("glTexEnvfv(GL_TEXTURE_ENV, GL_TEXTURE_ENV_COLOR, color);");
504 /* TODO: NV_POINT_SPRITE */
505 if (GL_SUPPORT(ARB_POINT_SPRITE)) {
506 if (This->stateBlock->renderState[WINED3DRS_POINTSPRITEENABLE] != FALSE) {
507 /* Doesn't work with GL_POINT_SMOOTH on on my ATI 9600, but then ATI drivers are buggered! */
508 glDisable(GL_POINT_SMOOTH);
510 /* Centre the texture on the vertex */
511 VTRACE(("glTexEnvf( GL_POINT_SPRITE_ARB, GL_COORD_REPLACE_ARB, GL_TRUE)\n"));
512 glTexEnvf( GL_POINT_SPRITE_ARB, GL_COORD_REPLACE_ARB, GL_TRUE);
514 VTRACE(("glTexEnvf( GL_POINT_SPRITE_ARB, GL_COORD_REPLACE_ARB, GL_TRUE)\n"));
515 glTexEnvf( GL_POINT_SPRITE_ARB, GL_COORD_REPLACE_ARB, GL_TRUE);
516 checkGLcall("glTexEnvf(...)");
517 VTRACE(("glEnable( GL_POINT_SPRITE_ARB )\n"));
518 glEnable( GL_POINT_SPRITE_ARB );
519 checkGLcall("glEnable(...)");
521 VTRACE(("glDisable( GL_POINT_SPRITE_ARB )\n"));
522 glDisable( GL_POINT_SPRITE_ARB );
523 checkGLcall("glEnable(...)");
527 TRACE("-----------------------> Updated the texture at Sampler %ld to have new texture state information\n", Sampler);
530 /**********************************************************
531 * IUnknown parts follows
532 **********************************************************/
534 HRESULT WINAPI IWineD3DDeviceImpl_QueryInterface(IWineD3DDevice *iface,REFIID riid,LPVOID *ppobj)
536 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
538 TRACE("(%p)->(%s,%p)\n",This,debugstr_guid(riid),ppobj);
539 if (IsEqualGUID(riid, &IID_IUnknown)
540 || IsEqualGUID(riid, &IID_IWineD3DBase)
541 || IsEqualGUID(riid, &IID_IWineD3DDevice)) {
542 IUnknown_AddRef(iface);
547 return E_NOINTERFACE;
550 ULONG WINAPI IWineD3DDeviceImpl_AddRef(IWineD3DDevice *iface) {
551 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
552 ULONG refCount = InterlockedIncrement(&This->ref);
554 TRACE("(%p) : AddRef increasing from %ld\n", This, refCount - 1);
558 ULONG WINAPI IWineD3DDeviceImpl_Release(IWineD3DDevice *iface) {
559 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
560 ULONG refCount = InterlockedDecrement(&This->ref);
562 TRACE("(%p) : Releasing from %ld\n", This, refCount + 1);
565 /* TODO: Clean up all the surfaces and textures! */
566 /* NOTE: You must release the parent if the object was created via a callback
567 ** ***************************/
569 /* Delete any GLSL shader programs that may exist */
570 if (wined3d_settings.shader_mode == SHADER_GLSL) {
571 delete_glsl_shader_list(iface);
574 /* Release the update stateblock */
575 if(IWineD3DStateBlock_Release((IWineD3DStateBlock *)This->updateStateBlock) > 0){
576 if(This->updateStateBlock != This->stateBlock)
577 FIXME("(%p) Something's still holding the Update stateblock\n",This);
579 This->updateStateBlock = NULL;
580 { /* because were not doing proper internal refcounts releasing the primary state block
581 causes recursion with the extra checks in ResourceReleased, to avoid this we have
582 to set this->stateBlock = NULL; first */
583 IWineD3DStateBlock *stateBlock = (IWineD3DStateBlock *)This->stateBlock;
584 This->stateBlock = NULL;
586 /* Release the stateblock */
587 if(IWineD3DStateBlock_Release(stateBlock) > 0){
588 FIXME("(%p) Something's still holding the Update stateblock\n",This);
592 if (This->resources != NULL ) {
593 FIXME("(%p) Device released with resources still bound, acceptable but unexpected\n", This);
594 dumpResources(This->resources);
598 IWineD3D_Release(This->wineD3D);
599 This->wineD3D = NULL;
600 HeapFree(GetProcessHeap(), 0, This);
601 TRACE("Freed device %p\n", This);
607 /**********************************************************
608 * IWineD3DDevice implementation follows
609 **********************************************************/
610 HRESULT WINAPI IWineD3DDeviceImpl_GetParent(IWineD3DDevice *iface, IUnknown **pParent) {
611 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
612 *pParent = This->parent;
613 IUnknown_AddRef(This->parent);
617 HRESULT WINAPI IWineD3DDeviceImpl_CreateVertexBuffer(IWineD3DDevice *iface, UINT Size, DWORD Usage,
618 DWORD FVF, WINED3DPOOL Pool, IWineD3DVertexBuffer** ppVertexBuffer, HANDLE *sharedHandle,
620 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
621 IWineD3DVertexBufferImpl *object;
622 WINED3DFORMAT Format = WINED3DFMT_VERTEXDATA; /* Dummy format for now */
623 D3DCREATERESOURCEOBJECTINSTANCE(object, VertexBuffer, WINED3DRTYPE_VERTEXBUFFER, Size)
626 if (Pool == WINED3DPOOL_DEFAULT ) { /* Allocate some system memory for now */
627 object->resource.allocatedMemory = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, object->resource.size);
631 TRACE("(%p) : Size=%d, Usage=%ld, FVF=%lx, Pool=%d - Memory@%p, Iface@%p\n", This, Size, Usage, FVF, Pool, object->resource.allocatedMemory, object);
632 *ppVertexBuffer = (IWineD3DVertexBuffer *)object;
637 HRESULT WINAPI IWineD3DDeviceImpl_CreateIndexBuffer(IWineD3DDevice *iface, UINT Length, DWORD Usage,
638 WINED3DFORMAT Format, WINED3DPOOL Pool, IWineD3DIndexBuffer** ppIndexBuffer,
639 HANDLE *sharedHandle, IUnknown *parent) {
640 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
641 IWineD3DIndexBufferImpl *object;
642 TRACE("(%p) Creating index buffer\n", This);
644 /* Allocate the storage for the device */
645 D3DCREATERESOURCEOBJECTINSTANCE(object,IndexBuffer,WINED3DRTYPE_INDEXBUFFER, Length)
648 if (Pool == WINED3DPOOL_DEFAULT ) { /* Allocate some system memory for now */
649 object->resource.allocatedMemory = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,object->resource.size);
652 TRACE("(%p) : Len=%d, Use=%lx, Format=(%u,%s), Pool=%d - Memory@%p, Iface@%p\n", This, Length, Usage, Format,
653 debug_d3dformat(Format), Pool, object, object->resource.allocatedMemory);
654 *ppIndexBuffer = (IWineD3DIndexBuffer *) object;
659 HRESULT WINAPI IWineD3DDeviceImpl_CreateStateBlock(IWineD3DDevice* iface, WINED3DSTATEBLOCKTYPE Type, IWineD3DStateBlock** ppStateBlock, IUnknown *parent) {
661 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
662 IWineD3DStateBlockImpl *object;
665 D3DCREATEOBJECTINSTANCE(object, StateBlock)
666 object->blockType = Type;
668 /* Special case - Used during initialization to produce a placeholder stateblock
669 so other functions called can update a state block */
670 if (Type == WINED3DSBT_INIT) {
671 /* Don't bother increasing the reference count otherwise a device will never
672 be freed due to circular dependencies */
676 /* Otherwise, might as well set the whole state block to the appropriate values */
677 if ( This->stateBlock != NULL) {
678 memcpy(object, This->stateBlock, sizeof(IWineD3DStateBlockImpl));
680 memset(object->streamFreq, 1, sizeof(object->streamFreq));
683 /* Reset the ref and type after kludging it */
684 object->wineD3DDevice = This;
686 object->blockType = Type;
688 TRACE("Updating changed flags appropriate for type %d\n", Type);
690 if (Type == WINED3DSBT_ALL) {
692 TRACE("ALL => Pretend everything has changed\n");
693 memset(&object->changed, TRUE, sizeof(This->stateBlock->changed));
694 } else if (Type == WINED3DSBT_PIXELSTATE) {
696 TRACE("PIXELSTATE => Pretend all pixel shates have changed\n");
697 memset(&object->changed, FALSE, sizeof(This->stateBlock->changed));
699 object->changed.pixelShader = TRUE;
701 /* Pixel Shader Constants */
702 for (i = 0; i < MAX_PSHADER_CONSTANTS; ++i) {
703 object->changed.pixelShaderConstantsF[i] = TRUE;
704 object->changed.pixelShaderConstantsB[i] = TRUE;
705 object->changed.pixelShaderConstantsI[i] = TRUE;
707 for (i = 0; i < NUM_SAVEDPIXELSTATES_R; i++) {
708 object->changed.renderState[SavedPixelStates_R[i]] = TRUE;
710 for (j = 0; j < GL_LIMITS(textures); j++) {
711 for (i = 0; i < NUM_SAVEDPIXELSTATES_T; i++) {
712 object->changed.textureState[j][SavedPixelStates_T[i]] = TRUE;
715 for (j = 0 ; j < 16; j++) {
716 for (i =0; i < NUM_SAVEDPIXELSTATES_S;i++) {
718 object->changed.samplerState[j][SavedPixelStates_S[i]] = TRUE;
722 } else if (Type == WINED3DSBT_VERTEXSTATE) {
724 TRACE("VERTEXSTATE => Pretend all vertex shates have changed\n");
725 memset(&object->changed, FALSE, sizeof(This->stateBlock->changed));
727 object->changed.vertexShader = TRUE;
729 /* Vertex Shader Constants */
730 for (i = 0; i < MAX_VSHADER_CONSTANTS; ++i) {
731 object->changed.vertexShaderConstantsF[i] = TRUE;
732 object->changed.vertexShaderConstantsB[i] = TRUE;
733 object->changed.vertexShaderConstantsI[i] = TRUE;
735 for (i = 0; i < NUM_SAVEDVERTEXSTATES_R; i++) {
736 object->changed.renderState[SavedVertexStates_R[i]] = TRUE;
738 for (j = 0; j < GL_LIMITS(textures); j++) {
739 for (i = 0; i < NUM_SAVEDVERTEXSTATES_T; i++) {
740 object->changed.textureState[j][SavedVertexStates_T[i]] = TRUE;
743 for (j = 0 ; j < 16; j++){
744 for (i =0; i < NUM_SAVEDVERTEXSTATES_S;i++) {
745 object->changed.samplerState[j][SavedVertexStates_S[i]] = TRUE;
749 /* Duplicate light chain */
751 PLIGHTINFOEL *src = NULL;
752 PLIGHTINFOEL *dst = NULL;
753 PLIGHTINFOEL *newEl = NULL;
754 src = This->stateBlock->lights;
755 object->lights = NULL;
759 newEl = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(PLIGHTINFOEL));
760 if (newEl == NULL) return WINED3DERR_OUTOFVIDEOMEMORY;
761 memcpy(newEl, src, sizeof(PLIGHTINFOEL));
763 newEl->changed = TRUE;
764 newEl->enabledChanged = TRUE;
766 object->lights = newEl;
777 FIXME("Unrecognized state block type %d\n", Type);
780 TRACE("(%p) returning token (ptr to stateblock) of %p\n", This, object);
785 /* ************************************
787 [in] Render targets are not lockable unless the application specifies TRUE for Lockable. Note that lockable render targets reduce performance on some graphics hardware.
790 [in] Set this flag to TRUE to enable z-buffer discarding, and FALSE otherwise.
792 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.
794 ******************************** */
796 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) {
797 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
798 IWineD3DSurfaceImpl *object; /*NOTE: impl ref allowed since this is a create function */
799 unsigned int pow2Width, pow2Height;
800 unsigned int Size = 1;
801 TRACE("(%p) Create surface\n",This);
803 /** FIXME: Check ranges on the inputs are valid
806 * [in] Quality level. The valid range is between zero and one less than the level
807 * returned by pQualityLevels used by IDirect3D9::CheckDeviceMultiSampleType.
808 * Passing a larger value returns the error WINED3DERR_INVALIDCALL. The MultisampleQuality
809 * values of paired render targets, depth stencil surfaces, and the MultiSample type
811 *******************************/
816 * [in] Set this flag to TRUE to enable z-buffer discarding, and FALSE otherwise.
818 * If this flag is set, the contents of the depth stencil buffer will be
819 * invalid after calling either IDirect3DDevice9::Present or * IDirect3DDevice9::SetDepthStencilSurface
820 * with a different depth surface.
822 *This flag has the same behavior as the constant, D3DPRESENTFLAG_DISCARD_DEPTHSTENCIL, in D3DPRESENTFLAG.
823 ***************************/
825 if(MultisampleQuality < 0) {
826 FIXME("Invalid multisample level %ld\n", MultisampleQuality);
827 return WINED3DERR_INVALIDCALL; /* TODO: Check that this is the case! */
830 if(MultisampleQuality > 0) {
831 FIXME("MultisampleQuality set to %ld, substituting 0\n", MultisampleQuality);
832 MultisampleQuality=0;
835 /** FIXME: Check that the format is supported
837 *******************************/
839 /* Non-power2 support */
841 /* Find the nearest pow2 match */
842 pow2Width = pow2Height = 1;
843 while (pow2Width < Width) pow2Width <<= 1;
844 while (pow2Height < Height) pow2Height <<= 1;
846 if (pow2Width > Width || pow2Height > Height) {
847 /** TODO: add support for non power two compressed textures (OpenGL 2 provices support for * non-power-two textures gratis) **/
848 if (Format == WINED3DFMT_DXT1 || Format == WINED3DFMT_DXT2 || Format == WINED3DFMT_DXT3
849 || Format == WINED3DFMT_DXT4 || Format == WINED3DFMT_DXT5) {
850 FIXME("(%p) Compressed non-power-two textures are not supported w(%d) h(%d)\n",
851 This, Width, Height);
852 return WINED3DERR_NOTAVAILABLE;
856 /** DXTn mipmaps use the same number of 'levels' down to eg. 8x1, but since
857 * it is based around 4x4 pixel blocks it requires padding, so allocate enough
859 *********************************/
860 if (WINED3DFMT_UNKNOWN == Format) {
862 } else if (Format == WINED3DFMT_DXT1) {
863 /* DXT1 is half byte per pixel */
864 Size = ((max(pow2Width,4) * D3DFmtGetBpp(This, Format)) * max(pow2Height,4)) >> 1;
866 } else if (Format == WINED3DFMT_DXT2 || Format == WINED3DFMT_DXT3 ||
867 Format == WINED3DFMT_DXT4 || Format == WINED3DFMT_DXT5) {
868 Size = ((max(pow2Width,4) * D3DFmtGetBpp(This, Format)) * max(pow2Height,4));
870 Size = (pow2Width * D3DFmtGetBpp(This, Format)) * pow2Height;
873 /** Create and initialise the surface resource **/
874 D3DCREATERESOURCEOBJECTINSTANCE(object,Surface,WINED3DRTYPE_SURFACE, Size)
875 /* "Standalone" surface */
876 IWineD3DSurface_SetContainer((IWineD3DSurface *)object, NULL);
878 object->currentDesc.Width = Width;
879 object->currentDesc.Height = Height;
880 object->currentDesc.MultiSampleType = MultiSample;
881 object->currentDesc.MultiSampleQuality = MultisampleQuality;
883 /* Setup some glformat defaults */
884 if (WINED3DFMT_UNKNOWN != Format) {
885 object->glDescription.glFormat = D3DFmt2GLFmt(This, object->resource.format);
886 object->glDescription.glFormatInternal = D3DFmt2GLIntFmt(This, object->resource.format);
887 object->glDescription.glType = D3DFmt2GLType(This, object->resource.format);
889 object->glDescription.glFormat = 0;
890 object->glDescription.glFormatInternal = 0;
891 object->glDescription.glType = 0;
894 object->glDescription.textureName = 0;
895 object->glDescription.level = Level;
896 object->glDescription.target = GL_TEXTURE_2D;
899 object->pow2Width = pow2Width;
900 object->pow2Height = pow2Height;
903 object->Flags = 0; /* We start without flags set */
904 object->Flags |= (pow2Width != Width || pow2Height != Height) ? SFLAG_NONPOW2 : 0;
905 object->Flags |= Discard ? SFLAG_DISCARD : 0;
906 object->Flags |= (WINED3DFMT_D16_LOCKABLE == Format) ? SFLAG_LOCKABLE : 0;
907 object->Flags |= Lockable ? SFLAG_LOCKABLE : 0;
910 if (WINED3DFMT_UNKNOWN != Format) {
911 object->bytesPerPixel = D3DFmtGetBpp(This, Format);
912 object->pow2Size = (pow2Width * object->bytesPerPixel) * pow2Height;
914 object->bytesPerPixel = 0;
915 object->pow2Size = 0;
918 /** TODO: change this into a texture transform matrix so that it's processed in hardware **/
920 TRACE("Pool %d %d %d %d",Pool, WINED3DPOOL_DEFAULT, WINED3DPOOL_MANAGED, WINED3DPOOL_SYSTEMMEM);
922 /** Quick lockable sanity check TODO: remove this after surfaces, usage and locablility have been debugged properly
923 * this function is too deap to need to care about things like this.
924 * Levels need to be checked too, and possibly Type wince they all affect what can be done.
925 * ****************************************/
927 case WINED3DPOOL_SCRATCH:
928 if(Lockable == FALSE)
929 FIXME("Create suface called with a pool of SCRATCH and a Lockable of FALSE \
930 which are mutually exclusive, setting lockable to true\n");
933 case WINED3DPOOL_SYSTEMMEM:
934 if(Lockable == FALSE) FIXME("Create surface called with a pool of SYSTEMMEM and a Lockable of FALSE, \
935 this is acceptable but unexpected (I can't know how the surface can be usable!)\n");
936 case WINED3DPOOL_MANAGED:
937 if(Usage == WINED3DUSAGE_DYNAMIC) FIXME("Create surface called with a pool of MANAGED and a \
938 Usage of DYNAMIC which are mutually exclusive, not doing \
939 anything just telling you.\n");
941 case WINED3DPOOL_DEFAULT: /*TODO: Create offscreen plain can cause this check to fail..., find out if it should */
942 if(!(Usage & WINED3DUSAGE_DYNAMIC) && !(Usage & WINED3DUSAGE_RENDERTARGET)
943 && !(Usage && WINED3DUSAGE_DEPTHSTENCIL ) && Lockable)
944 WARN("Creating a surface with a POOL of DEFAULT with Lockable true, that doesn't specify DYNAMIC usage.\n");
947 FIXME("(%p) Unknown pool %d\n", This, Pool);
951 if (Usage & WINED3DUSAGE_RENDERTARGET && Pool != WINED3DPOOL_DEFAULT) {
952 FIXME("Trying to create a render target that isn't in the default pool\n");
955 /* mark the texture as dirty so that it get's loaded first time around*/
956 IWineD3DSurface_AddDirtyRect(*ppSurface, NULL);
957 TRACE("(%p) : w(%d) h(%d) fmt(%d,%s) lockable(%d) surf@%p, surfmem@%p, %d bytes\n",
958 This, Width, Height, Format, debug_d3dformat(Format),
959 (WINED3DFMT_D16_LOCKABLE == Format), *ppSurface, object->resource.allocatedMemory, object->resource.size);
961 /* Store the DirectDraw primary surface. This is the first rendertarget surface created */
962 if( (Usage & WINED3DUSAGE_RENDERTARGET) && (!This->ddraw_primary) )
963 This->ddraw_primary = (IWineD3DSurface *) object;
965 /* Look at the implementation and set the correct Vtable */
968 /* Nothing to do, it's set already */
972 object->lpVtbl = &IWineGDISurface_Vtbl;
976 /* To be sure to catch this */
977 ERR("Unknown requested surface implementation %d!\n", Impl);
978 IWineD3DSurface_Release((IWineD3DSurface *) object);
979 return WINED3DERR_INVALIDCALL;
982 /* Call the private setup routine */
983 return IWineD3DSurface_PrivateSetup( (IWineD3DSurface *) object );
987 HRESULT WINAPI IWineD3DDeviceImpl_CreateTexture(IWineD3DDevice *iface, UINT Width, UINT Height, UINT Levels,
988 DWORD Usage, WINED3DFORMAT Format, WINED3DPOOL Pool,
989 IWineD3DTexture** ppTexture, HANDLE* pSharedHandle, IUnknown *parent,
990 D3DCB_CREATESURFACEFN D3DCB_CreateSurface) {
992 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
993 IWineD3DTextureImpl *object;
998 unsigned int pow2Width = Width;
999 unsigned int pow2Height = Height;
1002 TRACE("(%p), Width(%d) Height(%d) Levels(%d) Usage(%ld) ....\n", This, Width, Height, Levels, Usage);
1004 /* TODO: It should only be possible to create textures for formats
1005 that are reported as supported */
1006 if (WINED3DFMT_UNKNOWN >= Format) {
1007 WARN("(%p) : Texture cannot be created with a format of D3DFMT_UNKNOWN\n", This);
1008 return WINED3DERR_INVALIDCALL;
1011 D3DCREATERESOURCEOBJECTINSTANCE(object, Texture, WINED3DRTYPE_TEXTURE, 0);
1012 D3DINITIALIZEBASETEXTURE(object->baseTexture);
1013 object->width = Width;
1014 object->height = Height;
1016 /** Non-power2 support **/
1017 /* Find the nearest pow2 match */
1018 pow2Width = pow2Height = 1;
1019 while (pow2Width < Width) pow2Width <<= 1;
1020 while (pow2Height < Height) pow2Height <<= 1;
1022 /** FIXME: add support for real non-power-two if it's provided by the video card **/
1023 /* Precalculated scaling for 'faked' non power of two texture coords */
1024 object->pow2scalingFactorX = (((float)Width) / ((float)pow2Width));
1025 object->pow2scalingFactorY = (((float)Height) / ((float)pow2Height));
1026 TRACE(" xf(%f) yf(%f)\n", object->pow2scalingFactorX, object->pow2scalingFactorY);
1028 /* Calculate levels for mip mapping */
1030 TRACE("calculating levels %d\n", object->baseTexture.levels);
1031 object->baseTexture.levels++;
1034 while (tmpW > 1 || tmpH > 1) {
1035 tmpW = max(1, tmpW >> 1);
1036 tmpH = max(1, tmpH >> 1);
1037 object->baseTexture.levels++;
1039 TRACE("Calculated levels = %d\n", object->baseTexture.levels);
1042 /* Generate all the surfaces */
1045 for (i = 0; i < object->baseTexture.levels; i++)
1047 /* use the callback to create the texture surface */
1048 hr = D3DCB_CreateSurface(This->parent, tmpW, tmpH, Format, Usage, Pool, i, &object->surfaces[i],NULL);
1049 if (hr!= WINED3D_OK || ( (IWineD3DSurfaceImpl *) object->surfaces[i])->Flags & SFLAG_OVERSIZE) {
1050 FIXME("Failed to create surface %p\n", object);
1052 object->surfaces[i] = NULL;
1053 IWineD3DTexture_Release((IWineD3DTexture *)object);
1059 IWineD3DSurface_SetContainer(object->surfaces[i], (IWineD3DBase *)object);
1060 TRACE("Created surface level %d @ %p\n", i, object->surfaces[i]);
1061 /* calculate the next mipmap level */
1062 tmpW = max(1, tmpW >> 1);
1063 tmpH = max(1, tmpH >> 1);
1066 TRACE("(%p) : Created texture %p\n", This, object);
1070 HRESULT WINAPI IWineD3DDeviceImpl_CreateVolumeTexture(IWineD3DDevice *iface,
1071 UINT Width, UINT Height, UINT Depth,
1072 UINT Levels, DWORD Usage,
1073 WINED3DFORMAT Format, WINED3DPOOL Pool,
1074 IWineD3DVolumeTexture **ppVolumeTexture,
1075 HANDLE *pSharedHandle, IUnknown *parent,
1076 D3DCB_CREATEVOLUMEFN D3DCB_CreateVolume) {
1078 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
1079 IWineD3DVolumeTextureImpl *object;
1085 /* TODO: It should only be possible to create textures for formats
1086 that are reported as supported */
1087 if (WINED3DFMT_UNKNOWN >= Format) {
1088 WARN("(%p) : Texture cannot be created with a format of D3DFMT_UNKNOWN\n", This);
1089 return WINED3DERR_INVALIDCALL;
1092 D3DCREATERESOURCEOBJECTINSTANCE(object, VolumeTexture, WINED3DRTYPE_VOLUMETEXTURE, 0);
1093 D3DINITIALIZEBASETEXTURE(object->baseTexture);
1095 TRACE("(%p) : W(%d) H(%d) D(%d), Lvl(%d) Usage(%ld), Fmt(%u,%s), Pool(%s)\n", This, Width, Height,
1096 Depth, Levels, Usage, Format, debug_d3dformat(Format), debug_d3dpool(Pool));
1098 object->width = Width;
1099 object->height = Height;
1100 object->depth = Depth;
1102 /* Calculate levels for mip mapping */
1104 object->baseTexture.levels++;
1108 while (tmpW > 1 || tmpH > 1 || tmpD > 1) {
1109 tmpW = max(1, tmpW >> 1);
1110 tmpH = max(1, tmpH >> 1);
1111 tmpD = max(1, tmpD >> 1);
1112 object->baseTexture.levels++;
1114 TRACE("Calculated levels = %d\n", object->baseTexture.levels);
1117 /* Generate all the surfaces */
1122 for (i = 0; i < object->baseTexture.levels; i++)
1124 /* Create the volume */
1125 D3DCB_CreateVolume(This->parent, Width, Height, Depth, Format, Pool, Usage,
1126 (IWineD3DVolume **)&object->volumes[i], pSharedHandle);
1128 /* Set it's container to this object */
1129 IWineD3DVolume_SetContainer(object->volumes[i], (IWineD3DBase *)object);
1131 /* calcualte the next mipmap level */
1132 tmpW = max(1, tmpW >> 1);
1133 tmpH = max(1, tmpH >> 1);
1134 tmpD = max(1, tmpD >> 1);
1137 *ppVolumeTexture = (IWineD3DVolumeTexture *) object;
1138 TRACE("(%p) : Created volume texture %p\n", This, object);
1142 HRESULT WINAPI IWineD3DDeviceImpl_CreateVolume(IWineD3DDevice *iface,
1143 UINT Width, UINT Height, UINT Depth,
1145 WINED3DFORMAT Format, WINED3DPOOL Pool,
1146 IWineD3DVolume** ppVolume,
1147 HANDLE* pSharedHandle, IUnknown *parent) {
1149 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
1150 IWineD3DVolumeImpl *object; /** NOTE: impl ref allowed since this is a create function **/
1152 D3DCREATERESOURCEOBJECTINSTANCE(object, Volume, WINED3DRTYPE_VOLUME, ((Width * D3DFmtGetBpp(This, Format)) * Height * Depth))
1154 TRACE("(%p) : W(%d) H(%d) D(%d), Usage(%ld), Fmt(%u,%s), Pool(%s)\n", This, Width, Height,
1155 Depth, Usage, Format, debug_d3dformat(Format), debug_d3dpool(Pool));
1157 object->currentDesc.Width = Width;
1158 object->currentDesc.Height = Height;
1159 object->currentDesc.Depth = Depth;
1160 object->bytesPerPixel = D3DFmtGetBpp(This, Format);
1162 /** Note: Volume textures cannot be dxtn, hence no need to check here **/
1163 object->lockable = TRUE;
1164 object->locked = FALSE;
1165 memset(&object->lockedBox, 0, sizeof(WINED3DBOX));
1166 object->dirty = TRUE;
1168 return IWineD3DVolume_AddDirtyBox((IWineD3DVolume *) object, NULL);
1171 HRESULT WINAPI IWineD3DDeviceImpl_CreateCubeTexture(IWineD3DDevice *iface, UINT EdgeLength,
1172 UINT Levels, DWORD Usage,
1173 WINED3DFORMAT Format, WINED3DPOOL Pool,
1174 IWineD3DCubeTexture **ppCubeTexture,
1175 HANDLE *pSharedHandle, IUnknown *parent,
1176 D3DCB_CREATESURFACEFN D3DCB_CreateSurface) {
1178 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
1179 IWineD3DCubeTextureImpl *object; /** NOTE: impl ref allowed since this is a create function **/
1183 unsigned int pow2EdgeLength = EdgeLength;
1185 /* TODO: It should only be possible to create textures for formats
1186 that are reported as supported */
1187 if (WINED3DFMT_UNKNOWN >= Format) {
1188 WARN("(%p) : Texture cannot be created with a format of D3DFMT_UNKNOWN\n", This);
1189 return WINED3DERR_INVALIDCALL;
1192 D3DCREATERESOURCEOBJECTINSTANCE(object, CubeTexture, WINED3DRTYPE_CUBETEXTURE, 0);
1193 D3DINITIALIZEBASETEXTURE(object->baseTexture);
1195 TRACE("(%p) Create Cube Texture\n", This);
1197 /** Non-power2 support **/
1199 /* Find the nearest pow2 match */
1201 while (pow2EdgeLength < EdgeLength) pow2EdgeLength <<= 1;
1203 object->edgeLength = EdgeLength;
1204 /* TODO: support for native non-power 2 */
1205 /* Precalculated scaling for 'faked' non power of two texture coords */
1206 object->pow2scalingFactor = ((float)EdgeLength) / ((float)pow2EdgeLength);
1208 /* Calculate levels for mip mapping */
1210 object->baseTexture.levels++;
1213 tmpW = max(1, tmpW >> 1);
1214 object->baseTexture.levels++;
1216 TRACE("Calculated levels = %d\n", object->baseTexture.levels);
1219 /* Generate all the surfaces */
1221 for (i = 0; i < object->baseTexture.levels; i++) {
1223 /* Create the 6 faces */
1224 for (j = 0; j < 6; j++) {
1226 hr=D3DCB_CreateSurface(This->parent, tmpW, tmpW, Format, Usage, Pool,
1227 i /* Level */, &object->surfaces[j][i],pSharedHandle);
1229 if(hr!= WINED3D_OK) {
1233 for (l = 0; l < j; l++) {
1234 IWineD3DSurface_Release(object->surfaces[j][i]);
1236 for (k = 0; k < i; k++) {
1237 for (l = 0; l < 6; l++) {
1238 IWineD3DSurface_Release(object->surfaces[l][j]);
1242 FIXME("(%p) Failed to create surface\n",object);
1243 HeapFree(GetProcessHeap(),0,object);
1244 *ppCubeTexture = NULL;
1247 IWineD3DSurface_SetContainer(object->surfaces[j][i], (IWineD3DBase *)object);
1248 TRACE("Created surface level %d @ %p,\n", i, object->surfaces[j][i]);
1250 tmpW = max(1, tmpW >> 1);
1253 TRACE("(%p) : Created Cube Texture %p\n", This, object);
1254 *ppCubeTexture = (IWineD3DCubeTexture *) object;
1258 HRESULT WINAPI IWineD3DDeviceImpl_CreateQuery(IWineD3DDevice *iface, WINED3DQUERYTYPE Type, IWineD3DQuery **ppQuery, IUnknown* parent) {
1259 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
1260 IWineD3DQueryImpl *object; /*NOTE: impl ref allowed since this is a create function */
1262 if (NULL == ppQuery) {
1263 /* Just a check to see if we support this type of query */
1264 HRESULT hr = WINED3DERR_NOTAVAILABLE;
1266 case WINED3DQUERYTYPE_OCCLUSION:
1267 TRACE("(%p) occlusion query\n", This);
1268 if (GL_SUPPORT(ARB_OCCLUSION_QUERY) || GL_SUPPORT(NV_OCCLUSION_QUERY))
1271 WARN("Unsupported in local OpenGL implementation: ARB_OCCLUSION_QUERY/NV_OCCLUSION_QUERY\n");
1273 case WINED3DQUERYTYPE_VCACHE:
1274 case WINED3DQUERYTYPE_RESOURCEMANAGER:
1275 case WINED3DQUERYTYPE_VERTEXSTATS:
1276 case WINED3DQUERYTYPE_EVENT:
1277 case WINED3DQUERYTYPE_TIMESTAMP:
1278 case WINED3DQUERYTYPE_TIMESTAMPDISJOINT:
1279 case WINED3DQUERYTYPE_TIMESTAMPFREQ:
1280 case WINED3DQUERYTYPE_PIPELINETIMINGS:
1281 case WINED3DQUERYTYPE_INTERFACETIMINGS:
1282 case WINED3DQUERYTYPE_VERTEXTIMINGS:
1283 case WINED3DQUERYTYPE_PIXELTIMINGS:
1284 case WINED3DQUERYTYPE_BANDWIDTHTIMINGS:
1285 case WINED3DQUERYTYPE_CACHEUTILIZATION:
1287 FIXME("(%p) Unhandled query type %d\n", This, Type);
1292 D3DCREATEOBJECTINSTANCE(object, Query)
1293 object->type = Type;
1294 /* allocated the 'extended' data based on the type of query requested */
1296 case D3DQUERYTYPE_OCCLUSION:
1297 if(GL_SUPPORT(ARB_OCCLUSION_QUERY) || GL_SUPPORT(NV_OCCLUSION_QUERY)) {
1298 TRACE("(%p) Allocating data for an occlusion query\n", This);
1299 object->extendedData = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(WineQueryOcclusionData));
1302 case D3DQUERYTYPE_VCACHE:
1303 case D3DQUERYTYPE_RESOURCEMANAGER:
1304 case D3DQUERYTYPE_VERTEXSTATS:
1305 case D3DQUERYTYPE_EVENT:
1306 case D3DQUERYTYPE_TIMESTAMP:
1307 case D3DQUERYTYPE_TIMESTAMPDISJOINT:
1308 case D3DQUERYTYPE_TIMESTAMPFREQ:
1309 case D3DQUERYTYPE_PIPELINETIMINGS:
1310 case D3DQUERYTYPE_INTERFACETIMINGS:
1311 case D3DQUERYTYPE_VERTEXTIMINGS:
1312 case D3DQUERYTYPE_PIXELTIMINGS:
1313 case D3DQUERYTYPE_BANDWIDTHTIMINGS:
1314 case D3DQUERYTYPE_CACHEUTILIZATION:
1316 object->extendedData = 0;
1317 FIXME("(%p) Unhandled query type %d\n",This , Type);
1319 TRACE("(%p) : Created Query %p\n", This, object);
1323 /* example at http://www.fairyengine.com/articles/dxmultiviews.htm */
1324 HRESULT WINAPI IWineD3DDeviceImpl_CreateAdditionalSwapChain(IWineD3DDevice* iface, WINED3DPRESENT_PARAMETERS* pPresentationParameters, IWineD3DSwapChain** ppSwapChain,
1326 D3DCB_CREATERENDERTARGETFN D3DCB_CreateRenderTarget,
1327 D3DCB_CREATEDEPTHSTENCILSURFACEFN D3DCB_CreateDepthStencil) {
1328 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
1331 IWineD3DSwapChainImpl *object; /** NOTE: impl ref allowed since this is a create function **/
1333 XVisualInfo template;
1334 GLXContext oldContext;
1335 Drawable oldDrawable;
1336 HRESULT hr = WINED3D_OK;
1338 TRACE("(%p) : Created Aditional Swap Chain\n", This);
1340 /** FIXME: Test under windows to find out what the life cycle of a swap chain is,
1341 * does a device hold a reference to a swap chain giving them a lifetime of the device
1342 * or does the swap chain notify the device of its destruction.
1343 *******************************/
1345 /* Check the params */
1346 if(*pPresentationParameters->BackBufferCount > 1) {
1347 ERR("App requested %d back buffers, this is not supported for now\n", *pPresentationParameters->BackBufferCount);
1348 return WINED3DERR_INVALIDCALL;
1351 D3DCREATEOBJECTINSTANCE(object, SwapChain)
1353 /*********************
1354 * Lookup the window Handle and the relating X window handle
1355 ********************/
1357 /* Setup hwnd we are using, plus which display this equates to */
1358 object->win_handle = *(pPresentationParameters->hDeviceWindow);
1359 if (!object->win_handle) {
1360 object->win_handle = This->createParms.hFocusWindow;
1363 object->win_handle = GetAncestor(object->win_handle, GA_ROOT);
1364 if ( !( object->win = (Window)GetPropA(object->win_handle, "__wine_x11_whole_window") ) ) {
1365 ERR("Can't get drawable (window), HWND:%p doesn't have the property __wine_x11_whole_window\n", object->win_handle);
1366 return WINED3DERR_NOTAVAILABLE;
1368 hDc = GetDC(object->win_handle);
1369 object->display = get_display(hDc);
1370 ReleaseDC(object->win_handle, hDc);
1371 TRACE("Using a display of %p %p\n", object->display, hDc);
1373 if (NULL == object->display || NULL == hDc) {
1374 WARN("Failed to get a display and HDc for Window %p\n", object->win_handle);
1375 return WINED3DERR_NOTAVAILABLE;
1378 if (object->win == 0) {
1379 WARN("Failed to get a valid XVisuial ID for the window %p\n", object->win_handle);
1380 return WINED3DERR_NOTAVAILABLE;
1383 * Create an opengl context for the display visual
1384 * NOTE: the visual is chosen as the window is created and the glcontext cannot
1385 * use different properties after that point in time. FIXME: How to handle when requested format
1386 * doesn't match actual visual? Cannot choose one here - code removed as it ONLY works if the one
1387 * it chooses is identical to the one already being used!
1388 **********************************/
1390 /** FIXME: Handle stencil appropriately via EnableAutoDepthStencil / AutoDepthStencilFormat **/
1393 /* Create a new context for this swapchain */
1394 template.visualid = (VisualID)GetPropA(GetDesktopWindow(), "__wine_x11_visual_id");
1395 /* TODO: change this to find a similar visual, but one with a stencil/zbuffer buffer that matches the request
1396 (or the best possible if none is requested) */
1397 TRACE("Found x visual ID : %ld\n", template.visualid);
1399 object->visInfo = XGetVisualInfo(object->display, VisualIDMask, &template, &num);
1400 if (NULL == object->visInfo) {
1401 ERR("cannot really get XVisual\n");
1403 return WINED3DERR_NOTAVAILABLE;
1406 /* Write out some debug info about the visual/s */
1407 TRACE("Using x visual ID : %ld\n", template.visualid);
1408 TRACE(" visual info: %p\n", object->visInfo);
1409 TRACE(" num items : %d\n", num);
1410 for (n = 0;n < num; n++) {
1411 TRACE("=====item=====: %d\n", n + 1);
1412 TRACE(" visualid : %ld\n", object->visInfo[n].visualid);
1413 TRACE(" screen : %d\n", object->visInfo[n].screen);
1414 TRACE(" depth : %u\n", object->visInfo[n].depth);
1415 TRACE(" class : %d\n", object->visInfo[n].class);
1416 TRACE(" red_mask : %ld\n", object->visInfo[n].red_mask);
1417 TRACE(" green_mask : %ld\n", object->visInfo[n].green_mask);
1418 TRACE(" blue_mask : %ld\n", object->visInfo[n].blue_mask);
1419 TRACE(" colormap_size : %d\n", object->visInfo[n].colormap_size);
1420 TRACE(" bits_per_rgb : %d\n", object->visInfo[n].bits_per_rgb);
1421 /* log some extra glx info */
1422 glXGetConfig(object->display, object->visInfo, GLX_AUX_BUFFERS, &value);
1423 TRACE(" gl_aux_buffers : %d\n", value);
1424 glXGetConfig(object->display, object->visInfo, GLX_BUFFER_SIZE ,&value);
1425 TRACE(" gl_buffer_size : %d\n", value);
1426 glXGetConfig(object->display, object->visInfo, GLX_RED_SIZE, &value);
1427 TRACE(" gl_red_size : %d\n", value);
1428 glXGetConfig(object->display, object->visInfo, GLX_GREEN_SIZE, &value);
1429 TRACE(" gl_green_size : %d\n", value);
1430 glXGetConfig(object->display, object->visInfo, GLX_BLUE_SIZE, &value);
1431 TRACE(" gl_blue_size : %d\n", value);
1432 glXGetConfig(object->display, object->visInfo, GLX_ALPHA_SIZE, &value);
1433 TRACE(" gl_alpha_size : %d\n", value);
1434 glXGetConfig(object->display, object->visInfo, GLX_DEPTH_SIZE ,&value);
1435 TRACE(" gl_depth_size : %d\n", value);
1436 glXGetConfig(object->display, object->visInfo, GLX_STENCIL_SIZE, &value);
1437 TRACE(" gl_stencil_size : %d\n", value);
1439 /* Now choose a simila visual ID*/
1441 #ifdef USE_CONTEXT_MANAGER
1443 /** TODO: use a context mamager **/
1447 IWineD3DSwapChain *implSwapChain;
1448 if (WINED3D_OK != IWineD3DDevice_GetSwapChain(iface, 0, &implSwapChain)) {
1449 /* The first time around we create the context that is shared with all other swapchains and render targets */
1450 object->glCtx = glXCreateContext(object->display, object->visInfo, NULL, GL_TRUE);
1451 TRACE("Creating implicit context for vis %p, hwnd %p\n", object->display, object->visInfo);
1454 TRACE("Creating context for vis %p, hwnd %p\n", object->display, object->visInfo);
1455 /* TODO: don't use Impl structures outside of create functions! (a context manager will replace the ->glCtx) */
1456 /* and create a new context with the implicit swapchains context as the shared context */
1457 object->glCtx = glXCreateContext(object->display, object->visInfo, ((IWineD3DSwapChainImpl *)implSwapChain)->glCtx, GL_TRUE);
1458 IWineD3DSwapChain_Release(implSwapChain);
1463 XFree(object->visInfo);
1464 object->visInfo = NULL;
1466 if (NULL == object->glCtx) {
1467 ERR("cannot create glxContext\n");
1469 return WINED3DERR_NOTAVAILABLE;
1473 if (object->glCtx == NULL) {
1474 ERR("Error in context creation !\n");
1475 return WINED3DERR_INVALIDCALL;
1477 TRACE("Context created (HWND=%p, glContext=%p, Window=%ld, VisInfo=%p)\n",
1478 object->win_handle, object->glCtx, object->win, object->visInfo);
1481 /*********************
1482 * Windowed / Fullscreen
1483 *******************/
1486 * TODO: MSDN says that we are only allowed one fullscreen swapchain per device,
1487 * so we should really check to see if there is a fullscreen swapchain already
1488 * I think Windows and X have different ideas about fullscreen, does a single head count as full screen?
1489 **************************************/
1491 if (!*(pPresentationParameters->Windowed)) {
1497 /* Get info on the current display setup */
1498 hdc = CreateDCA("DISPLAY", NULL, NULL, NULL);
1499 bpp = GetDeviceCaps(hdc, BITSPIXEL);
1502 /* Change the display settings */
1503 memset(&devmode, 0, sizeof(DEVMODEW));
1504 devmode.dmFields = DM_BITSPERPEL | DM_PELSWIDTH | DM_PELSHEIGHT;
1505 devmode.dmBitsPerPel = (bpp >= 24) ? 32 : bpp; /* Stupid XVidMode cannot change bpp */
1506 devmode.dmPelsWidth = *(pPresentationParameters->BackBufferWidth);
1507 devmode.dmPelsHeight = *(pPresentationParameters->BackBufferHeight);
1508 MultiByteToWideChar(CP_ACP, 0, "Gamers CG", -1, devmode.dmDeviceName, CCHDEVICENAME);
1509 ChangeDisplaySettingsExW(devmode.dmDeviceName, &devmode, object->win_handle, CDS_FULLSCREEN, NULL);
1511 /* Make popup window */
1512 SetWindowLongA(object->win_handle, GWL_STYLE, WS_POPUP);
1513 SetWindowPos(object->win_handle, HWND_TOP, 0, 0,
1514 *(pPresentationParameters->BackBufferWidth),
1515 *(pPresentationParameters->BackBufferHeight), SWP_SHOWWINDOW | SWP_FRAMECHANGED);
1517 /* For GetDisplayMode */
1518 This->ddraw_width = devmode.dmPelsWidth;
1519 This->ddraw_height = devmode.dmPelsHeight;
1520 This->ddraw_format = *(pPresentationParameters->BackBufferFormat);
1524 /** MSDN: If Windowed is TRUE and either of the BackBufferWidth/Height values is zero,
1525 * then the corresponding dimension of the client area of the hDeviceWindow
1526 * (or the focus window, if hDeviceWindow is NULL) is taken.
1527 **********************/
1529 if (*(pPresentationParameters->Windowed) &&
1530 ((*(pPresentationParameters->BackBufferWidth) == 0) ||
1531 (*(pPresentationParameters->BackBufferHeight) == 0))) {
1534 GetClientRect(object->win_handle, &Rect);
1536 if (*(pPresentationParameters->BackBufferWidth) == 0) {
1537 *(pPresentationParameters->BackBufferWidth) = Rect.right;
1538 TRACE("Updating width to %d\n", *(pPresentationParameters->BackBufferWidth));
1540 if (*(pPresentationParameters->BackBufferHeight) == 0) {
1541 *(pPresentationParameters->BackBufferHeight) = Rect.bottom;
1542 TRACE("Updating height to %d\n", *(pPresentationParameters->BackBufferHeight));
1546 /*********************
1547 * finish off parameter initialization
1548 *******************/
1550 /* Put the correct figures in the presentation parameters */
1551 TRACE("Coppying accross presentaion paraneters\n");
1552 object->presentParms.BackBufferWidth = *(pPresentationParameters->BackBufferWidth);
1553 object->presentParms.BackBufferHeight = *(pPresentationParameters->BackBufferHeight);
1554 object->presentParms.BackBufferFormat = *(pPresentationParameters->BackBufferFormat);
1555 object->presentParms.BackBufferCount = *(pPresentationParameters->BackBufferCount);
1556 object->presentParms.MultiSampleType = *(pPresentationParameters->MultiSampleType);
1557 object->presentParms.MultiSampleQuality = NULL == pPresentationParameters->MultiSampleQuality ? 0 : *(pPresentationParameters->MultiSampleQuality);
1558 object->presentParms.SwapEffect = *(pPresentationParameters->SwapEffect);
1559 object->presentParms.hDeviceWindow = *(pPresentationParameters->hDeviceWindow);
1560 object->presentParms.Windowed = *(pPresentationParameters->Windowed);
1561 object->presentParms.EnableAutoDepthStencil = *(pPresentationParameters->EnableAutoDepthStencil);
1562 object->presentParms.AutoDepthStencilFormat = *(pPresentationParameters->AutoDepthStencilFormat);
1563 object->presentParms.Flags = *(pPresentationParameters->Flags);
1564 object->presentParms.FullScreen_RefreshRateInHz = *(pPresentationParameters->FullScreen_RefreshRateInHz);
1565 object->presentParms.PresentationInterval = *(pPresentationParameters->PresentationInterval);
1568 /*********************
1569 * Create the back, front and stencil buffers
1570 *******************/
1572 TRACE("calling rendertarget CB\n");
1573 hr = D3DCB_CreateRenderTarget((IUnknown *) This->parent,
1574 object->presentParms.BackBufferWidth,
1575 object->presentParms.BackBufferHeight,
1576 object->presentParms.BackBufferFormat,
1577 object->presentParms.MultiSampleType,
1578 object->presentParms.MultiSampleQuality,
1579 TRUE /* Lockable */,
1580 &object->frontBuffer,
1581 NULL /* pShared (always null)*/);
1582 if (object->frontBuffer != NULL)
1583 IWineD3DSurface_SetContainer(object->frontBuffer, (IWineD3DBase *)object);
1584 if(object->presentParms.BackBufferCount > 0) {
1585 TRACE("calling rendertarget CB\n");
1586 hr = D3DCB_CreateRenderTarget((IUnknown *) This->parent,
1587 object->presentParms.BackBufferWidth,
1588 object->presentParms.BackBufferHeight,
1589 object->presentParms.BackBufferFormat,
1590 object->presentParms.MultiSampleType,
1591 object->presentParms.MultiSampleQuality,
1592 TRUE /* Lockable */,
1593 &object->backBuffer,
1594 NULL /* pShared (always null)*/);
1596 object->backBuffer = NULL;
1599 if (object->backBuffer != NULL) {
1600 IWineD3DSurface_SetContainer(object->backBuffer, (IWineD3DBase *)object);
1602 glDrawBuffer(GL_BACK);
1603 checkGLcall("glDrawBuffer(GL_BACK)");
1606 /* Single buffering - draw to front buffer */
1608 glDrawBuffer(GL_FRONT);
1609 checkGLcall("glDrawBuffer(GL_FRONT)");
1613 /* Under directX swapchains share the depth stencil, so only create one depth-stencil */
1614 if (pPresentationParameters->EnableAutoDepthStencil) {
1615 TRACE("Creating depth stencil buffer\n");
1616 if (This->depthStencilBuffer == NULL ) {
1617 hr = D3DCB_CreateDepthStencil((IUnknown *) This->parent,
1618 object->presentParms.BackBufferWidth,
1619 object->presentParms.BackBufferHeight,
1620 object->presentParms.AutoDepthStencilFormat,
1621 object->presentParms.MultiSampleType,
1622 object->presentParms.MultiSampleQuality,
1623 FALSE /* FIXME: Discard */,
1624 &This->depthStencilBuffer,
1625 NULL /* pShared (always null)*/ );
1626 if (This->depthStencilBuffer != NULL)
1627 IWineD3DSurface_SetContainer(This->depthStencilBuffer, 0);
1630 /** TODO: A check on width, height and multisample types
1631 *(since the zbuffer must be at least as large as the render target and have the same multisample parameters)
1632 ****************************/
1633 object->wantsDepthStencilBuffer = TRUE;
1635 object->wantsDepthStencilBuffer = FALSE;
1638 TRACE("FrontBuf @ %p, BackBuf @ %p, DepthStencil %d\n",object->frontBuffer, object->backBuffer, object->wantsDepthStencilBuffer);
1641 /*********************
1642 * init the default renderTarget management
1643 *******************/
1644 object->drawable = object->win;
1645 object->render_ctx = object->glCtx;
1647 if (hr == WINED3D_OK) {
1648 /*********************
1649 * Setup some defaults and clear down the buffers
1650 *******************/
1652 /** save current context and drawable **/
1653 oldContext = glXGetCurrentContext();
1654 oldDrawable = glXGetCurrentDrawable();
1656 TRACE("Activating context (display %p context %p drawable %ld)!\n", object->display, object->glCtx, object->win);
1657 if (glXMakeCurrent(object->display, object->win, object->glCtx) == False) {
1658 ERR("Error in setting current context (display %p context %p drawable %ld)!\n", object->display, object->glCtx, object->win);
1660 checkGLcall("glXMakeCurrent");
1662 TRACE("Setting up the screen\n");
1663 /* Clear the screen */
1664 glClearColor(1.0, 0.0, 0.0, 0.0);
1665 checkGLcall("glClearColor");
1668 glClearStencil(0xffff);
1670 checkGLcall("glClear");
1672 glColor3f(1.0, 1.0, 1.0);
1673 checkGLcall("glColor3f");
1675 glEnable(GL_LIGHTING);
1676 checkGLcall("glEnable");
1678 glLightModeli(GL_LIGHT_MODEL_LOCAL_VIEWER, GL_TRUE);
1679 checkGLcall("glLightModeli(GL_LIGHT_MODEL_LOCAL_VIEWER, GL_TRUE);");
1681 glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE_EXT);
1682 checkGLcall("glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE_EXT);");
1684 glLightModeli(GL_LIGHT_MODEL_COLOR_CONTROL, GL_SEPARATE_SPECULAR_COLOR);
1685 checkGLcall("glLightModeli(GL_LIGHT_MODEL_COLOR_CONTROL, GL_SEPARATE_SPECULAR_COLOR);");
1687 /* switch back to the original context (if there was one)*/
1688 if (This->swapchains) {
1689 /** TODO: restore the context and drawable **/
1690 glXMakeCurrent(object->display, oldDrawable, oldContext);
1695 TRACE("Set swapchain to %p\n", object);
1696 } else { /* something went wrong so clean up */
1697 IUnknown* bufferParent;
1698 if (object->frontBuffer) {
1700 IWineD3DSurface_GetParent(object->frontBuffer, &bufferParent);
1701 IUnknown_Release(bufferParent); /* once for the get parent */
1702 if (IUnknown_Release(bufferParent) > 0) {
1703 FIXME("(%p) Something's still holding the front buffer\n",This);
1706 if (object->backBuffer) {
1707 IWineD3DSurface_GetParent(object->backBuffer, &bufferParent);
1708 IUnknown_Release(bufferParent); /* once for the get parent */
1709 if (IUnknown_Release(bufferParent) > 0) {
1710 FIXME("(%p) Something's still holding the back buffer\n",This);
1713 /* NOTE: don't clean up the depthstencil buffer because it belongs to the device */
1714 /* Clean up the context */
1715 /* check that we are the current context first (we shouldn't be though!) */
1716 if (object->glCtx != 0) {
1717 if(glXGetCurrentContext() == object->glCtx) {
1718 glXMakeCurrent(object->display, None, NULL);
1720 glXDestroyContext(object->display, object->glCtx);
1722 HeapFree(GetProcessHeap(), 0, object);
1729 /** NOTE: These are ahead of the other getters and setters to save using a forward declaration **/
1730 UINT WINAPI IWineD3DDeviceImpl_GetNumberOfSwapChains(IWineD3DDevice *iface) {
1731 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
1732 TRACE("(%p)\n", This);
1734 return This->NumberOfSwapChains;
1737 HRESULT WINAPI IWineD3DDeviceImpl_GetSwapChain(IWineD3DDevice *iface, UINT iSwapChain, IWineD3DSwapChain **pSwapChain) {
1738 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
1739 TRACE("(%p) : swapchain %d\n", This, iSwapChain);
1741 if(iSwapChain < This->NumberOfSwapChains) {
1742 *pSwapChain = This->swapchains[iSwapChain];
1743 IWineD3DSwapChain_AddRef(*pSwapChain);
1744 TRACE("(%p) returning %p\n", This, *pSwapChain);
1747 TRACE("Swapchain out of range\n");
1749 return WINED3DERR_INVALIDCALL;
1754 * Vertex Declaration
1756 HRESULT WINAPI IWineD3DDeviceImpl_CreateVertexDeclaration(IWineD3DDevice* iface, CONST VOID* pDeclaration, IWineD3DVertexDeclaration** ppVertexDeclaration, IUnknown *parent) {
1757 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
1758 IWineD3DVertexDeclarationImpl *object = NULL;
1759 HRESULT hr = WINED3D_OK;
1760 TRACE("(%p) : directXVersion=%u, pFunction=%p, ppDecl=%p\n", This, ((IWineD3DImpl *)This->wineD3D)->dxVersion, pDeclaration, ppVertexDeclaration);
1761 D3DCREATEOBJECTINSTANCE(object, VertexDeclaration)
1764 hr = IWineD3DVertexDeclaration_SetDeclaration((IWineD3DVertexDeclaration *)object, (void *)pDeclaration);
1769 /* http://msdn.microsoft.com/archive/default.asp?url=/archive/en-us/directx9_c/directx/graphics/programmingguide/programmable/vertexshaders/vscreate.asp */
1770 HRESULT WINAPI IWineD3DDeviceImpl_CreateVertexShader(IWineD3DDevice *iface, CONST DWORD *pDeclaration, CONST DWORD *pFunction, IWineD3DVertexShader **ppVertexShader, IUnknown *parent) {
1771 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
1772 IWineD3DVertexShaderImpl *object; /* NOTE: impl usage is ok, this is a create */
1773 HRESULT hr = WINED3D_OK;
1774 D3DCREATEOBJECTINSTANCE(object, VertexShader)
1775 object->baseShader.shader_ins = IWineD3DVertexShaderImpl_shader_ins;
1777 TRACE("(%p) : Created Vertex shader %p\n", This, *ppVertexShader);
1779 /* If a vertex declaration has been passed, save it to the vertex shader, this affects d3d8 only. */
1780 /* Further it needs to be set before calling SetFunction as SetFunction needs the declaration. */
1781 if (pDeclaration != NULL) {
1782 IWineD3DVertexDeclaration *vertexDeclaration;
1783 hr = IWineD3DDevice_CreateVertexDeclaration(iface, pDeclaration, &vertexDeclaration ,NULL);
1784 if (WINED3D_OK == hr) {
1785 TRACE("(%p) : Setting vertex declaration to %p\n", This, vertexDeclaration);
1786 object->vertexDeclaration = vertexDeclaration;
1788 FIXME("(%p) : Failed to set the declaration, returning WINED3DERR_INVALIDCALL\n", iface);
1789 IWineD3DVertexShader_Release(*ppVertexShader);
1790 return WINED3DERR_INVALIDCALL;
1794 hr = IWineD3DVertexShader_SetFunction(*ppVertexShader, pFunction);
1796 if (WINED3D_OK != hr) {
1797 FIXME("(%p) : Failed to set the function, returning WINED3DERR_INVALIDCALL\n", iface);
1798 IWineD3DVertexShader_Release(*ppVertexShader);
1799 return WINED3DERR_INVALIDCALL;
1802 #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. */
1803 if(Usage == WINED3DUSAGE_SOFTWAREVERTEXPROCESSING) {
1814 HRESULT WINAPI IWineD3DDeviceImpl_CreatePixelShader(IWineD3DDevice *iface, CONST DWORD *pFunction, IWineD3DPixelShader **ppPixelShader, IUnknown *parent) {
1815 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
1816 IWineD3DPixelShaderImpl *object; /* NOTE: impl allowed, this is a create */
1817 HRESULT hr = WINED3D_OK;
1819 D3DCREATEOBJECTINSTANCE(object, PixelShader)
1820 object->baseShader.shader_ins = IWineD3DPixelShaderImpl_shader_ins;
1821 hr = IWineD3DPixelShader_SetFunction(*ppPixelShader, pFunction);
1822 if (WINED3D_OK == hr) {
1823 TRACE("(%p) : Created Pixel shader %p\n", This, *ppPixelShader);
1825 WARN("(%p) : Failed to create pixel shader\n", This);
1831 HRESULT WINAPI IWineD3DDeviceImpl_CreatePalette(IWineD3DDevice *iface, DWORD Flags, PALETTEENTRY *PalEnt, IWineD3DPalette **Palette, IUnknown *Parent) {
1832 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *) iface;
1833 IWineD3DPaletteImpl *object;
1835 TRACE("(%p)->(%lx, %p, %p, %p)\n", This, Flags, PalEnt, Palette, Parent);
1837 /* Create the new object */
1838 object = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(IWineD3DPaletteImpl));
1840 ERR("Out of memory when allocating memory for a IWineD3DPalette implementation\n");
1841 return E_OUTOFMEMORY;
1844 object->lpVtbl = &IWineD3DPalette_Vtbl;
1846 object->Flags = Flags;
1847 object->parent = Parent;
1848 object->wineD3DDevice = This;
1849 object->palNumEntries = IWineD3DPaletteImpl_Size(Flags);
1851 object->hpal = CreatePalette((const LOGPALETTE*)&(object->palVersion));
1854 HeapFree( GetProcessHeap(), 0, object);
1855 return E_OUTOFMEMORY;
1858 hr = IWineD3DPalette_SetEntries((IWineD3DPalette *) object, 0, 0, IWineD3DPaletteImpl_Size(Flags), PalEnt);
1860 IWineD3DPalette_Release((IWineD3DPalette *) object);
1864 *Palette = (IWineD3DPalette *) object;
1869 HRESULT WINAPI IWineD3DDeviceImpl_Init3D(IWineD3DDevice *iface, WINED3DPRESENT_PARAMETERS* pPresentationParameters, D3DCB_CREATEADDITIONALSWAPCHAIN D3DCB_CreateAdditionalSwapChain) {
1870 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *) iface;
1871 IWineD3DSwapChainImpl *swapchain;
1873 TRACE("(%p)->(%p,%p)\n", This, pPresentationParameters, D3DCB_CreateAdditionalSwapChain);
1874 if(This->d3d_initialized) return WINED3DERR_INVALIDCALL;
1876 /* TODO: Test if OpenGL is compiled in and loaded */
1878 /* Setup the implicit swapchain */
1879 TRACE("Creating implicit swapchain\n");
1880 if (D3D_OK != D3DCB_CreateAdditionalSwapChain((IUnknown *) This->parent, pPresentationParameters, (IWineD3DSwapChain **)&swapchain) || swapchain == NULL) {
1881 WARN("Failed to create implicit swapchain\n");
1882 return WINED3DERR_INVALIDCALL;
1885 This->NumberOfSwapChains = 1;
1886 This->swapchains = HeapAlloc(GetProcessHeap(), 0, This->NumberOfSwapChains * sizeof(IWineD3DSwapChain *));
1887 if(!This->swapchains) {
1888 ERR("Out of memory!\n");
1889 IWineD3DSwapChain_Release( (IWineD3DSwapChain *) swapchain);
1890 return E_OUTOFMEMORY;
1892 This->swapchains[0] = (IWineD3DSwapChain *) swapchain;
1894 if(swapchain->backBuffer) {
1895 TRACE("Setting rendertarget to %p\n", swapchain->backBuffer);
1896 This->renderTarget = swapchain->backBuffer;
1899 TRACE("Setting rendertarget to %p\n", swapchain->frontBuffer);
1900 This->renderTarget = swapchain->frontBuffer;
1902 IWineD3DSurface_AddRef(This->renderTarget);
1903 /* Depth Stencil support */
1904 This->stencilBufferTarget = This->depthStencilBuffer;
1905 if (NULL != This->stencilBufferTarget) {
1906 IWineD3DSurface_AddRef(This->stencilBufferTarget);
1909 /* Set up some starting GL setup */
1912 * Initialize openGL extension related variables
1913 * with Default values
1916 ((IWineD3DImpl *) This->wineD3D)->isGLInfoValid = IWineD3DImpl_FillGLCaps( &((IWineD3DImpl *) This->wineD3D)->gl_info, swapchain->display);
1917 /* Setup all the devices defaults */
1918 IWineD3DStateBlock_InitStartupStateBlock((IWineD3DStateBlock *)This->stateBlock);
1920 IWineD3DImpl_CheckGraphicsMemory();
1924 /* Initialize our list of GLSL programs */
1925 list_init(&This->glsl_shader_progs);
1927 { /* Set a default viewport */
1931 vp.Width = *(pPresentationParameters->BackBufferWidth);
1932 vp.Height = *(pPresentationParameters->BackBufferHeight);
1935 IWineD3DDevice_SetViewport((IWineD3DDevice *)This, &vp);
1938 /* Initialize the current view state */
1939 This->modelview_valid = 1;
1940 This->proj_valid = 0;
1941 This->view_ident = 1;
1942 This->last_was_rhw = 0;
1943 glGetIntegerv(GL_MAX_LIGHTS, &This->maxConcurrentLights);
1944 TRACE("(%p) All defaults now set up, leaving Init3D with %p\n", This, This);
1946 /* Clear the screen */
1947 IWineD3DDevice_Clear((IWineD3DDevice *) This, 0, NULL, D3DCLEAR_STENCIL|D3DCLEAR_ZBUFFER|D3DCLEAR_TARGET, 0x00, 1.0, 0);
1949 This->d3d_initialized = TRUE;
1953 HRESULT WINAPI IWineD3DDeviceImpl_Uninit3D(IWineD3DDevice *iface) {
1954 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *) iface;
1956 IUnknown* stencilBufferParent;
1957 IUnknown* swapChainParent;
1959 TRACE("(%p)\n", This);
1961 if(!This->d3d_initialized) return WINED3DERR_INVALIDCALL;
1963 for(texstage = 0; texstage < GL_LIMITS(textures); texstage++) {
1964 IWineD3DDevice_SetTexture(iface, texstage, NULL);
1967 /* Release the buffers (with sanity checks)*/
1968 TRACE("Releasing the depth stencil buffer at %p\n", This->stencilBufferTarget);
1969 if(This->stencilBufferTarget != NULL && (IWineD3DSurface_Release(This->stencilBufferTarget) >0)){
1970 if(This->depthStencilBuffer != This->stencilBufferTarget)
1971 FIXME("(%p) Something's still holding the depthStencilBuffer\n",This);
1973 This->stencilBufferTarget = NULL;
1975 TRACE("Releasing the render target at %p\n", This->renderTarget);
1976 if(IWineD3DSurface_Release(This->renderTarget) >0){
1977 /* This check is a bit silly, itshould be in swapchain_release FIXME("(%p) Something's still holding the renderTarget\n",This); */
1979 TRACE("Setting rendertarget to NULL\n");
1980 This->renderTarget = NULL;
1982 IWineD3DSurface_GetParent(This->depthStencilBuffer, &stencilBufferParent);
1983 IUnknown_Release(stencilBufferParent); /* once for the get parent */
1984 if(IUnknown_Release(stencilBufferParent) >0){ /* the second time for when it was created */
1985 FIXME("(%p) Something's still holding the depthStencilBuffer\n",This);
1987 This->depthStencilBuffer = NULL;
1989 for(i=0; i < This->NumberOfSwapChains; i++) {
1990 TRACE("Releasing the implicit swapchain %d\n", i);
1991 /* Swapchain 0 is special because it's created in startup with a hanging parent, so we have to release its parent now */
1992 IWineD3DSwapChain_GetParent(This->swapchains[i], &swapChainParent);
1993 IUnknown_Release(swapChainParent); /* once for the get parent */
1994 if (IUnknown_Release(swapChainParent) > 0) { /* the second time for when it was created */
1995 FIXME("(%p) Something's still holding the implicit swapchain\n", This);
1999 HeapFree(GetProcessHeap(), 0, This->swapchains);
2000 This->swapchains = NULL;
2001 This->NumberOfSwapChains = 0;
2003 This->d3d_initialized = FALSE;
2007 HRESULT WINAPI IWineD3DDeviceImpl_EnumDisplayModes(IWineD3DDevice *iface, DWORD Flags, UINT Width, UINT Height, WINED3DFORMAT pixelformat, LPVOID context, D3DCB_ENUMDISPLAYMODESCALLBACK callback) {
2008 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2013 TRACE("(%p)->(%lx,%d,%d,%d,%p,%p)\n", This, Flags, Width, Height, pixelformat, context, callback);
2015 for (i = 0; EnumDisplaySettingsExW(NULL, i, &DevModeW, 0); i++) {
2016 /* Ignore some modes if a description was passed */
2017 if ( (Width > 0) && (Width != DevModeW.dmPelsWidth)) continue;
2018 if ( (Height > 0) && (Height != DevModeW.dmPelsHeight)) continue;
2019 if ( (pixelformat != WINED3DFMT_UNKNOWN) && ( D3DFmtGetBpp(NULL, pixelformat) != DevModeW.dmBitsPerPel) ) continue;
2021 TRACE("Enumerating %ldx%ld@%s\n", DevModeW.dmPelsWidth, DevModeW.dmPelsHeight, debug_d3dformat(pixelformat_for_depth(DevModeW.dmBitsPerPel)));
2023 if (callback((IUnknown *) This, (UINT) DevModeW.dmPelsWidth, (UINT) DevModeW.dmPelsHeight, pixelformat_for_depth(DevModeW.dmBitsPerPel), 60.0, context) == DDENUMRET_CANCEL)
2030 HRESULT WINAPI IWineD3DDeviceImpl_SetDisplayMode(IWineD3DDevice *iface, UINT iSwapChain, WINED3DDISPLAYMODE* pMode) {
2032 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2035 TRACE("(%p)->(%d,%p) Mode=%dx%dx@%d, %s\n", This, iSwapChain, pMode, pMode->Width, pMode->Height, pMode->RefreshRate, debug_d3dformat(pMode->Format));
2037 /* Resize the screen even without a window:
2038 * The app could have unset it with SetCooperativeLevel, but not called
2039 * RestoreDisplayMode first. Then the release will call RestoreDisplayMode,
2040 * but we don't have any hwnd
2043 devmode.dmFields = DM_BITSPERPEL | DM_PELSWIDTH | DM_PELSHEIGHT;
2044 devmode.dmBitsPerPel = D3DFmtGetBpp(This, pMode->Format) * 8;
2045 if(devmode.dmBitsPerPel == 24) devmode.dmBitsPerPel = 32;
2046 devmode.dmPelsWidth = pMode->Width;
2047 devmode.dmPelsHeight = pMode->Height;
2049 devmode.dmDisplayFrequency = pMode->RefreshRate;
2050 if (pMode->RefreshRate != 0) {
2051 devmode.dmFields |= DM_DISPLAYFREQUENCY;
2054 /* Only change the mode if necessary */
2055 if( (This->ddraw_width == pMode->Width) &&
2056 (This->ddraw_height == pMode->Height) &&
2057 (This->ddraw_format == pMode->Format) &&
2058 (pMode->RefreshRate == 0) ) {
2062 ret = ChangeDisplaySettingsExW(NULL, &devmode, NULL, CDS_FULLSCREEN, NULL);
2063 if (ret != DISP_CHANGE_SUCCESSFUL) {
2064 if(devmode.dmDisplayFrequency != 0) {
2065 WARN("ChangeDisplaySettingsExW failed, trying without the refresh rate\n");
2066 devmode.dmFields &= ~DM_DISPLAYFREQUENCY;
2067 devmode.dmDisplayFrequency = 0;
2068 ret = ChangeDisplaySettingsExW(NULL, &devmode, NULL, CDS_FULLSCREEN, NULL) != DISP_CHANGE_SUCCESSFUL;
2070 if(ret != DISP_CHANGE_SUCCESSFUL) {
2071 return DDERR_INVALIDMODE;
2075 /* Store the new values */
2076 This->ddraw_width = pMode->Width;
2077 This->ddraw_height = pMode->Height;
2078 This->ddraw_format = pMode->Format;
2080 /* Only do this with a window of course */
2081 if(This->ddraw_window)
2082 MoveWindow(This->ddraw_window, 0, 0, pMode->Width, pMode->Height, TRUE);
2087 HRESULT WINAPI IWineD3DDeviceImpl_EnumZBufferFormats(IWineD3DDevice *iface, D3DCB_ENUMPIXELFORMATS Callback, void *Context) {
2088 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *) iface;
2091 WINED3DFORMAT FormatList[] = {
2098 WINED3DFMT_UNKNOWN /* Terminate the list */
2101 TRACE("(%p)->(%p,%p)\n", This, Callback, Context);
2103 while(FormatList[i] != WINED3DFMT_UNKNOWN) {
2104 TRACE("Enumerating %s\n", debug_d3dformat(FormatList[i]));
2105 ret = Callback((IUnknown *) This, FormatList[i], Context);
2106 if(ret != DDENUMRET_OK) {
2107 TRACE("Enumeration cancelled by Application\n");
2113 TRACE("End of Enumeration\n");
2118 HRESULT WINAPI IWineD3DDeviceImpl_EnumTextureFormats(IWineD3DDevice *iface, D3DCB_ENUMPIXELFORMATS Callback, void *Context) {
2119 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *) iface;
2124 * WINED3DFMT_A1R5G5B5 needs to be the first 16 bit format, as some dumb apps depend on this
2126 * Do not enumerate RGBA pixel formats: "some games choose the first 16 bit texture format
2127 * with alpha they find enumerated, others the last one. And both want to have the ARGB one."
2128 * But WineD3D doesn't support RGBA formats anyway...
2131 WINED3DFORMAT FormatList[] = {
2133 WINED3DFMT_A8R8G8B8,
2134 WINED3DFMT_X8R8G8B8,
2138 WINED3DFMT_A1R5G5B5,
2139 WINED3DFMT_A4R4G4B4,
2141 WINED3DFMT_X1R5G5B5,
2149 /* Terminate the list */
2153 TRACE("(%p)->(%p,%p)\n", This, Callback, Context);
2155 while(FormatList[i] != WINED3DFMT_UNKNOWN) {
2156 TRACE("Enumerating %s\n", debug_d3dformat(FormatList[i]));
2157 ret = Callback((IUnknown *) This, FormatList[i], Context);
2158 if(ret != DDENUMRET_OK) {
2159 TRACE("Enumeration cancelled by Application\n");
2165 TRACE("End of Enumeration\n");
2170 HRESULT WINAPI IWineD3DDeviceImpl_GetDirect3D(IWineD3DDevice *iface, IWineD3D **ppD3D) {
2171 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2172 *ppD3D= This->wineD3D;
2173 TRACE("(%p) : wineD3D returning %p\n", This, *ppD3D);
2174 IWineD3D_AddRef(*ppD3D);
2178 UINT WINAPI IWineD3DDeviceImpl_GetAvailableTextureMem(IWineD3DDevice *iface) {
2179 /** NOTE: There's a probably a hack-around for this one by putting as many pbuffers, VBO's (or whatever)
2180 * Into the video ram as possible and seeing how many fit
2181 * you can also get the correct initial value from via X and ATI's driver
2182 *******************/
2183 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2184 static BOOL showfixmes = TRUE;
2186 FIXME("(%p) : stub, emulating %dMB for now, returning %dMB\n", This, (emulated_textureram/(1024*1024)),
2187 ((emulated_textureram - wineD3DGlobalStatistics->glsurfaceram) / (1024*1024)));
2190 TRACE("(%p) : emulating %dMB for now, returning %dMB\n", This, (emulated_textureram/(1024*1024)),
2191 ((emulated_textureram - wineD3DGlobalStatistics->glsurfaceram) / (1024*1024)));
2192 /* videomemory is simulated videomemory + AGP memory left */
2193 return (emulated_textureram - wineD3DGlobalStatistics->glsurfaceram);
2201 HRESULT WINAPI IWineD3DDeviceImpl_SetFVF(IWineD3DDevice *iface, DWORD fvf) {
2202 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2203 HRESULT hr = WINED3D_OK;
2205 /* Update the current state block */
2206 This->updateStateBlock->fvf = fvf;
2207 This->updateStateBlock->changed.fvf = TRUE;
2208 This->updateStateBlock->set.fvf = TRUE;
2210 TRACE("(%p) : FVF Shader FVF set to %lx\n", This, fvf);
2213 /* clear down the vertex declaration
2214 NOTE: Axis and Allies doesn't work properly otherwise
2215 (may be a stateblock problem though!)
2217 hr = IWineD3DDevice_SetVertexDeclaration(iface, NULL);
2224 HRESULT WINAPI IWineD3DDeviceImpl_GetFVF(IWineD3DDevice *iface, DWORD *pfvf) {
2225 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2226 TRACE("(%p) : GetFVF returning %lx\n", This, This->stateBlock->fvf);
2227 *pfvf = This->stateBlock->fvf;
2232 * Get / Set Stream Source
2234 HRESULT WINAPI IWineD3DDeviceImpl_SetStreamSource(IWineD3DDevice *iface, UINT StreamNumber,IWineD3DVertexBuffer* pStreamData, UINT OffsetInBytes, UINT Stride) {
2235 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2236 IWineD3DVertexBuffer *oldSrc;
2238 /**TODO: instance and index data, see
2239 http://msdn.microsoft.com/library/default.asp?url=/library/en-us/directx9_c/directx/graphics/programmingguide/advancedtopics/DrawingMultipleInstances.asp
2241 http://msdn.microsoft.com/library/default.asp?url=/library/en-us/directx9_c/directx/graphics/reference/d3d/interfaces/idirect3ddevice9/SetStreamSourceFreq.asp
2244 /* D3d9 only, but shouldn't hurt d3d8 */
2247 streamFlags = StreamNumber &(D3DSTREAMSOURCE_INDEXEDDATA | D3DSTREAMSOURCE_INSTANCEDATA);
2249 if (streamFlags & D3DSTREAMSOURCE_INDEXEDDATA) {
2250 FIXME("stream index data not supported\n");
2252 if (streamFlags & D3DSTREAMSOURCE_INDEXEDDATA) {
2253 FIXME("stream instance data not supported\n");
2257 StreamNumber&= ~(D3DSTREAMSOURCE_INDEXEDDATA | D3DSTREAMSOURCE_INSTANCEDATA);
2259 if (StreamNumber >= MAX_STREAMS) {
2260 WARN("Stream out of range %d\n", StreamNumber);
2261 return WINED3DERR_INVALIDCALL;
2264 oldSrc = This->stateBlock->streamSource[StreamNumber];
2265 TRACE("(%p) : StreamNo: %d, OldStream (%p), NewStream (%p), NewStride %d\n", This, StreamNumber, oldSrc, pStreamData, Stride);
2267 This->updateStateBlock->changed.streamSource[StreamNumber] = TRUE;
2268 This->updateStateBlock->set.streamSource[StreamNumber] = TRUE;
2269 This->updateStateBlock->streamStride[StreamNumber] = Stride;
2270 This->updateStateBlock->streamSource[StreamNumber] = pStreamData;
2271 This->updateStateBlock->streamOffset[StreamNumber] = OffsetInBytes;
2272 This->updateStateBlock->streamFlags[StreamNumber] = streamFlags;
2274 /* Handle recording of state blocks */
2275 if (This->isRecordingState) {
2276 TRACE("Recording... not performing anything\n");
2280 /* Not recording... */
2281 /* Need to do a getParent and pass the reffs up */
2282 /* MSDN says ..... When an application no longer holds a references to this interface, the interface will automatically be freed.
2283 which suggests that we shouldn't be ref counting? and do need a _release on the stream source to reset the stream source
2284 so for now, just count internally */
2285 if (pStreamData != NULL) {
2286 IWineD3DVertexBuffer_AddRef(pStreamData);
2288 if (oldSrc != NULL) {
2289 IWineD3DVertexBuffer_Release(oldSrc);
2295 HRESULT WINAPI IWineD3DDeviceImpl_GetStreamSource(IWineD3DDevice *iface, UINT StreamNumber,IWineD3DVertexBuffer** pStream, UINT *pOffset, UINT* pStride) {
2296 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2299 TRACE("(%p) : StreamNo: %d, Stream (%p), Stride %d\n", This, StreamNumber,
2300 This->stateBlock->streamSource[StreamNumber], This->stateBlock->streamStride[StreamNumber]);
2303 streamFlags = StreamNumber &(D3DSTREAMSOURCE_INDEXEDDATA | D3DSTREAMSOURCE_INSTANCEDATA);
2305 if (streamFlags & D3DSTREAMSOURCE_INDEXEDDATA) {
2306 FIXME("stream index data not supported\n");
2308 if (streamFlags & D3DSTREAMSOURCE_INDEXEDDATA) {
2309 FIXME("stream instance data not supported\n");
2313 StreamNumber&= ~(D3DSTREAMSOURCE_INDEXEDDATA | D3DSTREAMSOURCE_INSTANCEDATA);
2315 if (StreamNumber >= MAX_STREAMS) {
2316 WARN("Stream out of range %d\n", StreamNumber);
2317 return WINED3DERR_INVALIDCALL;
2319 *pStream = This->stateBlock->streamSource[StreamNumber];
2320 *pStride = This->stateBlock->streamStride[StreamNumber];
2321 *pOffset = This->stateBlock->streamOffset[StreamNumber];
2323 if (*pStream == NULL) {
2324 FIXME("Attempting to get an empty stream %d, returning WINED3DERR_INVALIDCALL\n", StreamNumber);
2325 return WINED3DERR_INVALIDCALL;
2328 IWineD3DVertexBuffer_AddRef(*pStream); /* We have created a new reference to the VB */
2332 /*Should be quite easy, just an extension of vertexdata
2334 http://msdn.microsoft.com/archive/default.asp?url=/archive/en-us/directx9_c_Summer_04/directx/graphics/programmingguide/advancedtopics/DrawingMultipleInstances.asp
2336 The divider is a bit odd though
2338 VertexOffset = StartVertex / Divider * StreamStride +
2339 VertexIndex / Divider * StreamStride + StreamOffset
2342 HRESULT WINAPI IWineD3DDeviceImpl_SetStreamSourceFreq(IWineD3DDevice *iface, UINT StreamNumber, UINT Divider) {
2343 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2345 TRACE("(%p) StreamNumber(%d), Divider(%d)\n", This, StreamNumber, Divider);
2346 This->updateStateBlock->streamFlags[StreamNumber] = Divider & (D3DSTREAMSOURCE_INSTANCEDATA | D3DSTREAMSOURCE_INDEXEDDATA );
2348 This->updateStateBlock->changed.streamFreq[StreamNumber] = TRUE;
2349 This->updateStateBlock->set.streamFreq[StreamNumber] = TRUE;
2350 This->updateStateBlock->streamFreq[StreamNumber] = Divider & 0x7FFFFF;
2352 if (This->updateStateBlock->streamFlags[StreamNumber] || This->updateStateBlock->streamFreq[StreamNumber] != 1) {
2353 FIXME("Stream indexing not fully supported\n");
2359 HRESULT WINAPI IWineD3DDeviceImpl_GetStreamSourceFreq(IWineD3DDevice *iface, UINT StreamNumber, UINT* Divider) {
2360 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2362 TRACE("(%p) StreamNumber(%d), Divider(%p)\n", This, StreamNumber, Divider);
2363 *Divider = This->updateStateBlock->streamFreq[StreamNumber] | This->updateStateBlock->streamFlags[StreamNumber];
2365 TRACE("(%p) : returning %d\n", This, *Divider);
2371 * Get / Set & Multiply Transform
2373 HRESULT WINAPI IWineD3DDeviceImpl_SetTransform(IWineD3DDevice *iface, D3DTRANSFORMSTATETYPE d3dts, CONST D3DMATRIX* lpmatrix) {
2374 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2376 /* Most of this routine, comments included copied from ddraw tree initially: */
2377 TRACE("(%p) : Transform State=%d\n", This, d3dts);
2379 /* Handle recording of state blocks */
2380 if (This->isRecordingState) {
2381 TRACE("Recording... not performing anything\n");
2382 This->updateStateBlock->changed.transform[d3dts] = TRUE;
2383 This->updateStateBlock->set.transform[d3dts] = TRUE;
2384 memcpy(&This->updateStateBlock->transforms[d3dts], lpmatrix, sizeof(D3DMATRIX));
2389 * If the new matrix is the same as the current one,
2390 * we cut off any further processing. this seems to be a reasonable
2391 * optimization because as was noticed, some apps (warcraft3 for example)
2392 * tend towards setting the same matrix repeatedly for some reason.
2394 * From here on we assume that the new matrix is different, wherever it matters.
2396 if (!memcmp(&This->stateBlock->transforms[d3dts].u.m[0][0], lpmatrix, sizeof(D3DMATRIX))) {
2397 TRACE("The app is setting the same matrix over again\n");
2400 conv_mat(lpmatrix, &This->stateBlock->transforms[d3dts].u.m[0][0]);
2404 ScreenCoord = ProjectionMat * ViewMat * WorldMat * ObjectCoord
2405 where ViewMat = Camera space, WorldMat = world space.
2407 In OpenGL, camera and world space is combined into GL_MODELVIEW
2408 matrix. The Projection matrix stay projection matrix.
2411 /* Capture the times we can just ignore the change for now */
2412 if (d3dts == D3DTS_WORLDMATRIX(0)) {
2413 This->modelview_valid = FALSE;
2416 } else if (d3dts == D3DTS_PROJECTION) {
2417 This->proj_valid = FALSE;
2420 } else if (d3dts >= D3DTS_WORLDMATRIX(1) && d3dts <= D3DTS_WORLDMATRIX(255)) {
2421 /* Indexed Vertex Blending Matrices 256 -> 511 */
2422 /* Use arb_vertex_blend or NV_VERTEX_WEIGHTING? */
2423 FIXME("D3DTS_WORLDMATRIX(1..255) not handled\n");
2427 /* Now we really are going to have to change a matrix */
2430 if (d3dts >= D3DTS_TEXTURE0 && d3dts <= D3DTS_TEXTURE7) { /* handle texture matrices */
2431 /* This is now set with the texture unit states, it may be a good idea to flag the change though! */
2432 } else if (d3dts == D3DTS_VIEW) { /* handle the VIEW matrice */
2435 /* If we are changing the View matrix, reset the light and clipping planes to the new view
2436 * NOTE: We have to reset the positions even if the light/plane is not currently
2437 * enabled, since the call to enable it will not reset the position.
2438 * NOTE2: Apparently texture transforms do NOT need reapplying
2441 PLIGHTINFOEL *lightChain = NULL;
2442 This->modelview_valid = FALSE;
2443 This->view_ident = !memcmp(lpmatrix, identity, 16 * sizeof(float));
2445 glMatrixMode(GL_MODELVIEW);
2446 checkGLcall("glMatrixMode(GL_MODELVIEW)");
2448 glLoadMatrixf((float *)lpmatrix);
2449 checkGLcall("glLoadMatrixf(...)");
2452 lightChain = This->stateBlock->lights;
2453 while (lightChain && lightChain->glIndex != -1) {
2454 glLightfv(GL_LIGHT0 + lightChain->glIndex, GL_POSITION, lightChain->lightPosn);
2455 checkGLcall("glLightfv posn");
2456 glLightfv(GL_LIGHT0 + lightChain->glIndex, GL_SPOT_DIRECTION, lightChain->lightDirn);
2457 checkGLcall("glLightfv dirn");
2458 lightChain = lightChain->next;
2461 /* Reset Clipping Planes if clipping is enabled */
2462 for (k = 0; k < GL_LIMITS(clipplanes); k++) {
2463 glClipPlane(GL_CLIP_PLANE0 + k, This->stateBlock->clipplane[k]);
2464 checkGLcall("glClipPlane");
2468 } else { /* What was requested!?? */
2469 WARN("invalid matrix specified: %i\n", d3dts);
2472 /* Release lock, all done */
2477 HRESULT WINAPI IWineD3DDeviceImpl_GetTransform(IWineD3DDevice *iface, D3DTRANSFORMSTATETYPE State, D3DMATRIX* pMatrix) {
2478 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2479 TRACE("(%p) : for Transform State %d\n", This, State);
2480 memcpy(pMatrix, &This->stateBlock->transforms[State], sizeof(D3DMATRIX));
2484 HRESULT WINAPI IWineD3DDeviceImpl_MultiplyTransform(IWineD3DDevice *iface, D3DTRANSFORMSTATETYPE State, CONST D3DMATRIX* pMatrix) {
2485 D3DMATRIX *mat = NULL;
2488 /* Note: Using 'updateStateBlock' rather than 'stateblock' in the code
2489 * below means it will be recorded in a state block change, but it
2490 * works regardless where it is recorded.
2491 * If this is found to be wrong, change to StateBlock.
2493 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2494 TRACE("(%p) : For state %u\n", This, State);
2496 if (State < HIGHEST_TRANSFORMSTATE)
2498 mat = &This->updateStateBlock->transforms[State];
2500 FIXME("Unhandled transform state!!\n");
2503 multiply_matrix(&temp, mat, (D3DMATRIX *) pMatrix);
2505 /* Apply change via set transform - will reapply to eg. lights this way */
2506 return IWineD3DDeviceImpl_SetTransform(iface, State, &temp);
2511 * WARNING: This code relies on the fact that D3DLIGHT8 == D3DLIGHT9
2513 /* Note lights are real special cases. Although the device caps state only eg. 8 are supported,
2514 you can reference any indexes you want as long as that number max are enabled at any
2515 one point in time! Therefore since the indexes can be anything, we need a linked list of them.
2516 However, this causes stateblock problems. When capturing the state block, I duplicate the list,
2517 but when recording, just build a chain pretty much of commands to be replayed. */
2519 HRESULT WINAPI IWineD3DDeviceImpl_SetLight(IWineD3DDevice *iface, DWORD Index, CONST WINED3DLIGHT* pLight) {
2521 PLIGHTINFOEL *object, *temp;
2523 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2524 TRACE("(%p) : Idx(%ld), pLight(%p)\n", This, Index, pLight);
2526 /* If recording state block, just add to end of lights chain */
2527 if (This->isRecordingState) {
2528 object = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(PLIGHTINFOEL));
2529 if (NULL == object) {
2530 return WINED3DERR_OUTOFVIDEOMEMORY;
2532 memcpy(&object->OriginalParms, pLight, sizeof(D3DLIGHT9));
2533 object->OriginalIndex = Index;
2534 object->glIndex = -1;
2535 object->changed = TRUE;
2537 /* Add to the END of the chain of lights changes to be replayed */
2538 if (This->updateStateBlock->lights == NULL) {
2539 This->updateStateBlock->lights = object;
2541 temp = This->updateStateBlock->lights;
2542 while (temp->next != NULL) temp=temp->next;
2543 temp->next = object;
2545 TRACE("Recording... not performing anything more\n");
2549 /* Ok, not recording any longer so do real work */
2550 object = This->stateBlock->lights;
2551 while (object != NULL && object->OriginalIndex != Index) object = object->next;
2553 /* If we didn't find it in the list of lights, time to add it */
2554 if (object == NULL) {
2555 PLIGHTINFOEL *insertAt,*prevPos;
2557 object = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(PLIGHTINFOEL));
2558 if (NULL == object) {
2559 return WINED3DERR_OUTOFVIDEOMEMORY;
2561 object->OriginalIndex = Index;
2562 object->glIndex = -1;
2564 /* Add it to the front of list with the idea that lights will be changed as needed
2565 BUT after any lights currently assigned GL indexes */
2566 insertAt = This->stateBlock->lights;
2568 while (insertAt != NULL && insertAt->glIndex != -1) {
2570 insertAt = insertAt->next;
2573 if (insertAt == NULL && prevPos == NULL) { /* Start of list */
2574 This->stateBlock->lights = object;
2575 } else if (insertAt == NULL) { /* End of list */
2576 prevPos->next = object;
2577 object->prev = prevPos;
2578 } else { /* Middle of chain */
2579 if (prevPos == NULL) {
2580 This->stateBlock->lights = object;
2582 prevPos->next = object;
2584 object->prev = prevPos;
2585 object->next = insertAt;
2586 insertAt->prev = object;
2590 /* Initialize the object */
2591 TRACE("Light %ld setting to type %d, Diffuse(%f,%f,%f,%f), Specular(%f,%f,%f,%f), Ambient(%f,%f,%f,%f)\n", Index, pLight->Type,
2592 pLight->Diffuse.r, pLight->Diffuse.g, pLight->Diffuse.b, pLight->Diffuse.a,
2593 pLight->Specular.r, pLight->Specular.g, pLight->Specular.b, pLight->Specular.a,
2594 pLight->Ambient.r, pLight->Ambient.g, pLight->Ambient.b, pLight->Ambient.a);
2595 TRACE("... Pos(%f,%f,%f), Dirn(%f,%f,%f)\n", pLight->Position.x, pLight->Position.y, pLight->Position.z,
2596 pLight->Direction.x, pLight->Direction.y, pLight->Direction.z);
2597 TRACE("... Range(%f), Falloff(%f), Theta(%f), Phi(%f)\n", pLight->Range, pLight->Falloff, pLight->Theta, pLight->Phi);
2599 /* Save away the information */
2600 memcpy(&object->OriginalParms, pLight, sizeof(D3DLIGHT9));
2602 switch (pLight->Type) {
2603 case D3DLIGHT_POINT:
2605 object->lightPosn[0] = pLight->Position.x;
2606 object->lightPosn[1] = pLight->Position.y;
2607 object->lightPosn[2] = pLight->Position.z;
2608 object->lightPosn[3] = 1.0f;
2609 object->cutoff = 180.0f;
2613 case D3DLIGHT_DIRECTIONAL:
2615 object->lightPosn[0] = -pLight->Direction.x;
2616 object->lightPosn[1] = -pLight->Direction.y;
2617 object->lightPosn[2] = -pLight->Direction.z;
2618 object->lightPosn[3] = 0.0;
2619 object->exponent = 0.0f;
2620 object->cutoff = 180.0f;
2625 object->lightPosn[0] = pLight->Position.x;
2626 object->lightPosn[1] = pLight->Position.y;
2627 object->lightPosn[2] = pLight->Position.z;
2628 object->lightPosn[3] = 1.0;
2631 object->lightDirn[0] = pLight->Direction.x;
2632 object->lightDirn[1] = pLight->Direction.y;
2633 object->lightDirn[2] = pLight->Direction.z;
2634 object->lightDirn[3] = 1.0;
2637 * opengl-ish and d3d-ish spot lights use too different models for the
2638 * light "intensity" as a function of the angle towards the main light direction,
2639 * so we only can approximate very roughly.
2640 * however spot lights are rather rarely used in games (if ever used at all).
2641 * furthermore if still used, probably nobody pays attention to such details.
2643 if (pLight->Falloff == 0) {
2646 rho = pLight->Theta + (pLight->Phi - pLight->Theta)/(2*pLight->Falloff);
2648 if (rho < 0.0001) rho = 0.0001f;
2649 object->exponent = -0.3/log(cos(rho/2));
2650 object->cutoff = pLight->Phi*90/M_PI;
2656 FIXME("Unrecognized light type %d\n", pLight->Type);
2659 /* Update the live definitions if the light is currently assigned a glIndex */
2660 if (object->glIndex != -1) {
2661 setup_light(iface, object->glIndex, object);
2666 HRESULT WINAPI IWineD3DDeviceImpl_GetLight(IWineD3DDevice *iface, DWORD Index, WINED3DLIGHT* pLight) {
2667 PLIGHTINFOEL *lightInfo = NULL;
2668 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2669 TRACE("(%p) : Idx(%ld), pLight(%p)\n", This, Index, pLight);
2671 /* Locate the light in the live lights */
2672 lightInfo = This->stateBlock->lights;
2673 while (lightInfo != NULL && lightInfo->OriginalIndex != Index) lightInfo = lightInfo->next;
2675 if (lightInfo == NULL) {
2676 TRACE("Light information requested but light not defined\n");
2677 return WINED3DERR_INVALIDCALL;
2680 memcpy(pLight, &lightInfo->OriginalParms, sizeof(D3DLIGHT9));
2685 * Get / Set Light Enable
2686 * (Note for consistency, renamed d3dx function by adding the 'set' prefix)
2688 HRESULT WINAPI IWineD3DDeviceImpl_SetLightEnable(IWineD3DDevice *iface, DWORD Index, BOOL Enable) {
2689 PLIGHTINFOEL *lightInfo = NULL;
2690 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2691 TRACE("(%p) : Idx(%ld), enable? %d\n", This, Index, Enable);
2693 /* If recording state block, just add to end of lights chain with changedEnable set to true */
2694 if (This->isRecordingState) {
2695 lightInfo = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(PLIGHTINFOEL));
2696 if (NULL == lightInfo) {
2697 return WINED3DERR_OUTOFVIDEOMEMORY;
2699 lightInfo->OriginalIndex = Index;
2700 lightInfo->glIndex = -1;
2701 lightInfo->enabledChanged = TRUE;
2703 /* Add to the END of the chain of lights changes to be replayed */
2704 if (This->updateStateBlock->lights == NULL) {
2705 This->updateStateBlock->lights = lightInfo;
2707 PLIGHTINFOEL *temp = This->updateStateBlock->lights;
2708 while (temp->next != NULL) temp=temp->next;
2709 temp->next = lightInfo;
2711 TRACE("Recording... not performing anything more\n");
2715 /* Not recording... So, locate the light in the live lights */
2716 lightInfo = This->stateBlock->lights;
2717 while (lightInfo != NULL && lightInfo->OriginalIndex != Index) lightInfo = lightInfo->next;
2719 /* Special case - enabling an undefined light creates one with a strict set of parms! */
2720 if (lightInfo == NULL) {
2722 TRACE("Light enabled requested but light not defined, so defining one!\n");
2723 IWineD3DDeviceImpl_SetLight(iface, Index, &WINED3D_default_light);
2725 /* Search for it again! Should be fairly quick as near head of list */
2726 lightInfo = This->stateBlock->lights;
2727 while (lightInfo != NULL && lightInfo->OriginalIndex != Index) lightInfo = lightInfo->next;
2728 if (lightInfo == NULL) {
2729 FIXME("Adding default lights has failed dismally\n");
2730 return WINED3DERR_INVALIDCALL;
2734 /* OK, we now have a light... */
2735 if (Enable == FALSE) {
2737 /* If we are disabling it, check it was enabled, and
2738 still only do something if it has assigned a glIndex (which it should have!) */
2739 if ((lightInfo->lightEnabled) && (lightInfo->glIndex != -1)) {
2740 TRACE("Disabling light set up at gl idx %ld\n", lightInfo->glIndex);
2742 glDisable(GL_LIGHT0 + lightInfo->glIndex);
2743 checkGLcall("glDisable GL_LIGHT0+Index");
2746 TRACE("Nothing to do as light was not enabled\n");
2748 lightInfo->lightEnabled = FALSE;
2751 /* We are enabling it. If it is enabled, it's really simple */
2752 if (lightInfo->lightEnabled) {
2754 TRACE("Nothing to do as light was enabled\n");
2756 /* If it already has a glIndex, it's still simple */
2757 } else if (lightInfo->glIndex != -1) {
2758 TRACE("Reusing light as already set up at gl idx %ld\n", lightInfo->glIndex);
2759 lightInfo->lightEnabled = TRUE;
2761 glEnable(GL_LIGHT0 + lightInfo->glIndex);
2762 checkGLcall("glEnable GL_LIGHT0+Index already setup");
2765 /* Otherwise got to find space - lights are ordered gl indexes first */
2767 PLIGHTINFOEL *bsf = NULL;
2768 PLIGHTINFOEL *pos = This->stateBlock->lights;
2769 PLIGHTINFOEL *prev = NULL;
2773 /* Try to minimize changes as much as possible */
2774 while (pos != NULL && pos->glIndex != -1 && Index < This->maxConcurrentLights) {
2776 /* Try to remember which index can be replaced if necessary */
2777 if (bsf==NULL && pos->lightEnabled == FALSE) {
2778 /* Found a light we can replace, save as best replacement */
2782 /* Step to next space */
2788 /* If we have too many active lights, fail the call */
2789 if ((Index == This->maxConcurrentLights) && (bsf == NULL)) {
2790 FIXME("Program requests too many concurrent lights\n");
2791 return WINED3DERR_INVALIDCALL;
2793 /* If we have allocated all lights, but not all are enabled,
2794 reuse one which is not enabled */
2795 } else if (Index == This->maxConcurrentLights) {
2796 /* use bsf - Simply swap the new light and the BSF one */
2797 PLIGHTINFOEL *bsfNext = bsf->next;
2798 PLIGHTINFOEL *bsfPrev = bsf->prev;
2801 if (lightInfo->next != NULL) lightInfo->next->prev = bsf;
2802 if (bsf->prev != NULL) {
2803 bsf->prev->next = lightInfo;
2805 This->stateBlock->lights = lightInfo;
2808 /* If not side by side, lots of chains to update */
2809 if (bsf->next != lightInfo) {
2810 lightInfo->prev->next = bsf;
2811 bsf->next->prev = lightInfo;
2812 bsf->next = lightInfo->next;
2813 bsf->prev = lightInfo->prev;
2814 lightInfo->next = bsfNext;
2815 lightInfo->prev = bsfPrev;
2819 bsf->prev = lightInfo;
2820 bsf->next = lightInfo->next;
2821 lightInfo->next = bsf;
2822 lightInfo->prev = bsfPrev;
2827 glIndex = bsf->glIndex;
2829 lightInfo->glIndex = glIndex;
2830 lightInfo->lightEnabled = TRUE;
2832 /* Finally set up the light in gl itself */
2833 TRACE("Replacing light which was set up at gl idx %ld\n", lightInfo->glIndex);
2835 setup_light(iface, glIndex, lightInfo);
2836 glEnable(GL_LIGHT0 + glIndex);
2837 checkGLcall("glEnable GL_LIGHT0 new setup");
2840 /* If we reached the end of the allocated lights, with space in the
2841 gl lights, setup a new light */
2842 } else if (pos->glIndex == -1) {
2844 /* We reached the end of the allocated gl lights, so already
2845 know the index of the next one! */
2847 lightInfo->glIndex = glIndex;
2848 lightInfo->lightEnabled = TRUE;
2850 /* In an ideal world, it's already in the right place */
2851 if (lightInfo->prev == NULL || lightInfo->prev->glIndex!=-1) {
2852 /* No need to move it */
2854 /* Remove this light from the list */
2855 lightInfo->prev->next = lightInfo->next;
2856 if (lightInfo->next != NULL) {
2857 lightInfo->next->prev = lightInfo->prev;
2860 /* Add in at appropriate place (inbetween prev and pos) */
2861 lightInfo->prev = prev;
2862 lightInfo->next = pos;
2864 This->stateBlock->lights = lightInfo;
2866 prev->next = lightInfo;
2869 pos->prev = lightInfo;
2873 /* Finally set up the light in gl itself */
2874 TRACE("Defining new light at gl idx %ld\n", lightInfo->glIndex);
2876 setup_light(iface, glIndex, lightInfo);
2877 glEnable(GL_LIGHT0 + glIndex);
2878 checkGLcall("glEnable GL_LIGHT0 new setup");
2887 HRESULT WINAPI IWineD3DDeviceImpl_GetLightEnable(IWineD3DDevice *iface, DWORD Index,BOOL* pEnable) {
2889 PLIGHTINFOEL *lightInfo = NULL;
2890 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2891 TRACE("(%p) : for idx(%ld)\n", This, Index);
2893 /* Locate the light in the live lights */
2894 lightInfo = This->stateBlock->lights;
2895 while (lightInfo != NULL && lightInfo->OriginalIndex != Index) lightInfo = lightInfo->next;
2897 if (lightInfo == NULL) {
2898 TRACE("Light enabled state requested but light not defined\n");
2899 return WINED3DERR_INVALIDCALL;
2901 *pEnable = lightInfo->lightEnabled;
2906 * Get / Set Clip Planes
2908 HRESULT WINAPI IWineD3DDeviceImpl_SetClipPlane(IWineD3DDevice *iface, DWORD Index, CONST float *pPlane) {
2909 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2910 TRACE("(%p) : for idx %ld, %p\n", This, Index, pPlane);
2912 /* Validate Index */
2913 if (Index >= GL_LIMITS(clipplanes)) {
2914 TRACE("Application has requested clipplane this device doesn't support\n");
2915 return WINED3DERR_INVALIDCALL;
2918 This->updateStateBlock->changed.clipplane[Index] = TRUE;
2919 This->updateStateBlock->set.clipplane[Index] = TRUE;
2920 This->updateStateBlock->clipplane[Index][0] = pPlane[0];
2921 This->updateStateBlock->clipplane[Index][1] = pPlane[1];
2922 This->updateStateBlock->clipplane[Index][2] = pPlane[2];
2923 This->updateStateBlock->clipplane[Index][3] = pPlane[3];
2925 /* Handle recording of state blocks */
2926 if (This->isRecordingState) {
2927 TRACE("Recording... not performing anything\n");
2935 /* Clip Plane settings are affected by the model view in OpenGL, the View transform in direct3d */
2936 glMatrixMode(GL_MODELVIEW);
2938 glLoadMatrixf((float *) &This->stateBlock->transforms[D3DTS_VIEW].u.m[0][0]);
2940 TRACE("Clipplane [%f,%f,%f,%f]\n",
2941 This->updateStateBlock->clipplane[Index][0],
2942 This->updateStateBlock->clipplane[Index][1],
2943 This->updateStateBlock->clipplane[Index][2],
2944 This->updateStateBlock->clipplane[Index][3]);
2945 glClipPlane(GL_CLIP_PLANE0 + Index, This->updateStateBlock->clipplane[Index]);
2946 checkGLcall("glClipPlane");
2954 HRESULT WINAPI IWineD3DDeviceImpl_GetClipPlane(IWineD3DDevice *iface, DWORD Index, float *pPlane) {
2955 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2956 TRACE("(%p) : for idx %ld\n", This, Index);
2958 /* Validate Index */
2959 if (Index >= GL_LIMITS(clipplanes)) {
2960 TRACE("Application has requested clipplane this device doesn't support\n");
2961 return WINED3DERR_INVALIDCALL;
2964 pPlane[0] = This->stateBlock->clipplane[Index][0];
2965 pPlane[1] = This->stateBlock->clipplane[Index][1];
2966 pPlane[2] = This->stateBlock->clipplane[Index][2];
2967 pPlane[3] = This->stateBlock->clipplane[Index][3];
2972 * Get / Set Clip Plane Status
2973 * WARNING: This code relies on the fact that D3DCLIPSTATUS8 == D3DCLIPSTATUS9
2975 HRESULT WINAPI IWineD3DDeviceImpl_SetClipStatus(IWineD3DDevice *iface, CONST WINED3DCLIPSTATUS* pClipStatus) {
2976 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2977 FIXME("(%p) : stub\n", This);
2978 if (NULL == pClipStatus) {
2979 return WINED3DERR_INVALIDCALL;
2981 This->updateStateBlock->clip_status.ClipUnion = pClipStatus->ClipUnion;
2982 This->updateStateBlock->clip_status.ClipIntersection = pClipStatus->ClipIntersection;
2986 HRESULT WINAPI IWineD3DDeviceImpl_GetClipStatus(IWineD3DDevice *iface, WINED3DCLIPSTATUS* pClipStatus) {
2987 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2988 FIXME("(%p) : stub\n", This);
2989 if (NULL == pClipStatus) {
2990 return WINED3DERR_INVALIDCALL;
2992 pClipStatus->ClipUnion = This->updateStateBlock->clip_status.ClipUnion;
2993 pClipStatus->ClipIntersection = This->updateStateBlock->clip_status.ClipIntersection;
2998 * Get / Set Material
2999 * WARNING: This code relies on the fact that D3DMATERIAL8 == D3DMATERIAL9
3001 HRESULT WINAPI IWineD3DDeviceImpl_SetMaterial(IWineD3DDevice *iface, CONST WINED3DMATERIAL* pMaterial) {
3002 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3004 This->updateStateBlock->changed.material = TRUE;
3005 This->updateStateBlock->set.material = TRUE;
3006 memcpy(&This->updateStateBlock->material, pMaterial, sizeof(WINED3DMATERIAL));
3008 /* Handle recording of state blocks */
3009 if (This->isRecordingState) {
3010 TRACE("Recording... not performing anything\n");
3015 TRACE("(%p) : Diffuse (%f,%f,%f,%f)\n", This, pMaterial->Diffuse.r, pMaterial->Diffuse.g,
3016 pMaterial->Diffuse.b, pMaterial->Diffuse.a);
3017 TRACE("(%p) : Ambient (%f,%f,%f,%f)\n", This, pMaterial->Ambient.r, pMaterial->Ambient.g,
3018 pMaterial->Ambient.b, pMaterial->Ambient.a);
3019 TRACE("(%p) : Specular (%f,%f,%f,%f)\n", This, pMaterial->Specular.r, pMaterial->Specular.g,
3020 pMaterial->Specular.b, pMaterial->Specular.a);
3021 TRACE("(%p) : Emissive (%f,%f,%f,%f)\n", This, pMaterial->Emissive.r, pMaterial->Emissive.g,
3022 pMaterial->Emissive.b, pMaterial->Emissive.a);
3023 TRACE("(%p) : Power (%f)\n", This, pMaterial->Power);
3025 glMaterialfv(GL_FRONT_AND_BACK, GL_AMBIENT, (float*) &This->updateStateBlock->material.Ambient);
3026 checkGLcall("glMaterialfv(GL_AMBIENT)");
3027 glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, (float*) &This->updateStateBlock->material.Diffuse);
3028 checkGLcall("glMaterialfv(GL_DIFFUSE)");
3030 /* Only change material color if specular is enabled, otherwise it is set to black */
3031 if (This->stateBlock->renderState[WINED3DRS_SPECULARENABLE]) {
3032 glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, (float*) &This->updateStateBlock->material.Specular);
3033 checkGLcall("glMaterialfv(GL_SPECULAR");
3035 float black[4] = {0.0f, 0.0f, 0.0f, 0.0f};
3036 glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, &black[0]);
3037 checkGLcall("glMaterialfv(GL_SPECULAR");
3039 glMaterialfv(GL_FRONT_AND_BACK, GL_EMISSION, (float*) &This->updateStateBlock->material.Emissive);
3040 checkGLcall("glMaterialfv(GL_EMISSION)");
3041 glMaterialf(GL_FRONT_AND_BACK, GL_SHININESS, This->updateStateBlock->material.Power);
3042 checkGLcall("glMaterialf(GL_SHININESS");
3048 HRESULT WINAPI IWineD3DDeviceImpl_GetMaterial(IWineD3DDevice *iface, WINED3DMATERIAL* pMaterial) {
3049 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3050 memcpy(pMaterial, &This->updateStateBlock->material, sizeof (WINED3DMATERIAL));
3051 TRACE("(%p) : Diffuse (%f,%f,%f,%f)\n", This, pMaterial->Diffuse.r, pMaterial->Diffuse.g,
3052 pMaterial->Diffuse.b, pMaterial->Diffuse.a);
3053 TRACE("(%p) : Ambient (%f,%f,%f,%f)\n", This, pMaterial->Ambient.r, pMaterial->Ambient.g,
3054 pMaterial->Ambient.b, pMaterial->Ambient.a);
3055 TRACE("(%p) : Specular (%f,%f,%f,%f)\n", This, pMaterial->Specular.r, pMaterial->Specular.g,
3056 pMaterial->Specular.b, pMaterial->Specular.a);
3057 TRACE("(%p) : Emissive (%f,%f,%f,%f)\n", This, pMaterial->Emissive.r, pMaterial->Emissive.g,
3058 pMaterial->Emissive.b, pMaterial->Emissive.a);
3059 TRACE("(%p) : Power (%f)\n", This, pMaterial->Power);
3067 HRESULT WINAPI IWineD3DDeviceImpl_SetIndices(IWineD3DDevice *iface, IWineD3DIndexBuffer* pIndexData,
3068 UINT BaseVertexIndex) {
3069 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3070 IWineD3DIndexBuffer *oldIdxs;
3072 TRACE("(%p) : Setting to %p, base %d\n", This, pIndexData, BaseVertexIndex);
3073 oldIdxs = This->updateStateBlock->pIndexData;
3075 This->updateStateBlock->changed.indices = TRUE;
3076 This->updateStateBlock->set.indices = TRUE;
3077 This->updateStateBlock->pIndexData = pIndexData;
3078 This->updateStateBlock->baseVertexIndex = BaseVertexIndex;
3080 /* Handle recording of state blocks */
3081 if (This->isRecordingState) {
3082 TRACE("Recording... not performing anything\n");
3086 if (NULL != pIndexData) {
3087 IWineD3DIndexBuffer_AddRef(pIndexData);
3089 if (NULL != oldIdxs) {
3090 IWineD3DIndexBuffer_Release(oldIdxs);
3095 HRESULT WINAPI IWineD3DDeviceImpl_GetIndices(IWineD3DDevice *iface, IWineD3DIndexBuffer** ppIndexData, UINT* pBaseVertexIndex) {
3096 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3098 *ppIndexData = This->stateBlock->pIndexData;
3100 /* up ref count on ppindexdata */
3102 IWineD3DIndexBuffer_AddRef(*ppIndexData);
3103 *pBaseVertexIndex = This->stateBlock->baseVertexIndex;
3104 TRACE("(%p) index data set to %p + %u\n", This, ppIndexData, This->stateBlock->baseVertexIndex);
3106 TRACE("(%p) No index data set\n", This);
3108 TRACE("Returning %p %d\n", *ppIndexData, *pBaseVertexIndex);
3114 * Get / Set Viewports
3116 HRESULT WINAPI IWineD3DDeviceImpl_SetViewport(IWineD3DDevice *iface, CONST WINED3DVIEWPORT* pViewport) {
3117 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3119 TRACE("(%p)\n", This);
3120 This->updateStateBlock->changed.viewport = TRUE;
3121 This->updateStateBlock->set.viewport = TRUE;
3122 memcpy(&This->updateStateBlock->viewport, pViewport, sizeof(WINED3DVIEWPORT));
3124 /* Handle recording of state blocks */
3125 if (This->isRecordingState) {
3126 TRACE("Recording... not performing anything\n");
3129 This->viewport_changed = TRUE;
3133 TRACE("(%p) : x=%ld, y=%ld, wid=%ld, hei=%ld, minz=%f, maxz=%f\n", This,
3134 pViewport->X, pViewport->Y, pViewport->Width, pViewport->Height, pViewport->MinZ, pViewport->MaxZ);
3136 glDepthRange(pViewport->MinZ, pViewport->MaxZ);
3137 checkGLcall("glDepthRange");
3138 /* Note: GL requires lower left, DirectX supplies upper left */
3139 /* TODO: replace usage of renderTarget with context management */
3140 glViewport(pViewport->X,
3141 (((IWineD3DSurfaceImpl *)This->renderTarget)->currentDesc.Height - (pViewport->Y + pViewport->Height)),
3142 pViewport->Width, pViewport->Height);
3144 checkGLcall("glViewport");
3152 HRESULT WINAPI IWineD3DDeviceImpl_GetViewport(IWineD3DDevice *iface, WINED3DVIEWPORT* pViewport) {
3153 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3154 TRACE("(%p)\n", This);
3155 memcpy(pViewport, &This->stateBlock->viewport, sizeof(WINED3DVIEWPORT));
3160 * Get / Set Render States
3161 * TODO: Verify against dx9 definitions
3163 HRESULT WINAPI IWineD3DDeviceImpl_SetRenderState(IWineD3DDevice *iface, D3DRENDERSTATETYPE State, DWORD Value) {
3165 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3166 DWORD OldValue = This->stateBlock->renderState[State];
3168 /* Simple way of referring to either a DWORD or a 4 byte float */
3174 TRACE("(%p)->state = %s(%d), value = %ld\n", This, debug_d3drenderstate(State), State, Value);
3175 This->updateStateBlock->changed.renderState[State] = TRUE;
3176 This->updateStateBlock->set.renderState[State] = TRUE;
3177 This->updateStateBlock->renderState[State] = Value;
3179 /* Handle recording of state blocks */
3180 if (This->isRecordingState) {
3181 TRACE("Recording... not performing anything\n");
3188 case WINED3DRS_FILLMODE :
3189 switch ((D3DFILLMODE) Value) {
3190 case D3DFILL_POINT : glPolygonMode(GL_FRONT_AND_BACK, GL_POINT); break;
3191 case D3DFILL_WIREFRAME : glPolygonMode(GL_FRONT_AND_BACK, GL_LINE); break;
3192 case D3DFILL_SOLID : glPolygonMode(GL_FRONT_AND_BACK, GL_FILL); break;
3194 FIXME("Unrecognized WINED3DRS_FILLMODE value %ld\n", Value);
3196 checkGLcall("glPolygonMode (fillmode)");
3199 case WINED3DRS_LIGHTING :
3201 glEnable(GL_LIGHTING);
3202 checkGLcall("glEnable GL_LIGHTING");
3204 glDisable(GL_LIGHTING);
3205 checkGLcall("glDisable GL_LIGHTING");
3209 case WINED3DRS_ZENABLE :
3210 switch ((D3DZBUFFERTYPE) Value) {
3212 glDisable(GL_DEPTH_TEST);
3213 checkGLcall("glDisable GL_DEPTH_TEST");
3216 glEnable(GL_DEPTH_TEST);
3217 checkGLcall("glEnable GL_DEPTH_TEST");
3220 glEnable(GL_DEPTH_TEST);
3221 checkGLcall("glEnable GL_DEPTH_TEST");
3222 FIXME("W buffer is not well handled\n");
3225 FIXME("Unrecognized D3DZBUFFERTYPE value %ld\n", Value);
3229 case WINED3DRS_CULLMODE :
3231 /* If we are culling "back faces with clockwise vertices" then
3232 set front faces to be counter clockwise and enable culling
3234 switch ((D3DCULL) Value) {
3236 glDisable(GL_CULL_FACE);
3237 checkGLcall("glDisable GL_CULL_FACE");
3240 glEnable(GL_CULL_FACE);
3241 checkGLcall("glEnable GL_CULL_FACE");
3242 if (This->renderUpsideDown) {
3244 checkGLcall("glFrontFace GL_CW");
3246 glFrontFace(GL_CCW);
3247 checkGLcall("glFrontFace GL_CCW");
3249 glCullFace(GL_BACK);
3252 glEnable(GL_CULL_FACE);
3253 checkGLcall("glEnable GL_CULL_FACE");
3254 if (This->renderUpsideDown) {
3255 glFrontFace(GL_CCW);
3256 checkGLcall("glFrontFace GL_CCW");
3259 checkGLcall("glFrontFace GL_CW");
3261 glCullFace(GL_BACK);
3264 FIXME("Unrecognized/Unhandled D3DCULL value %ld\n", Value);
3268 case WINED3DRS_SHADEMODE :
3269 switch ((D3DSHADEMODE) Value) {
3271 glShadeModel(GL_FLAT);
3272 checkGLcall("glShadeModel");
3274 case D3DSHADE_GOURAUD:
3275 glShadeModel(GL_SMOOTH);
3276 checkGLcall("glShadeModel");
3278 case D3DSHADE_PHONG:
3279 FIXME("D3DSHADE_PHONG isn't supported?\n");
3282 return WINED3DERR_INVALIDCALL;
3284 FIXME("Unrecognized/Unhandled D3DSHADEMODE value %ld\n", Value);
3288 case WINED3DRS_DITHERENABLE :
3290 glEnable(GL_DITHER);
3291 checkGLcall("glEnable GL_DITHER");
3293 glDisable(GL_DITHER);
3294 checkGLcall("glDisable GL_DITHER");
3298 case WINED3DRS_ZWRITEENABLE :
3301 checkGLcall("glDepthMask");
3304 checkGLcall("glDepthMask");
3308 case WINED3DRS_ZFUNC :
3310 int glParm = GL_LESS;
3312 switch ((D3DCMPFUNC) Value) {
3313 case D3DCMP_NEVER: glParm=GL_NEVER; break;
3314 case D3DCMP_LESS: glParm=GL_LESS; break;
3315 case D3DCMP_EQUAL: glParm=GL_EQUAL; break;
3316 case D3DCMP_LESSEQUAL: glParm=GL_LEQUAL; break;
3317 case D3DCMP_GREATER: glParm=GL_GREATER; break;
3318 case D3DCMP_NOTEQUAL: glParm=GL_NOTEQUAL; break;
3319 case D3DCMP_GREATEREQUAL: glParm=GL_GEQUAL; break;
3320 case D3DCMP_ALWAYS: glParm=GL_ALWAYS; break;
3322 FIXME("Unrecognized/Unhandled D3DCMPFUNC value %ld\n", Value);
3324 glDepthFunc(glParm);
3325 checkGLcall("glDepthFunc");
3329 case WINED3DRS_AMBIENT :
3332 D3DCOLORTOGLFLOAT4(Value, col);
3333 TRACE("Setting ambient to (%f,%f,%f,%f)\n", col[0], col[1], col[2], col[3]);
3334 glLightModelfv(GL_LIGHT_MODEL_AMBIENT, col);
3335 checkGLcall("glLightModel for MODEL_AMBIENT");
3340 case WINED3DRS_ALPHABLENDENABLE :
3343 checkGLcall("glEnable GL_BLEND");
3345 glDisable(GL_BLEND);
3346 checkGLcall("glDisable GL_BLEND");
3350 case WINED3DRS_SRCBLEND :
3351 case WINED3DRS_DESTBLEND :
3353 int newVal = GL_ZERO;
3355 case D3DBLEND_ZERO : newVal = GL_ZERO; break;
3356 case D3DBLEND_ONE : newVal = GL_ONE; break;
3357 case D3DBLEND_SRCCOLOR : newVal = GL_SRC_COLOR; break;
3358 case D3DBLEND_INVSRCCOLOR : newVal = GL_ONE_MINUS_SRC_COLOR; break;
3359 case D3DBLEND_SRCALPHA : newVal = GL_SRC_ALPHA; break;
3360 case D3DBLEND_INVSRCALPHA : newVal = GL_ONE_MINUS_SRC_ALPHA; break;
3361 case D3DBLEND_DESTALPHA : newVal = GL_DST_ALPHA; break;
3362 case D3DBLEND_INVDESTALPHA : newVal = GL_ONE_MINUS_DST_ALPHA; break;
3363 case D3DBLEND_DESTCOLOR : newVal = GL_DST_COLOR; break;
3364 case D3DBLEND_INVDESTCOLOR : newVal = GL_ONE_MINUS_DST_COLOR; break;
3365 case D3DBLEND_SRCALPHASAT : newVal = GL_SRC_ALPHA_SATURATE; break;
3367 case D3DBLEND_BOTHSRCALPHA : newVal = GL_SRC_ALPHA;
3368 This->srcBlend = newVal;
3369 This->dstBlend = newVal;
3372 case D3DBLEND_BOTHINVSRCALPHA : newVal = GL_ONE_MINUS_SRC_ALPHA;
3373 This->srcBlend = newVal;
3374 This->dstBlend = newVal;
3377 FIXME("Unrecognized src/dest blend value %ld (%d)\n", Value, State);
3380 if (State == WINED3DRS_SRCBLEND) This->srcBlend = newVal;
3381 if (State == WINED3DRS_DESTBLEND) This->dstBlend = newVal;
3382 TRACE("glBlendFunc src=%x, dst=%x\n", This->srcBlend, This->dstBlend);
3383 glBlendFunc(This->srcBlend, This->dstBlend);
3385 checkGLcall("glBlendFunc");
3389 case WINED3DRS_ALPHATESTENABLE :
3390 case WINED3DRS_ALPHAFUNC :
3391 case WINED3DRS_ALPHAREF :
3392 case WINED3DRS_COLORKEYENABLE :
3395 float ref = GL_LESS;
3396 BOOL enable_ckey = FALSE;
3398 IWineD3DSurfaceImpl *surf;
3400 /* Find out if the texture on the first stage has a ckey set */
3401 if(This->stateBlock->textures[0]) {
3402 surf = (IWineD3DSurfaceImpl *) ((IWineD3DTextureImpl *)This->stateBlock->textures[0])->surfaces[0];
3403 if(surf->CKeyFlags & DDSD_CKSRCBLT) enable_ckey = TRUE;
3406 if (This->stateBlock->renderState[WINED3DRS_ALPHATESTENABLE] ||
3407 (This->stateBlock->renderState[WINED3DRS_COLORKEYENABLE] && enable_ckey)) {
3408 glEnable(GL_ALPHA_TEST);
3409 checkGLcall("glEnable GL_ALPHA_TEST");
3411 glDisable(GL_ALPHA_TEST);
3412 checkGLcall("glDisable GL_ALPHA_TEST");
3413 /* Alpha test is disabled, don't bother setting the params - it will happen on the next
3419 if(This->stateBlock->renderState[WINED3DRS_COLORKEYENABLE] && enable_ckey) {
3420 glParm = GL_NOTEQUAL;
3423 ref = ((float) This->stateBlock->renderState[WINED3DRS_ALPHAREF]) / 255.0f;
3425 switch ((D3DCMPFUNC) This->stateBlock->renderState[WINED3DRS_ALPHAFUNC]) {
3426 case D3DCMP_NEVER: glParm = GL_NEVER; break;
3427 case D3DCMP_LESS: glParm = GL_LESS; break;
3428 case D3DCMP_EQUAL: glParm = GL_EQUAL; break;
3429 case D3DCMP_LESSEQUAL: glParm = GL_LEQUAL; break;
3430 case D3DCMP_GREATER: glParm = GL_GREATER; break;
3431 case D3DCMP_NOTEQUAL: glParm = GL_NOTEQUAL; break;
3432 case D3DCMP_GREATEREQUAL: glParm = GL_GEQUAL; break;
3433 case D3DCMP_ALWAYS: glParm = GL_ALWAYS; break;
3435 FIXME("Unrecognized/Unhandled D3DCMPFUNC value %ld\n", Value);
3438 This->alphafunc = glParm;
3439 glAlphaFunc(glParm, ref);
3440 checkGLcall("glAlphaFunc");
3444 case WINED3DRS_CLIPPLANEENABLE :
3445 case WINED3DRS_CLIPPING :
3447 /* Ensure we only do the changed clip planes */
3448 DWORD enable = 0xFFFFFFFF;
3449 DWORD disable = 0x00000000;
3451 /* If enabling / disabling all */
3452 if (State == WINED3DRS_CLIPPING) {
3454 enable = This->stateBlock->renderState[WINED3DRS_CLIPPLANEENABLE];
3457 disable = This->stateBlock->renderState[WINED3DRS_CLIPPLANEENABLE];
3461 enable = Value & ~OldValue;
3462 disable = ~Value & OldValue;
3465 if (enable & D3DCLIPPLANE0) { glEnable(GL_CLIP_PLANE0); checkGLcall("glEnable(clip plane 0)"); }
3466 if (enable & D3DCLIPPLANE1) { glEnable(GL_CLIP_PLANE1); checkGLcall("glEnable(clip plane 1)"); }
3467 if (enable & D3DCLIPPLANE2) { glEnable(GL_CLIP_PLANE2); checkGLcall("glEnable(clip plane 2)"); }
3468 if (enable & D3DCLIPPLANE3) { glEnable(GL_CLIP_PLANE3); checkGLcall("glEnable(clip plane 3)"); }
3469 if (enable & D3DCLIPPLANE4) { glEnable(GL_CLIP_PLANE4); checkGLcall("glEnable(clip plane 4)"); }
3470 if (enable & D3DCLIPPLANE5) { glEnable(GL_CLIP_PLANE5); checkGLcall("glEnable(clip plane 5)"); }
3472 if (disable & D3DCLIPPLANE0) { glDisable(GL_CLIP_PLANE0); checkGLcall("glDisable(clip plane 0)"); }
3473 if (disable & D3DCLIPPLANE1) { glDisable(GL_CLIP_PLANE1); checkGLcall("glDisable(clip plane 1)"); }
3474 if (disable & D3DCLIPPLANE2) { glDisable(GL_CLIP_PLANE2); checkGLcall("glDisable(clip plane 2)"); }
3475 if (disable & D3DCLIPPLANE3) { glDisable(GL_CLIP_PLANE3); checkGLcall("glDisable(clip plane 3)"); }
3476 if (disable & D3DCLIPPLANE4) { glDisable(GL_CLIP_PLANE4); checkGLcall("glDisable(clip plane 4)"); }
3477 if (disable & D3DCLIPPLANE5) { glDisable(GL_CLIP_PLANE5); checkGLcall("glDisable(clip plane 5)"); }
3479 /** update clipping status */
3481 This->stateBlock->clip_status.ClipUnion = 0;
3482 This->stateBlock->clip_status.ClipIntersection = 0xFFFFFFFF;
3484 This->stateBlock->clip_status.ClipUnion = 0;
3485 This->stateBlock->clip_status.ClipIntersection = 0;
3490 case WINED3DRS_BLENDOP :
3492 int glParm = GL_FUNC_ADD;
3494 switch ((D3DBLENDOP) Value) {
3495 case D3DBLENDOP_ADD : glParm = GL_FUNC_ADD; break;
3496 case D3DBLENDOP_SUBTRACT : glParm = GL_FUNC_SUBTRACT; break;
3497 case D3DBLENDOP_REVSUBTRACT : glParm = GL_FUNC_REVERSE_SUBTRACT; break;
3498 case D3DBLENDOP_MIN : glParm = GL_MIN; break;
3499 case D3DBLENDOP_MAX : glParm = GL_MAX; break;
3501 FIXME("Unrecognized/Unhandled D3DBLENDOP value %ld\n", Value);
3504 if(GL_SUPPORT(ARB_IMAGING)) {
3505 TRACE("glBlendEquation(%x)\n", glParm);
3506 GL_EXTCALL(glBlendEquation(glParm));
3507 checkGLcall("glBlendEquation");
3509 WARN("Unsupported in local OpenGL implementation: glBlendEquation\n");
3514 case WINED3DRS_TEXTUREFACTOR :
3518 /* Note the texture color applies to all textures whereas
3519 GL_TEXTURE_ENV_COLOR applies to active only */
3521 D3DCOLORTOGLFLOAT4(Value, col);
3522 /* Set the default alpha blend color */
3523 if (GL_SUPPORT(ARB_IMAGING)) {
3524 GL_EXTCALL(glBlendColor(col[0], col[1], col[2], col[3]));
3525 checkGLcall("glBlendColor");
3527 WARN("Unsupported in local OpenGL implementation: glBlendColor\n");
3530 /* And now the default texture color as well */
3531 for (i = 0; i < GL_LIMITS(textures); i++) {
3533 /* Note the D3DRS value applies to all textures, but GL has one
3534 per texture, so apply it now ready to be used! */
3535 if (GL_SUPPORT(ARB_MULTITEXTURE)) {
3536 GL_EXTCALL(glActiveTextureARB(GL_TEXTURE0_ARB + i));
3537 checkGLcall("glActiveTextureARB");
3539 FIXME("Program using multiple concurrent textures which this opengl implementation doesn't support\n");
3542 glTexEnvfv(GL_TEXTURE_ENV, GL_TEXTURE_ENV_COLOR, &col[0]);
3543 checkGLcall("glTexEnvfv(GL_TEXTURE_ENV, GL_TEXTURE_ENV_COLOR, color);");
3548 case WINED3DRS_SPECULARENABLE :
3550 /* Originally this used glLightModeli(GL_LIGHT_MODEL_COLOR_CONTROL,GL_SEPARATE_SPECULAR_COLOR)
3551 and (GL_LIGHT_MODEL_COLOR_CONTROL,GL_SINGLE_COLOR) to swap between enabled/disabled
3552 specular color. This is wrong:
3553 Separate specular color means the specular colour is maintained separately, whereas
3554 single color means it is merged in. However in both cases they are being used to
3556 To disable specular color, set it explicitly to black and turn off GL_COLOR_SUM_EXT
3557 NOTE: If not supported don't give FIXMEs the impact is really minimal and very few people are
3561 glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, (float*) &This->updateStateBlock->material.Specular);
3562 checkGLcall("glMaterialfv");
3563 if (GL_SUPPORT(EXT_SECONDARY_COLOR)) {
3564 glEnable(GL_COLOR_SUM_EXT);
3566 TRACE("Specular colors cannot be enabled in this version of opengl\n");
3568 checkGLcall("glEnable(GL_COLOR_SUM)");
3570 float black[4] = {0.0f, 0.0f, 0.0f, 0.0f};
3572 /* for the case of enabled lighting: */
3573 glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, &black[0]);
3574 checkGLcall("glMaterialfv");
3576 /* for the case of disabled lighting: */
3577 if (GL_SUPPORT(EXT_SECONDARY_COLOR)) {
3578 glDisable(GL_COLOR_SUM_EXT);
3580 TRACE("Specular colors cannot be disabled in this version of opengl\n");
3582 checkGLcall("glDisable(GL_COLOR_SUM)");
3587 case WINED3DRS_STENCILENABLE :
3589 glEnable(GL_STENCIL_TEST);
3590 checkGLcall("glEnable GL_STENCIL_TEST");
3592 glDisable(GL_STENCIL_TEST);
3593 checkGLcall("glDisable GL_STENCIL_TEST");
3597 case WINED3DRS_STENCILFUNC :
3600 GLint ref = This->stateBlock->renderState[WINED3DRS_STENCILREF];
3601 GLuint mask = This->stateBlock->renderState[WINED3DRS_STENCILMASK];
3604 switch ((D3DCMPFUNC)Value) {
3605 case D3DCMP_NEVER: func = GL_NEVER; break;
3606 case D3DCMP_LESS: func = GL_LESS; break;
3607 case D3DCMP_EQUAL: func = GL_EQUAL; break;
3608 case D3DCMP_LESSEQUAL: func = GL_LEQUAL; break;
3609 case D3DCMP_GREATER: func = GL_GREATER; break;
3610 case D3DCMP_NOTEQUAL: func = GL_NOTEQUAL; break;
3611 case D3DCMP_GREATEREQUAL: func = GL_GEQUAL; break;
3612 case D3DCMP_ALWAYS: func = GL_ALWAYS; break;
3614 FIXME("Unrecognized/Unhandled D3DCMPFUNC value %ld\n", Value);
3616 This->stencilfunc = func;
3617 if(!This->stateBlock->renderState[WINED3DRS_TWOSIDEDSTENCILMODE]) {
3618 #if 0 /* Don't use OpenGL 2.0 calls for now */
3619 if(GL_EXTCALL(glStencilFuncSeparate)) {
3620 GL_EXTCALL(glStencilFuncSeparate(GL_FRONT, func, ref, mask));
3621 checkGLcall("glStencilFuncSeparate(GL_FRONT,...)");
3625 if(GL_SUPPORT(EXT_STENCIL_TWO_SIDE)) {
3626 glEnable(GL_STENCIL_TEST_TWO_SIDE_EXT);
3627 checkGLcall("glEnable(GL_STENCIL_TEST_TWO_SIDE_EXT)");
3628 GL_EXTCALL(glActiveStencilFaceEXT(GL_FRONT));
3629 checkGLcall("glActiveStencilFaceEXT(GL_FRONT)");
3630 glStencilFunc(func, ref, mask);
3631 checkGLcall("glStencilFunc(...)");
3633 else if(GL_SUPPORT(ATI_SEPARATE_STENCIL)) {
3634 GL_EXTCALL(glStencilFuncSeparateATI(GL_FRONT, func, ref, mask));
3635 checkGLcall("glStencilFuncSeparateATI(GL_FRONT,...)");
3637 TRACE("Separate stencil function not supported on this version of opengl");
3638 glStencilFunc(func, ref, mask);
3639 checkGLcall("glStencilFunc(...)");
3642 glStencilFunc(func, ref, mask);
3643 checkGLcall("glStencilFunc(...)");
3647 case WINED3DRS_STENCILREF :
3649 int glParm = This->stencilfunc;
3651 GLuint mask = This->stateBlock->renderState[WINED3DRS_STENCILMASK];
3654 TRACE("glStencilFunc with Parm=%x, ref=%d, mask=%x\n", glParm, ref, mask);
3655 glStencilFunc(glParm, ref, mask);
3656 checkGLcall("glStencilFunc");
3660 case WINED3DRS_STENCILMASK :
3662 int glParm = This->stencilfunc;
3663 int ref = This->stateBlock->renderState[WINED3DRS_STENCILREF];
3664 GLuint mask = Value;
3666 TRACE("glStencilFunc with Parm=%x, ref=%d, mask=%x\n", glParm, ref, mask);
3667 glStencilFunc(glParm, ref, mask);
3668 checkGLcall("glStencilFunc");
3672 case WINED3DRS_STENCILFAIL :
3673 case WINED3DRS_STENCILZFAIL :
3674 case WINED3DRS_STENCILPASS :
3680 GLint action = StencilOp(Value);
3682 glGetIntegerv(GL_STENCIL_FAIL, &stencilFail);
3683 glGetIntegerv(GL_STENCIL_PASS_DEPTH_FAIL, &depthFail);
3684 glGetIntegerv(GL_STENCIL_PASS_DEPTH_PASS, &stencilPass);
3686 if(WINED3DRS_STENCILFAIL == State) {
3687 stencilFail = action;
3689 else if(WINED3DRS_STENCILZFAIL == State) {
3692 else if(WINED3DRS_STENCILPASS == State) {
3693 stencilPass = action;
3696 if(!This->stateBlock->renderState[WINED3DRS_TWOSIDEDSTENCILMODE]) {
3697 #if 0 /* Don't use OpenGL 2.0 calls for now */
3698 if(GL_EXTCALL(glStencilOpSeparate)) {
3699 GL_EXTCALL(glStencilOpSeparate(GL_FRONT, stencilFail, depthFail, stencilPass));
3700 checkGLcall("glStencilOpSeparate(GL_FRONT,...)");
3704 if(GL_SUPPORT(EXT_STENCIL_TWO_SIDE)) {
3705 glEnable(GL_STENCIL_TEST_TWO_SIDE_EXT);
3706 checkGLcall("glEnable(GL_STENCIL_TEST_TWO_SIDE_EXT)");
3707 GL_EXTCALL(glActiveStencilFaceEXT(GL_FRONT));
3708 checkGLcall("glActiveStencilFaceEXT(GL_FRONT)");
3709 glStencilOp(stencilFail, depthFail, stencilPass);
3710 checkGLcall("glStencilOp(...)");
3712 else if(GL_SUPPORT(ATI_SEPARATE_STENCIL)) {
3713 GL_EXTCALL(glStencilOpSeparateATI(GL_FRONT, stencilFail, depthFail, stencilPass));
3714 checkGLcall("glStencilOpSeparateATI(GL_FRONT,...)");
3716 TRACE("Separate stencil operation not supported on this version of opengl");
3717 glStencilOp(stencilFail, depthFail, stencilPass);
3718 checkGLcall("glStencilOp(...)");
3721 glStencilOp(stencilFail, depthFail, stencilPass);
3722 checkGLcall("glStencilOp(...)");
3726 case WINED3DRS_STENCILWRITEMASK :
3728 glStencilMask(Value);
3729 TRACE("glStencilMask(%lu)\n", Value);
3730 checkGLcall("glStencilMask");
3734 case WINED3DRS_FOGENABLE :
3736 if (Value/* && This->stateBlock->renderState[WINED3DRS_FOGTABLEMODE] != D3DFOG_NONE*/) {
3738 checkGLcall("glEnable GL_FOG");
3741 checkGLcall("glDisable GL_FOG");
3746 case WINED3DRS_RANGEFOGENABLE :
3749 TRACE("Enabled RANGEFOG");
3751 TRACE("Disabled RANGEFOG");
3756 case WINED3DRS_FOGCOLOR :
3759 D3DCOLORTOGLFLOAT4(Value, col);
3760 /* Set the default alpha blend color */
3761 glFogfv(GL_FOG_COLOR, &col[0]);
3762 checkGLcall("glFog GL_FOG_COLOR");
3766 case WINED3DRS_FOGTABLEMODE :
3768 glHint(GL_FOG_HINT, GL_NICEST);
3771 if(This->stateBlock->renderState[WINED3DRS_FOGVERTEXMODE] == D3DFOG_NONE) {
3772 glFogi(GL_FOG_MODE, GL_LINEAR); checkGLcall("glFogi(GL_FOG_MODE, GL_LINEAR");
3774 /* Otherwise leave the vertex fog value */
3777 case D3DFOG_EXP: glFogi(GL_FOG_MODE, GL_EXP); checkGLcall("glFogi(GL_FOG_MODE, GL_EXP"); break;
3778 case D3DFOG_EXP2: glFogi(GL_FOG_MODE, GL_EXP2); checkGLcall("glFogi(GL_FOG_MODE, GL_EXP2"); break;
3779 case D3DFOG_LINEAR: glFogi(GL_FOG_MODE, GL_LINEAR); checkGLcall("glFogi(GL_FOG_MODE, GL_LINEAR"); break;
3781 FIXME("Unsupported Value(%lu) for WINED3DRS_FOGTABLEMODE!\n", Value);
3783 if (GL_SUPPORT(NV_FOG_DISTANCE)) {
3784 glFogi(GL_FOG_DISTANCE_MODE_NV, GL_EYE_PLANE_ABSOLUTE_NV);
3789 case WINED3DRS_FOGVERTEXMODE :
3791 glHint(GL_FOG_HINT, GL_FASTEST);
3792 /* 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." */
3793 if(This->stateBlock->renderState[WINED3DRS_FOGTABLEMODE] == D3DFOG_NONE) {
3795 case D3DFOG_EXP: glFogi(GL_FOG_MODE, GL_EXP); checkGLcall("glFogi(GL_FOG_MODE, GL_EXP"); break;
3796 case D3DFOG_EXP2: glFogi(GL_FOG_MODE, GL_EXP2); checkGLcall("glFogi(GL_FOG_MODE, GL_EXP2"); break;
3798 case D3DFOG_LINEAR: glFogi(GL_FOG_MODE, GL_LINEAR); checkGLcall("glFogi(GL_FOG_MODE, GL_LINEAR"); break;
3800 FIXME("Unsupported Value(%lu) for WINED3DRS_FOGTABLEMODE!\n", Value);
3802 if (GL_SUPPORT(NV_FOG_DISTANCE)) {
3803 glFogi(GL_FOG_DISTANCE_MODE_NV, This->stateBlock->renderState[WINED3DRS_RANGEFOGENABLE] ? GL_EYE_RADIAL_NV : GL_EYE_PLANE_ABSOLUTE_NV);
3809 case WINED3DRS_FOGSTART :
3812 glFogfv(GL_FOG_START, &tmpvalue.f);
3813 checkGLcall("glFogf(GL_FOG_START, (float) Value)");
3814 TRACE("Fog Start == %f\n", tmpvalue.f);
3818 case WINED3DRS_FOGEND :
3821 glFogfv(GL_FOG_END, &tmpvalue.f);
3822 checkGLcall("glFogf(GL_FOG_END, (float) Value)");
3823 TRACE("Fog End == %f\n", tmpvalue.f);
3827 case WINED3DRS_FOGDENSITY :
3830 glFogfv(GL_FOG_DENSITY, &tmpvalue.f);
3831 checkGLcall("glFogf(GL_FOG_DENSITY, (float) Value)");
3835 case WINED3DRS_VERTEXBLEND :
3837 This->updateStateBlock->vertex_blend = (D3DVERTEXBLENDFLAGS) Value;
3838 TRACE("Vertex Blending state to %ld\n", Value);
3842 case WINED3DRS_TWEENFACTOR :
3845 This->updateStateBlock->tween_factor = tmpvalue.f;
3846 TRACE("Vertex Blending Tween Factor to %f\n", This->updateStateBlock->tween_factor);
3850 case WINED3DRS_INDEXEDVERTEXBLENDENABLE :
3852 TRACE("Indexed Vertex Blend Enable to %ul\n", (BOOL) Value);
3856 case WINED3DRS_COLORVERTEX :
3857 case WINED3DRS_DIFFUSEMATERIALSOURCE :
3858 case WINED3DRS_SPECULARMATERIALSOURCE :
3859 case WINED3DRS_AMBIENTMATERIALSOURCE :
3860 case WINED3DRS_EMISSIVEMATERIALSOURCE :
3862 GLenum Parm = GL_AMBIENT_AND_DIFFUSE;
3864 if (This->stateBlock->renderState[WINED3DRS_COLORVERTEX]) {
3865 TRACE("diff %ld, amb %ld, emis %ld, spec %ld\n",
3866 This->stateBlock->renderState[WINED3DRS_DIFFUSEMATERIALSOURCE],
3867 This->stateBlock->renderState[WINED3DRS_AMBIENTMATERIALSOURCE],
3868 This->stateBlock->renderState[WINED3DRS_EMISSIVEMATERIALSOURCE],
3869 This->stateBlock->renderState[WINED3DRS_SPECULARMATERIALSOURCE]);
3871 if (This->stateBlock->renderState[WINED3DRS_DIFFUSEMATERIALSOURCE] == D3DMCS_COLOR1) {
3872 if (This->stateBlock->renderState[WINED3DRS_AMBIENTMATERIALSOURCE] == D3DMCS_COLOR1) {
3873 Parm = GL_AMBIENT_AND_DIFFUSE;
3877 } else if (This->stateBlock->renderState[WINED3DRS_AMBIENTMATERIALSOURCE] == D3DMCS_COLOR1) {
3879 } else if (This->stateBlock->renderState[WINED3DRS_EMISSIVEMATERIALSOURCE] == D3DMCS_COLOR1) {
3881 } else if (This->stateBlock->renderState[WINED3DRS_SPECULARMATERIALSOURCE] == D3DMCS_COLOR1) {
3888 if (This->tracking_color != DISABLED_TRACKING) This->tracking_color = NEEDS_DISABLE;
3890 This->tracking_color = NEEDS_TRACKING;
3891 This->tracking_parm = Parm;
3895 if (This->tracking_color != DISABLED_TRACKING) This->tracking_color = NEEDS_DISABLE;
3900 case WINED3DRS_LINEPATTERN :
3906 tmppattern.d = Value;
3908 TRACE("Line pattern: repeat %d bits %x\n", tmppattern.lp.wRepeatFactor, tmppattern.lp.wLinePattern);
3910 if (tmppattern.lp.wRepeatFactor) {
3911 glLineStipple(tmppattern.lp.wRepeatFactor, tmppattern.lp.wLinePattern);
3912 checkGLcall("glLineStipple(repeat, linepattern)");
3913 glEnable(GL_LINE_STIPPLE);
3914 checkGLcall("glEnable(GL_LINE_STIPPLE);");
3916 glDisable(GL_LINE_STIPPLE);
3917 checkGLcall("glDisable(GL_LINE_STIPPLE);");
3922 case WINED3DRS_ZBIAS : /* D3D8 only */
3926 TRACE("ZBias value %f\n", tmpvalue.f);
3927 glPolygonOffset(0, -tmpvalue.f);
3928 checkGLcall("glPolygonOffset(0, -Value)");
3929 glEnable(GL_POLYGON_OFFSET_FILL);
3930 checkGLcall("glEnable(GL_POLYGON_OFFSET_FILL);");
3931 glEnable(GL_POLYGON_OFFSET_LINE);
3932 checkGLcall("glEnable(GL_POLYGON_OFFSET_LINE);");
3933 glEnable(GL_POLYGON_OFFSET_POINT);
3934 checkGLcall("glEnable(GL_POLYGON_OFFSET_POINT);");
3936 glDisable(GL_POLYGON_OFFSET_FILL);
3937 checkGLcall("glDisable(GL_POLYGON_OFFSET_FILL);");
3938 glDisable(GL_POLYGON_OFFSET_LINE);
3939 checkGLcall("glDisable(GL_POLYGON_OFFSET_LINE);");
3940 glDisable(GL_POLYGON_OFFSET_POINT);
3941 checkGLcall("glDisable(GL_POLYGON_OFFSET_POINT);");
3946 case WINED3DRS_NORMALIZENORMALS :
3948 glEnable(GL_NORMALIZE);
3949 checkGLcall("glEnable(GL_NORMALIZE);");
3951 glDisable(GL_NORMALIZE);
3952 checkGLcall("glDisable(GL_NORMALIZE);");
3956 case WINED3DRS_POINTSIZE :
3957 /* FIXME: check that pointSize isn't outside glGetFloatv( GL_POINT_SIZE_MAX_ARB, &maxSize ); or -ve */
3959 TRACE("Set point size to %f\n", tmpvalue.f);
3960 glPointSize(tmpvalue.f);
3961 checkGLcall("glPointSize(...);");
3964 case WINED3DRS_POINTSIZE_MIN :
3965 if (GL_SUPPORT(EXT_POINT_PARAMETERS)) {
3967 GL_EXTCALL(glPointParameterfEXT)(GL_POINT_SIZE_MIN_EXT, tmpvalue.f);
3968 checkGLcall("glPointParameterfEXT(...);");
3970 FIXME("WINED3DRS_POINTSIZE_MIN not supported on this opengl\n");
3974 case WINED3DRS_POINTSIZE_MAX :
3975 if (GL_SUPPORT(EXT_POINT_PARAMETERS)) {
3977 GL_EXTCALL(glPointParameterfEXT)(GL_POINT_SIZE_MAX_EXT, tmpvalue.f);
3978 checkGLcall("glPointParameterfEXT(...);");
3980 FIXME("WINED3DRS_POINTSIZE_MAX not supported on this opengl\n");
3984 case WINED3DRS_POINTSCALE_A :
3985 case WINED3DRS_POINTSCALE_B :
3986 case WINED3DRS_POINTSCALE_C :
3987 case WINED3DRS_POINTSCALEENABLE :
3990 * POINTSCALEENABLE controls how point size value is treated. If set to
3991 * true, the point size is scaled with respect to height of viewport.
3992 * When set to false point size is in pixels.
3994 * http://msdn.microsoft.com/library/en-us/directx9_c/point_sprites.asp
3997 /* Default values */
3998 GLfloat att[3] = {1.0f, 0.0f, 0.0f};
4001 * Minimum valid point size for OpenGL is 1.0f. For Direct3D it is 0.0f.
4002 * This means that OpenGL will clamp really small point sizes to 1.0f.
4003 * To correct for this we need to multiply by the scale factor when sizes
4004 * are less than 1.0f. scale_factor = 1.0f / point_size.
4006 GLfloat pointSize = *((float*)&This->stateBlock->renderState[WINED3DRS_POINTSIZE]);
4007 if(pointSize > 0.0f) {
4008 GLfloat scaleFactor;
4010 if(pointSize < 1.0f) {
4011 scaleFactor = pointSize * pointSize;
4016 if(This->stateBlock->renderState[WINED3DRS_POINTSCALEENABLE]) {
4017 att[0] = *((float*)&This->stateBlock->renderState[WINED3DRS_POINTSCALE_A]) /
4018 (This->stateBlock->viewport.Height * This->stateBlock->viewport.Height * scaleFactor);
4019 att[1] = *((float*)&This->stateBlock->renderState[WINED3DRS_POINTSCALE_B]) /
4020 (This->stateBlock->viewport.Height * This->stateBlock->viewport.Height * scaleFactor);
4021 att[2] = *((float*)&This->stateBlock->renderState[WINED3DRS_POINTSCALE_C]) /
4022 (This->stateBlock->viewport.Height * This->stateBlock->viewport.Height * scaleFactor);
4026 if(GL_SUPPORT(ARB_POINT_PARAMETERS)) {
4027 GL_EXTCALL(glPointParameterfvARB)(GL_POINT_DISTANCE_ATTENUATION_ARB, att);
4028 checkGLcall("glPointParameterfvARB(GL_DISTANCE_ATTENUATION_ARB, ...");
4030 else if(GL_SUPPORT(EXT_POINT_PARAMETERS)) {
4031 GL_EXTCALL(glPointParameterfvEXT)(GL_DISTANCE_ATTENUATION_EXT, att);
4032 checkGLcall("glPointParameterfvEXT(GL_DISTANCE_ATTENUATION_EXT, ...");
4034 TRACE("POINT_PARAMETERS not supported in this version of opengl\n");
4038 case WINED3DRS_COLORWRITEENABLE :
4040 TRACE("Color mask: r(%d) g(%d) b(%d) a(%d)\n",
4041 Value & D3DCOLORWRITEENABLE_RED ? 1 : 0,
4042 Value & D3DCOLORWRITEENABLE_GREEN ? 1 : 0,
4043 Value & D3DCOLORWRITEENABLE_BLUE ? 1 : 0,
4044 Value & D3DCOLORWRITEENABLE_ALPHA ? 1 : 0);
4045 glColorMask(Value & D3DCOLORWRITEENABLE_RED ? GL_TRUE : GL_FALSE,
4046 Value & D3DCOLORWRITEENABLE_GREEN ? GL_TRUE : GL_FALSE,
4047 Value & D3DCOLORWRITEENABLE_BLUE ? GL_TRUE : GL_FALSE,
4048 Value & D3DCOLORWRITEENABLE_ALPHA ? GL_TRUE : GL_FALSE);
4049 checkGLcall("glColorMask(...)");
4053 case WINED3DRS_LOCALVIEWER :
4055 GLint state = (Value) ? 1 : 0;
4056 TRACE("Local Viewer Enable to %ul\n", (BOOL) Value);
4057 glLightModeli(GL_LIGHT_MODEL_LOCAL_VIEWER, state);
4061 case WINED3DRS_LASTPIXEL :
4064 TRACE("Last Pixel Drawing Enabled\n");
4066 FIXME("Last Pixel Drawing Disabled, not handled yet\n");
4071 case WINED3DRS_SOFTWAREVERTEXPROCESSING :
4074 TRACE("Software Processing Enabled\n");
4076 TRACE("Software Processing Disabled\n");
4081 /** not supported */
4082 case WINED3DRS_ZVISIBLE :
4085 return WINED3DERR_INVALIDCALL;
4087 case WINED3DRS_POINTSPRITEENABLE :
4089 /* TODO: NV_POINT_SPRITE */
4090 if (!GL_SUPPORT(ARB_POINT_SPRITE)) {
4091 TRACE("Point sprites not supported\n");
4096 * Point sprites are always enabled. Value controls texture coordinate
4097 * replacement mode. Must be set true for point sprites to use
4100 glEnable(GL_POINT_SPRITE_ARB);
4101 checkGLcall("glEnable(GL_POINT_SPRITE_ARB)");
4104 glTexEnvf(GL_POINT_SPRITE_ARB, GL_COORD_REPLACE_ARB, TRUE);
4105 checkGLcall("glTexEnvf(GL_POINT_SPRITE, GL_COORD_REPLACE, TRUE)");
4107 glTexEnvf(GL_POINT_SPRITE_ARB, GL_COORD_REPLACE_ARB, FALSE);
4108 checkGLcall("glTexEnvf(GL_POINT_SPRITE, GL_COORD_REPLACE, FALSE)");
4112 case WINED3DRS_EDGEANTIALIAS :
4115 glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
4117 checkGLcall("glEnable(GL_BLEND)");
4118 glEnable(GL_LINE_SMOOTH);
4119 checkGLcall("glEnable(GL_LINE_SMOOTH)");
4121 if(!This->stateBlock->renderState[WINED3DRS_ALPHABLENDENABLE])
4122 glDisable(GL_BLEND);
4123 checkGLcall("glDisable(GL_BLEND)");
4124 glDisable(GL_LINE_SMOOTH);
4125 checkGLcall("glDisable(GL_LINE_SMOOTH)");
4129 case WINED3DRS_WRAP0 :
4130 case WINED3DRS_WRAP1 :
4131 case WINED3DRS_WRAP2 :
4132 case WINED3DRS_WRAP3 :
4133 case WINED3DRS_WRAP4 :
4134 case WINED3DRS_WRAP5 :
4135 case WINED3DRS_WRAP6 :
4136 case WINED3DRS_WRAP7 :
4137 case WINED3DRS_WRAP8 :
4138 case WINED3DRS_WRAP9 :
4139 case WINED3DRS_WRAP10 :
4140 case WINED3DRS_WRAP11 :
4141 case WINED3DRS_WRAP12 :
4142 case WINED3DRS_WRAP13 :
4143 case WINED3DRS_WRAP14 :
4144 case WINED3DRS_WRAP15 :
4146 http://www.cosc.brocku.ca/Offerings/3P98/course/lectures/texture/
4147 http://msdn.microsoft.com/archive/default.asp?url=/archive/en-us/directx9_c/directx/graphics/programmingguide/FixedFunction/Textures/texturewrapping.asp
4148 http://www.gamedev.net/reference/programming/features/rendererdll3/page2.asp
4149 Descussion that ways to turn on WRAPing to solve an opengl conversion problem.
4150 http://www.flipcode.org/cgi-bin/fcmsg.cgi?thread_show=10248
4152 so far as I can tell, wrapping and texture-coordinate generate go hand in hand,
4154 TRACE("(%p)->(%s,%ld) Texture wraping not yet supported\n",This, debug_d3drenderstate(State), Value);
4156 case WINED3DRS_MULTISAMPLEANTIALIAS :
4158 if (!GL_SUPPORT(ARB_MULTISAMPLE)) {
4159 TRACE("Multisample antialiasing not supported\n");
4164 glEnable(GL_MULTISAMPLE_ARB);
4165 checkGLcall("glEnable(GL_MULTISAMPLE_ARB)");
4167 glDisable(GL_MULTISAMPLE_ARB);
4168 checkGLcall("glDisable(GL_MULTISAMPLE_ARB)");
4172 case WINED3DRS_SCISSORTESTENABLE :
4175 glEnable(GL_SCISSOR_TEST);
4176 checkGLcall("glEnable(GL_SCISSOR_TEST)");
4178 glDisable(GL_SCISSOR_TEST);
4179 checkGLcall("glDisable(GL_SCISSOR_TEST)");
4183 case WINED3DRS_SLOPESCALEDEPTHBIAS :
4187 glEnable(GL_POLYGON_OFFSET_FILL);
4188 checkGLcall("glEnable(GL_POLYGON_OFFSET_FILL)");
4189 glPolygonOffset(tmpvalue.f, *((float*)&This->stateBlock->renderState[WINED3DRS_DEPTHBIAS]));
4190 checkGLcall("glPolygonOffset(...)");
4192 glDisable(GL_POLYGON_OFFSET_FILL);
4193 checkGLcall("glDisable(GL_POLYGON_OFFSET_FILL)");
4197 case WINED3DRS_ANTIALIASEDLINEENABLE :
4200 glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
4202 checkGLcall("glEnable(GL_BLEND)");
4203 glEnable(GL_LINE_SMOOTH);
4204 checkGLcall("glEnable(GL_LINE_SMOOTH)");
4206 glDisable(GL_BLEND);
4207 checkGLcall("glDisable(GL_BLEND)");
4208 glDisable(GL_LINE_SMOOTH);
4209 checkGLcall("glDisable(GL_LINE_SMOOTH)");
4213 case WINED3DRS_TWOSIDEDSTENCILMODE :
4216 TRACE("Two-sided stencil mode enabled\n");
4218 TRACE("Two-sided stencil mode disabled\n");
4222 case WINED3DRS_CCW_STENCILFAIL :
4223 case WINED3DRS_CCW_STENCILZFAIL :
4224 case WINED3DRS_CCW_STENCILPASS :
4230 GLint action = StencilOp(Value);
4232 glGetIntegerv(GL_STENCIL_BACK_FAIL, &stencilFail);
4233 glGetIntegerv(GL_STENCIL_BACK_PASS_DEPTH_FAIL, &depthFail);
4234 glGetIntegerv(GL_STENCIL_BACK_PASS_DEPTH_PASS, &stencilPass);
4236 if(WINED3DRS_CCW_STENCILFAIL == State) {
4237 stencilFail = action;
4239 else if(WINED3DRS_CCW_STENCILZFAIL == State) {
4242 else if(WINED3DRS_CCW_STENCILPASS == State) {
4243 stencilPass = action;
4246 if(!This->stateBlock->renderState[WINED3DRS_TWOSIDEDSTENCILMODE]) {
4247 #if 0 /* Don't use OpenGL 2.0 calls for now */
4248 if(GL_EXTCALL(glStencilOpSeparate)) {
4249 GL_EXTCALL(glStencilOpSeparate(GL_BACK, stencilFail, depthFail, stencilPass));
4250 checkGLcall("glStencilOpSeparate(GL_BACK,...)");
4254 if(GL_SUPPORT(EXT_STENCIL_TWO_SIDE)) {
4255 glEnable(GL_STENCIL_TEST_TWO_SIDE_EXT);
4256 checkGLcall("glEnable(GL_STENCIL_TEST_TWO_SIDE_EXT)");
4257 GL_EXTCALL(glActiveStencilFaceEXT(GL_BACK));
4258 checkGLcall("glActiveStencilFaceEXT(GL_BACK)");
4259 glStencilOp(stencilFail, depthFail, stencilPass);
4260 checkGLcall("glStencilOp(...)");
4262 else if(GL_SUPPORT(ATI_SEPARATE_STENCIL)) {
4263 GL_EXTCALL(glStencilOpSeparateATI(GL_BACK, stencilFail, depthFail, stencilPass));
4264 checkGLcall("glStencilOpSeparateATI(GL_BACK,...)");
4266 TRACE("Separate stencil operation not supported on this version of opengl");
4267 glStencilOp(stencilFail, depthFail, stencilPass);
4268 checkGLcall("glStencilOp(...)");
4271 glStencilOp(stencilFail, depthFail, stencilPass);
4272 checkGLcall("glStencilOp(...)");
4276 case WINED3DRS_CCW_STENCILFUNC :
4279 GLint ref = This->stateBlock->renderState[WINED3DRS_STENCILREF];
4280 GLuint mask = This->stateBlock->renderState[WINED3DRS_STENCILMASK];
4283 switch ((D3DCMPFUNC)Value) {
4284 case D3DCMP_NEVER: func = GL_NEVER; break;
4285 case D3DCMP_LESS: func = GL_LESS; break;
4286 case D3DCMP_EQUAL: func = GL_EQUAL; break;
4287 case D3DCMP_LESSEQUAL: func = GL_LEQUAL; break;
4288 case D3DCMP_GREATER: func = GL_GREATER; break;
4289 case D3DCMP_NOTEQUAL: func = GL_NOTEQUAL; break;
4290 case D3DCMP_GREATEREQUAL: func = GL_GEQUAL; break;
4291 case D3DCMP_ALWAYS: func = GL_ALWAYS; break;
4293 FIXME("Unrecognized/Unhandled D3DCMPFUNC value %ld\n", Value);
4295 This->stencilfunc = func;
4296 if(!This->stateBlock->renderState[WINED3DRS_TWOSIDEDSTENCILMODE]) {
4297 #if 0 /* Don't use OpenGL 2.0 calls for now */
4298 if(GL_EXTCALL(glStencilFuncSeparate)) {
4299 GL_EXTCALL(glStencilFuncSeparate(GL_BACK, func, ref, mask));
4300 checkGLcall("glStencilFuncSeparate(GL_BACK,...)");
4304 if(GL_SUPPORT(EXT_STENCIL_TWO_SIDE)) {
4305 glEnable(GL_STENCIL_TEST_TWO_SIDE_EXT);
4306 checkGLcall("glEnable(GL_STENCIL_TEST_TWO_SIDE_EXT)");
4307 GL_EXTCALL(glActiveStencilFaceEXT(GL_BACK));
4308 checkGLcall("glActiveStencilFaceEXT(GL_BACK)");
4309 glStencilFunc(func, ref, mask);
4310 checkGLcall("glStencilFunc(...)");
4312 else if(GL_SUPPORT(ATI_SEPARATE_STENCIL)) {
4313 GL_EXTCALL(glStencilFuncSeparateATI(GL_BACK, func, ref, mask));
4314 checkGLcall("glStencilFuncSeparateATI(GL_BACK,...)");
4316 TRACE("Separate stencil function not supported on this version of opengl");
4317 glStencilFunc(func, ref, mask);
4318 checkGLcall("glStencilFunc(...)");
4321 glStencilFunc(func, ref, mask);
4322 checkGLcall("glStencilFunc(...)");
4326 case WINED3DRS_DEPTHBIAS :
4330 glEnable(GL_POLYGON_OFFSET_FILL);
4331 checkGLcall("glEnable(GL_POLYGON_OFFSET_FILL)");
4332 glPolygonOffset(*((float*)&This->stateBlock->renderState[WINED3DRS_SLOPESCALEDEPTHBIAS]), tmpvalue.f);
4333 checkGLcall("glPolygonOffset(...)");
4335 glDisable(GL_POLYGON_OFFSET_FILL);
4336 checkGLcall("glDisable(GL_POLYGON_OFFSET_FILL)");
4341 case WINED3DRS_TEXTUREPERSPECTIVE :
4344 glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST);
4346 glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_FASTEST);
4350 case WINED3DRS_STIPPLEDALPHA :
4353 ERR(" Stippled Alpha not supported yet.\n");
4356 case WINED3DRS_ANTIALIAS :
4359 ERR(" Antialias not supported yet.\n");
4363 FIXME("(%p)->(%s,%ld) not handled yet\n", This, debug_d3drenderstate(State), Value);
4371 HRESULT WINAPI IWineD3DDeviceImpl_GetRenderState(IWineD3DDevice *iface, D3DRENDERSTATETYPE State, DWORD *pValue) {
4372 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4373 TRACE("(%p) for State %d = %ld\n", This, State, This->stateBlock->renderState[State]);
4374 *pValue = This->stateBlock->renderState[State];
4379 * Get / Set Sampler States
4380 * TODO: Verify against dx9 definitions
4383 HRESULT WINAPI IWineD3DDeviceImpl_SetSamplerState(IWineD3DDevice *iface, DWORD Sampler, WINED3DSAMPLERSTATETYPE Type, DWORD Value) {
4384 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4386 * SetSampler is designed to allow for more than the standard up to 8 textures
4387 * and Geforce has stopped supporting more than 6 standard textures in openGL.
4388 * So I have to use ARB for Gforce. (maybe if the sampler > 4 then use ARB?)
4390 * http://developer.nvidia.com/object/General_FAQ.html#t6
4392 * There are two new settings for GForce
4394 * GL_MAX_TEXTURE_IMAGE_UNITS_ARB
4395 * and the texture one:
4396 * GL_MAX_TEXTURE_COORDS_ARB.
4397 * Ok GForce say it's ok to use glTexParameter/glGetTexParameter(...).
4399 /** NOTE: States are appled in IWineD3DBaseTextre ApplyStateChanges and IWineD3DDevice SetupTextureStates**/
4400 TRACE("(%p) Sampler(%ld), Type(%d) Value(%ld)\n",This, Sampler ,Type, Value);
4402 if(Sampler > GL_LIMITS(samplers) || Sampler < 0 || Type > WINED3D_HIGHEST_SAMPLER_STATE || Type < 0) {
4403 FIXME("out of range %d %d sampler %ld type %u\n", GL_LIMITS(samplers), WINED3D_HIGHEST_SAMPLER_STATE, Sampler, Type);
4404 return WINED3DERR_INVALIDCALL;
4406 TRACE("Setting sampler %ld %d to %ld\n", Sampler, Type, Value);
4407 This->updateStateBlock->samplerState[Sampler][Type] = Value;
4408 This->updateStateBlock->set.samplerState[Sampler][Type] = Value;
4409 This->updateStateBlock->changed.samplerState[Sampler][Type] = Value;
4411 /* Handle recording of state blocks */
4412 if (This->isRecordingState) {
4413 TRACE("Recording... not performing anything\n");
4420 HRESULT WINAPI IWineD3DDeviceImpl_GetSamplerState(IWineD3DDevice *iface, DWORD Sampler, WINED3DSAMPLERSTATETYPE Type, DWORD* Value) {
4421 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4422 /** TODO: check that sampler is in range **/
4423 *Value = This->updateStateBlock->samplerState[Sampler][Type];
4424 TRACE("(%p) : Sampler %ld Type %u Returning %ld\n", This, Sampler, Type, *Value);
4429 HRESULT WINAPI IWineD3DDeviceImpl_SetScissorRect(IWineD3DDevice *iface, CONST RECT* pRect) {
4430 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4433 /** FIXME: Windows uses a top,left origin openGL uses a bottom Right? **/
4434 TRACE("(%p)Setting new Scissor Rect to %ld:%ld-%ld:%ld\n", This, pRect->left, pRect->top, pRect->right, pRect->bottom);
4435 glScissor(pRect->left, pRect->top, pRect->right - pRect->left, pRect->bottom - pRect->top);
4441 HRESULT WINAPI IWineD3DDeviceImpl_GetScissorRect(IWineD3DDevice *iface, RECT* pRect) {
4442 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4443 GLint scissorBox[4];
4446 /** FIXME: Windows uses a top,left origin openGL uses a bottom Right? **/
4447 glGetIntegerv(GL_SCISSOR_BOX, scissorBox);
4448 pRect->left = scissorBox[1];
4449 pRect->top = scissorBox[2];
4450 pRect->right = scissorBox[1] + scissorBox[3];
4451 pRect->bottom = scissorBox[2] + scissorBox[4];
4452 TRACE("(%p)Returning a Scissor Rect of %ld:%ld-%ld:%ld\n", This, pRect->left, pRect->top, pRect->right, pRect->bottom);
4457 HRESULT WINAPI IWineD3DDeviceImpl_SetVertexDeclaration(IWineD3DDevice* iface, IWineD3DVertexDeclaration* pDecl) {
4458 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *) iface;
4459 IWineD3DVertexDeclaration *oldDecl = This->updateStateBlock->vertexDecl;
4461 TRACE("(%p) : pDecl=%p\n", This, pDecl);
4463 This->updateStateBlock->vertexDecl = pDecl;
4464 This->updateStateBlock->changed.vertexDecl = TRUE;
4465 This->updateStateBlock->set.vertexDecl = TRUE;
4467 if (This->isRecordingState) {
4468 TRACE("Recording... not performing anything\n");
4471 if (NULL != pDecl) {
4472 IWineD3DVertexDeclaration_AddRef(pDecl);
4474 if (NULL != oldDecl) {
4475 IWineD3DVertexDeclaration_Release(oldDecl);
4480 HRESULT WINAPI IWineD3DDeviceImpl_GetVertexDeclaration(IWineD3DDevice* iface, IWineD3DVertexDeclaration** ppDecl) {
4481 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4483 TRACE("(%p) : ppDecl=%p\n", This, ppDecl);
4485 *ppDecl = This->stateBlock->vertexDecl;
4486 if (NULL != *ppDecl) IWineD3DVertexDeclaration_AddRef(*ppDecl);
4490 HRESULT WINAPI IWineD3DDeviceImpl_SetVertexShader(IWineD3DDevice *iface, IWineD3DVertexShader* pShader) {
4491 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4492 IWineD3DVertexShader* oldShader = This->updateStateBlock->vertexShader;
4494 This->updateStateBlock->vertexShader = pShader;
4495 This->updateStateBlock->changed.vertexShader = TRUE;
4496 This->updateStateBlock->set.vertexShader = TRUE;
4498 if (This->isRecordingState) {
4499 TRACE("Recording... not performing anything\n");
4502 if (NULL != pShader) {
4503 IWineD3DVertexShader_AddRef(pShader);
4505 if (NULL != oldShader) {
4506 IWineD3DVertexShader_Release(oldShader);
4509 if (pShader != NULL && ((IWineD3DVertexShaderImpl *)pShader)->vertexDeclaration != NULL) {
4510 TRACE("(%p) : setting vertexDeclaration(%p)\n", This, ((IWineD3DVertexShaderImpl *)pShader)->vertexDeclaration);
4511 IWineD3DDevice_SetVertexDeclaration(iface, ((IWineD3DVertexShaderImpl *)pShader)->vertexDeclaration);
4514 TRACE("(%p) : setting pShader(%p)\n", This, pShader);
4516 * TODO: merge HAL shaders context switching from prototype
4521 HRESULT WINAPI IWineD3DDeviceImpl_GetVertexShader(IWineD3DDevice *iface, IWineD3DVertexShader** ppShader) {
4522 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4524 if (NULL == ppShader) {
4525 return WINED3DERR_INVALIDCALL;
4527 *ppShader = This->stateBlock->vertexShader;
4528 if( NULL != *ppShader)
4529 IWineD3DVertexShader_AddRef(*ppShader);
4531 TRACE("(%p) : returning %p\n", This, *ppShader);
4535 HRESULT WINAPI IWineD3DDeviceImpl_SetVertexShaderConstantB(
4536 IWineD3DDevice *iface,
4538 CONST BOOL *srcData,
4541 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4542 int i, cnt = min(count, MAX_VSHADER_CONSTANTS - (start + 1));
4544 TRACE("(iface %p, srcData %p, start %d, count %d)\n",
4545 iface, srcData, start, count);
4547 if (srcData == NULL || cnt < 0)
4548 return WINED3DERR_INVALIDCALL;
4550 memcpy(&This->updateStateBlock->vertexShaderConstantB[start], srcData, cnt * sizeof(BOOL));
4552 for (i = start; i < cnt + start; ++i) {
4553 This->updateStateBlock->changed.vertexShaderConstantsB[i] = TRUE;
4554 This->updateStateBlock->set.vertexShaderConstantsB[i] = TRUE;
4560 HRESULT WINAPI IWineD3DDeviceImpl_GetVertexShaderConstantB(
4561 IWineD3DDevice *iface,
4566 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4567 int cnt = min(count, MAX_VSHADER_CONSTANTS - (start + 1));
4569 TRACE("(iface %p, dstData %p, start %d, count %d)\n",
4570 iface, dstData, start, count);
4572 if (dstData == NULL || cnt < 0)
4573 return WINED3DERR_INVALIDCALL;
4575 memcpy(dstData, &This->updateStateBlock->vertexShaderConstantB[start], cnt * sizeof(BOOL));
4579 HRESULT WINAPI IWineD3DDeviceImpl_SetVertexShaderConstantI(
4580 IWineD3DDevice *iface,
4585 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4586 int i, cnt = min(count, MAX_VSHADER_CONSTANTS - (start + 1));
4588 TRACE("(iface %p, srcData %p, start %d, count %d)\n",
4589 iface, srcData, start, count);
4591 if (srcData == NULL || cnt < 0)
4592 return WINED3DERR_INVALIDCALL;
4594 memcpy(&This->updateStateBlock->vertexShaderConstantI[start * 4], srcData, cnt * sizeof(int) * 4);
4596 for (i = start; i < cnt + start; ++i) {
4597 This->updateStateBlock->changed.vertexShaderConstantsI[i] = TRUE;
4598 This->updateStateBlock->set.vertexShaderConstantsI[i] = TRUE;
4604 HRESULT WINAPI IWineD3DDeviceImpl_GetVertexShaderConstantI(
4605 IWineD3DDevice *iface,
4610 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4611 int cnt = min(count, MAX_VSHADER_CONSTANTS - (start + 1));
4613 TRACE("(iface %p, dstData %p, start %d, count %d)\n",
4614 iface, dstData, start, count);
4616 if (dstData == NULL || cnt < 0)
4617 return WINED3DERR_INVALIDCALL;
4619 memcpy(dstData, &This->updateStateBlock->vertexShaderConstantI[start * 4], cnt * sizeof(int) * 4);
4623 HRESULT WINAPI IWineD3DDeviceImpl_SetVertexShaderConstantF(
4624 IWineD3DDevice *iface,
4626 CONST float *srcData,
4629 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4630 int i, cnt = min(count, MAX_VSHADER_CONSTANTS - (start + 1));
4632 TRACE("(iface %p, srcData %p, start %d, count %d)\n",
4633 iface, srcData, start, count);
4635 if (srcData == NULL || cnt < 0)
4636 return WINED3DERR_INVALIDCALL;
4638 memcpy(&This->updateStateBlock->vertexShaderConstantF[start * 4], srcData, cnt * sizeof(float) * 4);
4640 for (i = start; i < cnt + start; ++i) {
4641 This->updateStateBlock->changed.vertexShaderConstantsF[i] = TRUE;
4642 This->updateStateBlock->set.vertexShaderConstantsF[i] = TRUE;
4648 HRESULT WINAPI IWineD3DDeviceImpl_GetVertexShaderConstantF(
4649 IWineD3DDevice *iface,
4654 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4655 int cnt = min(count, MAX_VSHADER_CONSTANTS - (start + 1));
4657 TRACE("(iface %p, dstData %p, start %d, count %d)\n",
4658 iface, dstData, start, count);
4660 if (dstData == NULL || cnt < 0)
4661 return WINED3DERR_INVALIDCALL;
4663 memcpy(dstData, &This->updateStateBlock->vertexShaderConstantF[start * 4], cnt * sizeof(float) * 4);
4667 HRESULT WINAPI IWineD3DDeviceImpl_SetPixelShader(IWineD3DDevice *iface, IWineD3DPixelShader *pShader) {
4668 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4669 IWineD3DPixelShader *oldShader = This->updateStateBlock->pixelShader;
4670 This->updateStateBlock->pixelShader = pShader;
4671 This->updateStateBlock->changed.pixelShader = TRUE;
4672 This->updateStateBlock->set.pixelShader = TRUE;
4674 /* Handle recording of state blocks */
4675 if (This->isRecordingState) {
4676 TRACE("Recording... not performing anything\n");
4679 if (NULL != pShader) {
4680 IWineD3DPixelShader_AddRef(pShader);
4682 if (NULL != oldShader) {
4683 IWineD3DPixelShader_Release(oldShader);
4686 TRACE("(%p) : setting pShader(%p)\n", This, pShader);
4688 * TODO: merge HAL shaders context switching from prototype
4693 HRESULT WINAPI IWineD3DDeviceImpl_GetPixelShader(IWineD3DDevice *iface, IWineD3DPixelShader **ppShader) {
4694 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4696 if (NULL == ppShader) {
4697 WARN("(%p) : PShader is NULL, returning INVALIDCALL\n", This);
4698 return WINED3DERR_INVALIDCALL;
4701 *ppShader = This->stateBlock->pixelShader;
4702 if (NULL != *ppShader) {
4703 IWineD3DPixelShader_AddRef(*ppShader);
4705 TRACE("(%p) : returning %p\n", This, *ppShader);
4709 HRESULT WINAPI IWineD3DDeviceImpl_SetPixelShaderConstantB(
4710 IWineD3DDevice *iface,
4712 CONST BOOL *srcData,
4715 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4716 int i, cnt = min(count, MAX_PSHADER_CONSTANTS - (start + 1));
4718 TRACE("(iface %p, srcData %p, start %d, count %d)\n",
4719 iface, srcData, start, count);
4721 if (srcData == NULL || cnt < 0)
4722 return WINED3DERR_INVALIDCALL;
4724 memcpy(&This->updateStateBlock->pixelShaderConstantB[start], srcData, cnt * sizeof(BOOL));
4726 for (i = start; i < cnt + start; ++i) {
4727 This->updateStateBlock->changed.pixelShaderConstantsB[i] = TRUE;
4728 This->updateStateBlock->set.pixelShaderConstantsB[i] = TRUE;
4734 HRESULT WINAPI IWineD3DDeviceImpl_GetPixelShaderConstantB(
4735 IWineD3DDevice *iface,
4740 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4741 int cnt = min(count, MAX_PSHADER_CONSTANTS - (start + 1));
4743 TRACE("(iface %p, dstData %p, start %d, count %d)\n",
4744 iface, dstData, start, count);
4746 if (dstData == NULL || cnt < 0)
4747 return WINED3DERR_INVALIDCALL;
4749 memcpy(dstData, &This->updateStateBlock->pixelShaderConstantB[start], cnt * sizeof(BOOL));
4753 HRESULT WINAPI IWineD3DDeviceImpl_SetPixelShaderConstantI(
4754 IWineD3DDevice *iface,
4759 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4760 int i, cnt = min(count, MAX_PSHADER_CONSTANTS - (start + 1));
4762 TRACE("(iface %p, srcData %p, start %d, count %d)\n",
4763 iface, srcData, start, count);
4765 if (srcData == NULL || cnt < 0)
4766 return WINED3DERR_INVALIDCALL;
4768 memcpy(&This->updateStateBlock->pixelShaderConstantI[start * 4], srcData, cnt * sizeof(int) * 4);
4770 for (i = start; i < cnt + start; ++i) {
4771 This->updateStateBlock->changed.pixelShaderConstantsI[i] = TRUE;
4772 This->updateStateBlock->set.pixelShaderConstantsI[i] = TRUE;
4778 HRESULT WINAPI IWineD3DDeviceImpl_GetPixelShaderConstantI(
4779 IWineD3DDevice *iface,
4784 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4785 int cnt = min(count, MAX_PSHADER_CONSTANTS - (start + 1));
4787 TRACE("(iface %p, dstData %p, start %d, count %d)\n",
4788 iface, dstData, start, count);
4790 if (dstData == NULL || cnt < 0)
4791 return WINED3DERR_INVALIDCALL;
4793 memcpy(dstData, &This->updateStateBlock->pixelShaderConstantI[start * 4], cnt * sizeof(int) * 4);
4797 HRESULT WINAPI IWineD3DDeviceImpl_SetPixelShaderConstantF(
4798 IWineD3DDevice *iface,
4800 CONST float *srcData,
4803 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4804 int i, cnt = min(count, MAX_PSHADER_CONSTANTS - (start + 1));
4806 TRACE("(iface %p, srcData %p, start %d, count %d)\n",
4807 iface, srcData, start, count);
4809 if (srcData == NULL || cnt < 0)
4810 return WINED3DERR_INVALIDCALL;
4812 memcpy(&This->updateStateBlock->pixelShaderConstantF[start * 4], srcData, cnt * sizeof(float) * 4);
4814 for (i = start; i < cnt + start; ++i) {
4815 This->updateStateBlock->changed.pixelShaderConstantsF[i] = TRUE;
4816 This->updateStateBlock->set.pixelShaderConstantsF[i] = TRUE;
4822 HRESULT WINAPI IWineD3DDeviceImpl_GetPixelShaderConstantF(
4823 IWineD3DDevice *iface,
4828 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4829 int cnt = min(count, MAX_PSHADER_CONSTANTS - (start + 1));
4831 TRACE("(iface %p, dstData %p, start %d, count %d)\n",
4832 iface, dstData, start, count);
4834 if (dstData == NULL || cnt < 0)
4835 return WINED3DERR_INVALIDCALL;
4837 memcpy(dstData, &This->updateStateBlock->pixelShaderConstantF[start * 4], cnt * sizeof(float) * 4);
4841 #define copy_and_next(dest, src, size) memcpy(dest, src, size); dest += (size)
4843 process_vertices_strided(IWineD3DDeviceImpl *This, DWORD dwDestIndex, DWORD dwCount, WineDirect3DVertexStridedData *lpStrideData, DWORD SrcFVF, IWineD3DVertexBufferImpl *dest, DWORD dwFlags) {
4846 DWORD DestFVF = dest->fvf;
4848 D3DMATRIX mat, proj_mat, view_mat, world_mat;
4852 if (SrcFVF & D3DFVF_NORMAL) {
4853 WARN(" lighting state not saved yet... Some strange stuff may happen !\n");
4856 if ( (SrcFVF & D3DFVF_POSITION_MASK) != D3DFVF_XYZ) {
4857 ERR("Source has no position mask\n");
4858 return WINED3DERR_INVALIDCALL;
4861 if (dest->resource.allocatedMemory == NULL) {
4862 ERR("Destination buffer has no memory allocated\n");
4863 return WINED3DERR_INVALIDCALL;
4867 * a) D3DRS_CLIPPING is enabled
4868 * b) WINED3DVOP_CLIP is passed
4870 if(This->stateBlock->renderState[WINED3DRS_CLIPPING]) {
4871 static BOOL warned = FALSE;
4873 * The clipping code is not quite correct. Some things need
4874 * to be checked against IDirect3DDevice3 (!), d3d8 and d3d9,
4875 * so disable clipping for now.
4876 * (The graphics in Half-Life are broken, and my processvertices
4877 * test crashes with IDirect3DDevice3)
4883 FIXME("Clipping is broken and disabled for now\n");
4885 } else doClip = FALSE;
4886 dest_ptr = ((char *) dest->resource.allocatedMemory) + dwDestIndex * get_flexible_vertex_size(DestFVF);
4888 IWineD3DDevice_GetTransform( (IWineD3DDevice *) This,
4891 IWineD3DDevice_GetTransform( (IWineD3DDevice *) This,
4894 IWineD3DDevice_GetTransform( (IWineD3DDevice *) This,
4895 D3DTS_WORLDMATRIX(0),
4898 TRACE("View mat: \n");
4899 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); \
4900 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); \
4901 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); \
4902 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); \
4904 TRACE("Proj mat: \n");
4905 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); \
4906 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); \
4907 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); \
4908 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); \
4910 TRACE("World mat: \n");
4911 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); \
4912 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); \
4913 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); \
4914 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); \
4916 /* Get the viewport */
4917 IWineD3DDevice_GetViewport( (IWineD3DDevice *) This, &vp);
4918 TRACE("Viewport: X=%ld, Y=%ld, Width=%ld, Height=%ld, MinZ=%f, MaxZ=%f\n",
4919 vp.X, vp.Y, vp.Width, vp.Height, vp.MinZ, vp.MaxZ);
4921 multiply_matrix(&mat,&view_mat,&world_mat);
4922 multiply_matrix(&mat,&proj_mat,&mat);
4924 numTextures = (DestFVF & D3DFVF_TEXCOUNT_MASK) >> D3DFVF_TEXCOUNT_SHIFT;
4926 for (i = 0; i < dwCount; i+= 1) {
4927 unsigned int tex_index;
4929 if ( ((DestFVF & D3DFVF_POSITION_MASK) == D3DFVF_XYZ ) ||
4930 ((DestFVF & D3DFVF_POSITION_MASK) == D3DFVF_XYZRHW ) ) {
4931 /* The position first */
4933 (float *) (((char *) lpStrideData->u.s.position.lpData) + i * lpStrideData->u.s.position.dwStride);
4935 TRACE("In: ( %06.2f %06.2f %06.2f )\n", p[0], p[1], p[2]);
4937 /* Multiplication with world, view and projection matrix */
4938 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);
4939 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);
4940 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);
4941 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);
4943 TRACE("x=%f y=%f z=%f rhw=%f\n", x, y, z, rhw);
4945 /* WARNING: The following things are taken from d3d7 and were not yet checked
4946 * against d3d8 or d3d9!
4949 /* Clipping conditions: From
4950 * http://msdn.microsoft.com/archive/default.asp?url=/archive/en-us/directx9_c/directx/graphics/programmingguide/fixedfunction/viewportsclipping/clippingvolumes.asp
4952 * A vertex is clipped if it does not match the following requirements
4956 * 0 < rhw ( Not in d3d7, but tested in d3d7)
4958 * If clipping is on is determined by the D3DVOP_CLIP flag in D3D7, and
4959 * by the D3DRS_CLIPPING in D3D9(according to the msdn, not checked)
4963 if( doClip == FALSE ||
4964 ( (-rhw -eps < x) && (-rhw -eps < y) && ( -eps < z) &&
4965 (x <= rhw + eps) && (y <= rhw + eps ) && (z <= rhw + eps) &&
4968 /* "Normal" viewport transformation (not clipped)
4969 * 1) The values are divided trough rhw
4970 * 2) The y axis is negative, so multiply it with -1
4971 * 3) Screen coordinates go from -(Width/2) to +(Width/2) and
4972 * -(Height/2) to +(Height/2). The z range is MinZ to MaxZ
4973 * 4) Multiply x with Width/2 and add Width/2
4974 * 5) The same for the height
4975 * 6) Add the viewpoint X and Y to the 2D coordinates and
4976 * The minimum Z value to z
4977 * 7) rhw = 1 / rhw Reciprocal of Homogeneous W....
4979 * Well, basically it's simply a linear transformation into viewport
4991 z *= vp.MaxZ - vp.MinZ;
4993 x += vp.Width / 2 + vp.X;
4994 y += vp.Height / 2 + vp.Y;
4999 /* That vertex got clipped
5000 * Contrary to OpenGL it is not dropped completely, it just
5001 * undergoes a different calculation.
5003 TRACE("Vertex got clipped\n");
5010 /* Msdn mentiones that Direct3D9 keeps a list of clipped vertices
5011 * outside of the main vertex buffer memory. That needs some more
5016 TRACE("Writing (%f %f %f) %f\n", x, y, z, rhw);
5019 ( (float *) dest_ptr)[0] = x;
5020 ( (float *) dest_ptr)[1] = y;
5021 ( (float *) dest_ptr)[2] = z;
5022 ( (float *) dest_ptr)[3] = rhw; /* SIC, see ddraw test! */
5024 dest_ptr += 3 * sizeof(float);
5026 if((DestFVF & D3DFVF_POSITION_MASK) == D3DFVF_XYZRHW) {
5027 dest_ptr += sizeof(float);
5030 if (DestFVF & D3DFVF_PSIZE) {
5031 dest_ptr += sizeof(DWORD);
5033 if (DestFVF & D3DFVF_NORMAL) {
5035 (float *) (((float *) lpStrideData->u.s.normal.lpData) + i * lpStrideData->u.s.normal.dwStride);
5036 /* AFAIK this should go into the lighting information */
5037 FIXME("Didn't expect the destination to have a normal\n");
5038 copy_and_next(dest_ptr, normal, 3 * sizeof(float));
5041 if (DestFVF & D3DFVF_DIFFUSE) {
5043 (DWORD *) (((char *) lpStrideData->u.s.diffuse.lpData) + i * lpStrideData->u.s.diffuse.dwStride);
5045 static BOOL warned = FALSE;
5047 if(warned == FALSE) {
5048 ERR("No diffuse color in source, but destination has one\n");
5052 *( (DWORD *) dest_ptr) = 0xffffffff;
5053 dest_ptr += sizeof(DWORD);
5056 copy_and_next(dest_ptr, color_d, sizeof(DWORD));
5059 if (DestFVF & D3DFVF_SPECULAR) {
5060 /* What's the color value in the feedback buffer? */
5062 (DWORD *) (((char *) lpStrideData->u.s.specular.lpData) + i * lpStrideData->u.s.specular.dwStride);
5064 static BOOL warned = FALSE;
5066 if(warned == FALSE) {
5067 ERR("No specular color in source, but destination has one\n");
5071 *( (DWORD *) dest_ptr) = 0xFF000000;
5072 dest_ptr += sizeof(DWORD);
5075 copy_and_next(dest_ptr, color_s, sizeof(DWORD));
5079 for (tex_index = 0; tex_index < numTextures; tex_index++) {
5081 (float *) (((char *) lpStrideData->u.s.texCoords[tex_index].lpData) +
5082 i * lpStrideData->u.s.texCoords[tex_index].dwStride);
5084 ERR("No source texture, but destination requests one\n");
5085 dest_ptr+=GET_TEXCOORD_SIZE_FROM_FVF(DestFVF, tex_index) * sizeof(float);
5088 copy_and_next(dest_ptr, tex_coord, GET_TEXCOORD_SIZE_FROM_FVF(DestFVF, tex_index) * sizeof(float));
5095 #undef copy_and_next
5097 HRESULT WINAPI IWineD3DDeviceImpl_ProcessVertices(IWineD3DDevice *iface, UINT SrcStartIndex, UINT DestIndex, UINT VertexCount, IWineD3DVertexBuffer* pDestBuffer, IWineD3DVertexBuffer* pVertexDecl, DWORD Flags) {
5098 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5099 IWineD3DVertexBufferImpl *SrcImpl = (IWineD3DVertexBufferImpl *) pVertexDecl;
5100 WineDirect3DVertexStridedData strided;
5102 TRACE("(%p)->(%d,%d,%d,%p,%p,%ld\n", This, SrcStartIndex, DestIndex, VertexCount, pDestBuffer, pVertexDecl, Flags);
5104 hr = IWineD3DDevice_SetFVF(iface, SrcImpl->fvf);
5105 hr = IWineD3DDevice_SetStreamSource(iface, 0, pVertexDecl, get_flexible_vertex_size(SrcImpl->fvf) * SrcStartIndex, get_flexible_vertex_size(SrcImpl->fvf));
5107 memset(&strided, 0, sizeof(strided));
5108 primitiveConvertToStridedData(iface, &strided, 0);
5110 return process_vertices_strided(This, DestIndex, VertexCount, &strided, SrcImpl->fvf, (IWineD3DVertexBufferImpl *) pDestBuffer, Flags);
5114 * Apply / Get / Set Texture Stage States
5115 * TODO: Verify against dx9 definitions
5118 /* 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 */
5119 static void WINAPI IWineD3DDeviceImpl_ApplyTextureUnitState(IWineD3DDevice *iface, DWORD Stage, WINED3DTEXTURESTAGESTATETYPE Type) {
5120 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5121 DWORD Value = This->updateStateBlock->textureState[Stage][Type];
5122 /* FIXME: Handle 3d textures? What if TSS value set before set texture? Need to reapply all values? */
5124 TRACE("(%p) : Stage=%ld, Type=%s(%d), Value=%ld\n", This, Stage, debug_d3dtexturestate(Type), Type, Value);
5126 /* Check that the stage is within limits */
5127 if (Stage >= GL_LIMITS(textures) || Stage < 0) {
5128 TRACE("Attempt to access invalid texture rejected\n");
5135 case WINED3DTSS_ALPHAOP :
5136 case WINED3DTSS_COLOROP :
5137 /* nothing to do as moved to drawprim for now */
5139 case WINED3DTSS_ADDRESSW :
5140 #if 0 /* I'm not sure what D3D does about ADDRESSW appearing twice */
5141 if (Value < minLookup[WINELOOKUP_WARPPARAM] || Value > maxLookup[WINELOOKUP_WARPPARAM]) {
5142 FIXME("Unrecognized or unsupported D3DTADDRESS_* value %ld, state %d\n", Value, Type);
5145 GLint wrapParm = stateLookup[WINELOOKUP_WARPPARAM][Value - minLookup[WINELOOKUP_WARPPARAM]];
5146 TRACE("Setting WRAP_R to %d for %x\n", wrapParm, This->stateBlock->textureDimensions[Stage]);
5147 glTexParameteri(This->stateBlock->textureDimensions[Stage], GL_TEXTURE_WRAP_R, wrapParm);
5148 checkGLcall("glTexParameteri(..., GL_TEXTURE_WRAP_R, wrapParm)");
5151 case WINED3DTSS_TEXCOORDINDEX :
5153 /* Values 0-7 are indexes into the FVF tex coords - See comments in DrawPrimitive */
5155 /* FIXME: From MSDN: The WINED3DTSS_TCI_* flags are mutually exclusive. If you include
5156 one flag, you can still specify an index value, which the system uses to
5157 determine the texture wrapping mode.
5158 eg. SetTextureStageState( 0, D3DTSS_TEXCOORDINDEX, D3DTSS_TCI_CAMERASPACEPOSITION | 1 );
5159 means use the vertex position (camera-space) as the input texture coordinates
5160 for this texture stage, and the wrap mode set in the WINED3DRS_WRAP1 render
5161 state. We do not (yet) support the D3DRENDERSTATE_WRAPx values, nor tie them up
5162 to the TEXCOORDINDEX value */
5165 * Be careful the value of the mask 0xF0000 come from d3d8types.h infos
5167 switch (Value & 0xFFFF0000) {
5168 case D3DTSS_TCI_PASSTHRU:
5169 /*Use the specified texture coordinates contained within the vertex format. This value resolves to zero.*/
5170 glDisable(GL_TEXTURE_GEN_S);
5171 glDisable(GL_TEXTURE_GEN_T);
5172 glDisable(GL_TEXTURE_GEN_R);
5173 glDisable(GL_TEXTURE_GEN_Q);
5174 checkGLcall("glDisable(GL_TEXTURE_GEN_S,T,R,Q)");
5177 case D3DTSS_TCI_CAMERASPACEPOSITION:
5178 /* CameraSpacePosition means use the vertex position, transformed to camera space,
5179 as the input texture coordinates for this stage's texture transformation. This
5180 equates roughly to EYE_LINEAR */
5182 float s_plane[] = { 1.0, 0.0, 0.0, 0.0 };
5183 float t_plane[] = { 0.0, 1.0, 0.0, 0.0 };
5184 float r_plane[] = { 0.0, 0.0, 1.0, 0.0 };
5185 float q_plane[] = { 0.0, 0.0, 0.0, 1.0 };
5186 TRACE("WINED3DTSS_TCI_CAMERASPACEPOSITION - Set eye plane\n");
5188 glMatrixMode(GL_MODELVIEW);
5191 glTexGenfv(GL_S, GL_EYE_PLANE, s_plane);
5192 glTexGenfv(GL_T, GL_EYE_PLANE, t_plane);
5193 glTexGenfv(GL_R, GL_EYE_PLANE, r_plane);
5194 glTexGenfv(GL_Q, GL_EYE_PLANE, q_plane);
5197 TRACE("WINED3DTSS_TCI_CAMERASPACEPOSITION - Set GL_TEXTURE_GEN_x and GL_x, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR\n");
5198 glEnable(GL_TEXTURE_GEN_S);
5199 checkGLcall("glEnable(GL_TEXTURE_GEN_S);");
5200 glTexGeni(GL_S, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR);
5201 checkGLcall("glTexGeni(GL_S, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR)");
5202 glEnable(GL_TEXTURE_GEN_T);
5203 checkGLcall("glEnable(GL_TEXTURE_GEN_T);");
5204 glTexGeni(GL_T, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR);
5205 checkGLcall("glTexGeni(GL_T, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR)");
5206 glEnable(GL_TEXTURE_GEN_R);
5207 checkGLcall("glEnable(GL_TEXTURE_GEN_R);");
5208 glTexGeni(GL_R, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR);
5209 checkGLcall("glTexGeni(GL_R, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR)");
5213 case D3DTSS_TCI_CAMERASPACENORMAL:
5215 if (GL_SUPPORT(NV_TEXGEN_REFLECTION)) {
5216 float s_plane[] = { 1.0, 0.0, 0.0, 0.0 };
5217 float t_plane[] = { 0.0, 1.0, 0.0, 0.0 };
5218 float r_plane[] = { 0.0, 0.0, 1.0, 0.0 };
5219 float q_plane[] = { 0.0, 0.0, 0.0, 1.0 };
5220 TRACE("WINED3DTSS_TCI_CAMERASPACENORMAL - Set eye plane\n");
5222 glMatrixMode(GL_MODELVIEW);
5225 glTexGenfv(GL_S, GL_EYE_PLANE, s_plane);
5226 glTexGenfv(GL_T, GL_EYE_PLANE, t_plane);
5227 glTexGenfv(GL_R, GL_EYE_PLANE, r_plane);
5228 glTexGenfv(GL_Q, GL_EYE_PLANE, q_plane);
5231 glEnable(GL_TEXTURE_GEN_S);
5232 checkGLcall("glEnable(GL_TEXTURE_GEN_S);");
5233 glTexGeni(GL_S, GL_TEXTURE_GEN_MODE, GL_NORMAL_MAP_NV);
5234 checkGLcall("glTexGeni(GL_S, GL_TEXTURE_GEN_MODE, GL_NORMAL_MAP_NV)");
5235 glEnable(GL_TEXTURE_GEN_T);
5236 checkGLcall("glEnable(GL_TEXTURE_GEN_T);");
5237 glTexGeni(GL_T, GL_TEXTURE_GEN_MODE, GL_NORMAL_MAP_NV);
5238 checkGLcall("glTexGeni(GL_T, GL_TEXTURE_GEN_MODE, GL_NORMAL_MAP_NV)");
5239 glEnable(GL_TEXTURE_GEN_R);
5240 checkGLcall("glEnable(GL_TEXTURE_GEN_R);");
5241 glTexGeni(GL_R, GL_TEXTURE_GEN_MODE, GL_NORMAL_MAP_NV);
5242 checkGLcall("glTexGeni(GL_R, GL_TEXTURE_GEN_MODE, GL_NORMAL_MAP_NV)");
5247 case D3DTSS_TCI_CAMERASPACEREFLECTIONVECTOR:
5249 if (GL_SUPPORT(NV_TEXGEN_REFLECTION)) {
5250 float s_plane[] = { 1.0, 0.0, 0.0, 0.0 };
5251 float t_plane[] = { 0.0, 1.0, 0.0, 0.0 };
5252 float r_plane[] = { 0.0, 0.0, 1.0, 0.0 };
5253 float q_plane[] = { 0.0, 0.0, 0.0, 1.0 };
5254 TRACE("WINED3DTSS_TCI_CAMERASPACEREFLECTIONVECTOR - Set eye plane\n");
5256 glMatrixMode(GL_MODELVIEW);
5259 glTexGenfv(GL_S, GL_EYE_PLANE, s_plane);
5260 glTexGenfv(GL_T, GL_EYE_PLANE, t_plane);
5261 glTexGenfv(GL_R, GL_EYE_PLANE, r_plane);
5262 glTexGenfv(GL_Q, GL_EYE_PLANE, q_plane);
5265 glEnable(GL_TEXTURE_GEN_S);
5266 checkGLcall("glEnable(GL_TEXTURE_GEN_S);");
5267 glTexGeni(GL_S, GL_TEXTURE_GEN_MODE, GL_REFLECTION_MAP_NV);
5268 checkGLcall("glTexGeni(GL_S, GL_TEXTURE_GEN_MODE, GL_REFLECTION_MAP_NV)");
5269 glEnable(GL_TEXTURE_GEN_T);
5270 checkGLcall("glEnable(GL_TEXTURE_GEN_T);");
5271 glTexGeni(GL_T, GL_TEXTURE_GEN_MODE, GL_REFLECTION_MAP_NV);
5272 checkGLcall("glTexGeni(GL_T, GL_TEXTURE_GEN_MODE, GL_REFLECTION_MAP_NV)");
5273 glEnable(GL_TEXTURE_GEN_R);
5274 checkGLcall("glEnable(GL_TEXTURE_GEN_R);");
5275 glTexGeni(GL_R, GL_TEXTURE_GEN_MODE, GL_REFLECTION_MAP_NV);
5276 checkGLcall("glTexGeni(GL_R, GL_TEXTURE_GEN_MODE, GL_REFLECTION_MAP_NV)");
5281 /* Unhandled types: */
5284 /* ? disable GL_TEXTURE_GEN_n ? */
5285 glDisable(GL_TEXTURE_GEN_S);
5286 glDisable(GL_TEXTURE_GEN_T);
5287 glDisable(GL_TEXTURE_GEN_R);
5288 glDisable(GL_TEXTURE_GEN_Q);
5289 FIXME("Unhandled WINED3DTSS_TEXCOORDINDEX %lx\n", Value);
5296 case WINED3DTSS_TEXTURETRANSFORMFLAGS :
5297 set_texture_matrix((float *)&This->stateBlock->transforms[D3DTS_TEXTURE0 + Stage].u.m[0][0], Value, (This->stateBlock->textureState[Stage][WINED3DTSS_TEXCOORDINDEX] & 0xFFFF0000) != D3DTSS_TCI_PASSTHRU);
5300 case WINED3DTSS_BUMPENVMAT00 :
5301 case WINED3DTSS_BUMPENVMAT01 :
5302 TRACE("BUMPENVMAT0%u Stage=%ld, Type=%d, Value =%ld\n", Type - WINED3DTSS_BUMPENVMAT00, Stage, Type, Value);
5304 case WINED3DTSS_BUMPENVMAT10 :
5305 case WINED3DTSS_BUMPENVMAT11 :
5306 TRACE("BUMPENVMAT1%u Stage=%ld, Type=%d, Value =%ld\n", Type - WINED3DTSS_BUMPENVMAT10, Stage, Type, Value);
5309 case WINED3DTSS_BUMPENVLSCALE :
5310 TRACE("BUMPENVLSCALE Stage=%ld, Type=%d, Value =%ld\n", Stage, Type, Value);
5313 case WINED3DTSS_BUMPENVLOFFSET :
5314 TRACE("BUMPENVLOFFSET Stage=%ld, Type=%d, Value =%ld\n", Stage, Type, Value);
5317 case WINED3DTSS_RESULTARG :
5318 TRACE("RESULTARG Still a stub, Stage=%ld, Type=%d, Value =%ld\n", Stage, Type, Value);
5322 /* Put back later: FIXME("(%p) : stub, Stage=%ld, Type=%d, Value =%ld\n", This, Stage, Type, Value); */
5323 TRACE("Still a stub, Stage=%ld, Type=%d, Value =%ld\n", Stage, Type, Value);
5332 * Get / Set Texture Stage States
5333 * TODO: Verify against dx9 definitions
5335 HRESULT WINAPI IWineD3DDeviceImpl_SetTextureStageState(IWineD3DDevice *iface, DWORD Stage, WINED3DTEXTURESTAGESTATETYPE Type, DWORD Value) {
5336 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5338 /* FIXME: Handle 3d textures? What if TSS value set before set texture? Need to reapply all values? */
5340 TRACE("(%p) : Stage=%ld, Type=%s(%d), Value=%ld\n", This, Stage, debug_d3dtexturestate(Type), Type, Value);
5342 /* Reject invalid texture units */
5343 if (Stage >= GL_LIMITS(textures)) {
5344 TRACE("Attempt to access invalid texture rejected\n");
5345 return WINED3DERR_INVALIDCALL;
5348 This->updateStateBlock->changed.textureState[Stage][Type] = TRUE;
5349 This->updateStateBlock->set.textureState[Stage][Type] = TRUE;
5350 This->updateStateBlock->textureState[Stage][Type] = Value;
5355 HRESULT WINAPI IWineD3DDeviceImpl_GetTextureStageState(IWineD3DDevice *iface, DWORD Stage, WINED3DTEXTURESTAGESTATETYPE Type, DWORD* pValue) {
5356 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5357 TRACE("(%p) : requesting Stage %ld, Type %d getting %ld\n", This, Stage, Type, This->updateStateBlock->textureState[Stage][Type]);
5358 *pValue = This->updateStateBlock->textureState[Stage][Type];
5365 HRESULT WINAPI IWineD3DDeviceImpl_SetTexture(IWineD3DDevice *iface, DWORD Stage, IWineD3DBaseTexture* pTexture) {
5367 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5368 IWineD3DBaseTexture *oldTexture;
5370 oldTexture = This->updateStateBlock->textures[Stage];
5371 TRACE("(%p) : Stage(%ld), Texture (%p)\n", This, Stage, pTexture);
5373 #if 0 /* TODO: check so vertex textures */
5374 if (Stage >= D3DVERTEXTEXTURESAMPLER && Stage <= D3DVERTEXTEXTURESAMPLER3){
5375 This->updateStateBlock->vertexTextures[Stage - D3DVERTEXTEXTURESAMPLER] = pTexture;
5380 /* Reject invalid texture units */
5381 if (Stage >= GL_LIMITS(textures) || Stage < 0) {
5382 WARN("Attempt to access invalid texture rejected\n");
5383 return WINED3DERR_INVALIDCALL;
5386 if(pTexture != NULL) {
5387 /* SetTexture isn't allowed on textures in WINED3DPOOL_SCRATCH;
5389 if(((IWineD3DTextureImpl*)pTexture)->resource.pool == WINED3DPOOL_SCRATCH) {
5390 WARN("(%p) Attempt to set scratch texture rejected\n", pTexture);
5391 return WINED3DERR_INVALIDCALL;
5395 oldTexture = This->updateStateBlock->textures[Stage];
5396 TRACE("GL_LIMITS %d\n",GL_LIMITS(textures));
5397 TRACE("(%p) : oldtexture(%p)\n", This,oldTexture);
5399 This->updateStateBlock->set.textures[Stage] = TRUE;
5400 This->updateStateBlock->changed.textures[Stage] = TRUE;
5401 TRACE("(%p) : setting new texture to %p\n", This, pTexture);
5402 This->updateStateBlock->textures[Stage] = pTexture;
5404 /* Handle recording of state blocks */
5405 if (This->isRecordingState) {
5406 TRACE("Recording... not performing anything\n");
5410 /** NOTE: MSDN says that setTexture increases the reference count,
5411 * and the the application nust set the texture back to null (or have a leaky application),
5412 * This means we should pass the refcount up to the parent
5413 *******************************/
5414 if (NULL != This->updateStateBlock->textures[Stage]) {
5415 IWineD3DBaseTexture_AddRef(This->updateStateBlock->textures[Stage]);
5418 if (NULL != oldTexture) {
5419 IWineD3DBaseTexture_Release(oldTexture);
5422 /* Reset color keying */
5423 if(Stage == 0 && This->stateBlock->renderState[WINED3DRS_COLORKEYENABLE]) {
5424 BOOL enable_ckey = FALSE;
5427 IWineD3DSurfaceImpl *surf = (IWineD3DSurfaceImpl *) ((IWineD3DTextureImpl *)pTexture)->surfaces[0];
5428 if(surf->CKeyFlags & DDSD_CKSRCBLT) enable_ckey = TRUE;
5432 glAlphaFunc(GL_NOTEQUAL, 0.0);
5433 checkGLcall("glAlphaFunc");
5440 HRESULT WINAPI IWineD3DDeviceImpl_GetTexture(IWineD3DDevice *iface, DWORD Stage, IWineD3DBaseTexture** ppTexture) {
5441 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5442 TRACE("(%p) : (%ld /* Stage */,%p /* ppTexture */)\n", This, Stage, ppTexture);
5444 /* Reject invalid texture units */
5445 if (Stage >= GL_LIMITS(textures)) {
5446 TRACE("Attempt to access invalid texture rejected\n");
5447 return WINED3DERR_INVALIDCALL;
5449 *ppTexture=This->updateStateBlock->textures[Stage];
5451 IWineD3DBaseTexture_AddRef(*ppTexture);
5453 return WINED3DERR_INVALIDCALL;
5460 HRESULT WINAPI IWineD3DDeviceImpl_GetBackBuffer(IWineD3DDevice *iface, UINT iSwapChain, UINT BackBuffer, WINED3DBACKBUFFER_TYPE Type,
5461 IWineD3DSurface **ppBackBuffer) {
5462 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5463 IWineD3DSwapChain *swapChain;
5466 TRACE("(%p) : BackBuf %d Type %d SwapChain %d returning %p\n", This, BackBuffer, Type, iSwapChain, *ppBackBuffer);
5468 hr = IWineD3DDeviceImpl_GetSwapChain(iface, iSwapChain, &swapChain);
5469 if (hr == WINED3D_OK) {
5470 hr = IWineD3DSwapChain_GetBackBuffer(swapChain, BackBuffer, Type, ppBackBuffer);
5471 IWineD3DSwapChain_Release(swapChain);
5473 *ppBackBuffer = NULL;
5478 HRESULT WINAPI IWineD3DDeviceImpl_GetDeviceCaps(IWineD3DDevice *iface, WINED3DCAPS* pCaps) {
5479 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5480 WARN("(%p) : stub, calling idirect3d for now\n", This);
5481 return IWineD3D_GetDeviceCaps(This->wineD3D, This->adapterNo, This->devType, pCaps);
5484 HRESULT WINAPI IWineD3DDeviceImpl_GetDisplayMode(IWineD3DDevice *iface, UINT iSwapChain, WINED3DDISPLAYMODE* pMode) {
5485 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5486 IWineD3DSwapChain *swapChain;
5489 if(iSwapChain > 0) {
5490 hr = IWineD3DDeviceImpl_GetSwapChain(iface, iSwapChain, (IWineD3DSwapChain **)&swapChain);
5491 if (hr == WINED3D_OK) {
5492 hr = IWineD3DSwapChain_GetDisplayMode(swapChain, pMode);
5493 IWineD3DSwapChain_Release(swapChain);
5495 FIXME("(%p) Error getting display mode\n", This);
5498 /* Don't read the real display mode,
5499 but return the stored mode instead. X11 can't change the color
5500 depth, and some apps are pretty angry if they SetDisplayMode from
5501 24 to 16 bpp and find out that GetDisplayMode still returns 24 bpp
5503 Also don't relay to the swapchain because with ddraw it's possible
5504 that there isn't a swapchain at all */
5505 pMode->Width = This->ddraw_width;
5506 pMode->Height = This->ddraw_height;
5507 pMode->Format = This->ddraw_format;
5508 pMode->RefreshRate = 0;
5515 HRESULT WINAPI IWineD3DDeviceImpl_SetHWND(IWineD3DDevice *iface, HWND hWnd) {
5516 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5517 TRACE("(%p)->(%p)\n", This, hWnd);
5519 This->ddraw_window = hWnd;
5523 HRESULT WINAPI IWineD3DDeviceImpl_GetHWND(IWineD3DDevice *iface, HWND *hWnd) {
5524 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5525 TRACE("(%p)->(%p)\n", This, hWnd);
5527 *hWnd = This->ddraw_window;
5532 * Stateblock related functions
5535 HRESULT WINAPI IWineD3DDeviceImpl_BeginStateBlock(IWineD3DDevice *iface) {
5536 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5537 IWineD3DStateBlockImpl *object;
5538 TRACE("(%p)", This);
5540 if (This->isRecordingState) {
5541 return WINED3DERR_INVALIDCALL;
5544 object = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(IWineD3DStateBlockImpl));
5545 if (NULL == object ) {
5546 FIXME("(%p)Error allocating memory for stateblock\n", This);
5547 return E_OUTOFMEMORY;
5549 TRACE("(%p) creted object %p\n", This, object);
5550 object->wineD3DDevice= This;
5551 /** FIXME: object->parent = parent; **/
5552 object->parent = NULL;
5553 object->blockType = WINED3DSBT_ALL;
5555 object->lpVtbl = &IWineD3DStateBlock_Vtbl;
5557 IWineD3DStateBlock_Release((IWineD3DStateBlock*)This->updateStateBlock);
5558 This->updateStateBlock = object;
5559 This->isRecordingState = TRUE;
5561 TRACE("(%p) recording stateblock %p\n",This , object);
5565 HRESULT WINAPI IWineD3DDeviceImpl_EndStateBlock(IWineD3DDevice *iface, IWineD3DStateBlock** ppStateBlock) {
5566 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5568 if (!This->isRecordingState) {
5569 FIXME("(%p) not recording! returning error\n", This);
5570 *ppStateBlock = NULL;
5571 return WINED3DERR_INVALIDCALL;
5574 *ppStateBlock = (IWineD3DStateBlock*)This->updateStateBlock;
5575 This->isRecordingState = FALSE;
5576 This->updateStateBlock = This->stateBlock;
5577 IWineD3DStateBlock_AddRef((IWineD3DStateBlock*)This->updateStateBlock);
5578 /* IWineD3DStateBlock_AddRef(*ppStateBlock); don't need to do this, since we should really just release UpdateStateBlock first */
5579 TRACE("(%p) returning token (ptr to stateblock) of %p\n", This, *ppStateBlock);
5584 * Scene related functions
5586 HRESULT WINAPI IWineD3DDeviceImpl_BeginScene(IWineD3DDevice *iface) {
5587 /* At the moment we have no need for any functionality at the beginning
5589 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5590 TRACE("(%p) : stub\n", This);
5594 HRESULT WINAPI IWineD3DDeviceImpl_EndScene(IWineD3DDevice *iface) {
5595 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5596 TRACE("(%p)\n", This);
5598 /* We only have to do this if we need to read the, swapbuffers performs a flush for us */
5600 checkGLcall("glFlush");
5602 TRACE("End Scene\n");
5603 if(This->renderTarget != NULL) {
5605 /* If the container of the rendertarget is a texture then we need to save the data from the pbuffer */
5606 IUnknown *targetContainer = NULL;
5607 if (WINED3D_OK == IWineD3DSurface_GetContainer(This->renderTarget, &IID_IWineD3DBaseTexture, (void **)&targetContainer)
5608 || WINED3D_OK == IWineD3DSurface_GetContainer(This->renderTarget, &IID_IWineD3DDevice, (void **)&targetContainer)) {
5609 TRACE("(%p) : Texture rendertarget %p\n", This ,This->renderTarget);
5610 /** always dirtify for now. we must find a better way to see that surface have been modified
5611 (Modifications should will only occur via draw-primitive, but we do need better locking
5612 switching to render-to-texture should remove the overhead though.
5614 IWineD3DSurface_SetPBufferState(This->renderTarget, TRUE /* inPBuffer */, FALSE /* inTexture */);
5615 IWineD3DSurface_AddDirtyRect(This->renderTarget, NULL);
5616 IWineD3DSurface_PreLoad(This->renderTarget);
5617 IWineD3DSurface_SetPBufferState(This->renderTarget, FALSE /* inPBuffer */, FALSE /* inTexture */);
5618 IUnknown_Release(targetContainer);
5621 This->sceneEnded = TRUE;
5626 HRESULT WINAPI IWineD3DDeviceImpl_Present(IWineD3DDevice *iface,
5627 CONST RECT* pSourceRect, CONST RECT* pDestRect,
5628 HWND hDestWindowOverride, CONST RGNDATA* pDirtyRegion) {
5629 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5630 IWineD3DSwapChain *swapChain = NULL;
5632 int swapchains = IWineD3DDeviceImpl_GetNumberOfSwapChains(iface);
5634 TRACE("(%p) Presenting the frame\n", This);
5636 for(i = 0 ; i < swapchains ; i ++) {
5638 IWineD3DDeviceImpl_GetSwapChain(iface, i , (IWineD3DSwapChain **)&swapChain);
5639 TRACE("presentinng chain %d, %p\n", i, swapChain);
5640 IWineD3DSwapChain_Present(swapChain, pSourceRect, pDestRect, hDestWindowOverride, pDirtyRegion, 0);
5641 IWineD3DSwapChain_Release(swapChain);
5647 HRESULT WINAPI IWineD3DDeviceImpl_Clear(IWineD3DDevice *iface, DWORD Count, CONST D3DRECT* pRects,
5648 DWORD Flags, D3DCOLOR Color, float Z, DWORD Stencil) {
5649 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5651 /* TODO: From MSDN This method fails if you specify the D3DCLEAR_ZBUFFER or D3DCLEAR_STENCIL flags when the
5652 render target does not have an attached depth buffer. Similarly, if you specify the D3DCLEAR_STENCIL flag
5653 when the depth-buffer format does not contain stencil buffer information, this method fails. */
5654 GLbitfield glMask = 0;
5655 GLboolean old_ztest;
5656 GLfloat old_z_clear_value;
5657 GLint old_stencil_clear_value;
5658 GLfloat old_color_clear_value[4];
5660 CONST D3DRECT* curRect;
5662 TRACE("(%p) Count (%ld), pRects (%p), Flags (%lx), Z (%f), Stencil (%ld)\n", This,
5663 Count, pRects, Flags, Z, Stencil);
5667 glEnable(GL_SCISSOR_TEST);
5668 checkGLcall("glEnable GL_SCISSOR_TEST");
5670 if (Count > 0 && pRects) {
5676 /* Only set the values up once, as they are not changing */
5677 if (Flags & D3DCLEAR_STENCIL) {
5678 glGetIntegerv(GL_STENCIL_CLEAR_VALUE, &old_stencil_clear_value);
5679 glClearStencil(Stencil);
5680 checkGLcall("glClearStencil");
5681 glMask = glMask | GL_STENCIL_BUFFER_BIT;
5682 glStencilMask(0xFFFFFFFF);
5685 if (Flags & D3DCLEAR_ZBUFFER) {
5686 glGetBooleanv(GL_DEPTH_WRITEMASK, &old_ztest);
5687 glDepthMask(GL_TRUE);
5688 glGetFloatv(GL_DEPTH_CLEAR_VALUE, &old_z_clear_value);
5690 checkGLcall("glClearDepth");
5691 glMask = glMask | GL_DEPTH_BUFFER_BIT;
5694 if (Flags & D3DCLEAR_TARGET) {
5695 TRACE("Clearing screen with glClear to color %lx\n", Color);
5696 glGetFloatv(GL_COLOR_CLEAR_VALUE, old_color_clear_value);
5697 glClearColor(D3DCOLOR_R(Color),
5701 checkGLcall("glClearColor");
5703 /* Clear ALL colors! */
5704 glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
5705 glMask = glMask | GL_COLOR_BUFFER_BIT;
5708 /* Now process each rect in turn */
5709 for (i = 0; i < Count || i == 0; i++) {
5712 /* Note gl uses lower left, width/height */
5713 TRACE("(%p) %p Rect=(%ld,%ld)->(%ld,%ld) glRect=(%ld,%ld), len=%ld, hei=%ld\n", This, curRect,
5714 curRect->x1, curRect->y1, curRect->x2, curRect->y2,
5715 curRect->x1, (((IWineD3DSurfaceImpl *)This->renderTarget)->currentDesc.Height - curRect->y2),
5716 curRect->x2 - curRect->x1, curRect->y2 - curRect->y1);
5717 glScissor(curRect->x1, (((IWineD3DSurfaceImpl *)This->renderTarget)->currentDesc.Height - curRect->y2),
5718 curRect->x2 - curRect->x1, curRect->y2 - curRect->y1);
5719 checkGLcall("glScissor");
5721 glScissor(This->stateBlock->viewport.X,
5722 (((IWineD3DSurfaceImpl *)This->renderTarget)->currentDesc.Height -
5723 (This->stateBlock->viewport.Y + This->stateBlock->viewport.Height)),
5724 This->stateBlock->viewport.Width,
5725 This->stateBlock->viewport.Height);
5726 checkGLcall("glScissor");
5729 /* Clear the selected rectangle (or full screen) */
5731 checkGLcall("glClear");
5733 /* Step to the next rectangle */
5734 if (curRect) curRect = curRect + sizeof(D3DRECT);
5737 /* Restore the old values (why..?) */
5738 if (Flags & D3DCLEAR_STENCIL) {
5739 glClearStencil(old_stencil_clear_value);
5740 glStencilMask(This->stateBlock->renderState[WINED3DRS_STENCILWRITEMASK]);
5742 if (Flags & D3DCLEAR_ZBUFFER) {
5743 glDepthMask(old_ztest);
5744 glClearDepth(old_z_clear_value);
5746 if (Flags & D3DCLEAR_TARGET) {
5747 glClearColor(old_color_clear_value[0],
5748 old_color_clear_value[1],
5749 old_color_clear_value[2],
5750 old_color_clear_value[3]);
5751 glColorMask(This->stateBlock->renderState[WINED3DRS_COLORWRITEENABLE] & D3DCOLORWRITEENABLE_RED ? GL_TRUE : GL_FALSE,
5752 This->stateBlock->renderState[WINED3DRS_COLORWRITEENABLE] & D3DCOLORWRITEENABLE_GREEN ? GL_TRUE : GL_FALSE,
5753 This->stateBlock->renderState[WINED3DRS_COLORWRITEENABLE] & D3DCOLORWRITEENABLE_BLUE ? GL_TRUE : GL_FALSE,
5754 This->stateBlock->renderState[WINED3DRS_COLORWRITEENABLE] & D3DCOLORWRITEENABLE_ALPHA ? GL_TRUE : GL_FALSE);
5757 glDisable(GL_SCISSOR_TEST);
5758 checkGLcall("glDisable");
5767 HRESULT WINAPI IWineD3DDeviceImpl_DrawPrimitive(IWineD3DDevice *iface, D3DPRIMITIVETYPE PrimitiveType, UINT StartVertex,
5768 UINT PrimitiveCount) {
5770 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5771 This->stateBlock->streamIsUP = FALSE;
5773 TRACE("(%p) : Type=(%d,%s), Start=%d, Count=%d\n", This, PrimitiveType,
5774 debug_d3dprimitivetype(PrimitiveType),
5775 StartVertex, PrimitiveCount);
5776 drawPrimitive(iface, PrimitiveType, PrimitiveCount, StartVertex, 0/* NumVertices */, -1 /* indxStart */,
5777 0 /* indxSize */, NULL /* indxData */, 0 /* minIndex */, NULL);
5783 /* TODO: baseVIndex needs to be provided from This->stateBlock->baseVertexIndex when called from d3d8 */
5784 HRESULT WINAPI IWineD3DDeviceImpl_DrawIndexedPrimitive(IWineD3DDevice *iface,
5785 D3DPRIMITIVETYPE PrimitiveType,
5786 INT baseVIndex, UINT minIndex,
5787 UINT NumVertices, UINT startIndex, UINT primCount) {
5789 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5791 IWineD3DIndexBuffer *pIB;
5792 WINED3DINDEXBUFFER_DESC IdxBufDsc;
5794 pIB = This->stateBlock->pIndexData;
5795 This->stateBlock->streamIsUP = FALSE;
5797 TRACE("(%p) : Type=(%d,%s), min=%d, CountV=%d, startIdx=%d, baseVidx=%d, countP=%d\n", This,
5798 PrimitiveType, debug_d3dprimitivetype(PrimitiveType),
5799 minIndex, NumVertices, startIndex, baseVIndex, primCount);
5801 IWineD3DIndexBuffer_GetDesc(pIB, &IdxBufDsc);
5802 if (IdxBufDsc.Format == WINED3DFMT_INDEX16) {
5808 drawPrimitive(iface, PrimitiveType, primCount, baseVIndex, NumVertices, startIndex,
5809 idxStride, ((IWineD3DIndexBufferImpl *) pIB)->resource.allocatedMemory, minIndex, NULL);
5814 HRESULT WINAPI IWineD3DDeviceImpl_DrawPrimitiveUP(IWineD3DDevice *iface, D3DPRIMITIVETYPE PrimitiveType,
5815 UINT PrimitiveCount, CONST void* pVertexStreamZeroData,
5816 UINT VertexStreamZeroStride) {
5817 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5819 TRACE("(%p) : Type=(%d,%s), pCount=%d, pVtxData=%p, Stride=%d\n", This, PrimitiveType,
5820 debug_d3dprimitivetype(PrimitiveType),
5821 PrimitiveCount, pVertexStreamZeroData, VertexStreamZeroStride);
5823 /* release the stream source */
5824 if (This->stateBlock->streamSource[0] != NULL) {
5825 IWineD3DVertexBuffer_Release(This->stateBlock->streamSource[0]);
5828 /* Note in the following, it's not this type, but that's the purpose of streamIsUP */
5829 This->stateBlock->streamSource[0] = (IWineD3DVertexBuffer *)pVertexStreamZeroData;
5830 This->stateBlock->streamStride[0] = VertexStreamZeroStride;
5831 This->stateBlock->streamIsUP = TRUE;
5833 drawPrimitive(iface, PrimitiveType, PrimitiveCount, 0 /* start vertex */, 0 /* NumVertices */,
5834 0 /* indxStart*/, 0 /* indxSize*/, NULL /* indxData */, 0 /* indxMin */, NULL);
5836 /* MSDN specifies stream zero settings must be set to NULL */
5837 This->stateBlock->streamStride[0] = 0;
5838 This->stateBlock->streamSource[0] = NULL;
5840 /*stream zero settings set to null at end, as per the msdn */
5844 HRESULT WINAPI IWineD3DDeviceImpl_DrawIndexedPrimitiveUP(IWineD3DDevice *iface, D3DPRIMITIVETYPE PrimitiveType,
5845 UINT MinVertexIndex, UINT NumVertices,
5846 UINT PrimitiveCount, CONST void* pIndexData,
5847 WINED3DFORMAT IndexDataFormat,CONST void* pVertexStreamZeroData,
5848 UINT VertexStreamZeroStride) {
5850 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5852 TRACE("(%p) : Type=(%d,%s), MinVtxIdx=%d, NumVIdx=%d, PCount=%d, pidxdata=%p, IdxFmt=%d, pVtxdata=%p, stride=%d\n",
5853 This, PrimitiveType, debug_d3dprimitivetype(PrimitiveType),
5854 MinVertexIndex, NumVertices, PrimitiveCount, pIndexData,
5855 IndexDataFormat, pVertexStreamZeroData, VertexStreamZeroStride);
5857 if (IndexDataFormat == WINED3DFMT_INDEX16) {
5863 /* release the stream and index data */
5864 if (This->stateBlock->streamSource[0] != NULL) {
5865 IWineD3DVertexBuffer_Release(This->stateBlock->streamSource[0]);
5867 if (This->stateBlock->pIndexData) {
5868 IWineD3DIndexBuffer_Release(This->stateBlock->pIndexData);
5871 /* Note in the following, it's not this type, but that's the purpose of streamIsUP */
5872 This->stateBlock->streamSource[0] = (IWineD3DVertexBuffer *)pVertexStreamZeroData;
5873 This->stateBlock->streamIsUP = TRUE;
5874 This->stateBlock->streamStride[0] = VertexStreamZeroStride;
5876 drawPrimitive(iface, PrimitiveType, PrimitiveCount, 0 /* vertexStart */, NumVertices, 0 /* indxStart */, idxStride, pIndexData, MinVertexIndex, NULL);
5878 /* MSDN specifies stream zero settings and index buffer must be set to NULL */
5879 This->stateBlock->streamSource[0] = NULL;
5880 This->stateBlock->streamStride[0] = 0;
5881 This->stateBlock->pIndexData = NULL;
5886 HRESULT WINAPI IWineD3DDeviceImpl_DrawPrimitiveStrided (IWineD3DDevice *iface, D3DPRIMITIVETYPE PrimitiveType, UINT PrimitiveCount, WineDirect3DVertexStridedData *DrawPrimStrideData) {
5888 drawPrimitive(iface, PrimitiveType, PrimitiveCount, 0, 0, 0, 0, NULL, 0, DrawPrimStrideData);
5891 /* Yet another way to update a texture, some apps use this to load default textures instead of using surface/texture lock/unlock */
5892 HRESULT WINAPI IWineD3DDeviceImpl_UpdateTexture (IWineD3DDevice *iface, IWineD3DBaseTexture *pSourceTexture, IWineD3DBaseTexture *pDestinationTexture){
5893 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5894 HRESULT hr = WINED3D_OK;
5895 WINED3DRESOURCETYPE sourceType;
5896 WINED3DRESOURCETYPE destinationType;
5899 /* TODO: think about moving the code into IWineD3DBaseTexture */
5901 TRACE("(%p) Source %p Destination %p\n", This, pSourceTexture, pDestinationTexture);
5903 /* verify that the source and destination textures aren't NULL */
5904 if (NULL == pSourceTexture || NULL == pDestinationTexture) {
5905 WARN("(%p) : source (%p) and destination (%p) textures must not be NULL, returning WINED3DERR_INVALIDCALL\n",
5906 This, pSourceTexture, pDestinationTexture);
5907 hr = WINED3DERR_INVALIDCALL;
5910 if (pSourceTexture == pDestinationTexture) {
5911 WARN("(%p) : source (%p) and destination (%p) textures must be different, returning WINED3DERR_INVALIDCALL\n",
5912 This, pSourceTexture, pDestinationTexture);
5913 hr = WINED3DERR_INVALIDCALL;
5915 /* Verify that the source and destination textures are the same type */
5916 sourceType = IWineD3DBaseTexture_GetType(pSourceTexture);
5917 destinationType = IWineD3DBaseTexture_GetType(pDestinationTexture);
5919 if (sourceType != destinationType) {
5920 WARN("(%p) Sorce and destination types must match, returning WINED3DERR_INVALIDCALL\n",
5922 hr = WINED3DERR_INVALIDCALL;
5925 /* check that both textures have the identical numbers of levels */
5926 if (IWineD3DBaseTexture_GetLevelCount(pDestinationTexture) != IWineD3DBaseTexture_GetLevelCount(pSourceTexture)) {
5927 WARN("(%p) : source (%p) and destination (%p) textures must have identicle numbers of levels, returning WINED3DERR_INVALIDCALL\n", This, pSourceTexture, pDestinationTexture);
5928 hr = WINED3DERR_INVALIDCALL;
5931 if (WINED3D_OK == hr) {
5933 /* Make sure that the destination texture is loaded */
5934 IWineD3DBaseTexture_PreLoad(pDestinationTexture);
5936 /* Update every surface level of the texture */
5937 levels = IWineD3DBaseTexture_GetLevelCount(pDestinationTexture);
5939 switch (sourceType) {
5940 case WINED3DRTYPE_TEXTURE:
5942 IWineD3DSurface *srcSurface;
5943 IWineD3DSurface *destSurface;
5945 for (i = 0 ; i < levels ; ++i) {
5946 IWineD3DTexture_GetSurfaceLevel((IWineD3DTexture *)pSourceTexture, i, &srcSurface);
5947 IWineD3DTexture_GetSurfaceLevel((IWineD3DTexture *)pDestinationTexture, i, &destSurface);
5948 hr = IWineD3DDevice_UpdateSurface(iface, srcSurface, NULL, destSurface, NULL);
5949 IWineD3DSurface_Release(srcSurface);
5950 IWineD3DSurface_Release(destSurface);
5951 if (WINED3D_OK != hr) {
5952 WARN("(%p) : Call to update surface failed\n", This);
5958 case WINED3DRTYPE_CUBETEXTURE:
5960 IWineD3DSurface *srcSurface;
5961 IWineD3DSurface *destSurface;
5962 WINED3DCUBEMAP_FACES faceType;
5964 for (i = 0 ; i < levels ; ++i) {
5965 /* Update each cube face */
5966 for (faceType = D3DCUBEMAP_FACE_POSITIVE_X; faceType <= D3DCUBEMAP_FACE_NEGATIVE_Z; ++faceType){
5967 hr = IWineD3DCubeTexture_GetCubeMapSurface((IWineD3DCubeTexture *)pSourceTexture, faceType, i, &srcSurface);
5968 if (WINED3D_OK != hr) {
5969 FIXME("(%p) : Failed to get src cube surface facetype %d, level %d\n", This, faceType, i);
5971 TRACE("Got srcSurface %p\n", srcSurface);
5973 hr = IWineD3DCubeTexture_GetCubeMapSurface((IWineD3DCubeTexture *)pDestinationTexture, faceType, i, &destSurface);
5974 if (WINED3D_OK != hr) {
5975 FIXME("(%p) : Failed to get src cube surface facetype %d, level %d\n", This, faceType, i);
5977 TRACE("Got desrSurface %p\n", destSurface);
5979 hr = IWineD3DDevice_UpdateSurface(iface, srcSurface, NULL, destSurface, NULL);
5980 IWineD3DSurface_Release(srcSurface);
5981 IWineD3DSurface_Release(destSurface);
5982 if (WINED3D_OK != hr) {
5983 WARN("(%p) : Call to update surface failed\n", This);
5990 #if 0 /* TODO: Add support for volume textures */
5991 case WINED3DRTYPE_VOLUMETEXTURE:
5993 IWineD3DVolume srcVolume = NULL;
5994 IWineD3DSurface destVolume = NULL;
5996 for (i = 0 ; i < levels ; ++i) {
5997 IWineD3DVolumeTexture_GetVolume((IWineD3DVolumeTexture *)pSourceTexture, i, &srcVolume);
5998 IWineD3DVolumeTexture_GetVolume((IWineD3DVolumeTexture *)pDestinationTexture, i, &destVolume);
5999 hr = IWineD3DFoo_UpdateVolume(iface, srcVolume, NULL, destVolume, NULL);
6000 IWineD3DVolume_Release(srcSurface);
6001 IWineD3DVolume_Release(destSurface);
6002 if (WINED3D_OK != hr) {
6003 WARN("(%p) : Call to update volume failed\n", This);
6011 FIXME("(%p) : Unsupported source and destination type\n", This);
6012 hr = WINED3DERR_INVALIDCALL;
6019 HRESULT WINAPI IWineD3DDeviceImpl_StretchRect(IWineD3DDevice *iface, IWineD3DSurface *pSourceSurface,
6020 CONST RECT* pSourceRect, IWineD3DSurface *pDestinationSurface,
6021 CONST RECT* pDestRect, WINED3DTEXTUREFILTERTYPE Filter) {
6022 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
6024 TRACE("(%p) : stub\n", This);
6027 HRESULT WINAPI IWineD3DDeviceImpl_GetRenderTargetData(IWineD3DDevice *iface, IWineD3DSurface *pRenderTarget, IWineD3DSurface *pSurface) {
6028 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
6029 /** TODO: remove remove casts to IWineD3DSurfaceImpl *
6030 * NOTE It may be best to move the code into surface to occomplish this
6031 ****************************************/
6033 WINED3DSURFACE_DESC surfaceDesc;
6034 unsigned int surfaceWidth, surfaceHeight;
6035 glDescriptor *targetGlDescription = NULL;
6036 glDescriptor *surfaceGlDescription = NULL;
6037 IWineD3DSwapChainImpl *container = NULL;
6039 IWineD3DSurface_GetGlDesc(pRenderTarget, &targetGlDescription);
6040 IWineD3DSurface_GetGlDesc(pSurface, &surfaceGlDescription);
6041 memset(&surfaceDesc, 0, sizeof(surfaceDesc));
6043 surfaceDesc.Width = &surfaceWidth;
6044 surfaceDesc.Height = &surfaceHeight;
6045 IWineD3DSurface_GetDesc(pSurface, &surfaceDesc);
6046 /* check to see if it's the backbuffer or the frontbuffer being requested (to make sure the data is up to date)*/
6048 /* Ok, I may need to setup some kind of active swapchain reference on the device */
6049 IWineD3DSurface_GetContainer(pRenderTarget, &IID_IWineD3DSwapChain, (void **)&container);
6051 /* TODO: opengl Context switching for swapchains etc... */
6052 if (NULL != container || pRenderTarget == This->renderTarget || pRenderTarget == This->depthStencilBuffer) {
6053 if (NULL != container && (pRenderTarget == container->backBuffer)) {
6054 glReadBuffer(GL_BACK);
6055 vcheckGLcall("glReadBuffer(GL_BACK)");
6056 } else if ((NULL != container && (pRenderTarget == container->frontBuffer)) || (pRenderTarget == This->renderTarget)) {
6057 glReadBuffer(GL_FRONT);
6058 vcheckGLcall("glReadBuffer(GL_FRONT)");
6059 } else if (pRenderTarget == This->depthStencilBuffer) {
6060 FIXME("Reading of depthstencil not yet supported\n");
6063 glReadPixels(surfaceGlDescription->target,
6064 surfaceGlDescription->level,
6067 surfaceGlDescription->glFormat,
6068 surfaceGlDescription->glType,
6069 (void *)IWineD3DSurface_GetData(pSurface));
6070 vcheckGLcall("glReadPixels(...)");
6071 if(NULL != container ){
6072 IWineD3DSwapChain_Release((IWineD3DSwapChain*) container);
6075 IWineD3DBaseTexture *container;
6076 GLenum textureDimensions = GL_TEXTURE_2D;
6078 if (WINED3D_OK == IWineD3DSurface_GetContainer(pSurface, &IID_IWineD3DBaseTexture, (void **)&container)) {
6079 textureDimensions = IWineD3DBaseTexture_GetTextureDimensions(container);
6080 IWineD3DBaseTexture_Release(container);
6082 /* TODO: 2D -> Cube surface coppies etc.. */
6083 if (surfaceGlDescription->target != textureDimensions) {
6084 FIXME("(%p) : Texture dimension mismatch\n", This);
6086 glEnable(textureDimensions);
6087 vcheckGLcall("glEnable(GL_TEXTURE_...)");
6088 /* FIXME: this isn't correct, it need to add a dirty rect if nothing else... */
6089 glBindTexture(targetGlDescription->target, targetGlDescription->textureName);
6090 vcheckGLcall("glBindTexture");
6091 glGetTexImage(surfaceGlDescription->target,
6092 surfaceGlDescription->level,
6093 surfaceGlDescription->glFormat,
6094 surfaceGlDescription->glType,
6095 (void *)IWineD3DSurface_GetData(pSurface));
6096 glDisable(textureDimensions);
6097 vcheckGLcall("glDisable(GL_TEXTURE_...)");
6104 HRESULT WINAPI IWineD3DDeviceImpl_GetFrontBufferData(IWineD3DDevice *iface,UINT iSwapChain, IWineD3DSurface *pDestSurface) {
6105 IWineD3DSwapChain *swapChain;
6107 hr = IWineD3DDeviceImpl_GetSwapChain(iface, iSwapChain, (IWineD3DSwapChain **)&swapChain);
6108 if(hr == WINED3D_OK) {
6109 hr = IWineD3DSwapChain_GetFrontBufferData(swapChain, pDestSurface);
6110 IWineD3DSwapChain_Release(swapChain);
6115 HRESULT WINAPI IWineD3DDeviceImpl_ValidateDevice(IWineD3DDevice *iface, DWORD* pNumPasses) {
6116 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
6117 /* return a sensible default */
6119 /* TODO: If the window is minimized then validate device should return something other than WINED3D_OK */
6120 FIXME("(%p) : stub\n", This);
6124 HRESULT WINAPI IWineD3DDeviceImpl_SetPaletteEntries(IWineD3DDevice *iface, UINT PaletteNumber, CONST PALETTEENTRY* pEntries) {
6125 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
6127 TRACE("(%p) : PaletteNumber %u\n", This, PaletteNumber);
6128 if ( PaletteNumber < 0 || PaletteNumber >= MAX_PALETTES) {
6129 WARN("(%p) : (%u) Out of range 0-%u, returning Invalid Call\n", This, PaletteNumber, MAX_PALETTES);
6130 return WINED3DERR_INVALIDCALL;
6132 for (j = 0; j < 256; ++j) {
6133 This->palettes[PaletteNumber][j].peRed = pEntries[j].peRed;
6134 This->palettes[PaletteNumber][j].peGreen = pEntries[j].peGreen;
6135 This->palettes[PaletteNumber][j].peBlue = pEntries[j].peBlue;
6136 This->palettes[PaletteNumber][j].peFlags = pEntries[j].peFlags;
6138 TRACE("(%p) : returning\n", This);
6142 HRESULT WINAPI IWineD3DDeviceImpl_GetPaletteEntries(IWineD3DDevice *iface, UINT PaletteNumber, PALETTEENTRY* pEntries) {
6143 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
6145 TRACE("(%p) : PaletteNumber %u\n", This, PaletteNumber);
6146 if ( PaletteNumber < 0 || PaletteNumber >= MAX_PALETTES) {
6147 WARN("(%p) : (%u) Out of range 0-%u, returning Invalid Call\n", This, PaletteNumber, MAX_PALETTES);
6148 return WINED3DERR_INVALIDCALL;
6150 for (j = 0; j < 256; ++j) {
6151 pEntries[j].peRed = This->palettes[PaletteNumber][j].peRed;
6152 pEntries[j].peGreen = This->palettes[PaletteNumber][j].peGreen;
6153 pEntries[j].peBlue = This->palettes[PaletteNumber][j].peBlue;
6154 pEntries[j].peFlags = This->palettes[PaletteNumber][j].peFlags;
6156 TRACE("(%p) : returning\n", This);
6160 HRESULT WINAPI IWineD3DDeviceImpl_SetCurrentTexturePalette(IWineD3DDevice *iface, UINT PaletteNumber) {
6161 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
6162 TRACE("(%p) : PaletteNumber %u\n", This, PaletteNumber);
6163 if ( PaletteNumber < 0 || PaletteNumber >= MAX_PALETTES) {
6164 WARN("(%p) : (%u) Out of range 0-%u, returning Invalid Call\n", This, PaletteNumber, MAX_PALETTES);
6165 return WINED3DERR_INVALIDCALL;
6167 /*TODO: stateblocks */
6168 This->currentPalette = PaletteNumber;
6169 TRACE("(%p) : returning\n", This);
6173 HRESULT WINAPI IWineD3DDeviceImpl_GetCurrentTexturePalette(IWineD3DDevice *iface, UINT* PaletteNumber) {
6174 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
6175 if (PaletteNumber == NULL) {
6176 WARN("(%p) : returning Invalid Call\n", This);
6177 return WINED3DERR_INVALIDCALL;
6179 /*TODO: stateblocks */
6180 *PaletteNumber = This->currentPalette;
6181 TRACE("(%p) : returning %u\n", This, *PaletteNumber);
6185 HRESULT WINAPI IWineD3DDeviceImpl_SetSoftwareVertexProcessing(IWineD3DDevice *iface, BOOL bSoftware) {
6186 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
6187 static BOOL showFixmes = TRUE;
6189 FIXME("(%p) : stub\n", This);
6193 This->softwareVertexProcessing = bSoftware;
6198 BOOL WINAPI IWineD3DDeviceImpl_GetSoftwareVertexProcessing(IWineD3DDevice *iface) {
6199 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
6200 static BOOL showFixmes = TRUE;
6202 FIXME("(%p) : stub\n", This);
6205 return This->softwareVertexProcessing;
6209 HRESULT WINAPI IWineD3DDeviceImpl_GetRasterStatus(IWineD3DDevice *iface, UINT iSwapChain, WINED3DRASTER_STATUS* pRasterStatus) {
6210 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
6211 IWineD3DSwapChain *swapChain;
6214 TRACE("(%p) : SwapChain %d returning %p\n", This, iSwapChain, pRasterStatus);
6216 hr = IWineD3DDeviceImpl_GetSwapChain(iface, iSwapChain, (IWineD3DSwapChain **)&swapChain);
6217 if(hr == WINED3D_OK){
6218 hr = IWineD3DSwapChain_GetRasterStatus(swapChain, pRasterStatus);
6219 IWineD3DSwapChain_Release(swapChain);
6221 FIXME("(%p) IWineD3DSwapChain_GetRasterStatus returned in error\n", This);
6227 HRESULT WINAPI IWineD3DDeviceImpl_SetNPatchMode(IWineD3DDevice *iface, float nSegments) {
6228 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
6229 static BOOL showfixmes = TRUE;
6230 if(nSegments != 0.0f) {
6232 FIXME("(%p) : stub nSegments(%f)\n", This, nSegments);
6239 float WINAPI IWineD3DDeviceImpl_GetNPatchMode(IWineD3DDevice *iface) {
6240 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
6241 static BOOL showfixmes = TRUE;
6243 FIXME("(%p) : stub returning(%f)\n", This, 0.0f);
6249 HRESULT WINAPI IWineD3DDeviceImpl_UpdateSurface(IWineD3DDevice *iface, IWineD3DSurface *pSourceSurface, CONST RECT* pSourceRect, IWineD3DSurface *pDestinationSurface, CONST POINT* pDestPoint) {
6250 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *) iface;
6251 /** TODO: remove casts to IWineD3DSurfaceImpl
6252 * NOTE: move code to surface to accomplish this
6253 ****************************************/
6254 IWineD3DSurfaceImpl *pSrcSurface = (IWineD3DSurfaceImpl *)pSourceSurface;
6255 int srcWidth, srcHeight;
6256 unsigned int srcSurfaceWidth, srcSurfaceHeight, destSurfaceWidth, destSurfaceHeight;
6257 WINED3DFORMAT destFormat, srcFormat;
6259 int destLeft, destTop;
6260 WINED3DPOOL srcPool, destPool;
6262 int rowoffset = 0; /* how many bytes to add onto the end of a row to wraparound to the beginning of the next */
6263 glDescriptor *glDescription = NULL;
6264 GLenum textureDimensions = GL_TEXTURE_2D;
6265 IWineD3DBaseTexture *baseTexture;
6267 WINED3DSURFACE_DESC winedesc;
6269 TRACE("(%p) : Source (%p) Rect (%p) Destination (%p) Point(%p)\n", This, pSourceSurface, pSourceRect, pDestinationSurface, pDestPoint);
6270 memset(&winedesc, 0, sizeof(winedesc));
6271 winedesc.Width = &srcSurfaceWidth;
6272 winedesc.Height = &srcSurfaceHeight;
6273 winedesc.Pool = &srcPool;
6274 winedesc.Format = &srcFormat;
6276 IWineD3DSurface_GetDesc(pSourceSurface, &winedesc);
6278 winedesc.Width = &destSurfaceWidth;
6279 winedesc.Height = &destSurfaceHeight;
6280 winedesc.Pool = &destPool;
6281 winedesc.Format = &destFormat;
6282 winedesc.Size = &destSize;
6284 IWineD3DSurface_GetDesc(pDestinationSurface, &winedesc);
6286 if(srcPool != WINED3DPOOL_SYSTEMMEM || destPool != WINED3DPOOL_DEFAULT){
6287 WARN("source %p must be SYSTEMMEM and dest %p must be DEFAULT, returning WINED3DERR_INVALIDCALL\n", pSourceSurface, pDestinationSurface);
6288 return WINED3DERR_INVALIDCALL;
6291 if (destFormat == WINED3DFMT_UNKNOWN) {
6292 TRACE("(%p) : Converting destination surface from WINED3DFMT_UNKNOWN to the source format\n", This);
6293 IWineD3DSurface_SetFormat(pDestinationSurface, srcFormat);
6295 /* Get the update surface description */
6296 IWineD3DSurface_GetDesc(pDestinationSurface, &winedesc);
6299 /* Make sure the surface is loaded and up to date */
6300 IWineD3DSurface_PreLoad(pDestinationSurface);
6302 IWineD3DSurface_GetGlDesc(pDestinationSurface, &glDescription);
6306 /* this needs to be done in lines if the sourceRect != the sourceWidth */
6307 srcWidth = pSourceRect ? pSourceRect->right - pSourceRect->left : srcSurfaceWidth;
6308 srcHeight = pSourceRect ? pSourceRect->top - pSourceRect->bottom : srcSurfaceHeight;
6309 destLeft = pDestPoint ? pDestPoint->x : 0;
6310 destTop = pDestPoint ? pDestPoint->y : 0;
6313 /* This function doesn't support compressed textures
6314 the pitch is just bytesPerPixel * width */
6315 if(srcWidth != srcSurfaceWidth || (pSourceRect != NULL && pSourceRect->left != 0) ){
6316 rowoffset = (srcSurfaceWidth - srcWidth) * pSrcSurface->bytesPerPixel;
6317 offset += pSourceRect->left * pSrcSurface->bytesPerPixel;
6318 /* TODO: do we ever get 3bpp?, would a shift and an add be quicker than a mul (well maybe a cycle or two) */
6320 /* TODO DXT formats */
6322 if(pSourceRect != NULL && pSourceRect->top != 0){
6323 offset += pSourceRect->top * srcWidth * pSrcSurface->bytesPerPixel;
6325 TRACE("(%p) glTexSubImage2D, Level %d, left %d, top %d, width %d, height %d , ftm %d, type %d, memory %p\n"
6327 ,glDescription->level
6332 ,glDescription->glFormat
6333 ,glDescription->glType
6334 ,IWineD3DSurface_GetData(pSourceSurface)
6338 if (IWineD3DSurface_GetData(pSourceSurface) == NULL) {
6340 /* need to lock the surface to get the data */
6341 FIXME("Surfaces has no allocated memory, but should be an in memory only surface\n");
6344 /* TODO: Cube and volume support */
6346 /* not a whole row so we have to do it a line at a time */
6349 /* hopefully using pointer addtion will be quicker than using a point + j * rowoffset */
6350 unsigned char* data =((unsigned char *)IWineD3DSurface_GetData(pSourceSurface)) + offset;
6352 for(j = destTop ; j < (srcHeight + destTop) ; j++){
6354 glTexSubImage2D(glDescription->target
6355 ,glDescription->level
6360 ,glDescription->glFormat
6361 ,glDescription->glType
6362 ,data /* could be quicker using */
6367 } else { /* Full width, so just write out the whole texture */
6369 if (WINED3DFMT_DXT1 == destFormat ||
6370 WINED3DFMT_DXT2 == destFormat ||
6371 WINED3DFMT_DXT3 == destFormat ||
6372 WINED3DFMT_DXT4 == destFormat ||
6373 WINED3DFMT_DXT5 == destFormat) {
6374 if (GL_SUPPORT(EXT_TEXTURE_COMPRESSION_S3TC)) {
6375 if (destSurfaceHeight != srcHeight || destSurfaceWidth != srcWidth) {
6376 /* FIXME: The easy way to do this is lock the destination, and copy the bits accross */
6377 FIXME("Updating part of a compressed texture is not supported at the moment\n");
6378 } if (destFormat != srcFormat) {
6379 FIXME("Updating mixed format compressed texture is not curretly support\n");
6381 GL_EXTCALL(glCompressedTexImage2DARB)(glDescription->target,
6382 glDescription->level,
6383 glDescription->glFormatInternal,
6388 IWineD3DSurface_GetData(pSourceSurface));
6391 FIXME("Attempting to update a DXT compressed texture without hardware support\n");
6396 if (NP2_REPACK == wined3d_settings.nonpower2_mode) {
6398 /* some applications cannot handle odd pitches returned by soft non-power2, so we have
6399 to repack the data from pow2Width/Height to expected Width,Height, this makes the
6400 data returned by GetData non-power2 width/height with hardware non-power2
6401 pow2Width/height are set to surface width height, repacking isn't needed so it
6402 doesn't matter which function gets called. */
6403 glTexSubImage2D(glDescription->target
6404 ,glDescription->level
6409 ,glDescription->glFormat
6410 ,glDescription->glType
6411 ,IWineD3DSurface_GetData(pSourceSurface)
6415 /* not repacked, the data returned by IWineD3DSurface_GetData is pow2Width x pow2Height */
6416 glTexSubImage2D(glDescription->target
6417 ,glDescription->level
6420 ,((IWineD3DSurfaceImpl *)pSourceSurface)->pow2Width
6421 ,((IWineD3DSurfaceImpl *)pSourceSurface)->pow2Height
6422 ,glDescription->glFormat
6423 ,glDescription->glType
6424 ,IWineD3DSurface_GetData(pSourceSurface)
6430 checkGLcall("glTexSubImage2D");
6432 /* I only need to look up baseTexture here, so it may be a good idea to hava a GL_TARGET ->
6433 * GL_DIMENSIONS lookup, or maybe store the dimensions on the surface (but that's making the
6434 * surface bigger than it needs to be hmm.. */
6435 if (WINED3D_OK == IWineD3DSurface_GetContainer(pDestinationSurface, &IID_IWineD3DBaseTexture, (void **)&baseTexture)) {
6436 textureDimensions = IWineD3DBaseTexture_GetTextureDimensions(baseTexture);
6437 IWineD3DBaseTexture_Release(baseTexture);
6440 glDisable(textureDimensions); /* This needs to be managed better.... */
6446 /* Used by DirectX 8 */
6447 HRESULT WINAPI IWineD3DDeviceImpl_CopyRects(IWineD3DDevice *iface,
6448 IWineD3DSurface* pSourceSurface, CONST RECT* pSourceRectsArray, UINT cRects,
6449 IWineD3DSurface* pDestinationSurface, CONST POINT* pDestPointsArray) {
6451 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
6452 HRESULT hr = WINED3D_OK;
6453 WINED3DFORMAT srcFormat, destFormat;
6454 UINT srcWidth, destWidth;
6455 UINT srcHeight, destHeight;
6457 WINED3DSURFACE_DESC winedesc;
6459 TRACE("(%p) pSrcSur=%p, pSourceRects=%p, cRects=%d, pDstSur=%p, pDestPtsArr=%p\n", This,
6460 pSourceSurface, pSourceRectsArray, cRects, pDestinationSurface, pDestPointsArray);
6463 /* Check that the source texture is in WINED3DPOOL_SYSTEMMEM and the destination texture is in WINED3DPOOL_DEFAULT */
6464 memset(&winedesc, 0, sizeof(winedesc));
6466 winedesc.Format = &srcFormat;
6467 winedesc.Width = &srcWidth;
6468 winedesc.Height = &srcHeight;
6469 winedesc.Size = &srcSize;
6470 IWineD3DSurface_GetDesc(pSourceSurface, &winedesc);
6472 winedesc.Format = &destFormat;
6473 winedesc.Width = &destWidth;
6474 winedesc.Height = &destHeight;
6475 winedesc.Size = NULL;
6476 IWineD3DSurface_GetDesc(pDestinationSurface, &winedesc);
6478 /* Check that the source and destination formats match */
6479 if (srcFormat != destFormat && WINED3DFMT_UNKNOWN != destFormat) {
6480 WARN("(%p) source %p format must match the dest %p format, returning WINED3DERR_INVALIDCALL\n", This, pSourceSurface, pDestinationSurface);
6481 return WINED3DERR_INVALIDCALL;
6482 } else if (WINED3DFMT_UNKNOWN == destFormat) {
6483 TRACE("(%p) : Converting destination surface from WINED3DFMT_UNKNOWN to the source format\n", This);
6484 IWineD3DSurface_SetFormat(pDestinationSurface, srcFormat);
6485 destFormat = srcFormat;
6488 /* Quick if complete copy ... */
6489 if (cRects == 0 && pSourceRectsArray == NULL && pDestPointsArray == NULL) {
6491 if (srcWidth == destWidth && srcHeight == destHeight) {
6492 WINED3DLOCKED_RECT lrSrc;
6493 WINED3DLOCKED_RECT lrDst;
6494 IWineD3DSurface_LockRect(pSourceSurface, &lrSrc, NULL, WINED3DLOCK_READONLY);
6495 IWineD3DSurface_LockRect(pDestinationSurface, &lrDst, NULL, 0L);
6496 TRACE("Locked src and dst, Direct copy as surfaces are equal, w=%d, h=%d\n", srcWidth, srcHeight);
6498 memcpy(lrDst.pBits, lrSrc.pBits, srcSize);
6500 IWineD3DSurface_UnlockRect(pSourceSurface);
6501 IWineD3DSurface_UnlockRect(pDestinationSurface);
6502 TRACE("Unlocked src and dst\n");
6506 FIXME("Wanted to copy all surfaces but size not compatible, returning WINED3DERR_INVALIDCALL\n");
6507 hr = WINED3DERR_INVALIDCALL;
6512 if (NULL != pSourceRectsArray && NULL != pDestPointsArray) {
6514 int bytesPerPixel = ((IWineD3DSurfaceImpl *) pSourceSurface)->bytesPerPixel;
6517 /* Copy rect by rect */
6518 for (i = 0; i < cRects; ++i) {
6519 CONST RECT* r = &pSourceRectsArray[i];
6520 CONST POINT* p = &pDestPointsArray[i];
6523 WINED3DLOCKED_RECT lrSrc;
6524 WINED3DLOCKED_RECT lrDst;
6527 TRACE("Copying rect %d (%ld,%ld),(%ld,%ld) -> (%ld,%ld)\n", i, r->left, r->top, r->right, r->bottom, p->x, p->y);
6528 if (srcFormat == WINED3DFMT_DXT1) {
6529 copyperline = ((r->right - r->left) * bytesPerPixel) / 2; /* DXT1 is half byte per pixel */
6531 copyperline = ((r->right - r->left) * bytesPerPixel);
6534 IWineD3DSurface_LockRect(pSourceSurface, &lrSrc, r, WINED3DLOCK_READONLY);
6535 dest_rect.left = p->x;
6536 dest_rect.top = p->y;
6537 dest_rect.right = p->x + (r->right - r->left);
6538 dest_rect.bottom= p->y + (r->bottom - r->top);
6539 IWineD3DSurface_LockRect(pDestinationSurface, &lrDst, &dest_rect, 0L);
6540 TRACE("Locked src and dst\n");
6542 /* Find where to start */
6543 for (j = 0; j < (r->bottom - r->top - 1); ++j) {
6544 memcpy((char*) lrDst.pBits + (j * lrDst.Pitch), (char*) lrSrc.pBits + (j * lrSrc.Pitch), copyperline);
6546 IWineD3DSurface_UnlockRect(pSourceSurface);
6547 IWineD3DSurface_UnlockRect(pDestinationSurface);
6548 TRACE("Unlocked src and dst\n");
6551 FIXME("Wanted to copy partial surfaces not implemented, returning WINED3DERR_INVALIDCALL\n");
6552 hr = WINED3DERR_INVALIDCALL;
6559 /* Implementation details at http://developer.nvidia.com/attach/6494
6561 http://oss.sgi.com/projects/ogl-sample/registry/NV/evaluators.txt
6562 hmm.. no longer supported use
6563 OpenGL evaluators or tessellate surfaces within your application.
6566 /* http://msdn.microsoft.com/library/default.asp?url=/library/en-us/directx9_c/directx/graphics/reference/d3d/interfaces/idirect3ddevice9/DrawRectPatch.asp */
6567 HRESULT WINAPI IWineD3DDeviceImpl_DrawRectPatch(IWineD3DDevice *iface, UINT Handle, CONST float* pNumSegs, CONST WINED3DRECTPATCH_INFO* pRectPatchInfo) {
6568 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
6569 TRACE("(%p) Handle(%d) noSegs(%p) rectpatch(%p)\n", This, Handle, pNumSegs, pRectPatchInfo);
6570 FIXME("(%p) : Stub\n", This);
6575 /* http://msdn.microsoft.com/library/default.asp?url=/library/en-us/directx9_c/directx/graphics/reference/d3d/interfaces/idirect3ddevice9/DrawTriPatch.asp */
6576 HRESULT WINAPI IWineD3DDeviceImpl_DrawTriPatch(IWineD3DDevice *iface, UINT Handle, CONST float* pNumSegs, CONST WINED3DTRIPATCH_INFO* pTriPatchInfo) {
6577 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
6578 TRACE("(%p) Handle(%d) noSegs(%p) tripatch(%p)\n", This, Handle, pNumSegs, pTriPatchInfo);
6579 FIXME("(%p) : Stub\n", This);
6583 HRESULT WINAPI IWineD3DDeviceImpl_DeletePatch(IWineD3DDevice *iface, UINT Handle) {
6584 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
6585 TRACE("(%p) Handle(%d)\n", This, Handle);
6586 FIXME("(%p) : Stub\n", This);
6590 HRESULT WINAPI IWineD3DDeviceImpl_ColorFill(IWineD3DDevice *iface, IWineD3DSurface *pSurface, CONST D3DRECT* pRect, D3DCOLOR color) {
6591 /* I couldn't find a 'really' quick way of doing this in openGl so here goes
6592 fill a surface with a block of color! */
6593 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
6594 /* TODO: get rid of the use of IWineD3DSurfaceImpl, move code into surface.c */
6595 IWineD3DSurfaceImpl *surface = (IWineD3DSurfaceImpl *)pSurface;
6596 IWineD3DSwapChainImpl *container = NULL;
6597 BOOL isRenderTarget = FALSE;
6598 unsigned int width, height;
6599 unsigned int top, left;
6602 TRACE("(%p) Colour fill Surface: %p rect: %p color: %ld\n", This, pSurface, pRect, color);
6604 if (surface->resource.pool != WINED3DPOOL_DEFAULT && surface->resource.pool != WINED3DPOOL_SYSTEMMEM) {
6605 FIXME("call to colorfill with non WINED3DPOOL_DEFAULT or WINED3DPOOL_SYSTEMMEM surface\n");
6606 return WINED3DERR_INVALIDCALL;
6609 /* TODO: get rid of IWineD3DSwapChainImpl reference, a 'context' manager may help with this */
6610 if (WINED3D_OK == IWineD3DSurface_GetContainer(pSurface, &IID_IWineD3DSwapChain, (void **)&container) || pSurface == This->renderTarget) {
6611 if (WINED3DUSAGE_RENDERTARGET & surface->resource.usage) {
6612 /* TODO: make sure we set everything back to the way it was, and context management!
6613 glGetIntegerv(GL_READ_BUFFER, &prev_read);
6614 vcheckGLcall("glIntegerv");
6615 glGetIntegerv(GL_PACK_SWAP_BYTES, &prev_store);
6616 vcheckGLcall("glIntegerv");
6618 TRACE("Color fill to render targets may cause some graphics issues\n");
6619 if (pSurface == container->frontBuffer) {
6620 glDrawBuffer(GL_FRONT);
6622 glDrawBuffer(GL_BACK);
6625 if (WINED3DUSAGE_DEPTHSTENCIL & surface->resource.usage) {
6626 FIXME("colouring of depth_stencil? %p buffers is not yet supported? %ld\n", surface, surface->resource.usage);
6628 FIXME("(%p) : Regression %ld %p %p\n", This, surface->resource.usage, pSurface, This->renderTarget);
6630 if (container != NULL) {
6631 IWineD3DSwapChain_Release((IWineD3DSwapChain *)container);
6633 /* we can use GL_STENCIL_INDEX etc...*/
6636 if (container != NULL) {
6637 IWineD3DSwapChain_Release((IWineD3DSwapChain *)container);
6639 isRenderTarget = TRUE;
6641 /* TODO: drawing to GL_FRONT and GL_BACK */
6642 /* TODO: see if things can be speeded up by using the correct
6643 * colour model of the target texture from the start (16 bit graphics on 32 X are slow anyway!) */
6644 if (pRect == NULL) {
6647 width = surface->currentDesc.Width;
6648 height = surface->currentDesc.Height;
6652 width = pRect->x2 - left;
6653 height = pRect->y2 - top;
6656 data = HeapAlloc(GetProcessHeap(), 0, 4 * width);
6657 /* Create a 'line' of color color, in the correct format for the surface */
6658 for (u = 0 ; u < width ; u ++) {
6663 if (isRenderTarget == FALSE) {
6664 glDescriptor *glDesc;
6665 IWineD3DSurface_PreLoad(pSurface);
6667 /* draw a block of the coloured line on the sufrace */
6668 IWineD3DSurface_GetGlDesc(pSurface, &glDesc);
6669 for (v = 0 ; v< height;v++) {
6670 glTexSubImage2D(glDesc->target
6671 ,glDesc->level /* level */
6681 checkGLcall("glTexSubImage2D");
6683 glDisable(glDesc->target);
6685 /** FIXME: Using GLClear may be faster **/
6686 glRasterPos2i(left, top);
6687 glPixelZoom((float)width ,(float)height);
6688 glDrawPixels(1, 1, GL_RGBA, GL_UNSIGNED_BYTE, data);
6689 checkGLcall("glDrawPixels");
6691 HeapFree(GetProcessHeap(), 0, data);
6697 /* rendertarget and deptth stencil functions */
6698 HRESULT WINAPI IWineD3DDeviceImpl_GetRenderTarget(IWineD3DDevice* iface,DWORD RenderTargetIndex, IWineD3DSurface **ppRenderTarget) {
6699 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
6701 /* FIXME: Implelent RenderTargetIndex >0 */
6702 if(RenderTargetIndex > 0)
6703 FIXME("(%p) : RenderTargetIndex %ld >0 not currently supported\n", This, RenderTargetIndex);
6705 *ppRenderTarget = This->renderTarget;
6706 TRACE("(%p) : RenderTarget %ld Index returning %p\n", This, RenderTargetIndex, *ppRenderTarget);
6707 /* Note inc ref on returned surface */
6708 if(*ppRenderTarget != NULL)
6709 IWineD3DSurface_AddRef(*ppRenderTarget);
6713 HRESULT WINAPI IWineD3DDeviceImpl_SetFrontBackBuffers(IWineD3DDevice *iface, IWineD3DSurface *Front, IWineD3DSurface *Back) {
6714 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
6715 IWineD3DSurfaceImpl *FrontImpl = (IWineD3DSurfaceImpl *) Front;
6716 IWineD3DSurfaceImpl *BackImpl = (IWineD3DSurfaceImpl *) Back;
6717 IWineD3DSwapChainImpl *Swapchain;
6720 TRACE("(%p)->(%p,%p)\n", This, FrontImpl, BackImpl);
6722 hr = IWineD3DDevice_GetSwapChain(iface, 0, (IWineD3DSwapChain **) &Swapchain);
6723 if(hr != WINED3D_OK) {
6724 ERR("Can't get the swapchain\n");
6728 /* Make sure to release the swapchain */
6729 IWineD3DSwapChain_Release((IWineD3DSwapChain *) Swapchain);
6731 if(FrontImpl && !(FrontImpl->resource.usage & WINED3DUSAGE_RENDERTARGET) ) {
6732 ERR("Trying to set a front buffer which doesn't have WINED3DUSAGE_RENDERTARGET usage\n");
6733 return WINED3DERR_INVALIDCALL;
6735 else if(BackImpl && !(BackImpl->resource.usage & WINED3DUSAGE_RENDERTARGET)) {
6736 ERR("Trying to set a back buffer which doesn't have WINED3DUSAGE_RENDERTARGET usage\n");
6737 return WINED3DERR_INVALIDCALL;
6740 if(Swapchain->frontBuffer != Front) {
6741 TRACE("Changing the front buffer from %p to %p\n", Swapchain->frontBuffer, Front);
6743 if(Swapchain->frontBuffer)
6744 IWineD3DSurface_SetContainer(Swapchain->frontBuffer, NULL);
6745 Swapchain->frontBuffer = Front;
6747 if(Swapchain->frontBuffer) {
6748 IWineD3DSurface_SetContainer(Swapchain->frontBuffer, (IWineD3DBase *) Swapchain);
6751 if(Swapchain->backBuffer != Back) {
6752 TRACE("Changing the back buffer from %p to %p\n", Swapchain->backBuffer, Back);
6754 if(!Swapchain->backBuffer) {
6755 /* GL was told to draw to the front buffer at creation,
6758 glDrawBuffer(GL_BACK);
6759 checkGLcall("glDrawBuffer(GL_BACK)");
6761 /* That makes problems - disable for now */
6762 /* glDrawBuffer(GL_FRONT); */
6763 checkGLcall("glDrawBuffer(GL_FRONT)");
6767 if(Swapchain->backBuffer)
6768 IWineD3DSurface_SetContainer(Swapchain->backBuffer, NULL);
6769 Swapchain->backBuffer = Back;
6771 if(Swapchain->backBuffer) {
6772 IWineD3DSurface_SetContainer(Swapchain->backBuffer, (IWineD3DBase *) Swapchain);
6780 HRESULT WINAPI IWineD3DDeviceImpl_GetDepthStencilSurface(IWineD3DDevice* iface, IWineD3DSurface **ppZStencilSurface) {
6781 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
6782 *ppZStencilSurface = This->depthStencilBuffer;
6783 TRACE("(%p) : zStencilSurface returning %p\n", This, *ppZStencilSurface);
6785 if(*ppZStencilSurface != NULL) {
6786 /* Note inc ref on returned surface */
6787 IWineD3DSurface_AddRef(*ppZStencilSurface);
6792 /* internal static helper functions */
6793 HRESULT WINAPI static IWineD3DDeviceImpl_ActiveRender(IWineD3DDevice* iface,
6794 IWineD3DSurface *RenderSurface);
6796 HRESULT WINAPI IWineD3DDeviceImpl_SetRenderTarget(IWineD3DDevice *iface, DWORD RenderTargetIndex, IWineD3DSurface *pRenderTarget) {
6797 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
6798 HRESULT hr = WINED3D_OK;
6799 WINED3DVIEWPORT viewport;
6801 TRACE("(%p) Swapping rendertarget\n",This);
6802 if (RenderTargetIndex > 0) {
6803 FIXME("(%p) Render targets other than the first are not supported\n",This);
6804 RenderTargetIndex = 0;
6807 /* MSDN says that null disables the render target
6808 but a device must always be associated with a render target
6809 nope MSDN says that we return invalid call to a null rendertarget with an index of 0
6811 see http://msdn.microsoft.com/library/default.asp?url=/library/en-us/directx9_c/directx/graphics/programmingguide/AdvancedTopics/PixelPipe/MultipleRenderTarget.asp
6814 if (RenderTargetIndex == 0 && pRenderTarget == NULL) {
6815 FIXME("Trying to set render target 0 to NULL\n");
6816 return WINED3DERR_INVALIDCALL;
6818 /* TODO: replace Impl* usage with interface usage */
6819 if (!((IWineD3DSurfaceImpl *)pRenderTarget)->resource.usage & WINED3DUSAGE_RENDERTARGET) {
6820 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);
6821 return WINED3DERR_INVALIDCALL;
6823 /** TODO: check that the depth stencil format matches the render target, this is only done in debug
6824 * builds, but I think wine counts as a 'debug' build for now.
6825 ******************************/
6826 /* If we are trying to set what we already have, don't bother */
6827 if (pRenderTarget == This->renderTarget) {
6828 TRACE("Trying to do a NOP SetRenderTarget operation\n");
6830 /* Otherwise, set the render target up */
6832 if (FALSE == This->sceneEnded) {
6833 IWineD3DDevice_EndScene(iface);
6835 TRACE("clearing renderer\n");
6836 /* IWineD3DDeviceImpl_CleanRender(iface); */
6837 /* OpenGL doesn't support 'sharing' of the stencilBuffer so we may incure an extra memory overhead
6838 depending on the renter target implementation being used.
6839 A shared context implementation will share all buffers between all rendertargets (including swapchains),
6840 implementations that use separate pbuffers for different swapchains or rendertargets will have to duplicate the
6841 stencil buffer and incure an extra memory overhead */
6842 hr = IWineD3DDeviceImpl_ActiveRender(iface, pRenderTarget);
6845 if (SUCCEEDED(hr)) {
6846 /* Finally, reset the viewport as the MSDN states. */
6847 /* TODO: Replace impl usage */
6848 viewport.Height = ((IWineD3DSurfaceImpl *)This->renderTarget)->currentDesc.Height;
6849 viewport.Width = ((IWineD3DSurfaceImpl *)This->renderTarget)->currentDesc.Width;
6852 viewport.MaxZ = 1.0f;
6853 viewport.MinZ = 0.0f;
6854 IWineD3DDeviceImpl_SetViewport(iface, &viewport);
6856 FIXME("Unknown error setting the render target\n");
6858 This->sceneEnded = FALSE;
6862 HRESULT WINAPI IWineD3DDeviceImpl_SetDepthStencilSurface(IWineD3DDevice *iface, IWineD3DSurface *pNewZStencil) {
6863 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
6864 HRESULT hr = WINED3D_OK;
6865 IWineD3DSurface *tmp;
6867 TRACE("(%p) Swapping z-buffer\n",This);
6869 if (pNewZStencil == This->stencilBufferTarget) {
6870 TRACE("Trying to do a NOP SetRenderTarget operation\n");
6872 /** OpenGL doesn't support 'sharing' of the stencilBuffer so we may incure an extra memory overhead
6873 * depending on the renter target implementation being used.
6874 * A shared context implementation will share all buffers between all rendertargets (including swapchains),
6875 * implementations that use separate pbuffers for different swapchains or rendertargets will have to duplicate the
6876 * stencil buffer and incure an extra memory overhead
6877 ******************************************************/
6880 tmp = This->stencilBufferTarget;
6881 This->stencilBufferTarget = pNewZStencil;
6882 /* should we be calling the parent or the wined3d surface? */
6883 if (NULL != This->stencilBufferTarget) IWineD3DSurface_AddRef(This->stencilBufferTarget);
6884 if (NULL != tmp) IWineD3DSurface_Release(tmp);
6886 /** TODO: glEnable/glDisable on depth/stencil depending on
6887 * pNewZStencil is NULL and the depth/stencil is enabled in d3d
6888 **********************************************************/
6895 #ifdef GL_VERSION_1_3
6896 /* Internal functions not in DirectX */
6897 /** TODO: move this off to the opengl context manager
6898 *(the swapchain doesn't need to know anything about offscreen rendering!)
6899 ****************************************************/
6901 HRESULT WINAPI IWineD3DDeviceImpl_CleanRender(IWineD3DDevice* iface, IWineD3DSwapChainImpl *swapchain)
6903 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
6905 TRACE("(%p), %p\n", This, swapchain);
6907 if (swapchain->win != swapchain->drawable) {
6908 /* Set everything back the way it ws */
6909 swapchain->render_ctx = swapchain->glCtx;
6910 swapchain->drawable = swapchain->win;
6915 /* TODO: move this off into a context manager so that GLX_ATI_render_texture and other types of surface can be used. */
6916 HRESULT WINAPI IWineD3DDeviceImpl_FindGLContext(IWineD3DDevice *iface, IWineD3DSurface *pSurface, glContext **context) {
6917 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
6920 unsigned int height;
6921 WINED3DFORMAT format;
6922 WINED3DSURFACE_DESC surfaceDesc;
6923 memset(&surfaceDesc, 0, sizeof(surfaceDesc));
6924 surfaceDesc.Width = &width;
6925 surfaceDesc.Height = &height;
6926 surfaceDesc.Format = &format;
6927 IWineD3DSurface_GetDesc(pSurface, &surfaceDesc);
6929 /* I need a get width/height function (and should do something with the format) */
6930 for (i = 0; i < CONTEXT_CACHE; ++i) {
6931 /** NOTE: the contextCache[i].pSurface == pSurface check ceates onepbuffer per surface
6932 ATI cards don't destroy pbuffers, but as soon as resource releasing callbacks are inplace
6933 the pSurface can be set to 0 allowing it to be reused from cache **/
6934 if (This->contextCache[i].Width == width && This->contextCache[i].Height == height
6935 && (pbuffer_per_surface == FALSE || This->contextCache[i].pSurface == pSurface || This->contextCache[i].pSurface == NULL)) {
6936 *context = &This->contextCache[i];
6939 if (This->contextCache[i].Width == 0) {
6940 This->contextCache[i].pSurface = pSurface;
6941 This->contextCache[i].Width = width;
6942 This->contextCache[i].Height = height;
6943 *context = &This->contextCache[i];
6947 if (i == CONTEXT_CACHE) {
6948 int minUsage = 0x7FFFFFFF; /* MAX_INT */
6949 glContext *dropContext = 0;
6950 for (i = 0; i < CONTEXT_CACHE; i++) {
6951 if (This->contextCache[i].usedcount < minUsage) {
6952 dropContext = &This->contextCache[i];
6953 minUsage = This->contextCache[i].usedcount;
6956 /* clean up the context (this doesn't work for ATI at the moment */
6958 glXDestroyContext(swapchain->display, dropContext->context);
6959 glXDestroyPbuffer(swapchain->display, dropContext->drawable);
6962 dropContext->Width = 0;
6963 dropContext->pSurface = pSurface;
6964 *context = dropContext;
6966 if (++This->contextCache[i].usedcount == 0x7FFFFFFF /* MAX_INT */ - 1 ) {
6967 for (i = 0; i < CONTEXT_CACHE; i++) {
6968 This->contextCache[i].usedcount = max(0, This->contextCache[i].usedcount - (0x7FFFFFFF /* MAX_INT */ >> 1));
6972 if (*context != NULL)
6975 return E_OUTOFMEMORY;
6979 /** FIXME: This is currently used called whenever SetRenderTarget or SetStencilBuffer are called
6980 * the functionality needs splitting up so that we don't do more than we should do.
6981 * this only seems to impact performance a little.
6982 ******************************/
6983 HRESULT WINAPI IWineD3DDeviceImpl_ActiveRender(IWineD3DDevice* iface,
6984 IWineD3DSurface *RenderSurface) {
6985 HRESULT ret = WINED3DERR_INVALIDCALL;
6988 * Currently only active for GLX >= 1.3
6989 * for others versions we'll have to use GLXPixmaps
6991 * normally we must test GLX_VERSION_1_3 but nvidia headers are not correct
6992 * as they implement GLX 1.3 but only define GLX_VERSION_1_2
6993 * so only check OpenGL version
6994 * ..........................
6995 * I don't believe that it is a problem with NVidia headers,
6996 * XFree only supports GLX1.2, nVidia (and ATI to some extent) provide 1.3 functions
6997 * in GLX 1.2, there is no mention of the correct way to tell if the extensions are provided.
6999 * Your application will report GLX version 1.2 on glXQueryVersion.
7000 * However, it is safe to call the GLX 1.3 functions as described below.
7002 #if defined(GL_VERSION_1_3)
7004 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
7005 IWineD3DSurface *StencilSurface = This->stencilBufferTarget;
7006 IWineD3DSurface *tmp;
7007 /** TODO: we only need to look up the configuration !IF! we are setting the target to a texture **/
7008 GLXFBConfig* cfgs = NULL;
7012 IWineD3DSwapChain *currentSwapchain;
7013 IWineD3DSwapChainImpl *swapchain;
7014 /** TODO: get rid of Impl usage we should always create a zbuffer/stencil with our contexts if possible,
7015 * but switch them off if the StencilSurface is set to NULL
7016 ** *********************************************************/
7017 D3DFORMAT BackBufferFormat = ((IWineD3DSurfaceImpl *) RenderSurface)->resource.format;
7018 D3DFORMAT StencilBufferFormat = (NULL != StencilSurface) ? ((IWineD3DSurfaceImpl *) StencilSurface)->resource.format : 0;
7021 if StencilSurface == NULL && zBufferTarget != NULL then switch the zbuffer off,
7022 it StencilSurface != NULL && zBufferTarget == NULL switch it on
7025 #define PUSH1(att) attribs[nAttribs++] = (att);
7026 #define PUSH2(att,value) attribs[nAttribs++] = (att); attribs[nAttribs++] = (value);
7028 /* PUSH2(GLX_BIND_TO_TEXTURE_RGBA_ATI, True); examples of this are few and far between (but I've got a nice working one!)*/
7030 /** TODO: remove the reff to Impl (context manager should fix this!) **/
7031 IWineD3DSwapChainImpl *impSwapChain;
7032 IWineD3DDevice_GetSwapChain(iface, 0, (IWineD3DSwapChain **)&impSwapChain);
7033 if (NULL == impSwapChain) { /* NOTE: This should NEVER fail */
7034 ERR("(%p) Failed to get a the implicit swapchain\n", iface);
7039 PUSH2(GLX_DRAWABLE_TYPE, GLX_PBUFFER_BIT);
7040 PUSH2(GLX_X_RENDERABLE, TRUE);
7041 PUSH2(GLX_DOUBLEBUFFER, TRUE);
7042 TRACE("calling makeglcfg\n");
7043 D3DFmtMakeGlCfg(BackBufferFormat, StencilBufferFormat, attribs, &nAttribs, FALSE /* alternate */);
7046 TRACE("calling chooseFGConfig\n");
7047 cfgs = glXChooseFBConfig(impSwapChain->display, DefaultScreen(impSwapChain->display),
7050 if (!cfgs) { /* OK we didn't find the exact config, so use any reasonable match */
7051 /* TODO: fill in the 'requested' and 'current' depths, also make sure that's
7052 why we failed and only show this message once! */
7053 MESSAGE("Failed to find exact match, finding alternative but you may suffer performance issues, try changing xfree's depth to match the requested depth\n"); /**/
7055 PUSH2(GLX_DRAWABLE_TYPE, GLX_PBUFFER_BIT | GLX_WINDOW_BIT);
7056 /* PUSH2(GLX_X_RENDERABLE, TRUE); */
7057 PUSH2(GLX_RENDER_TYPE, GLX_RGBA_BIT);
7058 PUSH2(GLX_DOUBLEBUFFER, FALSE);
7059 TRACE("calling makeglcfg\n");
7060 D3DFmtMakeGlCfg(BackBufferFormat, StencilBufferFormat, attribs, &nAttribs, TRUE /* alternate */);
7062 cfgs = glXChooseFBConfig(impSwapChain->display, DefaultScreen(impSwapChain->display),
7069 for (i = 0; i < nCfgs; ++i) {
7070 TRACE("for (%u,%s)/(%u,%s) found config[%d]@%p\n", BackBufferFormat,
7071 debug_d3dformat(BackBufferFormat), StencilBufferFormat,
7072 debug_d3dformat(StencilBufferFormat), i, cfgs[i]);
7075 if (NULL != This->renderTarget) {
7077 vcheckGLcall("glFlush");
7078 /** This is only useful if the old render target was a swapchain,
7079 * we need to supercede this with a function that displays
7080 * the current buffer on the screen. This is easy to do in glx1.3 but
7081 * we need to do copy-write pixels in glx 1.2.
7082 ************************************************/
7083 glXSwapBuffers(impSwapChain->display, impSwapChain->drawable);
7085 printf("Hit Enter to get next frame ...\n");
7091 if (IWineD3DSurface_GetContainer(This->renderTarget, &IID_IWineD3DSwapChain, (void **)¤tSwapchain) != WINED3D_OK) {
7092 /* the selected render target doesn't belong to a swapchain, so use the devices implicit swapchain */
7093 IWineD3DDevice_GetSwapChain(iface, 0, ¤tSwapchain);
7097 * TODO: remove the use of IWineD3DSwapChainImpl, a context manager will help since it will replace the
7098 * renderTarget = swapchain->backBuffer bit and anything to do with *glContexts
7099 **********************************************************************/
7100 if (IWineD3DSurface_GetContainer(RenderSurface, &IID_IWineD3DSwapChain, (void **)&swapchain) == WINED3D_OK) {
7101 /* We also need to make sure that the lights &co are also in the context of the swapchains */
7102 /* FIXME: If the render target gets sent to the frontBuffer should be be presenting it raw? */
7103 TRACE("making swapchain active\n");
7104 if (RenderSurface != This->renderTarget) {
7105 if (RenderSurface == swapchain->backBuffer) {
7107 /* This could be flagged so that some operations work directly with the front buffer */
7108 FIXME("Attempting to set the renderTarget to the frontBuffer\n");
7110 if (glXMakeCurrent(swapchain->display, swapchain->win, swapchain->glCtx)
7112 TRACE("Error in setting current context: context %p drawable %ld !\n",
7113 impSwapChain->glCtx, impSwapChain->win);
7116 IWineD3DDeviceImpl_CleanRender(iface, (IWineD3DSwapChainImpl *)currentSwapchain);
7118 checkGLcall("glXMakeContextCurrent");
7120 IWineD3DSwapChain_Release((IWineD3DSwapChain *)swapchain);
7122 else if (pbuffer_support && cfgs != NULL /* && some test to make sure that opengl supports pbuffers */) {
7124 /** ********************************************************************
7125 * This is a quickly hacked out implementation of offscreen textures.
7126 * It will work in most cases but there may be problems if the client
7127 * modifies the texture directly, or expects the contents of the rendertarget
7130 * There are some real speed vs compatibility issues here:
7131 * we should really use a new context for every texture, but that eats ram.
7132 * we should also be restoring the texture to the pbuffer but that eats CPU
7133 * we can also 'reuse' the current pbuffer if the size is larger than the requested buffer,
7134 * but if this means reusing the display backbuffer then we need to make sure that
7135 * states are correctly preserved.
7136 * In many cases I would expect that we can 'skip' some functions, such as preserving states,
7137 * and gain a good performance increase at the cost of compatibility.
7138 * I would suggest that, when this is the case, a user configurable flag be made
7139 * available, allowing the user to choose the best emulated experience for them.
7140 *********************************************************************/
7142 XVisualInfo *visinfo;
7143 glContext *newContext;
7145 /* Here were using a shared context model */
7146 if (WINED3D_OK != IWineD3DDeviceImpl_FindGLContext(iface, RenderSurface, &newContext)) {
7147 FIXME("(%p) : Failed to find a context for surface %p\n", iface, RenderSurface);
7150 /* If the context doesn't exist then create a new one */
7151 /* TODO: This should really be part of findGlContext */
7152 if (NULL == newContext->context) {
7154 TRACE("making new buffer\n");
7156 PUSH2(GLX_PBUFFER_WIDTH, newContext->Width);
7157 PUSH2(GLX_PBUFFER_HEIGHT, newContext->Height);
7160 newContext->drawable = glXCreatePbuffer(impSwapChain->display, cfgs[0], attribs);
7162 /** ****************************************
7163 *GLX1.3 isn't supported by XFree 'yet' until that point ATI emulates pBuffers
7165 * In future releases, we may provide the calls glXCreateNewContext,
7166 * glXQueryDrawable and glXMakeContextCurrent.
7167 * so until then we have to use glXGetVisualFromFBConfig &co..
7168 ********************************************/
7171 visinfo = glXGetVisualFromFBConfig(impSwapChain->display, cfgs[0]);
7173 ERR("Error: couldn't get an RGBA, double-buffered visual\n");
7175 newContext->context = glXCreateContext(impSwapChain->display, visinfo, impSwapChain->glCtx, GL_TRUE);
7179 if (NULL == newContext || NULL == newContext->context) {
7180 ERR("(%p) : Failed to find a context for surface %p\n", iface, RenderSurface);
7182 /* Debug logging, (this function leaks), change to a TRACE when the leak is plugged */
7183 if (glXMakeCurrent(impSwapChain->display, newContext->drawable, newContext->context) == False) {
7184 TRACE("Error in setting current context: context %p drawable %ld\n", newContext->context, newContext->drawable);
7187 /* Clean up the old context */
7188 IWineD3DDeviceImpl_CleanRender(iface, (IWineD3DSwapChainImpl *)currentSwapchain);
7189 /* Set the current context of the swapchain to the new context */
7190 impSwapChain->drawable = newContext->drawable;
7191 impSwapChain->render_ctx = newContext->context;
7195 #if 1 /* Apply the stateblock to the new context
7196 FIXME: This is a bit of a hack, each context should know it's own state,
7197 the directX current directX state should then be applied to the context */
7200 IWineD3DStateBlockImpl *oldUpdateStateBlock;
7201 oldUpdateStateBlock = This->updateStateBlock;
7202 oldRecording= This->isRecordingState;
7203 This->isRecordingState = FALSE;
7204 This->updateStateBlock = This->stateBlock;
7205 IWineD3DStateBlock_Apply((IWineD3DStateBlock *)This->stateBlock);
7207 This->isRecordingState = oldRecording;
7208 This->updateStateBlock = oldUpdateStateBlock;
7213 /* clean up the current rendertargets swapchain (if it belonged to one) */
7214 if (currentSwapchain != NULL) {
7215 IWineD3DSwapChain_Release((IWineD3DSwapChain *)currentSwapchain);
7218 /* Were done with the opengl context management, setup the rendertargets */
7220 tmp = This->renderTarget;
7221 This->renderTarget = RenderSurface;
7222 IWineD3DSurface_AddRef(This->renderTarget);
7223 IWineD3DSurface_Release(tmp);
7229 /* The surface must be rendered upside down to cancel the flip produce by glCopyTexImage */
7230 /* Check that the container is not a swapchain member */
7232 IWineD3DSwapChain *tmpSwapChain;
7233 if (WINED3D_OK != IWineD3DSurface_GetContainer(This->renderTarget, &IID_IWineD3DSwapChain, (void **)&tmpSwapChain)) {
7234 This->renderUpsideDown = TRUE;
7236 This->renderUpsideDown = FALSE;
7237 IWineD3DSwapChain_Release(tmpSwapChain);
7239 /* Force updating the cull mode */
7240 TRACE("setting render state\n");
7241 IWineD3DDevice_GetRenderState(iface, WINED3DRS_CULLMODE, &value);
7242 IWineD3DDevice_SetRenderState(iface, WINED3DRS_CULLMODE, value);
7244 /* Force updating projection matrix */
7245 This->last_was_rhw = FALSE;
7246 This->proj_valid = FALSE;
7254 ERR("cannot get valides GLXFBConfig for (%u,%s)/(%u,%s)\n", BackBufferFormat,
7255 debug_d3dformat(BackBufferFormat), StencilBufferFormat, debug_d3dformat(StencilBufferFormat));
7260 if ( NULL != impSwapChain) {
7261 IWineD3DSwapChain_Release((IWineD3DSwapChain *)impSwapChain);
7269 HRESULT WINAPI IWineD3DDeviceImpl_SetCursorProperties(IWineD3DDevice* iface, UINT XHotSpot,
7270 UINT YHotSpot, IWineD3DSurface *pCursorBitmap) {
7271 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *) iface;
7272 /* TODO: the use of Impl is deprecated. */
7273 /* some basic validation checks */
7274 IWineD3DSurfaceImpl * pSur = (IWineD3DSurfaceImpl *) pCursorBitmap;
7276 TRACE("(%p) : Spot Pos(%u,%u)\n", This, XHotSpot, YHotSpot);
7278 if (WINED3DFMT_A8R8G8B8 != pSur->resource.format) {
7279 ERR("(%p) : surface(%p) has an invalid format\n", This, pCursorBitmap);
7280 return WINED3DERR_INVALIDCALL;
7282 if (32 != pSur->currentDesc.Height || 32 != pSur->currentDesc.Width) {
7283 ERR("(%p) : surface(%p) has an invalid size\n", This, pCursorBitmap);
7284 return WINED3DERR_INVALIDCALL;
7286 /* TODO: make the cursor 'real' */
7288 This->xHotSpot = XHotSpot;
7289 This->yHotSpot = YHotSpot;
7294 void WINAPI IWineD3DDeviceImpl_SetCursorPosition(IWineD3DDevice* iface, int XScreenSpace, int YScreenSpace, DWORD Flags) {
7295 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *) iface;
7296 TRACE("(%p) : SetPos to (%u,%u)\n", This, XScreenSpace, YScreenSpace);
7298 This->xScreenSpace = XScreenSpace;
7299 This->yScreenSpace = YScreenSpace;
7305 BOOL WINAPI IWineD3DDeviceImpl_ShowCursor(IWineD3DDevice* iface, BOOL bShow) {
7306 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *) iface;
7307 TRACE("(%p) : visible(%d)\n", This, bShow);
7309 This->bCursorVisible = bShow;
7314 HRESULT WINAPI IWineD3DDeviceImpl_TestCooperativeLevel(IWineD3DDevice* iface) {
7315 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *) iface;
7316 TRACE("(%p) : state (%lu)\n", This, This->state);
7317 /* TODO: Implement wrapping of the WndProc so that mimimize and maxamise can be monitored and the states adjusted. */
7318 switch (This->state) {
7321 case WINED3DERR_DEVICELOST:
7323 ResourceList *resourceList = This->resources;
7324 while (NULL != resourceList) {
7325 if (((IWineD3DResourceImpl *)resourceList->resource)->resource.pool == WINED3DPOOL_DEFAULT /* TODO: IWineD3DResource_GetPool(resourceList->resource)*/)
7326 return WINED3DERR_DEVICENOTRESET;
7327 resourceList = resourceList->next;
7329 return WINED3DERR_DEVICELOST;
7331 case WINED3DERR_DRIVERINTERNALERROR:
7332 return WINED3DERR_DRIVERINTERNALERROR;
7336 return WINED3DERR_DRIVERINTERNALERROR;
7340 HRESULT WINAPI IWineD3DDeviceImpl_EvictManagedResources(IWineD3DDevice* iface) {
7341 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *) iface;
7342 /** FIXME: Resource tracking needs to be done,
7343 * The closes we can do to this is set the priorities of all managed textures low
7344 * and then reset them.
7345 ***********************************************************/
7346 FIXME("(%p) : stub\n", This);
7350 HRESULT WINAPI IWineD3DDeviceImpl_Reset(IWineD3DDevice* iface, WINED3DPRESENT_PARAMETERS* pPresentationParameters) {
7351 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *) iface;
7352 /** FIXME: Resource trascking needs to be done.
7353 * in effect this pulls all non only default
7354 * textures out of video memory and deletes all glTextures (glDeleteTextures)
7355 * and should clear down the context and set it up according to pPresentationParameters
7356 ***********************************************************/
7357 FIXME("(%p) : stub\n", This);
7361 HRESULT WINAPI IWineD3DDeviceImpl_SetDialogBoxMode(IWineD3DDevice *iface, BOOL bEnableDialogs) {
7362 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
7363 /** FIXME: always true at the moment **/
7364 if(bEnableDialogs == FALSE) {
7365 FIXME("(%p) Dialogs cannot be disabled yet\n", This);
7371 HRESULT WINAPI IWineD3DDeviceImpl_GetCreationParameters(IWineD3DDevice *iface, WINED3DDEVICE_CREATION_PARAMETERS *pParameters) {
7372 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *) iface;
7373 TRACE("(%p) : pParameters %p\n", This, pParameters);
7375 *pParameters = This->createParms;
7379 void WINAPI IWineD3DDeviceImpl_SetGammaRamp(IWineD3DDevice * iface, UINT iSwapChain, DWORD Flags, CONST WINED3DGAMMARAMP* pRamp) {
7380 IWineD3DSwapChain *swapchain;
7381 HRESULT hrc = WINED3D_OK;
7383 TRACE("Relaying to swapchain\n");
7385 if ((hrc = IWineD3DDeviceImpl_GetSwapChain(iface, iSwapChain, &swapchain)) == WINED3D_OK) {
7386 IWineD3DSwapChain_SetGammaRamp(swapchain, Flags, (WINED3DGAMMARAMP *)pRamp);
7387 IWineD3DSwapChain_Release(swapchain);
7392 void WINAPI IWineD3DDeviceImpl_GetGammaRamp(IWineD3DDevice *iface, UINT iSwapChain, WINED3DGAMMARAMP* pRamp) {
7393 IWineD3DSwapChain *swapchain;
7394 HRESULT hrc = WINED3D_OK;
7396 TRACE("Relaying to swapchain\n");
7398 if ((hrc = IWineD3DDeviceImpl_GetSwapChain(iface, iSwapChain, &swapchain)) == WINED3D_OK) {
7399 hrc =IWineD3DSwapChain_GetGammaRamp(swapchain, pRamp);
7400 IWineD3DSwapChain_Release(swapchain);
7406 /** ********************************************************
7407 * Notification functions
7408 ** ********************************************************/
7409 /** This function must be called in the release of a resource when ref == 0,
7410 * the contents of resource must still be correct,
7411 * any handels to other resource held by the caller must be closed
7412 * (e.g. a texture should release all held surfaces because telling the device that it's been released.)
7413 *****************************************************/
7414 static void WINAPI IWineD3DDeviceImpl_AddResource(IWineD3DDevice *iface, IWineD3DResource *resource){
7415 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
7416 ResourceList* resourceList;
7418 TRACE("(%p) : resource %p\n", This, resource);
7420 EnterCriticalSection(&resourceStoreCriticalSection);
7422 /* add a new texture to the frot of the linked list */
7423 resourceList = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(ResourceList));
7424 resourceList->resource = resource;
7426 /* Get the old head */
7427 resourceList->next = This->resources;
7429 This->resources = resourceList;
7430 TRACE("Added resource %p with element %p pointing to %p\n", resource, resourceList, resourceList->next);
7433 LeaveCriticalSection(&resourceStoreCriticalSection);
7438 static void WINAPI IWineD3DDeviceImpl_RemoveResource(IWineD3DDevice *iface, IWineD3DResource *resource){
7439 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
7440 ResourceList* resourceList = NULL;
7441 ResourceList* previousResourceList = NULL;
7443 TRACE("(%p) : resource %p\n", This, resource);
7446 EnterCriticalSection(&resourceStoreCriticalSection);
7448 resourceList = This->resources;
7450 while (resourceList != NULL) {
7451 if(resourceList->resource == resource) break;
7452 previousResourceList = resourceList;
7453 resourceList = resourceList->next;
7456 if (resourceList == NULL) {
7457 FIXME("Attempted to remove resource %p that hasn't been stored\n", resource);
7459 LeaveCriticalSection(&resourceStoreCriticalSection);
7463 TRACE("Found resource %p with element %p pointing to %p (previous %p)\n", resourceList->resource, resourceList, resourceList->next, previousResourceList);
7465 /* make sure we don't leave a hole in the list */
7466 if (previousResourceList != NULL) {
7467 previousResourceList->next = resourceList->next;
7469 This->resources = resourceList->next;
7473 LeaveCriticalSection(&resourceStoreCriticalSection);
7479 void WINAPI IWineD3DDeviceImpl_ResourceReleased(IWineD3DDevice *iface, IWineD3DResource *resource){
7480 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *) iface;
7483 TRACE("(%p) : resource %p\n", This, resource);
7484 switch(IWineD3DResource_GetType(resource)){
7485 case WINED3DRTYPE_SURFACE:
7486 /* TODO: check front and back buffers, rendertargets etc.. possibly swapchains? */
7488 case WINED3DRTYPE_TEXTURE:
7489 case WINED3DRTYPE_CUBETEXTURE:
7490 case WINED3DRTYPE_VOLUMETEXTURE:
7491 for (counter = 0; counter < GL_LIMITS(textures); counter++) {
7492 if (This->stateBlock != NULL && This->stateBlock->textures[counter] == (IWineD3DBaseTexture *)resource) {
7493 WARN("Texture being released is still by a stateblock, Stage = %u Texture = %p\n", counter, resource);
7494 This->stateBlock->textures[counter] = NULL;
7496 if (This->updateStateBlock != This->stateBlock ){
7497 if (This->updateStateBlock->textures[counter] == (IWineD3DBaseTexture *)resource) {
7498 WARN("Texture being released is still by a stateblock, Stage = %u Texture = %p\n", counter, resource);
7499 This->updateStateBlock->textures[counter] = NULL;
7504 case WINED3DRTYPE_VOLUME:
7505 /* TODO: nothing really? */
7507 case WINED3DRTYPE_VERTEXBUFFER:
7508 /* MSDN: When an application no longer holds a references to this interface, the interface will automatically be freed. */
7511 TRACE("Cleaning up stream pointers\n");
7513 for(streamNumber = 0; streamNumber < MAX_STREAMS; streamNumber ++){
7514 /* FINDOUT: should a warn be generated if were recording and updateStateBlock->streamSource is lost?
7515 FINDOUT: should changes.streamSource[StreamNumber] be set ?
7517 if (This->updateStateBlock != NULL ) { /* ==NULL when device is being destroyed */
7518 if ((IWineD3DResource *)This->updateStateBlock->streamSource[streamNumber] == resource) {
7519 FIXME("Vertex buffer released whlst bound to a state block stream %d\n", streamNumber);
7520 This->updateStateBlock->streamSource[streamNumber] = 0;
7521 /* Set changed flag? */
7524 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) */
7525 if ((IWineD3DResource *)This->stateBlock->streamSource[streamNumber] == resource) {
7526 TRACE("Vertex buffer released whlst bound to a state block stream %d\n", streamNumber);
7527 This->stateBlock->streamSource[streamNumber] = 0;
7530 #if 0 /* TODO: Manage internal tracking properly so that 'this shouldn't happen' */
7531 else { /* This shouldn't happen */
7532 FIXME("Calling application has released the device before relasing all the resources bound to the device\n");
7539 case WINED3DRTYPE_INDEXBUFFER:
7540 /* MSDN: When an application no longer holds a references to this interface, the interface will automatically be freed.*/
7541 if (This->updateStateBlock != NULL ) { /* ==NULL when device is being destroyed */
7542 if (This->updateStateBlock->pIndexData == (IWineD3DIndexBuffer *)resource) {
7543 This->updateStateBlock->pIndexData = NULL;
7546 if (This->stateBlock != NULL ) { /* ==NULL when device is being destroyed */
7547 if (This->stateBlock->pIndexData == (IWineD3DIndexBuffer *)resource) {
7548 This->stateBlock->pIndexData = NULL;
7554 FIXME("(%p) unknown resource type %p %u\n", This, resource, IWineD3DResource_GetType(resource));
7559 /* Remove the resoruce from the resourceStore */
7560 IWineD3DDeviceImpl_RemoveResource(iface, resource);
7562 TRACE("Resource released\n");
7566 /**********************************************************
7567 * IWineD3DDevice VTbl follows
7568 **********************************************************/
7570 const IWineD3DDeviceVtbl IWineD3DDevice_Vtbl =
7572 /*** IUnknown methods ***/
7573 IWineD3DDeviceImpl_QueryInterface,
7574 IWineD3DDeviceImpl_AddRef,
7575 IWineD3DDeviceImpl_Release,
7576 /*** IWineD3DDevice methods ***/
7577 IWineD3DDeviceImpl_GetParent,
7578 /*** Creation methods**/
7579 IWineD3DDeviceImpl_CreateVertexBuffer,
7580 IWineD3DDeviceImpl_CreateIndexBuffer,
7581 IWineD3DDeviceImpl_CreateStateBlock,
7582 IWineD3DDeviceImpl_CreateSurface,
7583 IWineD3DDeviceImpl_CreateTexture,
7584 IWineD3DDeviceImpl_CreateVolumeTexture,
7585 IWineD3DDeviceImpl_CreateVolume,
7586 IWineD3DDeviceImpl_CreateCubeTexture,
7587 IWineD3DDeviceImpl_CreateQuery,
7588 IWineD3DDeviceImpl_CreateAdditionalSwapChain,
7589 IWineD3DDeviceImpl_CreateVertexDeclaration,
7590 IWineD3DDeviceImpl_CreateVertexShader,
7591 IWineD3DDeviceImpl_CreatePixelShader,
7592 IWineD3DDeviceImpl_CreatePalette,
7593 /*** Odd functions **/
7594 IWineD3DDeviceImpl_Init3D,
7595 IWineD3DDeviceImpl_Uninit3D,
7596 IWineD3DDeviceImpl_EnumDisplayModes,
7597 IWineD3DDeviceImpl_EvictManagedResources,
7598 IWineD3DDeviceImpl_GetAvailableTextureMem,
7599 IWineD3DDeviceImpl_GetBackBuffer,
7600 IWineD3DDeviceImpl_GetCreationParameters,
7601 IWineD3DDeviceImpl_GetDeviceCaps,
7602 IWineD3DDeviceImpl_GetDirect3D,
7603 IWineD3DDeviceImpl_GetDisplayMode,
7604 IWineD3DDeviceImpl_SetDisplayMode,
7605 IWineD3DDeviceImpl_GetHWND,
7606 IWineD3DDeviceImpl_SetHWND,
7607 IWineD3DDeviceImpl_GetNumberOfSwapChains,
7608 IWineD3DDeviceImpl_GetRasterStatus,
7609 IWineD3DDeviceImpl_GetSwapChain,
7610 IWineD3DDeviceImpl_Reset,
7611 IWineD3DDeviceImpl_SetDialogBoxMode,
7612 IWineD3DDeviceImpl_SetCursorProperties,
7613 IWineD3DDeviceImpl_SetCursorPosition,
7614 IWineD3DDeviceImpl_ShowCursor,
7615 IWineD3DDeviceImpl_TestCooperativeLevel,
7616 IWineD3DDeviceImpl_EnumZBufferFormats,
7617 IWineD3DDeviceImpl_EnumTextureFormats,
7618 /*** Getters and setters **/
7619 IWineD3DDeviceImpl_SetClipPlane,
7620 IWineD3DDeviceImpl_GetClipPlane,
7621 IWineD3DDeviceImpl_SetClipStatus,
7622 IWineD3DDeviceImpl_GetClipStatus,
7623 IWineD3DDeviceImpl_SetCurrentTexturePalette,
7624 IWineD3DDeviceImpl_GetCurrentTexturePalette,
7625 IWineD3DDeviceImpl_SetDepthStencilSurface,
7626 IWineD3DDeviceImpl_GetDepthStencilSurface,
7627 IWineD3DDeviceImpl_SetFVF,
7628 IWineD3DDeviceImpl_GetFVF,
7629 IWineD3DDeviceImpl_SetGammaRamp,
7630 IWineD3DDeviceImpl_GetGammaRamp,
7631 IWineD3DDeviceImpl_SetIndices,
7632 IWineD3DDeviceImpl_GetIndices,
7633 IWineD3DDeviceImpl_SetLight,
7634 IWineD3DDeviceImpl_GetLight,
7635 IWineD3DDeviceImpl_SetLightEnable,
7636 IWineD3DDeviceImpl_GetLightEnable,
7637 IWineD3DDeviceImpl_SetMaterial,
7638 IWineD3DDeviceImpl_GetMaterial,
7639 IWineD3DDeviceImpl_SetNPatchMode,
7640 IWineD3DDeviceImpl_GetNPatchMode,
7641 IWineD3DDeviceImpl_SetPaletteEntries,
7642 IWineD3DDeviceImpl_GetPaletteEntries,
7643 IWineD3DDeviceImpl_SetPixelShader,
7644 IWineD3DDeviceImpl_GetPixelShader,
7645 IWineD3DDeviceImpl_SetPixelShaderConstantB,
7646 IWineD3DDeviceImpl_GetPixelShaderConstantB,
7647 IWineD3DDeviceImpl_SetPixelShaderConstantI,
7648 IWineD3DDeviceImpl_GetPixelShaderConstantI,
7649 IWineD3DDeviceImpl_SetPixelShaderConstantF,
7650 IWineD3DDeviceImpl_GetPixelShaderConstantF,
7651 IWineD3DDeviceImpl_SetRenderState,
7652 IWineD3DDeviceImpl_GetRenderState,
7653 IWineD3DDeviceImpl_SetRenderTarget,
7654 IWineD3DDeviceImpl_GetRenderTarget,
7655 IWineD3DDeviceImpl_SetFrontBackBuffers,
7656 IWineD3DDeviceImpl_SetSamplerState,
7657 IWineD3DDeviceImpl_GetSamplerState,
7658 IWineD3DDeviceImpl_SetScissorRect,
7659 IWineD3DDeviceImpl_GetScissorRect,
7660 IWineD3DDeviceImpl_SetSoftwareVertexProcessing,
7661 IWineD3DDeviceImpl_GetSoftwareVertexProcessing,
7662 IWineD3DDeviceImpl_SetStreamSource,
7663 IWineD3DDeviceImpl_GetStreamSource,
7664 IWineD3DDeviceImpl_SetStreamSourceFreq,
7665 IWineD3DDeviceImpl_GetStreamSourceFreq,
7666 IWineD3DDeviceImpl_SetTexture,
7667 IWineD3DDeviceImpl_GetTexture,
7668 IWineD3DDeviceImpl_SetTextureStageState,
7669 IWineD3DDeviceImpl_GetTextureStageState,
7670 IWineD3DDeviceImpl_SetTransform,
7671 IWineD3DDeviceImpl_GetTransform,
7672 IWineD3DDeviceImpl_SetVertexDeclaration,
7673 IWineD3DDeviceImpl_GetVertexDeclaration,
7674 IWineD3DDeviceImpl_SetVertexShader,
7675 IWineD3DDeviceImpl_GetVertexShader,
7676 IWineD3DDeviceImpl_SetVertexShaderConstantB,
7677 IWineD3DDeviceImpl_GetVertexShaderConstantB,
7678 IWineD3DDeviceImpl_SetVertexShaderConstantI,
7679 IWineD3DDeviceImpl_GetVertexShaderConstantI,
7680 IWineD3DDeviceImpl_SetVertexShaderConstantF,
7681 IWineD3DDeviceImpl_GetVertexShaderConstantF,
7682 IWineD3DDeviceImpl_SetViewport,
7683 IWineD3DDeviceImpl_GetViewport,
7684 IWineD3DDeviceImpl_MultiplyTransform,
7685 IWineD3DDeviceImpl_ValidateDevice,
7686 IWineD3DDeviceImpl_ProcessVertices,
7687 /*** State block ***/
7688 IWineD3DDeviceImpl_BeginStateBlock,
7689 IWineD3DDeviceImpl_EndStateBlock,
7690 /*** Scene management ***/
7691 IWineD3DDeviceImpl_BeginScene,
7692 IWineD3DDeviceImpl_EndScene,
7693 IWineD3DDeviceImpl_Present,
7694 IWineD3DDeviceImpl_Clear,
7696 IWineD3DDeviceImpl_DrawPrimitive,
7697 IWineD3DDeviceImpl_DrawIndexedPrimitive,
7698 IWineD3DDeviceImpl_DrawPrimitiveUP,
7699 IWineD3DDeviceImpl_DrawIndexedPrimitiveUP,
7700 IWineD3DDeviceImpl_DrawPrimitiveStrided,
7701 IWineD3DDeviceImpl_DrawRectPatch,
7702 IWineD3DDeviceImpl_DrawTriPatch,
7703 IWineD3DDeviceImpl_DeletePatch,
7704 IWineD3DDeviceImpl_ColorFill,
7705 IWineD3DDeviceImpl_UpdateTexture,
7706 IWineD3DDeviceImpl_UpdateSurface,
7707 IWineD3DDeviceImpl_CopyRects,
7708 IWineD3DDeviceImpl_StretchRect,
7709 IWineD3DDeviceImpl_GetRenderTargetData,
7710 IWineD3DDeviceImpl_GetFrontBufferData,
7711 /*** Internal use IWineD3DDevice methods ***/
7712 IWineD3DDeviceImpl_SetupTextureStates,
7713 /*** object tracking ***/
7714 IWineD3DDeviceImpl_ResourceReleased
7718 const DWORD SavedPixelStates_R[NUM_SAVEDPIXELSTATES_R] = {
7719 WINED3DRS_ALPHABLENDENABLE ,
7720 WINED3DRS_ALPHAFUNC ,
7721 WINED3DRS_ALPHAREF ,
7722 WINED3DRS_ALPHATESTENABLE ,
7724 WINED3DRS_COLORWRITEENABLE ,
7725 WINED3DRS_DESTBLEND ,
7726 WINED3DRS_DITHERENABLE ,
7727 WINED3DRS_FILLMODE ,
7728 WINED3DRS_FOGDENSITY ,
7730 WINED3DRS_FOGSTART ,
7731 WINED3DRS_LASTPIXEL ,
7732 WINED3DRS_SHADEMODE ,
7733 WINED3DRS_SRCBLEND ,
7734 WINED3DRS_STENCILENABLE ,
7735 WINED3DRS_STENCILFAIL ,
7736 WINED3DRS_STENCILFUNC ,
7737 WINED3DRS_STENCILMASK ,
7738 WINED3DRS_STENCILPASS ,
7739 WINED3DRS_STENCILREF ,
7740 WINED3DRS_STENCILWRITEMASK ,
7741 WINED3DRS_STENCILZFAIL ,
7742 WINED3DRS_TEXTUREFACTOR ,
7753 WINED3DRS_ZWRITEENABLE
7756 const DWORD SavedPixelStates_T[NUM_SAVEDPIXELSTATES_T] = {
7757 WINED3DTSS_ADDRESSW ,
7758 WINED3DTSS_ALPHAARG0 ,
7759 WINED3DTSS_ALPHAARG1 ,
7760 WINED3DTSS_ALPHAARG2 ,
7761 WINED3DTSS_ALPHAOP ,
7762 WINED3DTSS_BUMPENVLOFFSET ,
7763 WINED3DTSS_BUMPENVLSCALE ,
7764 WINED3DTSS_BUMPENVMAT00 ,
7765 WINED3DTSS_BUMPENVMAT01 ,
7766 WINED3DTSS_BUMPENVMAT10 ,
7767 WINED3DTSS_BUMPENVMAT11 ,
7768 WINED3DTSS_COLORARG0 ,
7769 WINED3DTSS_COLORARG1 ,
7770 WINED3DTSS_COLORARG2 ,
7771 WINED3DTSS_COLOROP ,
7772 WINED3DTSS_RESULTARG ,
7773 WINED3DTSS_TEXCOORDINDEX ,
7774 WINED3DTSS_TEXTURETRANSFORMFLAGS
7777 const DWORD SavedPixelStates_S[NUM_SAVEDPIXELSTATES_S] = {
7778 WINED3DSAMP_ADDRESSU ,
7779 WINED3DSAMP_ADDRESSV ,
7780 WINED3DSAMP_ADDRESSW ,
7781 WINED3DSAMP_BORDERCOLOR ,
7782 WINED3DSAMP_MAGFILTER ,
7783 WINED3DSAMP_MINFILTER ,
7784 WINED3DSAMP_MIPFILTER ,
7785 WINED3DSAMP_MIPMAPLODBIAS ,
7786 WINED3DSAMP_MAXMIPLEVEL ,
7787 WINED3DSAMP_MAXANISOTROPY ,
7788 WINED3DSAMP_SRGBTEXTURE ,
7789 WINED3DSAMP_ELEMENTINDEX
7792 const DWORD SavedVertexStates_R[NUM_SAVEDVERTEXSTATES_R] = {
7794 WINED3DRS_AMBIENTMATERIALSOURCE ,
7795 WINED3DRS_CLIPPING ,
7796 WINED3DRS_CLIPPLANEENABLE ,
7797 WINED3DRS_COLORVERTEX ,
7798 WINED3DRS_DIFFUSEMATERIALSOURCE ,
7799 WINED3DRS_EMISSIVEMATERIALSOURCE ,
7800 WINED3DRS_FOGDENSITY ,
7802 WINED3DRS_FOGSTART ,
7803 WINED3DRS_FOGTABLEMODE ,
7804 WINED3DRS_FOGVERTEXMODE ,
7805 WINED3DRS_INDEXEDVERTEXBLENDENABLE ,
7806 WINED3DRS_LIGHTING ,
7807 WINED3DRS_LOCALVIEWER ,
7808 WINED3DRS_MULTISAMPLEANTIALIAS ,
7809 WINED3DRS_MULTISAMPLEMASK ,
7810 WINED3DRS_NORMALIZENORMALS ,
7811 WINED3DRS_PATCHEDGESTYLE ,
7812 WINED3DRS_POINTSCALE_A ,
7813 WINED3DRS_POINTSCALE_B ,
7814 WINED3DRS_POINTSCALE_C ,
7815 WINED3DRS_POINTSCALEENABLE ,
7816 WINED3DRS_POINTSIZE ,
7817 WINED3DRS_POINTSIZE_MAX ,
7818 WINED3DRS_POINTSIZE_MIN ,
7819 WINED3DRS_POINTSPRITEENABLE ,
7820 WINED3DRS_RANGEFOGENABLE ,
7821 WINED3DRS_SPECULARMATERIALSOURCE ,
7822 WINED3DRS_TWEENFACTOR ,
7823 WINED3DRS_VERTEXBLEND
7826 const DWORD SavedVertexStates_T[NUM_SAVEDVERTEXSTATES_T] = {
7827 WINED3DTSS_TEXCOORDINDEX ,
7828 WINED3DTSS_TEXTURETRANSFORMFLAGS
7831 const DWORD SavedVertexStates_S[NUM_SAVEDVERTEXSTATES_S] = {
7832 WINED3DSAMP_DMAPOFFSET