wined3d: Silence the offscreen surface creation fixme.
[wine/wine64.git] / dlls / wined3d / device.c
blobc473de7e853f32df8d2576b009098e3066ccf2be
1 /*
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
26 #include "config.h"
27 #ifdef HAVE_FLOAT_H
28 # include <float.h>
29 #endif
30 #include "wined3d_private.h"
32 WINE_DEFAULT_DEBUG_CHANNEL(d3d);
33 #define GLINFO_LOCATION ((IWineD3DImpl *)(This->wineD3D))->gl_info
35 /* x11drv GDI escapes */
36 #define X11DRV_ESCAPE 6789
37 enum x11drv_escape_codes
39 X11DRV_GET_DISPLAY, /* get X11 display for a DC */
40 X11DRV_GET_DRAWABLE, /* get current drawable for a DC */
41 X11DRV_GET_FONT, /* get current X font for a DC */
44 /* retrieve the X display to use on a given DC */
45 inline static Display *get_display( HDC hdc )
47 Display *display;
48 enum x11drv_escape_codes escape = X11DRV_GET_DISPLAY;
50 if (!ExtEscape( hdc, X11DRV_ESCAPE, sizeof(escape), (LPCSTR)&escape,
51 sizeof(display), (LPSTR)&display )) display = NULL;
52 return display;
55 /* Memory tracking and object counting */
56 static unsigned int emulated_textureram = 64*1024*1024;
58 /* TODO: setup some flags in the regestry to enable, disable pbuffer support */
59 /* enable pbuffer support for offscreen textures */
60 BOOL pbuffer_support = FALSE;
61 /* allocate one pbuffer per surface */
62 BOOL pbuffer_per_surface = FALSE;
64 /* static function declarations */
65 static void WINAPI IWineD3DDeviceImpl_AddResource(IWineD3DDevice *iface, IWineD3DResource *resource);
67 static void WINAPI IWineD3DDeviceImpl_ApplyTextureUnitState(IWineD3DDevice *iface, DWORD Stage, WINED3DTEXTURESTAGESTATETYPE Type);
69 /* helper macros */
70 #define D3DMEMCHECK(object, ppResult) if(NULL == object) { *ppResult = NULL; WARN("Out of memory\n"); return WINED3DERR_OUTOFVIDEOMEMORY;}
72 #define D3DCREATEOBJECTINSTANCE(object, type) { \
73 object=HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(IWineD3D##type##Impl)); \
74 D3DMEMCHECK(object, pp##type); \
75 object->lpVtbl = &IWineD3D##type##_Vtbl; \
76 object->wineD3DDevice = This; \
77 object->parent = parent; \
78 object->ref = 1; \
79 *pp##type = (IWineD3D##type *) object; \
82 #define D3DCREATERESOURCEOBJECTINSTANCE(object, type, d3dtype, _size){ \
83 object=HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(IWineD3D##type##Impl)); \
84 D3DMEMCHECK(object, pp##type); \
85 object->lpVtbl = &IWineD3D##type##_Vtbl; \
86 object->resource.wineD3DDevice = This; \
87 object->resource.parent = parent; \
88 object->resource.resourceType = d3dtype; \
89 object->resource.ref = 1; \
90 object->resource.pool = Pool; \
91 object->resource.format = Format; \
92 object->resource.usage = Usage; \
93 object->resource.size = _size; \
94 /* Check that we have enough video ram left */ \
95 if (Pool == WINED3DPOOL_DEFAULT) { \
96 if (IWineD3DDevice_GetAvailableTextureMem(iface) <= _size) { \
97 WARN("Out of 'bogus' video memory\n"); \
98 HeapFree(GetProcessHeap(), 0, object); \
99 *pp##type = NULL; \
100 return WINED3DERR_OUTOFVIDEOMEMORY; \
102 globalChangeGlRam(_size); \
104 object->resource.allocatedMemory = (0 == _size ? NULL : Pool == WINED3DPOOL_DEFAULT ? NULL : HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, _size)); \
105 if (object->resource.allocatedMemory == NULL && _size != 0 && Pool != WINED3DPOOL_DEFAULT) { \
106 FIXME("Out of memory!\n"); \
107 HeapFree(GetProcessHeap(), 0, object); \
108 *pp##type = NULL; \
109 return WINED3DERR_OUTOFVIDEOMEMORY; \
111 *pp##type = (IWineD3D##type *) object; \
112 IWineD3DDeviceImpl_AddResource(iface, (IWineD3DResource *)object) ;\
113 TRACE("(%p) : Created resource %p\n", This, object); \
116 #define D3DINITIALIZEBASETEXTURE(_basetexture) { \
117 _basetexture.levels = Levels; \
118 _basetexture.filterType = (Usage & WINED3DUSAGE_AUTOGENMIPMAP) ? WINED3DTEXF_LINEAR : WINED3DTEXF_NONE; \
119 _basetexture.LOD = 0; \
120 _basetexture.dirty = TRUE; \
123 /**********************************************************
124 * Global variable / Constants follow
125 **********************************************************/
126 const float identity[16] = {1,0,0,0, 0,1,0,0, 0,0,1,0, 0,0,0,1}; /* When needed for comparisons */
128 /**********************************************************
129 * Utility functions follow
130 **********************************************************/
131 /* Convert the D3DLIGHT properties into equivalent gl lights */
132 static void setup_light(IWineD3DDevice *iface, LONG Index, PLIGHTINFOEL *lightInfo) {
134 float quad_att;
135 float colRGBA[] = {0.0, 0.0, 0.0, 0.0};
136 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
138 /* Light settings are affected by the model view in OpenGL, the View transform in direct3d*/
139 glMatrixMode(GL_MODELVIEW);
140 glPushMatrix();
141 glLoadMatrixf((float *)&This->stateBlock->transforms[D3DTS_VIEW].u.m[0][0]);
143 /* Diffuse: */
144 colRGBA[0] = lightInfo->OriginalParms.Diffuse.r;
145 colRGBA[1] = lightInfo->OriginalParms.Diffuse.g;
146 colRGBA[2] = lightInfo->OriginalParms.Diffuse.b;
147 colRGBA[3] = lightInfo->OriginalParms.Diffuse.a;
148 glLightfv(GL_LIGHT0+Index, GL_DIFFUSE, colRGBA);
149 checkGLcall("glLightfv");
151 /* Specular */
152 colRGBA[0] = lightInfo->OriginalParms.Specular.r;
153 colRGBA[1] = lightInfo->OriginalParms.Specular.g;
154 colRGBA[2] = lightInfo->OriginalParms.Specular.b;
155 colRGBA[3] = lightInfo->OriginalParms.Specular.a;
156 glLightfv(GL_LIGHT0+Index, GL_SPECULAR, colRGBA);
157 checkGLcall("glLightfv");
159 /* Ambient */
160 colRGBA[0] = lightInfo->OriginalParms.Ambient.r;
161 colRGBA[1] = lightInfo->OriginalParms.Ambient.g;
162 colRGBA[2] = lightInfo->OriginalParms.Ambient.b;
163 colRGBA[3] = lightInfo->OriginalParms.Ambient.a;
164 glLightfv(GL_LIGHT0+Index, GL_AMBIENT, colRGBA);
165 checkGLcall("glLightfv");
167 /* Attenuation - Are these right? guessing... */
168 glLightf(GL_LIGHT0+Index, GL_CONSTANT_ATTENUATION, lightInfo->OriginalParms.Attenuation0);
169 checkGLcall("glLightf");
170 glLightf(GL_LIGHT0+Index, GL_LINEAR_ATTENUATION, lightInfo->OriginalParms.Attenuation1);
171 checkGLcall("glLightf");
173 if ((lightInfo->OriginalParms.Range *lightInfo->OriginalParms.Range) >= FLT_MIN) {
174 quad_att = 1.4/(lightInfo->OriginalParms.Range *lightInfo->OriginalParms.Range);
175 } else {
176 quad_att = 0; /* 0 or MAX? (0 seems to be ok) */
179 if (quad_att < lightInfo->OriginalParms.Attenuation2) quad_att = lightInfo->OriginalParms.Attenuation2;
180 glLightf(GL_LIGHT0+Index, GL_QUADRATIC_ATTENUATION, quad_att);
181 checkGLcall("glLightf");
183 switch (lightInfo->OriginalParms.Type) {
184 case D3DLIGHT_POINT:
185 /* Position */
186 glLightfv(GL_LIGHT0+Index, GL_POSITION, &lightInfo->lightPosn[0]);
187 checkGLcall("glLightfv");
188 glLightf(GL_LIGHT0 + Index, GL_SPOT_CUTOFF, lightInfo->cutoff);
189 checkGLcall("glLightf");
190 /* FIXME: Range */
191 break;
193 case D3DLIGHT_SPOT:
194 /* Position */
195 glLightfv(GL_LIGHT0+Index, GL_POSITION, &lightInfo->lightPosn[0]);
196 checkGLcall("glLightfv");
197 /* Direction */
198 glLightfv(GL_LIGHT0+Index, GL_SPOT_DIRECTION, &lightInfo->lightDirn[0]);
199 checkGLcall("glLightfv");
200 glLightf(GL_LIGHT0 + Index, GL_SPOT_EXPONENT, lightInfo->exponent);
201 checkGLcall("glLightf");
202 glLightf(GL_LIGHT0 + Index, GL_SPOT_CUTOFF, lightInfo->cutoff);
203 checkGLcall("glLightf");
204 /* FIXME: Range */
205 break;
207 case D3DLIGHT_DIRECTIONAL:
208 /* Direction */
209 glLightfv(GL_LIGHT0+Index, GL_POSITION, &lightInfo->lightPosn[0]); /* Note gl uses w position of 0 for direction! */
210 checkGLcall("glLightfv");
211 glLightf(GL_LIGHT0+Index, GL_SPOT_CUTOFF, lightInfo->cutoff);
212 checkGLcall("glLightf");
213 glLightf(GL_LIGHT0+Index, GL_SPOT_EXPONENT, 0.0f);
214 checkGLcall("glLightf");
215 break;
217 default:
218 FIXME("Unrecognized light type %d\n", lightInfo->OriginalParms.Type);
221 /* Restore the modelview matrix */
222 glPopMatrix();
225 /* Apply the current values to the specified texture stage */
226 void WINAPI IWineD3DDeviceImpl_SetupTextureStates(IWineD3DDevice *iface, DWORD Sampler, DWORD Flags) {
227 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
228 float col[4];
230 union {
231 float f;
232 DWORD d;
233 } tmpvalue;
235 /* In addition, IDirect3DDevice9::SetSamplerState will now be used for filtering, tiling,
236 clamping, MIPLOD, etc. This will work for up to 16 samplers.
239 if (Sampler >= GL_LIMITS(samplers)) {
240 FIXME("Trying to set the state of more samplers %ld than are supported %d by this openGL implementation\n", Sampler, GL_LIMITS(samplers));
241 return;
243 VTRACE(("Activating appropriate texture state %ld\n", Sampler));
244 if (GL_SUPPORT(ARB_MULTITEXTURE)) {
245 ENTER_GL();
246 GLACTIVETEXTURE(Sampler);
247 LEAVE_GL();
248 /* Could we use bindTexture and then apply the states instead of GLACTIVETEXTURE */
249 } else if (Sampler > 0) {
250 FIXME("Program using multiple concurrent textures which this opengl implementation doesn't support\n");
251 return;
254 /* TODO: change this to a lookup table
255 LOOKUP_TEXTURE_STATES lists all texture states that should be applied.
256 LOOKUP_CONTEXT_SATES list all context applicable states that can be applied
257 etc.... it's a lot cleaner, quicker and possibly easier to maintain than running a switch and setting a skip flag...
258 especially when there are a number of groups of states. */
260 TRACE("-----------------------> Updating the texture at Sampler %ld to have new texture state information\n", Sampler);
262 /* 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 */
263 #define APPLY_STATE(_state) IWineD3DDeviceImpl_ApplyTextureUnitState(iface, Sampler, _state)
264 /* these are the only two supported states that need to be applied */
265 APPLY_STATE(WINED3DTSS_TEXCOORDINDEX);
266 APPLY_STATE(WINED3DTSS_TEXTURETRANSFORMFLAGS);
267 #if 0 /* not supported at the moment */
268 APPLY_STATE(WINED3DTSS_BUMPENVMAT00);
269 APPLY_STATE(WINED3DTSS_BUMPENVMAT01);
270 APPLY_STATE(WINED3DTSS_BUMPENVMAT10);
271 APPLY_STATE(WINED3DTSS_BUMPENVMAT11);
272 APPLY_STATE(WINED3DTSS_BUMPENVLSCALE);
273 APPLY_STATE(WINED3DTSS_BUMPENVLOFFSET);
274 APPLY_STATE(WINED3DTSS_RESULTARG);
275 APPLY_STATE(WINED3DTSS_CONSTANT);
276 #endif
277 /* a quick sanity check in case someone forgot to update this function */
278 if (WINED3D_HIGHEST_TEXTURE_STATE > WINED3DTSS_CONSTANT) {
279 FIXME("(%p) : There are more texture states than expected, update device.c to match\n", This);
281 #undef APPLY_STATE
283 /* apply any sampler states that always need applying */
284 if (GL_SUPPORT(EXT_TEXTURE_LOD_BIAS)) {
285 tmpvalue.d = This->stateBlock->samplerState[Sampler][WINED3DSAMP_MIPMAPLODBIAS];
286 glTexEnvf(GL_TEXTURE_FILTER_CONTROL_EXT,
287 GL_TEXTURE_LOD_BIAS_EXT,
288 tmpvalue.f);
289 checkGLcall("glTexEnvi GL_TEXTURE_LOD_BIAS_EXT ...");
292 /* Note the D3DRS value applies to all textures, but GL has one
293 * per texture, so apply it now ready to be used!
295 D3DCOLORTOGLFLOAT4(This->stateBlock->renderState[WINED3DRS_TEXTUREFACTOR], col);
296 /* Set the default alpha blend color */
297 if (GL_SUPPORT(ARB_IMAGING)) {
298 GL_EXTCALL(glBlendColor(col[0], col[1], col[2], col[3]));
299 checkGLcall("glBlendColor");
300 } else {
301 WARN("Unsupported in local OpenGL implementation: glBlendColor\n");
304 D3DCOLORTOGLFLOAT4(This->stateBlock->renderState[WINED3DRS_TEXTUREFACTOR], col);
305 glTexEnvfv(GL_TEXTURE_ENV, GL_TEXTURE_ENV_COLOR, &col[0]);
306 checkGLcall("glTexEnvfv(GL_TEXTURE_ENV, GL_TEXTURE_ENV_COLOR, color);");
308 /* TODO: NV_POINT_SPRITE */
309 if (GL_SUPPORT(ARB_POINT_SPRITE)) {
310 if (This->stateBlock->renderState[WINED3DRS_POINTSPRITEENABLE] != FALSE) {
311 /* Doesn't work with GL_POINT_SMOOTH on on my ATI 9600, but then ATI drivers are buggered! */
312 glDisable(GL_POINT_SMOOTH);
314 /* Centre the texture on the vertex */
315 VTRACE(("glTexEnvf( GL_POINT_SPRITE_ARB, GL_COORD_REPLACE_ARB, GL_TRUE)\n"));
316 glTexEnvf( GL_POINT_SPRITE_ARB, GL_COORD_REPLACE_ARB, GL_TRUE);
318 VTRACE(("glTexEnvf( GL_POINT_SPRITE_ARB, GL_COORD_REPLACE_ARB, GL_TRUE)\n"));
319 glTexEnvf( GL_POINT_SPRITE_ARB, GL_COORD_REPLACE_ARB, GL_TRUE);
320 checkGLcall("glTexEnvf(...)");
321 VTRACE(("glEnable( GL_POINT_SPRITE_ARB )\n"));
322 glEnable( GL_POINT_SPRITE_ARB );
323 checkGLcall("glEnable(...)");
324 } else {
325 VTRACE(("glDisable( GL_POINT_SPRITE_ARB )\n"));
326 glDisable( GL_POINT_SPRITE_ARB );
327 checkGLcall("glEnable(...)");
331 TRACE("-----------------------> Updated the texture at Sampler %ld to have new texture state information\n", Sampler);
334 /**********************************************************
335 * IUnknown parts follows
336 **********************************************************/
338 HRESULT WINAPI IWineD3DDeviceImpl_QueryInterface(IWineD3DDevice *iface,REFIID riid,LPVOID *ppobj)
340 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
342 TRACE("(%p)->(%s,%p)\n",This,debugstr_guid(riid),ppobj);
343 if (IsEqualGUID(riid, &IID_IUnknown)
344 || IsEqualGUID(riid, &IID_IWineD3DBase)
345 || IsEqualGUID(riid, &IID_IWineD3DDevice)) {
346 IUnknown_AddRef(iface);
347 *ppobj = This;
348 return S_OK;
350 *ppobj = NULL;
351 return E_NOINTERFACE;
354 ULONG WINAPI IWineD3DDeviceImpl_AddRef(IWineD3DDevice *iface) {
355 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
356 ULONG refCount = InterlockedIncrement(&This->ref);
358 TRACE("(%p) : AddRef increasing from %ld\n", This, refCount - 1);
359 return refCount;
362 ULONG WINAPI IWineD3DDeviceImpl_Release(IWineD3DDevice *iface) {
363 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
364 ULONG refCount = InterlockedDecrement(&This->ref);
366 TRACE("(%p) : Releasing from %ld\n", This, refCount + 1);
368 if (!refCount) {
369 /* TODO: Clean up all the surfaces and textures! */
370 /* NOTE: You must release the parent if the object was created via a callback
371 ** ***************************/
373 /* Release the update stateblock */
374 if(IWineD3DStateBlock_Release((IWineD3DStateBlock *)This->updateStateBlock) > 0){
375 if(This->updateStateBlock != This->stateBlock)
376 FIXME("(%p) Something's still holding the Update stateblock\n",This);
378 This->updateStateBlock = NULL;
379 { /* because were not doing proper internal refcounts releasing the primary state block
380 causes recursion with the extra checks in ResourceReleased, to avoid this we have
381 to set this->stateBlock = NULL; first */
382 IWineD3DStateBlock *stateBlock = (IWineD3DStateBlock *)This->stateBlock;
383 This->stateBlock = NULL;
385 /* Release the stateblock */
386 if(IWineD3DStateBlock_Release(stateBlock) > 0){
387 FIXME("(%p) Something's still holding the Update stateblock\n",This);
391 if (This->resources != NULL ) {
392 FIXME("(%p) Device released with resources still bound, acceptable but unexpected\n", This);
393 dumpResources(This->resources);
397 IWineD3D_Release(This->wineD3D);
398 This->wineD3D = NULL;
399 HeapFree(GetProcessHeap(), 0, This);
400 TRACE("Freed device %p\n", This);
401 This = NULL;
403 return refCount;
406 /**********************************************************
407 * IWineD3DDevice implementation follows
408 **********************************************************/
409 HRESULT WINAPI IWineD3DDeviceImpl_GetParent(IWineD3DDevice *iface, IUnknown **pParent) {
410 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
411 *pParent = This->parent;
412 IUnknown_AddRef(This->parent);
413 return WINED3D_OK;
416 HRESULT WINAPI IWineD3DDeviceImpl_CreateVertexBuffer(IWineD3DDevice *iface, UINT Size, DWORD Usage,
417 DWORD FVF, WINED3DPOOL Pool, IWineD3DVertexBuffer** ppVertexBuffer, HANDLE *sharedHandle,
418 IUnknown *parent) {
419 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
420 IWineD3DVertexBufferImpl *object;
421 WINED3DFORMAT Format = WINED3DFMT_VERTEXDATA; /* Dummy format for now */
422 D3DCREATERESOURCEOBJECTINSTANCE(object, VertexBuffer, WINED3DRTYPE_VERTEXBUFFER, Size)
424 /*TODO: use VBO's */
425 if (Pool == WINED3DPOOL_DEFAULT ) { /* Allocate some system memory for now */
426 object->resource.allocatedMemory = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, object->resource.size);
428 object->fvf = FVF;
430 TRACE("(%p) : Size=%d, Usage=%ld, FVF=%lx, Pool=%d - Memory@%p, Iface@%p\n", This, Size, Usage, FVF, Pool, object->resource.allocatedMemory, object);
431 *ppVertexBuffer = (IWineD3DVertexBuffer *)object;
433 return WINED3D_OK;
436 HRESULT WINAPI IWineD3DDeviceImpl_CreateIndexBuffer(IWineD3DDevice *iface, UINT Length, DWORD Usage,
437 WINED3DFORMAT Format, WINED3DPOOL Pool, IWineD3DIndexBuffer** ppIndexBuffer,
438 HANDLE *sharedHandle, IUnknown *parent) {
439 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
440 IWineD3DIndexBufferImpl *object;
441 TRACE("(%p) Creating index buffer\n", This);
443 /* Allocate the storage for the device */
444 D3DCREATERESOURCEOBJECTINSTANCE(object,IndexBuffer,WINED3DRTYPE_INDEXBUFFER, Length)
446 /*TODO: use VBO's */
447 if (Pool == WINED3DPOOL_DEFAULT ) { /* Allocate some system memory for now */
448 object->resource.allocatedMemory = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,object->resource.size);
451 TRACE("(%p) : Len=%d, Use=%lx, Format=(%u,%s), Pool=%d - Memory@%p, Iface@%p\n", This, Length, Usage, Format,
452 debug_d3dformat(Format), Pool, object, object->resource.allocatedMemory);
453 *ppIndexBuffer = (IWineD3DIndexBuffer *) object;
455 return WINED3D_OK;
458 HRESULT WINAPI IWineD3DDeviceImpl_CreateStateBlock(IWineD3DDevice* iface, WINED3DSTATEBLOCKTYPE Type, IWineD3DStateBlock** ppStateBlock, IUnknown *parent) {
460 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
461 IWineD3DStateBlockImpl *object;
462 int i, j;
464 D3DCREATEOBJECTINSTANCE(object, StateBlock)
465 object->blockType = Type;
467 /* Special case - Used during initialization to produce a placeholder stateblock
468 so other functions called can update a state block */
469 if (Type == WINED3DSBT_INIT) {
470 /* Don't bother increasing the reference count otherwise a device will never
471 be freed due to circular dependencies */
472 return WINED3D_OK;
475 /* Otherwise, might as well set the whole state block to the appropriate values */
476 if ( This->stateBlock != NULL) {
477 memcpy(object, This->stateBlock, sizeof(IWineD3DStateBlockImpl));
478 } else {
479 memset(object->streamFreq, 1, sizeof(object->streamFreq));
482 /* Reset the ref and type after kludging it */
483 object->wineD3DDevice = This;
484 object->ref = 1;
485 object->blockType = Type;
487 TRACE("Updating changed flags appropriate for type %d\n", Type);
489 if (Type == WINED3DSBT_ALL) {
491 TRACE("ALL => Pretend everything has changed\n");
492 memset(&object->changed, TRUE, sizeof(This->stateBlock->changed));
493 } else if (Type == WINED3DSBT_PIXELSTATE) {
495 TRACE("PIXELSTATE => Pretend all pixel shates have changed\n");
496 memset(&object->changed, FALSE, sizeof(This->stateBlock->changed));
498 object->changed.pixelShader = TRUE;
500 /* Pixel Shader Constants */
501 for (i = 0; i < MAX_PSHADER_CONSTANTS; ++i) {
502 object->changed.pixelShaderConstants[i] = TRUE;
504 for (i = 0; i < NUM_SAVEDPIXELSTATES_R; i++) {
505 object->changed.renderState[SavedPixelStates_R[i]] = TRUE;
507 for (j = 0; j < GL_LIMITS(textures); j++) {
508 for (i = 0; i < NUM_SAVEDPIXELSTATES_T; i++) {
509 object->changed.textureState[j][SavedPixelStates_T[i]] = TRUE;
512 for (j = 0 ; j < 16; j++) {
513 for (i =0; i < NUM_SAVEDPIXELSTATES_S;i++) {
515 object->changed.samplerState[j][SavedPixelStates_S[i]] = TRUE;
519 } else if (Type == WINED3DSBT_VERTEXSTATE) {
521 TRACE("VERTEXSTATE => Pretend all vertex shates have changed\n");
522 memset(&object->changed, FALSE, sizeof(This->stateBlock->changed));
524 object->changed.vertexShader = TRUE;
526 /* Vertex Shader Constants */
527 for (i = 0; i < MAX_VSHADER_CONSTANTS; ++i) {
528 object->changed.vertexShaderConstants[i] = TRUE;
530 for (i = 0; i < NUM_SAVEDVERTEXSTATES_R; i++) {
531 object->changed.renderState[SavedVertexStates_R[i]] = TRUE;
533 for (j = 0; j < GL_LIMITS(textures); j++) {
534 for (i = 0; i < NUM_SAVEDVERTEXSTATES_T; i++) {
535 object->changed.textureState[j][SavedVertexStates_T[i]] = TRUE;
538 for (j = 0 ; j < 16; j++){
539 for (i =0; i < NUM_SAVEDVERTEXSTATES_S;i++) {
540 object->changed.samplerState[j][SavedVertexStates_S[i]] = TRUE;
544 /* Duplicate light chain */
546 PLIGHTINFOEL *src = NULL;
547 PLIGHTINFOEL *dst = NULL;
548 PLIGHTINFOEL *newEl = NULL;
549 src = This->stateBlock->lights;
550 object->lights = NULL;
553 while (src) {
554 newEl = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(PLIGHTINFOEL));
555 if (newEl == NULL) return WINED3DERR_OUTOFVIDEOMEMORY;
556 memcpy(newEl, src, sizeof(PLIGHTINFOEL));
557 newEl->prev = dst;
558 newEl->changed = TRUE;
559 newEl->enabledChanged = TRUE;
560 if (dst == NULL) {
561 object->lights = newEl;
562 } else {
563 dst->next = newEl;
565 dst = newEl;
566 src = src->next;
571 } else {
572 FIXME("Unrecognized state block type %d\n", Type);
575 TRACE("(%p) returning token (ptr to stateblock) of %p\n", This, object);
576 return WINED3D_OK;
580 /* ************************************
581 MSDN:
582 [in] Render targets are not lockable unless the application specifies TRUE for Lockable. Note that lockable render targets reduce performance on some graphics hardware.
584 Discard
585 [in] Set this flag to TRUE to enable z-buffer discarding, and FALSE otherwise.
587 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.
589 ******************************** */
591 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) {
592 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
593 IWineD3DSurfaceImpl *object; /*NOTE: impl ref allowed since this is a create function */
594 unsigned int pow2Width, pow2Height;
595 unsigned int Size = 1;
596 TRACE("(%p) Create surface\n",This);
598 /** FIXME: Check ranges on the inputs are valid
599 * MSDN
600 * MultisampleQuality
601 * [in] Quality level. The valid range is between zero and one less than the level
602 * returned by pQualityLevels used by IDirect3D9::CheckDeviceMultiSampleType.
603 * Passing a larger value returns the error WINED3DERR_INVALIDCALL. The MultisampleQuality
604 * values of paired render targets, depth stencil surfaces, and the MultiSample type
605 * must all match.
606 *******************************/
610 * TODO: Discard MSDN
611 * [in] Set this flag to TRUE to enable z-buffer discarding, and FALSE otherwise.
613 * If this flag is set, the contents of the depth stencil buffer will be
614 * invalid after calling either IDirect3DDevice9::Present or * IDirect3DDevice9::SetDepthStencilSurface
615 * with a different depth surface.
617 *This flag has the same behavior as the constant, D3DPRESENTFLAG_DISCARD_DEPTHSTENCIL, in D3DPRESENTFLAG.
618 ***************************/
620 if(MultisampleQuality < 0) {
621 FIXME("Invalid multisample level %ld\n", MultisampleQuality);
622 return WINED3DERR_INVALIDCALL; /* TODO: Check that this is the case! */
625 if(MultisampleQuality > 0) {
626 FIXME("MultisampleQuality set to %ld, substituting 0\n", MultisampleQuality);
627 MultisampleQuality=0;
630 /** FIXME: Check that the format is supported
631 * by the device.
632 *******************************/
634 /* Non-power2 support */
636 /* Find the nearest pow2 match */
637 pow2Width = pow2Height = 1;
638 while (pow2Width < Width) pow2Width <<= 1;
639 while (pow2Height < Height) pow2Height <<= 1;
641 if (pow2Width > Width || pow2Height > Height) {
642 /** TODO: add support for non power two compressed textures (OpenGL 2 provices support for * non-power-two textures gratis) **/
643 if (Format == WINED3DFMT_DXT1 || Format == WINED3DFMT_DXT2 || Format == WINED3DFMT_DXT3
644 || Format == WINED3DFMT_DXT4 || Format == WINED3DFMT_DXT5) {
645 FIXME("(%p) Compressed non-power-two textures are not supported w(%d) h(%d)\n",
646 This, Width, Height);
647 return WINED3DERR_NOTAVAILABLE;
651 /** DXTn mipmaps use the same number of 'levels' down to eg. 8x1, but since
652 * it is based around 4x4 pixel blocks it requires padding, so allocate enough
653 * space!
654 *********************************/
655 if (WINED3DFMT_UNKNOWN == Format) {
656 Size = 0;
657 } else if (Format == WINED3DFMT_DXT1) {
658 /* DXT1 is half byte per pixel */
659 Size = ((max(pow2Width,4) * D3DFmtGetBpp(This, Format)) * max(pow2Height,4)) >> 1;
661 } else if (Format == WINED3DFMT_DXT2 || Format == WINED3DFMT_DXT3 ||
662 Format == WINED3DFMT_DXT4 || Format == WINED3DFMT_DXT5) {
663 Size = ((max(pow2Width,4) * D3DFmtGetBpp(This, Format)) * max(pow2Height,4));
664 } else {
665 Size = (pow2Width * D3DFmtGetBpp(This, Format)) * pow2Height;
668 /** Create and initialise the surface resource **/
669 D3DCREATERESOURCEOBJECTINSTANCE(object,Surface,WINED3DRTYPE_SURFACE, Size)
670 /* "Standalone" surface */
671 IWineD3DSurface_SetContainer((IWineD3DSurface *)object, NULL);
673 object->currentDesc.Width = Width;
674 object->currentDesc.Height = Height;
675 object->currentDesc.MultiSampleType = MultiSample;
676 object->currentDesc.MultiSampleQuality = MultisampleQuality;
678 /* Setup some glformat defaults */
679 if (WINED3DFMT_UNKNOWN != Format) {
680 object->glDescription.glFormat = D3DFmt2GLFmt(This, object->resource.format);
681 object->glDescription.glFormatInternal = D3DFmt2GLIntFmt(This, object->resource.format);
682 object->glDescription.glType = D3DFmt2GLType(This, object->resource.format);
683 } else {
684 object->glDescription.glFormat = 0;
685 object->glDescription.glFormatInternal = 0;
686 object->glDescription.glType = 0;
689 object->glDescription.textureName = 0;
690 object->glDescription.level = Level;
691 object->glDescription.target = GL_TEXTURE_2D;
693 /* Internal data */
694 object->pow2Width = pow2Width;
695 object->pow2Height = pow2Height;
697 /* Flags */
698 object->Flags = 0; /* We start without flags set */
699 object->Flags |= (pow2Width != Width || pow2Height != Height) ? SFLAG_NONPOW2 : 0;
700 object->Flags |= Discard ? SFLAG_DISCARD : 0;
701 object->Flags |= (WINED3DFMT_D16_LOCKABLE == Format) ? SFLAG_LOCKABLE : 0;
702 object->Flags |= Lockable ? SFLAG_LOCKABLE : 0;
705 if (WINED3DFMT_UNKNOWN != Format) {
706 object->bytesPerPixel = D3DFmtGetBpp(This, Format);
707 object->pow2Size = (pow2Width * object->bytesPerPixel) * pow2Height;
708 } else {
709 object->bytesPerPixel = 0;
710 object->pow2Size = 0;
713 /** TODO: change this into a texture transform matrix so that it's processed in hardware **/
715 TRACE("Pool %d %d %d %d",Pool, WINED3DPOOL_DEFAULT, WINED3DPOOL_MANAGED, WINED3DPOOL_SYSTEMMEM);
717 /** Quick lockable sanity check TODO: remove this after surfaces, usage and locablility have been debugged properly
718 * this function is too deap to need to care about things like this.
719 * Levels need to be checked too, and possibly Type wince they all affect what can be done.
720 * ****************************************/
721 switch(Pool) {
722 case WINED3DPOOL_SCRATCH:
723 if(Lockable == FALSE)
724 FIXME("Create suface called with a pool of SCRATCH and a Lockable of FALSE \
725 which are mutually exclusive, setting lockable to true\n");
726 Lockable = TRUE;
727 break;
728 case WINED3DPOOL_SYSTEMMEM:
729 if(Lockable == FALSE) FIXME("Create surface called with a pool of SYSTEMMEM and a Lockable of FALSE, \
730 this is acceptable but unexpected (I can't know how the surface can be usable!)\n");
731 case WINED3DPOOL_MANAGED:
732 if(Usage == WINED3DUSAGE_DYNAMIC) FIXME("Create surface called with a pool of MANAGED and a \
733 Usage of DYNAMIC which are mutually exclusive, not doing \
734 anything just telling you.\n");
735 break;
736 case WINED3DPOOL_DEFAULT: /*TODO: Create offscreen plain can cause this check to fail..., find out if it should */
737 if(!(Usage & WINED3DUSAGE_DYNAMIC) && !(Usage & WINED3DUSAGE_RENDERTARGET)
738 && !(Usage && WINED3DUSAGE_DEPTHSTENCIL ) && Lockable)
739 WARN("Creating a surface with a POOL of DEFAULT with Lockable true, that doesn't specify DYNAMIC usage.\n");
740 break;
741 default:
742 FIXME("(%p) Unknown pool %d\n", This, Pool);
743 break;
746 if (Usage & WINED3DUSAGE_RENDERTARGET && Pool != WINED3DPOOL_DEFAULT) {
747 FIXME("Trying to create a render target that isn't in the default pool\n");
750 /* mark the texture as dirty so that it get's loaded first time around*/
751 IWineD3DSurface_AddDirtyRect(*ppSurface, NULL);
752 TRACE("(%p) : w(%d) h(%d) fmt(%d,%s) lockable(%d) surf@%p, surfmem@%p, %d bytes\n",
753 This, Width, Height, Format, debug_d3dformat(Format),
754 (WINED3DFMT_D16_LOCKABLE == Format), *ppSurface, object->resource.allocatedMemory, object->resource.size);
756 /* Store the DirectDraw primary surface. This is the first rendertarget surface created */
757 if( (Usage & WINED3DUSAGE_RENDERTARGET) && (!This->ddraw_primary) )
758 This->ddraw_primary = (IWineD3DSurface *) object;
760 /* Look at the implementation and set the correct Vtable */
761 switch(Impl) {
762 case SURFACE_OPENGL:
763 /* Nothing to do, it's set already */
764 break;
766 case SURFACE_GDI:
767 object->lpVtbl = &IWineGDISurface_Vtbl;
768 break;
770 default:
771 /* To be sure to catch this */
772 ERR("Unknown requested surface implementation %d!\n", Impl);
773 IWineD3DSurface_Release((IWineD3DSurface *) object);
774 return WINED3DERR_INVALIDCALL;
777 /* Call the private setup routine */
778 return IWineD3DSurface_PrivateSetup( (IWineD3DSurface *) object );
782 HRESULT WINAPI IWineD3DDeviceImpl_CreateTexture(IWineD3DDevice *iface, UINT Width, UINT Height, UINT Levels,
783 DWORD Usage, WINED3DFORMAT Format, WINED3DPOOL Pool,
784 IWineD3DTexture** ppTexture, HANDLE* pSharedHandle, IUnknown *parent,
785 D3DCB_CREATESURFACEFN D3DCB_CreateSurface) {
787 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
788 IWineD3DTextureImpl *object;
789 unsigned int i;
790 UINT tmpW;
791 UINT tmpH;
792 HRESULT hr;
793 unsigned int pow2Width = Width;
794 unsigned int pow2Height = Height;
797 TRACE("(%p), Width(%d) Height(%d) Levels(%d) Usage(%ld) ....\n", This, Width, Height, Levels, Usage);
799 /* TODO: It should only be possible to create textures for formats
800 that are reported as supported */
801 if (WINED3DFMT_UNKNOWN >= Format) {
802 WARN("(%p) : Texture cannot be created with a format of D3DFMT_UNKNOWN\n", This);
803 return WINED3DERR_INVALIDCALL;
806 D3DCREATERESOURCEOBJECTINSTANCE(object, Texture, WINED3DRTYPE_TEXTURE, 0);
807 D3DINITIALIZEBASETEXTURE(object->baseTexture);
808 object->width = Width;
809 object->height = Height;
811 /** Non-power2 support **/
812 /* Find the nearest pow2 match */
813 pow2Width = pow2Height = 1;
814 while (pow2Width < Width) pow2Width <<= 1;
815 while (pow2Height < Height) pow2Height <<= 1;
817 /** FIXME: add support for real non-power-two if it's provided by the video card **/
818 /* Precalculated scaling for 'faked' non power of two texture coords */
819 object->pow2scalingFactorX = (((float)Width) / ((float)pow2Width));
820 object->pow2scalingFactorY = (((float)Height) / ((float)pow2Height));
821 TRACE(" xf(%f) yf(%f)\n", object->pow2scalingFactorX, object->pow2scalingFactorY);
823 /* Calculate levels for mip mapping */
824 if (Levels == 0) {
825 TRACE("calculating levels %d\n", object->baseTexture.levels);
826 object->baseTexture.levels++;
827 tmpW = Width;
828 tmpH = Height;
829 while (tmpW > 1 || tmpH > 1) {
830 tmpW = max(1, tmpW >> 1);
831 tmpH = max(1, tmpH >> 1);
832 object->baseTexture.levels++;
834 TRACE("Calculated levels = %d\n", object->baseTexture.levels);
837 /* Generate all the surfaces */
838 tmpW = Width;
839 tmpH = Height;
840 for (i = 0; i < object->baseTexture.levels; i++)
842 /* use the callback to create the texture surface */
843 hr = D3DCB_CreateSurface(This->parent, tmpW, tmpH, Format, Usage, Pool, i, &object->surfaces[i],NULL);
844 if (hr!= WINED3D_OK || ( (IWineD3DSurfaceImpl *) object->surfaces[i])->Flags & SFLAG_OVERSIZE) {
845 int j;
846 FIXME("Failed to create surface %p\n", object);
847 /* clean up */
848 for (j = 0 ; j <= i ; j++) {
849 if(object->surfaces[j]) IWineD3DSurface_Release(object->surfaces[j]);
851 /* heap free object */
852 HeapFree(GetProcessHeap(), 0, object);
854 *ppTexture = NULL;
855 return hr;
858 IWineD3DSurface_SetContainer(object->surfaces[i], (IWineD3DBase *)object);
859 TRACE("Created surface level %d @ %p\n", i, object->surfaces[i]);
860 /* calculate the next mipmap level */
861 tmpW = max(1, tmpW >> 1);
862 tmpH = max(1, tmpH >> 1);
865 TRACE("(%p) : Created texture %p\n", This, object);
866 return WINED3D_OK;
869 HRESULT WINAPI IWineD3DDeviceImpl_CreateVolumeTexture(IWineD3DDevice *iface,
870 UINT Width, UINT Height, UINT Depth,
871 UINT Levels, DWORD Usage,
872 WINED3DFORMAT Format, WINED3DPOOL Pool,
873 IWineD3DVolumeTexture **ppVolumeTexture,
874 HANDLE *pSharedHandle, IUnknown *parent,
875 D3DCB_CREATEVOLUMEFN D3DCB_CreateVolume) {
877 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
878 IWineD3DVolumeTextureImpl *object;
879 unsigned int i;
880 UINT tmpW;
881 UINT tmpH;
882 UINT tmpD;
884 /* TODO: It should only be possible to create textures for formats
885 that are reported as supported */
886 if (WINED3DFMT_UNKNOWN >= Format) {
887 WARN("(%p) : Texture cannot be created with a format of D3DFMT_UNKNOWN\n", This);
888 return WINED3DERR_INVALIDCALL;
891 D3DCREATERESOURCEOBJECTINSTANCE(object, VolumeTexture, WINED3DRTYPE_VOLUMETEXTURE, 0);
892 D3DINITIALIZEBASETEXTURE(object->baseTexture);
894 TRACE("(%p) : W(%d) H(%d) D(%d), Lvl(%d) Usage(%ld), Fmt(%u,%s), Pool(%s)\n", This, Width, Height,
895 Depth, Levels, Usage, Format, debug_d3dformat(Format), debug_d3dpool(Pool));
897 object->width = Width;
898 object->height = Height;
899 object->depth = Depth;
901 /* Calculate levels for mip mapping */
902 if (Levels == 0) {
903 object->baseTexture.levels++;
904 tmpW = Width;
905 tmpH = Height;
906 tmpD = Depth;
907 while (tmpW > 1 || tmpH > 1 || tmpD > 1) {
908 tmpW = max(1, tmpW >> 1);
909 tmpH = max(1, tmpH >> 1);
910 tmpD = max(1, tmpD >> 1);
911 object->baseTexture.levels++;
913 TRACE("Calculated levels = %d\n", object->baseTexture.levels);
916 /* Generate all the surfaces */
917 tmpW = Width;
918 tmpH = Height;
919 tmpD = Depth;
921 for (i = 0; i < object->baseTexture.levels; i++)
923 /* Create the volume */
924 D3DCB_CreateVolume(This->parent, Width, Height, Depth, Format, Pool, Usage,
925 (IWineD3DVolume **)&object->volumes[i], pSharedHandle);
927 /* Set it's container to this object */
928 IWineD3DVolume_SetContainer(object->volumes[i], (IWineD3DBase *)object);
930 /* calcualte the next mipmap level */
931 tmpW = max(1, tmpW >> 1);
932 tmpH = max(1, tmpH >> 1);
933 tmpD = max(1, tmpD >> 1);
936 *ppVolumeTexture = (IWineD3DVolumeTexture *) object;
937 TRACE("(%p) : Created volume texture %p\n", This, object);
938 return WINED3D_OK;
941 HRESULT WINAPI IWineD3DDeviceImpl_CreateVolume(IWineD3DDevice *iface,
942 UINT Width, UINT Height, UINT Depth,
943 DWORD Usage,
944 WINED3DFORMAT Format, WINED3DPOOL Pool,
945 IWineD3DVolume** ppVolume,
946 HANDLE* pSharedHandle, IUnknown *parent) {
948 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
949 IWineD3DVolumeImpl *object; /** NOTE: impl ref allowed since this is a create function **/
951 D3DCREATERESOURCEOBJECTINSTANCE(object, Volume, WINED3DRTYPE_VOLUME, ((Width * D3DFmtGetBpp(This, Format)) * Height * Depth))
953 TRACE("(%p) : W(%d) H(%d) D(%d), Usage(%ld), Fmt(%u,%s), Pool(%s)\n", This, Width, Height,
954 Depth, Usage, Format, debug_d3dformat(Format), debug_d3dpool(Pool));
956 object->currentDesc.Width = Width;
957 object->currentDesc.Height = Height;
958 object->currentDesc.Depth = Depth;
959 object->bytesPerPixel = D3DFmtGetBpp(This, Format);
961 /** Note: Volume textures cannot be dxtn, hence no need to check here **/
962 object->lockable = TRUE;
963 object->locked = FALSE;
964 memset(&object->lockedBox, 0, sizeof(WINED3DBOX));
965 object->dirty = TRUE;
967 return IWineD3DVolume_AddDirtyBox((IWineD3DVolume *) object, NULL);
970 HRESULT WINAPI IWineD3DDeviceImpl_CreateCubeTexture(IWineD3DDevice *iface, UINT EdgeLength,
971 UINT Levels, DWORD Usage,
972 WINED3DFORMAT Format, WINED3DPOOL Pool,
973 IWineD3DCubeTexture **ppCubeTexture,
974 HANDLE *pSharedHandle, IUnknown *parent,
975 D3DCB_CREATESURFACEFN D3DCB_CreateSurface) {
977 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
978 IWineD3DCubeTextureImpl *object; /** NOTE: impl ref allowed since this is a create function **/
979 unsigned int i, j;
980 UINT tmpW;
981 HRESULT hr;
982 unsigned int pow2EdgeLength = EdgeLength;
984 /* TODO: It should only be possible to create textures for formats
985 that are reported as supported */
986 if (WINED3DFMT_UNKNOWN >= Format) {
987 WARN("(%p) : Texture cannot be created with a format of D3DFMT_UNKNOWN\n", This);
988 return WINED3DERR_INVALIDCALL;
991 D3DCREATERESOURCEOBJECTINSTANCE(object, CubeTexture, WINED3DRTYPE_CUBETEXTURE, 0);
992 D3DINITIALIZEBASETEXTURE(object->baseTexture);
994 TRACE("(%p) Create Cube Texture\n", This);
996 /** Non-power2 support **/
998 /* Find the nearest pow2 match */
999 pow2EdgeLength = 1;
1000 while (pow2EdgeLength < EdgeLength) pow2EdgeLength <<= 1;
1002 object->edgeLength = EdgeLength;
1003 /* TODO: support for native non-power 2 */
1004 /* Precalculated scaling for 'faked' non power of two texture coords */
1005 object->pow2scalingFactor = ((float)EdgeLength) / ((float)pow2EdgeLength);
1007 /* Calculate levels for mip mapping */
1008 if (Levels == 0) {
1009 object->baseTexture.levels++;
1010 tmpW = EdgeLength;
1011 while (tmpW > 1) {
1012 tmpW = max(1, tmpW >> 1);
1013 object->baseTexture.levels++;
1015 TRACE("Calculated levels = %d\n", object->baseTexture.levels);
1018 /* Generate all the surfaces */
1019 tmpW = EdgeLength;
1020 for (i = 0; i < object->baseTexture.levels; i++) {
1022 /* Create the 6 faces */
1023 for (j = 0; j < 6; j++) {
1025 hr=D3DCB_CreateSurface(This->parent, tmpW, tmpW, Format, Usage, Pool,
1026 i /* Level */, &object->surfaces[j][i],pSharedHandle);
1028 if(hr!= WINED3D_OK) {
1029 /* clean up */
1030 int k;
1031 int l;
1032 for (l = 0; l < j; l++) {
1033 IWineD3DSurface_Release(object->surfaces[j][i]);
1035 for (k = 0; k < i; k++) {
1036 for (l = 0; l < 6; l++) {
1037 IWineD3DSurface_Release(object->surfaces[l][j]);
1041 FIXME("(%p) Failed to create surface\n",object);
1042 HeapFree(GetProcessHeap(),0,object);
1043 *ppCubeTexture = NULL;
1044 return hr;
1046 IWineD3DSurface_SetContainer(object->surfaces[j][i], (IWineD3DBase *)object);
1047 TRACE("Created surface level %d @ %p,\n", i, object->surfaces[j][i]);
1049 tmpW = max(1, tmpW >> 1);
1052 TRACE("(%p) : Created Cube Texture %p\n", This, object);
1053 *ppCubeTexture = (IWineD3DCubeTexture *) object;
1054 return WINED3D_OK;
1057 HRESULT WINAPI IWineD3DDeviceImpl_CreateQuery(IWineD3DDevice *iface, WINED3DQUERYTYPE Type, IWineD3DQuery **ppQuery, IUnknown* parent) {
1058 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
1059 IWineD3DQueryImpl *object; /*NOTE: impl ref allowed since this is a create function */
1061 if (NULL == ppQuery) {
1062 /* Just a check to see if we support this type of query */
1063 HRESULT hr = WINED3DERR_NOTAVAILABLE;
1064 switch(Type) {
1065 case WINED3DQUERYTYPE_OCCLUSION:
1066 TRACE("(%p) occlusion query\n", This);
1067 if (GL_SUPPORT(ARB_OCCLUSION_QUERY) || GL_SUPPORT(NV_OCCLUSION_QUERY))
1068 hr = WINED3D_OK;
1069 else
1070 WARN("Unsupported in local OpenGL implementation: ARB_OCCLUSION_QUERY/NV_OCCLUSION_QUERY\n");
1071 break;
1072 case WINED3DQUERYTYPE_VCACHE:
1073 case WINED3DQUERYTYPE_RESOURCEMANAGER:
1074 case WINED3DQUERYTYPE_VERTEXSTATS:
1075 case WINED3DQUERYTYPE_EVENT:
1076 case WINED3DQUERYTYPE_TIMESTAMP:
1077 case WINED3DQUERYTYPE_TIMESTAMPDISJOINT:
1078 case WINED3DQUERYTYPE_TIMESTAMPFREQ:
1079 case WINED3DQUERYTYPE_PIPELINETIMINGS:
1080 case WINED3DQUERYTYPE_INTERFACETIMINGS:
1081 case WINED3DQUERYTYPE_VERTEXTIMINGS:
1082 case WINED3DQUERYTYPE_PIXELTIMINGS:
1083 case WINED3DQUERYTYPE_BANDWIDTHTIMINGS:
1084 case WINED3DQUERYTYPE_CACHEUTILIZATION:
1085 default:
1086 FIXME("(%p) Unhandled query type %d\n", This, Type);
1088 return hr;
1091 D3DCREATEOBJECTINSTANCE(object, Query)
1092 object->type = Type;
1093 /* allocated the 'extended' data based on the type of query requested */
1094 switch(Type){
1095 case D3DQUERYTYPE_OCCLUSION:
1096 if(GL_SUPPORT(ARB_OCCLUSION_QUERY) || GL_SUPPORT(NV_OCCLUSION_QUERY)) {
1097 TRACE("(%p) Allocating data for an occlusion query\n", This);
1098 object->extendedData = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(WineQueryOcclusionData));
1099 break;
1101 case D3DQUERYTYPE_VCACHE:
1102 case D3DQUERYTYPE_RESOURCEMANAGER:
1103 case D3DQUERYTYPE_VERTEXSTATS:
1104 case D3DQUERYTYPE_EVENT:
1105 case D3DQUERYTYPE_TIMESTAMP:
1106 case D3DQUERYTYPE_TIMESTAMPDISJOINT:
1107 case D3DQUERYTYPE_TIMESTAMPFREQ:
1108 case D3DQUERYTYPE_PIPELINETIMINGS:
1109 case D3DQUERYTYPE_INTERFACETIMINGS:
1110 case D3DQUERYTYPE_VERTEXTIMINGS:
1111 case D3DQUERYTYPE_PIXELTIMINGS:
1112 case D3DQUERYTYPE_BANDWIDTHTIMINGS:
1113 case D3DQUERYTYPE_CACHEUTILIZATION:
1114 default:
1115 object->extendedData = 0;
1116 FIXME("(%p) Unhandled query type %d\n",This , Type);
1118 TRACE("(%p) : Created Query %p\n", This, object);
1119 return WINED3D_OK;
1122 /* example at http://www.fairyengine.com/articles/dxmultiviews.htm */
1123 HRESULT WINAPI IWineD3DDeviceImpl_CreateAdditionalSwapChain(IWineD3DDevice* iface, WINED3DPRESENT_PARAMETERS* pPresentationParameters, IWineD3DSwapChain** ppSwapChain,
1124 IUnknown* parent,
1125 D3DCB_CREATERENDERTARGETFN D3DCB_CreateRenderTarget,
1126 D3DCB_CREATEDEPTHSTENCILSURFACEFN D3DCB_CreateDepthStencil) {
1127 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
1129 HDC hDc;
1130 IWineD3DSwapChainImpl *object; /** NOTE: impl ref allowed since this is a create function **/
1131 int num;
1132 XVisualInfo template;
1133 GLXContext oldContext;
1134 Drawable oldDrawable;
1135 HRESULT hr = WINED3D_OK;
1137 TRACE("(%p) : Created Aditional Swap Chain\n", This);
1139 /** FIXME: Test under windows to find out what the life cycle of a swap chain is,
1140 * does a device hold a reference to a swap chain giving them a lifetime of the device
1141 * or does the swap chain notify the device of its destruction.
1142 *******************************/
1144 /* Check the params */
1145 if(*pPresentationParameters->BackBufferCount > 1) {
1146 ERR("App requested %d back buffers, this is not supported for now\n", *pPresentationParameters->BackBufferCount);
1147 return WINED3DERR_INVALIDCALL;
1150 D3DCREATEOBJECTINSTANCE(object, SwapChain)
1152 /*********************
1153 * Lookup the window Handle and the relating X window handle
1154 ********************/
1156 /* Setup hwnd we are using, plus which display this equates to */
1157 object->win_handle = *(pPresentationParameters->hDeviceWindow);
1158 if (!object->win_handle) {
1159 object->win_handle = This->createParms.hFocusWindow;
1162 object->win_handle = GetAncestor(object->win_handle, GA_ROOT);
1163 if ( !( object->win = (Window)GetPropA(object->win_handle, "__wine_x11_whole_window") ) ) {
1164 ERR("Can't get drawable (window), HWND:%p doesn't have the property __wine_x11_whole_window\n", object->win_handle);
1165 return WINED3DERR_NOTAVAILABLE;
1167 hDc = GetDC(object->win_handle);
1168 object->display = get_display(hDc);
1169 ReleaseDC(object->win_handle, hDc);
1170 TRACE("Using a display of %p %p\n", object->display, hDc);
1172 if (NULL == object->display || NULL == hDc) {
1173 WARN("Failed to get a display and HDc for Window %p\n", object->win_handle);
1174 return WINED3DERR_NOTAVAILABLE;
1177 if (object->win == 0) {
1178 WARN("Failed to get a valid XVisuial ID for the window %p\n", object->win_handle);
1179 return WINED3DERR_NOTAVAILABLE;
1182 * Create an opengl context for the display visual
1183 * NOTE: the visual is chosen as the window is created and the glcontext cannot
1184 * use different properties after that point in time. FIXME: How to handle when requested format
1185 * doesn't match actual visual? Cannot choose one here - code removed as it ONLY works if the one
1186 * it chooses is identical to the one already being used!
1187 **********************************/
1189 /** FIXME: Handle stencil appropriately via EnableAutoDepthStencil / AutoDepthStencilFormat **/
1190 ENTER_GL();
1192 /* Create a new context for this swapchain */
1193 template.visualid = (VisualID)GetPropA(GetDesktopWindow(), "__wine_x11_visual_id");
1194 /* TODO: change this to find a similar visual, but one with a stencil/zbuffer buffer that matches the request
1195 (or the best possible if none is requested) */
1196 TRACE("Found x visual ID : %ld\n", template.visualid);
1198 object->visInfo = XGetVisualInfo(object->display, VisualIDMask, &template, &num);
1199 if (NULL == object->visInfo) {
1200 ERR("cannot really get XVisual\n");
1201 LEAVE_GL();
1202 return WINED3DERR_NOTAVAILABLE;
1203 } else {
1204 int n, value;
1205 /* Write out some debug info about the visual/s */
1206 TRACE("Using x visual ID : %ld\n", template.visualid);
1207 TRACE(" visual info: %p\n", object->visInfo);
1208 TRACE(" num items : %d\n", num);
1209 for (n = 0;n < num; n++) {
1210 TRACE("=====item=====: %d\n", n + 1);
1211 TRACE(" visualid : %ld\n", object->visInfo[n].visualid);
1212 TRACE(" screen : %d\n", object->visInfo[n].screen);
1213 TRACE(" depth : %u\n", object->visInfo[n].depth);
1214 TRACE(" class : %d\n", object->visInfo[n].class);
1215 TRACE(" red_mask : %ld\n", object->visInfo[n].red_mask);
1216 TRACE(" green_mask : %ld\n", object->visInfo[n].green_mask);
1217 TRACE(" blue_mask : %ld\n", object->visInfo[n].blue_mask);
1218 TRACE(" colormap_size : %d\n", object->visInfo[n].colormap_size);
1219 TRACE(" bits_per_rgb : %d\n", object->visInfo[n].bits_per_rgb);
1220 /* log some extra glx info */
1221 glXGetConfig(object->display, object->visInfo, GLX_AUX_BUFFERS, &value);
1222 TRACE(" gl_aux_buffers : %d\n", value);
1223 glXGetConfig(object->display, object->visInfo, GLX_BUFFER_SIZE ,&value);
1224 TRACE(" gl_buffer_size : %d\n", value);
1225 glXGetConfig(object->display, object->visInfo, GLX_RED_SIZE, &value);
1226 TRACE(" gl_red_size : %d\n", value);
1227 glXGetConfig(object->display, object->visInfo, GLX_GREEN_SIZE, &value);
1228 TRACE(" gl_green_size : %d\n", value);
1229 glXGetConfig(object->display, object->visInfo, GLX_BLUE_SIZE, &value);
1230 TRACE(" gl_blue_size : %d\n", value);
1231 glXGetConfig(object->display, object->visInfo, GLX_ALPHA_SIZE, &value);
1232 TRACE(" gl_alpha_size : %d\n", value);
1233 glXGetConfig(object->display, object->visInfo, GLX_DEPTH_SIZE ,&value);
1234 TRACE(" gl_depth_size : %d\n", value);
1235 glXGetConfig(object->display, object->visInfo, GLX_STENCIL_SIZE, &value);
1236 TRACE(" gl_stencil_size : %d\n", value);
1238 /* Now choose a simila visual ID*/
1240 #ifdef USE_CONTEXT_MANAGER
1242 /** TODO: use a context mamager **/
1243 #endif
1246 IWineD3DSwapChain *implSwapChain;
1247 if (WINED3D_OK != IWineD3DDevice_GetSwapChain(iface, 0, &implSwapChain)) {
1248 /* The first time around we create the context that is shared with all other swapchains and render targets */
1249 object->glCtx = glXCreateContext(object->display, object->visInfo, NULL, GL_TRUE);
1250 TRACE("Creating implicit context for vis %p, hwnd %p\n", object->display, object->visInfo);
1251 } else {
1253 TRACE("Creating context for vis %p, hwnd %p\n", object->display, object->visInfo);
1254 /* TODO: don't use Impl structures outside of create functions! (a context manager will replace the ->glCtx) */
1255 /* and create a new context with the implicit swapchains context as the shared context */
1256 object->glCtx = glXCreateContext(object->display, object->visInfo, ((IWineD3DSwapChainImpl *)implSwapChain)->glCtx, GL_TRUE);
1257 IWineD3DSwapChain_Release(implSwapChain);
1261 /* Cleanup */
1262 XFree(object->visInfo);
1263 object->visInfo = NULL;
1265 if (NULL == object->glCtx) {
1266 ERR("cannot create glxContext\n");
1267 LEAVE_GL();
1268 return WINED3DERR_NOTAVAILABLE;
1271 LEAVE_GL();
1272 if (object->glCtx == NULL) {
1273 ERR("Error in context creation !\n");
1274 return WINED3DERR_INVALIDCALL;
1275 } else {
1276 TRACE("Context created (HWND=%p, glContext=%p, Window=%ld, VisInfo=%p)\n",
1277 object->win_handle, object->glCtx, object->win, object->visInfo);
1280 /*********************
1281 * Windowed / Fullscreen
1282 *******************/
1285 * TODO: MSDN says that we are only allowed one fullscreen swapchain per device,
1286 * so we should really check to see if there is a fullscreen swapchain already
1287 * I think Windows and X have different ideas about fullscreen, does a single head count as full screen?
1288 **************************************/
1290 if (!*(pPresentationParameters->Windowed)) {
1292 DEVMODEW devmode;
1293 HDC hdc;
1294 int bpp = 0;
1296 /* Get info on the current display setup */
1297 hdc = CreateDCA("DISPLAY", NULL, NULL, NULL);
1298 bpp = GetDeviceCaps(hdc, BITSPIXEL);
1299 DeleteDC(hdc);
1301 /* Change the display settings */
1302 memset(&devmode, 0, sizeof(DEVMODEW));
1303 devmode.dmFields = DM_BITSPERPEL | DM_PELSWIDTH | DM_PELSHEIGHT;
1304 devmode.dmBitsPerPel = (bpp >= 24) ? 32 : bpp; /* Stupid XVidMode cannot change bpp */
1305 devmode.dmPelsWidth = *(pPresentationParameters->BackBufferWidth);
1306 devmode.dmPelsHeight = *(pPresentationParameters->BackBufferHeight);
1307 MultiByteToWideChar(CP_ACP, 0, "Gamers CG", -1, devmode.dmDeviceName, CCHDEVICENAME);
1308 ChangeDisplaySettingsExW(devmode.dmDeviceName, &devmode, object->win_handle, CDS_FULLSCREEN, NULL);
1310 /* Make popup window */
1311 SetWindowLongA(object->win_handle, GWL_STYLE, WS_POPUP);
1312 SetWindowPos(object->win_handle, HWND_TOP, 0, 0,
1313 *(pPresentationParameters->BackBufferWidth),
1314 *(pPresentationParameters->BackBufferHeight), SWP_SHOWWINDOW | SWP_FRAMECHANGED);
1316 /* For GetDisplayMode */
1317 This->ddraw_width = devmode.dmPelsWidth;
1318 This->ddraw_height = devmode.dmPelsHeight;
1319 This->ddraw_format = *(pPresentationParameters->BackBufferFormat);
1323 /** MSDN: If Windowed is TRUE and either of the BackBufferWidth/Height values is zero,
1324 * then the corresponding dimension of the client area of the hDeviceWindow
1325 * (or the focus window, if hDeviceWindow is NULL) is taken.
1326 **********************/
1328 if (*(pPresentationParameters->Windowed) &&
1329 ((*(pPresentationParameters->BackBufferWidth) == 0) ||
1330 (*(pPresentationParameters->BackBufferHeight) == 0))) {
1332 RECT Rect;
1333 GetClientRect(object->win_handle, &Rect);
1335 if (*(pPresentationParameters->BackBufferWidth) == 0) {
1336 *(pPresentationParameters->BackBufferWidth) = Rect.right;
1337 TRACE("Updating width to %d\n", *(pPresentationParameters->BackBufferWidth));
1339 if (*(pPresentationParameters->BackBufferHeight) == 0) {
1340 *(pPresentationParameters->BackBufferHeight) = Rect.bottom;
1341 TRACE("Updating height to %d\n", *(pPresentationParameters->BackBufferHeight));
1345 /*********************
1346 * finish off parameter initialization
1347 *******************/
1349 /* Put the correct figures in the presentation parameters */
1350 TRACE("Coppying accross presentaion paraneters\n");
1351 object->presentParms.BackBufferWidth = *(pPresentationParameters->BackBufferWidth);
1352 object->presentParms.BackBufferHeight = *(pPresentationParameters->BackBufferHeight);
1353 object->presentParms.BackBufferFormat = *(pPresentationParameters->BackBufferFormat);
1354 object->presentParms.BackBufferCount = *(pPresentationParameters->BackBufferCount);
1355 object->presentParms.MultiSampleType = *(pPresentationParameters->MultiSampleType);
1356 object->presentParms.MultiSampleQuality = NULL == pPresentationParameters->MultiSampleQuality ? 0 : *(pPresentationParameters->MultiSampleQuality);
1357 object->presentParms.SwapEffect = *(pPresentationParameters->SwapEffect);
1358 object->presentParms.hDeviceWindow = *(pPresentationParameters->hDeviceWindow);
1359 object->presentParms.Windowed = *(pPresentationParameters->Windowed);
1360 object->presentParms.EnableAutoDepthStencil = *(pPresentationParameters->EnableAutoDepthStencil);
1361 object->presentParms.AutoDepthStencilFormat = *(pPresentationParameters->AutoDepthStencilFormat);
1362 object->presentParms.Flags = *(pPresentationParameters->Flags);
1363 object->presentParms.FullScreen_RefreshRateInHz = *(pPresentationParameters->FullScreen_RefreshRateInHz);
1364 object->presentParms.PresentationInterval = *(pPresentationParameters->PresentationInterval);
1367 /*********************
1368 * Create the back, front and stencil buffers
1369 *******************/
1371 TRACE("calling rendertarget CB\n");
1372 hr = D3DCB_CreateRenderTarget((IUnknown *) This->parent,
1373 object->presentParms.BackBufferWidth,
1374 object->presentParms.BackBufferHeight,
1375 object->presentParms.BackBufferFormat,
1376 object->presentParms.MultiSampleType,
1377 object->presentParms.MultiSampleQuality,
1378 TRUE /* Lockable */,
1379 &object->frontBuffer,
1380 NULL /* pShared (always null)*/);
1381 if (object->frontBuffer != NULL)
1382 IWineD3DSurface_SetContainer(object->frontBuffer, (IWineD3DBase *)object);
1383 if(object->presentParms.BackBufferCount > 0) {
1384 TRACE("calling rendertarget CB\n");
1385 hr = D3DCB_CreateRenderTarget((IUnknown *) This->parent,
1386 object->presentParms.BackBufferWidth,
1387 object->presentParms.BackBufferHeight,
1388 object->presentParms.BackBufferFormat,
1389 object->presentParms.MultiSampleType,
1390 object->presentParms.MultiSampleQuality,
1391 TRUE /* Lockable */,
1392 &object->backBuffer,
1393 NULL /* pShared (always null)*/);
1394 } else {
1395 object->backBuffer = NULL;
1398 if (object->backBuffer != NULL) {
1399 IWineD3DSurface_SetContainer(object->backBuffer, (IWineD3DBase *)object);
1400 ENTER_GL();
1401 glDrawBuffer(GL_BACK);
1402 checkGLcall("glDrawBuffer(GL_BACK)");
1403 LEAVE_GL();
1404 } else {
1405 /* Single buffering - draw to front buffer */
1406 ENTER_GL();
1407 glDrawBuffer(GL_FRONT);
1408 checkGLcall("glDrawBuffer(GL_FRONT)");
1409 LEAVE_GL();
1412 /* Under directX swapchains share the depth stencil, so only create one depth-stencil */
1413 if (pPresentationParameters->EnableAutoDepthStencil) {
1414 TRACE("Creating depth stencil buffer\n");
1415 if (This->depthStencilBuffer == NULL ) {
1416 hr = D3DCB_CreateDepthStencil((IUnknown *) This->parent,
1417 object->presentParms.BackBufferWidth,
1418 object->presentParms.BackBufferHeight,
1419 object->presentParms.AutoDepthStencilFormat,
1420 object->presentParms.MultiSampleType,
1421 object->presentParms.MultiSampleQuality,
1422 FALSE /* FIXME: Discard */,
1423 &This->depthStencilBuffer,
1424 NULL /* pShared (always null)*/ );
1425 if (This->depthStencilBuffer != NULL)
1426 IWineD3DSurface_SetContainer(This->depthStencilBuffer, 0);
1429 /** TODO: A check on width, height and multisample types
1430 *(since the zbuffer must be at least as large as the render target and have the same multisample parameters)
1431 ****************************/
1432 object->wantsDepthStencilBuffer = TRUE;
1433 } else {
1434 object->wantsDepthStencilBuffer = FALSE;
1437 TRACE("FrontBuf @ %p, BackBuf @ %p, DepthStencil %d\n",object->frontBuffer, object->backBuffer, object->wantsDepthStencilBuffer);
1440 /*********************
1441 * init the default renderTarget management
1442 *******************/
1443 object->drawable = object->win;
1444 object->render_ctx = object->glCtx;
1446 if (hr == WINED3D_OK) {
1447 /*********************
1448 * Setup some defaults and clear down the buffers
1449 *******************/
1450 ENTER_GL();
1451 /** save current context and drawable **/
1452 oldContext = glXGetCurrentContext();
1453 oldDrawable = glXGetCurrentDrawable();
1455 TRACE("Activating context (display %p context %p drawable %ld)!\n", object->display, object->glCtx, object->win);
1456 if (glXMakeCurrent(object->display, object->win, object->glCtx) == False) {
1457 ERR("Error in setting current context (display %p context %p drawable %ld)!\n", object->display, object->glCtx, object->win);
1459 checkGLcall("glXMakeCurrent");
1461 TRACE("Setting up the screen\n");
1462 /* Clear the screen */
1463 glClearColor(1.0, 0.0, 0.0, 0.0);
1464 checkGLcall("glClearColor");
1465 glClearIndex(0);
1466 glClearDepth(1);
1467 glClearStencil(0xffff);
1469 checkGLcall("glClear");
1471 glColor3f(1.0, 1.0, 1.0);
1472 checkGLcall("glColor3f");
1474 glEnable(GL_LIGHTING);
1475 checkGLcall("glEnable");
1477 glLightModeli(GL_LIGHT_MODEL_LOCAL_VIEWER, GL_TRUE);
1478 checkGLcall("glLightModeli(GL_LIGHT_MODEL_LOCAL_VIEWER, GL_TRUE);");
1480 glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE_EXT);
1481 checkGLcall("glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE_EXT);");
1483 glLightModeli(GL_LIGHT_MODEL_COLOR_CONTROL, GL_SEPARATE_SPECULAR_COLOR);
1484 checkGLcall("glLightModeli(GL_LIGHT_MODEL_COLOR_CONTROL, GL_SEPARATE_SPECULAR_COLOR);");
1486 /* switch back to the original context (if there was one)*/
1487 if (This->swapchains) {
1488 /** TODO: restore the context and drawable **/
1489 glXMakeCurrent(object->display, oldDrawable, oldContext);
1492 LEAVE_GL();
1494 TRACE("Set swapchain to %p\n", object);
1495 } else { /* something went wrong so clean up */
1496 IUnknown* bufferParent;
1497 if (object->frontBuffer) {
1499 IWineD3DSurface_GetParent(object->frontBuffer, &bufferParent);
1500 IUnknown_Release(bufferParent); /* once for the get parent */
1501 if (IUnknown_Release(bufferParent) > 0) {
1502 FIXME("(%p) Something's still holding the front buffer\n",This);
1505 if (object->backBuffer) {
1506 IWineD3DSurface_GetParent(object->backBuffer, &bufferParent);
1507 IUnknown_Release(bufferParent); /* once for the get parent */
1508 if (IUnknown_Release(bufferParent) > 0) {
1509 FIXME("(%p) Something's still holding the back buffer\n",This);
1512 /* NOTE: don't clean up the depthstencil buffer because it belongs to the device */
1513 /* Clean up the context */
1514 /* check that we are the current context first (we shouldn't be though!) */
1515 if (object->glCtx != 0) {
1516 if(glXGetCurrentContext() == object->glCtx) {
1517 glXMakeCurrent(object->display, None, NULL);
1519 glXDestroyContext(object->display, object->glCtx);
1521 HeapFree(GetProcessHeap(), 0, object);
1525 return hr;
1528 /** NOTE: These are ahead of the other getters and setters to save using a forward declaration **/
1529 UINT WINAPI IWineD3DDeviceImpl_GetNumberOfSwapChains(IWineD3DDevice *iface) {
1530 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
1531 TRACE("(%p)\n", This);
1533 return This->NumberOfSwapChains;
1536 HRESULT WINAPI IWineD3DDeviceImpl_GetSwapChain(IWineD3DDevice *iface, UINT iSwapChain, IWineD3DSwapChain **pSwapChain) {
1537 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
1538 TRACE("(%p) : swapchain %d\n", This, iSwapChain);
1540 if(iSwapChain < This->NumberOfSwapChains) {
1541 *pSwapChain = This->swapchains[iSwapChain];
1542 IWineD3DSwapChain_AddRef(*pSwapChain);
1543 TRACE("(%p) returning %p\n", This, *pSwapChain);
1544 return WINED3D_OK;
1545 } else {
1546 TRACE("Swapchain out of range\n");
1547 *pSwapChain = NULL;
1548 return WINED3DERR_INVALIDCALL;
1552 /*****
1553 * Vertex Declaration
1554 *****/
1555 HRESULT WINAPI IWineD3DDeviceImpl_CreateVertexDeclaration(IWineD3DDevice* iface, CONST VOID* pDeclaration, IWineD3DVertexDeclaration** ppVertexDeclaration, IUnknown *parent) {
1556 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
1557 IWineD3DVertexDeclarationImpl *object = NULL;
1558 HRESULT hr = WINED3D_OK;
1559 TRACE("(%p) : directXVersion=%u, pFunction=%p, ppDecl=%p\n", This, ((IWineD3DImpl *)This->wineD3D)->dxVersion, pDeclaration, ppVertexDeclaration);
1560 D3DCREATEOBJECTINSTANCE(object, VertexDeclaration)
1561 object->allFVF = 0;
1563 hr = IWineD3DVertexDeclaration_SetDeclaration((IWineD3DVertexDeclaration *)object, (void *)pDeclaration);
1565 return hr;
1568 /* http://msdn.microsoft.com/archive/default.asp?url=/archive/en-us/directx9_c/directx/graphics/programmingguide/programmable/vertexshaders/vscreate.asp */
1569 HRESULT WINAPI IWineD3DDeviceImpl_CreateVertexShader(IWineD3DDevice *iface, CONST DWORD *pDeclaration, CONST DWORD *pFunction, IWineD3DVertexShader **ppVertexShader, IUnknown *parent) {
1570 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
1571 IWineD3DVertexShaderImpl *object; /* NOTE: impl usage is ok, this is a create */
1572 HRESULT hr = WINED3D_OK;
1573 D3DCREATEOBJECTINSTANCE(object, VertexShader)
1574 object->baseShader.shader_ins = IWineD3DVertexShaderImpl_shader_ins;
1576 TRACE("(%p) : Created Vertex shader %p\n", This, *ppVertexShader);
1578 /* If a vertex declaration has been passed, save it to the vertex shader, this affects d3d8 only. */
1579 /* Further it needs to be set before calling SetFunction as SetFunction needs the declaration. */
1580 if (pDeclaration != NULL) {
1581 IWineD3DVertexDeclaration *vertexDeclaration;
1582 hr = IWineD3DDevice_CreateVertexDeclaration(iface, pDeclaration, &vertexDeclaration ,NULL);
1583 if (WINED3D_OK == hr) {
1584 TRACE("(%p) : Setting vertex declaration to %p\n", This, vertexDeclaration);
1585 object->vertexDeclaration = vertexDeclaration;
1586 } else {
1587 FIXME("(%p) : Failed to set the declaration, returning WINED3DERR_INVALIDCALL\n", iface);
1588 IWineD3DVertexShader_Release(*ppVertexShader);
1589 return WINED3DERR_INVALIDCALL;
1593 hr = IWineD3DVertexShader_SetFunction(*ppVertexShader, pFunction);
1595 if (WINED3D_OK != hr) {
1596 FIXME("(%p) : Failed to set the function, returning WINED3DERR_INVALIDCALL\n", iface);
1597 IWineD3DVertexShader_Release(*ppVertexShader);
1598 return WINED3DERR_INVALIDCALL;
1601 #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. */
1602 if(Usage == WINED3DUSAGE_SOFTWAREVERTEXPROCESSING) {
1603 /* Foo */
1604 } else {
1605 /* Bar */
1608 #endif
1610 return WINED3D_OK;
1613 HRESULT WINAPI IWineD3DDeviceImpl_CreatePixelShader(IWineD3DDevice *iface, CONST DWORD *pFunction, IWineD3DPixelShader **ppPixelShader, IUnknown *parent) {
1614 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
1615 IWineD3DPixelShaderImpl *object; /* NOTE: impl allowed, this is a create */
1616 HRESULT hr = WINED3D_OK;
1618 D3DCREATEOBJECTINSTANCE(object, PixelShader)
1619 object->baseShader.shader_ins = IWineD3DPixelShaderImpl_shader_ins;
1620 hr = IWineD3DPixelShader_SetFunction(*ppPixelShader, pFunction);
1621 if (WINED3D_OK == hr) {
1622 TRACE("(%p) : Created Pixel shader %p\n", This, *ppPixelShader);
1623 } else {
1624 WARN("(%p) : Failed to create pixel shader\n", This);
1627 return hr;
1630 HRESULT WINAPI IWineD3DDeviceImpl_CreatePalette(IWineD3DDevice *iface, DWORD Flags, PALETTEENTRY *PalEnt, IWineD3DPalette **Palette, IUnknown *Parent) {
1631 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *) iface;
1632 IWineD3DPaletteImpl *object;
1633 HRESULT hr;
1634 TRACE("(%p)->(%lx, %p, %p, %p)\n", This, Flags, PalEnt, Palette, Parent);
1636 /* Create the new object */
1637 object = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(IWineD3DPaletteImpl));
1638 if(!object) {
1639 ERR("Out of memory when allocating memory for a IWineD3DPalette implementation\n");
1640 return E_OUTOFMEMORY;
1643 object->lpVtbl = &IWineD3DPalette_Vtbl;
1644 object->ref = 1;
1645 object->Flags = Flags;
1646 object->parent = Parent;
1647 object->wineD3DDevice = This;
1648 object->palNumEntries = IWineD3DPaletteImpl_Size(Flags);
1650 object->hpal = CreatePalette((const LOGPALETTE*)&(object->palVersion));
1652 if(!object->hpal) {
1653 HeapFree( GetProcessHeap(), 0, object);
1654 return E_OUTOFMEMORY;
1657 hr = IWineD3DPalette_SetEntries((IWineD3DPalette *) object, 0, 0, IWineD3DPaletteImpl_Size(Flags), PalEnt);
1658 if(FAILED(hr)) {
1659 IWineD3DPalette_Release((IWineD3DPalette *) object);
1660 return hr;
1663 *Palette = (IWineD3DPalette *) object;
1665 return WINED3D_OK;
1668 HRESULT WINAPI IWineD3DDeviceImpl_Init3D(IWineD3DDevice *iface, WINED3DPRESENT_PARAMETERS* pPresentationParameters, D3DCB_CREATEADDITIONALSWAPCHAIN D3DCB_CreateAdditionalSwapChain) {
1669 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *) iface;
1670 IWineD3DSwapChainImpl *swapchain;
1672 TRACE("(%p)->(%p,%p)\n", This, pPresentationParameters, D3DCB_CreateAdditionalSwapChain);
1673 if(This->d3d_initialized) return WINED3DERR_INVALIDCALL;
1675 /* TODO: Test if OpenGL is compiled in and loaded */
1677 /* Setup the implicit swapchain */
1678 TRACE("Creating implicit swapchain\n");
1679 if (D3D_OK != D3DCB_CreateAdditionalSwapChain((IUnknown *) This->parent, pPresentationParameters, (IWineD3DSwapChain **)&swapchain) || swapchain == NULL) {
1680 WARN("Failed to create implicit swapchain\n");
1681 return WINED3DERR_INVALIDCALL;
1684 This->NumberOfSwapChains = 1;
1685 This->swapchains = HeapAlloc(GetProcessHeap(), 0, This->NumberOfSwapChains * sizeof(IWineD3DSwapChain *));
1686 if(!This->swapchains) {
1687 ERR("Out of memory!\n");
1688 IWineD3DSwapChain_Release( (IWineD3DSwapChain *) swapchain);
1689 return E_OUTOFMEMORY;
1691 This->swapchains[0] = (IWineD3DSwapChain *) swapchain;
1693 if(swapchain->backBuffer) {
1694 TRACE("Setting rendertarget to %p\n", swapchain->backBuffer);
1695 This->renderTarget = swapchain->backBuffer;
1697 else {
1698 TRACE("Setting rendertarget to %p\n", swapchain->frontBuffer);
1699 This->renderTarget = swapchain->frontBuffer;
1701 IWineD3DSurface_AddRef(This->renderTarget);
1702 /* Depth Stencil support */
1703 This->stencilBufferTarget = This->depthStencilBuffer;
1704 if (NULL != This->stencilBufferTarget) {
1705 IWineD3DSurface_AddRef(This->stencilBufferTarget);
1708 /* Set up some starting GL setup */
1709 ENTER_GL();
1711 * Initialize openGL extension related variables
1712 * with Default values
1715 ((IWineD3DImpl *) This->wineD3D)->isGLInfoValid = IWineD3DImpl_FillGLCaps( &((IWineD3DImpl *) This->wineD3D)->gl_info, swapchain->display);
1716 /* Setup all the devices defaults */
1717 IWineD3DStateBlock_InitStartupStateBlock((IWineD3DStateBlock *)This->stateBlock);
1718 #if 0
1719 IWineD3DImpl_CheckGraphicsMemory();
1720 #endif
1721 LEAVE_GL();
1723 { /* Set a default viewport */
1724 D3DVIEWPORT9 vp;
1725 vp.X = 0;
1726 vp.Y = 0;
1727 vp.Width = *(pPresentationParameters->BackBufferWidth);
1728 vp.Height = *(pPresentationParameters->BackBufferHeight);
1729 vp.MinZ = 0.0f;
1730 vp.MaxZ = 1.0f;
1731 IWineD3DDevice_SetViewport((IWineD3DDevice *)This, &vp);
1735 /* Initialize the current view state */
1736 This->modelview_valid = 1;
1737 This->proj_valid = 0;
1738 This->view_ident = 1;
1739 This->last_was_rhw = 0;
1740 glGetIntegerv(GL_MAX_LIGHTS, &This->maxConcurrentLights);
1741 TRACE("(%p) All defaults now set up, leaving Init3D with %p\n", This, This);
1743 /* Clear the screen */
1744 IWineD3DDevice_Clear((IWineD3DDevice *) This, 0, NULL, D3DCLEAR_STENCIL|D3DCLEAR_ZBUFFER|D3DCLEAR_TARGET, 0x00, 1.0, 0);
1746 This->d3d_initialized = TRUE;
1747 return WINED3D_OK;
1750 HRESULT WINAPI IWineD3DDeviceImpl_Uninit3D(IWineD3DDevice *iface) {
1751 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *) iface;
1752 int texstage;
1753 IUnknown* stencilBufferParent;
1754 IUnknown* swapChainParent;
1755 uint i;
1756 TRACE("(%p)\n", This);
1758 if(!This->d3d_initialized) return WINED3DERR_INVALIDCALL;
1760 for(texstage = 0; texstage < GL_LIMITS(textures); texstage++) {
1761 IWineD3DDevice_SetTexture(iface, texstage, NULL);
1764 /* Release the buffers (with sanity checks)*/
1765 TRACE("Releasing the depth stencil buffer at %p\n", This->stencilBufferTarget);
1766 if(This->stencilBufferTarget != NULL && (IWineD3DSurface_Release(This->stencilBufferTarget) >0)){
1767 if(This->depthStencilBuffer != This->stencilBufferTarget)
1768 FIXME("(%p) Something's still holding the depthStencilBuffer\n",This);
1770 This->stencilBufferTarget = NULL;
1772 TRACE("Releasing the render target at %p\n", This->renderTarget);
1773 if(IWineD3DSurface_Release(This->renderTarget) >0){
1774 /* This check is a bit silly, itshould be in swapchain_release FIXME("(%p) Something's still holding the renderTarget\n",This); */
1776 TRACE("Setting rendertarget to NULL\n");
1777 This->renderTarget = NULL;
1779 IWineD3DSurface_GetParent(This->depthStencilBuffer, &stencilBufferParent);
1780 IUnknown_Release(stencilBufferParent); /* once for the get parent */
1781 if(IUnknown_Release(stencilBufferParent) >0){ /* the second time for when it was created */
1782 FIXME("(%p) Something's still holding the depthStencilBuffer\n",This);
1784 This->depthStencilBuffer = NULL;
1786 for(i=0; i < This->NumberOfSwapChains; i++) {
1787 TRACE("Releasing the implicit swapchain %d\n", i);
1788 /* Swapchain 0 is special because it's created in startup with a hanging parent, so we have to release its parent now */
1789 IWineD3DSwapChain_GetParent(This->swapchains[i], &swapChainParent);
1790 IUnknown_Release(swapChainParent); /* once for the get parent */
1791 if (IUnknown_Release(swapChainParent) > 0) { /* the second time for when it was created */
1792 FIXME("(%p) Something's still holding the implicit swapchain\n", This);
1796 HeapFree(GetProcessHeap(), 0, This->swapchains);
1797 This->swapchains = NULL;
1798 This->NumberOfSwapChains = 0;
1800 This->d3d_initialized = FALSE;
1801 return WINED3D_OK;
1804 HRESULT WINAPI IWineD3DDeviceImpl_EnumDisplayModes(IWineD3DDevice *iface, DWORD Flags, UINT Width, UINT Height, WINED3DFORMAT pixelformat, LPVOID context, D3DCB_ENUMDISPLAYMODESCALLBACK callback) {
1805 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
1807 DEVMODEW DevModeW;
1808 int i;
1810 TRACE("(%p)->(%lx,%d,%d,%d,%p,%p)\n", This, Flags, Width, Height, pixelformat, context, callback);
1812 for (i = 0; EnumDisplaySettingsExW(NULL, i, &DevModeW, 0); i++) {
1813 /* Ignore some modes if a description was passed */
1814 if ( (Width > 0) && (Width != DevModeW.dmPelsWidth)) continue;
1815 if ( (Height > 0) && (Height != DevModeW.dmPelsHeight)) continue;
1816 if ( (pixelformat != WINED3DFMT_UNKNOWN) && ( D3DFmtGetBpp(NULL, pixelformat) != DevModeW.dmBitsPerPel) ) continue;
1818 TRACE("Enumerating %ldx%ld@%s\n", DevModeW.dmPelsWidth, DevModeW.dmPelsHeight, debug_d3dformat(pixelformat_for_depth(DevModeW.dmBitsPerPel)));
1820 if (callback((IUnknown *) This, (UINT) DevModeW.dmPelsWidth, (UINT) DevModeW.dmPelsHeight, pixelformat_for_depth(DevModeW.dmBitsPerPel), 60.0, context) == DDENUMRET_CANCEL)
1821 return D3D_OK;
1824 return D3D_OK;
1827 HRESULT WINAPI IWineD3DDeviceImpl_SetDisplayMode(IWineD3DDevice *iface, UINT iSwapChain, WINED3DDISPLAYMODE* pMode) {
1828 DEVMODEW devmode;
1829 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
1830 LONG ret;
1832 TRACE("(%p)->(%d,%p) Mode=%dx%dx@%d, %s\n", This, iSwapChain, pMode, pMode->Width, pMode->Height, pMode->RefreshRate, debug_d3dformat(pMode->Format));
1834 /* Resize the screen even without a window:
1835 * The app could have unset it with SetCooperativeLevel, but not called
1836 * RestoreDisplayMode first. Then the release will call RestoreDisplayMode,
1837 * but we don't have any hwnd
1840 devmode.dmFields = DM_BITSPERPEL | DM_PELSWIDTH | DM_PELSHEIGHT;
1841 devmode.dmBitsPerPel = D3DFmtGetBpp(This, pMode->Format) * 8;
1842 if(devmode.dmBitsPerPel == 24) devmode.dmBitsPerPel = 32;
1843 devmode.dmPelsWidth = pMode->Width;
1844 devmode.dmPelsHeight = pMode->Height;
1846 devmode.dmDisplayFrequency = pMode->RefreshRate;
1847 if (pMode->RefreshRate != 0) {
1848 devmode.dmFields |= DM_DISPLAYFREQUENCY;
1851 /* Only change the mode if necessary */
1852 if( (This->ddraw_width == pMode->Width) &&
1853 (This->ddraw_height == pMode->Height) &&
1854 (This->ddraw_format == pMode->Format) &&
1855 (pMode->RefreshRate == 0) ) {
1856 return D3D_OK;
1859 ret = ChangeDisplaySettingsExW(NULL, &devmode, NULL, CDS_FULLSCREEN, NULL);
1860 if (ret != DISP_CHANGE_SUCCESSFUL) {
1861 if(devmode.dmDisplayFrequency != 0) {
1862 WARN("ChangeDisplaySettingsExW failed, trying without the refresh rate\n");
1863 devmode.dmFields &= ~DM_DISPLAYFREQUENCY;
1864 devmode.dmDisplayFrequency = 0;
1865 ret = ChangeDisplaySettingsExW(NULL, &devmode, NULL, CDS_FULLSCREEN, NULL) != DISP_CHANGE_SUCCESSFUL;
1867 if(ret != DISP_CHANGE_SUCCESSFUL) {
1868 return DDERR_INVALIDMODE;
1872 /* Store the new values */
1873 This->ddraw_width = pMode->Width;
1874 This->ddraw_height = pMode->Height;
1875 This->ddraw_format = pMode->Format;
1877 /* Only do this with a window of course */
1878 if(This->ddraw_window)
1879 MoveWindow(This->ddraw_window, 0, 0, pMode->Width, pMode->Height, TRUE);
1881 return WINED3D_OK;
1884 HRESULT WINAPI IWineD3DDeviceImpl_EnumZBufferFormats(IWineD3DDevice *iface, D3DCB_ENUMPIXELFORMATS Callback, void *Context) {
1885 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *) iface;
1886 HRESULT ret;
1887 int i = 0;
1888 WINED3DFORMAT FormatList[] = {
1889 WINED3DFMT_D16,
1890 WINED3DFMT_D32,
1891 WINED3DFMT_D24X4S4,
1892 WINED3DFMT_D24S8,
1893 WINED3DFMT_D24X8,
1894 WINED3DFMT_D15S1,
1895 WINED3DFMT_UNKNOWN /* Terminate the list */
1898 TRACE("(%p)->(%p,%p)\n", This, Callback, Context);
1900 while(FormatList[i] != WINED3DFMT_UNKNOWN) {
1901 TRACE("Enumerating %s\n", debug_d3dformat(FormatList[i]));
1902 ret = Callback((IUnknown *) This, FormatList[i], Context);
1903 if(ret != DDENUMRET_OK) {
1904 TRACE("Enumeration cancelled by Application\n");
1905 return WINED3D_OK;
1907 i++;
1910 TRACE("End of Enumeration\n");
1912 return WINED3D_OK;
1915 HRESULT WINAPI IWineD3DDeviceImpl_EnumTextureFormats(IWineD3DDevice *iface, D3DCB_ENUMPIXELFORMATS Callback, void *Context) {
1916 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *) iface;
1917 HRESULT ret;
1918 int i = 0;
1920 /* From old ddraw:
1921 * WINED3DFMT_A1R5G5B5 needs to be the first 16 bit format, as some dumb apps depend on this
1923 * Do not enumerate RGBA pixel formats: "some games choose the first 16 bit texture format
1924 * with alpha they find enumerated, others the last one. And both want to have the ARGB one."
1925 * But WineD3D doesn't support RGBA formats anyway...
1928 WINED3DFORMAT FormatList[] = {
1929 /* 32 bit */
1930 WINED3DFMT_A8R8G8B8,
1931 WINED3DFMT_X8R8G8B8,
1932 /* 24 bit */
1933 WINED3DFMT_R8G8B8,
1934 /* 16 Bit */
1935 WINED3DFMT_A1R5G5B5,
1936 WINED3DFMT_A4R4G4B4,
1937 WINED3DFMT_R5G6B5,
1938 WINED3DFMT_X1R5G5B5,
1939 /* 8 Bit */
1940 WINED3DFMT_R3G3B2,
1941 WINED3DFMT_P8,
1942 /* FOURCC codes */
1943 WINED3DFMT_DXT1,
1944 WINED3DFMT_DXT3,
1945 WINED3DFMT_DXT5,
1946 /* Terminate the list */
1947 WINED3DFMT_UNKNOWN
1950 TRACE("(%p)->(%p,%p)\n", This, Callback, Context);
1952 while(FormatList[i] != WINED3DFMT_UNKNOWN) {
1953 TRACE("Enumerating %s\n", debug_d3dformat(FormatList[i]));
1954 ret = Callback((IUnknown *) This, FormatList[i], Context);
1955 if(ret != DDENUMRET_OK) {
1956 TRACE("Enumeration cancelled by Application\n");
1957 return WINED3D_OK;
1959 i++;
1962 TRACE("End of Enumeration\n");
1964 return WINED3D_OK;
1967 HRESULT WINAPI IWineD3DDeviceImpl_GetDirect3D(IWineD3DDevice *iface, IWineD3D **ppD3D) {
1968 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
1969 *ppD3D= This->wineD3D;
1970 TRACE("(%p) : wineD3D returning %p\n", This, *ppD3D);
1971 IWineD3D_AddRef(*ppD3D);
1972 return WINED3D_OK;
1975 UINT WINAPI IWineD3DDeviceImpl_GetAvailableTextureMem(IWineD3DDevice *iface) {
1976 /** NOTE: There's a probably a hack-around for this one by putting as many pbuffers, VBO's (or whatever)
1977 * Into the video ram as possible and seeing how many fit
1978 * you can also get the correct initial value from via X and ATI's driver
1979 *******************/
1980 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
1981 static BOOL showfixmes = TRUE;
1982 if (showfixmes) {
1983 FIXME("(%p) : stub, emulating %dMB for now, returning %dMB\n", This, (emulated_textureram/(1024*1024)),
1984 ((emulated_textureram - wineD3DGlobalStatistics->glsurfaceram) / (1024*1024)));
1985 showfixmes = FALSE;
1987 TRACE("(%p) : emulating %dMB for now, returning %dMB\n", This, (emulated_textureram/(1024*1024)),
1988 ((emulated_textureram - wineD3DGlobalStatistics->glsurfaceram) / (1024*1024)));
1989 /* videomemory is simulated videomemory + AGP memory left */
1990 return (emulated_textureram - wineD3DGlobalStatistics->glsurfaceram);
1995 /*****
1996 * Get / Set FVF
1997 *****/
1998 HRESULT WINAPI IWineD3DDeviceImpl_SetFVF(IWineD3DDevice *iface, DWORD fvf) {
1999 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2000 HRESULT hr = WINED3D_OK;
2002 /* Update the current state block */
2003 This->updateStateBlock->fvf = fvf;
2004 This->updateStateBlock->changed.fvf = TRUE;
2005 This->updateStateBlock->set.fvf = TRUE;
2007 TRACE("(%p) : FVF Shader FVF set to %lx\n", This, fvf);
2009 if (0 != fvf) {
2010 /* clear down the vertex declaration
2011 NOTE: Axis and Allies doesn't work properly otherwise
2012 (may be a stateblock problem though!)
2014 hr = IWineD3DDevice_SetVertexDeclaration(iface, NULL);
2017 return hr;
2021 HRESULT WINAPI IWineD3DDeviceImpl_GetFVF(IWineD3DDevice *iface, DWORD *pfvf) {
2022 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2023 TRACE("(%p) : GetFVF returning %lx\n", This, This->stateBlock->fvf);
2024 *pfvf = This->stateBlock->fvf;
2025 return WINED3D_OK;
2028 /*****
2029 * Get / Set Stream Source
2030 *****/
2031 HRESULT WINAPI IWineD3DDeviceImpl_SetStreamSource(IWineD3DDevice *iface, UINT StreamNumber,IWineD3DVertexBuffer* pStreamData, UINT OffsetInBytes, UINT Stride) {
2032 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2033 IWineD3DVertexBuffer *oldSrc;
2035 /**TODO: instance and index data, see
2036 http://msdn.microsoft.com/library/default.asp?url=/library/en-us/directx9_c/directx/graphics/programmingguide/advancedtopics/DrawingMultipleInstances.asp
2038 http://msdn.microsoft.com/library/default.asp?url=/library/en-us/directx9_c/directx/graphics/reference/d3d/interfaces/idirect3ddevice9/SetStreamSourceFreq.asp
2039 **************/
2041 /* D3d9 only, but shouldn't hurt d3d8 */
2042 UINT streamFlags;
2044 streamFlags = StreamNumber &(D3DSTREAMSOURCE_INDEXEDDATA | D3DSTREAMSOURCE_INSTANCEDATA);
2045 if (streamFlags) {
2046 if (streamFlags & D3DSTREAMSOURCE_INDEXEDDATA) {
2047 FIXME("stream index data not supported\n");
2049 if (streamFlags & D3DSTREAMSOURCE_INDEXEDDATA) {
2050 FIXME("stream instance data not supported\n");
2054 StreamNumber&= ~(D3DSTREAMSOURCE_INDEXEDDATA | D3DSTREAMSOURCE_INSTANCEDATA);
2056 if (StreamNumber >= MAX_STREAMS) {
2057 WARN("Stream out of range %d\n", StreamNumber);
2058 return WINED3DERR_INVALIDCALL;
2061 oldSrc = This->stateBlock->streamSource[StreamNumber];
2062 TRACE("(%p) : StreamNo: %d, OldStream (%p), NewStream (%p), NewStride %d\n", This, StreamNumber, oldSrc, pStreamData, Stride);
2064 This->updateStateBlock->changed.streamSource[StreamNumber] = TRUE;
2065 This->updateStateBlock->set.streamSource[StreamNumber] = TRUE;
2066 This->updateStateBlock->streamStride[StreamNumber] = Stride;
2067 This->updateStateBlock->streamSource[StreamNumber] = pStreamData;
2068 This->updateStateBlock->streamOffset[StreamNumber] = OffsetInBytes;
2069 This->updateStateBlock->streamFlags[StreamNumber] = streamFlags;
2071 /* Handle recording of state blocks */
2072 if (This->isRecordingState) {
2073 TRACE("Recording... not performing anything\n");
2074 return WINED3D_OK;
2077 /* Not recording... */
2078 /* Need to do a getParent and pass the reffs up */
2079 /* MSDN says ..... When an application no longer holds a references to this interface, the interface will automatically be freed.
2080 which suggests that we shouldn't be ref counting? and do need a _release on the stream source to reset the stream source
2081 so for now, just count internally */
2082 if (pStreamData != NULL) {
2083 IWineD3DVertexBuffer_AddRef(pStreamData);
2085 if (oldSrc != NULL) {
2086 IWineD3DVertexBuffer_Release(oldSrc);
2089 return WINED3D_OK;
2092 HRESULT WINAPI IWineD3DDeviceImpl_GetStreamSource(IWineD3DDevice *iface, UINT StreamNumber,IWineD3DVertexBuffer** pStream, UINT *pOffset, UINT* pStride) {
2093 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2094 UINT streamFlags;
2096 TRACE("(%p) : StreamNo: %d, Stream (%p), Stride %d\n", This, StreamNumber,
2097 This->stateBlock->streamSource[StreamNumber], This->stateBlock->streamStride[StreamNumber]);
2100 streamFlags = StreamNumber &(D3DSTREAMSOURCE_INDEXEDDATA | D3DSTREAMSOURCE_INSTANCEDATA);
2101 if (streamFlags) {
2102 if (streamFlags & D3DSTREAMSOURCE_INDEXEDDATA) {
2103 FIXME("stream index data not supported\n");
2105 if (streamFlags & D3DSTREAMSOURCE_INDEXEDDATA) {
2106 FIXME("stream instance data not supported\n");
2110 StreamNumber&= ~(D3DSTREAMSOURCE_INDEXEDDATA | D3DSTREAMSOURCE_INSTANCEDATA);
2112 if (StreamNumber >= MAX_STREAMS) {
2113 WARN("Stream out of range %d\n", StreamNumber);
2114 return WINED3DERR_INVALIDCALL;
2116 *pStream = This->stateBlock->streamSource[StreamNumber];
2117 *pStride = This->stateBlock->streamStride[StreamNumber];
2118 *pOffset = This->stateBlock->streamOffset[StreamNumber];
2120 if (*pStream == NULL) {
2121 FIXME("Attempting to get an empty stream %d, returning WINED3DERR_INVALIDCALL\n", StreamNumber);
2122 return WINED3DERR_INVALIDCALL;
2125 IWineD3DVertexBuffer_AddRef(*pStream); /* We have created a new reference to the VB */
2126 return WINED3D_OK;
2129 /*Should be quite easy, just an extension of vertexdata
2130 ref...
2131 http://msdn.microsoft.com/archive/default.asp?url=/archive/en-us/directx9_c_Summer_04/directx/graphics/programmingguide/advancedtopics/DrawingMultipleInstances.asp
2133 The divider is a bit odd though
2135 VertexOffset = StartVertex / Divider * StreamStride +
2136 VertexIndex / Divider * StreamStride + StreamOffset
2139 HRESULT WINAPI IWineD3DDeviceImpl_SetStreamSourceFreq(IWineD3DDevice *iface, UINT StreamNumber, UINT Divider) {
2140 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2142 TRACE("(%p) StreamNumber(%d), Divider(%d)\n", This, StreamNumber, Divider);
2143 This->updateStateBlock->streamFlags[StreamNumber] = Divider & (D3DSTREAMSOURCE_INSTANCEDATA | D3DSTREAMSOURCE_INDEXEDDATA );
2145 This->updateStateBlock->changed.streamFreq[StreamNumber] = TRUE;
2146 This->updateStateBlock->set.streamFreq[StreamNumber] = TRUE;
2147 This->updateStateBlock->streamFreq[StreamNumber] = Divider & 0x7FFFFF;
2149 if (This->updateStateBlock->streamFlags[StreamNumber] || This->updateStateBlock->streamFreq[StreamNumber] != 1) {
2150 FIXME("Stream indexing not fully supported\n");
2153 return WINED3D_OK;
2156 HRESULT WINAPI IWineD3DDeviceImpl_GetStreamSourceFreq(IWineD3DDevice *iface, UINT StreamNumber, UINT* Divider) {
2157 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2159 TRACE("(%p) StreamNumber(%d), Divider(%p)\n", This, StreamNumber, Divider);
2160 *Divider = This->updateStateBlock->streamFreq[StreamNumber] | This->updateStateBlock->streamFlags[StreamNumber];
2162 TRACE("(%p) : returning %d\n", This, *Divider);
2164 return WINED3D_OK;
2167 /*****
2168 * Get / Set & Multiply Transform
2169 *****/
2170 HRESULT WINAPI IWineD3DDeviceImpl_SetTransform(IWineD3DDevice *iface, D3DTRANSFORMSTATETYPE d3dts, CONST D3DMATRIX* lpmatrix) {
2171 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2173 /* Most of this routine, comments included copied from ddraw tree initially: */
2174 TRACE("(%p) : Transform State=%d\n", This, d3dts);
2176 /* Handle recording of state blocks */
2177 if (This->isRecordingState) {
2178 TRACE("Recording... not performing anything\n");
2179 This->updateStateBlock->changed.transform[d3dts] = TRUE;
2180 This->updateStateBlock->set.transform[d3dts] = TRUE;
2181 memcpy(&This->updateStateBlock->transforms[d3dts], lpmatrix, sizeof(D3DMATRIX));
2182 return WINED3D_OK;
2186 * If the new matrix is the same as the current one,
2187 * we cut off any further processing. this seems to be a reasonable
2188 * optimization because as was noticed, some apps (warcraft3 for example)
2189 * tend towards setting the same matrix repeatedly for some reason.
2191 * From here on we assume that the new matrix is different, wherever it matters.
2193 if (!memcmp(&This->stateBlock->transforms[d3dts].u.m[0][0], lpmatrix, sizeof(D3DMATRIX))) {
2194 TRACE("The app is setting the same matrix over again\n");
2195 return WINED3D_OK;
2196 } else {
2197 conv_mat(lpmatrix, &This->stateBlock->transforms[d3dts].u.m[0][0]);
2201 ScreenCoord = ProjectionMat * ViewMat * WorldMat * ObjectCoord
2202 where ViewMat = Camera space, WorldMat = world space.
2204 In OpenGL, camera and world space is combined into GL_MODELVIEW
2205 matrix. The Projection matrix stay projection matrix.
2208 /* Capture the times we can just ignore the change for now */
2209 if (d3dts == D3DTS_WORLDMATRIX(0)) {
2210 This->modelview_valid = FALSE;
2211 return WINED3D_OK;
2213 } else if (d3dts == D3DTS_PROJECTION) {
2214 This->proj_valid = FALSE;
2215 return WINED3D_OK;
2217 } else if (d3dts >= D3DTS_WORLDMATRIX(1) && d3dts <= D3DTS_WORLDMATRIX(255)) {
2218 /* Indexed Vertex Blending Matrices 256 -> 511 */
2219 /* Use arb_vertex_blend or NV_VERTEX_WEIGHTING? */
2220 FIXME("D3DTS_WORLDMATRIX(1..255) not handled\n");
2221 return WINED3D_OK;
2224 /* Now we really are going to have to change a matrix */
2225 ENTER_GL();
2227 if (d3dts >= D3DTS_TEXTURE0 && d3dts <= D3DTS_TEXTURE7) { /* handle texture matrices */
2228 /* This is now set with the texture unit states, it may be a good idea to flag the change though! */
2229 } else if (d3dts == D3DTS_VIEW) { /* handle the VIEW matrice */
2230 unsigned int k;
2232 /* If we are changing the View matrix, reset the light and clipping planes to the new view
2233 * NOTE: We have to reset the positions even if the light/plane is not currently
2234 * enabled, since the call to enable it will not reset the position.
2235 * NOTE2: Apparently texture transforms do NOT need reapplying
2238 PLIGHTINFOEL *lightChain = NULL;
2239 This->modelview_valid = FALSE;
2240 This->view_ident = !memcmp(lpmatrix, identity, 16 * sizeof(float));
2242 glMatrixMode(GL_MODELVIEW);
2243 checkGLcall("glMatrixMode(GL_MODELVIEW)");
2244 glPushMatrix();
2245 glLoadMatrixf((float *)lpmatrix);
2246 checkGLcall("glLoadMatrixf(...)");
2248 /* Reset lights */
2249 lightChain = This->stateBlock->lights;
2250 while (lightChain && lightChain->glIndex != -1) {
2251 glLightfv(GL_LIGHT0 + lightChain->glIndex, GL_POSITION, lightChain->lightPosn);
2252 checkGLcall("glLightfv posn");
2253 glLightfv(GL_LIGHT0 + lightChain->glIndex, GL_SPOT_DIRECTION, lightChain->lightDirn);
2254 checkGLcall("glLightfv dirn");
2255 lightChain = lightChain->next;
2258 /* Reset Clipping Planes if clipping is enabled */
2259 for (k = 0; k < GL_LIMITS(clipplanes); k++) {
2260 glClipPlane(GL_CLIP_PLANE0 + k, This->stateBlock->clipplane[k]);
2261 checkGLcall("glClipPlane");
2263 glPopMatrix();
2265 } else { /* What was requested!?? */
2266 WARN("invalid matrix specified: %i\n", d3dts);
2269 /* Release lock, all done */
2270 LEAVE_GL();
2271 return WINED3D_OK;
2274 HRESULT WINAPI IWineD3DDeviceImpl_GetTransform(IWineD3DDevice *iface, D3DTRANSFORMSTATETYPE State, D3DMATRIX* pMatrix) {
2275 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2276 TRACE("(%p) : for Transform State %d\n", This, State);
2277 memcpy(pMatrix, &This->stateBlock->transforms[State], sizeof(D3DMATRIX));
2278 return WINED3D_OK;
2281 HRESULT WINAPI IWineD3DDeviceImpl_MultiplyTransform(IWineD3DDevice *iface, D3DTRANSFORMSTATETYPE State, CONST D3DMATRIX* pMatrix) {
2282 D3DMATRIX *mat = NULL;
2283 D3DMATRIX temp;
2285 /* Note: Using 'updateStateBlock' rather than 'stateblock' in the code
2286 * below means it will be recorded in a state block change, but it
2287 * works regardless where it is recorded.
2288 * If this is found to be wrong, change to StateBlock.
2290 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2291 TRACE("(%p) : For state %u\n", This, State);
2293 if (State < HIGHEST_TRANSFORMSTATE)
2295 mat = &This->updateStateBlock->transforms[State];
2296 } else {
2297 FIXME("Unhandled transform state!!\n");
2300 multiply_matrix(&temp, mat, (D3DMATRIX *) pMatrix);
2302 /* Apply change via set transform - will reapply to eg. lights this way */
2303 return IWineD3DDeviceImpl_SetTransform(iface, State, &temp);
2306 /*****
2307 * Get / Set Light
2308 * WARNING: This code relies on the fact that D3DLIGHT8 == D3DLIGHT9
2309 *****/
2310 /* Note lights are real special cases. Although the device caps state only eg. 8 are supported,
2311 you can reference any indexes you want as long as that number max are enabled at any
2312 one point in time! Therefore since the indexes can be anything, we need a linked list of them.
2313 However, this causes stateblock problems. When capturing the state block, I duplicate the list,
2314 but when recording, just build a chain pretty much of commands to be replayed. */
2316 HRESULT WINAPI IWineD3DDeviceImpl_SetLight(IWineD3DDevice *iface, DWORD Index, CONST WINED3DLIGHT* pLight) {
2317 float rho;
2318 PLIGHTINFOEL *object, *temp;
2320 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2321 TRACE("(%p) : Idx(%ld), pLight(%p)\n", This, Index, pLight);
2323 /* If recording state block, just add to end of lights chain */
2324 if (This->isRecordingState) {
2325 object = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(PLIGHTINFOEL));
2326 if (NULL == object) {
2327 return WINED3DERR_OUTOFVIDEOMEMORY;
2329 memcpy(&object->OriginalParms, pLight, sizeof(D3DLIGHT9));
2330 object->OriginalIndex = Index;
2331 object->glIndex = -1;
2332 object->changed = TRUE;
2334 /* Add to the END of the chain of lights changes to be replayed */
2335 if (This->updateStateBlock->lights == NULL) {
2336 This->updateStateBlock->lights = object;
2337 } else {
2338 temp = This->updateStateBlock->lights;
2339 while (temp->next != NULL) temp=temp->next;
2340 temp->next = object;
2342 TRACE("Recording... not performing anything more\n");
2343 return WINED3D_OK;
2346 /* Ok, not recording any longer so do real work */
2347 object = This->stateBlock->lights;
2348 while (object != NULL && object->OriginalIndex != Index) object = object->next;
2350 /* If we didn't find it in the list of lights, time to add it */
2351 if (object == NULL) {
2352 PLIGHTINFOEL *insertAt,*prevPos;
2354 object = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(PLIGHTINFOEL));
2355 if (NULL == object) {
2356 return WINED3DERR_OUTOFVIDEOMEMORY;
2358 object->OriginalIndex = Index;
2359 object->glIndex = -1;
2361 /* Add it to the front of list with the idea that lights will be changed as needed
2362 BUT after any lights currently assigned GL indexes */
2363 insertAt = This->stateBlock->lights;
2364 prevPos = NULL;
2365 while (insertAt != NULL && insertAt->glIndex != -1) {
2366 prevPos = insertAt;
2367 insertAt = insertAt->next;
2370 if (insertAt == NULL && prevPos == NULL) { /* Start of list */
2371 This->stateBlock->lights = object;
2372 } else if (insertAt == NULL) { /* End of list */
2373 prevPos->next = object;
2374 object->prev = prevPos;
2375 } else { /* Middle of chain */
2376 if (prevPos == NULL) {
2377 This->stateBlock->lights = object;
2378 } else {
2379 prevPos->next = object;
2381 object->prev = prevPos;
2382 object->next = insertAt;
2383 insertAt->prev = object;
2387 /* Initialize the object */
2388 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,
2389 pLight->Diffuse.r, pLight->Diffuse.g, pLight->Diffuse.b, pLight->Diffuse.a,
2390 pLight->Specular.r, pLight->Specular.g, pLight->Specular.b, pLight->Specular.a,
2391 pLight->Ambient.r, pLight->Ambient.g, pLight->Ambient.b, pLight->Ambient.a);
2392 TRACE("... Pos(%f,%f,%f), Dirn(%f,%f,%f)\n", pLight->Position.x, pLight->Position.y, pLight->Position.z,
2393 pLight->Direction.x, pLight->Direction.y, pLight->Direction.z);
2394 TRACE("... Range(%f), Falloff(%f), Theta(%f), Phi(%f)\n", pLight->Range, pLight->Falloff, pLight->Theta, pLight->Phi);
2396 /* Save away the information */
2397 memcpy(&object->OriginalParms, pLight, sizeof(D3DLIGHT9));
2399 switch (pLight->Type) {
2400 case D3DLIGHT_POINT:
2401 /* Position */
2402 object->lightPosn[0] = pLight->Position.x;
2403 object->lightPosn[1] = pLight->Position.y;
2404 object->lightPosn[2] = pLight->Position.z;
2405 object->lightPosn[3] = 1.0f;
2406 object->cutoff = 180.0f;
2407 /* FIXME: Range */
2408 break;
2410 case D3DLIGHT_DIRECTIONAL:
2411 /* Direction */
2412 object->lightPosn[0] = -pLight->Direction.x;
2413 object->lightPosn[1] = -pLight->Direction.y;
2414 object->lightPosn[2] = -pLight->Direction.z;
2415 object->lightPosn[3] = 0.0;
2416 object->exponent = 0.0f;
2417 object->cutoff = 180.0f;
2418 break;
2420 case D3DLIGHT_SPOT:
2421 /* Position */
2422 object->lightPosn[0] = pLight->Position.x;
2423 object->lightPosn[1] = pLight->Position.y;
2424 object->lightPosn[2] = pLight->Position.z;
2425 object->lightPosn[3] = 1.0;
2427 /* Direction */
2428 object->lightDirn[0] = pLight->Direction.x;
2429 object->lightDirn[1] = pLight->Direction.y;
2430 object->lightDirn[2] = pLight->Direction.z;
2431 object->lightDirn[3] = 1.0;
2434 * opengl-ish and d3d-ish spot lights use too different models for the
2435 * light "intensity" as a function of the angle towards the main light direction,
2436 * so we only can approximate very roughly.
2437 * however spot lights are rather rarely used in games (if ever used at all).
2438 * furthermore if still used, probably nobody pays attention to such details.
2440 if (pLight->Falloff == 0) {
2441 rho = 6.28f;
2442 } else {
2443 rho = pLight->Theta + (pLight->Phi - pLight->Theta)/(2*pLight->Falloff);
2445 if (rho < 0.0001) rho = 0.0001f;
2446 object->exponent = -0.3/log(cos(rho/2));
2447 object->cutoff = pLight->Phi*90/M_PI;
2449 /* FIXME: Range */
2450 break;
2452 default:
2453 FIXME("Unrecognized light type %d\n", pLight->Type);
2456 /* Update the live definitions if the light is currently assigned a glIndex */
2457 if (object->glIndex != -1) {
2458 setup_light(iface, object->glIndex, object);
2460 return WINED3D_OK;
2463 HRESULT WINAPI IWineD3DDeviceImpl_GetLight(IWineD3DDevice *iface, DWORD Index, WINED3DLIGHT* pLight) {
2464 PLIGHTINFOEL *lightInfo = NULL;
2465 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2466 TRACE("(%p) : Idx(%ld), pLight(%p)\n", This, Index, pLight);
2468 /* Locate the light in the live lights */
2469 lightInfo = This->stateBlock->lights;
2470 while (lightInfo != NULL && lightInfo->OriginalIndex != Index) lightInfo = lightInfo->next;
2472 if (lightInfo == NULL) {
2473 TRACE("Light information requested but light not defined\n");
2474 return WINED3DERR_INVALIDCALL;
2477 memcpy(pLight, &lightInfo->OriginalParms, sizeof(D3DLIGHT9));
2478 return WINED3D_OK;
2481 /*****
2482 * Get / Set Light Enable
2483 * (Note for consistency, renamed d3dx function by adding the 'set' prefix)
2484 *****/
2485 HRESULT WINAPI IWineD3DDeviceImpl_SetLightEnable(IWineD3DDevice *iface, DWORD Index, BOOL Enable) {
2486 PLIGHTINFOEL *lightInfo = NULL;
2487 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2488 TRACE("(%p) : Idx(%ld), enable? %d\n", This, Index, Enable);
2490 /* If recording state block, just add to end of lights chain with changedEnable set to true */
2491 if (This->isRecordingState) {
2492 lightInfo = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(PLIGHTINFOEL));
2493 if (NULL == lightInfo) {
2494 return WINED3DERR_OUTOFVIDEOMEMORY;
2496 lightInfo->OriginalIndex = Index;
2497 lightInfo->glIndex = -1;
2498 lightInfo->enabledChanged = TRUE;
2500 /* Add to the END of the chain of lights changes to be replayed */
2501 if (This->updateStateBlock->lights == NULL) {
2502 This->updateStateBlock->lights = lightInfo;
2503 } else {
2504 PLIGHTINFOEL *temp = This->updateStateBlock->lights;
2505 while (temp->next != NULL) temp=temp->next;
2506 temp->next = lightInfo;
2508 TRACE("Recording... not performing anything more\n");
2509 return WINED3D_OK;
2512 /* Not recording... So, locate the light in the live lights */
2513 lightInfo = This->stateBlock->lights;
2514 while (lightInfo != NULL && lightInfo->OriginalIndex != Index) lightInfo = lightInfo->next;
2516 /* Special case - enabling an undefined light creates one with a strict set of parms! */
2517 if (lightInfo == NULL) {
2518 D3DLIGHT9 lightParms;
2519 /* Warning - untested code :-) Prob safe to change fixme to a trace but
2520 wait until someone confirms it seems to work! */
2521 TRACE("Light enabled requested but light not defined, so defining one!\n");
2522 lightParms.Type = D3DLIGHT_DIRECTIONAL;
2523 lightParms.Diffuse.r = 1.0;
2524 lightParms.Diffuse.g = 1.0;
2525 lightParms.Diffuse.b = 1.0;
2526 lightParms.Diffuse.a = 0.0;
2527 lightParms.Specular.r = 0.0;
2528 lightParms.Specular.g = 0.0;
2529 lightParms.Specular.b = 0.0;
2530 lightParms.Specular.a = 0.0;
2531 lightParms.Ambient.r = 0.0;
2532 lightParms.Ambient.g = 0.0;
2533 lightParms.Ambient.b = 0.0;
2534 lightParms.Ambient.a = 0.0;
2535 lightParms.Position.x = 0.0;
2536 lightParms.Position.y = 0.0;
2537 lightParms.Position.z = 0.0;
2538 lightParms.Direction.x = 0.0;
2539 lightParms.Direction.y = 0.0;
2540 lightParms.Direction.z = 1.0;
2541 lightParms.Range = 0.0;
2542 lightParms.Falloff = 0.0;
2543 lightParms.Attenuation0 = 0.0;
2544 lightParms.Attenuation1 = 0.0;
2545 lightParms.Attenuation2 = 0.0;
2546 lightParms.Theta = 0.0;
2547 lightParms.Phi = 0.0;
2548 IWineD3DDeviceImpl_SetLight(iface, Index, &lightParms);
2550 /* Search for it again! Should be fairly quick as near head of list */
2551 lightInfo = This->stateBlock->lights;
2552 while (lightInfo != NULL && lightInfo->OriginalIndex != Index) lightInfo = lightInfo->next;
2553 if (lightInfo == NULL) {
2554 FIXME("Adding default lights has failed dismally\n");
2555 return WINED3DERR_INVALIDCALL;
2559 /* OK, we now have a light... */
2560 if (Enable == FALSE) {
2562 /* If we are disabling it, check it was enabled, and
2563 still only do something if it has assigned a glIndex (which it should have!) */
2564 if ((lightInfo->lightEnabled) && (lightInfo->glIndex != -1)) {
2565 TRACE("Disabling light set up at gl idx %ld\n", lightInfo->glIndex);
2566 ENTER_GL();
2567 glDisable(GL_LIGHT0 + lightInfo->glIndex);
2568 checkGLcall("glDisable GL_LIGHT0+Index");
2569 LEAVE_GL();
2570 } else {
2571 TRACE("Nothing to do as light was not enabled\n");
2573 lightInfo->lightEnabled = FALSE;
2574 } else {
2576 /* We are enabling it. If it is enabled, it's really simple */
2577 if (lightInfo->lightEnabled) {
2578 /* nop */
2579 TRACE("Nothing to do as light was enabled\n");
2581 /* If it already has a glIndex, it's still simple */
2582 } else if (lightInfo->glIndex != -1) {
2583 TRACE("Reusing light as already set up at gl idx %ld\n", lightInfo->glIndex);
2584 lightInfo->lightEnabled = TRUE;
2585 ENTER_GL();
2586 glEnable(GL_LIGHT0 + lightInfo->glIndex);
2587 checkGLcall("glEnable GL_LIGHT0+Index already setup");
2588 LEAVE_GL();
2590 /* Otherwise got to find space - lights are ordered gl indexes first */
2591 } else {
2592 PLIGHTINFOEL *bsf = NULL;
2593 PLIGHTINFOEL *pos = This->stateBlock->lights;
2594 PLIGHTINFOEL *prev = NULL;
2595 int Index= 0;
2596 int glIndex = -1;
2598 /* Try to minimize changes as much as possible */
2599 while (pos != NULL && pos->glIndex != -1 && Index < This->maxConcurrentLights) {
2601 /* Try to remember which index can be replaced if necessary */
2602 if (bsf==NULL && pos->lightEnabled == FALSE) {
2603 /* Found a light we can replace, save as best replacement */
2604 bsf = pos;
2607 /* Step to next space */
2608 prev = pos;
2609 pos = pos->next;
2610 Index ++;
2613 /* If we have too many active lights, fail the call */
2614 if ((Index == This->maxConcurrentLights) && (bsf == NULL)) {
2615 FIXME("Program requests too many concurrent lights\n");
2616 return WINED3DERR_INVALIDCALL;
2618 /* If we have allocated all lights, but not all are enabled,
2619 reuse one which is not enabled */
2620 } else if (Index == This->maxConcurrentLights) {
2621 /* use bsf - Simply swap the new light and the BSF one */
2622 PLIGHTINFOEL *bsfNext = bsf->next;
2623 PLIGHTINFOEL *bsfPrev = bsf->prev;
2625 /* Sort out ends */
2626 if (lightInfo->next != NULL) lightInfo->next->prev = bsf;
2627 if (bsf->prev != NULL) {
2628 bsf->prev->next = lightInfo;
2629 } else {
2630 This->stateBlock->lights = lightInfo;
2633 /* If not side by side, lots of chains to update */
2634 if (bsf->next != lightInfo) {
2635 lightInfo->prev->next = bsf;
2636 bsf->next->prev = lightInfo;
2637 bsf->next = lightInfo->next;
2638 bsf->prev = lightInfo->prev;
2639 lightInfo->next = bsfNext;
2640 lightInfo->prev = bsfPrev;
2642 } else {
2643 /* Simple swaps */
2644 bsf->prev = lightInfo;
2645 bsf->next = lightInfo->next;
2646 lightInfo->next = bsf;
2647 lightInfo->prev = bsfPrev;
2651 /* Update states */
2652 glIndex = bsf->glIndex;
2653 bsf->glIndex = -1;
2654 lightInfo->glIndex = glIndex;
2655 lightInfo->lightEnabled = TRUE;
2657 /* Finally set up the light in gl itself */
2658 TRACE("Replacing light which was set up at gl idx %ld\n", lightInfo->glIndex);
2659 ENTER_GL();
2660 setup_light(iface, glIndex, lightInfo);
2661 glEnable(GL_LIGHT0 + glIndex);
2662 checkGLcall("glEnable GL_LIGHT0 new setup");
2663 LEAVE_GL();
2665 /* If we reached the end of the allocated lights, with space in the
2666 gl lights, setup a new light */
2667 } else if (pos->glIndex == -1) {
2669 /* We reached the end of the allocated gl lights, so already
2670 know the index of the next one! */
2671 glIndex = Index;
2672 lightInfo->glIndex = glIndex;
2673 lightInfo->lightEnabled = TRUE;
2675 /* In an ideal world, it's already in the right place */
2676 if (lightInfo->prev == NULL || lightInfo->prev->glIndex!=-1) {
2677 /* No need to move it */
2678 } else {
2679 /* Remove this light from the list */
2680 lightInfo->prev->next = lightInfo->next;
2681 if (lightInfo->next != NULL) {
2682 lightInfo->next->prev = lightInfo->prev;
2685 /* Add in at appropriate place (inbetween prev and pos) */
2686 lightInfo->prev = prev;
2687 lightInfo->next = pos;
2688 if (prev == NULL) {
2689 This->stateBlock->lights = lightInfo;
2690 } else {
2691 prev->next = lightInfo;
2693 if (pos != NULL) {
2694 pos->prev = lightInfo;
2698 /* Finally set up the light in gl itself */
2699 TRACE("Defining new light at gl idx %ld\n", lightInfo->glIndex);
2700 ENTER_GL();
2701 setup_light(iface, glIndex, lightInfo);
2702 glEnable(GL_LIGHT0 + glIndex);
2703 checkGLcall("glEnable GL_LIGHT0 new setup");
2704 LEAVE_GL();
2709 return WINED3D_OK;
2712 HRESULT WINAPI IWineD3DDeviceImpl_GetLightEnable(IWineD3DDevice *iface, DWORD Index,BOOL* pEnable) {
2714 PLIGHTINFOEL *lightInfo = NULL;
2715 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2716 TRACE("(%p) : for idx(%ld)\n", This, Index);
2718 /* Locate the light in the live lights */
2719 lightInfo = This->stateBlock->lights;
2720 while (lightInfo != NULL && lightInfo->OriginalIndex != Index) lightInfo = lightInfo->next;
2722 if (lightInfo == NULL) {
2723 TRACE("Light enabled state requested but light not defined\n");
2724 return WINED3DERR_INVALIDCALL;
2726 *pEnable = lightInfo->lightEnabled;
2727 return WINED3D_OK;
2730 /*****
2731 * Get / Set Clip Planes
2732 *****/
2733 HRESULT WINAPI IWineD3DDeviceImpl_SetClipPlane(IWineD3DDevice *iface, DWORD Index, CONST float *pPlane) {
2734 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2735 TRACE("(%p) : for idx %ld, %p\n", This, Index, pPlane);
2737 /* Validate Index */
2738 if (Index >= GL_LIMITS(clipplanes)) {
2739 TRACE("Application has requested clipplane this device doesn't support\n");
2740 return WINED3DERR_INVALIDCALL;
2743 This->updateStateBlock->changed.clipplane[Index] = TRUE;
2744 This->updateStateBlock->set.clipplane[Index] = TRUE;
2745 This->updateStateBlock->clipplane[Index][0] = pPlane[0];
2746 This->updateStateBlock->clipplane[Index][1] = pPlane[1];
2747 This->updateStateBlock->clipplane[Index][2] = pPlane[2];
2748 This->updateStateBlock->clipplane[Index][3] = pPlane[3];
2750 /* Handle recording of state blocks */
2751 if (This->isRecordingState) {
2752 TRACE("Recording... not performing anything\n");
2753 return WINED3D_OK;
2756 /* Apply it */
2758 ENTER_GL();
2760 /* Clip Plane settings are affected by the model view in OpenGL, the View transform in direct3d */
2761 glMatrixMode(GL_MODELVIEW);
2762 glPushMatrix();
2763 glLoadMatrixf((float *) &This->stateBlock->transforms[D3DTS_VIEW].u.m[0][0]);
2765 TRACE("Clipplane [%f,%f,%f,%f]\n",
2766 This->updateStateBlock->clipplane[Index][0],
2767 This->updateStateBlock->clipplane[Index][1],
2768 This->updateStateBlock->clipplane[Index][2],
2769 This->updateStateBlock->clipplane[Index][3]);
2770 glClipPlane(GL_CLIP_PLANE0 + Index, This->updateStateBlock->clipplane[Index]);
2771 checkGLcall("glClipPlane");
2773 glPopMatrix();
2774 LEAVE_GL();
2776 return WINED3D_OK;
2779 HRESULT WINAPI IWineD3DDeviceImpl_GetClipPlane(IWineD3DDevice *iface, DWORD Index, float *pPlane) {
2780 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2781 TRACE("(%p) : for idx %ld\n", This, Index);
2783 /* Validate Index */
2784 if (Index >= GL_LIMITS(clipplanes)) {
2785 TRACE("Application has requested clipplane this device doesn't support\n");
2786 return WINED3DERR_INVALIDCALL;
2789 pPlane[0] = This->stateBlock->clipplane[Index][0];
2790 pPlane[1] = This->stateBlock->clipplane[Index][1];
2791 pPlane[2] = This->stateBlock->clipplane[Index][2];
2792 pPlane[3] = This->stateBlock->clipplane[Index][3];
2793 return WINED3D_OK;
2796 /*****
2797 * Get / Set Clip Plane Status
2798 * WARNING: This code relies on the fact that D3DCLIPSTATUS8 == D3DCLIPSTATUS9
2799 *****/
2800 HRESULT WINAPI IWineD3DDeviceImpl_SetClipStatus(IWineD3DDevice *iface, CONST WINED3DCLIPSTATUS* pClipStatus) {
2801 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2802 FIXME("(%p) : stub\n", This);
2803 if (NULL == pClipStatus) {
2804 return WINED3DERR_INVALIDCALL;
2806 This->updateStateBlock->clip_status.ClipUnion = pClipStatus->ClipUnion;
2807 This->updateStateBlock->clip_status.ClipIntersection = pClipStatus->ClipIntersection;
2808 return WINED3D_OK;
2811 HRESULT WINAPI IWineD3DDeviceImpl_GetClipStatus(IWineD3DDevice *iface, WINED3DCLIPSTATUS* pClipStatus) {
2812 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2813 FIXME("(%p) : stub\n", This);
2814 if (NULL == pClipStatus) {
2815 return WINED3DERR_INVALIDCALL;
2817 pClipStatus->ClipUnion = This->updateStateBlock->clip_status.ClipUnion;
2818 pClipStatus->ClipIntersection = This->updateStateBlock->clip_status.ClipIntersection;
2819 return WINED3D_OK;
2822 /*****
2823 * Get / Set Material
2824 * WARNING: This code relies on the fact that D3DMATERIAL8 == D3DMATERIAL9
2825 *****/
2826 HRESULT WINAPI IWineD3DDeviceImpl_SetMaterial(IWineD3DDevice *iface, CONST WINED3DMATERIAL* pMaterial) {
2827 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2829 This->updateStateBlock->changed.material = TRUE;
2830 This->updateStateBlock->set.material = TRUE;
2831 memcpy(&This->updateStateBlock->material, pMaterial, sizeof(WINED3DMATERIAL));
2833 /* Handle recording of state blocks */
2834 if (This->isRecordingState) {
2835 TRACE("Recording... not performing anything\n");
2836 return WINED3D_OK;
2839 ENTER_GL();
2840 TRACE("(%p) : Diffuse (%f,%f,%f,%f)\n", This, pMaterial->Diffuse.r, pMaterial->Diffuse.g,
2841 pMaterial->Diffuse.b, pMaterial->Diffuse.a);
2842 TRACE("(%p) : Ambient (%f,%f,%f,%f)\n", This, pMaterial->Ambient.r, pMaterial->Ambient.g,
2843 pMaterial->Ambient.b, pMaterial->Ambient.a);
2844 TRACE("(%p) : Specular (%f,%f,%f,%f)\n", This, pMaterial->Specular.r, pMaterial->Specular.g,
2845 pMaterial->Specular.b, pMaterial->Specular.a);
2846 TRACE("(%p) : Emissive (%f,%f,%f,%f)\n", This, pMaterial->Emissive.r, pMaterial->Emissive.g,
2847 pMaterial->Emissive.b, pMaterial->Emissive.a);
2848 TRACE("(%p) : Power (%f)\n", This, pMaterial->Power);
2850 glMaterialfv(GL_FRONT_AND_BACK, GL_AMBIENT, (float*) &This->updateStateBlock->material.Ambient);
2851 checkGLcall("glMaterialfv(GL_AMBIENT)");
2852 glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, (float*) &This->updateStateBlock->material.Diffuse);
2853 checkGLcall("glMaterialfv(GL_DIFFUSE)");
2855 /* Only change material color if specular is enabled, otherwise it is set to black */
2856 if (This->stateBlock->renderState[WINED3DRS_SPECULARENABLE]) {
2857 glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, (float*) &This->updateStateBlock->material.Specular);
2858 checkGLcall("glMaterialfv(GL_SPECULAR");
2859 } else {
2860 float black[4] = {0.0f, 0.0f, 0.0f, 0.0f};
2861 glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, &black[0]);
2862 checkGLcall("glMaterialfv(GL_SPECULAR");
2864 glMaterialfv(GL_FRONT_AND_BACK, GL_EMISSION, (float*) &This->updateStateBlock->material.Emissive);
2865 checkGLcall("glMaterialfv(GL_EMISSION)");
2866 glMaterialf(GL_FRONT_AND_BACK, GL_SHININESS, This->updateStateBlock->material.Power);
2867 checkGLcall("glMaterialf(GL_SHININESS");
2869 LEAVE_GL();
2870 return WINED3D_OK;
2873 HRESULT WINAPI IWineD3DDeviceImpl_GetMaterial(IWineD3DDevice *iface, WINED3DMATERIAL* pMaterial) {
2874 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2875 memcpy(pMaterial, &This->updateStateBlock->material, sizeof (WINED3DMATERIAL));
2876 TRACE("(%p) : Diffuse (%f,%f,%f,%f)\n", This, pMaterial->Diffuse.r, pMaterial->Diffuse.g,
2877 pMaterial->Diffuse.b, pMaterial->Diffuse.a);
2878 TRACE("(%p) : Ambient (%f,%f,%f,%f)\n", This, pMaterial->Ambient.r, pMaterial->Ambient.g,
2879 pMaterial->Ambient.b, pMaterial->Ambient.a);
2880 TRACE("(%p) : Specular (%f,%f,%f,%f)\n", This, pMaterial->Specular.r, pMaterial->Specular.g,
2881 pMaterial->Specular.b, pMaterial->Specular.a);
2882 TRACE("(%p) : Emissive (%f,%f,%f,%f)\n", This, pMaterial->Emissive.r, pMaterial->Emissive.g,
2883 pMaterial->Emissive.b, pMaterial->Emissive.a);
2884 TRACE("(%p) : Power (%f)\n", This, pMaterial->Power);
2886 return WINED3D_OK;
2889 /*****
2890 * Get / Set Indices
2891 *****/
2892 HRESULT WINAPI IWineD3DDeviceImpl_SetIndices(IWineD3DDevice *iface, IWineD3DIndexBuffer* pIndexData,
2893 UINT BaseVertexIndex) {
2894 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2895 IWineD3DIndexBuffer *oldIdxs;
2897 TRACE("(%p) : Setting to %p, base %d\n", This, pIndexData, BaseVertexIndex);
2898 oldIdxs = This->updateStateBlock->pIndexData;
2900 This->updateStateBlock->changed.indices = TRUE;
2901 This->updateStateBlock->set.indices = TRUE;
2902 This->updateStateBlock->pIndexData = pIndexData;
2903 This->updateStateBlock->baseVertexIndex = BaseVertexIndex;
2905 /* Handle recording of state blocks */
2906 if (This->isRecordingState) {
2907 TRACE("Recording... not performing anything\n");
2908 return WINED3D_OK;
2911 if (NULL != pIndexData) {
2912 IWineD3DIndexBuffer_AddRef(pIndexData);
2914 if (NULL != oldIdxs) {
2915 IWineD3DIndexBuffer_Release(oldIdxs);
2917 return WINED3D_OK;
2920 HRESULT WINAPI IWineD3DDeviceImpl_GetIndices(IWineD3DDevice *iface, IWineD3DIndexBuffer** ppIndexData, UINT* pBaseVertexIndex) {
2921 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2923 *ppIndexData = This->stateBlock->pIndexData;
2925 /* up ref count on ppindexdata */
2926 if (*ppIndexData) {
2927 IWineD3DIndexBuffer_AddRef(*ppIndexData);
2928 *pBaseVertexIndex = This->stateBlock->baseVertexIndex;
2929 TRACE("(%p) index data set to %p + %u\n", This, ppIndexData, This->stateBlock->baseVertexIndex);
2930 }else{
2931 TRACE("(%p) No index data set\n", This);
2933 TRACE("Returning %p %d\n", *ppIndexData, *pBaseVertexIndex);
2935 return WINED3D_OK;
2938 /*****
2939 * Get / Set Viewports
2940 *****/
2941 HRESULT WINAPI IWineD3DDeviceImpl_SetViewport(IWineD3DDevice *iface, CONST WINED3DVIEWPORT* pViewport) {
2942 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2944 TRACE("(%p)\n", This);
2945 This->updateStateBlock->changed.viewport = TRUE;
2946 This->updateStateBlock->set.viewport = TRUE;
2947 memcpy(&This->updateStateBlock->viewport, pViewport, sizeof(WINED3DVIEWPORT));
2949 /* Handle recording of state blocks */
2950 if (This->isRecordingState) {
2951 TRACE("Recording... not performing anything\n");
2952 return WINED3D_OK;
2954 This->viewport_changed = TRUE;
2956 ENTER_GL();
2958 TRACE("(%p) : x=%ld, y=%ld, wid=%ld, hei=%ld, minz=%f, maxz=%f\n", This,
2959 pViewport->X, pViewport->Y, pViewport->Width, pViewport->Height, pViewport->MinZ, pViewport->MaxZ);
2961 glDepthRange(pViewport->MinZ, pViewport->MaxZ);
2962 checkGLcall("glDepthRange");
2963 /* Note: GL requires lower left, DirectX supplies upper left */
2964 /* TODO: replace usage of renderTarget with context management */
2965 glViewport(pViewport->X,
2966 (((IWineD3DSurfaceImpl *)This->renderTarget)->currentDesc.Height - (pViewport->Y + pViewport->Height)),
2967 pViewport->Width, pViewport->Height);
2969 checkGLcall("glViewport");
2971 LEAVE_GL();
2973 return WINED3D_OK;
2977 HRESULT WINAPI IWineD3DDeviceImpl_GetViewport(IWineD3DDevice *iface, WINED3DVIEWPORT* pViewport) {
2978 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2979 TRACE("(%p)\n", This);
2980 memcpy(pViewport, &This->stateBlock->viewport, sizeof(WINED3DVIEWPORT));
2981 return WINED3D_OK;
2984 /*****
2985 * Get / Set Render States
2986 * TODO: Verify against dx9 definitions
2987 *****/
2988 HRESULT WINAPI IWineD3DDeviceImpl_SetRenderState(IWineD3DDevice *iface, D3DRENDERSTATETYPE State, DWORD Value) {
2990 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2991 DWORD OldValue = This->stateBlock->renderState[State];
2993 /* Simple way of referring to either a DWORD or a 4 byte float */
2994 union {
2995 DWORD d;
2996 float f;
2997 } tmpvalue;
2999 TRACE("(%p)->state = %s(%d), value = %ld\n", This, debug_d3drenderstate(State), State, Value);
3000 This->updateStateBlock->changed.renderState[State] = TRUE;
3001 This->updateStateBlock->set.renderState[State] = TRUE;
3002 This->updateStateBlock->renderState[State] = Value;
3004 /* Handle recording of state blocks */
3005 if (This->isRecordingState) {
3006 TRACE("Recording... not performing anything\n");
3007 return WINED3D_OK;
3010 ENTER_GL();
3012 switch (State) {
3013 case WINED3DRS_FILLMODE :
3014 switch ((D3DFILLMODE) Value) {
3015 case D3DFILL_POINT : glPolygonMode(GL_FRONT_AND_BACK, GL_POINT); break;
3016 case D3DFILL_WIREFRAME : glPolygonMode(GL_FRONT_AND_BACK, GL_LINE); break;
3017 case D3DFILL_SOLID : glPolygonMode(GL_FRONT_AND_BACK, GL_FILL); break;
3018 default:
3019 FIXME("Unrecognized WINED3DRS_FILLMODE value %ld\n", Value);
3021 checkGLcall("glPolygonMode (fillmode)");
3022 break;
3024 case WINED3DRS_LIGHTING :
3025 if (Value) {
3026 glEnable(GL_LIGHTING);
3027 checkGLcall("glEnable GL_LIGHTING");
3028 } else {
3029 glDisable(GL_LIGHTING);
3030 checkGLcall("glDisable GL_LIGHTING");
3032 break;
3034 case WINED3DRS_ZENABLE :
3035 switch ((D3DZBUFFERTYPE) Value) {
3036 case D3DZB_FALSE:
3037 glDisable(GL_DEPTH_TEST);
3038 checkGLcall("glDisable GL_DEPTH_TEST");
3039 break;
3040 case D3DZB_TRUE:
3041 glEnable(GL_DEPTH_TEST);
3042 checkGLcall("glEnable GL_DEPTH_TEST");
3043 break;
3044 case D3DZB_USEW:
3045 glEnable(GL_DEPTH_TEST);
3046 checkGLcall("glEnable GL_DEPTH_TEST");
3047 FIXME("W buffer is not well handled\n");
3048 break;
3049 default:
3050 FIXME("Unrecognized D3DZBUFFERTYPE value %ld\n", Value);
3052 break;
3054 case WINED3DRS_CULLMODE :
3056 /* If we are culling "back faces with clockwise vertices" then
3057 set front faces to be counter clockwise and enable culling
3058 of back faces */
3059 switch ((D3DCULL) Value) {
3060 case D3DCULL_NONE:
3061 glDisable(GL_CULL_FACE);
3062 checkGLcall("glDisable GL_CULL_FACE");
3063 break;
3064 case D3DCULL_CW:
3065 glEnable(GL_CULL_FACE);
3066 checkGLcall("glEnable GL_CULL_FACE");
3067 if (This->renderUpsideDown) {
3068 glFrontFace(GL_CW);
3069 checkGLcall("glFrontFace GL_CW");
3070 } else {
3071 glFrontFace(GL_CCW);
3072 checkGLcall("glFrontFace GL_CCW");
3074 glCullFace(GL_BACK);
3075 break;
3076 case D3DCULL_CCW:
3077 glEnable(GL_CULL_FACE);
3078 checkGLcall("glEnable GL_CULL_FACE");
3079 if (This->renderUpsideDown) {
3080 glFrontFace(GL_CCW);
3081 checkGLcall("glFrontFace GL_CCW");
3082 } else {
3083 glFrontFace(GL_CW);
3084 checkGLcall("glFrontFace GL_CW");
3086 glCullFace(GL_BACK);
3087 break;
3088 default:
3089 FIXME("Unrecognized/Unhandled D3DCULL value %ld\n", Value);
3091 break;
3093 case WINED3DRS_SHADEMODE :
3094 switch ((D3DSHADEMODE) Value) {
3095 case D3DSHADE_FLAT:
3096 glShadeModel(GL_FLAT);
3097 checkGLcall("glShadeModel");
3098 break;
3099 case D3DSHADE_GOURAUD:
3100 glShadeModel(GL_SMOOTH);
3101 checkGLcall("glShadeModel");
3102 break;
3103 case D3DSHADE_PHONG:
3104 FIXME("D3DSHADE_PHONG isn't supported?\n");
3106 LEAVE_GL();
3107 return WINED3DERR_INVALIDCALL;
3108 default:
3109 FIXME("Unrecognized/Unhandled D3DSHADEMODE value %ld\n", Value);
3111 break;
3113 case WINED3DRS_DITHERENABLE :
3114 if (Value) {
3115 glEnable(GL_DITHER);
3116 checkGLcall("glEnable GL_DITHER");
3117 } else {
3118 glDisable(GL_DITHER);
3119 checkGLcall("glDisable GL_DITHER");
3121 break;
3123 case WINED3DRS_ZWRITEENABLE :
3124 if (Value) {
3125 glDepthMask(1);
3126 checkGLcall("glDepthMask");
3127 } else {
3128 glDepthMask(0);
3129 checkGLcall("glDepthMask");
3131 break;
3133 case WINED3DRS_ZFUNC :
3135 int glParm = GL_LESS;
3137 switch ((D3DCMPFUNC) Value) {
3138 case D3DCMP_NEVER: glParm=GL_NEVER; break;
3139 case D3DCMP_LESS: glParm=GL_LESS; break;
3140 case D3DCMP_EQUAL: glParm=GL_EQUAL; break;
3141 case D3DCMP_LESSEQUAL: glParm=GL_LEQUAL; break;
3142 case D3DCMP_GREATER: glParm=GL_GREATER; break;
3143 case D3DCMP_NOTEQUAL: glParm=GL_NOTEQUAL; break;
3144 case D3DCMP_GREATEREQUAL: glParm=GL_GEQUAL; break;
3145 case D3DCMP_ALWAYS: glParm=GL_ALWAYS; break;
3146 default:
3147 FIXME("Unrecognized/Unhandled D3DCMPFUNC value %ld\n", Value);
3149 glDepthFunc(glParm);
3150 checkGLcall("glDepthFunc");
3152 break;
3154 case WINED3DRS_AMBIENT :
3156 float col[4];
3157 D3DCOLORTOGLFLOAT4(Value, col);
3158 TRACE("Setting ambient to (%f,%f,%f,%f)\n", col[0], col[1], col[2], col[3]);
3159 glLightModelfv(GL_LIGHT_MODEL_AMBIENT, col);
3160 checkGLcall("glLightModel for MODEL_AMBIENT");
3163 break;
3165 case WINED3DRS_ALPHABLENDENABLE :
3166 if (Value) {
3167 glEnable(GL_BLEND);
3168 checkGLcall("glEnable GL_BLEND");
3169 } else {
3170 glDisable(GL_BLEND);
3171 checkGLcall("glDisable GL_BLEND");
3173 break;
3175 case WINED3DRS_SRCBLEND :
3176 case WINED3DRS_DESTBLEND :
3178 int newVal = GL_ZERO;
3179 switch (Value) {
3180 case D3DBLEND_ZERO : newVal = GL_ZERO; break;
3181 case D3DBLEND_ONE : newVal = GL_ONE; break;
3182 case D3DBLEND_SRCCOLOR : newVal = GL_SRC_COLOR; break;
3183 case D3DBLEND_INVSRCCOLOR : newVal = GL_ONE_MINUS_SRC_COLOR; break;
3184 case D3DBLEND_SRCALPHA : newVal = GL_SRC_ALPHA; break;
3185 case D3DBLEND_INVSRCALPHA : newVal = GL_ONE_MINUS_SRC_ALPHA; break;
3186 case D3DBLEND_DESTALPHA : newVal = GL_DST_ALPHA; break;
3187 case D3DBLEND_INVDESTALPHA : newVal = GL_ONE_MINUS_DST_ALPHA; break;
3188 case D3DBLEND_DESTCOLOR : newVal = GL_DST_COLOR; break;
3189 case D3DBLEND_INVDESTCOLOR : newVal = GL_ONE_MINUS_DST_COLOR; break;
3190 case D3DBLEND_SRCALPHASAT : newVal = GL_SRC_ALPHA_SATURATE; break;
3192 case D3DBLEND_BOTHSRCALPHA : newVal = GL_SRC_ALPHA;
3193 This->srcBlend = newVal;
3194 This->dstBlend = newVal;
3195 break;
3197 case D3DBLEND_BOTHINVSRCALPHA : newVal = GL_ONE_MINUS_SRC_ALPHA;
3198 This->srcBlend = newVal;
3199 This->dstBlend = newVal;
3200 break;
3201 default:
3202 FIXME("Unrecognized src/dest blend value %ld (%d)\n", Value, State);
3205 if (State == WINED3DRS_SRCBLEND) This->srcBlend = newVal;
3206 if (State == WINED3DRS_DESTBLEND) This->dstBlend = newVal;
3207 TRACE("glBlendFunc src=%x, dst=%x\n", This->srcBlend, This->dstBlend);
3208 glBlendFunc(This->srcBlend, This->dstBlend);
3210 checkGLcall("glBlendFunc");
3212 break;
3214 case WINED3DRS_ALPHATESTENABLE :
3215 case WINED3DRS_ALPHAFUNC :
3216 case WINED3DRS_ALPHAREF :
3217 case WINED3DRS_COLORKEYENABLE :
3219 int glParm = 0.0;
3220 float ref = GL_LESS;
3221 BOOL enable_ckey = FALSE;
3223 IWineD3DSurfaceImpl *surf;
3225 /* Find out if the texture on the first stage has a ckey set */
3226 if(This->stateBlock->textures[0]) {
3227 surf = (IWineD3DSurfaceImpl *) ((IWineD3DTextureImpl *)This->stateBlock->textures[0])->surfaces[0];
3228 if(surf->CKeyFlags & DDSD_CKSRCBLT) enable_ckey = TRUE;
3231 if (This->stateBlock->renderState[WINED3DRS_ALPHATESTENABLE] ||
3232 (This->stateBlock->renderState[WINED3DRS_COLORKEYENABLE] && enable_ckey)) {
3233 glEnable(GL_ALPHA_TEST);
3234 checkGLcall("glEnable GL_ALPHA_TEST");
3235 } else {
3236 glDisable(GL_ALPHA_TEST);
3237 checkGLcall("glDisable GL_ALPHA_TEST");
3238 /* Alpha test is disabled, don't bother setting the params - it will happen on the next
3239 * enable call
3241 break;
3244 if(This->stateBlock->renderState[WINED3DRS_COLORKEYENABLE] && enable_ckey) {
3245 glParm = GL_NOTEQUAL;
3246 ref = 0.0;
3247 } else {
3248 ref = ((float) This->stateBlock->renderState[WINED3DRS_ALPHAREF]) / 255.0f;
3250 switch ((D3DCMPFUNC) This->stateBlock->renderState[WINED3DRS_ALPHAFUNC]) {
3251 case D3DCMP_NEVER: glParm = GL_NEVER; break;
3252 case D3DCMP_LESS: glParm = GL_LESS; break;
3253 case D3DCMP_EQUAL: glParm = GL_EQUAL; break;
3254 case D3DCMP_LESSEQUAL: glParm = GL_LEQUAL; break;
3255 case D3DCMP_GREATER: glParm = GL_GREATER; break;
3256 case D3DCMP_NOTEQUAL: glParm = GL_NOTEQUAL; break;
3257 case D3DCMP_GREATEREQUAL: glParm = GL_GEQUAL; break;
3258 case D3DCMP_ALWAYS: glParm = GL_ALWAYS; break;
3259 default:
3260 FIXME("Unrecognized/Unhandled D3DCMPFUNC value %ld\n", Value);
3263 This->alphafunc = glParm;
3264 glAlphaFunc(glParm, ref);
3265 checkGLcall("glAlphaFunc");
3267 break;
3269 case WINED3DRS_CLIPPLANEENABLE :
3270 case WINED3DRS_CLIPPING :
3272 /* Ensure we only do the changed clip planes */
3273 DWORD enable = 0xFFFFFFFF;
3274 DWORD disable = 0x00000000;
3276 /* If enabling / disabling all */
3277 if (State == WINED3DRS_CLIPPING) {
3278 if (Value) {
3279 enable = This->stateBlock->renderState[WINED3DRS_CLIPPLANEENABLE];
3280 disable = 0x00;
3281 } else {
3282 disable = This->stateBlock->renderState[WINED3DRS_CLIPPLANEENABLE];
3283 enable = 0x00;
3285 } else {
3286 enable = Value & ~OldValue;
3287 disable = ~Value & OldValue;
3290 if (enable & D3DCLIPPLANE0) { glEnable(GL_CLIP_PLANE0); checkGLcall("glEnable(clip plane 0)"); }
3291 if (enable & D3DCLIPPLANE1) { glEnable(GL_CLIP_PLANE1); checkGLcall("glEnable(clip plane 1)"); }
3292 if (enable & D3DCLIPPLANE2) { glEnable(GL_CLIP_PLANE2); checkGLcall("glEnable(clip plane 2)"); }
3293 if (enable & D3DCLIPPLANE3) { glEnable(GL_CLIP_PLANE3); checkGLcall("glEnable(clip plane 3)"); }
3294 if (enable & D3DCLIPPLANE4) { glEnable(GL_CLIP_PLANE4); checkGLcall("glEnable(clip plane 4)"); }
3295 if (enable & D3DCLIPPLANE5) { glEnable(GL_CLIP_PLANE5); checkGLcall("glEnable(clip plane 5)"); }
3297 if (disable & D3DCLIPPLANE0) { glDisable(GL_CLIP_PLANE0); checkGLcall("glDisable(clip plane 0)"); }
3298 if (disable & D3DCLIPPLANE1) { glDisable(GL_CLIP_PLANE1); checkGLcall("glDisable(clip plane 1)"); }
3299 if (disable & D3DCLIPPLANE2) { glDisable(GL_CLIP_PLANE2); checkGLcall("glDisable(clip plane 2)"); }
3300 if (disable & D3DCLIPPLANE3) { glDisable(GL_CLIP_PLANE3); checkGLcall("glDisable(clip plane 3)"); }
3301 if (disable & D3DCLIPPLANE4) { glDisable(GL_CLIP_PLANE4); checkGLcall("glDisable(clip plane 4)"); }
3302 if (disable & D3DCLIPPLANE5) { glDisable(GL_CLIP_PLANE5); checkGLcall("glDisable(clip plane 5)"); }
3304 /** update clipping status */
3305 if (enable) {
3306 This->stateBlock->clip_status.ClipUnion = 0;
3307 This->stateBlock->clip_status.ClipIntersection = 0xFFFFFFFF;
3308 } else {
3309 This->stateBlock->clip_status.ClipUnion = 0;
3310 This->stateBlock->clip_status.ClipIntersection = 0;
3313 break;
3315 case WINED3DRS_BLENDOP :
3317 int glParm = GL_FUNC_ADD;
3319 switch ((D3DBLENDOP) Value) {
3320 case D3DBLENDOP_ADD : glParm = GL_FUNC_ADD; break;
3321 case D3DBLENDOP_SUBTRACT : glParm = GL_FUNC_SUBTRACT; break;
3322 case D3DBLENDOP_REVSUBTRACT : glParm = GL_FUNC_REVERSE_SUBTRACT; break;
3323 case D3DBLENDOP_MIN : glParm = GL_MIN; break;
3324 case D3DBLENDOP_MAX : glParm = GL_MAX; break;
3325 default:
3326 FIXME("Unrecognized/Unhandled D3DBLENDOP value %ld\n", Value);
3329 if(GL_SUPPORT(ARB_IMAGING)) {
3330 TRACE("glBlendEquation(%x)\n", glParm);
3331 GL_EXTCALL(glBlendEquation(glParm));
3332 checkGLcall("glBlendEquation");
3333 } else {
3334 WARN("Unsupported in local OpenGL implementation: glBlendEquation\n");
3337 break;
3339 case WINED3DRS_TEXTUREFACTOR :
3341 unsigned int i;
3343 /* Note the texture color applies to all textures whereas
3344 GL_TEXTURE_ENV_COLOR applies to active only */
3345 float col[4];
3346 D3DCOLORTOGLFLOAT4(Value, col);
3347 /* Set the default alpha blend color */
3348 if (GL_SUPPORT(ARB_IMAGING)) {
3349 GL_EXTCALL(glBlendColor(col[0], col[1], col[2], col[3]));
3350 checkGLcall("glBlendColor");
3351 } else {
3352 WARN("Unsupported in local OpenGL implementation: glBlendColor\n");
3355 /* And now the default texture color as well */
3356 for (i = 0; i < GL_LIMITS(textures); i++) {
3358 /* Note the D3DRS value applies to all textures, but GL has one
3359 per texture, so apply it now ready to be used! */
3360 if (GL_SUPPORT(ARB_MULTITEXTURE)) {
3361 GLACTIVETEXTURE(i);
3362 } else if (i>0) {
3363 FIXME("Program using multiple concurrent textures which this opengl implementation doesn't support\n");
3366 glTexEnvfv(GL_TEXTURE_ENV, GL_TEXTURE_ENV_COLOR, &col[0]);
3367 checkGLcall("glTexEnvfv(GL_TEXTURE_ENV, GL_TEXTURE_ENV_COLOR, color);");
3370 break;
3372 case WINED3DRS_SPECULARENABLE :
3374 /* Originally this used glLightModeli(GL_LIGHT_MODEL_COLOR_CONTROL,GL_SEPARATE_SPECULAR_COLOR)
3375 and (GL_LIGHT_MODEL_COLOR_CONTROL,GL_SINGLE_COLOR) to swap between enabled/disabled
3376 specular color. This is wrong:
3377 Separate specular color means the specular colour is maintained separately, whereas
3378 single color means it is merged in. However in both cases they are being used to
3379 some extent.
3380 To disable specular color, set it explicitly to black and turn off GL_COLOR_SUM_EXT
3381 NOTE: If not supported don't give FIXMEs the impact is really minimal and very few people are
3382 running 1.4 yet!
3384 if (Value) {
3385 glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, (float*) &This->updateStateBlock->material.Specular);
3386 checkGLcall("glMaterialfv");
3387 if (GL_SUPPORT(EXT_SECONDARY_COLOR)) {
3388 glEnable(GL_COLOR_SUM_EXT);
3389 } else {
3390 TRACE("Specular colors cannot be enabled in this version of opengl\n");
3392 checkGLcall("glEnable(GL_COLOR_SUM)");
3393 } else {
3394 float black[4] = {0.0f, 0.0f, 0.0f, 0.0f};
3396 /* for the case of enabled lighting: */
3397 glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, &black[0]);
3398 checkGLcall("glMaterialfv");
3400 /* for the case of disabled lighting: */
3401 if (GL_SUPPORT(EXT_SECONDARY_COLOR)) {
3402 glDisable(GL_COLOR_SUM_EXT);
3403 } else {
3404 TRACE("Specular colors cannot be disabled in this version of opengl\n");
3406 checkGLcall("glDisable(GL_COLOR_SUM)");
3409 break;
3411 case WINED3DRS_STENCILENABLE :
3412 if (Value) {
3413 glEnable(GL_STENCIL_TEST);
3414 checkGLcall("glEnable GL_STENCIL_TEST");
3415 } else {
3416 glDisable(GL_STENCIL_TEST);
3417 checkGLcall("glDisable GL_STENCIL_TEST");
3419 break;
3421 case WINED3DRS_STENCILFUNC :
3423 GLint func;
3424 GLint ref = This->stateBlock->renderState[WINED3DRS_STENCILREF];
3425 GLuint mask = This->stateBlock->renderState[WINED3DRS_STENCILMASK];
3427 func = GL_ALWAYS;
3428 switch ((D3DCMPFUNC)Value) {
3429 case D3DCMP_NEVER: func = GL_NEVER; break;
3430 case D3DCMP_LESS: func = GL_LESS; break;
3431 case D3DCMP_EQUAL: func = GL_EQUAL; break;
3432 case D3DCMP_LESSEQUAL: func = GL_LEQUAL; break;
3433 case D3DCMP_GREATER: func = GL_GREATER; break;
3434 case D3DCMP_NOTEQUAL: func = GL_NOTEQUAL; break;
3435 case D3DCMP_GREATEREQUAL: func = GL_GEQUAL; break;
3436 case D3DCMP_ALWAYS: func = GL_ALWAYS; break;
3437 default:
3438 FIXME("Unrecognized/Unhandled D3DCMPFUNC value %ld\n", Value);
3440 This->stencilfunc = func;
3441 if(!This->stateBlock->renderState[WINED3DRS_TWOSIDEDSTENCILMODE]) {
3442 #if 0 /* Don't use OpenGL 2.0 calls for now */
3443 if(GL_EXTCALL(glStencilFuncSeparate)) {
3444 GL_EXTCALL(glStencilFuncSeparate(GL_FRONT, func, ref, mask));
3445 checkGLcall("glStencilFuncSeparate(GL_FRONT,...)");
3447 else
3448 #endif
3449 if(GL_SUPPORT(EXT_STENCIL_TWO_SIDE)) {
3450 glEnable(GL_STENCIL_TEST_TWO_SIDE_EXT);
3451 checkGLcall("glEnable(GL_STENCIL_TEST_TWO_SIDE_EXT)");
3452 GL_EXTCALL(glActiveStencilFaceEXT(GL_FRONT));
3453 checkGLcall("glActiveStencilFaceEXT(GL_FRONT)");
3454 glStencilFunc(func, ref, mask);
3455 checkGLcall("glStencilFunc(...)");
3457 else if(GL_SUPPORT(ATI_SEPARATE_STENCIL)) {
3458 GL_EXTCALL(glStencilFuncSeparateATI(GL_FRONT, func, ref, mask));
3459 checkGLcall("glStencilFuncSeparateATI(GL_FRONT,...)");
3460 } else {
3461 TRACE("Separate stencil function not supported on this version of opengl");
3462 glStencilFunc(func, ref, mask);
3463 checkGLcall("glStencilFunc(...)");
3465 } else {
3466 glStencilFunc(func, ref, mask);
3467 checkGLcall("glStencilFunc(...)");
3469 break;
3471 case WINED3DRS_STENCILREF :
3473 int glParm = This->stencilfunc;
3474 int ref = 0;
3475 GLuint mask = This->stateBlock->renderState[WINED3DRS_STENCILMASK];
3477 ref = Value;
3478 TRACE("glStencilFunc with Parm=%x, ref=%d, mask=%x\n", glParm, ref, mask);
3479 glStencilFunc(glParm, ref, mask);
3480 checkGLcall("glStencilFunc");
3482 break;
3484 case WINED3DRS_STENCILMASK :
3486 int glParm = This->stencilfunc;
3487 int ref = This->stateBlock->renderState[WINED3DRS_STENCILREF];
3488 GLuint mask = Value;
3490 TRACE("glStencilFunc with Parm=%x, ref=%d, mask=%x\n", glParm, ref, mask);
3491 glStencilFunc(glParm, ref, mask);
3492 checkGLcall("glStencilFunc");
3494 break;
3496 case WINED3DRS_STENCILFAIL :
3497 case WINED3DRS_STENCILZFAIL :
3498 case WINED3DRS_STENCILPASS :
3500 GLint stencilFail;
3501 GLint depthFail;
3502 GLint stencilPass;
3504 GLint action = StencilOp(Value);
3506 glGetIntegerv(GL_STENCIL_FAIL, &stencilFail);
3507 glGetIntegerv(GL_STENCIL_PASS_DEPTH_FAIL, &depthFail);
3508 glGetIntegerv(GL_STENCIL_PASS_DEPTH_PASS, &stencilPass);
3510 if(WINED3DRS_STENCILFAIL == State) {
3511 stencilFail = action;
3513 else if(WINED3DRS_STENCILZFAIL == State) {
3514 depthFail = action;
3516 else if(WINED3DRS_STENCILPASS == State) {
3517 stencilPass = action;
3520 if(!This->stateBlock->renderState[WINED3DRS_TWOSIDEDSTENCILMODE]) {
3521 #if 0 /* Don't use OpenGL 2.0 calls for now */
3522 if(GL_EXTCALL(glStencilOpSeparate)) {
3523 GL_EXTCALL(glStencilOpSeparate(GL_FRONT, stencilFail, depthFail, stencilPass));
3524 checkGLcall("glStencilOpSeparate(GL_FRONT,...)");
3526 else
3527 #endif
3528 if(GL_SUPPORT(EXT_STENCIL_TWO_SIDE)) {
3529 glEnable(GL_STENCIL_TEST_TWO_SIDE_EXT);
3530 checkGLcall("glEnable(GL_STENCIL_TEST_TWO_SIDE_EXT)");
3531 GL_EXTCALL(glActiveStencilFaceEXT(GL_FRONT));
3532 checkGLcall("glActiveStencilFaceEXT(GL_FRONT)");
3533 glStencilOp(stencilFail, depthFail, stencilPass);
3534 checkGLcall("glStencilOp(...)");
3536 else if(GL_SUPPORT(ATI_SEPARATE_STENCIL)) {
3537 GL_EXTCALL(glStencilOpSeparateATI(GL_FRONT, stencilFail, depthFail, stencilPass));
3538 checkGLcall("glStencilOpSeparateATI(GL_FRONT,...)");
3539 } else {
3540 TRACE("Separate stencil operation not supported on this version of opengl");
3541 glStencilOp(stencilFail, depthFail, stencilPass);
3542 checkGLcall("glStencilOp(...)");
3544 } else {
3545 glStencilOp(stencilFail, depthFail, stencilPass);
3546 checkGLcall("glStencilOp(...)");
3548 break;
3550 case WINED3DRS_STENCILWRITEMASK :
3552 glStencilMask(Value);
3553 TRACE("glStencilMask(%lu)\n", Value);
3554 checkGLcall("glStencilMask");
3556 break;
3558 case WINED3DRS_FOGENABLE :
3560 if (Value/* && This->stateBlock->renderState[WINED3DRS_FOGTABLEMODE] != D3DFOG_NONE*/) {
3561 glEnable(GL_FOG);
3562 checkGLcall("glEnable GL_FOG");
3563 } else {
3564 glDisable(GL_FOG);
3565 checkGLcall("glDisable GL_FOG");
3568 break;
3570 case WINED3DRS_RANGEFOGENABLE :
3572 if (Value) {
3573 TRACE("Enabled RANGEFOG");
3574 } else {
3575 TRACE("Disabled RANGEFOG");
3578 break;
3580 case WINED3DRS_FOGCOLOR :
3582 float col[4];
3583 D3DCOLORTOGLFLOAT4(Value, col);
3584 /* Set the default alpha blend color */
3585 glFogfv(GL_FOG_COLOR, &col[0]);
3586 checkGLcall("glFog GL_FOG_COLOR");
3588 break;
3590 case WINED3DRS_FOGTABLEMODE :
3592 glHint(GL_FOG_HINT, GL_NICEST);
3593 switch (Value) {
3594 case D3DFOG_NONE: /* I don't know what to do here */ checkGLcall("glFogi(GL_FOG_MODE, GL_EXP"); break;
3595 case D3DFOG_EXP: glFogi(GL_FOG_MODE, GL_EXP); checkGLcall("glFogi(GL_FOG_MODE, GL_EXP"); break;
3596 case D3DFOG_EXP2: glFogi(GL_FOG_MODE, GL_EXP2); checkGLcall("glFogi(GL_FOG_MODE, GL_EXP2"); break;
3597 case D3DFOG_LINEAR: glFogi(GL_FOG_MODE, GL_LINEAR); checkGLcall("glFogi(GL_FOG_MODE, GL_LINEAR"); break;
3598 default:
3599 FIXME("Unsupported Value(%lu) for WINED3DRS_FOGTABLEMODE!\n", Value);
3601 if (GL_SUPPORT(NV_FOG_DISTANCE)) {
3602 glFogi(GL_FOG_DISTANCE_MODE_NV, GL_EYE_PLANE_ABSOLUTE_NV);
3605 break;
3607 case WINED3DRS_FOGVERTEXMODE :
3609 glHint(GL_FOG_HINT, GL_FASTEST);
3610 switch (Value) {
3611 case D3DFOG_NONE: /* I don't know what to do here */ checkGLcall("glFogi(GL_FOG_MODE, GL_EXP"); break;
3612 case D3DFOG_EXP: glFogi(GL_FOG_MODE, GL_EXP); checkGLcall("glFogi(GL_FOG_MODE, GL_EXP"); break;
3613 case D3DFOG_EXP2: glFogi(GL_FOG_MODE, GL_EXP2); checkGLcall("glFogi(GL_FOG_MODE, GL_EXP2"); break;
3614 case D3DFOG_LINEAR: glFogi(GL_FOG_MODE, GL_LINEAR); checkGLcall("glFogi(GL_FOG_MODE, GL_LINEAR"); break;
3615 default:
3616 FIXME("Unsupported Value(%lu) for WINED3DRS_FOGTABLEMODE!\n", Value);
3618 if (GL_SUPPORT(NV_FOG_DISTANCE)) {
3619 glFogi(GL_FOG_DISTANCE_MODE_NV, This->stateBlock->renderState[WINED3DRS_RANGEFOGENABLE] ? GL_EYE_RADIAL_NV : GL_EYE_PLANE_ABSOLUTE_NV);
3622 break;
3624 case WINED3DRS_FOGSTART :
3626 tmpvalue.d = Value;
3627 glFogfv(GL_FOG_START, &tmpvalue.f);
3628 checkGLcall("glFogf(GL_FOG_START, (float) Value)");
3629 TRACE("Fog Start == %f\n", tmpvalue.f);
3631 break;
3633 case WINED3DRS_FOGEND :
3635 tmpvalue.d = Value;
3636 glFogfv(GL_FOG_END, &tmpvalue.f);
3637 checkGLcall("glFogf(GL_FOG_END, (float) Value)");
3638 TRACE("Fog End == %f\n", tmpvalue.f);
3640 break;
3642 case WINED3DRS_FOGDENSITY :
3644 tmpvalue.d = Value;
3645 glFogfv(GL_FOG_DENSITY, &tmpvalue.f);
3646 checkGLcall("glFogf(GL_FOG_DENSITY, (float) Value)");
3648 break;
3650 case WINED3DRS_VERTEXBLEND :
3652 This->updateStateBlock->vertex_blend = (D3DVERTEXBLENDFLAGS) Value;
3653 TRACE("Vertex Blending state to %ld\n", Value);
3655 break;
3657 case WINED3DRS_TWEENFACTOR :
3659 tmpvalue.d = Value;
3660 This->updateStateBlock->tween_factor = tmpvalue.f;
3661 TRACE("Vertex Blending Tween Factor to %f\n", This->updateStateBlock->tween_factor);
3663 break;
3665 case WINED3DRS_INDEXEDVERTEXBLENDENABLE :
3667 TRACE("Indexed Vertex Blend Enable to %ul\n", (BOOL) Value);
3669 break;
3671 case WINED3DRS_COLORVERTEX :
3672 case WINED3DRS_DIFFUSEMATERIALSOURCE :
3673 case WINED3DRS_SPECULARMATERIALSOURCE :
3674 case WINED3DRS_AMBIENTMATERIALSOURCE :
3675 case WINED3DRS_EMISSIVEMATERIALSOURCE :
3677 GLenum Parm = GL_AMBIENT_AND_DIFFUSE;
3679 if (This->stateBlock->renderState[WINED3DRS_COLORVERTEX]) {
3680 TRACE("diff %ld, amb %ld, emis %ld, spec %ld\n",
3681 This->stateBlock->renderState[WINED3DRS_DIFFUSEMATERIALSOURCE],
3682 This->stateBlock->renderState[WINED3DRS_AMBIENTMATERIALSOURCE],
3683 This->stateBlock->renderState[WINED3DRS_EMISSIVEMATERIALSOURCE],
3684 This->stateBlock->renderState[WINED3DRS_SPECULARMATERIALSOURCE]);
3686 if (This->stateBlock->renderState[WINED3DRS_DIFFUSEMATERIALSOURCE] == D3DMCS_COLOR1) {
3687 if (This->stateBlock->renderState[WINED3DRS_AMBIENTMATERIALSOURCE] == D3DMCS_COLOR1) {
3688 Parm = GL_AMBIENT_AND_DIFFUSE;
3689 } else {
3690 Parm = GL_DIFFUSE;
3692 } else if (This->stateBlock->renderState[WINED3DRS_AMBIENTMATERIALSOURCE] == D3DMCS_COLOR1) {
3693 Parm = GL_AMBIENT;
3694 } else if (This->stateBlock->renderState[WINED3DRS_EMISSIVEMATERIALSOURCE] == D3DMCS_COLOR1) {
3695 Parm = GL_EMISSION;
3696 } else if (This->stateBlock->renderState[WINED3DRS_SPECULARMATERIALSOURCE] == D3DMCS_COLOR1) {
3697 Parm = GL_SPECULAR;
3698 } else {
3699 Parm = -1;
3702 if (Parm == -1) {
3703 if (This->tracking_color != DISABLED_TRACKING) This->tracking_color = NEEDS_DISABLE;
3704 } else {
3705 This->tracking_color = NEEDS_TRACKING;
3706 This->tracking_parm = Parm;
3709 } else {
3710 if (This->tracking_color != DISABLED_TRACKING) This->tracking_color = NEEDS_DISABLE;
3713 break;
3715 case WINED3DRS_LINEPATTERN :
3717 union {
3718 DWORD d;
3719 D3DLINEPATTERN lp;
3720 } tmppattern;
3721 tmppattern.d = Value;
3723 TRACE("Line pattern: repeat %d bits %x\n", tmppattern.lp.wRepeatFactor, tmppattern.lp.wLinePattern);
3725 if (tmppattern.lp.wRepeatFactor) {
3726 glLineStipple(tmppattern.lp.wRepeatFactor, tmppattern.lp.wLinePattern);
3727 checkGLcall("glLineStipple(repeat, linepattern)");
3728 glEnable(GL_LINE_STIPPLE);
3729 checkGLcall("glEnable(GL_LINE_STIPPLE);");
3730 } else {
3731 glDisable(GL_LINE_STIPPLE);
3732 checkGLcall("glDisable(GL_LINE_STIPPLE);");
3735 break;
3737 case WINED3DRS_ZBIAS : /* D3D8 only */
3739 if (Value) {
3740 tmpvalue.d = Value;
3741 TRACE("ZBias value %f\n", tmpvalue.f);
3742 glPolygonOffset(0, -tmpvalue.f);
3743 checkGLcall("glPolygonOffset(0, -Value)");
3744 glEnable(GL_POLYGON_OFFSET_FILL);
3745 checkGLcall("glEnable(GL_POLYGON_OFFSET_FILL);");
3746 glEnable(GL_POLYGON_OFFSET_LINE);
3747 checkGLcall("glEnable(GL_POLYGON_OFFSET_LINE);");
3748 glEnable(GL_POLYGON_OFFSET_POINT);
3749 checkGLcall("glEnable(GL_POLYGON_OFFSET_POINT);");
3750 } else {
3751 glDisable(GL_POLYGON_OFFSET_FILL);
3752 checkGLcall("glDisable(GL_POLYGON_OFFSET_FILL);");
3753 glDisable(GL_POLYGON_OFFSET_LINE);
3754 checkGLcall("glDisable(GL_POLYGON_OFFSET_LINE);");
3755 glDisable(GL_POLYGON_OFFSET_POINT);
3756 checkGLcall("glDisable(GL_POLYGON_OFFSET_POINT);");
3759 break;
3761 case WINED3DRS_NORMALIZENORMALS :
3762 if (Value) {
3763 glEnable(GL_NORMALIZE);
3764 checkGLcall("glEnable(GL_NORMALIZE);");
3765 } else {
3766 glDisable(GL_NORMALIZE);
3767 checkGLcall("glDisable(GL_NORMALIZE);");
3769 break;
3771 case WINED3DRS_POINTSIZE :
3772 /* FIXME: check that pointSize isn't outside glGetFloatv( GL_POINT_SIZE_MAX_ARB, &maxSize ); or -ve */
3773 tmpvalue.d = Value;
3774 TRACE("Set point size to %f\n", tmpvalue.f);
3775 glPointSize(tmpvalue.f);
3776 checkGLcall("glPointSize(...);");
3777 break;
3779 case WINED3DRS_POINTSIZE_MIN :
3780 if (GL_SUPPORT(EXT_POINT_PARAMETERS)) {
3781 tmpvalue.d = Value;
3782 GL_EXTCALL(glPointParameterfEXT)(GL_POINT_SIZE_MIN_EXT, tmpvalue.f);
3783 checkGLcall("glPointParameterfEXT(...);");
3784 } else {
3785 FIXME("WINED3DRS_POINTSIZE_MIN not supported on this opengl\n");
3787 break;
3789 case WINED3DRS_POINTSIZE_MAX :
3790 if (GL_SUPPORT(EXT_POINT_PARAMETERS)) {
3791 tmpvalue.d = Value;
3792 GL_EXTCALL(glPointParameterfEXT)(GL_POINT_SIZE_MAX_EXT, tmpvalue.f);
3793 checkGLcall("glPointParameterfEXT(...);");
3794 } else {
3795 FIXME("WINED3DRS_POINTSIZE_MAX not supported on this opengl\n");
3797 break;
3799 case WINED3DRS_POINTSCALE_A :
3800 case WINED3DRS_POINTSCALE_B :
3801 case WINED3DRS_POINTSCALE_C :
3802 case WINED3DRS_POINTSCALEENABLE :
3805 * POINTSCALEENABLE controls how point size value is treated. If set to
3806 * true, the point size is scaled with respect to height of viewport.
3807 * When set to false point size is in pixels.
3809 * http://msdn.microsoft.com/library/en-us/directx9_c/point_sprites.asp
3812 /* Default values */
3813 GLfloat att[3] = {1.0f, 0.0f, 0.0f};
3816 * Minimum valid point size for OpenGL is 1.0f. For Direct3D it is 0.0f.
3817 * This means that OpenGL will clamp really small point sizes to 1.0f.
3818 * To correct for this we need to multiply by the scale factor when sizes
3819 * are less than 1.0f. scale_factor = 1.0f / point_size.
3821 GLfloat pointSize = *((float*)&This->stateBlock->renderState[WINED3DRS_POINTSIZE]);
3822 if(pointSize > 0.0f) {
3823 GLfloat scaleFactor;
3825 if(pointSize < 1.0f) {
3826 scaleFactor = pointSize * pointSize;
3827 } else {
3828 scaleFactor = 1.0f;
3831 if(This->stateBlock->renderState[WINED3DRS_POINTSCALEENABLE]) {
3832 att[0] = *((float*)&This->stateBlock->renderState[WINED3DRS_POINTSCALE_A]) /
3833 (This->stateBlock->viewport.Height * This->stateBlock->viewport.Height * scaleFactor);
3834 att[1] = *((float*)&This->stateBlock->renderState[WINED3DRS_POINTSCALE_B]) /
3835 (This->stateBlock->viewport.Height * This->stateBlock->viewport.Height * scaleFactor);
3836 att[2] = *((float*)&This->stateBlock->renderState[WINED3DRS_POINTSCALE_C]) /
3837 (This->stateBlock->viewport.Height * This->stateBlock->viewport.Height * scaleFactor);
3841 if(GL_SUPPORT(ARB_POINT_PARAMETERS)) {
3842 GL_EXTCALL(glPointParameterfvARB)(GL_POINT_DISTANCE_ATTENUATION_ARB, att);
3843 checkGLcall("glPointParameterfvARB(GL_DISTANCE_ATTENUATION_ARB, ...");
3845 else if(GL_SUPPORT(EXT_POINT_PARAMETERS)) {
3846 GL_EXTCALL(glPointParameterfvEXT)(GL_DISTANCE_ATTENUATION_EXT, att);
3847 checkGLcall("glPointParameterfvEXT(GL_DISTANCE_ATTENUATION_EXT, ...");
3848 } else {
3849 TRACE("POINT_PARAMETERS not supported in this version of opengl\n");
3851 break;
3853 case WINED3DRS_COLORWRITEENABLE :
3855 TRACE("Color mask: r(%d) g(%d) b(%d) a(%d)\n",
3856 Value & D3DCOLORWRITEENABLE_RED ? 1 : 0,
3857 Value & D3DCOLORWRITEENABLE_GREEN ? 1 : 0,
3858 Value & D3DCOLORWRITEENABLE_BLUE ? 1 : 0,
3859 Value & D3DCOLORWRITEENABLE_ALPHA ? 1 : 0);
3860 glColorMask(Value & D3DCOLORWRITEENABLE_RED ? GL_TRUE : GL_FALSE,
3861 Value & D3DCOLORWRITEENABLE_GREEN ? GL_TRUE : GL_FALSE,
3862 Value & D3DCOLORWRITEENABLE_BLUE ? GL_TRUE : GL_FALSE,
3863 Value & D3DCOLORWRITEENABLE_ALPHA ? GL_TRUE : GL_FALSE);
3864 checkGLcall("glColorMask(...)");
3866 break;
3868 case WINED3DRS_LOCALVIEWER :
3870 GLint state = (Value) ? 1 : 0;
3871 TRACE("Local Viewer Enable to %ul\n", (BOOL) Value);
3872 glLightModeli(GL_LIGHT_MODEL_LOCAL_VIEWER, state);
3874 break;
3876 case WINED3DRS_LASTPIXEL :
3878 if (Value) {
3879 TRACE("Last Pixel Drawing Enabled\n");
3880 } else {
3881 FIXME("Last Pixel Drawing Disabled, not handled yet\n");
3884 break;
3886 case WINED3DRS_SOFTWAREVERTEXPROCESSING :
3888 if (Value) {
3889 TRACE("Software Processing Enabled\n");
3890 } else {
3891 TRACE("Software Processing Disabled\n");
3894 break;
3896 /** not supported */
3897 case WINED3DRS_ZVISIBLE :
3899 LEAVE_GL();
3900 return WINED3DERR_INVALIDCALL;
3902 case WINED3DRS_POINTSPRITEENABLE :
3904 /* TODO: NV_POINT_SPRITE */
3905 if (!GL_SUPPORT(ARB_POINT_SPRITE)) {
3906 TRACE("Point sprites not supported\n");
3907 break;
3911 * Point sprites are always enabled. Value controls texture coordinate
3912 * replacement mode. Must be set true for point sprites to use
3913 * textures.
3915 glEnable(GL_POINT_SPRITE_ARB);
3916 checkGLcall("glEnable(GL_POINT_SPRITE_ARB)");
3918 if (Value) {
3919 glTexEnvf(GL_POINT_SPRITE_ARB, GL_COORD_REPLACE_ARB, TRUE);
3920 checkGLcall("glTexEnvf(GL_POINT_SPRITE, GL_COORD_REPLACE, TRUE)");
3921 } else {
3922 glTexEnvf(GL_POINT_SPRITE_ARB, GL_COORD_REPLACE_ARB, FALSE);
3923 checkGLcall("glTexEnvf(GL_POINT_SPRITE, GL_COORD_REPLACE, FALSE)");
3925 break;
3927 case WINED3DRS_EDGEANTIALIAS :
3929 if(Value) {
3930 glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
3931 glEnable(GL_BLEND);
3932 checkGLcall("glEnable(GL_BLEND)");
3933 glEnable(GL_LINE_SMOOTH);
3934 checkGLcall("glEnable(GL_LINE_SMOOTH)");
3935 } else {
3936 glDisable(GL_BLEND);
3937 checkGLcall("glDisable(GL_BLEND)");
3938 glDisable(GL_LINE_SMOOTH);
3939 checkGLcall("glDisable(GL_LINE_SMOOTH)");
3941 break;
3943 case WINED3DRS_WRAP0 :
3944 case WINED3DRS_WRAP1 :
3945 case WINED3DRS_WRAP2 :
3946 case WINED3DRS_WRAP3 :
3947 case WINED3DRS_WRAP4 :
3948 case WINED3DRS_WRAP5 :
3949 case WINED3DRS_WRAP6 :
3950 case WINED3DRS_WRAP7 :
3951 case WINED3DRS_WRAP8 :
3952 case WINED3DRS_WRAP9 :
3953 case WINED3DRS_WRAP10 :
3954 case WINED3DRS_WRAP11 :
3955 case WINED3DRS_WRAP12 :
3956 case WINED3DRS_WRAP13 :
3957 case WINED3DRS_WRAP14 :
3958 case WINED3DRS_WRAP15 :
3960 http://www.cosc.brocku.ca/Offerings/3P98/course/lectures/texture/
3961 http://msdn.microsoft.com/archive/default.asp?url=/archive/en-us/directx9_c/directx/graphics/programmingguide/FixedFunction/Textures/texturewrapping.asp
3962 http://www.gamedev.net/reference/programming/features/rendererdll3/page2.asp
3963 Descussion that ways to turn on WRAPing to solve an opengl conversion problem.
3964 http://www.flipcode.org/cgi-bin/fcmsg.cgi?thread_show=10248
3966 so far as I can tell, wrapping and texture-coordinate generate go hand in hand,
3968 TRACE("(%p)->(%s,%ld) Texture wraping not yet supported\n",This, debug_d3drenderstate(State), Value);
3969 break;
3970 case WINED3DRS_MULTISAMPLEANTIALIAS :
3972 if (!GL_SUPPORT(ARB_MULTISAMPLE)) {
3973 TRACE("Multisample antialiasing not supported\n");
3974 break;
3977 if(Value) {
3978 glEnable(GL_MULTISAMPLE_ARB);
3979 checkGLcall("glEnable(GL_MULTISAMPLE_ARB)");
3980 } else {
3981 glDisable(GL_MULTISAMPLE_ARB);
3982 checkGLcall("glDisable(GL_MULTISAMPLE_ARB)");
3984 break;
3986 case WINED3DRS_SCISSORTESTENABLE :
3988 if(Value) {
3989 glEnable(GL_SCISSOR_TEST);
3990 checkGLcall("glEnable(GL_SCISSOR_TEST)");
3991 } else {
3992 glDisable(GL_SCISSOR_TEST);
3993 checkGLcall("glDisable(GL_SCISSOR_TEST)");
3995 break;
3997 case WINED3DRS_SLOPESCALEDEPTHBIAS :
3999 if(Value) {
4000 tmpvalue.d = Value;
4001 glEnable(GL_POLYGON_OFFSET_FILL);
4002 checkGLcall("glEnable(GL_POLYGON_OFFSET_FILL)");
4003 glPolygonOffset(tmpvalue.f, *((float*)&This->stateBlock->renderState[WINED3DRS_DEPTHBIAS]));
4004 checkGLcall("glPolygonOffset(...)");
4005 } else {
4006 glDisable(GL_POLYGON_OFFSET_FILL);
4007 checkGLcall("glDisable(GL_POLYGON_OFFSET_FILL)");
4009 break;
4011 case WINED3DRS_ANTIALIASEDLINEENABLE :
4013 if(Value) {
4014 glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
4015 glEnable(GL_BLEND);
4016 checkGLcall("glEnable(GL_BLEND)");
4017 glEnable(GL_LINE_SMOOTH);
4018 checkGLcall("glEnable(GL_LINE_SMOOTH)");
4019 } else {
4020 glDisable(GL_BLEND);
4021 checkGLcall("glDisable(GL_BLEND)");
4022 glDisable(GL_LINE_SMOOTH);
4023 checkGLcall("glDisable(GL_LINE_SMOOTH)");
4025 break;
4027 case WINED3DRS_TWOSIDEDSTENCILMODE :
4029 if(Value) {
4030 TRACE("Two-sided stencil mode enabled\n");
4031 } else {
4032 TRACE("Two-sided stencil mode disabled\n");
4034 break;
4036 case WINED3DRS_CCW_STENCILFAIL :
4037 case WINED3DRS_CCW_STENCILZFAIL :
4038 case WINED3DRS_CCW_STENCILPASS :
4040 GLint stencilFail;
4041 GLint depthFail;
4042 GLint stencilPass;
4044 GLint action = StencilOp(Value);
4046 glGetIntegerv(GL_STENCIL_BACK_FAIL, &stencilFail);
4047 glGetIntegerv(GL_STENCIL_BACK_PASS_DEPTH_FAIL, &depthFail);
4048 glGetIntegerv(GL_STENCIL_BACK_PASS_DEPTH_PASS, &stencilPass);
4050 if(WINED3DRS_CCW_STENCILFAIL == State) {
4051 stencilFail = action;
4053 else if(WINED3DRS_CCW_STENCILZFAIL == State) {
4054 depthFail = action;
4056 else if(WINED3DRS_CCW_STENCILPASS == State) {
4057 stencilPass = action;
4060 if(!This->stateBlock->renderState[WINED3DRS_TWOSIDEDSTENCILMODE]) {
4061 #if 0 /* Don't use OpenGL 2.0 calls for now */
4062 if(GL_EXTCALL(glStencilOpSeparate)) {
4063 GL_EXTCALL(glStencilOpSeparate(GL_BACK, stencilFail, depthFail, stencilPass));
4064 checkGLcall("glStencilOpSeparate(GL_BACK,...)");
4066 else
4067 #endif
4068 if(GL_SUPPORT(EXT_STENCIL_TWO_SIDE)) {
4069 glEnable(GL_STENCIL_TEST_TWO_SIDE_EXT);
4070 checkGLcall("glEnable(GL_STENCIL_TEST_TWO_SIDE_EXT)");
4071 GL_EXTCALL(glActiveStencilFaceEXT(GL_BACK));
4072 checkGLcall("glActiveStencilFaceEXT(GL_BACK)");
4073 glStencilOp(stencilFail, depthFail, stencilPass);
4074 checkGLcall("glStencilOp(...)");
4076 else if(GL_SUPPORT(ATI_SEPARATE_STENCIL)) {
4077 GL_EXTCALL(glStencilOpSeparateATI(GL_BACK, stencilFail, depthFail, stencilPass));
4078 checkGLcall("glStencilOpSeparateATI(GL_BACK,...)");
4079 } else {
4080 TRACE("Separate stencil operation not supported on this version of opengl");
4081 glStencilOp(stencilFail, depthFail, stencilPass);
4082 checkGLcall("glStencilOp(...)");
4084 } else {
4085 glStencilOp(stencilFail, depthFail, stencilPass);
4086 checkGLcall("glStencilOp(...)");
4088 break;
4090 case WINED3DRS_CCW_STENCILFUNC :
4092 GLint func;
4093 GLint ref = This->stateBlock->renderState[WINED3DRS_STENCILREF];
4094 GLuint mask = This->stateBlock->renderState[WINED3DRS_STENCILMASK];
4096 func = GL_ALWAYS;
4097 switch ((D3DCMPFUNC)Value) {
4098 case D3DCMP_NEVER: func = GL_NEVER; break;
4099 case D3DCMP_LESS: func = GL_LESS; break;
4100 case D3DCMP_EQUAL: func = GL_EQUAL; break;
4101 case D3DCMP_LESSEQUAL: func = GL_LEQUAL; break;
4102 case D3DCMP_GREATER: func = GL_GREATER; break;
4103 case D3DCMP_NOTEQUAL: func = GL_NOTEQUAL; break;
4104 case D3DCMP_GREATEREQUAL: func = GL_GEQUAL; break;
4105 case D3DCMP_ALWAYS: func = GL_ALWAYS; break;
4106 default:
4107 FIXME("Unrecognized/Unhandled D3DCMPFUNC value %ld\n", Value);
4109 This->stencilfunc = func;
4110 if(!This->stateBlock->renderState[WINED3DRS_TWOSIDEDSTENCILMODE]) {
4111 #if 0 /* Don't use OpenGL 2.0 calls for now */
4112 if(GL_EXTCALL(glStencilFuncSeparate)) {
4113 GL_EXTCALL(glStencilFuncSeparate(GL_BACK, func, ref, mask));
4114 checkGLcall("glStencilFuncSeparate(GL_BACK,...)");
4116 else
4117 #endif
4118 if(GL_SUPPORT(EXT_STENCIL_TWO_SIDE)) {
4119 glEnable(GL_STENCIL_TEST_TWO_SIDE_EXT);
4120 checkGLcall("glEnable(GL_STENCIL_TEST_TWO_SIDE_EXT)");
4121 GL_EXTCALL(glActiveStencilFaceEXT(GL_BACK));
4122 checkGLcall("glActiveStencilFaceEXT(GL_BACK)");
4123 glStencilFunc(func, ref, mask);
4124 checkGLcall("glStencilFunc(...)");
4126 else if(GL_SUPPORT(ATI_SEPARATE_STENCIL)) {
4127 GL_EXTCALL(glStencilFuncSeparateATI(GL_BACK, func, ref, mask));
4128 checkGLcall("glStencilFuncSeparateATI(GL_BACK,...)");
4129 } else {
4130 TRACE("Separate stencil function not supported on this version of opengl");
4131 glStencilFunc(func, ref, mask);
4132 checkGLcall("glStencilFunc(...)");
4134 } else {
4135 glStencilFunc(func, ref, mask);
4136 checkGLcall("glStencilFunc(...)");
4138 break;
4140 case WINED3DRS_DEPTHBIAS :
4142 if(Value) {
4143 tmpvalue.d = Value;
4144 glEnable(GL_POLYGON_OFFSET_FILL);
4145 checkGLcall("glEnable(GL_POLYGON_OFFSET_FILL)");
4146 glPolygonOffset(*((float*)&This->stateBlock->renderState[WINED3DRS_SLOPESCALEDEPTHBIAS]), tmpvalue.f);
4147 checkGLcall("glPolygonOffset(...)");
4148 } else {
4149 glDisable(GL_POLYGON_OFFSET_FILL);
4150 checkGLcall("glDisable(GL_POLYGON_OFFSET_FILL)");
4152 break;
4155 case WINED3DRS_TEXTUREPERSPECTIVE :
4157 if (Value)
4158 glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST);
4159 else
4160 glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_FASTEST);
4161 break;
4164 case WINED3DRS_STIPPLEDALPHA :
4166 if (Value)
4167 ERR(" Stippled Alpha not supported yet.\n");
4168 break;
4170 case WINED3DRS_ANTIALIAS :
4172 if (Value)
4173 ERR(" Antialias not supported yet.\n");
4174 break;
4176 default:
4177 FIXME("(%p)->(%s,%ld) not handled yet\n", This, debug_d3drenderstate(State), Value);
4180 LEAVE_GL();
4182 return WINED3D_OK;
4185 HRESULT WINAPI IWineD3DDeviceImpl_GetRenderState(IWineD3DDevice *iface, D3DRENDERSTATETYPE State, DWORD *pValue) {
4186 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4187 TRACE("(%p) for State %d = %ld\n", This, State, This->stateBlock->renderState[State]);
4188 *pValue = This->stateBlock->renderState[State];
4189 return WINED3D_OK;
4192 /*****
4193 * Get / Set Sampler States
4194 * TODO: Verify against dx9 definitions
4195 *****/
4197 HRESULT WINAPI IWineD3DDeviceImpl_SetSamplerState(IWineD3DDevice *iface, DWORD Sampler, WINED3DSAMPLERSTATETYPE Type, DWORD Value) {
4198 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4200 * SetSampler is designed to allow for more than the standard up to 8 textures
4201 * and Geforce has stopped supporting more than 6 standard textures in openGL.
4202 * So I have to use ARB for Gforce. (maybe if the sampler > 4 then use ARB?)
4204 * http://developer.nvidia.com/object/General_FAQ.html#t6
4206 * There are two new settings for GForce
4207 * the sampler one:
4208 * GL_MAX_TEXTURE_IMAGE_UNITS_ARB
4209 * and the texture one:
4210 * GL_MAX_TEXTURE_COORDS_ARB.
4211 * Ok GForce say it's ok to use glTexParameter/glGetTexParameter(...).
4212 ******************/
4213 /** NOTE: States are appled in IWineD3DBaseTextre ApplyStateChanges and IWineD3DDevice SetupTextureStates**/
4214 TRACE("(%p) Sampler(%ld), Type(%d) Value(%ld)\n",This, Sampler ,Type, Value);
4216 if(Sampler > GL_LIMITS(samplers) || Sampler < 0 || Type > WINED3D_HIGHEST_SAMPLER_STATE || Type < 0) {
4217 FIXME("out of range %d %d sampler %ld type %u\n", GL_LIMITS(samplers), WINED3D_HIGHEST_SAMPLER_STATE, Sampler, Type);
4218 return WINED3DERR_INVALIDCALL;
4220 TRACE("Setting sampler %ld %d to %ld\n", Sampler, Type, Value);
4221 This->updateStateBlock->samplerState[Sampler][Type] = Value;
4222 This->updateStateBlock->set.samplerState[Sampler][Type] = Value;
4223 This->updateStateBlock->changed.samplerState[Sampler][Type] = Value;
4225 /* Handle recording of state blocks */
4226 if (This->isRecordingState) {
4227 TRACE("Recording... not performing anything\n");
4228 return WINED3D_OK;
4231 return WINED3D_OK;
4234 HRESULT WINAPI IWineD3DDeviceImpl_GetSamplerState(IWineD3DDevice *iface, DWORD Sampler, WINED3DSAMPLERSTATETYPE Type, DWORD* Value) {
4235 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4236 /** TODO: check that sampler is in range **/
4237 *Value = This->updateStateBlock->samplerState[Sampler][Type];
4238 TRACE("(%p) : Sampler %ld Type %u Returning %ld\n", This, Sampler, Type, *Value);
4240 return WINED3D_OK;
4243 HRESULT WINAPI IWineD3DDeviceImpl_SetScissorRect(IWineD3DDevice *iface, CONST RECT* pRect) {
4244 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4245 ENTER_GL();
4247 /** FIXME: Windows uses a top,left origin openGL uses a bottom Right? **/
4248 TRACE("(%p)Setting new Scissor Rect to %ld:%ld-%ld:%ld\n", This, pRect->left, pRect->top, pRect->right, pRect->bottom);
4249 glScissor(pRect->left, pRect->top, pRect->right - pRect->left, pRect->bottom - pRect->top);
4250 LEAVE_GL();
4252 return WINED3D_OK;
4255 HRESULT WINAPI IWineD3DDeviceImpl_GetScissorRect(IWineD3DDevice *iface, RECT* pRect) {
4256 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4257 GLint scissorBox[4];
4259 ENTER_GL();
4260 /** FIXME: Windows uses a top,left origin openGL uses a bottom Right? **/
4261 glGetIntegerv(GL_SCISSOR_BOX, scissorBox);
4262 pRect->left = scissorBox[1];
4263 pRect->top = scissorBox[2];
4264 pRect->right = scissorBox[1] + scissorBox[3];
4265 pRect->bottom = scissorBox[2] + scissorBox[4];
4266 TRACE("(%p)Returning a Scissor Rect of %ld:%ld-%ld:%ld\n", This, pRect->left, pRect->top, pRect->right, pRect->bottom);
4267 LEAVE_GL();
4268 return WINED3D_OK;
4271 HRESULT WINAPI IWineD3DDeviceImpl_SetVertexDeclaration(IWineD3DDevice* iface, IWineD3DVertexDeclaration* pDecl) {
4272 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *) iface;
4273 IWineD3DVertexDeclaration *oldDecl = This->updateStateBlock->vertexDecl;
4275 TRACE("(%p) : pDecl=%p\n", This, pDecl);
4277 This->updateStateBlock->vertexDecl = pDecl;
4278 This->updateStateBlock->changed.vertexDecl = TRUE;
4279 This->updateStateBlock->set.vertexDecl = TRUE;
4281 if (This->isRecordingState) {
4282 TRACE("Recording... not performing anything\n");
4285 if (NULL != pDecl) {
4286 IWineD3DVertexDeclaration_AddRef(pDecl);
4288 if (NULL != oldDecl) {
4289 IWineD3DVertexDeclaration_Release(oldDecl);
4291 return WINED3D_OK;
4294 HRESULT WINAPI IWineD3DDeviceImpl_GetVertexDeclaration(IWineD3DDevice* iface, IWineD3DVertexDeclaration** ppDecl) {
4295 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4297 TRACE("(%p) : ppDecl=%p\n", This, ppDecl);
4299 *ppDecl = This->stateBlock->vertexDecl;
4300 if (NULL != *ppDecl) IWineD3DVertexDeclaration_AddRef(*ppDecl);
4301 return WINED3D_OK;
4304 HRESULT WINAPI IWineD3DDeviceImpl_SetVertexShader(IWineD3DDevice *iface, IWineD3DVertexShader* pShader) {
4305 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4306 IWineD3DVertexShader* oldShader = This->updateStateBlock->vertexShader;
4308 This->updateStateBlock->vertexShader = pShader;
4309 This->updateStateBlock->changed.vertexShader = TRUE;
4310 This->updateStateBlock->set.vertexShader = TRUE;
4312 if (This->isRecordingState) {
4313 TRACE("Recording... not performing anything\n");
4316 if (NULL != pShader) {
4317 IWineD3DVertexShader_AddRef(pShader);
4319 if (NULL != oldShader) {
4320 IWineD3DVertexShader_Release(oldShader);
4323 if (pShader != NULL && ((IWineD3DVertexShaderImpl *)pShader)->vertexDeclaration != NULL) {
4324 TRACE("(%p) : setting vertexDeclaration(%p)\n", This, ((IWineD3DVertexShaderImpl *)pShader)->vertexDeclaration);
4325 IWineD3DDevice_SetVertexDeclaration(iface, ((IWineD3DVertexShaderImpl *)pShader)->vertexDeclaration);
4328 TRACE("(%p) : setting pShader(%p)\n", This, pShader);
4330 * TODO: merge HAL shaders context switching from prototype
4332 return WINED3D_OK;
4335 HRESULT WINAPI IWineD3DDeviceImpl_GetVertexShader(IWineD3DDevice *iface, IWineD3DVertexShader** ppShader) {
4336 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4338 if (NULL == ppShader) {
4339 return WINED3DERR_INVALIDCALL;
4341 *ppShader = This->stateBlock->vertexShader;
4342 if( NULL != *ppShader)
4343 IWineD3DVertexShader_AddRef(*ppShader);
4345 TRACE("(%p) : returning %p\n", This, *ppShader);
4346 return WINED3D_OK;
4349 HRESULT WINAPI IWineD3DDeviceImpl_SetVertexShaderConstant(IWineD3DDevice *iface, void *dstData, const void *srcData, UINT type, UINT start, UINT count, UINT registersize) {
4350 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4352 int i;
4353 int cnt = min(count, MAX_VSHADER_CONSTANTS - (start + 1));
4355 TRACE("(iface %p, dstData %p, srcData %p, type %d, start %d, count %d, registersize %d)\n",
4356 iface, dstData, srcData, type, start, count, registersize);
4358 if (type != WINESHADERCNST_NONE) {
4359 if (srcData == NULL || cnt < 0) {
4360 return WINED3DERR_INVALIDCALL;
4363 CopyMemory((char *)dstData + (start * registersize), srcData, cnt * registersize);
4366 for (i = start; i < cnt + start; ++i) {
4367 This->updateStateBlock->changed.vertexShaderConstants[i] = TRUE;
4368 This->updateStateBlock->set.vertexShaderConstants[i] = TRUE;
4369 This->updateStateBlock->vertexShaderConstantT[i] = type;
4372 return WINED3D_OK;
4375 HRESULT WINAPI IWineD3DDeviceImpl_GetVertexShaderConstant(IWineD3DDevice *iface, void *dstData, const void *srcData, UINT type, UINT start, UINT count, UINT registersize) {
4376 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4378 int i;
4379 int cnt = min(count, MAX_VSHADER_CONSTANTS - (start + 1));
4381 TRACE("(iface %p, dstData %p, srcData %p, type %d, start %d, count %d, registersize %d)\n",
4382 iface, dstData, srcData, type, start, count, registersize);
4384 /* Verify that the requested shader constant was populated with the correct type */
4385 for (i = start; i < cnt + start; ++i) {
4386 if (This->updateStateBlock->vertexShaderConstantT[i] != type) {
4387 TRACE("(%p) : Caller requested 0x%x while type is 0x%x. Returning WINED3DERR_INVALIDCALL\n",
4388 This, type, This->updateStateBlock->vertexShaderConstantT[i]);
4389 return WINED3DERR_INVALIDCALL;
4393 if (dstData == NULL || cnt < 0) {
4394 return WINED3DERR_INVALIDCALL;
4397 CopyMemory(dstData, (char *)srcData + (start * registersize), cnt * registersize);
4399 return WINED3D_OK;
4402 HRESULT WINAPI IWineD3DDeviceImpl_SetVertexShaderConstantB(IWineD3DDevice *iface, UINT StartRegister, CONST BOOL *pConstantData, UINT BoolCount){
4403 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4405 return IWineD3DDeviceImpl_SetVertexShaderConstant(iface,
4406 This->updateStateBlock->vertexShaderConstantB,
4407 pConstantData,
4408 WINESHADERCNST_BOOL,
4409 StartRegister,
4410 BoolCount,
4411 sizeof(*pConstantData));
4414 HRESULT WINAPI IWineD3DDeviceImpl_GetVertexShaderConstantB(IWineD3DDevice *iface, UINT StartRegister, BOOL *pConstantData, UINT BoolCount){
4415 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4417 return IWineD3DDeviceImpl_GetVertexShaderConstant(iface,
4418 pConstantData,
4419 This->updateStateBlock->vertexShaderConstantB,
4420 WINESHADERCNST_BOOL,
4421 StartRegister,
4422 BoolCount,
4423 sizeof(*pConstantData));
4426 HRESULT WINAPI IWineD3DDeviceImpl_SetVertexShaderConstantI(IWineD3DDevice *iface, UINT StartRegister, CONST int *pConstantData, UINT Vector4iCount){
4427 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4429 return IWineD3DDeviceImpl_SetVertexShaderConstant(iface,
4430 This->updateStateBlock->vertexShaderConstantI,
4431 pConstantData,
4432 WINESHADERCNST_INTEGER,
4433 StartRegister,
4434 Vector4iCount,
4435 4 * sizeof(*pConstantData));
4438 HRESULT WINAPI IWineD3DDeviceImpl_GetVertexShaderConstantI(IWineD3DDevice *iface, UINT StartRegister, int *pConstantData, UINT Vector4iCount){
4439 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4441 return IWineD3DDeviceImpl_GetVertexShaderConstant(iface,
4442 pConstantData,
4443 This->updateStateBlock->vertexShaderConstantI,
4444 WINESHADERCNST_INTEGER,
4445 StartRegister,
4446 Vector4iCount,
4447 4 * sizeof(*pConstantData));
4451 HRESULT WINAPI IWineD3DDeviceImpl_SetVertexShaderConstantF(IWineD3DDevice *iface, UINT StartRegister, CONST float *pConstantData, UINT Vector4fCount){
4452 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4454 return IWineD3DDeviceImpl_SetVertexShaderConstant(iface,
4455 This->updateStateBlock->vertexShaderConstantF,
4456 pConstantData,
4457 WINESHADERCNST_FLOAT,
4458 StartRegister,
4459 Vector4fCount,
4460 4 * sizeof(*pConstantData));
4463 HRESULT WINAPI IWineD3DDeviceImpl_GetVertexShaderConstantF(IWineD3DDevice *iface, UINT StartRegister, float *pConstantData, UINT Vector4fCount){
4464 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4466 return IWineD3DDeviceImpl_GetVertexShaderConstant(iface,
4467 pConstantData,
4468 This->updateStateBlock->vertexShaderConstantF,
4469 WINESHADERCNST_FLOAT,
4470 StartRegister,
4471 Vector4fCount,
4472 4 * sizeof(*pConstantData));
4475 HRESULT WINAPI IWineD3DDeviceImpl_SetVertexShaderConstantN(IWineD3DDevice *iface, UINT StartRegister, UINT VectorNCount){
4476 return IWineD3DDeviceImpl_SetVertexShaderConstant(iface,
4477 NULL,
4478 NULL,
4479 WINESHADERCNST_NONE,
4480 StartRegister,
4481 VectorNCount,
4485 HRESULT WINAPI IWineD3DDeviceImpl_SetPixelShader(IWineD3DDevice *iface, IWineD3DPixelShader *pShader) {
4486 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4487 IWineD3DPixelShader *oldShader = This->updateStateBlock->pixelShader;
4488 This->updateStateBlock->pixelShader = pShader;
4489 This->updateStateBlock->changed.pixelShader = TRUE;
4490 This->updateStateBlock->set.pixelShader = TRUE;
4492 /* Handle recording of state blocks */
4493 if (This->isRecordingState) {
4494 TRACE("Recording... not performing anything\n");
4497 if (NULL != pShader) {
4498 IWineD3DPixelShader_AddRef(pShader);
4500 if (NULL != oldShader) {
4501 IWineD3DPixelShader_Release(oldShader);
4504 TRACE("(%p) : setting pShader(%p)\n", This, pShader);
4506 * TODO: merge HAL shaders context switching from prototype
4508 return WINED3D_OK;
4511 HRESULT WINAPI IWineD3DDeviceImpl_GetPixelShader(IWineD3DDevice *iface, IWineD3DPixelShader **ppShader) {
4512 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4514 if (NULL == ppShader) {
4515 WARN("(%p) : PShader is NULL, returning INVALIDCALL\n", This);
4516 return WINED3DERR_INVALIDCALL;
4519 *ppShader = This->stateBlock->pixelShader;
4520 if (NULL != *ppShader) {
4521 IWineD3DPixelShader_AddRef(*ppShader);
4523 TRACE("(%p) : returning %p\n", This, *ppShader);
4524 return WINED3D_OK;
4527 HRESULT WINAPI IWineD3DDeviceImpl_SetPixelShaderConstant(IWineD3DDevice *iface, void *dstData, const void *srcData, UINT type, UINT start, UINT count, UINT registersize) {
4528 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4530 int i;
4531 int cnt = min(count, MAX_PSHADER_CONSTANTS - (start + 1));
4533 TRACE("(iface %p, dstData %p, srcData %p, type %d, start %d, count %d, registersize %d)\n",
4534 iface, dstData, srcData, type, start, count, registersize);
4536 if (type != WINESHADERCNST_NONE) {
4537 if (srcData == NULL || cnt < 0) {
4538 return WINED3DERR_INVALIDCALL;
4541 CopyMemory((char *)dstData + (start * registersize), srcData, cnt * registersize);
4544 for (i = start; i < cnt + start; ++i) {
4545 This->updateStateBlock->changed.pixelShaderConstants[i] = TRUE;
4546 This->updateStateBlock->set.pixelShaderConstants[i] = TRUE;
4547 This->updateStateBlock->pixelShaderConstantT[i] = type;
4550 return WINED3D_OK;
4553 HRESULT WINAPI IWineD3DDeviceImpl_GetPixelShaderConstant(IWineD3DDevice *iface, void *dstData, const void *srcData, UINT type, UINT start, UINT count, UINT registersize) {
4554 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4556 int i;
4557 int cnt = min(count, MAX_PSHADER_CONSTANTS - (start + 1));
4559 TRACE("(iface %p, dstData %p, srcData %p, type %d, start %d, count %d, registersize %d)\n",
4560 iface, dstData, srcData, type, start, count, registersize);
4562 /* Verify that the requested shader constant was populated with the correct type */
4563 for (i = start; i < cnt + start; ++i) {
4564 if (This->updateStateBlock->pixelShaderConstantT[i] != type) {
4565 TRACE("(%p) : Caller requested 0x%x while type is 0x%x. Returning WINED3DERR_INVALIDCALL\n",
4566 This, type, This->updateStateBlock->pixelShaderConstantT[i]);
4567 return WINED3DERR_INVALIDCALL;
4571 if (dstData == NULL || cnt < 0) {
4572 return WINED3DERR_INVALIDCALL;
4575 CopyMemory(dstData, (char *)srcData + (start * registersize), cnt * registersize);
4577 return WINED3D_OK;
4580 HRESULT WINAPI IWineD3DDeviceImpl_SetPixelShaderConstantB(IWineD3DDevice *iface, UINT StartRegister, CONST BOOL *pConstantData, UINT BoolCount) {
4581 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4583 return IWineD3DDeviceImpl_SetPixelShaderConstant(iface,
4584 This->updateStateBlock->pixelShaderConstantB,
4585 pConstantData,
4586 WINESHADERCNST_BOOL,
4587 StartRegister,
4588 BoolCount,
4589 sizeof(*pConstantData));
4592 HRESULT WINAPI IWineD3DDeviceImpl_GetPixelShaderConstantB(IWineD3DDevice *iface, UINT StartRegister, BOOL *pConstantData, UINT BoolCount) {
4593 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4595 return IWineD3DDeviceImpl_GetPixelShaderConstant(iface,
4596 pConstantData,
4597 This->updateStateBlock->pixelShaderConstantB,
4598 WINESHADERCNST_BOOL,
4599 StartRegister,
4600 BoolCount,
4601 sizeof(*pConstantData));
4604 HRESULT WINAPI IWineD3DDeviceImpl_SetPixelShaderConstantI(IWineD3DDevice *iface, UINT StartRegister, CONST int *pConstantData, UINT Vector4iCount) {
4605 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4607 return IWineD3DDeviceImpl_SetPixelShaderConstant(iface,
4608 This->updateStateBlock->pixelShaderConstantI,
4609 pConstantData,
4610 WINESHADERCNST_INTEGER,
4611 StartRegister,
4612 Vector4iCount,
4613 4 * sizeof(*pConstantData));
4616 HRESULT WINAPI IWineD3DDeviceImpl_GetPixelShaderConstantI(IWineD3DDevice *iface, UINT StartRegister, int *pConstantData, UINT Vector4iCount) {
4617 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4619 return IWineD3DDeviceImpl_GetPixelShaderConstant(iface,
4620 pConstantData,
4621 This->updateStateBlock->pixelShaderConstantI,
4622 WINESHADERCNST_INTEGER,
4623 StartRegister,
4624 Vector4iCount,
4625 4 * sizeof(*pConstantData));
4628 HRESULT WINAPI IWineD3DDeviceImpl_SetPixelShaderConstantF(IWineD3DDevice *iface, UINT StartRegister, CONST float *pConstantData, UINT Vector4fCount) {
4629 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4631 return IWineD3DDeviceImpl_SetPixelShaderConstant(iface,
4632 This->updateStateBlock->pixelShaderConstantF,
4633 pConstantData,
4634 WINESHADERCNST_FLOAT,
4635 StartRegister,
4636 Vector4fCount,
4637 4 * sizeof(*pConstantData));
4640 HRESULT WINAPI IWineD3DDeviceImpl_GetPixelShaderConstantF(IWineD3DDevice *iface, UINT StartRegister, float *pConstantData, UINT Vector4fCount) {
4641 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4643 return IWineD3DDeviceImpl_GetPixelShaderConstant(iface,
4644 pConstantData,
4645 This->updateStateBlock->pixelShaderConstantF,
4646 WINESHADERCNST_FLOAT,
4647 StartRegister,
4648 Vector4fCount,
4649 4 * sizeof(*pConstantData));
4652 HRESULT WINAPI IWineD3DDeviceImpl_SetPixelShaderConstantN(IWineD3DDevice *iface, UINT StartRegister, UINT VectorNCount){
4653 return IWineD3DDeviceImpl_SetPixelShaderConstant(iface,
4654 NULL,
4655 NULL,
4656 WINESHADERCNST_NONE,
4657 StartRegister,
4658 VectorNCount,
4662 #define copy_and_next(dest, src, size) memcpy(dest, src, size); dest += (size)
4663 static HRESULT
4664 process_vertices_strided(IWineD3DDeviceImpl *This, DWORD dwDestIndex, DWORD dwCount, WineDirect3DVertexStridedData *lpStrideData, DWORD SrcFVF, IWineD3DVertexBufferImpl *dest, DWORD dwFlags) {
4665 char *dest_ptr;
4666 unsigned int i;
4667 DWORD DestFVF = dest->fvf;
4668 D3DVIEWPORT9 vp;
4669 D3DMATRIX mat, proj_mat, view_mat, world_mat;
4670 BOOL doClip;
4671 int numTextures;
4673 if (SrcFVF & D3DFVF_NORMAL) {
4674 WARN(" lighting state not saved yet... Some strange stuff may happen !\n");
4677 if ( (SrcFVF & D3DFVF_POSITION_MASK) != D3DFVF_XYZ) {
4678 ERR("Source has no position mask\n");
4679 return WINED3DERR_INVALIDCALL;
4682 if (dest->resource.allocatedMemory == NULL) {
4683 ERR("Destination buffer has no memory allocated\n");
4684 return WINED3DERR_INVALIDCALL;
4687 /* Should I clip?
4688 * a) D3DRS_CLIPPING is enabled
4689 * b) WINED3DVOP_CLIP is passed
4691 if(This->stateBlock->renderState[WINED3DRS_CLIPPING]) {
4692 static BOOL warned = FALSE;
4694 * The clipping code is not quite correct. Some things need
4695 * to be checked against IDirect3DDevice3 (!), d3d8 and d3d9,
4696 * so disable clipping for now.
4697 * (The graphics in Half-Life are broken, and my processvertices
4698 * test crashes with IDirect3DDevice3)
4699 doClip = TRUE;
4701 doClip = FALSE;
4702 if(!warned) {
4703 warned = TRUE;
4704 FIXME("Clipping is broken and disabled for now\n");
4706 } else doClip = FALSE;
4707 dest_ptr = ((char *) dest->resource.allocatedMemory) + dwDestIndex * get_flexible_vertex_size(DestFVF);
4709 IWineD3DDevice_GetTransform( (IWineD3DDevice *) This,
4710 D3DTS_VIEW,
4711 &view_mat);
4712 IWineD3DDevice_GetTransform( (IWineD3DDevice *) This,
4713 D3DTS_PROJECTION,
4714 &proj_mat);
4715 IWineD3DDevice_GetTransform( (IWineD3DDevice *) This,
4716 D3DTS_WORLDMATRIX(0),
4717 &world_mat);
4719 TRACE("View mat: \n");
4720 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); \
4721 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); \
4722 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); \
4723 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); \
4725 TRACE("Proj mat: \n");
4726 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); \
4727 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); \
4728 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); \
4729 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); \
4731 TRACE("World mat: \n");
4732 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); \
4733 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); \
4734 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); \
4735 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); \
4737 /* Get the viewport */
4738 IWineD3DDevice_GetViewport( (IWineD3DDevice *) This, &vp);
4739 TRACE("Viewport: X=%ld, Y=%ld, Width=%ld, Height=%ld, MinZ=%f, MaxZ=%f\n",
4740 vp.X, vp.Y, vp.Width, vp.Height, vp.MinZ, vp.MaxZ);
4742 multiply_matrix(&mat,&view_mat,&world_mat);
4743 multiply_matrix(&mat,&proj_mat,&mat);
4745 numTextures = (DestFVF & D3DFVF_TEXCOUNT_MASK) >> D3DFVF_TEXCOUNT_SHIFT;
4747 for (i = 0; i < dwCount; i+= 1) {
4748 unsigned int tex_index;
4750 if ( ((DestFVF & D3DFVF_POSITION_MASK) == D3DFVF_XYZ ) ||
4751 ((DestFVF & D3DFVF_POSITION_MASK) == D3DFVF_XYZRHW ) ) {
4752 /* The position first */
4753 float *p =
4754 (float *) (((char *) lpStrideData->u.s.position.lpData) + i * lpStrideData->u.s.position.dwStride);
4755 float x, y, z, rhw;
4756 TRACE("In: ( %06.2f %06.2f %06.2f )\n", p[0], p[1], p[2]);
4758 /* Multiplication with world, view and projection matrix */
4759 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);
4760 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);
4761 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);
4762 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);
4764 TRACE("x=%f y=%f z=%f rhw=%f\n", x, y, z, rhw);
4766 /* WARNING: The following things are taken from d3d7 and were not yet checked
4767 * against d3d8 or d3d9!
4770 /* Clipping conditions: From
4771 * http://msdn.microsoft.com/archive/default.asp?url=/archive/en-us/directx9_c/directx/graphics/programmingguide/fixedfunction/viewportsclipping/clippingvolumes.asp
4773 * A vertex is clipped if it does not match the following requirements
4774 * -rhw < x <= rhw
4775 * -rhw < y <= rhw
4776 * 0 < z <= rhw
4777 * 0 < rhw ( Not in d3d7, but tested in d3d7)
4779 * If clipping is on is determined by the D3DVOP_CLIP flag in D3D7, and
4780 * by the D3DRS_CLIPPING in D3D9(according to the msdn, not checked)
4784 if( doClip == FALSE ||
4785 ( (-rhw -eps < x) && (-rhw -eps < y) && ( -eps < z) &&
4786 (x <= rhw + eps) && (y <= rhw + eps ) && (z <= rhw + eps) &&
4787 ( rhw > eps ) ) ) {
4789 /* "Normal" viewport transformation (not clipped)
4790 * 1) The values are divided trough rhw
4791 * 2) The y axis is negative, so multiply it with -1
4792 * 3) Screen coordinates go from -(Width/2) to +(Width/2) and
4793 * -(Height/2) to +(Height/2). The z range is MinZ to MaxZ
4794 * 4) Multiply x with Width/2 and add Width/2
4795 * 5) The same for the height
4796 * 6) Add the viewpoint X and Y to the 2D coordinates and
4797 * The minimum Z value to z
4798 * 7) rhw = 1 / rhw Reciprocal of Homogeneous W....
4800 * Well, basically it's simply a linear transformation into viewport
4801 * coordinates
4804 x /= rhw;
4805 y /= rhw;
4806 z /= rhw;
4808 y *= -1;
4810 x *= vp.Width / 2;
4811 y *= vp.Height / 2;
4812 z *= vp.MaxZ - vp.MinZ;
4814 x += vp.Width / 2 + vp.X;
4815 y += vp.Height / 2 + vp.Y;
4816 z += vp.MinZ;
4818 rhw = 1 / rhw;
4819 } else {
4820 /* That vertex got clipped
4821 * Contrary to OpenGL it is not dropped completely, it just
4822 * undergoes a different calculation.
4824 TRACE("Vertex got clipped\n");
4825 x += rhw;
4826 y += rhw;
4828 x /= 2;
4829 y /= 2;
4831 /* Msdn mentiones that Direct3D9 keeps a list of clipped vertices
4832 * outside of the main vertex buffer memory. That needs some more
4833 * investigation...
4837 TRACE("Writing (%f %f %f) %f\n", x, y, z, rhw);
4840 ( (float *) dest_ptr)[0] = x;
4841 ( (float *) dest_ptr)[1] = y;
4842 ( (float *) dest_ptr)[2] = z;
4843 ( (float *) dest_ptr)[3] = rhw; /* SIC, see ddraw test! */
4845 dest_ptr += 3 * sizeof(float);
4847 if((DestFVF & D3DFVF_POSITION_MASK) == D3DFVF_XYZRHW) {
4848 dest_ptr += sizeof(float);
4851 if (DestFVF & D3DFVF_PSIZE) {
4852 dest_ptr += sizeof(DWORD);
4854 if (DestFVF & D3DFVF_NORMAL) {
4855 float *normal =
4856 (float *) (((float *) lpStrideData->u.s.normal.lpData) + i * lpStrideData->u.s.normal.dwStride);
4857 /* AFAIK this should go into the lighting information */
4858 FIXME("Didn't expect the destination to have a normal\n");
4859 copy_and_next(dest_ptr, normal, 3 * sizeof(float));
4862 if (DestFVF & D3DFVF_DIFFUSE) {
4863 DWORD *color_d =
4864 (DWORD *) (((char *) lpStrideData->u.s.diffuse.lpData) + i * lpStrideData->u.s.diffuse.dwStride);
4865 if(!color_d) {
4866 static BOOL warned = FALSE;
4868 if(warned == FALSE) {
4869 ERR("No diffuse color in source, but destination has one\n");
4870 warned = TRUE;
4873 *( (DWORD *) dest_ptr) = 0xffffffff;
4874 dest_ptr += sizeof(DWORD);
4876 else
4877 copy_and_next(dest_ptr, color_d, sizeof(DWORD));
4880 if (DestFVF & D3DFVF_SPECULAR) {
4881 /* What's the color value in the feedback buffer? */
4882 DWORD *color_s =
4883 (DWORD *) (((char *) lpStrideData->u.s.specular.lpData) + i * lpStrideData->u.s.specular.dwStride);
4884 if(!color_s) {
4885 static BOOL warned = FALSE;
4887 if(warned == FALSE) {
4888 ERR("No specular color in source, but destination has one\n");
4889 warned = TRUE;
4892 *( (DWORD *) dest_ptr) = 0xFF000000;
4893 dest_ptr += sizeof(DWORD);
4895 else {
4896 copy_and_next(dest_ptr, color_s, sizeof(DWORD));
4900 for (tex_index = 0; tex_index < numTextures; tex_index++) {
4901 float *tex_coord =
4902 (float *) (((char *) lpStrideData->u.s.texCoords[tex_index].lpData) +
4903 i * lpStrideData->u.s.texCoords[tex_index].dwStride);
4904 if(!tex_coord) {
4905 ERR("No source texture, but destination requests one\n");
4906 dest_ptr+=GET_TEXCOORD_SIZE_FROM_FVF(DestFVF, tex_index) * sizeof(float);
4908 else {
4909 copy_and_next(dest_ptr, tex_coord, GET_TEXCOORD_SIZE_FROM_FVF(DestFVF, tex_index) * sizeof(float));
4914 return WINED3D_OK;
4916 #undef copy_and_next
4918 HRESULT WINAPI IWineD3DDeviceImpl_ProcessVertices(IWineD3DDevice *iface, UINT SrcStartIndex, UINT DestIndex, UINT VertexCount, IWineD3DVertexBuffer* pDestBuffer, IWineD3DVertexBuffer* pVertexDecl, DWORD Flags) {
4919 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4920 IWineD3DVertexBufferImpl *SrcImpl = (IWineD3DVertexBufferImpl *) pVertexDecl;
4921 WineDirect3DVertexStridedData strided;
4922 HRESULT hr;
4923 TRACE("(%p)->(%d,%d,%d,%p,%p,%ld\n", This, SrcStartIndex, DestIndex, VertexCount, pDestBuffer, pVertexDecl, Flags);
4925 hr = IWineD3DDevice_SetFVF(iface, SrcImpl->fvf);
4926 hr = IWineD3DDevice_SetStreamSource(iface, 0, pVertexDecl, get_flexible_vertex_size(SrcImpl->fvf) * SrcStartIndex, get_flexible_vertex_size(SrcImpl->fvf));
4928 memset(&strided, 0, sizeof(strided));
4929 primitiveConvertToStridedData(iface, &strided, 0);
4931 return process_vertices_strided(This, DestIndex, VertexCount, &strided, SrcImpl->fvf, (IWineD3DVertexBufferImpl *) pDestBuffer, Flags);
4934 /*****
4935 * Apply / Get / Set Texture Stage States
4936 * TODO: Verify against dx9 definitions
4937 *****/
4939 /* 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 */
4940 static void WINAPI IWineD3DDeviceImpl_ApplyTextureUnitState(IWineD3DDevice *iface, DWORD Stage, WINED3DTEXTURESTAGESTATETYPE Type) {
4941 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4942 DWORD Value = This->updateStateBlock->textureState[Stage][Type];
4943 /* FIXME: Handle 3d textures? What if TSS value set before set texture? Need to reapply all values? */
4945 TRACE("(%p) : Stage=%ld, Type=%s(%d), Value=%ld\n", This, Stage, debug_d3dtexturestate(Type), Type, Value);
4947 /* Check that the stage is within limits */
4948 if (Stage >= GL_LIMITS(textures) || Stage < 0) {
4949 TRACE("Attempt to access invalid texture rejected\n");
4950 return;
4953 ENTER_GL();
4955 switch (Type) {
4956 case WINED3DTSS_ALPHAOP :
4957 case WINED3DTSS_COLOROP :
4958 /* nothing to do as moved to drawprim for now */
4959 break;
4960 case WINED3DTSS_ADDRESSW :
4961 #if 0 /* I'm not sure what D3D does about ADDRESSW appearing twice */
4962 if (Value < minLookup[WINELOOKUP_WARPPARAM] || Value > maxLookup[WINELOOKUP_WARPPARAM]) {
4963 FIXME("Unrecognized or unsupported D3DTADDRESS_* value %ld, state %d\n", Value, Type);
4965 } else {
4966 GLint wrapParm = stateLookup[WINELOOKUP_WARPPARAM][Value - minLookup[WINELOOKUP_WARPPARAM]];
4967 TRACE("Setting WRAP_R to %d for %x\n", wrapParm, This->stateBlock->textureDimensions[Stage]);
4968 glTexParameteri(This->stateBlock->textureDimensions[Stage], GL_TEXTURE_WRAP_R, wrapParm);
4969 checkGLcall("glTexParameteri(..., GL_TEXTURE_WRAP_R, wrapParm)");
4971 #endif
4972 case WINED3DTSS_TEXCOORDINDEX :
4974 /* Values 0-7 are indexes into the FVF tex coords - See comments in DrawPrimitive */
4976 /* FIXME: From MSDN: The WINED3DTSS_TCI_* flags are mutually exclusive. If you include
4977 one flag, you can still specify an index value, which the system uses to
4978 determine the texture wrapping mode.
4979 eg. SetTextureStageState( 0, D3DTSS_TEXCOORDINDEX, D3DTSS_TCI_CAMERASPACEPOSITION | 1 );
4980 means use the vertex position (camera-space) as the input texture coordinates
4981 for this texture stage, and the wrap mode set in the WINED3DRS_WRAP1 render
4982 state. We do not (yet) support the D3DRENDERSTATE_WRAPx values, nor tie them up
4983 to the TEXCOORDINDEX value */
4986 * Be careful the value of the mask 0xF0000 come from d3d8types.h infos
4988 switch (Value & 0xFFFF0000) {
4989 case D3DTSS_TCI_PASSTHRU:
4990 /*Use the specified texture coordinates contained within the vertex format. This value resolves to zero.*/
4991 glDisable(GL_TEXTURE_GEN_S);
4992 glDisable(GL_TEXTURE_GEN_T);
4993 glDisable(GL_TEXTURE_GEN_R);
4994 glDisable(GL_TEXTURE_GEN_Q);
4995 checkGLcall("glDisable(GL_TEXTURE_GEN_S,T,R,Q)");
4996 break;
4998 case D3DTSS_TCI_CAMERASPACEPOSITION:
4999 /* CameraSpacePosition means use the vertex position, transformed to camera space,
5000 as the input texture coordinates for this stage's texture transformation. This
5001 equates roughly to EYE_LINEAR */
5003 float s_plane[] = { 1.0, 0.0, 0.0, 0.0 };
5004 float t_plane[] = { 0.0, 1.0, 0.0, 0.0 };
5005 float r_plane[] = { 0.0, 0.0, 1.0, 0.0 };
5006 float q_plane[] = { 0.0, 0.0, 0.0, 1.0 };
5007 TRACE("WINED3DTSS_TCI_CAMERASPACEPOSITION - Set eye plane\n");
5009 glMatrixMode(GL_MODELVIEW);
5010 glPushMatrix();
5011 glLoadIdentity();
5012 glTexGenfv(GL_S, GL_EYE_PLANE, s_plane);
5013 glTexGenfv(GL_T, GL_EYE_PLANE, t_plane);
5014 glTexGenfv(GL_R, GL_EYE_PLANE, r_plane);
5015 glTexGenfv(GL_Q, GL_EYE_PLANE, q_plane);
5016 glPopMatrix();
5018 TRACE("WINED3DTSS_TCI_CAMERASPACEPOSITION - Set GL_TEXTURE_GEN_x and GL_x, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR\n");
5019 glEnable(GL_TEXTURE_GEN_S);
5020 checkGLcall("glEnable(GL_TEXTURE_GEN_S);");
5021 glTexGeni(GL_S, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR);
5022 checkGLcall("glTexGeni(GL_S, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR)");
5023 glEnable(GL_TEXTURE_GEN_T);
5024 checkGLcall("glEnable(GL_TEXTURE_GEN_T);");
5025 glTexGeni(GL_T, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR);
5026 checkGLcall("glTexGeni(GL_T, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR)");
5027 glEnable(GL_TEXTURE_GEN_R);
5028 checkGLcall("glEnable(GL_TEXTURE_GEN_R);");
5029 glTexGeni(GL_R, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR);
5030 checkGLcall("glTexGeni(GL_R, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR)");
5032 break;
5034 case D3DTSS_TCI_CAMERASPACENORMAL:
5036 if (GL_SUPPORT(NV_TEXGEN_REFLECTION)) {
5037 float s_plane[] = { 1.0, 0.0, 0.0, 0.0 };
5038 float t_plane[] = { 0.0, 1.0, 0.0, 0.0 };
5039 float r_plane[] = { 0.0, 0.0, 1.0, 0.0 };
5040 float q_plane[] = { 0.0, 0.0, 0.0, 1.0 };
5041 TRACE("WINED3DTSS_TCI_CAMERASPACENORMAL - Set eye plane\n");
5043 glMatrixMode(GL_MODELVIEW);
5044 glPushMatrix();
5045 glLoadIdentity();
5046 glTexGenfv(GL_S, GL_EYE_PLANE, s_plane);
5047 glTexGenfv(GL_T, GL_EYE_PLANE, t_plane);
5048 glTexGenfv(GL_R, GL_EYE_PLANE, r_plane);
5049 glTexGenfv(GL_Q, GL_EYE_PLANE, q_plane);
5050 glPopMatrix();
5052 glEnable(GL_TEXTURE_GEN_S);
5053 checkGLcall("glEnable(GL_TEXTURE_GEN_S);");
5054 glTexGeni(GL_S, GL_TEXTURE_GEN_MODE, GL_NORMAL_MAP_NV);
5055 checkGLcall("glTexGeni(GL_S, GL_TEXTURE_GEN_MODE, GL_NORMAL_MAP_NV)");
5056 glEnable(GL_TEXTURE_GEN_T);
5057 checkGLcall("glEnable(GL_TEXTURE_GEN_T);");
5058 glTexGeni(GL_T, GL_TEXTURE_GEN_MODE, GL_NORMAL_MAP_NV);
5059 checkGLcall("glTexGeni(GL_T, GL_TEXTURE_GEN_MODE, GL_NORMAL_MAP_NV)");
5060 glEnable(GL_TEXTURE_GEN_R);
5061 checkGLcall("glEnable(GL_TEXTURE_GEN_R);");
5062 glTexGeni(GL_R, GL_TEXTURE_GEN_MODE, GL_NORMAL_MAP_NV);
5063 checkGLcall("glTexGeni(GL_R, GL_TEXTURE_GEN_MODE, GL_NORMAL_MAP_NV)");
5066 break;
5068 case D3DTSS_TCI_CAMERASPACEREFLECTIONVECTOR:
5070 if (GL_SUPPORT(NV_TEXGEN_REFLECTION)) {
5071 float s_plane[] = { 1.0, 0.0, 0.0, 0.0 };
5072 float t_plane[] = { 0.0, 1.0, 0.0, 0.0 };
5073 float r_plane[] = { 0.0, 0.0, 1.0, 0.0 };
5074 float q_plane[] = { 0.0, 0.0, 0.0, 1.0 };
5075 TRACE("WINED3DTSS_TCI_CAMERASPACEREFLECTIONVECTOR - Set eye plane\n");
5077 glMatrixMode(GL_MODELVIEW);
5078 glPushMatrix();
5079 glLoadIdentity();
5080 glTexGenfv(GL_S, GL_EYE_PLANE, s_plane);
5081 glTexGenfv(GL_T, GL_EYE_PLANE, t_plane);
5082 glTexGenfv(GL_R, GL_EYE_PLANE, r_plane);
5083 glTexGenfv(GL_Q, GL_EYE_PLANE, q_plane);
5084 glPopMatrix();
5086 glEnable(GL_TEXTURE_GEN_S);
5087 checkGLcall("glEnable(GL_TEXTURE_GEN_S);");
5088 glTexGeni(GL_S, GL_TEXTURE_GEN_MODE, GL_REFLECTION_MAP_NV);
5089 checkGLcall("glTexGeni(GL_S, GL_TEXTURE_GEN_MODE, GL_REFLECTION_MAP_NV)");
5090 glEnable(GL_TEXTURE_GEN_T);
5091 checkGLcall("glEnable(GL_TEXTURE_GEN_T);");
5092 glTexGeni(GL_T, GL_TEXTURE_GEN_MODE, GL_REFLECTION_MAP_NV);
5093 checkGLcall("glTexGeni(GL_T, GL_TEXTURE_GEN_MODE, GL_REFLECTION_MAP_NV)");
5094 glEnable(GL_TEXTURE_GEN_R);
5095 checkGLcall("glEnable(GL_TEXTURE_GEN_R);");
5096 glTexGeni(GL_R, GL_TEXTURE_GEN_MODE, GL_REFLECTION_MAP_NV);
5097 checkGLcall("glTexGeni(GL_R, GL_TEXTURE_GEN_MODE, GL_REFLECTION_MAP_NV)");
5100 break;
5102 /* Unhandled types: */
5103 default:
5104 /* Todo: */
5105 /* ? disable GL_TEXTURE_GEN_n ? */
5106 glDisable(GL_TEXTURE_GEN_S);
5107 glDisable(GL_TEXTURE_GEN_T);
5108 glDisable(GL_TEXTURE_GEN_R);
5109 glDisable(GL_TEXTURE_GEN_Q);
5110 FIXME("Unhandled WINED3DTSS_TEXCOORDINDEX %lx\n", Value);
5111 break;
5114 break;
5116 /* Unhandled */
5117 case WINED3DTSS_TEXTURETRANSFORMFLAGS :
5118 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);
5119 break;
5121 case WINED3DTSS_BUMPENVMAT00 :
5122 case WINED3DTSS_BUMPENVMAT01 :
5123 TRACE("BUMPENVMAT0%u Stage=%ld, Type=%d, Value =%ld\n", Type - WINED3DTSS_BUMPENVMAT00, Stage, Type, Value);
5124 break;
5125 case WINED3DTSS_BUMPENVMAT10 :
5126 case WINED3DTSS_BUMPENVMAT11 :
5127 TRACE("BUMPENVMAT1%u Stage=%ld, Type=%d, Value =%ld\n", Type - WINED3DTSS_BUMPENVMAT10, Stage, Type, Value);
5128 break;
5130 case WINED3DTSS_BUMPENVLSCALE :
5131 TRACE("BUMPENVLSCALE Stage=%ld, Type=%d, Value =%ld\n", Stage, Type, Value);
5132 break;
5134 case WINED3DTSS_BUMPENVLOFFSET :
5135 TRACE("BUMPENVLOFFSET Stage=%ld, Type=%d, Value =%ld\n", Stage, Type, Value);
5136 break;
5138 case WINED3DTSS_RESULTARG :
5139 TRACE("RESULTARG Still a stub, Stage=%ld, Type=%d, Value =%ld\n", Stage, Type, Value);
5140 break;
5142 default:
5143 /* Put back later: FIXME("(%p) : stub, Stage=%ld, Type=%d, Value =%ld\n", This, Stage, Type, Value); */
5144 TRACE("Still a stub, Stage=%ld, Type=%d, Value =%ld\n", Stage, Type, Value);
5147 LEAVE_GL();
5149 return;
5152 /*****
5153 * Get / Set Texture Stage States
5154 * TODO: Verify against dx9 definitions
5155 *****/
5156 HRESULT WINAPI IWineD3DDeviceImpl_SetTextureStageState(IWineD3DDevice *iface, DWORD Stage, WINED3DTEXTURESTAGESTATETYPE Type, DWORD Value) {
5157 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5159 /* FIXME: Handle 3d textures? What if TSS value set before set texture? Need to reapply all values? */
5161 TRACE("(%p) : Stage=%ld, Type=%s(%d), Value=%ld\n", This, Stage, debug_d3dtexturestate(Type), Type, Value);
5163 /* Reject invalid texture units */
5164 if (Stage >= GL_LIMITS(textures)) {
5165 TRACE("Attempt to access invalid texture rejected\n");
5166 return WINED3DERR_INVALIDCALL;
5169 This->updateStateBlock->changed.textureState[Stage][Type] = TRUE;
5170 This->updateStateBlock->set.textureState[Stage][Type] = TRUE;
5171 This->updateStateBlock->textureState[Stage][Type] = Value;
5173 return WINED3D_OK;
5176 HRESULT WINAPI IWineD3DDeviceImpl_GetTextureStageState(IWineD3DDevice *iface, DWORD Stage, WINED3DTEXTURESTAGESTATETYPE Type, DWORD* pValue) {
5177 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5178 TRACE("(%p) : requesting Stage %ld, Type %d getting %ld\n", This, Stage, Type, This->updateStateBlock->textureState[Stage][Type]);
5179 *pValue = This->updateStateBlock->textureState[Stage][Type];
5180 return WINED3D_OK;
5183 /*****
5184 * Get / Set Texture
5185 *****/
5186 HRESULT WINAPI IWineD3DDeviceImpl_SetTexture(IWineD3DDevice *iface, DWORD Stage, IWineD3DBaseTexture* pTexture) {
5188 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5189 IWineD3DBaseTexture *oldTexture;
5191 oldTexture = This->updateStateBlock->textures[Stage];
5192 TRACE("(%p) : Stage(%ld), Texture (%p)\n", This, Stage, pTexture);
5194 #if 0 /* TODO: check so vertex textures */
5195 if (Stage >= D3DVERTEXTEXTURESAMPLER && Stage <= D3DVERTEXTEXTURESAMPLER3){
5196 This->updateStateBlock->vertexTextures[Stage - D3DVERTEXTEXTURESAMPLER] = pTexture;
5197 return WINED3D_OK;
5199 #endif
5201 /* Reject invalid texture units */
5202 if (Stage >= GL_LIMITS(textures) || Stage < 0) {
5203 WARN("Attempt to access invalid texture rejected\n");
5204 return WINED3DERR_INVALIDCALL;
5207 if(pTexture != NULL) {
5208 /* SetTexture isn't allowed on textures in WINED3DPOOL_SCRATCH;
5210 if(((IWineD3DTextureImpl*)pTexture)->resource.pool == WINED3DPOOL_SCRATCH) {
5211 WARN("(%p) Attempt to set scratch texture rejected\n", pTexture);
5212 return WINED3DERR_INVALIDCALL;
5216 oldTexture = This->updateStateBlock->textures[Stage];
5217 TRACE("GL_LIMITS %d\n",GL_LIMITS(textures));
5218 TRACE("(%p) : oldtexture(%p)\n", This,oldTexture);
5220 This->updateStateBlock->set.textures[Stage] = TRUE;
5221 This->updateStateBlock->changed.textures[Stage] = TRUE;
5222 TRACE("(%p) : setting new texture to %p\n", This, pTexture);
5223 This->updateStateBlock->textures[Stage] = pTexture;
5225 /* Handle recording of state blocks */
5226 if (This->isRecordingState) {
5227 TRACE("Recording... not performing anything\n");
5228 return WINED3D_OK;
5231 /** NOTE: MSDN says that setTexture increases the reference count,
5232 * and the the application nust set the texture back to null (or have a leaky application),
5233 * This means we should pass the refcount up to the parent
5234 *******************************/
5235 if (NULL != This->updateStateBlock->textures[Stage]) {
5236 IWineD3DBaseTexture_AddRef(This->updateStateBlock->textures[Stage]);
5239 if (NULL != oldTexture) {
5240 IWineD3DBaseTexture_Release(oldTexture);
5243 /* Reset color keying */
5244 if(Stage == 0 && This->stateBlock->renderState[WINED3DRS_COLORKEYENABLE]) {
5245 BOOL enable_ckey = FALSE;
5247 if(pTexture) {
5248 IWineD3DSurfaceImpl *surf = (IWineD3DSurfaceImpl *) ((IWineD3DTextureImpl *)pTexture)->surfaces[0];
5249 if(surf->CKeyFlags & DDSD_CKSRCBLT) enable_ckey = TRUE;
5252 if(enable_ckey) {
5253 glAlphaFunc(GL_NOTEQUAL, 0.0);
5254 checkGLcall("glAlphaFunc");
5258 return WINED3D_OK;
5261 HRESULT WINAPI IWineD3DDeviceImpl_GetTexture(IWineD3DDevice *iface, DWORD Stage, IWineD3DBaseTexture** ppTexture) {
5262 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5263 TRACE("(%p) : (%ld /* Stage */,%p /* ppTexture */)\n", This, Stage, ppTexture);
5265 /* Reject invalid texture units */
5266 if (Stage >= GL_LIMITS(textures)) {
5267 TRACE("Attempt to access invalid texture rejected\n");
5268 return WINED3DERR_INVALIDCALL;
5270 *ppTexture=This->updateStateBlock->textures[Stage];
5271 if (*ppTexture)
5272 IWineD3DBaseTexture_AddRef(*ppTexture);
5273 else
5274 return WINED3DERR_INVALIDCALL;
5275 return WINED3D_OK;
5278 /*****
5279 * Get Back Buffer
5280 *****/
5281 HRESULT WINAPI IWineD3DDeviceImpl_GetBackBuffer(IWineD3DDevice *iface, UINT iSwapChain, UINT BackBuffer, WINED3DBACKBUFFER_TYPE Type,
5282 IWineD3DSurface **ppBackBuffer) {
5283 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5284 IWineD3DSwapChain *swapChain;
5285 HRESULT hr;
5287 TRACE("(%p) : BackBuf %d Type %d SwapChain %d returning %p\n", This, BackBuffer, Type, iSwapChain, *ppBackBuffer);
5289 hr = IWineD3DDeviceImpl_GetSwapChain(iface, iSwapChain, &swapChain);
5290 if (hr == WINED3D_OK) {
5291 hr = IWineD3DSwapChain_GetBackBuffer(swapChain, BackBuffer, Type, ppBackBuffer);
5292 IWineD3DSwapChain_Release(swapChain);
5293 } else {
5294 *ppBackBuffer = NULL;
5296 return hr;
5299 HRESULT WINAPI IWineD3DDeviceImpl_GetDeviceCaps(IWineD3DDevice *iface, WINED3DCAPS* pCaps) {
5300 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5301 WARN("(%p) : stub, calling idirect3d for now\n", This);
5302 return IWineD3D_GetDeviceCaps(This->wineD3D, This->adapterNo, This->devType, pCaps);
5305 HRESULT WINAPI IWineD3DDeviceImpl_GetDisplayMode(IWineD3DDevice *iface, UINT iSwapChain, WINED3DDISPLAYMODE* pMode) {
5306 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5307 IWineD3DSwapChain *swapChain;
5308 HRESULT hr;
5310 if(iSwapChain > 0) {
5311 hr = IWineD3DDeviceImpl_GetSwapChain(iface, iSwapChain, (IWineD3DSwapChain **)&swapChain);
5312 if (hr == WINED3D_OK) {
5313 hr = IWineD3DSwapChain_GetDisplayMode(swapChain, pMode);
5314 IWineD3DSwapChain_Release(swapChain);
5315 } else {
5316 FIXME("(%p) Error getting display mode\n", This);
5318 } else {
5319 /* Don't read the real display mode,
5320 but return the stored mode instead. X11 can't change the color
5321 depth, and some apps are pretty angry if they SetDisplayMode from
5322 24 to 16 bpp and find out that GetDisplayMode still returns 24 bpp
5324 Also don't relay to the swapchain because with ddraw it's possible
5325 that there isn't a swapchain at all */
5326 pMode->Width = This->ddraw_width;
5327 pMode->Height = This->ddraw_height;
5328 pMode->Format = This->ddraw_format;
5329 pMode->RefreshRate = 0;
5330 hr = WINED3D_OK;
5333 return hr;
5336 HRESULT WINAPI IWineD3DDeviceImpl_SetHWND(IWineD3DDevice *iface, HWND hWnd) {
5337 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5338 TRACE("(%p)->(%p)\n", This, hWnd);
5340 This->ddraw_window = hWnd;
5341 return WINED3D_OK;
5344 HRESULT WINAPI IWineD3DDeviceImpl_GetHWND(IWineD3DDevice *iface, HWND *hWnd) {
5345 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5346 TRACE("(%p)->(%p)\n", This, hWnd);
5348 *hWnd = This->ddraw_window;
5349 return WINED3D_OK;
5352 /*****
5353 * Stateblock related functions
5354 *****/
5356 HRESULT WINAPI IWineD3DDeviceImpl_BeginStateBlock(IWineD3DDevice *iface) {
5357 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5358 IWineD3DStateBlockImpl *object;
5359 TRACE("(%p)", This);
5361 if (This->isRecordingState) {
5362 return WINED3DERR_INVALIDCALL;
5365 object = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(IWineD3DStateBlockImpl));
5366 if (NULL == object ) {
5367 FIXME("(%p)Error allocating memory for stateblock\n", This);
5368 return E_OUTOFMEMORY;
5370 TRACE("(%p) creted object %p\n", This, object);
5371 object->wineD3DDevice= This;
5372 /** FIXME: object->parent = parent; **/
5373 object->parent = NULL;
5374 object->blockType = WINED3DSBT_ALL;
5375 object->ref = 1;
5376 object->lpVtbl = &IWineD3DStateBlock_Vtbl;
5378 IWineD3DStateBlock_Release((IWineD3DStateBlock*)This->updateStateBlock);
5379 This->updateStateBlock = object;
5380 This->isRecordingState = TRUE;
5382 TRACE("(%p) recording stateblock %p\n",This , object);
5383 return WINED3D_OK;
5386 HRESULT WINAPI IWineD3DDeviceImpl_EndStateBlock(IWineD3DDevice *iface, IWineD3DStateBlock** ppStateBlock) {
5387 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5389 if (!This->isRecordingState) {
5390 FIXME("(%p) not recording! returning error\n", This);
5391 *ppStateBlock = NULL;
5392 return WINED3DERR_INVALIDCALL;
5395 *ppStateBlock = (IWineD3DStateBlock*)This->updateStateBlock;
5396 This->isRecordingState = FALSE;
5397 This->updateStateBlock = This->stateBlock;
5398 IWineD3DStateBlock_AddRef((IWineD3DStateBlock*)This->updateStateBlock);
5399 /* IWineD3DStateBlock_AddRef(*ppStateBlock); don't need to do this, since we should really just release UpdateStateBlock first */
5400 TRACE("(%p) returning token (ptr to stateblock) of %p\n", This, *ppStateBlock);
5401 return WINED3D_OK;
5404 /*****
5405 * Scene related functions
5406 *****/
5407 HRESULT WINAPI IWineD3DDeviceImpl_BeginScene(IWineD3DDevice *iface) {
5408 /* At the moment we have no need for any functionality at the beginning
5409 of a scene */
5410 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5411 TRACE("(%p) : stub\n", This);
5412 return WINED3D_OK;
5415 HRESULT WINAPI IWineD3DDeviceImpl_EndScene(IWineD3DDevice *iface) {
5416 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5417 TRACE("(%p)\n", This);
5418 ENTER_GL();
5419 /* We only have to do this if we need to read the, swapbuffers performs a flush for us */
5420 glFlush();
5421 checkGLcall("glFlush");
5423 TRACE("End Scene\n");
5424 if(This->renderTarget != NULL) {
5426 /* If the container of the rendertarget is a texture then we need to save the data from the pbuffer */
5427 IUnknown *targetContainer = NULL;
5428 if (WINED3D_OK == IWineD3DSurface_GetContainer(This->renderTarget, &IID_IWineD3DBaseTexture, (void **)&targetContainer)
5429 || WINED3D_OK == IWineD3DSurface_GetContainer(This->renderTarget, &IID_IWineD3DDevice, (void **)&targetContainer)) {
5430 TRACE("(%p) : Texture rendertarget %p\n", This ,This->renderTarget);
5431 /** always dirtify for now. we must find a better way to see that surface have been modified
5432 (Modifications should will only occur via draw-primitive, but we do need better locking
5433 switching to render-to-texture should remove the overhead though.
5435 IWineD3DSurface_SetPBufferState(This->renderTarget, TRUE /* inPBuffer */, FALSE /* inTexture */);
5436 IWineD3DSurface_AddDirtyRect(This->renderTarget, NULL);
5437 IWineD3DSurface_PreLoad(This->renderTarget);
5438 IWineD3DSurface_SetPBufferState(This->renderTarget, FALSE /* inPBuffer */, FALSE /* inTexture */);
5439 IUnknown_Release(targetContainer);
5442 This->sceneEnded = TRUE;
5443 LEAVE_GL();
5444 return WINED3D_OK;
5447 HRESULT WINAPI IWineD3DDeviceImpl_Present(IWineD3DDevice *iface,
5448 CONST RECT* pSourceRect, CONST RECT* pDestRect,
5449 HWND hDestWindowOverride, CONST RGNDATA* pDirtyRegion) {
5450 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5451 IWineD3DSwapChain *swapChain = NULL;
5452 int i;
5453 int swapchains = IWineD3DDeviceImpl_GetNumberOfSwapChains(iface);
5455 TRACE("(%p) Presenting the frame\n", This);
5457 for(i = 0 ; i < swapchains ; i ++) {
5459 IWineD3DDeviceImpl_GetSwapChain(iface, i , (IWineD3DSwapChain **)&swapChain);
5460 TRACE("presentinng chain %d, %p\n", i, swapChain);
5461 IWineD3DSwapChain_Present(swapChain, pSourceRect, pDestRect, hDestWindowOverride, pDirtyRegion, 0);
5462 IWineD3DSwapChain_Release(swapChain);
5465 return WINED3D_OK;
5468 HRESULT WINAPI IWineD3DDeviceImpl_Clear(IWineD3DDevice *iface, DWORD Count, CONST D3DRECT* pRects,
5469 DWORD Flags, D3DCOLOR Color, float Z, DWORD Stencil) {
5470 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5472 /* TODO: From MSDN This method fails if you specify the D3DCLEAR_ZBUFFER or D3DCLEAR_STENCIL flags when the
5473 render target does not have an attached depth buffer. Similarly, if you specify the D3DCLEAR_STENCIL flag
5474 when the depth-buffer format does not contain stencil buffer information, this method fails. */
5475 GLbitfield glMask = 0;
5476 GLboolean old_ztest;
5477 GLfloat old_z_clear_value;
5478 GLint old_stencil_clear_value;
5479 GLfloat old_color_clear_value[4];
5480 unsigned int i;
5481 CONST D3DRECT* curRect;
5483 TRACE("(%p) Count (%ld), pRects (%p), Flags (%lx), Z (%f), Stencil (%ld)\n", This,
5484 Count, pRects, Flags, Z, Stencil);
5486 ENTER_GL();
5488 glEnable(GL_SCISSOR_TEST);
5489 checkGLcall("glEnable GL_SCISSOR_TEST");
5491 if (Count > 0 && pRects) {
5492 curRect = pRects;
5493 } else {
5494 curRect = NULL;
5497 /* Only set the values up once, as they are not changing */
5498 if (Flags & D3DCLEAR_STENCIL) {
5499 glGetIntegerv(GL_STENCIL_CLEAR_VALUE, &old_stencil_clear_value);
5500 glClearStencil(Stencil);
5501 checkGLcall("glClearStencil");
5502 glMask = glMask | GL_STENCIL_BUFFER_BIT;
5503 glStencilMask(0xFFFFFFFF);
5506 if (Flags & D3DCLEAR_ZBUFFER) {
5507 glGetBooleanv(GL_DEPTH_WRITEMASK, &old_ztest);
5508 glDepthMask(GL_TRUE);
5509 glGetFloatv(GL_DEPTH_CLEAR_VALUE, &old_z_clear_value);
5510 glClearDepth(Z);
5511 checkGLcall("glClearDepth");
5512 glMask = glMask | GL_DEPTH_BUFFER_BIT;
5515 if (Flags & D3DCLEAR_TARGET) {
5516 TRACE("Clearing screen with glClear to color %lx\n", Color);
5517 glGetFloatv(GL_COLOR_CLEAR_VALUE, old_color_clear_value);
5518 glClearColor(D3DCOLOR_R(Color),
5519 D3DCOLOR_G(Color),
5520 D3DCOLOR_B(Color),
5521 D3DCOLOR_A(Color));
5522 checkGLcall("glClearColor");
5524 /* Clear ALL colors! */
5525 glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
5526 glMask = glMask | GL_COLOR_BUFFER_BIT;
5529 /* Now process each rect in turn */
5530 for (i = 0; i < Count || i == 0; i++) {
5532 if (curRect) {
5533 /* Note gl uses lower left, width/height */
5534 TRACE("(%p) %p Rect=(%ld,%ld)->(%ld,%ld) glRect=(%ld,%ld), len=%ld, hei=%ld\n", This, curRect,
5535 curRect->x1, curRect->y1, curRect->x2, curRect->y2,
5536 curRect->x1, (((IWineD3DSurfaceImpl *)This->renderTarget)->currentDesc.Height - curRect->y2),
5537 curRect->x2 - curRect->x1, curRect->y2 - curRect->y1);
5538 glScissor(curRect->x1, (((IWineD3DSurfaceImpl *)This->renderTarget)->currentDesc.Height - curRect->y2),
5539 curRect->x2 - curRect->x1, curRect->y2 - curRect->y1);
5540 checkGLcall("glScissor");
5541 } else {
5542 glScissor(This->stateBlock->viewport.X,
5543 (((IWineD3DSurfaceImpl *)This->renderTarget)->currentDesc.Height -
5544 (This->stateBlock->viewport.Y + This->stateBlock->viewport.Height)),
5545 This->stateBlock->viewport.Width,
5546 This->stateBlock->viewport.Height);
5547 checkGLcall("glScissor");
5550 /* Clear the selected rectangle (or full screen) */
5551 glClear(glMask);
5552 checkGLcall("glClear");
5554 /* Step to the next rectangle */
5555 if (curRect) curRect = curRect + sizeof(D3DRECT);
5558 /* Restore the old values (why..?) */
5559 if (Flags & D3DCLEAR_STENCIL) {
5560 glClearStencil(old_stencil_clear_value);
5561 glStencilMask(This->stateBlock->renderState[WINED3DRS_STENCILWRITEMASK]);
5563 if (Flags & D3DCLEAR_ZBUFFER) {
5564 glDepthMask(old_ztest);
5565 glClearDepth(old_z_clear_value);
5567 if (Flags & D3DCLEAR_TARGET) {
5568 glClearColor(old_color_clear_value[0],
5569 old_color_clear_value[1],
5570 old_color_clear_value[2],
5571 old_color_clear_value[3]);
5572 glColorMask(This->stateBlock->renderState[WINED3DRS_COLORWRITEENABLE] & D3DCOLORWRITEENABLE_RED ? GL_TRUE : GL_FALSE,
5573 This->stateBlock->renderState[WINED3DRS_COLORWRITEENABLE] & D3DCOLORWRITEENABLE_GREEN ? GL_TRUE : GL_FALSE,
5574 This->stateBlock->renderState[WINED3DRS_COLORWRITEENABLE] & D3DCOLORWRITEENABLE_BLUE ? GL_TRUE : GL_FALSE,
5575 This->stateBlock->renderState[WINED3DRS_COLORWRITEENABLE] & D3DCOLORWRITEENABLE_ALPHA ? GL_TRUE : GL_FALSE);
5578 glDisable(GL_SCISSOR_TEST);
5579 checkGLcall("glDisable");
5580 LEAVE_GL();
5582 return WINED3D_OK;
5585 /*****
5586 * Drawing functions
5587 *****/
5588 HRESULT WINAPI IWineD3DDeviceImpl_DrawPrimitive(IWineD3DDevice *iface, D3DPRIMITIVETYPE PrimitiveType, UINT StartVertex,
5589 UINT PrimitiveCount) {
5591 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5592 This->stateBlock->streamIsUP = FALSE;
5594 TRACE("(%p) : Type=(%d,%s), Start=%d, Count=%d\n", This, PrimitiveType,
5595 debug_d3dprimitivetype(PrimitiveType),
5596 StartVertex, PrimitiveCount);
5597 drawPrimitive(iface, PrimitiveType, PrimitiveCount, StartVertex, 0/* NumVertices */, -1 /* indxStart */,
5598 0 /* indxSize */, NULL /* indxData */, 0 /* minIndex */, NULL);
5601 return WINED3D_OK;
5604 /* TODO: baseVIndex needs to be provided from This->stateBlock->baseVertexIndex when called from d3d8 */
5605 HRESULT WINAPI IWineD3DDeviceImpl_DrawIndexedPrimitive(IWineD3DDevice *iface,
5606 D3DPRIMITIVETYPE PrimitiveType,
5607 INT baseVIndex, UINT minIndex,
5608 UINT NumVertices, UINT startIndex, UINT primCount) {
5610 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5611 UINT idxStride = 2;
5612 IWineD3DIndexBuffer *pIB;
5613 WINED3DINDEXBUFFER_DESC IdxBufDsc;
5615 pIB = This->stateBlock->pIndexData;
5616 This->stateBlock->streamIsUP = FALSE;
5618 TRACE("(%p) : Type=(%d,%s), min=%d, CountV=%d, startIdx=%d, baseVidx=%d, countP=%d\n", This,
5619 PrimitiveType, debug_d3dprimitivetype(PrimitiveType),
5620 minIndex, NumVertices, startIndex, baseVIndex, primCount);
5622 IWineD3DIndexBuffer_GetDesc(pIB, &IdxBufDsc);
5623 if (IdxBufDsc.Format == WINED3DFMT_INDEX16) {
5624 idxStride = 2;
5625 } else {
5626 idxStride = 4;
5629 drawPrimitive(iface, PrimitiveType, primCount, baseVIndex, NumVertices, startIndex,
5630 idxStride, ((IWineD3DIndexBufferImpl *) pIB)->resource.allocatedMemory, minIndex, NULL);
5632 return WINED3D_OK;
5635 HRESULT WINAPI IWineD3DDeviceImpl_DrawPrimitiveUP(IWineD3DDevice *iface, D3DPRIMITIVETYPE PrimitiveType,
5636 UINT PrimitiveCount, CONST void* pVertexStreamZeroData,
5637 UINT VertexStreamZeroStride) {
5638 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5640 TRACE("(%p) : Type=(%d,%s), pCount=%d, pVtxData=%p, Stride=%d\n", This, PrimitiveType,
5641 debug_d3dprimitivetype(PrimitiveType),
5642 PrimitiveCount, pVertexStreamZeroData, VertexStreamZeroStride);
5644 /* release the stream source */
5645 if (This->stateBlock->streamSource[0] != NULL) {
5646 IWineD3DVertexBuffer_Release(This->stateBlock->streamSource[0]);
5649 /* Note in the following, it's not this type, but that's the purpose of streamIsUP */
5650 This->stateBlock->streamSource[0] = (IWineD3DVertexBuffer *)pVertexStreamZeroData;
5651 This->stateBlock->streamStride[0] = VertexStreamZeroStride;
5652 This->stateBlock->streamIsUP = TRUE;
5654 drawPrimitive(iface, PrimitiveType, PrimitiveCount, 0 /* start vertex */, 0 /* NumVertices */,
5655 0 /* indxStart*/, 0 /* indxSize*/, NULL /* indxData */, 0 /* indxMin */, NULL);
5657 /* MSDN specifies stream zero settings must be set to NULL */
5658 This->stateBlock->streamStride[0] = 0;
5659 This->stateBlock->streamSource[0] = NULL;
5661 /*stream zero settings set to null at end, as per the msdn */
5662 return WINED3D_OK;
5665 HRESULT WINAPI IWineD3DDeviceImpl_DrawIndexedPrimitiveUP(IWineD3DDevice *iface, D3DPRIMITIVETYPE PrimitiveType,
5666 UINT MinVertexIndex, UINT NumVertices,
5667 UINT PrimitiveCount, CONST void* pIndexData,
5668 WINED3DFORMAT IndexDataFormat,CONST void* pVertexStreamZeroData,
5669 UINT VertexStreamZeroStride) {
5670 int idxStride;
5671 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5673 TRACE("(%p) : Type=(%d,%s), MinVtxIdx=%d, NumVIdx=%d, PCount=%d, pidxdata=%p, IdxFmt=%d, pVtxdata=%p, stride=%d\n",
5674 This, PrimitiveType, debug_d3dprimitivetype(PrimitiveType),
5675 MinVertexIndex, NumVertices, PrimitiveCount, pIndexData,
5676 IndexDataFormat, pVertexStreamZeroData, VertexStreamZeroStride);
5678 if (IndexDataFormat == WINED3DFMT_INDEX16) {
5679 idxStride = 2;
5680 } else {
5681 idxStride = 4;
5684 /* release the stream and index data */
5685 if (This->stateBlock->streamSource[0] != NULL) {
5686 IWineD3DVertexBuffer_Release(This->stateBlock->streamSource[0]);
5688 if (This->stateBlock->pIndexData) {
5689 IWineD3DIndexBuffer_Release(This->stateBlock->pIndexData);
5692 /* Note in the following, it's not this type, but that's the purpose of streamIsUP */
5693 This->stateBlock->streamSource[0] = (IWineD3DVertexBuffer *)pVertexStreamZeroData;
5694 This->stateBlock->streamIsUP = TRUE;
5695 This->stateBlock->streamStride[0] = VertexStreamZeroStride;
5697 drawPrimitive(iface, PrimitiveType, PrimitiveCount, 0 /* vertexStart */, NumVertices, 0 /* indxStart */, idxStride, pIndexData, MinVertexIndex, NULL);
5699 /* MSDN specifies stream zero settings and index buffer must be set to NULL */
5700 This->stateBlock->streamSource[0] = NULL;
5701 This->stateBlock->streamStride[0] = 0;
5702 This->stateBlock->pIndexData = NULL;
5704 return WINED3D_OK;
5707 HRESULT WINAPI IWineD3DDeviceImpl_DrawPrimitiveStrided (IWineD3DDevice *iface, D3DPRIMITIVETYPE PrimitiveType, UINT PrimitiveCount, WineDirect3DVertexStridedData *DrawPrimStrideData) {
5709 drawPrimitive(iface, PrimitiveType, PrimitiveCount, 0, 0, 0, 0, NULL, 0, DrawPrimStrideData);
5710 return WINED3D_OK;
5712 /* Yet another way to update a texture, some apps use this to load default textures instead of using surface/texture lock/unlock */
5713 HRESULT WINAPI IWineD3DDeviceImpl_UpdateTexture (IWineD3DDevice *iface, IWineD3DBaseTexture *pSourceTexture, IWineD3DBaseTexture *pDestinationTexture){
5714 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5715 HRESULT hr = WINED3D_OK;
5716 WINED3DRESOURCETYPE sourceType;
5717 WINED3DRESOURCETYPE destinationType;
5718 int i ,levels;
5720 /* TODO: think about moving the code into IWineD3DBaseTexture */
5722 TRACE("(%p) Source %p Destination %p\n", This, pSourceTexture, pDestinationTexture);
5724 /* verify that the source and destination textures aren't NULL */
5725 if (NULL == pSourceTexture || NULL == pDestinationTexture) {
5726 WARN("(%p) : source (%p) and destination (%p) textures must not be NULL, returning WINED3DERR_INVALIDCALL\n",
5727 This, pSourceTexture, pDestinationTexture);
5728 hr = WINED3DERR_INVALIDCALL;
5731 if (pSourceTexture == pDestinationTexture) {
5732 WARN("(%p) : source (%p) and destination (%p) textures must be different, returning WINED3DERR_INVALIDCALL\n",
5733 This, pSourceTexture, pDestinationTexture);
5734 hr = WINED3DERR_INVALIDCALL;
5736 /* Verify that the source and destination textures are the same type */
5737 sourceType = IWineD3DBaseTexture_GetType(pSourceTexture);
5738 destinationType = IWineD3DBaseTexture_GetType(pDestinationTexture);
5740 if (sourceType != destinationType) {
5741 WARN("(%p) Sorce and destination types must match, returning WINED3DERR_INVALIDCALL\n",
5742 This);
5743 hr = WINED3DERR_INVALIDCALL;
5746 /* check that both textures have the identical numbers of levels */
5747 if (IWineD3DBaseTexture_GetLevelCount(pDestinationTexture) != IWineD3DBaseTexture_GetLevelCount(pSourceTexture)) {
5748 WARN("(%p) : source (%p) and destination (%p) textures must have identicle numbers of levels, returning WINED3DERR_INVALIDCALL\n", This, pSourceTexture, pDestinationTexture);
5749 hr = WINED3DERR_INVALIDCALL;
5752 if (WINED3D_OK == hr) {
5754 /* Make sure that the destination texture is loaded */
5755 IWineD3DBaseTexture_PreLoad(pDestinationTexture);
5757 /* Update every surface level of the texture */
5758 levels = IWineD3DBaseTexture_GetLevelCount(pDestinationTexture);
5760 switch (sourceType) {
5761 case WINED3DRTYPE_TEXTURE:
5763 IWineD3DSurface *srcSurface;
5764 IWineD3DSurface *destSurface;
5766 for (i = 0 ; i < levels ; ++i) {
5767 IWineD3DTexture_GetSurfaceLevel((IWineD3DTexture *)pSourceTexture, i, &srcSurface);
5768 IWineD3DTexture_GetSurfaceLevel((IWineD3DTexture *)pDestinationTexture, i, &destSurface);
5769 hr = IWineD3DDevice_UpdateSurface(iface, srcSurface, NULL, destSurface, NULL);
5770 IWineD3DSurface_Release(srcSurface);
5771 IWineD3DSurface_Release(destSurface);
5772 if (WINED3D_OK != hr) {
5773 WARN("(%p) : Call to update surface failed\n", This);
5774 return hr;
5778 break;
5779 case WINED3DRTYPE_CUBETEXTURE:
5781 IWineD3DSurface *srcSurface;
5782 IWineD3DSurface *destSurface;
5783 WINED3DCUBEMAP_FACES faceType;
5785 for (i = 0 ; i < levels ; ++i) {
5786 /* Update each cube face */
5787 for (faceType = D3DCUBEMAP_FACE_POSITIVE_X; faceType <= D3DCUBEMAP_FACE_NEGATIVE_Z; ++faceType){
5788 hr = IWineD3DCubeTexture_GetCubeMapSurface((IWineD3DCubeTexture *)pSourceTexture, faceType, i, &srcSurface);
5789 if (WINED3D_OK != hr) {
5790 FIXME("(%p) : Failed to get src cube surface facetype %d, level %d\n", This, faceType, i);
5791 } else {
5792 TRACE("Got srcSurface %p\n", srcSurface);
5794 hr = IWineD3DCubeTexture_GetCubeMapSurface((IWineD3DCubeTexture *)pDestinationTexture, faceType, i, &destSurface);
5795 if (WINED3D_OK != hr) {
5796 FIXME("(%p) : Failed to get src cube surface facetype %d, level %d\n", This, faceType, i);
5797 } else {
5798 TRACE("Got desrSurface %p\n", destSurface);
5800 hr = IWineD3DDevice_UpdateSurface(iface, srcSurface, NULL, destSurface, NULL);
5801 IWineD3DSurface_Release(srcSurface);
5802 IWineD3DSurface_Release(destSurface);
5803 if (WINED3D_OK != hr) {
5804 WARN("(%p) : Call to update surface failed\n", This);
5805 return hr;
5810 break;
5811 #if 0 /* TODO: Add support for volume textures */
5812 case WINED3DRTYPE_VOLUMETEXTURE:
5814 IWineD3DVolume srcVolume = NULL;
5815 IWineD3DSurface destVolume = NULL;
5817 for (i = 0 ; i < levels ; ++i) {
5818 IWineD3DVolumeTexture_GetVolume((IWineD3DVolumeTexture *)pSourceTexture, i, &srcVolume);
5819 IWineD3DVolumeTexture_GetVolume((IWineD3DVolumeTexture *)pDestinationTexture, i, &destVolume);
5820 hr = IWineD3DFoo_UpdateVolume(iface, srcVolume, NULL, destVolume, NULL);
5821 IWineD3DVolume_Release(srcSurface);
5822 IWineD3DVolume_Release(destSurface);
5823 if (WINED3D_OK != hr) {
5824 WARN("(%p) : Call to update volume failed\n", This);
5825 return hr;
5829 break;
5830 #endif
5831 default:
5832 FIXME("(%p) : Unsupported source and destination type\n", This);
5833 hr = WINED3DERR_INVALIDCALL;
5837 return hr;
5840 HRESULT WINAPI IWineD3DDeviceImpl_StretchRect(IWineD3DDevice *iface, IWineD3DSurface *pSourceSurface,
5841 CONST RECT* pSourceRect, IWineD3DSurface *pDestinationSurface,
5842 CONST RECT* pDestRect, WINED3DTEXTUREFILTERTYPE Filter) {
5843 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5845 TRACE("(%p) : stub\n", This);
5846 return WINED3D_OK;
5848 HRESULT WINAPI IWineD3DDeviceImpl_GetRenderTargetData(IWineD3DDevice *iface, IWineD3DSurface *pRenderTarget, IWineD3DSurface *pSurface) {
5849 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5850 /** TODO: remove remove casts to IWineD3DSurfaceImpl *
5851 * NOTE It may be best to move the code into surface to occomplish this
5852 ****************************************/
5854 WINED3DSURFACE_DESC surfaceDesc;
5855 unsigned int surfaceWidth, surfaceHeight;
5856 glDescriptor *targetGlDescription = NULL;
5857 glDescriptor *surfaceGlDescription = NULL;
5858 IWineD3DSwapChainImpl *container = NULL;
5860 IWineD3DSurface_GetGlDesc(pRenderTarget, &targetGlDescription);
5861 IWineD3DSurface_GetGlDesc(pSurface, &surfaceGlDescription);
5862 memset(&surfaceDesc, 0, sizeof(surfaceDesc));
5864 surfaceDesc.Width = &surfaceWidth;
5865 surfaceDesc.Height = &surfaceHeight;
5866 IWineD3DSurface_GetDesc(pSurface, &surfaceDesc);
5867 /* check to see if it's the backbuffer or the frontbuffer being requested (to make sure the data is up to date)*/
5869 /* Ok, I may need to setup some kind of active swapchain reference on the device */
5870 IWineD3DSurface_GetContainer(pRenderTarget, &IID_IWineD3DSwapChain, (void **)&container);
5871 ENTER_GL();
5872 /* TODO: opengl Context switching for swapchains etc... */
5873 if (NULL != container || pRenderTarget == This->renderTarget || pRenderTarget == This->depthStencilBuffer) {
5874 if (NULL != container && (pRenderTarget == container->backBuffer)) {
5875 glReadBuffer(GL_BACK);
5876 vcheckGLcall("glReadBuffer(GL_BACK)");
5877 } else if ((NULL != container && (pRenderTarget == container->frontBuffer)) || (pRenderTarget == This->renderTarget)) {
5878 glReadBuffer(GL_FRONT);
5879 vcheckGLcall("glReadBuffer(GL_FRONT)");
5880 } else if (pRenderTarget == This->depthStencilBuffer) {
5881 FIXME("Reading of depthstencil not yet supported\n");
5884 glReadPixels(surfaceGlDescription->target,
5885 surfaceGlDescription->level,
5886 surfaceWidth,
5887 surfaceHeight,
5888 surfaceGlDescription->glFormat,
5889 surfaceGlDescription->glType,
5890 (void *)IWineD3DSurface_GetData(pSurface));
5891 vcheckGLcall("glReadPixels(...)");
5892 if(NULL != container ){
5893 IWineD3DSwapChain_Release((IWineD3DSwapChain*) container);
5895 } else {
5896 IWineD3DBaseTexture *container;
5897 GLenum textureDimensions = GL_TEXTURE_2D;
5899 if (WINED3D_OK == IWineD3DSurface_GetContainer(pSurface, &IID_IWineD3DBaseTexture, (void **)&container)) {
5900 textureDimensions = IWineD3DBaseTexture_GetTextureDimensions(container);
5901 IWineD3DBaseTexture_Release(container);
5903 /* TODO: 2D -> Cube surface coppies etc.. */
5904 if (surfaceGlDescription->target != textureDimensions) {
5905 FIXME("(%p) : Texture dimension mismatch\n", This);
5907 glEnable(textureDimensions);
5908 vcheckGLcall("glEnable(GL_TEXTURE_...)");
5909 /* FIXME: this isn't correct, it need to add a dirty rect if nothing else... */
5910 glBindTexture(targetGlDescription->target, targetGlDescription->textureName);
5911 vcheckGLcall("glBindTexture");
5912 glGetTexImage(surfaceGlDescription->target,
5913 surfaceGlDescription->level,
5914 surfaceGlDescription->glFormat,
5915 surfaceGlDescription->glType,
5916 (void *)IWineD3DSurface_GetData(pSurface));
5917 glDisable(textureDimensions);
5918 vcheckGLcall("glDisable(GL_TEXTURE_...)");
5921 LEAVE_GL();
5922 return WINED3D_OK;
5925 HRESULT WINAPI IWineD3DDeviceImpl_GetFrontBufferData(IWineD3DDevice *iface,UINT iSwapChain, IWineD3DSurface *pDestSurface) {
5926 IWineD3DSwapChain *swapChain;
5927 HRESULT hr;
5928 hr = IWineD3DDeviceImpl_GetSwapChain(iface, iSwapChain, (IWineD3DSwapChain **)&swapChain);
5929 if(hr == WINED3D_OK) {
5930 hr = IWineD3DSwapChain_GetFrontBufferData(swapChain, pDestSurface);
5931 IWineD3DSwapChain_Release(swapChain);
5933 return hr;
5936 HRESULT WINAPI IWineD3DDeviceImpl_ValidateDevice(IWineD3DDevice *iface, DWORD* pNumPasses) {
5937 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5938 /* return a sensible default */
5939 *pNumPasses = 1;
5940 /* TODO: If the window is minimized then validate device should return something other than WINED3D_OK */
5941 FIXME("(%p) : stub\n", This);
5942 return WINED3D_OK;
5945 HRESULT WINAPI IWineD3DDeviceImpl_SetPaletteEntries(IWineD3DDevice *iface, UINT PaletteNumber, CONST PALETTEENTRY* pEntries) {
5946 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5947 int j;
5948 TRACE("(%p) : PaletteNumber %u\n", This, PaletteNumber);
5949 if ( PaletteNumber < 0 || PaletteNumber >= MAX_PALETTES) {
5950 WARN("(%p) : (%u) Out of range 0-%u, returning Invalid Call\n", This, PaletteNumber, MAX_PALETTES);
5951 return WINED3DERR_INVALIDCALL;
5953 for (j = 0; j < 256; ++j) {
5954 This->palettes[PaletteNumber][j].peRed = pEntries[j].peRed;
5955 This->palettes[PaletteNumber][j].peGreen = pEntries[j].peGreen;
5956 This->palettes[PaletteNumber][j].peBlue = pEntries[j].peBlue;
5957 This->palettes[PaletteNumber][j].peFlags = pEntries[j].peFlags;
5959 TRACE("(%p) : returning\n", This);
5960 return WINED3D_OK;
5963 HRESULT WINAPI IWineD3DDeviceImpl_GetPaletteEntries(IWineD3DDevice *iface, UINT PaletteNumber, PALETTEENTRY* pEntries) {
5964 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5965 int j;
5966 TRACE("(%p) : PaletteNumber %u\n", This, PaletteNumber);
5967 if ( PaletteNumber < 0 || PaletteNumber >= MAX_PALETTES) {
5968 WARN("(%p) : (%u) Out of range 0-%u, returning Invalid Call\n", This, PaletteNumber, MAX_PALETTES);
5969 return WINED3DERR_INVALIDCALL;
5971 for (j = 0; j < 256; ++j) {
5972 pEntries[j].peRed = This->palettes[PaletteNumber][j].peRed;
5973 pEntries[j].peGreen = This->palettes[PaletteNumber][j].peGreen;
5974 pEntries[j].peBlue = This->palettes[PaletteNumber][j].peBlue;
5975 pEntries[j].peFlags = This->palettes[PaletteNumber][j].peFlags;
5977 TRACE("(%p) : returning\n", This);
5978 return WINED3D_OK;
5981 HRESULT WINAPI IWineD3DDeviceImpl_SetCurrentTexturePalette(IWineD3DDevice *iface, UINT PaletteNumber) {
5982 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5983 TRACE("(%p) : PaletteNumber %u\n", This, PaletteNumber);
5984 if ( PaletteNumber < 0 || PaletteNumber >= MAX_PALETTES) {
5985 WARN("(%p) : (%u) Out of range 0-%u, returning Invalid Call\n", This, PaletteNumber, MAX_PALETTES);
5986 return WINED3DERR_INVALIDCALL;
5988 /*TODO: stateblocks */
5989 This->currentPalette = PaletteNumber;
5990 TRACE("(%p) : returning\n", This);
5991 return WINED3D_OK;
5994 HRESULT WINAPI IWineD3DDeviceImpl_GetCurrentTexturePalette(IWineD3DDevice *iface, UINT* PaletteNumber) {
5995 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5996 if (PaletteNumber == NULL) {
5997 WARN("(%p) : returning Invalid Call\n", This);
5998 return WINED3DERR_INVALIDCALL;
6000 /*TODO: stateblocks */
6001 *PaletteNumber = This->currentPalette;
6002 TRACE("(%p) : returning %u\n", This, *PaletteNumber);
6003 return WINED3D_OK;
6006 HRESULT WINAPI IWineD3DDeviceImpl_SetSoftwareVertexProcessing(IWineD3DDevice *iface, BOOL bSoftware) {
6007 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
6008 static BOOL showFixmes = TRUE;
6009 if (showFixmes) {
6010 FIXME("(%p) : stub\n", This);
6011 showFixmes = FALSE;
6014 This->softwareVertexProcessing = bSoftware;
6015 return WINED3D_OK;
6019 BOOL WINAPI IWineD3DDeviceImpl_GetSoftwareVertexProcessing(IWineD3DDevice *iface) {
6020 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
6021 static BOOL showFixmes = TRUE;
6022 if (showFixmes) {
6023 FIXME("(%p) : stub\n", This);
6024 showFixmes = FALSE;
6026 return This->softwareVertexProcessing;
6030 HRESULT WINAPI IWineD3DDeviceImpl_GetRasterStatus(IWineD3DDevice *iface, UINT iSwapChain, WINED3DRASTER_STATUS* pRasterStatus) {
6031 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
6032 IWineD3DSwapChain *swapChain;
6033 HRESULT hr;
6035 TRACE("(%p) : SwapChain %d returning %p\n", This, iSwapChain, pRasterStatus);
6037 hr = IWineD3DDeviceImpl_GetSwapChain(iface, iSwapChain, (IWineD3DSwapChain **)&swapChain);
6038 if(hr == WINED3D_OK){
6039 hr = IWineD3DSwapChain_GetRasterStatus(swapChain, pRasterStatus);
6040 IWineD3DSwapChain_Release(swapChain);
6041 }else{
6042 FIXME("(%p) IWineD3DSwapChain_GetRasterStatus returned in error\n", This);
6044 return hr;
6048 HRESULT WINAPI IWineD3DDeviceImpl_SetNPatchMode(IWineD3DDevice *iface, float nSegments) {
6049 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
6050 static BOOL showfixmes = TRUE;
6051 if(nSegments != 0.0f) {
6052 if( showfixmes) {
6053 FIXME("(%p) : stub nSegments(%f)\n", This, nSegments);
6054 showfixmes = FALSE;
6057 return WINED3D_OK;
6060 float WINAPI IWineD3DDeviceImpl_GetNPatchMode(IWineD3DDevice *iface) {
6061 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
6062 static BOOL showfixmes = TRUE;
6063 if( showfixmes) {
6064 FIXME("(%p) : stub returning(%f)\n", This, 0.0f);
6065 showfixmes = FALSE;
6067 return 0.0f;
6070 HRESULT WINAPI IWineD3DDeviceImpl_UpdateSurface(IWineD3DDevice *iface, IWineD3DSurface *pSourceSurface, CONST RECT* pSourceRect, IWineD3DSurface *pDestinationSurface, CONST POINT* pDestPoint) {
6071 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *) iface;
6072 /** TODO: remove casts to IWineD3DSurfaceImpl
6073 * NOTE: move code to surface to accomplish this
6074 ****************************************/
6075 IWineD3DSurfaceImpl *pSrcSurface = (IWineD3DSurfaceImpl *)pSourceSurface;
6076 int srcWidth, srcHeight;
6077 unsigned int srcSurfaceWidth, srcSurfaceHeight, destSurfaceWidth, destSurfaceHeight;
6078 WINED3DFORMAT destFormat, srcFormat;
6079 UINT destSize;
6080 int destLeft, destTop;
6081 WINED3DPOOL srcPool, destPool;
6082 int offset = 0;
6083 int rowoffset = 0; /* how many bytes to add onto the end of a row to wraparound to the beginning of the next */
6084 glDescriptor *glDescription = NULL;
6085 GLenum textureDimensions = GL_TEXTURE_2D;
6086 IWineD3DBaseTexture *baseTexture;
6088 WINED3DSURFACE_DESC winedesc;
6090 TRACE("(%p) : Source (%p) Rect (%p) Destination (%p) Point(%p)\n", This, pSourceSurface, pSourceRect, pDestinationSurface, pDestPoint);
6091 memset(&winedesc, 0, sizeof(winedesc));
6092 winedesc.Width = &srcSurfaceWidth;
6093 winedesc.Height = &srcSurfaceHeight;
6094 winedesc.Pool = &srcPool;
6095 winedesc.Format = &srcFormat;
6097 IWineD3DSurface_GetDesc(pSourceSurface, &winedesc);
6099 winedesc.Width = &destSurfaceWidth;
6100 winedesc.Height = &destSurfaceHeight;
6101 winedesc.Pool = &destPool;
6102 winedesc.Format = &destFormat;
6103 winedesc.Size = &destSize;
6105 IWineD3DSurface_GetDesc(pDestinationSurface, &winedesc);
6107 if(srcPool != WINED3DPOOL_SYSTEMMEM || destPool != WINED3DPOOL_DEFAULT){
6108 WARN("source %p must be SYSTEMMEM and dest %p must be DEFAULT, returning WINED3DERR_INVALIDCALL\n", pSourceSurface, pDestinationSurface);
6109 return WINED3DERR_INVALIDCALL;
6112 if (destFormat == WINED3DFMT_UNKNOWN) {
6113 TRACE("(%p) : Converting destination surface from WINED3DFMT_UNKNOWN to the source format\n", This);
6114 IWineD3DSurface_SetFormat(pDestinationSurface, srcFormat);
6116 /* Get the update surface description */
6117 IWineD3DSurface_GetDesc(pDestinationSurface, &winedesc);
6120 /* Make sure the surface is loaded and up to date */
6121 IWineD3DSurface_PreLoad(pDestinationSurface);
6123 IWineD3DSurface_GetGlDesc(pDestinationSurface, &glDescription);
6125 ENTER_GL();
6127 /* this needs to be done in lines if the sourceRect != the sourceWidth */
6128 srcWidth = pSourceRect ? pSourceRect->right - pSourceRect->left : srcSurfaceWidth;
6129 srcHeight = pSourceRect ? pSourceRect->top - pSourceRect->bottom : srcSurfaceHeight;
6130 destLeft = pDestPoint ? pDestPoint->x : 0;
6131 destTop = pDestPoint ? pDestPoint->y : 0;
6134 /* This function doesn't support compressed textures
6135 the pitch is just bytesPerPixel * width */
6136 if(srcWidth != srcSurfaceWidth || (pSourceRect != NULL && pSourceRect->left != 0) ){
6137 rowoffset = (srcSurfaceWidth - srcWidth) * pSrcSurface->bytesPerPixel;
6138 offset += pSourceRect->left * pSrcSurface->bytesPerPixel;
6139 /* TODO: do we ever get 3bpp?, would a shift and an add be quicker than a mul (well maybe a cycle or two) */
6141 /* TODO DXT formats */
6143 if(pSourceRect != NULL && pSourceRect->top != 0){
6144 offset += pSourceRect->top * srcWidth * pSrcSurface->bytesPerPixel;
6146 TRACE("(%p) glTexSubImage2D, Level %d, left %d, top %d, width %d, height %d , ftm %d, type %d, memory %p\n"
6147 ,This
6148 ,glDescription->level
6149 ,destLeft
6150 ,destTop
6151 ,srcWidth
6152 ,srcHeight
6153 ,glDescription->glFormat
6154 ,glDescription->glType
6155 ,IWineD3DSurface_GetData(pSourceSurface)
6158 /* Sanity check */
6159 if (IWineD3DSurface_GetData(pSourceSurface) == NULL) {
6161 /* need to lock the surface to get the data */
6162 FIXME("Surfaces has no allocated memory, but should be an in memory only surface\n");
6165 /* TODO: Cube and volume support */
6166 if(rowoffset != 0){
6167 /* not a whole row so we have to do it a line at a time */
6168 int j;
6170 /* hopefully using pointer addtion will be quicker than using a point + j * rowoffset */
6171 unsigned char* data =((unsigned char *)IWineD3DSurface_GetData(pSourceSurface)) + offset;
6173 for(j = destTop ; j < (srcHeight + destTop) ; j++){
6175 glTexSubImage2D(glDescription->target
6176 ,glDescription->level
6177 ,destLeft
6179 ,srcWidth
6181 ,glDescription->glFormat
6182 ,glDescription->glType
6183 ,data /* could be quicker using */
6185 data += rowoffset;
6188 } else { /* Full width, so just write out the whole texture */
6190 if (WINED3DFMT_DXT1 == destFormat ||
6191 WINED3DFMT_DXT2 == destFormat ||
6192 WINED3DFMT_DXT3 == destFormat ||
6193 WINED3DFMT_DXT4 == destFormat ||
6194 WINED3DFMT_DXT5 == destFormat) {
6195 if (GL_SUPPORT(EXT_TEXTURE_COMPRESSION_S3TC)) {
6196 if (destSurfaceHeight != srcHeight || destSurfaceWidth != srcWidth) {
6197 /* FIXME: The easy way to do this is lock the destination, and copy the bits accross */
6198 FIXME("Updating part of a compressed texture is not supported at the moment\n");
6199 } if (destFormat != srcFormat) {
6200 FIXME("Updating mixed format compressed texture is not curretly support\n");
6201 } else {
6202 GL_EXTCALL(glCompressedTexImage2DARB)(glDescription->target,
6203 glDescription->level,
6204 glDescription->glFormatInternal,
6205 srcWidth,
6206 srcHeight,
6208 destSize,
6209 IWineD3DSurface_GetData(pSourceSurface));
6211 } else {
6212 FIXME("Attempting to update a DXT compressed texture without hardware support\n");
6216 } else {
6217 if (NP2_REPACK == wined3d_settings.nonpower2_mode) {
6219 /* some applications cannot handle odd pitches returned by soft non-power2, so we have
6220 to repack the data from pow2Width/Height to expected Width,Height, this makes the
6221 data returned by GetData non-power2 width/height with hardware non-power2
6222 pow2Width/height are set to surface width height, repacking isn't needed so it
6223 doesn't matter which function gets called. */
6224 glTexSubImage2D(glDescription->target
6225 ,glDescription->level
6226 ,destLeft
6227 ,destTop
6228 ,srcWidth
6229 ,srcHeight
6230 ,glDescription->glFormat
6231 ,glDescription->glType
6232 ,IWineD3DSurface_GetData(pSourceSurface)
6234 } else {
6236 /* not repacked, the data returned by IWineD3DSurface_GetData is pow2Width x pow2Height */
6237 glTexSubImage2D(glDescription->target
6238 ,glDescription->level
6239 ,destLeft
6240 ,destTop
6241 ,((IWineD3DSurfaceImpl *)pSourceSurface)->pow2Width
6242 ,((IWineD3DSurfaceImpl *)pSourceSurface)->pow2Height
6243 ,glDescription->glFormat
6244 ,glDescription->glType
6245 ,IWineD3DSurface_GetData(pSourceSurface)
6251 checkGLcall("glTexSubImage2D");
6253 /* I only need to look up baseTexture here, so it may be a good idea to hava a GL_TARGET ->
6254 * GL_DIMENSIONS lookup, or maybe store the dimensions on the surface (but that's making the
6255 * surface bigger than it needs to be hmm.. */
6256 if (WINED3D_OK == IWineD3DSurface_GetContainer(pDestinationSurface, &IID_IWineD3DBaseTexture, (void **)&baseTexture)) {
6257 textureDimensions = IWineD3DBaseTexture_GetTextureDimensions(baseTexture);
6258 IWineD3DBaseTexture_Release(baseTexture);
6261 glDisable(textureDimensions); /* This needs to be managed better.... */
6262 LEAVE_GL();
6264 return WINED3D_OK;
6267 /* Used by DirectX 8 */
6268 HRESULT WINAPI IWineD3DDeviceImpl_CopyRects(IWineD3DDevice *iface,
6269 IWineD3DSurface* pSourceSurface, CONST RECT* pSourceRectsArray, UINT cRects,
6270 IWineD3DSurface* pDestinationSurface, CONST POINT* pDestPointsArray) {
6272 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
6273 HRESULT hr = WINED3D_OK;
6274 WINED3DFORMAT srcFormat, destFormat;
6275 UINT srcWidth, destWidth;
6276 UINT srcHeight, destHeight;
6277 UINT srcSize;
6278 WINED3DSURFACE_DESC winedesc;
6280 TRACE("(%p) pSrcSur=%p, pSourceRects=%p, cRects=%d, pDstSur=%p, pDestPtsArr=%p\n", This,
6281 pSourceSurface, pSourceRectsArray, cRects, pDestinationSurface, pDestPointsArray);
6284 /* Check that the source texture is in WINED3DPOOL_SYSTEMMEM and the destination texture is in WINED3DPOOL_DEFAULT */
6285 memset(&winedesc, 0, sizeof(winedesc));
6287 winedesc.Format = &srcFormat;
6288 winedesc.Width = &srcWidth;
6289 winedesc.Height = &srcHeight;
6290 winedesc.Size = &srcSize;
6291 IWineD3DSurface_GetDesc(pSourceSurface, &winedesc);
6293 winedesc.Format = &destFormat;
6294 winedesc.Width = &destWidth;
6295 winedesc.Height = &destHeight;
6296 winedesc.Size = NULL;
6297 IWineD3DSurface_GetDesc(pDestinationSurface, &winedesc);
6299 /* Check that the source and destination formats match */
6300 if (srcFormat != destFormat && WINED3DFMT_UNKNOWN != destFormat) {
6301 WARN("(%p) source %p format must match the dest %p format, returning WINED3DERR_INVALIDCALL\n", This, pSourceSurface, pDestinationSurface);
6302 return WINED3DERR_INVALIDCALL;
6303 } else if (WINED3DFMT_UNKNOWN == destFormat) {
6304 TRACE("(%p) : Converting destination surface from WINED3DFMT_UNKNOWN to the source format\n", This);
6305 IWineD3DSurface_SetFormat(pDestinationSurface, srcFormat);
6306 destFormat = srcFormat;
6309 /* Quick if complete copy ... */
6310 if (cRects == 0 && pSourceRectsArray == NULL && pDestPointsArray == NULL) {
6312 if (srcWidth == destWidth && srcHeight == destHeight) {
6313 WINED3DLOCKED_RECT lrSrc;
6314 WINED3DLOCKED_RECT lrDst;
6315 IWineD3DSurface_LockRect(pSourceSurface, &lrSrc, NULL, WINED3DLOCK_READONLY);
6316 IWineD3DSurface_LockRect(pDestinationSurface, &lrDst, NULL, 0L);
6317 TRACE("Locked src and dst, Direct copy as surfaces are equal, w=%d, h=%d\n", srcWidth, srcHeight);
6319 memcpy(lrDst.pBits, lrSrc.pBits, srcSize);
6321 IWineD3DSurface_UnlockRect(pSourceSurface);
6322 IWineD3DSurface_UnlockRect(pDestinationSurface);
6323 TRACE("Unlocked src and dst\n");
6325 } else {
6327 FIXME("Wanted to copy all surfaces but size not compatible, returning WINED3DERR_INVALIDCALL\n");
6328 hr = WINED3DERR_INVALIDCALL;
6331 } else {
6333 if (NULL != pSourceRectsArray && NULL != pDestPointsArray) {
6335 int bytesPerPixel = ((IWineD3DSurfaceImpl *) pSourceSurface)->bytesPerPixel;
6336 unsigned int i;
6338 /* Copy rect by rect */
6339 for (i = 0; i < cRects; ++i) {
6340 CONST RECT* r = &pSourceRectsArray[i];
6341 CONST POINT* p = &pDestPointsArray[i];
6342 int copyperline;
6343 int j;
6344 WINED3DLOCKED_RECT lrSrc;
6345 WINED3DLOCKED_RECT lrDst;
6346 RECT dest_rect;
6348 TRACE("Copying rect %d (%ld,%ld),(%ld,%ld) -> (%ld,%ld)\n", i, r->left, r->top, r->right, r->bottom, p->x, p->y);
6349 if (srcFormat == WINED3DFMT_DXT1) {
6350 copyperline = ((r->right - r->left) * bytesPerPixel) / 2; /* DXT1 is half byte per pixel */
6351 } else {
6352 copyperline = ((r->right - r->left) * bytesPerPixel);
6355 IWineD3DSurface_LockRect(pSourceSurface, &lrSrc, r, WINED3DLOCK_READONLY);
6356 dest_rect.left = p->x;
6357 dest_rect.top = p->y;
6358 dest_rect.right = p->x + (r->right - r->left);
6359 dest_rect.bottom= p->y + (r->bottom - r->top);
6360 IWineD3DSurface_LockRect(pDestinationSurface, &lrDst, &dest_rect, 0L);
6361 TRACE("Locked src and dst\n");
6363 /* Find where to start */
6364 for (j = 0; j < (r->bottom - r->top - 1); ++j) {
6365 memcpy((char*) lrDst.pBits + (j * lrDst.Pitch), (char*) lrSrc.pBits + (j * lrSrc.Pitch), copyperline);
6367 IWineD3DSurface_UnlockRect(pSourceSurface);
6368 IWineD3DSurface_UnlockRect(pDestinationSurface);
6369 TRACE("Unlocked src and dst\n");
6371 } else {
6372 FIXME("Wanted to copy partial surfaces not implemented, returning WINED3DERR_INVALIDCALL\n");
6373 hr = WINED3DERR_INVALIDCALL;
6377 return hr;
6380 /* Implementation details at http://developer.nvidia.com/attach/6494
6382 http://oss.sgi.com/projects/ogl-sample/registry/NV/evaluators.txt
6383 hmm.. no longer supported use
6384 OpenGL evaluators or tessellate surfaces within your application.
6387 /* http://msdn.microsoft.com/library/default.asp?url=/library/en-us/directx9_c/directx/graphics/reference/d3d/interfaces/idirect3ddevice9/DrawRectPatch.asp */
6388 HRESULT WINAPI IWineD3DDeviceImpl_DrawRectPatch(IWineD3DDevice *iface, UINT Handle, CONST float* pNumSegs, CONST WINED3DRECTPATCH_INFO* pRectPatchInfo) {
6389 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
6390 TRACE("(%p) Handle(%d) noSegs(%p) rectpatch(%p)\n", This, Handle, pNumSegs, pRectPatchInfo);
6391 FIXME("(%p) : Stub\n", This);
6392 return WINED3D_OK;
6396 /* http://msdn.microsoft.com/library/default.asp?url=/library/en-us/directx9_c/directx/graphics/reference/d3d/interfaces/idirect3ddevice9/DrawTriPatch.asp */
6397 HRESULT WINAPI IWineD3DDeviceImpl_DrawTriPatch(IWineD3DDevice *iface, UINT Handle, CONST float* pNumSegs, CONST WINED3DTRIPATCH_INFO* pTriPatchInfo) {
6398 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
6399 TRACE("(%p) Handle(%d) noSegs(%p) tripatch(%p)\n", This, Handle, pNumSegs, pTriPatchInfo);
6400 FIXME("(%p) : Stub\n", This);
6401 return WINED3D_OK;
6404 HRESULT WINAPI IWineD3DDeviceImpl_DeletePatch(IWineD3DDevice *iface, UINT Handle) {
6405 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
6406 TRACE("(%p) Handle(%d)\n", This, Handle);
6407 FIXME("(%p) : Stub\n", This);
6408 return WINED3D_OK;
6411 HRESULT WINAPI IWineD3DDeviceImpl_ColorFill(IWineD3DDevice *iface, IWineD3DSurface *pSurface, CONST D3DRECT* pRect, D3DCOLOR color) {
6412 /* I couldn't find a 'really' quick way of doing this in openGl so here goes
6413 fill a surface with a block of color! */
6414 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
6415 /* TODO: get rid of the use of IWineD3DSurfaceImpl, move code into surface.c */
6416 IWineD3DSurfaceImpl *surface = (IWineD3DSurfaceImpl *)pSurface;
6417 IWineD3DSwapChainImpl *container = NULL;
6418 BOOL isRenderTarget = FALSE;
6419 unsigned int width, height;
6420 unsigned int top, left;
6421 unsigned int u, v;
6422 DWORD *data;
6423 TRACE("(%p) Colour fill Surface: %p rect: %p color: %ld\n", This, pSurface, pRect, color);
6425 if (surface->resource.pool != WINED3DPOOL_DEFAULT && surface->resource.pool != WINED3DPOOL_SYSTEMMEM) {
6426 FIXME("call to colorfill with non WINED3DPOOL_DEFAULT or WINED3DPOOL_SYSTEMMEM surface\n");
6427 return WINED3DERR_INVALIDCALL;
6430 /* TODO: get rid of IWineD3DSwapChainImpl reference, a 'context' manager may help with this */
6431 if (WINED3D_OK == IWineD3DSurface_GetContainer(pSurface, &IID_IWineD3DSwapChain, (void **)&container) || pSurface == This->renderTarget) {
6432 if (WINED3DUSAGE_RENDERTARGET & surface->resource.usage) {
6433 /* TODO: make sure we set everything back to the way it was, and context management!
6434 glGetIntegerv(GL_READ_BUFFER, &prev_read);
6435 vcheckGLcall("glIntegerv");
6436 glGetIntegerv(GL_PACK_SWAP_BYTES, &prev_store);
6437 vcheckGLcall("glIntegerv");
6439 TRACE("Color fill to render targets may cause some graphics issues\n");
6440 if (pSurface == container->frontBuffer) {
6441 glDrawBuffer(GL_FRONT);
6442 } else {
6443 glDrawBuffer(GL_BACK);
6445 } else {
6446 if (WINED3DUSAGE_DEPTHSTENCIL & surface->resource.usage) {
6447 FIXME("colouring of depth_stencil? %p buffers is not yet supported? %ld\n", surface, surface->resource.usage);
6448 } else {
6449 FIXME("(%p) : Regression %ld %p %p\n", This, surface->resource.usage, pSurface, This->renderTarget);
6451 if (container != NULL) {
6452 IWineD3DSwapChain_Release((IWineD3DSwapChain *)container);
6454 /* we can use GL_STENCIL_INDEX etc...*/
6455 return WINED3D_OK;
6457 if (container != NULL) {
6458 IWineD3DSwapChain_Release((IWineD3DSwapChain *)container);
6460 isRenderTarget = TRUE;
6462 /* TODO: drawing to GL_FRONT and GL_BACK */
6463 /* TODO: see if things can be speeded up by using the correct
6464 * colour model of the target texture from the start (16 bit graphics on 32 X are slow anyway!) */
6465 if (pRect == NULL) {
6466 top = 0;
6467 left = 0;
6468 width = surface->currentDesc.Width;
6469 height = surface->currentDesc.Height;
6470 } else {
6471 left = pRect->x1;
6472 top = pRect->y1;
6473 width = pRect->x2 - left;
6474 height = pRect->y2 - top;
6477 data = HeapAlloc(GetProcessHeap(), 0, 4 * width);
6478 /* Create a 'line' of color color, in the correct format for the surface */
6479 for (u = 0 ; u < width ; u ++) {
6480 data[u] = color;
6483 ENTER_GL();
6484 if (isRenderTarget == FALSE) {
6485 glDescriptor *glDesc;
6486 IWineD3DSurface_PreLoad(pSurface);
6488 /* draw a block of the coloured line on the sufrace */
6489 IWineD3DSurface_GetGlDesc(pSurface, &glDesc);
6490 for (v = 0 ; v< height;v++) {
6491 glTexSubImage2D(glDesc->target
6492 ,glDesc->level /* level */
6493 ,left
6494 ,top + v
6495 ,width
6496 ,1 /* height */
6497 ,GL_RGBA
6498 ,GL_UNSIGNED_BYTE
6499 ,data
6502 checkGLcall("glTexSubImage2D");
6503 /* clean up */
6504 glDisable(glDesc->target);
6505 } else {
6506 /** FIXME: Using GLClear may be faster **/
6507 glRasterPos2i(left, top);
6508 glPixelZoom((float)width ,(float)height);
6509 glDrawPixels(1, 1, GL_RGBA, GL_UNSIGNED_BYTE, data);
6510 checkGLcall("glDrawPixels");
6512 HeapFree(GetProcessHeap(), 0, data);
6513 LEAVE_GL();
6514 return WINED3D_OK;
6518 /* rendertarget and deptth stencil functions */
6519 HRESULT WINAPI IWineD3DDeviceImpl_GetRenderTarget(IWineD3DDevice* iface,DWORD RenderTargetIndex, IWineD3DSurface **ppRenderTarget) {
6520 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
6522 /* FIXME: Implelent RenderTargetIndex >0 */
6523 if(RenderTargetIndex > 0)
6524 FIXME("(%p) : RenderTargetIndex %ld >0 not currently supported\n", This, RenderTargetIndex);
6526 *ppRenderTarget = This->renderTarget;
6527 TRACE("(%p) : RenderTarget %ld Index returning %p\n", This, RenderTargetIndex, *ppRenderTarget);
6528 /* Note inc ref on returned surface */
6529 if(*ppRenderTarget != NULL)
6530 IWineD3DSurface_AddRef(*ppRenderTarget);
6531 return WINED3D_OK;
6534 HRESULT WINAPI IWineD3DDeviceImpl_SetFrontBackBuffers(IWineD3DDevice *iface, IWineD3DSurface *Front, IWineD3DSurface *Back) {
6535 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
6536 IWineD3DSurfaceImpl *FrontImpl = (IWineD3DSurfaceImpl *) Front;
6537 IWineD3DSurfaceImpl *BackImpl = (IWineD3DSurfaceImpl *) Back;
6538 IWineD3DSwapChainImpl *Swapchain;
6539 HRESULT hr;
6541 TRACE("(%p)->(%p,%p)\n", This, FrontImpl, BackImpl);
6543 hr = IWineD3DDevice_GetSwapChain(iface, 0, (IWineD3DSwapChain **) &Swapchain);
6544 if(hr != WINED3D_OK) {
6545 ERR("Can't get the swapchain\n");
6546 return hr;
6549 /* Make sure to release the swapchain */
6550 IWineD3DSwapChain_Release((IWineD3DSwapChain *) Swapchain);
6552 if(FrontImpl && !(FrontImpl->resource.usage & WINED3DUSAGE_RENDERTARGET) ) {
6553 ERR("Trying to set a front buffer which doesn't have WINED3DUSAGE_RENDERTARGET usage\n");
6554 return WINED3DERR_INVALIDCALL;
6556 else if(BackImpl && !(BackImpl->resource.usage & WINED3DUSAGE_RENDERTARGET)) {
6557 ERR("Trying to set a back buffer which doesn't have WINED3DUSAGE_RENDERTARGET usage\n");
6558 return WINED3DERR_INVALIDCALL;
6561 if(Swapchain->frontBuffer != Front) {
6562 TRACE("Changing the front buffer from %p to %p\n", Swapchain->frontBuffer, Front);
6564 if(Swapchain->frontBuffer)
6565 IWineD3DSurface_SetContainer(Swapchain->frontBuffer, NULL);
6566 Swapchain->frontBuffer = Front;
6568 if(Swapchain->frontBuffer) {
6569 IWineD3DSurface_SetContainer(Swapchain->frontBuffer, (IWineD3DBase *) Swapchain);
6572 if(Swapchain->backBuffer != Back) {
6573 TRACE("Changing the back buffer from %p to %p\n", Swapchain->backBuffer, Back);
6574 ENTER_GL();
6575 if(!Swapchain->backBuffer) {
6576 /* GL was told to draw to the front buffer at creation,
6577 * undo that
6579 glDrawBuffer(GL_BACK);
6580 checkGLcall("glDrawBuffer(GL_BACK)");
6581 } else if (!Back) {
6582 /* That makes problems - disable for now */
6583 /* glDrawBuffer(GL_FRONT); */
6584 checkGLcall("glDrawBuffer(GL_FRONT)");
6586 LEAVE_GL();
6588 if(Swapchain->backBuffer)
6589 IWineD3DSurface_SetContainer(Swapchain->backBuffer, NULL);
6590 Swapchain->backBuffer = Back;
6592 if(Swapchain->backBuffer) {
6593 IWineD3DSurface_SetContainer(Swapchain->backBuffer, (IWineD3DBase *) Swapchain);
6598 return WINED3D_OK;
6601 HRESULT WINAPI IWineD3DDeviceImpl_GetDepthStencilSurface(IWineD3DDevice* iface, IWineD3DSurface **ppZStencilSurface) {
6602 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
6603 *ppZStencilSurface = This->depthStencilBuffer;
6604 TRACE("(%p) : zStencilSurface returning %p\n", This, *ppZStencilSurface);
6606 if(*ppZStencilSurface != NULL) {
6607 /* Note inc ref on returned surface */
6608 IWineD3DSurface_AddRef(*ppZStencilSurface);
6610 return WINED3D_OK;
6613 /* internal static helper functions */
6614 HRESULT WINAPI static IWineD3DDeviceImpl_ActiveRender(IWineD3DDevice* iface,
6615 IWineD3DSurface *RenderSurface);
6617 HRESULT WINAPI IWineD3DDeviceImpl_SetRenderTarget(IWineD3DDevice *iface, DWORD RenderTargetIndex, IWineD3DSurface *pRenderTarget) {
6618 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
6619 HRESULT hr = WINED3D_OK;
6620 WINED3DVIEWPORT viewport;
6622 TRACE("(%p) Swapping rendertarget\n",This);
6623 if (RenderTargetIndex > 0) {
6624 FIXME("(%p) Render targets other than the first are not supported\n",This);
6625 RenderTargetIndex = 0;
6628 /* MSDN says that null disables the render target
6629 but a device must always be associated with a render target
6630 nope MSDN says that we return invalid call to a null rendertarget with an index of 0
6632 see http://msdn.microsoft.com/library/default.asp?url=/library/en-us/directx9_c/directx/graphics/programmingguide/AdvancedTopics/PixelPipe/MultipleRenderTarget.asp
6633 for more details
6635 if (RenderTargetIndex == 0 && pRenderTarget == NULL) {
6636 FIXME("Trying to set render target 0 to NULL\n");
6637 return WINED3DERR_INVALIDCALL;
6639 /* TODO: replace Impl* usage with interface usage */
6640 if (!((IWineD3DSurfaceImpl *)pRenderTarget)->resource.usage & WINED3DUSAGE_RENDERTARGET) {
6641 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);
6642 return WINED3DERR_INVALIDCALL;
6644 /** TODO: check that the depth stencil format matches the render target, this is only done in debug
6645 * builds, but I think wine counts as a 'debug' build for now.
6646 ******************************/
6647 /* If we are trying to set what we already have, don't bother */
6648 if (pRenderTarget == This->renderTarget) {
6649 TRACE("Trying to do a NOP SetRenderTarget operation\n");
6650 } else {
6651 /* Otherwise, set the render target up */
6653 if (FALSE == This->sceneEnded) {
6654 IWineD3DDevice_EndScene(iface);
6656 TRACE("clearing renderer\n");
6657 /* IWineD3DDeviceImpl_CleanRender(iface); */
6658 /* OpenGL doesn't support 'sharing' of the stencilBuffer so we may incure an extra memory overhead
6659 depending on the renter target implementation being used.
6660 A shared context implementation will share all buffers between all rendertargets (including swapchains),
6661 implementations that use separate pbuffers for different swapchains or rendertargets will have to duplicate the
6662 stencil buffer and incure an extra memory overhead */
6663 hr = IWineD3DDeviceImpl_ActiveRender(iface, pRenderTarget);
6666 if (SUCCEEDED(hr)) {
6667 /* Finally, reset the viewport as the MSDN states. */
6668 /* TODO: Replace impl usage */
6669 viewport.Height = ((IWineD3DSurfaceImpl *)This->renderTarget)->currentDesc.Height;
6670 viewport.Width = ((IWineD3DSurfaceImpl *)This->renderTarget)->currentDesc.Width;
6671 viewport.X = 0;
6672 viewport.Y = 0;
6673 viewport.MaxZ = 1.0f;
6674 viewport.MinZ = 0.0f;
6675 IWineD3DDeviceImpl_SetViewport(iface, &viewport);
6676 } else {
6677 FIXME("Unknown error setting the render target\n");
6679 This->sceneEnded = FALSE;
6680 return hr;
6683 HRESULT WINAPI IWineD3DDeviceImpl_SetDepthStencilSurface(IWineD3DDevice *iface, IWineD3DSurface *pNewZStencil) {
6684 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
6685 HRESULT hr = WINED3D_OK;
6686 IWineD3DSurface *tmp;
6688 TRACE("(%p) Swapping z-buffer\n",This);
6690 if (pNewZStencil == This->stencilBufferTarget) {
6691 TRACE("Trying to do a NOP SetRenderTarget operation\n");
6692 } else {
6693 /** OpenGL doesn't support 'sharing' of the stencilBuffer so we may incure an extra memory overhead
6694 * depending on the renter target implementation being used.
6695 * A shared context implementation will share all buffers between all rendertargets (including swapchains),
6696 * implementations that use separate pbuffers for different swapchains or rendertargets will have to duplicate the
6697 * stencil buffer and incure an extra memory overhead
6698 ******************************************************/
6701 tmp = This->stencilBufferTarget;
6702 This->stencilBufferTarget = pNewZStencil;
6703 /* should we be calling the parent or the wined3d surface? */
6704 if (NULL != This->stencilBufferTarget) IWineD3DSurface_AddRef(This->stencilBufferTarget);
6705 if (NULL != tmp) IWineD3DSurface_Release(tmp);
6706 hr = WINED3D_OK;
6707 /** TODO: glEnable/glDisable on depth/stencil depending on
6708 * pNewZStencil is NULL and the depth/stencil is enabled in d3d
6709 **********************************************************/
6712 return hr;
6716 #ifdef GL_VERSION_1_3
6717 /* Internal functions not in DirectX */
6718 /** TODO: move this off to the opengl context manager
6719 *(the swapchain doesn't need to know anything about offscreen rendering!)
6720 ****************************************************/
6722 HRESULT WINAPI IWineD3DDeviceImpl_CleanRender(IWineD3DDevice* iface, IWineD3DSwapChainImpl *swapchain)
6724 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
6726 TRACE("(%p), %p\n", This, swapchain);
6728 if (swapchain->win != swapchain->drawable) {
6729 /* Set everything back the way it ws */
6730 swapchain->render_ctx = swapchain->glCtx;
6731 swapchain->drawable = swapchain->win;
6733 return WINED3D_OK;
6736 /* TODO: move this off into a context manager so that GLX_ATI_render_texture and other types of surface can be used. */
6737 HRESULT WINAPI IWineD3DDeviceImpl_FindGLContext(IWineD3DDevice *iface, IWineD3DSurface *pSurface, glContext **context) {
6738 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
6739 int i;
6740 unsigned int width;
6741 unsigned int height;
6742 WINED3DFORMAT format;
6743 WINED3DSURFACE_DESC surfaceDesc;
6744 memset(&surfaceDesc, 0, sizeof(surfaceDesc));
6745 surfaceDesc.Width = &width;
6746 surfaceDesc.Height = &height;
6747 surfaceDesc.Format = &format;
6748 IWineD3DSurface_GetDesc(pSurface, &surfaceDesc);
6749 *context = NULL;
6750 /* I need a get width/height function (and should do something with the format) */
6751 for (i = 0; i < CONTEXT_CACHE; ++i) {
6752 /** NOTE: the contextCache[i].pSurface == pSurface check ceates onepbuffer per surface
6753 ATI cards don't destroy pbuffers, but as soon as resource releasing callbacks are inplace
6754 the pSurface can be set to 0 allowing it to be reused from cache **/
6755 if (This->contextCache[i].Width == width && This->contextCache[i].Height == height
6756 && (pbuffer_per_surface == FALSE || This->contextCache[i].pSurface == pSurface || This->contextCache[i].pSurface == NULL)) {
6757 *context = &This->contextCache[i];
6758 break;
6760 if (This->contextCache[i].Width == 0) {
6761 This->contextCache[i].pSurface = pSurface;
6762 This->contextCache[i].Width = width;
6763 This->contextCache[i].Height = height;
6764 *context = &This->contextCache[i];
6765 break;
6768 if (i == CONTEXT_CACHE) {
6769 int minUsage = 0x7FFFFFFF; /* MAX_INT */
6770 glContext *dropContext = 0;
6771 for (i = 0; i < CONTEXT_CACHE; i++) {
6772 if (This->contextCache[i].usedcount < minUsage) {
6773 dropContext = &This->contextCache[i];
6774 minUsage = This->contextCache[i].usedcount;
6777 /* clean up the context (this doesn't work for ATI at the moment */
6778 #if 0
6779 glXDestroyContext(swapchain->display, dropContext->context);
6780 glXDestroyPbuffer(swapchain->display, dropContext->drawable);
6781 #endif
6782 FIXME("Leak\n");
6783 dropContext->Width = 0;
6784 dropContext->pSurface = pSurface;
6785 *context = dropContext;
6786 } else {
6787 if (++This->contextCache[i].usedcount == 0x7FFFFFFF /* MAX_INT */ - 1 ) {
6788 for (i = 0; i < CONTEXT_CACHE; i++) {
6789 This->contextCache[i].usedcount = max(0, This->contextCache[i].usedcount - (0x7FFFFFFF /* MAX_INT */ >> 1));
6793 if (*context != NULL)
6794 return WINED3D_OK;
6795 else
6796 return E_OUTOFMEMORY;
6798 #endif
6800 /** FIXME: This is currently used called whenever SetRenderTarget or SetStencilBuffer are called
6801 * the functionality needs splitting up so that we don't do more than we should do.
6802 * this only seems to impact performance a little.
6803 ******************************/
6804 HRESULT WINAPI IWineD3DDeviceImpl_ActiveRender(IWineD3DDevice* iface,
6805 IWineD3DSurface *RenderSurface) {
6806 HRESULT ret = WINED3DERR_INVALIDCALL;
6809 * Currently only active for GLX >= 1.3
6810 * for others versions we'll have to use GLXPixmaps
6812 * normally we must test GLX_VERSION_1_3 but nvidia headers are not correct
6813 * as they implement GLX 1.3 but only define GLX_VERSION_1_2
6814 * so only check OpenGL version
6815 * ..........................
6816 * I don't believe that it is a problem with NVidia headers,
6817 * XFree only supports GLX1.2, nVidia (and ATI to some extent) provide 1.3 functions
6818 * in GLX 1.2, there is no mention of the correct way to tell if the extensions are provided.
6819 * ATI Note:
6820 * Your application will report GLX version 1.2 on glXQueryVersion.
6821 * However, it is safe to call the GLX 1.3 functions as described below.
6823 #if defined(GL_VERSION_1_3)
6825 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
6826 IWineD3DSurface *StencilSurface = This->stencilBufferTarget;
6827 IWineD3DSurface *tmp;
6828 /** TODO: we only need to look up the configuration !IF! we are setting the target to a texture **/
6829 GLXFBConfig* cfgs = NULL;
6830 int nCfgs = 0;
6831 int attribs[256];
6832 int nAttribs = 0;
6833 IWineD3DSwapChain *currentSwapchain;
6834 IWineD3DSwapChainImpl *swapchain;
6835 /** TODO: get rid of Impl usage we should always create a zbuffer/stencil with our contexts if possible,
6836 * but switch them off if the StencilSurface is set to NULL
6837 ** *********************************************************/
6838 D3DFORMAT BackBufferFormat = ((IWineD3DSurfaceImpl *) RenderSurface)->resource.format;
6839 D3DFORMAT StencilBufferFormat = (NULL != StencilSurface) ? ((IWineD3DSurfaceImpl *) StencilSurface)->resource.format : 0;
6841 /**TODO:
6842 if StencilSurface == NULL && zBufferTarget != NULL then switch the zbuffer off,
6843 it StencilSurface != NULL && zBufferTarget == NULL switch it on
6846 #define PUSH1(att) attribs[nAttribs++] = (att);
6847 #define PUSH2(att,value) attribs[nAttribs++] = (att); attribs[nAttribs++] = (value);
6849 /* PUSH2(GLX_BIND_TO_TEXTURE_RGBA_ATI, True); examples of this are few and far between (but I've got a nice working one!)*/
6851 /** TODO: remove the reff to Impl (context manager should fix this!) **/
6852 IWineD3DSwapChainImpl *impSwapChain;
6853 IWineD3DDevice_GetSwapChain(iface, 0, (IWineD3DSwapChain **)&impSwapChain);
6854 if (NULL == impSwapChain) { /* NOTE: This should NEVER fail */
6855 ERR("(%p) Failed to get a the implicit swapchain\n", iface);
6858 ENTER_GL();
6860 PUSH2(GLX_DRAWABLE_TYPE, GLX_PBUFFER_BIT);
6861 PUSH2(GLX_X_RENDERABLE, TRUE);
6862 PUSH2(GLX_DOUBLEBUFFER, TRUE);
6863 TRACE("calling makeglcfg\n");
6864 D3DFmtMakeGlCfg(BackBufferFormat, StencilBufferFormat, attribs, &nAttribs, FALSE /* alternate */);
6865 PUSH1(None);
6867 TRACE("calling chooseFGConfig\n");
6868 cfgs = glXChooseFBConfig(impSwapChain->display, DefaultScreen(impSwapChain->display),
6869 attribs, &nCfgs);
6871 if (!cfgs) { /* OK we didn't find the exact config, so use any reasonable match */
6872 /* TODO: fill in the 'requested' and 'current' depths, also make sure that's
6873 why we failed and only show this message once! */
6874 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"); /**/
6875 nAttribs = 0;
6876 PUSH2(GLX_DRAWABLE_TYPE, GLX_PBUFFER_BIT | GLX_WINDOW_BIT);
6877 /* PUSH2(GLX_X_RENDERABLE, TRUE); */
6878 PUSH2(GLX_RENDER_TYPE, GLX_RGBA_BIT);
6879 PUSH2(GLX_DOUBLEBUFFER, FALSE);
6880 TRACE("calling makeglcfg\n");
6881 D3DFmtMakeGlCfg(BackBufferFormat, StencilBufferFormat, attribs, &nAttribs, TRUE /* alternate */);
6882 PUSH1(None);
6883 cfgs = glXChooseFBConfig(impSwapChain->display, DefaultScreen(impSwapChain->display),
6884 attribs, &nCfgs);
6887 if (NULL != cfgs) {
6888 #ifdef EXTRA_TRACES
6889 int i;
6890 for (i = 0; i < nCfgs; ++i) {
6891 TRACE("for (%u,%s)/(%u,%s) found config[%d]@%p\n", BackBufferFormat,
6892 debug_d3dformat(BackBufferFormat), StencilBufferFormat,
6893 debug_d3dformat(StencilBufferFormat), i, cfgs[i]);
6896 if (NULL != This->renderTarget) {
6897 glFlush();
6898 vcheckGLcall("glFlush");
6899 /** This is only useful if the old render target was a swapchain,
6900 * we need to supercede this with a function that displays
6901 * the current buffer on the screen. This is easy to do in glx1.3 but
6902 * we need to do copy-write pixels in glx 1.2.
6903 ************************************************/
6904 glXSwapBuffers(impSwapChain->display, impSwapChain->drawable);
6906 printf("Hit Enter to get next frame ...\n");
6907 getchar();
6909 #endif
6912 if (IWineD3DSurface_GetContainer(This->renderTarget, &IID_IWineD3DSwapChain, (void **)&currentSwapchain) != WINED3D_OK) {
6913 /* the selected render target doesn't belong to a swapchain, so use the devices implicit swapchain */
6914 IWineD3DDevice_GetSwapChain(iface, 0, &currentSwapchain);
6918 * TODO: remove the use of IWineD3DSwapChainImpl, a context manager will help since it will replace the
6919 * renderTarget = swapchain->backBuffer bit and anything to do with *glContexts
6920 **********************************************************************/
6921 if (IWineD3DSurface_GetContainer(RenderSurface, &IID_IWineD3DSwapChain, (void **)&swapchain) == WINED3D_OK) {
6922 /* We also need to make sure that the lights &co are also in the context of the swapchains */
6923 /* FIXME: If the render target gets sent to the frontBuffer should be be presenting it raw? */
6924 TRACE("making swapchain active\n");
6925 if (RenderSurface != This->renderTarget) {
6926 if (RenderSurface == swapchain->backBuffer) {
6927 } else {
6928 /* This could be flagged so that some operations work directly with the front buffer */
6929 FIXME("Attempting to set the renderTarget to the frontBuffer\n");
6931 if (glXMakeCurrent(swapchain->display, swapchain->win, swapchain->glCtx)
6932 == False) {
6933 TRACE("Error in setting current context: context %p drawable %ld !\n",
6934 impSwapChain->glCtx, impSwapChain->win);
6937 IWineD3DDeviceImpl_CleanRender(iface, (IWineD3DSwapChainImpl *)currentSwapchain);
6939 checkGLcall("glXMakeContextCurrent");
6941 IWineD3DSwapChain_Release((IWineD3DSwapChain *)swapchain);
6943 else if (pbuffer_support && cfgs != NULL /* && some test to make sure that opengl supports pbuffers */) {
6945 /** ********************************************************************
6946 * This is a quickly hacked out implementation of offscreen textures.
6947 * It will work in most cases but there may be problems if the client
6948 * modifies the texture directly, or expects the contents of the rendertarget
6949 * to be persistent.
6951 * There are some real speed vs compatibility issues here:
6952 * we should really use a new context for every texture, but that eats ram.
6953 * we should also be restoring the texture to the pbuffer but that eats CPU
6954 * we can also 'reuse' the current pbuffer if the size is larger than the requested buffer,
6955 * but if this means reusing the display backbuffer then we need to make sure that
6956 * states are correctly preserved.
6957 * In many cases I would expect that we can 'skip' some functions, such as preserving states,
6958 * and gain a good performance increase at the cost of compatibility.
6959 * I would suggest that, when this is the case, a user configurable flag be made
6960 * available, allowing the user to choose the best emulated experience for them.
6961 *********************************************************************/
6963 XVisualInfo *visinfo;
6964 glContext *newContext;
6966 /* Here were using a shared context model */
6967 if (WINED3D_OK != IWineD3DDeviceImpl_FindGLContext(iface, RenderSurface, &newContext)) {
6968 FIXME("(%p) : Failed to find a context for surface %p\n", iface, RenderSurface);
6971 /* If the context doesn't exist then create a new one */
6972 /* TODO: This should really be part of findGlContext */
6973 if (NULL == newContext->context) {
6975 TRACE("making new buffer\n");
6976 nAttribs = 0;
6977 PUSH2(GLX_PBUFFER_WIDTH, newContext->Width);
6978 PUSH2(GLX_PBUFFER_HEIGHT, newContext->Height);
6979 PUSH1(None);
6981 newContext->drawable = glXCreatePbuffer(impSwapChain->display, cfgs[0], attribs);
6983 /** ****************************************
6984 *GLX1.3 isn't supported by XFree 'yet' until that point ATI emulates pBuffers
6985 *they note:
6986 * In future releases, we may provide the calls glXCreateNewContext,
6987 * glXQueryDrawable and glXMakeContextCurrent.
6988 * so until then we have to use glXGetVisualFromFBConfig &co..
6989 ********************************************/
6992 visinfo = glXGetVisualFromFBConfig(impSwapChain->display, cfgs[0]);
6993 if (!visinfo) {
6994 ERR("Error: couldn't get an RGBA, double-buffered visual\n");
6995 } else {
6996 newContext->context = glXCreateContext(impSwapChain->display, visinfo, impSwapChain->glCtx, GL_TRUE);
6997 XFree(visinfo);
7000 if (NULL == newContext || NULL == newContext->context) {
7001 ERR("(%p) : Failed to find a context for surface %p\n", iface, RenderSurface);
7002 } else {
7003 /* Debug logging, (this function leaks), change to a TRACE when the leak is plugged */
7004 if (glXMakeCurrent(impSwapChain->display, newContext->drawable, newContext->context) == False) {
7005 TRACE("Error in setting current context: context %p drawable %ld\n", newContext->context, newContext->drawable);
7008 /* Clean up the old context */
7009 IWineD3DDeviceImpl_CleanRender(iface, (IWineD3DSwapChainImpl *)currentSwapchain);
7010 /* Set the current context of the swapchain to the new context */
7011 impSwapChain->drawable = newContext->drawable;
7012 impSwapChain->render_ctx = newContext->context;
7016 #if 1 /* Apply the stateblock to the new context
7017 FIXME: This is a bit of a hack, each context should know it's own state,
7018 the directX current directX state should then be applied to the context */
7020 BOOL oldRecording;
7021 IWineD3DStateBlockImpl *oldUpdateStateBlock;
7022 oldUpdateStateBlock = This->updateStateBlock;
7023 oldRecording= This->isRecordingState;
7024 This->isRecordingState = FALSE;
7025 This->updateStateBlock = This->stateBlock;
7026 IWineD3DStateBlock_Apply((IWineD3DStateBlock *)This->stateBlock);
7028 This->isRecordingState = oldRecording;
7029 This->updateStateBlock = oldUpdateStateBlock;
7031 #endif
7034 /* clean up the current rendertargets swapchain (if it belonged to one) */
7035 if (currentSwapchain != NULL) {
7036 IWineD3DSwapChain_Release((IWineD3DSwapChain *)currentSwapchain);
7039 /* Were done with the opengl context management, setup the rendertargets */
7041 tmp = This->renderTarget;
7042 This->renderTarget = RenderSurface;
7043 IWineD3DSurface_AddRef(This->renderTarget);
7044 IWineD3DSurface_Release(tmp);
7049 DWORD value;
7050 /* The surface must be rendered upside down to cancel the flip produce by glCopyTexImage */
7051 /* Check that the container is not a swapchain member */
7053 IWineD3DSwapChain *tmpSwapChain;
7054 if (WINED3D_OK != IWineD3DSurface_GetContainer(This->renderTarget, &IID_IWineD3DSwapChain, (void **)&tmpSwapChain)) {
7055 This->renderUpsideDown = TRUE;
7056 }else{
7057 This->renderUpsideDown = FALSE;
7058 IWineD3DSwapChain_Release(tmpSwapChain);
7060 /* Force updating the cull mode */
7061 TRACE("setting render state\n");
7062 IWineD3DDevice_GetRenderState(iface, WINED3DRS_CULLMODE, &value);
7063 IWineD3DDevice_SetRenderState(iface, WINED3DRS_CULLMODE, value);
7065 /* Force updating projection matrix */
7066 This->last_was_rhw = FALSE;
7067 This->proj_valid = FALSE;
7070 ret = WINED3D_OK;
7072 if (cfgs != NULL) {
7073 XFree(cfgs);
7074 } else {
7075 ERR("cannot get valides GLXFBConfig for (%u,%s)/(%u,%s)\n", BackBufferFormat,
7076 debug_d3dformat(BackBufferFormat), StencilBufferFormat, debug_d3dformat(StencilBufferFormat));
7079 #undef PUSH1
7080 #undef PUSH2
7081 if ( NULL != impSwapChain) {
7082 IWineD3DSwapChain_Release((IWineD3DSwapChain *)impSwapChain);
7084 LEAVE_GL();
7086 #endif
7087 return ret;
7090 HRESULT WINAPI IWineD3DDeviceImpl_SetCursorProperties(IWineD3DDevice* iface, UINT XHotSpot,
7091 UINT YHotSpot, IWineD3DSurface *pCursorBitmap) {
7092 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *) iface;
7093 /* TODO: the use of Impl is deprecated. */
7094 /* some basic validation checks */
7095 IWineD3DSurfaceImpl * pSur = (IWineD3DSurfaceImpl *) pCursorBitmap;
7097 TRACE("(%p) : Spot Pos(%u,%u)\n", This, XHotSpot, YHotSpot);
7099 if (WINED3DFMT_A8R8G8B8 != pSur->resource.format) {
7100 ERR("(%p) : surface(%p) has an invalid format\n", This, pCursorBitmap);
7101 return WINED3DERR_INVALIDCALL;
7103 if (32 != pSur->currentDesc.Height || 32 != pSur->currentDesc.Width) {
7104 ERR("(%p) : surface(%p) has an invalid size\n", This, pCursorBitmap);
7105 return WINED3DERR_INVALIDCALL;
7107 /* TODO: make the cursor 'real' */
7109 This->xHotSpot = XHotSpot;
7110 This->yHotSpot = YHotSpot;
7112 return WINED3D_OK;
7115 void WINAPI IWineD3DDeviceImpl_SetCursorPosition(IWineD3DDevice* iface, int XScreenSpace, int YScreenSpace, DWORD Flags) {
7116 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *) iface;
7117 TRACE("(%p) : SetPos to (%u,%u)\n", This, XScreenSpace, YScreenSpace);
7119 This->xScreenSpace = XScreenSpace;
7120 This->yScreenSpace = YScreenSpace;
7122 return;
7126 BOOL WINAPI IWineD3DDeviceImpl_ShowCursor(IWineD3DDevice* iface, BOOL bShow) {
7127 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *) iface;
7128 TRACE("(%p) : visible(%d)\n", This, bShow);
7130 This->bCursorVisible = bShow;
7132 return WINED3D_OK;
7135 HRESULT WINAPI IWineD3DDeviceImpl_TestCooperativeLevel(IWineD3DDevice* iface) {
7136 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *) iface;
7137 TRACE("(%p) : state (%lu)\n", This, This->state);
7138 /* TODO: Implement wrapping of the WndProc so that mimimize and maxamise can be monitored and the states adjusted. */
7139 switch (This->state) {
7140 case WINED3D_OK:
7141 return WINED3D_OK;
7142 case WINED3DERR_DEVICELOST:
7144 ResourceList *resourceList = This->resources;
7145 while (NULL != resourceList) {
7146 if (((IWineD3DResourceImpl *)resourceList->resource)->resource.pool == WINED3DPOOL_DEFAULT /* TODO: IWineD3DResource_GetPool(resourceList->resource)*/)
7147 return WINED3DERR_DEVICENOTRESET;
7148 resourceList = resourceList->next;
7150 return WINED3DERR_DEVICELOST;
7152 case WINED3DERR_DRIVERINTERNALERROR:
7153 return WINED3DERR_DRIVERINTERNALERROR;
7156 /* Unknown state */
7157 return WINED3DERR_DRIVERINTERNALERROR;
7161 HRESULT WINAPI IWineD3DDeviceImpl_EvictManagedResources(IWineD3DDevice* iface) {
7162 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *) iface;
7163 /** FIXME: Resource tracking needs to be done,
7164 * The closes we can do to this is set the priorities of all managed textures low
7165 * and then reset them.
7166 ***********************************************************/
7167 FIXME("(%p) : stub\n", This);
7168 return WINED3D_OK;
7171 HRESULT WINAPI IWineD3DDeviceImpl_Reset(IWineD3DDevice* iface, WINED3DPRESENT_PARAMETERS* pPresentationParameters) {
7172 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *) iface;
7173 /** FIXME: Resource trascking needs to be done.
7174 * in effect this pulls all non only default
7175 * textures out of video memory and deletes all glTextures (glDeleteTextures)
7176 * and should clear down the context and set it up according to pPresentationParameters
7177 ***********************************************************/
7178 FIXME("(%p) : stub\n", This);
7179 return WINED3D_OK;
7182 HRESULT WINAPI IWineD3DDeviceImpl_SetDialogBoxMode(IWineD3DDevice *iface, BOOL bEnableDialogs) {
7183 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
7184 /** FIXME: always true at the moment **/
7185 if(bEnableDialogs == FALSE) {
7186 FIXME("(%p) Dialogs cannot be disabled yet\n", This);
7188 return WINED3D_OK;
7192 HRESULT WINAPI IWineD3DDeviceImpl_GetCreationParameters(IWineD3DDevice *iface, WINED3DDEVICE_CREATION_PARAMETERS *pParameters) {
7193 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *) iface;
7194 TRACE("(%p) : pParameters %p\n", This, pParameters);
7196 *pParameters = This->createParms;
7197 return WINED3D_OK;
7200 void WINAPI IWineD3DDeviceImpl_SetGammaRamp(IWineD3DDevice * iface, UINT iSwapChain, DWORD Flags, CONST WINED3DGAMMARAMP* pRamp) {
7201 IWineD3DSwapChain *swapchain;
7202 HRESULT hrc = WINED3D_OK;
7204 TRACE("Relaying to swapchain\n");
7206 if ((hrc = IWineD3DDeviceImpl_GetSwapChain(iface, iSwapChain, &swapchain)) == WINED3D_OK) {
7207 IWineD3DSwapChain_SetGammaRamp(swapchain, Flags, (WINED3DGAMMARAMP *)pRamp);
7208 IWineD3DSwapChain_Release(swapchain);
7210 return;
7213 void WINAPI IWineD3DDeviceImpl_GetGammaRamp(IWineD3DDevice *iface, UINT iSwapChain, WINED3DGAMMARAMP* pRamp) {
7214 IWineD3DSwapChain *swapchain;
7215 HRESULT hrc = WINED3D_OK;
7217 TRACE("Relaying to swapchain\n");
7219 if ((hrc = IWineD3DDeviceImpl_GetSwapChain(iface, iSwapChain, &swapchain)) == WINED3D_OK) {
7220 hrc =IWineD3DSwapChain_GetGammaRamp(swapchain, pRamp);
7221 IWineD3DSwapChain_Release(swapchain);
7223 return;
7227 /** ********************************************************
7228 * Notification functions
7229 ** ********************************************************/
7230 /** This function must be called in the release of a resource when ref == 0,
7231 * the contents of resource must still be correct,
7232 * any handels to other resource held by the caller must be closed
7233 * (e.g. a texture should release all held surfaces because telling the device that it's been released.)
7234 *****************************************************/
7235 static void WINAPI IWineD3DDeviceImpl_AddResource(IWineD3DDevice *iface, IWineD3DResource *resource){
7236 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
7237 ResourceList* resourceList;
7239 TRACE("(%p) : resource %p\n", This, resource);
7240 #if 0
7241 EnterCriticalSection(&resourceStoreCriticalSection);
7242 #endif
7243 /* add a new texture to the frot of the linked list */
7244 resourceList = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(ResourceList));
7245 resourceList->resource = resource;
7247 /* Get the old head */
7248 resourceList->next = This->resources;
7250 This->resources = resourceList;
7251 TRACE("Added resource %p with element %p pointing to %p\n", resource, resourceList, resourceList->next);
7253 #if 0
7254 LeaveCriticalSection(&resourceStoreCriticalSection);
7255 #endif
7256 return;
7259 static void WINAPI IWineD3DDeviceImpl_RemoveResource(IWineD3DDevice *iface, IWineD3DResource *resource){
7260 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
7261 ResourceList* resourceList = NULL;
7262 ResourceList* previousResourceList = NULL;
7264 TRACE("(%p) : resource %p\n", This, resource);
7266 #if 0
7267 EnterCriticalSection(&resourceStoreCriticalSection);
7268 #endif
7269 resourceList = This->resources;
7271 while (resourceList != NULL) {
7272 if(resourceList->resource == resource) break;
7273 previousResourceList = resourceList;
7274 resourceList = resourceList->next;
7277 if (resourceList == NULL) {
7278 FIXME("Attempted to remove resource %p that hasn't been stored\n", resource);
7279 #if 0
7280 LeaveCriticalSection(&resourceStoreCriticalSection);
7281 #endif
7282 return;
7283 } else {
7284 TRACE("Found resource %p with element %p pointing to %p (previous %p)\n", resourceList->resource, resourceList, resourceList->next, previousResourceList);
7286 /* make sure we don't leave a hole in the list */
7287 if (previousResourceList != NULL) {
7288 previousResourceList->next = resourceList->next;
7289 } else {
7290 This->resources = resourceList->next;
7293 #if 0
7294 LeaveCriticalSection(&resourceStoreCriticalSection);
7295 #endif
7296 return;
7300 void WINAPI IWineD3DDeviceImpl_ResourceReleased(IWineD3DDevice *iface, IWineD3DResource *resource){
7301 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *) iface;
7302 int counter;
7304 TRACE("(%p) : resource %p\n", This, resource);
7305 switch(IWineD3DResource_GetType(resource)){
7306 case WINED3DRTYPE_SURFACE:
7307 /* TODO: check front and back buffers, rendertargets etc.. possibly swapchains? */
7308 break;
7309 case WINED3DRTYPE_TEXTURE:
7310 case WINED3DRTYPE_CUBETEXTURE:
7311 case WINED3DRTYPE_VOLUMETEXTURE:
7312 for (counter = 0; counter < GL_LIMITS(textures); counter++) {
7313 if (This->stateBlock != NULL && This->stateBlock->textures[counter] == (IWineD3DBaseTexture *)resource) {
7314 WARN("Texture being released is still by a stateblock, Stage = %u Texture = %p\n", counter, resource);
7315 This->stateBlock->textures[counter] = NULL;
7317 if (This->updateStateBlock != This->stateBlock ){
7318 if (This->updateStateBlock->textures[counter] == (IWineD3DBaseTexture *)resource) {
7319 WARN("Texture being released is still by a stateblock, Stage = %u Texture = %p\n", counter, resource);
7320 This->updateStateBlock->textures[counter] = NULL;
7324 break;
7325 case WINED3DRTYPE_VOLUME:
7326 /* TODO: nothing really? */
7327 break;
7328 case WINED3DRTYPE_VERTEXBUFFER:
7329 /* MSDN: When an application no longer holds a references to this interface, the interface will automatically be freed. */
7331 int streamNumber;
7332 TRACE("Cleaning up stream pointers\n");
7334 for(streamNumber = 0; streamNumber < MAX_STREAMS; streamNumber ++){
7335 /* FINDOUT: should a warn be generated if were recording and updateStateBlock->streamSource is lost?
7336 FINDOUT: should changes.streamSource[StreamNumber] be set ?
7338 if (This->updateStateBlock != NULL ) { /* ==NULL when device is being destroyed */
7339 if ((IWineD3DResource *)This->updateStateBlock->streamSource[streamNumber] == resource) {
7340 FIXME("Vertex buffer released whlst bound to a state block stream %d\n", streamNumber);
7341 This->updateStateBlock->streamSource[streamNumber] = 0;
7342 /* Set changed flag? */
7345 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) */
7346 if ((IWineD3DResource *)This->stateBlock->streamSource[streamNumber] == resource) {
7347 TRACE("Vertex buffer released whlst bound to a state block stream %d\n", streamNumber);
7348 This->stateBlock->streamSource[streamNumber] = 0;
7351 #if 0 /* TODO: Manage internal tracking properly so that 'this shouldn't happen' */
7352 else { /* This shouldn't happen */
7353 FIXME("Calling application has released the device before relasing all the resources bound to the device\n");
7355 #endif
7359 break;
7360 case WINED3DRTYPE_INDEXBUFFER:
7361 /* MSDN: When an application no longer holds a references to this interface, the interface will automatically be freed.*/
7362 if (This->updateStateBlock != NULL ) { /* ==NULL when device is being destroyed */
7363 if (This->updateStateBlock->pIndexData == (IWineD3DIndexBuffer *)resource) {
7364 This->updateStateBlock->pIndexData = NULL;
7367 if (This->stateBlock != NULL ) { /* ==NULL when device is being destroyed */
7368 if (This->stateBlock->pIndexData == (IWineD3DIndexBuffer *)resource) {
7369 This->stateBlock->pIndexData = NULL;
7373 break;
7374 default:
7375 FIXME("(%p) unknown resource type %p %u\n", This, resource, IWineD3DResource_GetType(resource));
7376 break;
7380 /* Remove the resoruce from the resourceStore */
7381 IWineD3DDeviceImpl_RemoveResource(iface, resource);
7383 TRACE("Resource released\n");
7387 /**********************************************************
7388 * IWineD3DDevice VTbl follows
7389 **********************************************************/
7391 const IWineD3DDeviceVtbl IWineD3DDevice_Vtbl =
7393 /*** IUnknown methods ***/
7394 IWineD3DDeviceImpl_QueryInterface,
7395 IWineD3DDeviceImpl_AddRef,
7396 IWineD3DDeviceImpl_Release,
7397 /*** IWineD3DDevice methods ***/
7398 IWineD3DDeviceImpl_GetParent,
7399 /*** Creation methods**/
7400 IWineD3DDeviceImpl_CreateVertexBuffer,
7401 IWineD3DDeviceImpl_CreateIndexBuffer,
7402 IWineD3DDeviceImpl_CreateStateBlock,
7403 IWineD3DDeviceImpl_CreateSurface,
7404 IWineD3DDeviceImpl_CreateTexture,
7405 IWineD3DDeviceImpl_CreateVolumeTexture,
7406 IWineD3DDeviceImpl_CreateVolume,
7407 IWineD3DDeviceImpl_CreateCubeTexture,
7408 IWineD3DDeviceImpl_CreateQuery,
7409 IWineD3DDeviceImpl_CreateAdditionalSwapChain,
7410 IWineD3DDeviceImpl_CreateVertexDeclaration,
7411 IWineD3DDeviceImpl_CreateVertexShader,
7412 IWineD3DDeviceImpl_CreatePixelShader,
7413 IWineD3DDeviceImpl_CreatePalette,
7414 /*** Odd functions **/
7415 IWineD3DDeviceImpl_Init3D,
7416 IWineD3DDeviceImpl_Uninit3D,
7417 IWineD3DDeviceImpl_EnumDisplayModes,
7418 IWineD3DDeviceImpl_EvictManagedResources,
7419 IWineD3DDeviceImpl_GetAvailableTextureMem,
7420 IWineD3DDeviceImpl_GetBackBuffer,
7421 IWineD3DDeviceImpl_GetCreationParameters,
7422 IWineD3DDeviceImpl_GetDeviceCaps,
7423 IWineD3DDeviceImpl_GetDirect3D,
7424 IWineD3DDeviceImpl_GetDisplayMode,
7425 IWineD3DDeviceImpl_SetDisplayMode,
7426 IWineD3DDeviceImpl_GetHWND,
7427 IWineD3DDeviceImpl_SetHWND,
7428 IWineD3DDeviceImpl_GetNumberOfSwapChains,
7429 IWineD3DDeviceImpl_GetRasterStatus,
7430 IWineD3DDeviceImpl_GetSwapChain,
7431 IWineD3DDeviceImpl_Reset,
7432 IWineD3DDeviceImpl_SetDialogBoxMode,
7433 IWineD3DDeviceImpl_SetCursorProperties,
7434 IWineD3DDeviceImpl_SetCursorPosition,
7435 IWineD3DDeviceImpl_ShowCursor,
7436 IWineD3DDeviceImpl_TestCooperativeLevel,
7437 IWineD3DDeviceImpl_EnumZBufferFormats,
7438 IWineD3DDeviceImpl_EnumTextureFormats,
7439 /*** Getters and setters **/
7440 IWineD3DDeviceImpl_SetClipPlane,
7441 IWineD3DDeviceImpl_GetClipPlane,
7442 IWineD3DDeviceImpl_SetClipStatus,
7443 IWineD3DDeviceImpl_GetClipStatus,
7444 IWineD3DDeviceImpl_SetCurrentTexturePalette,
7445 IWineD3DDeviceImpl_GetCurrentTexturePalette,
7446 IWineD3DDeviceImpl_SetDepthStencilSurface,
7447 IWineD3DDeviceImpl_GetDepthStencilSurface,
7448 IWineD3DDeviceImpl_SetFVF,
7449 IWineD3DDeviceImpl_GetFVF,
7450 IWineD3DDeviceImpl_SetGammaRamp,
7451 IWineD3DDeviceImpl_GetGammaRamp,
7452 IWineD3DDeviceImpl_SetIndices,
7453 IWineD3DDeviceImpl_GetIndices,
7454 IWineD3DDeviceImpl_SetLight,
7455 IWineD3DDeviceImpl_GetLight,
7456 IWineD3DDeviceImpl_SetLightEnable,
7457 IWineD3DDeviceImpl_GetLightEnable,
7458 IWineD3DDeviceImpl_SetMaterial,
7459 IWineD3DDeviceImpl_GetMaterial,
7460 IWineD3DDeviceImpl_SetNPatchMode,
7461 IWineD3DDeviceImpl_GetNPatchMode,
7462 IWineD3DDeviceImpl_SetPaletteEntries,
7463 IWineD3DDeviceImpl_GetPaletteEntries,
7464 IWineD3DDeviceImpl_SetPixelShader,
7465 IWineD3DDeviceImpl_GetPixelShader,
7466 IWineD3DDeviceImpl_SetPixelShaderConstant,
7467 IWineD3DDeviceImpl_GetPixelShaderConstant,
7468 IWineD3DDeviceImpl_SetPixelShaderConstantB,
7469 IWineD3DDeviceImpl_GetPixelShaderConstantB,
7470 IWineD3DDeviceImpl_SetPixelShaderConstantI,
7471 IWineD3DDeviceImpl_GetPixelShaderConstantI,
7472 IWineD3DDeviceImpl_SetPixelShaderConstantF,
7473 IWineD3DDeviceImpl_GetPixelShaderConstantF,
7474 IWineD3DDeviceImpl_SetPixelShaderConstantN,
7475 IWineD3DDeviceImpl_SetRenderState,
7476 IWineD3DDeviceImpl_GetRenderState,
7477 IWineD3DDeviceImpl_SetRenderTarget,
7478 IWineD3DDeviceImpl_GetRenderTarget,
7479 IWineD3DDeviceImpl_SetFrontBackBuffers,
7480 IWineD3DDeviceImpl_SetSamplerState,
7481 IWineD3DDeviceImpl_GetSamplerState,
7482 IWineD3DDeviceImpl_SetScissorRect,
7483 IWineD3DDeviceImpl_GetScissorRect,
7484 IWineD3DDeviceImpl_SetSoftwareVertexProcessing,
7485 IWineD3DDeviceImpl_GetSoftwareVertexProcessing,
7486 IWineD3DDeviceImpl_SetStreamSource,
7487 IWineD3DDeviceImpl_GetStreamSource,
7488 IWineD3DDeviceImpl_SetStreamSourceFreq,
7489 IWineD3DDeviceImpl_GetStreamSourceFreq,
7490 IWineD3DDeviceImpl_SetTexture,
7491 IWineD3DDeviceImpl_GetTexture,
7492 IWineD3DDeviceImpl_SetTextureStageState,
7493 IWineD3DDeviceImpl_GetTextureStageState,
7494 IWineD3DDeviceImpl_SetTransform,
7495 IWineD3DDeviceImpl_GetTransform,
7496 IWineD3DDeviceImpl_SetVertexDeclaration,
7497 IWineD3DDeviceImpl_GetVertexDeclaration,
7498 IWineD3DDeviceImpl_SetVertexShader,
7499 IWineD3DDeviceImpl_GetVertexShader,
7500 IWineD3DDeviceImpl_SetVertexShaderConstant,
7501 IWineD3DDeviceImpl_GetVertexShaderConstant,
7502 IWineD3DDeviceImpl_SetVertexShaderConstantB,
7503 IWineD3DDeviceImpl_GetVertexShaderConstantB,
7504 IWineD3DDeviceImpl_SetVertexShaderConstantI,
7505 IWineD3DDeviceImpl_GetVertexShaderConstantI,
7506 IWineD3DDeviceImpl_SetVertexShaderConstantF,
7507 IWineD3DDeviceImpl_GetVertexShaderConstantF,
7508 IWineD3DDeviceImpl_SetVertexShaderConstantN,
7509 IWineD3DDeviceImpl_SetViewport,
7510 IWineD3DDeviceImpl_GetViewport,
7511 IWineD3DDeviceImpl_MultiplyTransform,
7512 IWineD3DDeviceImpl_ValidateDevice,
7513 IWineD3DDeviceImpl_ProcessVertices,
7514 /*** State block ***/
7515 IWineD3DDeviceImpl_BeginStateBlock,
7516 IWineD3DDeviceImpl_EndStateBlock,
7517 /*** Scene management ***/
7518 IWineD3DDeviceImpl_BeginScene,
7519 IWineD3DDeviceImpl_EndScene,
7520 IWineD3DDeviceImpl_Present,
7521 IWineD3DDeviceImpl_Clear,
7522 /*** Drawing ***/
7523 IWineD3DDeviceImpl_DrawPrimitive,
7524 IWineD3DDeviceImpl_DrawIndexedPrimitive,
7525 IWineD3DDeviceImpl_DrawPrimitiveUP,
7526 IWineD3DDeviceImpl_DrawIndexedPrimitiveUP,
7527 IWineD3DDeviceImpl_DrawPrimitiveStrided,
7528 IWineD3DDeviceImpl_DrawRectPatch,
7529 IWineD3DDeviceImpl_DrawTriPatch,
7530 IWineD3DDeviceImpl_DeletePatch,
7531 IWineD3DDeviceImpl_ColorFill,
7532 IWineD3DDeviceImpl_UpdateTexture,
7533 IWineD3DDeviceImpl_UpdateSurface,
7534 IWineD3DDeviceImpl_CopyRects,
7535 IWineD3DDeviceImpl_StretchRect,
7536 IWineD3DDeviceImpl_GetRenderTargetData,
7537 IWineD3DDeviceImpl_GetFrontBufferData,
7538 /*** Internal use IWineD3DDevice methods ***/
7539 IWineD3DDeviceImpl_SetupTextureStates,
7540 /*** object tracking ***/
7541 IWineD3DDeviceImpl_ResourceReleased
7545 const DWORD SavedPixelStates_R[NUM_SAVEDPIXELSTATES_R] = {
7546 WINED3DRS_ALPHABLENDENABLE ,
7547 WINED3DRS_ALPHAFUNC ,
7548 WINED3DRS_ALPHAREF ,
7549 WINED3DRS_ALPHATESTENABLE ,
7550 WINED3DRS_BLENDOP ,
7551 WINED3DRS_COLORWRITEENABLE ,
7552 WINED3DRS_DESTBLEND ,
7553 WINED3DRS_DITHERENABLE ,
7554 WINED3DRS_FILLMODE ,
7555 WINED3DRS_FOGDENSITY ,
7556 WINED3DRS_FOGEND ,
7557 WINED3DRS_FOGSTART ,
7558 WINED3DRS_LASTPIXEL ,
7559 WINED3DRS_SHADEMODE ,
7560 WINED3DRS_SRCBLEND ,
7561 WINED3DRS_STENCILENABLE ,
7562 WINED3DRS_STENCILFAIL ,
7563 WINED3DRS_STENCILFUNC ,
7564 WINED3DRS_STENCILMASK ,
7565 WINED3DRS_STENCILPASS ,
7566 WINED3DRS_STENCILREF ,
7567 WINED3DRS_STENCILWRITEMASK ,
7568 WINED3DRS_STENCILZFAIL ,
7569 WINED3DRS_TEXTUREFACTOR ,
7570 WINED3DRS_WRAP0 ,
7571 WINED3DRS_WRAP1 ,
7572 WINED3DRS_WRAP2 ,
7573 WINED3DRS_WRAP3 ,
7574 WINED3DRS_WRAP4 ,
7575 WINED3DRS_WRAP5 ,
7576 WINED3DRS_WRAP6 ,
7577 WINED3DRS_WRAP7 ,
7578 WINED3DRS_ZENABLE ,
7579 WINED3DRS_ZFUNC ,
7580 WINED3DRS_ZWRITEENABLE
7583 const DWORD SavedPixelStates_T[NUM_SAVEDPIXELSTATES_T] = {
7584 WINED3DTSS_ADDRESSW ,
7585 WINED3DTSS_ALPHAARG0 ,
7586 WINED3DTSS_ALPHAARG1 ,
7587 WINED3DTSS_ALPHAARG2 ,
7588 WINED3DTSS_ALPHAOP ,
7589 WINED3DTSS_BUMPENVLOFFSET ,
7590 WINED3DTSS_BUMPENVLSCALE ,
7591 WINED3DTSS_BUMPENVMAT00 ,
7592 WINED3DTSS_BUMPENVMAT01 ,
7593 WINED3DTSS_BUMPENVMAT10 ,
7594 WINED3DTSS_BUMPENVMAT11 ,
7595 WINED3DTSS_COLORARG0 ,
7596 WINED3DTSS_COLORARG1 ,
7597 WINED3DTSS_COLORARG2 ,
7598 WINED3DTSS_COLOROP ,
7599 WINED3DTSS_RESULTARG ,
7600 WINED3DTSS_TEXCOORDINDEX ,
7601 WINED3DTSS_TEXTURETRANSFORMFLAGS
7604 const DWORD SavedPixelStates_S[NUM_SAVEDPIXELSTATES_S] = {
7605 WINED3DSAMP_ADDRESSU ,
7606 WINED3DSAMP_ADDRESSV ,
7607 WINED3DSAMP_ADDRESSW ,
7608 WINED3DSAMP_BORDERCOLOR ,
7609 WINED3DSAMP_MAGFILTER ,
7610 WINED3DSAMP_MINFILTER ,
7611 WINED3DSAMP_MIPFILTER ,
7612 WINED3DSAMP_MIPMAPLODBIAS ,
7613 WINED3DSAMP_MAXMIPLEVEL ,
7614 WINED3DSAMP_MAXANISOTROPY ,
7615 WINED3DSAMP_SRGBTEXTURE ,
7616 WINED3DSAMP_ELEMENTINDEX
7619 const DWORD SavedVertexStates_R[NUM_SAVEDVERTEXSTATES_R] = {
7620 WINED3DRS_AMBIENT ,
7621 WINED3DRS_AMBIENTMATERIALSOURCE ,
7622 WINED3DRS_CLIPPING ,
7623 WINED3DRS_CLIPPLANEENABLE ,
7624 WINED3DRS_COLORVERTEX ,
7625 WINED3DRS_DIFFUSEMATERIALSOURCE ,
7626 WINED3DRS_EMISSIVEMATERIALSOURCE ,
7627 WINED3DRS_FOGDENSITY ,
7628 WINED3DRS_FOGEND ,
7629 WINED3DRS_FOGSTART ,
7630 WINED3DRS_FOGTABLEMODE ,
7631 WINED3DRS_FOGVERTEXMODE ,
7632 WINED3DRS_INDEXEDVERTEXBLENDENABLE ,
7633 WINED3DRS_LIGHTING ,
7634 WINED3DRS_LOCALVIEWER ,
7635 WINED3DRS_MULTISAMPLEANTIALIAS ,
7636 WINED3DRS_MULTISAMPLEMASK ,
7637 WINED3DRS_NORMALIZENORMALS ,
7638 WINED3DRS_PATCHEDGESTYLE ,
7639 WINED3DRS_POINTSCALE_A ,
7640 WINED3DRS_POINTSCALE_B ,
7641 WINED3DRS_POINTSCALE_C ,
7642 WINED3DRS_POINTSCALEENABLE ,
7643 WINED3DRS_POINTSIZE ,
7644 WINED3DRS_POINTSIZE_MAX ,
7645 WINED3DRS_POINTSIZE_MIN ,
7646 WINED3DRS_POINTSPRITEENABLE ,
7647 WINED3DRS_RANGEFOGENABLE ,
7648 WINED3DRS_SPECULARMATERIALSOURCE ,
7649 WINED3DRS_TWEENFACTOR ,
7650 WINED3DRS_VERTEXBLEND
7653 const DWORD SavedVertexStates_T[NUM_SAVEDVERTEXSTATES_T] = {
7654 WINED3DTSS_TEXCOORDINDEX ,
7655 WINED3DTSS_TEXTURETRANSFORMFLAGS
7658 const DWORD SavedVertexStates_S[NUM_SAVEDVERTEXSTATES_S] = {
7659 WINED3DSAMP_DMAPOFFSET